From 358b96e95361225bda63e34e8bd6e29d5937cb80 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 27 Oct 2006 15:11:17 +0000 Subject: [PATCH] Added osgUtil::IntersectorGroup to handle groups of osgUtil::Intersectors --- examples/osgintersection/osgintersection.cpp | 132 +++++++++++++----- include/osgUtil/IntersectionVisitor | 71 ++++++++-- src/osgUtil/IntersectionVisitor.cpp | 136 +++++++++++++++++-- 3 files changed, 289 insertions(+), 50 deletions(-) diff --git a/examples/osgintersection/osgintersection.cpp b/examples/osgintersection/osgintersection.cpp index a8498a7d7..0f0f20a04 100644 --- a/examples/osgintersection/osgintersection.cpp +++ b/examples/osgintersection/osgintersection.cpp @@ -39,45 +39,115 @@ int main(int argc, char **argv) std::cout<<"Intersection "<tick(); osg::BoundingSphere bs = root->getBound(); -#if 1 - osg::Vec3d start = bs.center() + osg::Vec3d(0.0,bs.radius(),0.0); - osg::Vec3d end = bs.center() - osg::Vec3d(0.0, bs.radius(),0.0); -#else - osg::Vec3d start = bs.center() + osg::Vec3d(0.0,0.0, bs.radius()); - osg::Vec3d end = bs.center() - osg::Vec3d(0.0, 0.0, bs.radius()); -#endif - - osg::ref_ptr intersector = new osgUtil::LineSegmentIntersector(start, end); - - osgUtil::IntersectionVisitor intersectVisitor( intersector.get(), new MyReadCallback ); - - root->accept(intersectVisitor); - - osg::Timer_t endTick = osg::Timer::instance()->tick(); - std::cout<<"Completed in "<delta_s(startTick,endTick)<containsIntersections() ) + bool useIntersectorGroup = true; + + if (useIntersectorGroup) { - osgUtil::LineSegmentIntersector::Intersections& intersections = intersector->getIntersections(); - for(osgUtil::LineSegmentIntersector::Intersections::iterator itr = intersections.begin(); - itr != intersections.end(); - ++itr) + osg::Timer_t startTick = osg::Timer::instance()->tick(); + + osg::Vec3d start = bs.center() + osg::Vec3d(0.0,bs.radius(),0.0); + osg::Vec3d end = bs.center();// - osg::Vec3d(0.0, bs.radius(),0.0); + osg::Vec3d deltaRow( 0.0, 0.0, bs.radius()*0.01); + osg::Vec3d deltaColumn( bs.radius()*0.01, 0.0, 0.0); + unsigned int numRows = 20; + unsigned int numColumns = 20; + + osg::ref_ptr intersectorGroup = new osgUtil::IntersectorGroup(); + + for(unsigned int r=0; r intersector = new osgUtil::LineSegmentIntersector(s, e); + intersectorGroup->addIntersector( intersector.get() ); + } + } + + + osgUtil::IntersectionVisitor intersectVisitor( intersectorGroup.get(), new MyReadCallback ); + root->accept(intersectVisitor); + + osg::Timer_t endTick = osg::Timer::instance()->tick(); + + std::cout<<"Completed in "<delta_s(startTick,endTick)<containsIntersections() ) + { + std::cout<<"Found intersections "<getIntersectors(); + for(osgUtil::IntersectorGroup::Intersectors::iterator intersector_itr = intersectors.begin(); + intersector_itr != intersectors.end(); + ++intersector_itr) + { + osgUtil::LineSegmentIntersector* lsi = dynamic_cast(intersector_itr->get()); + if (lsi) + { + osgUtil::LineSegmentIntersector::Intersections& intersections = lsi->getIntersections(); + for(osgUtil::LineSegmentIntersector::Intersections::iterator itr = intersections.begin(); + itr != intersections.end(); + ++itr) + { + const osgUtil::LineSegmentIntersector::Intersection& intersection = *itr; + std::cout<<" ratio "<tick(); + + #if 1 + osg::Vec3d start = bs.center() + osg::Vec3d(0.0,bs.radius(),0.0); + osg::Vec3d end = bs.center() - osg::Vec3d(0.0, bs.radius(),0.0); + #else + osg::Vec3d start = bs.center() + osg::Vec3d(0.0,0.0, bs.radius()); + osg::Vec3d end = bs.center() - osg::Vec3d(0.0, 0.0, bs.radius()); + #endif + + osg::ref_ptr intersector = new osgUtil::LineSegmentIntersector(start, end); + + osgUtil::IntersectionVisitor intersectVisitor( intersector.get(), new MyReadCallback ); + + root->accept(intersectVisitor); + + osg::Timer_t endTick = osg::Timer::instance()->tick(); + + std::cout<<"Completed in "<delta_s(startTick,endTick)<containsIntersections() ) + { + osgUtil::LineSegmentIntersector::Intersections& intersections = intersector->getIntersections(); + for(osgUtil::LineSegmentIntersector::Intersections::iterator itr = intersections.begin(); + itr != intersections.end(); + ++itr) + { + const osgUtil::LineSegmentIntersector::Intersection& intersection = *itr; + std::cout<<" ratio "<0) --_disabledCount; } + + protected: + + unsigned int _disabledCount; }; /** Concrent class for implementing line intersections with the scene graph. * To be used in conjunction with IntersectionVisitor. */ -class LineSegmentIntersector : public Intersector +class OSGUTIL_EXPORT LineSegmentIntersector : public Intersector { public: - LineSegmentIntersector(const osg::Vec3d& start, const osg::Vec3d& end); + LineSegmentIntersector(const osg::Vec3d& start, const osg::Vec3d& end, LineSegmentIntersector* parent=0); struct Intersection { @@ -75,14 +86,15 @@ class LineSegmentIntersector : public Intersector typedef std::multiset Intersections; - Intersections& getIntersections() { return _intersections; } + inline void insertIntersection(const Intersection& intersection) { getIntersections().insert(intersection); } + + inline Intersections& getIntersections() { return _parent ? _parent->_intersections : _intersections; } + public: virtual Intersector* clone(osgUtil::IntersectionVisitor& iv); - virtual void merge(Intersector* intersector); - virtual bool enter(const osg::Node& node); virtual void leave(); @@ -98,6 +110,8 @@ class LineSegmentIntersector : public Intersector bool intersects(const osg::BoundingSphere& bs); bool intersectAndClip(osg::Vec3d& s, osg::Vec3d& e,const osg::BoundingBox& bb); + LineSegmentIntersector* _parent; + osg::Vec3d _start; osg::Vec3d _end; @@ -105,6 +119,45 @@ class LineSegmentIntersector : public Intersector }; +/** Concrent class for passing multiple intersectors through the scene graph. + * To be used in conjunction with IntersectionVisitor. */ +class OSGUTIL_EXPORT IntersectorGroup : public Intersector +{ + public: + + IntersectorGroup(); + + /** Add an Intersector. */ + void addIntersector(Intersector* intersector); + + typedef std::vector< osg::ref_ptr > Intersectors; + + /** Get the list of intersector. */ + Intersectors& getIntersectors() { return _intersectors; } + + /** Clear the list of intersectors.*/ + void clear(); + + public: + + virtual Intersector* clone(osgUtil::IntersectionVisitor& iv); + + virtual bool enter(const osg::Node& node); + + virtual void leave(); + + virtual void intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable); + + virtual void reset(); + + virtual bool containsIntersections(); + + protected: + + Intersectors _intersectors; + +}; + /** InteresectionVisitor is used to testing for intersections with the scene, traversing the scene using generic osgUtil::Intersector's to test against the scene. * To implement different types of intersection techniques, one implements custom versions of the osgUtil::Intersector, and then * pass the constructed intersector to the IntersectionVisitor.*/ @@ -170,7 +223,7 @@ class OSGUTIL_EXPORT IntersectionVisitor : public osg::NodeVisitor inline void leave() { _intersectorStack.back()->leave(); } inline void intersect(osg::Drawable* drawable) { _intersectorStack.back()->intersect(*this, drawable); } inline void push_clone() { _intersectorStack.push_back ( _intersectorStack.front()->clone(*this) ); } - inline void pop_clone() { if (_intersectorStack.size()>=2) { _intersectorStack.front()->merge(_intersectorStack.back().get()); _intersectorStack.pop_back(); } } + inline void pop_clone() { if (_intersectorStack.size()>=2) _intersectorStack.pop_back(); } typedef std::list< osg::ref_ptr > IntersectorStack; IntersectorStack _intersectorStack; diff --git a/src/osgUtil/IntersectionVisitor.cpp b/src/osgUtil/IntersectionVisitor.cpp index 43eb28603..5434d7be2 100644 --- a/src/osgUtil/IntersectionVisitor.cpp +++ b/src/osgUtil/IntersectionVisitor.cpp @@ -197,7 +197,8 @@ struct TriangleIntersector // LineSegmentIntersector // -LineSegmentIntersector::LineSegmentIntersector(const osg::Vec3d& start, const osg::Vec3d& end): +LineSegmentIntersector::LineSegmentIntersector(const osg::Vec3d& start, const osg::Vec3d& end, LineSegmentIntersector* parent): + _parent(parent), _start(start), _end(end) { @@ -211,20 +212,14 @@ Intersector* LineSegmentIntersector::clone(osgUtil::IntersectionVisitor& iv) osg::Matrix inverse; inverse.invert(*model); - return new LineSegmentIntersector(_start * inverse, _end * inverse); + return new LineSegmentIntersector(_start * inverse, _end * inverse, this); } else { - return new LineSegmentIntersector(_start, _end); + return new LineSegmentIntersector(_start, _end, this); } } -void LineSegmentIntersector::merge(Intersector* intersector) -{ - LineSegmentIntersector* lsi = dynamic_cast(intersector); - _intersections.insert(lsi->_intersections.begin(),lsi->_intersections.end()); -} - bool LineSegmentIntersector::enter(const osg::Node& node) { return intersects( node.getBound() ); @@ -282,7 +277,7 @@ void LineSegmentIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Dr } } - _intersections.insert(hit); + insertIntersection(hit); } } @@ -291,6 +286,8 @@ void LineSegmentIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Dr void LineSegmentIntersector::reset() { + Intersector::reset(); + _intersections.clear(); } @@ -447,6 +444,125 @@ bool LineSegmentIntersector::intersectAndClip(osg::Vec3d& s, osg::Vec3d& e,const } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// LineSegmentIntersector +// + + +IntersectorGroup::IntersectorGroup() +{ +} + +void IntersectorGroup::addIntersector(Intersector* intersector) +{ + _intersectors.push_back(intersector); +} + +void IntersectorGroup::clear() +{ + _intersectors.clear(); +} + +Intersector* IntersectorGroup::clone(osgUtil::IntersectionVisitor& iv) +{ + IntersectorGroup* ig = new IntersectorGroup; + + // now copy across all intersectors that arn't disabled. + for(Intersectors::iterator itr = _intersectors.begin(); + itr != _intersectors.end(); + ++itr) + { + if (!(*itr)->disabled()) + { + ig->addIntersector( (*itr)->clone(iv) ); + } + } + + return ig; +} + +bool IntersectorGroup::enter(const osg::Node& node) +{ + if (disabled()) return false; + + bool foundIntersections = false; + + for(Intersectors::iterator itr = _intersectors.begin(); + itr != _intersectors.end(); + ++itr) + { + if ((*itr)->disabled()) (*itr)->incrementDisabledCount(); + else if ((*itr)->enter(node)) foundIntersections = true; + else (*itr)->incrementDisabledCount(); + } + + if (!foundIntersections) + { + // need to call leave to clean up the DisabledCount's. + leave(); + return false; + } + + // we have found at least one suitable intersector, so return true + return true; +} + +void IntersectorGroup::leave() +{ + for(Intersectors::iterator itr = _intersectors.begin(); + itr != _intersectors.end(); + ++itr) + { + if ((*itr)->disabled()) (*itr)->decrementDisabledCount(); + } +} + +void IntersectorGroup::intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable) +{ + if (disabled()) return; + + unsigned int numTested = 0; + for(Intersectors::iterator itr = _intersectors.begin(); + itr != _intersectors.end(); + ++itr) + { + if (!(*itr)->disabled()) + { + (*itr)->intersect(iv, drawable); + + ++numTested; + } + } + + // osg::notify(osg::NOTICE)<<"Number testing "<reset(); + } +} + +bool IntersectorGroup::containsIntersections() +{ + for(Intersectors::iterator itr = _intersectors.begin(); + itr != _intersectors.end(); + ++itr) + { + if ((*itr)->containsIntersections()) return true; + } + return false; +} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // IntersectionVisitor