|
osgViewer::View 在拾取交点的时候,默认是获得所有交点。如果模型比较大,因为有很多面,视线一次可能交点会很多。比如一个城市模型在平放的时候可能会有上万的交点。但是如果我们只需要最近的1个交点,那么这会严重地降低性能。下面是我的处理方法:- class ViewForNearestIntersection : public osgViewer::View
- {
- public:
- // Only get the first (nearest) intersection
- bool computeIntersections(float x,float y, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask = 0xffffffff);
- // computeIntersections 函数与其父类的不同只是加了 LIMIT_ONE 的限制
- bool ViewForNearestIntersection::computeIntersections(float x,float y, osgUtil::LineSegmentIntersector::Intersections& intersections, osg::Node::NodeMask traversalMask)
- {
- if (!_camera.valid()) return false;
- float local_x, local_y = 0.0;
- const osg::Camera* camera = getCameraContainingPosition(x, y, local_x, local_y);
- if (!camera) camera = _camera.get();
- osgUtil::LineSegmentIntersector::CoordinateFrame cf = camera->getViewport() ? osgUtil::Intersector::WINDOW : osgUtil::Intersector::PROJECTION;
- osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(cf, local_x, local_y);
- picker->setIntersectionLimit(osgUtil::Intersector::LIMIT_ONE); // LIMIT_ONE seems 10 times faster than LIMIT_NEAREST.
- osgUtil::IntersectionVisitor iv(picker.get());
- iv.setTraversalMask(traversalMask);
- const_cast<osg::Camera*>(camera)->accept(iv);
- if (picker->containsIntersections())
- {
- intersections = picker->getIntersections();
- return true;
- }
- else
- {
- intersections.clear();
- return false;
- }
- }
- // 然后跟往常一样写一个这样的类似函数
- bool getNearestIntersection(ViewForNearestIntersection* viewer, const osgGA::GUIEventAdapter& ea, osg::Vec3d& v3d);
- // 最后在事件处理函数中获得交点可以下面这样写:
- if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE && button == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)
- {
- osgViewer::View* view1 = dynamic_cast<osgViewer::View*> (&aa);
- ViewForNearestIntersection* view = static_cast<ViewForNearestIntersection*> (view1);
- if(!view)
- {
- return false;
- }
- osg::Vec3d pointCoordinate;
- getNearestIntersection(view, ea, pointCoordinate);
复制代码 看起来还可以,不知有没有更好的方法。 |
|