From Farshid Lashkari, "Another update. I added a LIMIT_NEAREST enum which implements your previous suggestion of rejecting bounding volumes further from the nearest existing intersection. I only implemented this for LineSegmentIntersector. I'd appreciate it if you could double check the math I added to LineSegmentIntersector::intersects() for checking if the bounding sphere is further away. The results of this are promising. I'm getting noticeable performance increase for line intersections with scenes containing many drawables.

"
This commit is contained in:
Robert Osfield
2011-03-14 10:07:15 +00:00
parent 76dea3d0f4
commit 7cd74f0282
7 changed files with 75 additions and 10 deletions

View File

@@ -63,6 +63,7 @@ namespace LineSegmentIntersectorUtils
int _index;
float _ratio;
bool _hit;
bool _limitOneIntersection;
TriangleIntersections _intersections;
@@ -72,6 +73,7 @@ namespace LineSegmentIntersectorUtils
_index = 0;
_ratio = 0.0f;
_hit = false;
_limitOneIntersection = false;
}
void set(const osg::Vec3d& start, osg::Vec3d& end, float ratio=FLT_MAX)
@@ -90,6 +92,8 @@ namespace LineSegmentIntersectorUtils
{
++_index;
if (_limitOneIntersection && _hit) return;
if (v1==v2 || v2==v3 || v1==v3) return;
osg::Vec3 v12 = v2-v1;
@@ -238,6 +242,7 @@ Intersector* LineSegmentIntersector::clone(osgUtil::IntersectionVisitor& iv)
{
osg::ref_ptr<LineSegmentIntersector> lsi = new LineSegmentIntersector(_start, _end);
lsi->_parent = this;
lsi->_intersectionLimit = this->_intersectionLimit;
return lsi.release();
}
@@ -271,11 +276,13 @@ Intersector* LineSegmentIntersector::clone(osgUtil::IntersectionVisitor& iv)
osg::ref_ptr<LineSegmentIntersector> lsi = new LineSegmentIntersector(_start * inverse, _end * inverse);
lsi->_parent = this;
lsi->_intersectionLimit = this->_intersectionLimit;
return lsi.release();
}
bool LineSegmentIntersector::enter(const osg::Node& node)
{
if (reachedLimit()) return false;
return !node.isCullingActive() || intersects( node.getBound() );
}
@@ -286,7 +293,9 @@ void LineSegmentIntersector::leave()
void LineSegmentIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable)
{
osg::Vec3d s(_start), e(_end);
if (reachedLimit()) return;
osg::Vec3d s(_start), e(_end);
if ( !intersectAndClip( s, e, drawable->getBound() ) ) return;
if (iv.getDoDummyTraversal()) return;
@@ -354,6 +363,7 @@ void LineSegmentIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Dr
osg::TriangleFunctor<LineSegmentIntersectorUtils::TriangleIntersector> ti;
ti.set(s,e);
ti._limitOneIntersection = (_intersectionLimit == LIMIT_ONE_PER_DRAWABLE || _intersectionLimit == LIMIT_ONE);
drawable->accept(ti);
if (ti._hit)
@@ -371,6 +381,14 @@ void LineSegmentIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Dr
// remap ratio into _start, _end range
double remap_ratio = ((s-_start).length() + ratio * (e-s).length() )/(_end-_start).length();
if ( _intersectionLimit == LIMIT_NEAREST && !getIntersections().empty() )
{
if (remap_ratio >= getIntersections().begin()->ratio )
break;
else
getIntersections().clear();
}
LineSegmentIntersectorUtils::TriangleIntersection& triHit = thitr->second;
Intersection hit;
@@ -450,6 +468,12 @@ bool LineSegmentIntersector::intersects(const osg::BoundingSphere& bs)
if (r1>=1.0 && r2>=1.0) return false;
if (_intersectionLimit == LIMIT_NEAREST && !getIntersections().empty())
{
double ratio = (sm.length() - bs._radius) / sqrt(a);
if (ratio >= getIntersections().begin()->ratio) return false;
}
// passed all the rejection tests so line must intersect bounding sphere, return true.
return true;
}