From 06cca16a2a1664597ec08458d997aac360d83930 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 2 Nov 2006 17:05:46 +0000 Subject: [PATCH] Added convinience constructors to help support picking with the new osgUtil::Intersector classes. --- .../osgkeyboardmouse/osgkeyboardmouse.cpp | 40 +++++------- include/osgUtil/IntersectionVisitor | 26 ++++++-- src/osgUtil/IntersectionVisitor.cpp | 65 +++++++++++++++---- 3 files changed, 92 insertions(+), 39 deletions(-) diff --git a/examples/osgkeyboardmouse/osgkeyboardmouse.cpp b/examples/osgkeyboardmouse/osgkeyboardmouse.cpp index 25c3b0c60..f0939afc7 100644 --- a/examples/osgkeyboardmouse/osgkeyboardmouse.cpp +++ b/examples/osgkeyboardmouse/osgkeyboardmouse.cpp @@ -191,29 +191,25 @@ public: bool usePolytopePicking = true; if (usePolytopePicking) { + +#if 0 // use window coordinates // remap the mouse x,y into viewport coordinates. osg::Viewport* viewport = viewer->getCamera()->getViewport(); - float mx = viewport->x() + (int)((float)viewport->width()*(ea.getXnormalized()*0.5f+0.5f)); - float my = viewport->y() + (int)((float)viewport->height()*(ea.getYnormalized()*0.5f+0.5f)); - - float width = 10.0f; - float height = 10.0f; - - float min_x = mx - width*0.5; - float max_x = mx + width*0.5; - float min_y = my - height*0.5; - float max_y = my + height*0.5; - - osg::Polytope polytope; - polytope.add(osg::Plane(1,0,0,-min_x)); - polytope.add(osg::Plane(-1,0,0,max_x)); - polytope.add(osg::Plane(0,1,0,-min_y)); - polytope.add(osg::Plane(0,-1,0,max_y)); - polytope.add(osg::Plane(0,0,1,0)); - - osgUtil::PolytopeIntersector* picker = new osgUtil::PolytopeIntersector( osgUtil::Intersector::WINDOW, polytope ); + double mx = viewport->x() + (int)((double )viewport->width()*(ea.getXnormalized()*0.5+0.5)); + double my = viewport->y() + (int)((double )viewport->height()*(ea.getYnormalized()*0.5+0.5)); + // half width, height. + double w = 5.0f; + double h = 5.0f; + osgUtil::PolytopeIntersector* picker = new osgUtil::PolytopeIntersector( osgUtil::Intersector::WINDOW, mx-w, my-h, mx+w, my+h ); +#else + double mx = ea.getXnormalized(); + double my = ea.getYnormalized(); + double w = 0.05; + double h = 0.05; + osgUtil::PolytopeIntersector* picker = new osgUtil::PolytopeIntersector( osgUtil::Intersector::PROJECTION, mx-w, my-h, mx+w, my+h ); +#endif osgUtil::IntersectionVisitor iv(picker); viewer->getCamera()->accept(iv); @@ -235,15 +231,15 @@ public: { #if 0 - // use non dimension coordinates - in projection/clip space - osgUtil::LineSegmentIntersector* picker = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::PROJECTION, osg::Vec3d(ea.getXnormalized(),ea.getYnormalized(),-1.0), osg::Vec3d(ea.getXnormalized(),ea.getYnormalized(),1.0) ); + // use non dimensional coordinates - in projection/clip space + osgUtil::LineSegmentIntersector* picker = new osgUtil::LineSegmentIntersector( osgUtil::Intersector::PROJECTION, ea.getXnormalized(),ea.getYnormalized() ); #else // use window coordinates // remap the mouse x,y into viewport coordinates. osg::Viewport* viewport = viewer->getCamera()->getViewport(); float mx = viewport->x() + (int)((float)viewport->width()*(ea.getXnormalized()*0.5f+0.5f)); float my = viewport->y() + (int)((float)viewport->height()*(ea.getYnormalized()*0.5f+0.5f)); - osgUtil::LineSegmentIntersector* picker = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, osg::Vec3d(mx,my,0.0), osg::Vec3d(mx,my,1.0) ); + osgUtil::LineSegmentIntersector* picker = new osgUtil::LineSegmentIntersector( osgUtil::Intersector::WINDOW, mx, my ); #endif osgUtil::IntersectionVisitor iv(picker); diff --git a/include/osgUtil/IntersectionVisitor b/include/osgUtil/IntersectionVisitor index 4d53d96cf..02bfa6373 100644 --- a/include/osgUtil/IntersectionVisitor +++ b/include/osgUtil/IntersectionVisitor @@ -81,10 +81,18 @@ class Intersector : public osg::Referenced class OSGUTIL_EXPORT LineSegmentIntersector : public Intersector { public: - - LineSegmentIntersector(const osg::Vec3d& start, const osg::Vec3d& end, LineSegmentIntersector* parent=0); + + /** Construct a LineSegmentIntersector the runs between the secified start and end points in MODEL coordinates. */ + LineSegmentIntersector(const osg::Vec3d& start, const osg::Vec3d& end); - LineSegmentIntersector(CoordinateFrame cf, const osg::Vec3d& start, const osg::Vec3d& end, LineSegmentIntersector* parent=0); + /** Construct a LineSegmentIntersector the runs between the secified start and end points in the specified coordinate frame. */ + LineSegmentIntersector(CoordinateFrame cf, const osg::Vec3d& start, const osg::Vec3d& end); + + /** Convinience constructor for supporting picking in WINDOW, or PROJECTION coorindates + * In WINDOW coordinates creates a start value of (x,y,0) and end value of (x,y,1). + * In PROJECTION coordinates (clip space cube) creates a start value of (x,y,1) and end value of (x,y,-1). + * In VIEW and MODEL coordinates creates a start value of (x,y,0) and end value of (x,y,1).*/ + LineSegmentIntersector(CoordinateFrame cf, double x, double y); struct Intersection { @@ -148,10 +156,18 @@ class OSGUTIL_EXPORT PolytopeIntersector : public Intersector { public: - PolytopeIntersector(const osg::Polytope& polytope, PolytopeIntersector* parent=0); + /** Construct a PolytopeIntersector using speified polytope in MODEL coordinates.*/ + PolytopeIntersector(const osg::Polytope& polytope); - PolytopeIntersector(CoordinateFrame cf, const osg::Polytope& polytope, PolytopeIntersector* parent=0); + /** Construct a PolytopeIntersector using speified polytope in specified coordinate frame.*/ + PolytopeIntersector(CoordinateFrame cf, const osg::Polytope& polytope); + /** Convinience constructor for supporting picking in WINDOW, or PROJECTION coorindates + * In WINDOW coordinates (clip space cube) creates a five sided polytope box that has a front face at 0.0 and sides around box xMin, yMin, xMax, yMax. + * In PROJECTION coordinates (clip space cube) creates a five sided polytope box that has a front face at -1 and sides around box xMin, yMin, xMax, yMax. + * In VIEW and MODEL coordinates (clip space cube) creates a five sided polytope box that has a front face at 0.0 and sides around box xMin, yMin, xMax, yMax.*/ + PolytopeIntersector(CoordinateFrame cf, double xMin, double yMin, double xMax, double yMax); + struct Intersection { Intersection() {} diff --git a/src/osgUtil/IntersectionVisitor.cpp b/src/osgUtil/IntersectionVisitor.cpp index fce41f085..2bbd77f2c 100644 --- a/src/osgUtil/IntersectionVisitor.cpp +++ b/src/osgUtil/IntersectionVisitor.cpp @@ -210,26 +210,41 @@ struct TriangleIntersector // LineSegmentIntersector // -LineSegmentIntersector::LineSegmentIntersector(const osg::Vec3d& start, const osg::Vec3d& end, LineSegmentIntersector* parent): - _parent(parent), +LineSegmentIntersector::LineSegmentIntersector(const osg::Vec3d& start, const osg::Vec3d& end): + _parent(0), _start(start), _end(end) { } -LineSegmentIntersector::LineSegmentIntersector(CoordinateFrame cf, const osg::Vec3d& start, const osg::Vec3d& end, LineSegmentIntersector* parent): +LineSegmentIntersector::LineSegmentIntersector(CoordinateFrame cf, const osg::Vec3d& start, const osg::Vec3d& end): Intersector(cf), - _parent(parent), + _parent(0), _start(start), _end(end) { } +LineSegmentIntersector::LineSegmentIntersector(CoordinateFrame cf, double x, double y): + Intersector(cf), + _parent(0) +{ + switch(cf) + { + case WINDOW : _start.set(x,y,0.0); _end.set(x,y,1.0); break; + case PROJECTION : _start.set(x,y,1.0); _end.set(x,y,-1.0); break; + case VIEW : _start.set(x,y,0.0); _end.set(x,y,1.0); break; + case MODEL : _start.set(x,y,0.0); _end.set(x,y,1.0); break; + } +} + Intersector* LineSegmentIntersector::clone(osgUtil::IntersectionVisitor& iv) { if (_coordinateFrame==MODEL && iv.getModelMatrix()==0) { - return new LineSegmentIntersector(_start, _end, this); + osg::ref_ptr lsi = new LineSegmentIntersector(_start, _end); + lsi->_parent = this; + return lsi.release(); } // compute the matrix that takes this Intersector from its CoordinateFrame into the local MODEL coordinate frame @@ -260,7 +275,9 @@ Intersector* LineSegmentIntersector::clone(osgUtil::IntersectionVisitor& iv) osg::Matrix inverse; inverse.invert(matrix); - return new LineSegmentIntersector(_start * inverse, _end * inverse, this); + osg::ref_ptr lsi = new LineSegmentIntersector(_start * inverse, _end * inverse); + lsi->_parent = this; + return lsi.release(); } bool LineSegmentIntersector::enter(const osg::Node& node) @@ -497,24 +514,46 @@ bool LineSegmentIntersector::intersectAndClip(osg::Vec3d& s, osg::Vec3d& e,const // // IntersectorGroup // -PolytopeIntersector::PolytopeIntersector(const osg::Polytope& polytope, PolytopeIntersector* parent): - _parent(parent), +PolytopeIntersector::PolytopeIntersector(const osg::Polytope& polytope): + _parent(0), _polytope(polytope) { } -PolytopeIntersector::PolytopeIntersector(CoordinateFrame cf, const osg::Polytope& polytope, PolytopeIntersector* parent): +PolytopeIntersector::PolytopeIntersector(CoordinateFrame cf, const osg::Polytope& polytope): Intersector(cf), - _parent(parent), + _parent(0), _polytope(polytope) { } +PolytopeIntersector::PolytopeIntersector(CoordinateFrame cf, double xMin, double yMin, double xMax, double yMax): + Intersector(cf), + _parent(0) +{ + double zNear = 0.0; + switch(cf) + { + case WINDOW : zNear = 0.0; break; + case PROJECTION : zNear = 1.0; break; + case VIEW : zNear = 0.0; break; + case MODEL : zNear = 0.0; break; + } + + _polytope.add(osg::Plane(1.0, 0.0, 0.0, -xMin)); + _polytope.add(osg::Plane(-1.0,0.0 ,0.0, xMax)); + _polytope.add(osg::Plane(0.0, 1.0, 0.0,-yMin)); + _polytope.add(osg::Plane(0.0,-1.0,0.0, yMax)); + _polytope.add(osg::Plane(0.0,0.0,1.0, zNear)); +} + Intersector* PolytopeIntersector::clone(osgUtil::IntersectionVisitor& iv) { if (_coordinateFrame==MODEL && iv.getModelMatrix()==0) { - return new PolytopeIntersector(_polytope, this); + osg::ref_ptr pi = new PolytopeIntersector(_polytope); + pi->_parent = this; + return pi.release(); } // compute the matrix that takes this Intersector from its CoordinateFrame into the local MODEL coordinate frame @@ -545,7 +584,9 @@ Intersector* PolytopeIntersector::clone(osgUtil::IntersectionVisitor& iv) osg::Polytope transformedPolytope; transformedPolytope.setAndTransformProvidingInverse(_polytope, matrix); - return new PolytopeIntersector(transformedPolytope, this); + osg::ref_ptr pi = new PolytopeIntersector(transformedPolytope); + pi->_parent = this; + return pi.release(); } bool PolytopeIntersector::enter(const osg::Node& node)