From ab7d1ecc42a9a0cf46820c06ca82f4fb400a17f5 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 29 Nov 2006 14:21:59 +0000 Subject: [PATCH] Further work on PlaneIntersector --- include/osg/View | 2 +- include/osgUtil/PlaneIntersector | 9 + src/osgSim/LineOfSight.cpp | 6 +- src/osgUtil/GNUmakefile | 10 +- src/osgUtil/LineSegmentIntersector.cpp | 304 +++++++++++++------------ src/osgUtil/PlaneIntersector.cpp | 151 +++++++++++- 6 files changed, 314 insertions(+), 168 deletions(-) diff --git a/include/osg/View b/include/osg/View index 7136c65f8..5aaa0440c 100644 --- a/include/osg/View +++ b/include/osg/View @@ -24,7 +24,7 @@ namespace osg { * Note, if no slave cameras are attached to the view then the master camera does both the control and implementation of the rendering of the scene, * but if slave cameras are present then the master controls the view onto the scene, while the slaves implement the rendering of the scene. */ -class OSG_EXPORT View : public osg::Referenced +class OSG_EXPORT View : public virtual osg::Referenced { public : diff --git a/include/osgUtil/PlaneIntersector b/include/osgUtil/PlaneIntersector index 223b9966d..1e8034545 100644 --- a/include/osgUtil/PlaneIntersector +++ b/include/osgUtil/PlaneIntersector @@ -37,13 +37,22 @@ class OSGUTIL_EXPORT PlaneIntersector : public Intersector bool operator < (const Intersection& rhs) const { + if (polyline < rhs.polyline) return true; + if (rhs.polyline < polyline) return false; + if (nodePath < rhs.nodePath) return true; if (rhs.nodePath < nodePath ) return false; + return (drawable < rhs.drawable); } + typedef std::vector Polyline; + osg::NodePath nodePath; + osg::ref_ptr matrix; osg::ref_ptr drawable; + Polyline polyline; + }; typedef std::set Intersections; diff --git a/src/osgSim/LineOfSight.cpp b/src/osgSim/LineOfSight.cpp index 85d4c3140..aca733627 100644 --- a/src/osgSim/LineOfSight.cpp +++ b/src/osgSim/LineOfSight.cpp @@ -43,7 +43,7 @@ osg::Node* DatabaseCacheReadCallback::readNodeFile(const std::string& filename) FileNameSceneMap::iterator itr = _filenameSceneMap.find(filename); if (itr != _filenameSceneMap.end()) { - osg::notify(osg::NOTICE)<<"Getting from cache "<second.get(); } @@ -59,7 +59,7 @@ osg::Node* DatabaseCacheReadCallback::readNodeFile(const std::string& filename) if (_filenameSceneMap.size() < _maxNumFilesToCache) { - osg::notify(osg::NOTICE)<<"Inserting into cache "< TriangleIntersections; - - TriangleIntersections _intersections; - TriangleIntersector() + struct TriangleIntersector { - } + osg::Vec3 _s; + osg::Vec3 _d; + float _length; - TriangleIntersector(const osg::Vec3d& start, osg::Vec3d& end, float ratio=FLT_MAX) - { - set(start,end,ratio); - } - - void set(const osg::Vec3d& start, osg::Vec3d& end, float ratio=FLT_MAX) - { - _hit=false; - _index = 0; - _ratio = ratio; + int _index; + float _ratio; + bool _hit; - _s = start; - _d = end - start; - _length = _d.length(); - _d /= _length; - } + TriangleIntersections _intersections; - // bool intersect(const Vec3& v1,const Vec3& v2,const Vec3& v3,float& r) - inline void operator () (const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3, bool treatVertexDataAsTemporary) - { - ++_index; - - 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; - if (d312>=0.0f) + TriangleIntersector() { - if (ds12<0.0f) return; - if (ds12>d312) return; - } - else // d312 < 0 - { - if (ds12>0.0f) return; - if (ds12=0.0f) + void set(const osg::Vec3d& start, osg::Vec3d& end, float ratio=FLT_MAX) { - if (ds23<0.0f) return; - if (ds23>d123) return; - } - else // d123 < 0 - { - if (ds23>0.0f) return; - if (ds23=0.0f) + inline void operator () (const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3, bool treatVertexDataAsTemporary) { - if (ds31<0.0f) return; - if (ds31>d231) return; - } - else // d231 < 0 - { - if (ds31>0.0f) return; - if (ds31=0.0f) + { + if (ds12<0.0f) return; + if (ds12>d312) return; + } + else // d312 < 0 + { + if (ds12>0.0f) return; + if (ds12=0.0f) + { + if (ds23<0.0f) return; + if (ds23>d123) return; + } + else // d123 < 0 + { + if (ds23>0.0f) return; + if (ds23=0.0f) + { + if (ds31<0.0f) return; + if (ds31>d231) return; + } + else // d231 < 0 + { + if (ds31>0.0f) return; + if (ds31_length) return; + + osg::Vec3 normal = v12^v23; + normal.normalize(); + + float r = d/_length; + + + if (treatVertexDataAsTemporary) + { + _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))); + } + _hit = true; - float 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; - r1 *= inv_total_r; - r2 *= inv_total_r; - r3 *= inv_total_r; - } - - osg::Vec3 in = v1*r1+v2*r2+v3*r3; - if (!in.valid()) - { - osg::notify(osg::WARN)<<"Warning:: Picked up error in TriangleIntersect"<_length) return; - - osg::Vec3 normal = v12^v23; - normal.normalize(); - - float r = d/_length; - - - if (treatVertexDataAsTemporary) - { - _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))); - } - _hit = true; - - } - -}; + }; +} /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // @@ -286,14 +287,15 @@ void LineSegmentIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Dr s = _start; e = _end; - osg::TriangleFunctor ti; + osg::TriangleFunctor ti; ti.set(s,e); drawable->accept(ti); + if (ti._hit) { osg::Geometry* geometry = drawable->asGeometry(); - for(TriangleIntersector::TriangleIntersections::iterator thitr = ti._intersections.begin(); + for(LineSegmentIntersectorUtils::TriangleIntersections::iterator thitr = ti._intersections.begin(); thitr != ti._intersections.end(); ++thitr) { @@ -304,7 +306,7 @@ void LineSegmentIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Dr // remap ratio into _start, _end range ratio = ((s-_start).length() + ratio * (e-s).length() )/(_end-_start).length(); - TriangleIntersection& triHit = thitr->second; + LineSegmentIntersectorUtils::TriangleIntersection& triHit = thitr->second; Intersection hit; hit.ratio = ratio; diff --git a/src/osgUtil/PlaneIntersector.cpp b/src/osgUtil/PlaneIntersector.cpp index c110140b1..1ceb4afed 100644 --- a/src/osgUtil/PlaneIntersector.cpp +++ b/src/osgUtil/PlaneIntersector.cpp @@ -21,6 +21,127 @@ using namespace osgUtil; +namespace PlaneIntersectorUtils +{ + + struct TriangleIntersection + { + osg::Vec3d v[2]; + }; + + typedef std::list TriangleIntersections; + + struct TriangleIntersector + { + + osg::Plane _plane; + osg::Polytope _polytope; + bool _hit; + + TriangleIntersections _intersections; + + TriangleIntersector() + { + _hit = false; + } + + void set(const osg::Plane& plane, const osg::Polytope& polytope) + { + _plane = plane; + _polytope = polytope; + _hit = false; + } + + inline void operator () (const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3, bool) + { + + double d1 = _plane.distance(v1); + double d2 = _plane.distance(v2); + double d3 = _plane.distance(v3); + + unsigned int numBelow = 0; + unsigned int numAbove = 0; + unsigned int numOnPlane = 0; + if (d1<0) ++numBelow; + else if (d1>0) ++numAbove; + else ++numOnPlane; + + if (d2<0) ++numBelow; + else if (d2>0) ++numAbove; + else ++numOnPlane; + + if (d3<0) ++numBelow; + else if (d3>0) ++numAbove; + else ++numOnPlane; + + // trivially discard triangles that are completely one side of the plane + if (numAbove==3 || numBelow==3) return; + + _hit = true; + + if (numOnPlane==3) + { + // triangle lives wholy in the plane + osg::notify(osg::NOTICE)<<"3"<getBound() ) ) return; + if ( _plane.intersect( drawable->getBound() )!=0 ) return; if ( !_polytope.contains( drawable->getBound() ) ) return; - osg::notify(osg::NOTICE)<<"Succed PlaneIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable)"< ti; + ti.set(_plane,_polytope); + drawable->accept(ti); + + if (ti._hit) + { + Intersection hit; + hit.nodePath = iv.getNodePath(); + hit.drawable = drawable; + + insertIntersection(hit); + + osg::notify(osg::NOTICE)<