Added osgUtil::IntersectorGroup to handle groups of osgUtil::Intersectors

This commit is contained in:
Robert Osfield 2006-10-27 15:11:17 +00:00
parent 0fe424996d
commit 358b96e953
3 changed files with 289 additions and 50 deletions

View File

@ -39,18 +39,87 @@ int main(int argc, char **argv)
std::cout<<"Intersection "<<std::endl;
osg::Timer_t startTick = osg::Timer::instance()->tick();
osg::BoundingSphere bs = root->getBound();
#if 1
bool useIntersectorGroup = true;
if (useIntersectorGroup)
{
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<osgUtil::IntersectorGroup> intersectorGroup = new osgUtil::IntersectorGroup();
for(unsigned int r=0; r<numRows; ++r)
{
for(unsigned int c=0; c<numColumns; ++c)
{
osg::Vec3d s = start + deltaColumn * double(c) + deltaRow * double(r);
osg::Vec3d e = end + deltaColumn * double(c) + deltaRow * double(r);
osg::ref_ptr<osgUtil::LineSegmentIntersector> 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 "<<osg::Timer::instance()->delta_s(startTick,endTick)<<std::endl;
if ( intersectorGroup->containsIntersections() )
{
std::cout<<"Found intersections "<<std::endl;
osgUtil::IntersectorGroup::Intersectors& intersectors = intersectorGroup->getIntersectors();
for(osgUtil::IntersectorGroup::Intersectors::iterator intersector_itr = intersectors.begin();
intersector_itr != intersectors.end();
++intersector_itr)
{
osgUtil::LineSegmentIntersector* lsi = dynamic_cast<osgUtil::LineSegmentIntersector*>(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 "<<intersection.ratio<<std::endl;
std::cout<<" point "<<intersection.localIntersectionPoint<<std::endl;
std::cout<<" normal "<<intersection.localIntersectionNormal<<std::endl;
std::cout<<" indices "<<intersection.indexList.size()<<std::endl;
std::cout<<" primitiveIndex "<<intersection.primitiveIndex<<std::endl;
std::cout<<std::endl;
}
}
}
}
}
else
{
osg::Timer_t startTick = osg::Timer::instance()->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
#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
#endif
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector = new osgUtil::LineSegmentIntersector(start, end);
@ -78,6 +147,7 @@ int main(int argc, char **argv)
std::cout<<std::endl;
}
}
}
return 0;
}

View File

@ -33,9 +33,10 @@ class Intersector : public osg::Referenced
{
public:
virtual Intersector* clone(osgUtil::IntersectionVisitor& iv) = 0;
Intersector():
_disabledCount(0) {}
virtual void merge(Intersector* intersector) = 0;
virtual Intersector* clone(osgUtil::IntersectionVisitor& iv) = 0;
virtual bool enter(const osg::Node& node) = 0;
@ -43,19 +44,29 @@ class Intersector : public osg::Referenced
virtual void intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable) = 0;
virtual void reset() = 0;
virtual void reset() { _disabledCount = 0; }
virtual bool containsIntersections() = 0;
inline bool disabled() const { return _disabledCount!=0; }
inline void incrementDisabledCount() { ++_disabledCount; }
inline void decrementDisabledCount() { if (_disabledCount>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<Intersection> 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<Intersector> > 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<Intersector> > IntersectorStack;
IntersectorStack _intersectorStack;

View File

@ -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<LineSegmentIntersector*>(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 "<<numTested<<std::endl;
}
void IntersectorGroup::reset()
{
Intersector::reset();
for(Intersectors::iterator itr = _intersectors.begin();
itr != _intersectors.end();
++itr)
{
(*itr)->reset();
}
}
bool IntersectorGroup::containsIntersections()
{
for(Intersectors::iterator itr = _intersectors.begin();
itr != _intersectors.end();
++itr)
{
if ((*itr)->containsIntersections()) return true;
}
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// IntersectionVisitor