From a856459a861781e085ebd6a9d0fdc6b6ff67b6fa Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 11 Jul 2008 16:48:39 +0000 Subject: [PATCH] Moved the building and intersecting of the KdTree into the .cpp, and cleaned up the header to ready it for wider usage --- include/osg/KdTree | 128 +++++------- src/osg/KdTree.cpp | 501 +++++++++++++++++++++++++++------------------ 2 files changed, 351 insertions(+), 278 deletions(-) diff --git a/include/osg/KdTree b/include/osg/KdTree index baf4c5b43..e4816048e 100644 --- a/include/osg/KdTree +++ b/include/osg/KdTree @@ -17,6 +17,8 @@ #include #include +#include + namespace osg { @@ -50,6 +52,12 @@ class OSG_EXPORT KdTree : public osg::Shape { LineSegmentIntersection(): ratio(-1.0), + p0(0), + p1(0), + p2(0), + r0(0.0f), + r1(0.0f), + r2(0.0f), primitiveIndex(0) {} bool operator < (const LineSegmentIntersection& rhs) const { return ratio < rhs.ratio; } @@ -60,21 +68,25 @@ class OSG_EXPORT KdTree : public osg::Shape double ratio; osg::Vec3d intersectionPoint; osg::Vec3 intersectionNormal; - IndexList indexList; - RatioList ratioList; + + unsigned int p0; + unsigned int p1; + unsigned int p2; + float r0; + float r1; + float r2; + unsigned int primitiveIndex; }; - typedef std::multiset LineSegmentIntersections; + typedef std::vector LineSegmentIntersections; /** compute the intersection of a line segment and the kdtree, return true if an intersection has been found.*/ virtual bool intersect(const osg::Vec3& start, const osg::Vec3& end, LineSegmentIntersections& intersections) const; - typedef int value_type; - typedef std::vector< value_type > Indices; struct KdNode { @@ -94,25 +106,28 @@ class OSG_EXPORT KdTree : public osg::Shape struct Triangle { - Triangle(unsigned int p1, unsigned int p2, unsigned int p3): - _p1(p1), _p2(p2), _p3(p3) {} + Triangle(): + p0(0),p1(0),p2(0) {} + + Triangle(unsigned int ip0, unsigned int ip1, unsigned int ip2): + p0(ip0), p1(ip1), p2(ip2) {} bool operator < (const Triangle& rhs) const { - if (_p1rhs._p1) return false; - if (_p2rhs._p2) return false; - return _p3rhs.p0) return false; + if (p1rhs.p1) return false; + return p2 AxisStack; typedef std::vector< KdNode > KdNodeList; + typedef std::vector< Triangle > TriangleList; int addNode(const KdNode& node) { @@ -121,77 +136,34 @@ class OSG_EXPORT KdTree : public osg::Shape return num; } - /// note, nodeNum is positive to distinguish from leftNum - KdNode& getNode(int nodeNum) - { - if (nodeNum<0 || nodeNum>static_cast(_kdNodes.size())-1) - { - osg::notify(osg::NOTICE)<<"Warning: getNode("<_kdTree.addTriangle(KdTree::Triangle(p0,p1,p2)); + + osg::BoundingBox bb; + bb.expandBy(v0); + bb.expandBy(v1); + bb.expandBy(v2); + + _buildKdTree->_centers.push_back(bb.center()); + _buildKdTree->_primitiveIndices.push_back(i); + + } + + BuildKdTree* _buildKdTree; + +}; + //////////////////////////////////////////////////////////////////////////////// // -// KdTree +// BuildKdTree Implementation -KdTree::KdTree() -{ -} - -KdTree::KdTree(const KdTree& rhs, const osg::CopyOp& copyop): - Shape(rhs) -{ -} - -bool KdTree::build(BuildOptions& options, osg::Geometry* geometry) +bool BuildKdTree::build(KdTree::BuildOptions& options, osg::Geometry* geometry) { + #ifdef VERBOSE_OUTPUT - osg::notify(osg::NOTICE)<<"osg::KDTreeBuilder::createKDTree()"<(geometry->getVertexArray()); @@ -87,9 +107,8 @@ bool KdTree::build(BuildOptions& options, osg::Geometry* geometry) if (vertices->size() <= options._targetNumTrianglesPerLeaf) return false; - _geometry = geometry; - _bb = _geometry->getBound(); - _vertices = vertices; + _bb = geometry->getBound(); + _kdTree.setVertices(vertices); unsigned int estimatedSize = (unsigned int)(2.0*float(vertices->size())/float(options._targetNumTrianglesPerLeaf)); @@ -97,7 +116,7 @@ bool KdTree::build(BuildOptions& options, osg::Geometry* geometry) osg::notify(osg::NOTICE)<<"kdTree->_kdNodes.reserve()="<size()*2; _primitiveIndices.reserve(estimatedNumTriangles); - _triangles.reserve(estimatedNumTriangles); _centers.reserve(estimatedNumTriangles); - + _kdTree.getTriangles().reserve(estimatedNumTriangles); osg::TriangleIndexFunctor collectTriangleIndices; - collectTriangleIndices._kdTree = this; + collectTriangleIndices._buildKdTree = this; geometry->accept(collectTriangleIndices); _primitiveIndices.reserve(vertices->size()); - KdNode node(-1, _primitiveIndices.size()); + KdTree::KdNode node(-1, _primitiveIndices.size()); node.bb = _bb; - int nodeNum = addNode(node); + int nodeNum = _kdTree.addNode(node); osg::BoundingBox bb = _bb; nodeNum = divide(options, bb, nodeNum, 0); + // now reorder the triangle list so that it's in order as per the primitiveIndex list. + KdTree::TriangleList triangleList(_kdTree.getTriangles().size()); + for(unsigned int i=0; i<_primitiveIndices.size(); ++i) + { + triangleList[i] = _kdTree.getTriangle(_primitiveIndices[i]); + } + + _kdTree.getTriangles().swap(triangleList); + + #ifdef VERBOSE_OUTPUT osg::notify(osg::NOTICE)<<"Root nodeNum="<=0.0f) + osg::Vec3 T = _s - v0; + osg::Vec3 E2 = v2 - v0; + osg::Vec3 E1 = v1 - v0; + + osg::Vec3 P = _d ^ E2; + + float det = P * E1; + + float r,r0,r1,r2; + + const float esplison = 1e-10; + if (det>esplison) { - if (ds12<0.0f) continue; - if (ds12>d312) continue; + float u = (P*T); + if (u<0.0 || u>det) continue; + + osg::Vec3 Q = T ^ E1; + float v = (Q*_d); + if (v<0.0 || v>det) continue; + + if ((u+v)> det) continue; + + float inv_det = 1.0f/det; + float t = (Q*E2)*inv_det; + if (t<0.0 || t>_length) continue; + + u *= inv_det; + v *= inv_det; + + r0 = 1.0f-u-v; + r1 = u; + r2 = v; + r = t * _inverse_length; } - else // d312 < 0 + else if (det<-esplison) { - if (ds12>0.0f) continue; - if (ds120.0 || u0.0 || v_length) continue; + + u *= inv_det; + v *= inv_det; + + r0 = 1.0f-u-v; + r1 = u; + r2 = v; + r = t * _inverse_length; } - - osg::Vec3 v23 = v3-v2; - osg::Vec3 n23 = v23^rayData._d; - float ds23 = (rayData._s-v2)*n23; - float d123 = (v1-v2)*n23; - if (d123>=0.0f) + else { - if (ds23<0.0f) continue; - if (ds23>d123) continue; - } - else // d123 < 0 - { - if (ds23>0.0f) continue; - if (ds23=0.0f) - { - if (ds31<0.0f) continue; - if (ds31>d231) continue; - } - else // d231 < 0 - { - if (ds31>0.0f) continue; - if (ds31rayData._length) continue; - - osg::Vec3 normal = v12^v23; + osg::Vec3 in = v0*r0 + v1*r1 + v2*r2; + osg::Vec3 normal = E1^E2; normal.normalize(); + +#if 1 + _intersections.push_back(KdTree::LineSegmentIntersection()); + KdTree::LineSegmentIntersection& intersection = _intersections.back(); - float r = d* rayData._inverse_length; - - LineSegmentIntersection intersection; intersection.ratio = r; - intersection.primitiveIndex = _primitiveIndices[i]; + intersection.primitiveIndex = i; intersection.intersectionPoint = in; intersection.intersectionNormal = normal; - intersection.indexList.push_back(tri._p1); - intersection.indexList.push_back(tri._p2); - intersection.indexList.push_back(tri._p3); - - intersection.ratioList.push_back(r1); - intersection.ratioList.push_back(r2); - intersection.ratioList.push_back(r3); - - intersections.insert(intersection); + intersection.p0 = tri.p0; + intersection.p1 = tri.p1; + intersection.p2 = tri.p2; + intersection.r0 = r0; + intersection.r1 = r1; + intersection.r2 = r1; +#endif // osg::notify(osg::NOTICE)<<" got intersection ("<