std::pair<bool, Real> doPicking(const Ogre::Ray& localRay, const CollisionModel& collisionModel, CullingMode cullingMode) { // Convert our ray to Opcode ray IceMaths::Ray world_ray( IceMaths::Point(localRay.getOrigin().x, localRay.getOrigin().y, localRay.getOrigin().z), IceMaths::Point(localRay.getDirection().x, localRay.getDirection().y, localRay.getDirection().z)); // Be aware we store triangle as ccw in collision mode, and Opcode treat it as cw, // so need to inverse cull mode here. Opcode::CullMode cullMode; switch (cullingMode) { default: case CULL_NONE: cullMode = Opcode::CULLMODE_NONE; break; case CULL_CLOCKWISE: cullMode = Opcode::CULLMODE_CCW; break; case CULL_ANTICLOCKWISE: cullMode = Opcode::CULLMODE_CW; break; } // Cull mode callback for Opcode struct Local { static Opcode::CullMode cullModeCallback(udword triangle_index, void* user_data) { return (Opcode::CullMode) (int) user_data; } }; std::pair<bool, Real> ret; // Do picking Opcode::CollisionFace picked_face; ret.first = Opcode::Picking(picked_face, world_ray, collisionModel.getOpcodeModel(), 0, 0, FLT_MAX, world_ray.mOrig, &Local::cullModeCallback, (void*) (int) cullMode); ret.second = ret.first ? picked_face.mDistance : 0; return ret; }
void PLodNode::ray_test_impl(Ray const& ray, int options, Mask const& mask, std::set<PickResult>& hits) { // first of all, check bbox auto box_hits(::gua::intersect(ray, bounding_box_)); // ray did not intersect bbox -- therefore it wont intersect if (box_hits.first == Ray::END && box_hits.second == Ray::END) { return; } // return if only first object shall be returned and the current first hit // is in front of the bbox entry point and the ray does not start inside // the bbox if (options & PickResult::PICK_ONLY_FIRST_OBJECT && hits.size() > 0 && hits.begin()->distance < box_hits.first && box_hits.first != Ray::END) { return; } // bbox is intersected, but check geometry only if mask tells us to check if (get_geometry_description() != "" && mask.check(get_tags())) { auto geometry( GeometryDatabase::instance()->lookup(get_geometry_description())); if (geometry) { Ray world_ray(ray); geometry->ray_test(world_ray, options, this, hits); } } for (auto child : get_children()) { child->ray_test_impl(ray, options, mask, hits); } }