Hi All, I have just checked into svn/trunk the following changes to better handle numerical precisions issues with the clamping of the line segment to the bounding box in LineSegmentIntersector.cpp. These changes are compatible with being merged with the OSG-3.2 branch and hence could be part of the up coming OSG-3.2.1 stable release, however, as these changes still experimental I feel that we need to do some more testing against real user data before I do this merge. I have also removed the user definable epsilon from osgUtil::Intersector as if the new code works fine users won't need to play with adjusting it.
~/OpenSceneGraph$ svn diff Index: include/osgUtil/IntersectionVisitor =================================================================== --- include/osgUtil/IntersectionVisitor (revision 13735) +++ include/osgUtil/IntersectionVisitor (working copy) @@ -53,8 +53,7 @@ Intersector(CoordinateFrame cf=MODEL): _coordinateFrame(cf), _intersectionLimit(NO_LIMIT), - _disabledCount(0), - _epsilon(1e-4) {} + _disabledCount(0) {} void setCoordinateFrame(CoordinateFrame cf) { _coordinateFrame = cf; } @@ -85,19 +84,11 @@ inline bool reachedLimit() { return _intersectionLimit == LIMIT_ONE && containsIntersections(); } - /** Set Epsilon value, where supported is used in numerical comparisons to workaround number precisions issues.*/ - inline void setEpsilon(double epsilon) { _epsilon = epsilon; } - - /** Get Epsilon value.*/ - inline double getEpsilon() const { return _epsilon; } - protected: CoordinateFrame _coordinateFrame; IntersectionLimit _intersectionLimit; unsigned int _disabledCount; - double _epsilon; - }; Index: src/osgUtil/LineSegmentIntersector.cpp =================================================================== --- src/osgUtil/LineSegmentIntersector.cpp (revision 13735) +++ src/osgUtil/LineSegmentIntersector.cpp (working copy) @@ -244,7 +244,6 @@ osg::ref_ptr<LineSegmentIntersector> lsi = new LineSegmentIntersector(_start, _end); lsi->_parent = this; lsi->_intersectionLimit = this->_intersectionLimit; - lsi->_epsilon = this->_epsilon; return lsi.release(); } @@ -279,7 +278,6 @@ osg::ref_ptr<LineSegmentIntersector> lsi = new LineSegmentIntersector(_start * inverse, _end * inverse); lsi->_parent = this; lsi->_intersectionLimit = this->_intersectionLimit; - lsi->_epsilon = this->_epsilon; return lsi.release(); } @@ -486,18 +484,11 @@ osg::Vec3d bb_min(bbInput._min); osg::Vec3d bb_max(bbInput._max); - // expand the extents of the bounding box by the epsilon to prevent numerical errors resulting in misses. - bb_min.x() -= _epsilon; - bb_min.y() -= _epsilon; - bb_min.z() -= _epsilon; - bb_max.x() += _epsilon; - bb_max.y() += _epsilon; - bb_max.z() += _epsilon; + double epsilon = 1e-13; // compate s and e against the xMin to xMax range of bb. if (s.x()<=e.x()) { - // trivial reject of segment wholely outside. if (e.x()<bb_min.x()) return false; if (s.x()>bb_max.x()) return false; @@ -505,13 +496,15 @@ if (s.x()<bb_min.x()) { // clip s to xMin. - s = s+(e-s)*(bb_min.x()-s.x())/(e.x()-s.x()); + double r = (bb_min.x()-s.x())/(e.x()-s.x()) - epsilon; + if (r>0.0) s = s + (e-s)*r; } if (e.x()>bb_max.x()) { // clip e to xMax. - e = s+(e-s)*(bb_max.x()-s.x())/(e.x()-s.x()); + double r = (bb_max.x()-s.x())/(e.x()-s.x()) + epsilon; + if (r<1.0) e = s+(e-s)*r; } } else @@ -521,21 +514,22 @@ if (e.x()<bb_min.x()) { - // clip s to xMin. - e = s+(e-s)*(bb_min.x()-s.x())/(e.x()-s.x()); + // clip e to xMin. + double r = (bb_min.x()-e.x())/(s.x()-e.x()) - epsilon; + if (r>0.0) e = e + (s-e)*r; } if (s.x()>bb_max.x()) { - // clip e to xMax. - s = s+(e-s)*(bb_max.x()-s.x())/(e.x()-s.x()); + // clip s to xMax. + double r = (bb_max.x()-e.x())/(s.x()-e.x()) + epsilon; + if (r<1.0) s = e + (s-e)*r; } } // compate s and e against the yMin to yMax range of bb. if (s.y()<=e.y()) { - // trivial reject of segment wholely outside. if (e.y()<bb_min.y()) return false; if (s.y()>bb_max.y()) return false; @@ -543,13 +537,15 @@ if (s.y()<bb_min.y()) { // clip s to yMin. - s = s+(e-s)*(bb_min.y()-s.y())/(e.y()-s.y()); + double r = (bb_min.y()-s.y())/(e.y()-s.y()) - epsilon; + if (r>0.0) s = s + (e-s)*r; } if (e.y()>bb_max.y()) { // clip e to yMax. - e = s+(e-s)*(bb_max.y()-s.y())/(e.y()-s.y()); + double r = (bb_max.y()-s.y())/(e.y()-s.y()) + epsilon; + if (r<1.0) e = s+(e-s)*r; } } else @@ -559,21 +555,22 @@ if (e.y()<bb_min.y()) { - // clip s to yMin. - e = s+(e-s)*(bb_min.y()-s.y())/(e.y()-s.y()); + // clip e to yMin. + double r = (bb_min.y()-e.y())/(s.y()-e.y()) - epsilon; + if (r>0.0) e = e + (s-e)*r; } if (s.y()>bb_max.y()) { - // clip e to yMax. - s = s+(e-s)*(bb_max.y()-s.y())/(e.y()-s.y()); + // clip s to yMax. + double r = (bb_max.y()-e.y())/(s.y()-e.y()) + epsilon; + if (r<1.0) s = e + (s-e)*r; } } // compate s and e against the zMin to zMax range of bb. if (s.z()<=e.z()) { - // trivial reject of segment wholely outside. if (e.z()<bb_min.z()) return false; if (s.z()>bb_max.z()) return false; @@ -581,13 +578,15 @@ if (s.z()<bb_min.z()) { // clip s to zMin. - s = s+(e-s)*(bb_min.z()-s.z())/(e.z()-s.z()); + double r = (bb_min.z()-s.z())/(e.z()-s.z()) - epsilon; + if (r>0.0) s = s + (e-s)*r; } if (e.z()>bb_max.z()) { // clip e to zMax. - e = s+(e-s)*(bb_max.z()-s.z())/(e.z()-s.z()); + double r = (bb_max.z()-s.z())/(e.z()-s.z()) + epsilon; + if (r<1.0) e = s+(e-s)*r; } } else @@ -597,14 +596,16 @@ if (e.z()<bb_min.z()) { - // clip s to zMin. - e = s+(e-s)*(bb_min.z()-s.z())/(e.z()-s.z()); + // clip e to zMin. + double r = (bb_min.z()-e.z())/(s.z()-e.z()) - epsilon; + if (r>0.0) e = e + (s-e)*r; } if (s.z()>bb_max.z()) { - // clip e to zMax. - s = s+(e-s)*(bb_max.z()-s.z())/(e.z()-s.z()); + // clip s to zMax. + double r = (bb_max.z()-e.z())/(s.z()-e.z()) + epsilon; + if (r<1.0) s = e + (s-e)*r; } } These changes are now checked into svn/trunk. I've also attached the modified LineSegmentIntersector.cpp. Could users please test against the dataset that they found problems with and let me know how you get on. We may need to adjust the value of epsilon of 1e-13 that I used to handle the scale of precision errors that we might see with large values. Let me know how you get on. Cheers, Robert.
_______________________________________________ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org