diff --git a/include/osgUtil/IntersectVisitor b/include/osgUtil/IntersectVisitor index 502f2da07..cec8997f0 100644 --- a/include/osgUtil/IntersectVisitor +++ b/include/osgUtil/IntersectVisitor @@ -202,6 +202,29 @@ class OSGUTIL_EXPORT IntersectVisitor : public osg::NodeVisitor osg::Vec3 _pseudoEyePoint; }; +/** Picking intersection visitor specialises the IntersectVistor to allow more convinient handling of mouse picking.*/ +class OSGUTIL_EXPORT PickVisitor : public osgUtil::IntersectVisitor +{ + public: + + PickVisitor(const osg::Viewport* viewport, const osg::Matrixd& proj, const osg::Matrixd& view, float mx, float my); + + void runNestedPickVisitor(osg::Node& node, const osg::Viewport* viewport, const osg::Matrix& proj, const osg::Matrix& view, float mx, float my); + + void apply(osg::Projection& projection); + + void apply(osg::CameraNode& camera); + + protected: + + float _mx; + float _my; + + osg::ref_ptr _lastViewport; + osg::Matrixd _lastProjectionMatrix; + osg::Matrixd _lastViewMatrix; +}; + } #endif diff --git a/src/osgProducer/Viewer.cpp b/src/osgProducer/Viewer.cpp index c5897b5f2..b35ec4fa3 100644 --- a/src/osgProducer/Viewer.cpp +++ b/src/osgProducer/Viewer.cpp @@ -30,87 +30,6 @@ using namespace osg; #define SINGLE_THREAD_KEYBOARDMOUSE #endif -////////////////////////////////////////////////////////////////////////////// -// -// Picking intersection visitor. -// -class PickVisitor : public osgUtil::IntersectVisitor -{ -public: - - - PickVisitor(const osg::Viewport* viewport, const osg::Matrixd& proj, const osg::Matrixd& view, float mx, float my): - _mx(mx), - _my(my), - _lastViewport(viewport), - _lastProjectionMatrix(proj), - _lastViewMatrix(view) - { - if (viewport && - mx >= static_cast(viewport->x()) && - my >= static_cast(viewport->y()) && - mx < static_cast(viewport->x()+viewport->width()) && - my < static_cast(viewport->y()+viewport->height())) - { - - // mouse pointer intersect viewport so we can proceed to set up a line segment - osg::Matrix MVPW = view * proj * viewport->computeWindowMatrix(); - osg::Matrixd inverseMVPW; - inverseMVPW.invert(MVPW); - - osg::Vec3 nearPoint = osg::Vec3(mx,my,0.0f) * inverseMVPW; - osg::Vec3 farPoint = osg::Vec3(mx,my,1.0f) * inverseMVPW; - osg::LineSegment* lineSegment = new osg::LineSegment; - lineSegment->set(nearPoint, farPoint); - - addLineSegment(lineSegment); - } - - } - - void runNestedPickVisitor(osg::Node& node, const osg::Viewport* viewport, const osg::Matrix& proj, const osg::Matrix& view, float mx, float my) - { - - PickVisitor newPickVisitor( viewport, proj, view, _mx, _my ); - newPickVisitor.setTraversalMask(getTraversalMask()); - - // the new pickvisitor over the nodes children. - node.traverse( newPickVisitor ); - - for(LineSegmentHitListMap::iterator itr = newPickVisitor._segHitList.begin(); - itr != newPickVisitor._segHitList.end(); - ++itr) - { - _segHitList.insert(*itr); - } - } - - void apply(osg::Projection& projection) - { - runNestedPickVisitor( projection, - _lastViewport.get(), - projection.getMatrix(), - _lastViewMatrix, - _mx, _my ); - } - - void apply(osg::CameraNode& camera) - { - runNestedPickVisitor( camera, - camera.getViewport() ? camera.getViewport() : _lastViewport.get(), - camera.getProjectionMatrix(), - camera.getViewMatrix(), - _mx, _my ); - } - - - float _mx; - float _my; - - osg::ref_ptr _lastViewport; - osg::Matrixd _lastProjectionMatrix; - osg::Matrixd _lastViewMatrix; -}; class CollectedCoordinateSystemNodesVisitor : public osg::NodeVisitor { @@ -847,13 +766,13 @@ bool Viewer::computeIntersections(float x,float y,unsigned int cameraNum,osg::No node = node->getParent(0); - PickVisitor pick(viewport, proj, view, pixel_x, pixel_y); + osgUtil::PickVisitor pick(viewport, proj, view, pixel_x, pixel_y); pick.setTraversalMask(traversalMask); node->accept(pick); // copy all the hits across to the external hits list - for(osgUtil::IntersectVisitor::LineSegmentHitListMap::iterator itr = pick.getSegHitList().begin(); + for(osgUtil::PickVisitor::LineSegmentHitListMap::iterator itr = pick.getSegHitList().begin(); itr != pick.getSegHitList().end(); ++itr) { diff --git a/src/osgUtil/IntersectVisitor.cpp b/src/osgUtil/IntersectVisitor.cpp index e9f79be59..e6d8f665e 100644 --- a/src/osgUtil/IntersectVisitor.cpp +++ b/src/osgUtil/IntersectVisitor.cpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include @@ -661,3 +663,67 @@ void IntersectVisitor::apply(LOD& node) { apply((Group&)node); } + +PickVisitor::PickVisitor(const osg::Viewport* viewport, const osg::Matrixd& proj, const osg::Matrixd& view, float mx, float my): + _mx(mx), + _my(my), + _lastViewport(viewport), + _lastProjectionMatrix(proj), + _lastViewMatrix(view) +{ + if (viewport && + mx >= static_cast(viewport->x()) && + my >= static_cast(viewport->y()) && + mx < static_cast(viewport->x()+viewport->width()) && + my < static_cast(viewport->y()+viewport->height())) + { + + // mouse pointer intersect viewport so we can proceed to set up a line segment + osg::Matrix MVPW = view * proj * viewport->computeWindowMatrix(); + osg::Matrixd inverseMVPW; + inverseMVPW.invert(MVPW); + + osg::Vec3 nearPoint = osg::Vec3(mx,my,0.0f) * inverseMVPW; + osg::Vec3 farPoint = osg::Vec3(mx,my,1.0f) * inverseMVPW; + osg::LineSegment* lineSegment = new osg::LineSegment; + lineSegment->set(nearPoint, farPoint); + + addLineSegment(lineSegment); + } + +} + +void PickVisitor::runNestedPickVisitor(osg::Node& node, const osg::Viewport* viewport, const osg::Matrix& proj, const osg::Matrix& view, float mx, float my) +{ + + PickVisitor newPickVisitor( viewport, proj, view, mx, my ); + newPickVisitor.setTraversalMask(getTraversalMask()); + + // the new pickvisitor over the nodes children. + node.traverse( newPickVisitor ); + + for(LineSegmentHitListMap::iterator itr = newPickVisitor._segHitList.begin(); + itr != newPickVisitor._segHitList.end(); + ++itr) + { + _segHitList.insert(*itr); + } +} + +void PickVisitor::apply(osg::Projection& projection) +{ + runNestedPickVisitor( projection, + _lastViewport.get(), + projection.getMatrix(), + _lastViewMatrix, + _mx, _my ); +} + +void PickVisitor::apply(osg::CameraNode& camera) +{ + runNestedPickVisitor( camera, + camera.getViewport() ? camera.getViewport() : _lastViewport.get(), + camera.getProjectionMatrix(), + camera.getViewMatrix(), + _mx, _my ); +} diff --git a/src/osgWrappers/osgUtil/IntersectVisitor.cpp b/src/osgWrappers/osgUtil/IntersectVisitor.cpp index 03f750d2b..e245585e2 100644 --- a/src/osgWrappers/osgUtil/IntersectVisitor.cpp +++ b/src/osgWrappers/osgUtil/IntersectVisitor.cpp @@ -10,16 +10,20 @@ #include #include +#include #include #include #include #include #include #include +#include #include +#include #include #include #include +#include #include // Must undefine IN and OUT macros defined in Windows headers @@ -103,6 +107,14 @@ BEGIN_OBJECT_REFLECTOR(osgUtil::IntersectVisitor) I_ReadOnlyProperty(osgUtil::IntersectVisitor::LineSegmentHitListMap &, SegHitList); END_REFLECTOR +BEGIN_OBJECT_REFLECTOR(osgUtil::PickVisitor) + I_BaseType(osgUtil::IntersectVisitor); + I_Constructor5(IN, const osg::Viewport *, viewport, IN, const osg::Matrixd &, proj, IN, const osg::Matrixd &, view, IN, float, mx, IN, float, my); + I_Method6(void, runNestedPickVisitor, IN, osg::Node &, node, IN, const osg::Viewport *, viewport, IN, const osg::Matrix &, proj, IN, const osg::Matrix &, view, IN, float, mx, IN, float, my); + I_Method1(void, apply, IN, osg::Projection &, projection); + I_Method1(void, apply, IN, osg::CameraNode &, camera); +END_REFLECTOR + STD_MAP_REFLECTOR(std::map< const osg::LineSegment * COMMA osgUtil::IntersectVisitor::HitList >); STD_VECTOR_REFLECTOR(std::vector< int >);