diff --git a/include/osgUtil/IntersectionVisitor b/include/osgUtil/IntersectionVisitor index 9be362252..13878888d 100644 --- a/include/osgUtil/IntersectionVisitor +++ b/include/osgUtil/IntersectionVisitor @@ -53,7 +53,8 @@ class Intersector : public osg::Referenced Intersector(CoordinateFrame cf=MODEL, IntersectionLimit il=NO_LIMIT): _coordinateFrame(cf), _intersectionLimit(il), - _disabledCount(0) {} + _disabledCount(0), + _precisionHint(USE_DOUBLE_CALCULATIONS) {} void setCoordinateFrame(CoordinateFrame cf) { _coordinateFrame = cf; } @@ -84,11 +85,25 @@ class Intersector : public osg::Referenced inline bool reachedLimit() { return _intersectionLimit == LIMIT_ONE && containsIntersections(); } + /** Hint to precision used in the internal intersections calculations.*/ + enum PrecisionHint + { + USE_DOUBLE_CALCULATIONS, + USE_FLOAT_CALCULATIONS + }; + + /** Set the hint to what precision to use in the intersections calculations.*/ + void setPrecisionHint(PrecisionHint hint) { _precisionHint = hint; } + + /** Get the hint to what precision should be used in the intersections calculations.*/ + PrecisionHint getPrecisionHint() const { return _precisionHint; } + protected: CoordinateFrame _coordinateFrame; IntersectionLimit _intersectionLimit; unsigned int _disabledCount; + PrecisionHint _precisionHint; }; diff --git a/src/osgUtil/LineSegmentIntersector.cpp b/src/osgUtil/LineSegmentIntersector.cpp index 0310d32c6..fad648bed 100644 --- a/src/osgUtil/LineSegmentIntersector.cpp +++ b/src/osgUtil/LineSegmentIntersector.cpp @@ -26,7 +26,6 @@ using namespace osgUtil; namespace LineSegmentIntersectorUtils { - struct TriangleIntersection { TriangleIntersection(unsigned int index, const osg::Vec3& normal, float r1, const osg::Vec3* v1, float r2, const osg::Vec3* v2, float r3, const osg::Vec3* v3): @@ -55,21 +54,23 @@ namespace LineSegmentIntersectorUtils typedef std::multimap TriangleIntersections; + + template struct TriangleIntersector { - osg::Vec3 _s; - osg::Vec3 _d; - float _length; + Vec3 _s; + Vec3 _d; + value_type _length; int _index; - float _ratio; + value_type _ratio; bool _hit; bool _limitOneIntersection; - - TriangleIntersections _intersections; + TriangleIntersections* _intersections; TriangleIntersector() { + _intersections = 0; _length = 0.0f; _index = 0; _ratio = 0.0f; @@ -77,7 +78,12 @@ namespace LineSegmentIntersectorUtils _limitOneIntersection = false; } - void set(const osg::Vec3d& start, const osg::Vec3d& end, float ratio=FLT_MAX) + void set(TriangleIntersections* intersections) + { + _intersections = intersections; + } + + void set(const osg::Vec3d& start, const osg::Vec3d& end, value_type ratio=FLT_MAX) { _hit=false; _index = 0; @@ -97,10 +103,10 @@ namespace LineSegmentIntersectorUtils if (v1==v2 || v2==v3 || v1==v3) return; - osg::Vec3 v12 = v2-v1; - osg::Vec3 n12 = v12^_d; - float ds12 = (_s-v1)*n12; - float d312 = (v3-v1)*n12; + Vec3 v12 = v2-v1; + Vec3 n12 = v12^_d; + value_type ds12 = (_s-v1)*n12; + value_type d312 = (v3-v1)*n12; if (d312>=0.0f) { if (ds12<0.0f) return; @@ -112,10 +118,10 @@ namespace LineSegmentIntersectorUtils if (ds12=0.0f) { if (ds23<0.0f) return; @@ -127,10 +133,10 @@ namespace LineSegmentIntersectorUtils if (ds23=0.0f) { if (ds31<0.0f) return; @@ -143,32 +149,32 @@ namespace LineSegmentIntersectorUtils } - float r3; + value_type r3; if (ds12==0.0f) r3=0.0f; else if (d312!=0.0f) r3 = ds12/d312; else return; // the triangle and the line must be parallel intersection. - float r1; + value_type r1; if (ds23==0.0f) r1=0.0f; else if (d123!=0.0f) r1 = ds23/d123; else return; // the triangle and the line must be parallel intersection. - float r2; + value_type r2; if (ds31==0.0f) r2=0.0f; else if (d231!=0.0f) r2 = ds31/d231; else return; // the triangle and the line must be parallel intersection. - float total_r = (r1+r2+r3); + value_type total_r = (r1+r2+r3); if (total_r!=1.0f) { if (total_r==0.0f) return; // the triangle and the line must be parallel intersection. - float inv_total_r = 1.0f/total_r; + value_type inv_total_r = 1.0f/total_r; r1 *= inv_total_r; r2 *= inv_total_r; r3 *= inv_total_r; } - osg::Vec3 in = v1*r1+v2*r2+v3*r3; + Vec3 in = v1*r1+v2*r2+v3*r3; if (!in.valid()) { OSG_WARN<<"Warning:: Picked up error in TriangleIntersect"<_length) return; - osg::Vec3 normal = v12^v23; + Vec3 normal = v12^v23; normal.normalize(); - float r = d/_length; + value_type r = d/_length; if (treatVertexDataAsTemporary) { - _intersections.insert(std::pair(r,TriangleIntersection(_index-1,normal,r1,0,r2,0,r3,0))); + _intersections->insert(std::pair(r,TriangleIntersection(_index-1,normal,r1,0,r2,0,r3,0))); } else { - _intersections.insert(std::pair(r,TriangleIntersection(_index-1,normal,r1,&v1,r2,&v2,r3,&v3))); + _intersections->insert(std::pair(r,TriangleIntersection(_index-1,normal,r1,&v1,r2,&v2,r3,&v3))); } _hit = true; @@ -245,6 +251,7 @@ Intersector* LineSegmentIntersector::clone(osgUtil::IntersectionVisitor& iv) osg::ref_ptr lsi = new LineSegmentIntersector(_start, _end); lsi->_parent = this; lsi->_intersectionLimit = this->_intersectionLimit; + lsi->setPrecisionHint(getPrecisionHint()); return lsi.release(); } @@ -255,6 +262,7 @@ Intersector* LineSegmentIntersector::clone(osgUtil::IntersectionVisitor& iv) osg::ref_ptr lsi = new LineSegmentIntersector(_start * matrix, _end * matrix); lsi->_parent = this; lsi->_intersectionLimit = this->_intersectionLimit; + lsi->setPrecisionHint(getPrecisionHint()); return lsi.release(); } @@ -375,17 +383,37 @@ void LineSegmentIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Dr return; } - osg::TriangleFunctor ti; - ti.set(s,e); - ti._limitOneIntersection = (_intersectionLimit == LIMIT_ONE_PER_DRAWABLE || _intersectionLimit == LIMIT_ONE); - drawable->accept(ti); + LineSegmentIntersectorUtils::TriangleIntersections intersections; - if (ti._hit) + if (getPrecisionHint()==USE_DOUBLE_CALCULATIONS) + { + OSG_NOTICE<<"Using double intersections"< TriangleIntersector; + osg::TriangleFunctor< TriangleIntersector > ti; + + ti.set(&intersections); + ti.set(s,e); + ti._limitOneIntersection = (_intersectionLimit == LIMIT_ONE_PER_DRAWABLE || _intersectionLimit == LIMIT_ONE); + drawable->accept(ti); + } + else + { + OSG_NOTICE<<"Using float intersections"< TriangleIntersector; + osg::TriangleFunctor< TriangleIntersector > ti; + + ti.set(&intersections); + ti.set(s,e); + ti._limitOneIntersection = (_intersectionLimit == LIMIT_ONE_PER_DRAWABLE || _intersectionLimit == LIMIT_ONE); + drawable->accept(ti); + } + + if (!intersections.empty()) { osg::Geometry* geometry = drawable->asGeometry(); - for(LineSegmentIntersectorUtils::TriangleIntersections::iterator thitr = ti._intersections.begin(); - thitr != ti._intersections.end(); + for(LineSegmentIntersectorUtils::TriangleIntersections::iterator thitr = intersections.begin(); + thitr != intersections.end(); ++thitr) { diff --git a/src/osgUtil/RayIntersector.cpp b/src/osgUtil/RayIntersector.cpp index f829151bf..b392505f1 100644 --- a/src/osgUtil/RayIntersector.cpp +++ b/src/osgUtil/RayIntersector.cpp @@ -34,6 +34,7 @@ RayIntersector::RayIntersector(CoordinateFrame cf, RayIntersector* parent, Intersector(cf, intersectionLimit), _parent(parent) { + if (parent) setPrecisionHint(parent->getPrecisionHint()); } RayIntersector::RayIntersector(const Vec3d& start, const Vec3d& direction) : @@ -50,6 +51,7 @@ RayIntersector::RayIntersector(CoordinateFrame cf, const Vec3d& start, const Vec _start(start), _direction(direction) { + if (parent) setPrecisionHint(parent->getPrecisionHint()); } RayIntersector::RayIntersector(CoordinateFrame cf, double x, double y) : @@ -112,6 +114,7 @@ void RayIntersector::intersect(IntersectionVisitor& iv, Drawable* drawable) // get intersections using LineSegmentIntersector LineSegmentIntersector lsi(MODEL, s, e, NULL, _intersectionLimit); + lsi.setPrecisionHint(getPrecisionHint()); lsi.intersect(iv, drawable, s, e); // copy intersections from LineSegmentIntersector