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:
parent
76dea3d0f4
commit
7cd74f0282
@ -42,8 +42,17 @@ class Intersector : public osg::Referenced
|
||||
MODEL
|
||||
};
|
||||
|
||||
enum IntersectionLimit
|
||||
{
|
||||
NO_LIMIT,
|
||||
LIMIT_ONE_PER_DRAWABLE,
|
||||
LIMIT_ONE,
|
||||
LIMIT_NEAREST
|
||||
};
|
||||
|
||||
Intersector(CoordinateFrame cf=MODEL):
|
||||
_coordinateFrame(cf),
|
||||
_intersectionLimit(NO_LIMIT),
|
||||
_disabledCount(0) {}
|
||||
|
||||
|
||||
@ -51,6 +60,9 @@ class Intersector : public osg::Referenced
|
||||
|
||||
CoordinateFrame getCoordinateFrame() const { return _coordinateFrame; }
|
||||
|
||||
void setIntersectionLimit(IntersectionLimit limit) { _intersectionLimit = limit; }
|
||||
|
||||
IntersectionLimit getIntersectionLimit() const { return _intersectionLimit; }
|
||||
|
||||
virtual Intersector* clone(osgUtil::IntersectionVisitor& iv) = 0;
|
||||
|
||||
@ -70,9 +82,12 @@ class Intersector : public osg::Referenced
|
||||
|
||||
inline void decrementDisabledCount() { if (_disabledCount>0) --_disabledCount; }
|
||||
|
||||
inline bool reachedLimit() { return _intersectionLimit == LIMIT_ONE && containsIntersections(); }
|
||||
|
||||
protected:
|
||||
|
||||
CoordinateFrame _coordinateFrame;
|
||||
IntersectionLimit _intersectionLimit;
|
||||
unsigned int _disabledCount;
|
||||
|
||||
};
|
||||
|
@ -91,7 +91,7 @@ class OSGUTIL_EXPORT LineSegmentIntersector : public Intersector
|
||||
|
||||
virtual void reset();
|
||||
|
||||
virtual bool containsIntersections() { return !_intersections.empty(); }
|
||||
virtual bool containsIntersections() { return !getIntersections().empty(); }
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -86,7 +86,7 @@ class OSGUTIL_EXPORT PlaneIntersector : public Intersector
|
||||
|
||||
virtual void reset();
|
||||
|
||||
virtual bool containsIntersections() { return !_intersections.empty(); }
|
||||
virtual bool containsIntersections() { return !getIntersections().empty(); }
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -109,7 +109,7 @@ class OSGUTIL_EXPORT PolytopeIntersector : public Intersector
|
||||
|
||||
virtual void reset();
|
||||
|
||||
virtual bool containsIntersections() { return !_intersections.empty(); }
|
||||
virtual bool containsIntersections() { return !getIntersections().empty(); }
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -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,6 +293,8 @@ void LineSegmentIntersector::leave()
|
||||
|
||||
void LineSegmentIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable)
|
||||
{
|
||||
if (reachedLimit()) return;
|
||||
|
||||
osg::Vec3d s(_start), e(_end);
|
||||
if ( !intersectAndClip( s, e, drawable->getBound() ) ) 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;
|
||||
}
|
||||
|
@ -359,6 +359,7 @@ namespace PlaneIntersectorUtils
|
||||
osg::ref_ptr<osg::RefMatrix> _matrix;
|
||||
bool _recordHeightsAsAttributes;
|
||||
osg::ref_ptr<osg::EllipsoidModel> _em;
|
||||
bool _limitOneIntersection;
|
||||
|
||||
PolylineConnector _polylineConnector;
|
||||
|
||||
@ -366,6 +367,7 @@ namespace PlaneIntersectorUtils
|
||||
TriangleIntersector()
|
||||
{
|
||||
_hit = false;
|
||||
_limitOneIntersection = false;
|
||||
}
|
||||
|
||||
void set(const osg::Plane& plane, const osg::Polytope& polytope, osg::RefMatrix* matrix, bool recordHeightsAsAttributes, osg::EllipsoidModel* em)
|
||||
@ -440,6 +442,8 @@ namespace PlaneIntersectorUtils
|
||||
inline void operator () (const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3, bool)
|
||||
{
|
||||
|
||||
if (_limitOneIntersection && _hit) return;
|
||||
|
||||
double d1 = _plane.distance(v1);
|
||||
double d2 = _plane.distance(v2);
|
||||
double d3 = _plane.distance(v3);
|
||||
@ -590,6 +594,7 @@ Intersector* PlaneIntersector::clone(osgUtil::IntersectionVisitor& iv)
|
||||
{
|
||||
osg::ref_ptr<PlaneIntersector> pi = new PlaneIntersector(_plane, _polytope);
|
||||
pi->_parent = this;
|
||||
pi->_intersectionLimit = this->_intersectionLimit;
|
||||
pi->_recordHeightsAsAttributes = _recordHeightsAsAttributes;
|
||||
pi->_em = _em;
|
||||
return pi.release();
|
||||
@ -628,6 +633,7 @@ Intersector* PlaneIntersector::clone(osgUtil::IntersectionVisitor& iv)
|
||||
|
||||
osg::ref_ptr<PlaneIntersector> pi = new PlaneIntersector(plane, transformedPolytope);
|
||||
pi->_parent = this;
|
||||
pi->_intersectionLimit = this->_intersectionLimit;
|
||||
pi->_recordHeightsAsAttributes = _recordHeightsAsAttributes;
|
||||
pi->_em = _em;
|
||||
return pi.release();
|
||||
@ -635,6 +641,7 @@ Intersector* PlaneIntersector::clone(osgUtil::IntersectionVisitor& iv)
|
||||
|
||||
bool PlaneIntersector::enter(const osg::Node& node)
|
||||
{
|
||||
if (reachedLimit()) return false;
|
||||
return !node.isCullingActive() ||
|
||||
( _plane.intersect(node.getBound())==0 && _polytope.contains(node.getBound()) );
|
||||
}
|
||||
@ -650,6 +657,7 @@ void PlaneIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable
|
||||
{
|
||||
// OSG_NOTICE<<"PlaneIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable)"<<std::endl;
|
||||
|
||||
if (reachedLimit()) return;
|
||||
if ( _plane.intersect( drawable->getBound() )!=0 ) return;
|
||||
if ( !_polytope.contains( drawable->getBound() ) ) return;
|
||||
|
||||
@ -657,6 +665,7 @@ void PlaneIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable
|
||||
|
||||
osg::TriangleFunctor<PlaneIntersectorUtils::TriangleIntersector> ti;
|
||||
ti.set(_plane, _polytope, iv.getModelMatrix(), _recordHeightsAsAttributes, _em.get());
|
||||
ti._limitOneIntersection = (_intersectionLimit == LIMIT_ONE_PER_DRAWABLE || _intersectionLimit == LIMIT_ONE);
|
||||
drawable->accept(ti);
|
||||
|
||||
ti._polylineConnector.consolidatePolylineLists();
|
||||
|
@ -88,6 +88,7 @@ namespace PolytopeIntersectorUtils
|
||||
PolytopePrimitiveIntersector() :
|
||||
_index(0),
|
||||
_dimensionMask( PolytopeIntersector::AllDims ),
|
||||
_limitOneIntersection( false ),
|
||||
_candidates(20) {}
|
||||
|
||||
void addIntersection(unsigned int index, const CandList_t& cands) {
|
||||
@ -130,6 +131,9 @@ namespace PolytopeIntersectorUtils
|
||||
{
|
||||
++_index;
|
||||
if ((_dimensionMask & PolytopeIntersector::DimZero) == 0) return;
|
||||
|
||||
if (_limitOneIntersection && !intersections.empty()) return;
|
||||
|
||||
for (PlaneList::const_iterator it=_planes.begin(); it!=_planes.end(); ++it)
|
||||
{
|
||||
const osg::Plane& plane=*it;
|
||||
@ -147,6 +151,8 @@ namespace PolytopeIntersectorUtils
|
||||
++_index;
|
||||
if ((_dimensionMask & PolytopeIntersector::DimOne) == 0) return;
|
||||
|
||||
if (_limitOneIntersection && !intersections.empty()) return;
|
||||
|
||||
PlaneMask selector_mask = 0x1;
|
||||
PlaneMask inside_mask = 0x0;
|
||||
_candidates.clear();
|
||||
@ -210,6 +216,8 @@ namespace PolytopeIntersectorUtils
|
||||
++_index;
|
||||
if ((_dimensionMask & PolytopeIntersector::DimTwo) == 0) return;
|
||||
|
||||
if (_limitOneIntersection && !intersections.empty()) return;
|
||||
|
||||
PlaneMask selector_mask = 0x1;
|
||||
PlaneMask inside_mask = 0x0;
|
||||
_candidates.clear();
|
||||
@ -354,6 +362,8 @@ namespace PolytopeIntersectorUtils
|
||||
|
||||
void setDimensionMask(unsigned int dimensionMask) { _dimensionMask = dimensionMask; }
|
||||
|
||||
void setLimitOneIntersection(bool limit) { _limitOneIntersection = limit; }
|
||||
|
||||
void setPolytope(osg::Polytope& polytope, osg::Plane& referencePlane)
|
||||
{
|
||||
_referencePlane = referencePlane;
|
||||
@ -426,6 +436,7 @@ namespace PolytopeIntersectorUtils
|
||||
unsigned int _index;
|
||||
|
||||
private:
|
||||
bool _limitOneIntersection;
|
||||
unsigned int _dimensionMask;
|
||||
PlaneList _planes; ///< active planes extracted from polytope
|
||||
LinesList _lines; ///< all intersection lines of two polytope planes
|
||||
@ -492,6 +503,7 @@ Intersector* PolytopeIntersector::clone(osgUtil::IntersectionVisitor& iv)
|
||||
{
|
||||
osg::ref_ptr<PolytopeIntersector> pi = new PolytopeIntersector(_polytope);
|
||||
pi->_parent = this;
|
||||
pi->_intersectionLimit = this->_intersectionLimit;
|
||||
pi->_dimensionMask = this->_dimensionMask;
|
||||
pi->_referencePlane = this->_referencePlane;
|
||||
return pi.release();
|
||||
@ -527,6 +539,7 @@ Intersector* PolytopeIntersector::clone(osgUtil::IntersectionVisitor& iv)
|
||||
|
||||
osg::ref_ptr<PolytopeIntersector> pi = new PolytopeIntersector(transformedPolytope);
|
||||
pi->_parent = this;
|
||||
pi->_intersectionLimit = this->_intersectionLimit;
|
||||
pi->_dimensionMask = this->_dimensionMask;
|
||||
pi->_referencePlane = this->_referencePlane;
|
||||
pi->_referencePlane.transformProvidingInverse(matrix);
|
||||
@ -535,6 +548,7 @@ Intersector* PolytopeIntersector::clone(osgUtil::IntersectionVisitor& iv)
|
||||
|
||||
bool PolytopeIntersector::enter(const osg::Node& node)
|
||||
{
|
||||
if (reachedLimit()) return false;
|
||||
return !node.isCullingActive() || _polytope.contains( node.getBound() );
|
||||
}
|
||||
|
||||
@ -547,11 +561,14 @@ void PolytopeIntersector::leave()
|
||||
|
||||
void PolytopeIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable)
|
||||
{
|
||||
if (reachedLimit()) return;
|
||||
|
||||
if ( !_polytope.contains( drawable->getBound() ) ) return;
|
||||
|
||||
osg::TemplatePrimitiveFunctor<PolytopeIntersectorUtils::PolytopePrimitiveIntersector> func;
|
||||
func.setPolytope( _polytope, _referencePlane );
|
||||
func.setDimensionMask( _dimensionMask );
|
||||
func.setLimitOneIntersection( _intersectionLimit == LIMIT_ONE_PER_DRAWABLE || _intersectionLimit == LIMIT_ONE );
|
||||
|
||||
drawable->accept(func);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user