diff --git a/examples/osgkdtree/variabledivision.h b/examples/osgkdtree/variabledivision.h index 72eccf48b..2470a7b67 100644 --- a/examples/osgkdtree/variabledivision.h +++ b/examples/osgkdtree/variabledivision.h @@ -118,7 +118,6 @@ class KDTree : public osg::Shape typedef std::vector< unsigned int > AxisStack; typedef std::vector< KDNode > KDNodeList; - typedef std::vector< KDLeaf > KDLeafList; /// note, leafNum is negative to distinguish from nodeNum diff --git a/include/osg/KdTree b/include/osg/KdTree index c0e26b820..eaff4c808 100644 --- a/include/osg/KdTree +++ b/include/osg/KdTree @@ -26,17 +26,28 @@ class OSG_EXPORT KdTree : public osg::Shape public: - KdTree() {} + KdTree(); - KdTree(const KdTree& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY): - Shape(rhs,copyop) {} + KdTree(const KdTree& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); META_Shape(osg, KdTree) + struct BuildOptions + { + BuildOptions(): + _numVerticesProcessed(0), + _targetNumTrianglesPerLeaf(4), + _maxNumLevels(24) {} + + unsigned int _numVerticesProcessed; + unsigned int _targetNumTrianglesPerLeaf; + unsigned int _maxNumLevels; + }; + + /** Build the kdtree from the specified source geometry object. * retun true on success. */ - virtual bool build(osg::Geometry* geometry); - + virtual bool build(BuildOptions& buildOptions, osg::Geometry* geometry); struct LineSegmentIntersection { @@ -68,13 +79,13 @@ class OSG_EXPORT KdTree : public osg::Shape typedef int value_type; typedef std::vector< value_type > Indices; - struct KDNode + struct KdNode { - KDNode(): + KdNode(): first(0), second(0) {} - KDNode(value_type f, value_type s): + KdNode(value_type f, value_type s): first(f), second(s) {} @@ -85,13 +96,13 @@ class OSG_EXPORT KdTree : public osg::Shape }; - struct KDLeaf + struct KdLeaf { - KDLeaf(): + KdLeaf(): first(0), second(0) {} - KDLeaf(value_type f, value_type s): + KdLeaf(value_type f, value_type s): first(f), second(s) {} @@ -120,6 +131,93 @@ class OSG_EXPORT KdTree : public osg::Shape unsigned int _p3; }; + typedef std::vector< unsigned int > AxisStack; + typedef std::vector< KdNode > KDNodeList; + typedef std::vector< KdLeaf > KDLeafList; + + /// note, leafNum is negative to distinguish from nodeNum + int addLeaf(const KdLeaf& leaf) { int num = _kdLeaves.size(); _kdLeaves.push_back(leaf); return -(num+1); } + + int replaceLeaf(int leafNum, const KdLeaf& leaf) + { + int num = -leafNum-1; + + if (num>_kdLeaves.size()-1) + { + osg::notify(osg::NOTICE)<<"Warning: replaceChild("<(geometry->getVertexArray()); + if (!vertices) return false; + + if (vertices->size() <= options._targetNumTrianglesPerLeaf) return false; + + _geometry = geometry; + _bb = _geometry->getBound(); + _vertices = vertices; + + unsigned int estimatedSize = (unsigned int)(2.0*float(vertices->size())/float(options._targetNumTrianglesPerLeaf)); + +#ifdef VERBOSE_OUTPUT + osg::notify(osg::NOTICE)<<"kdTree->_kdNodes.reserve()="<size(); + + unsigned int estimatedNumTriangles = vertices->size()*2; + _primitiveIndices.reserve(estimatedNumTriangles); + _boundingBoxes.reserve(estimatedNumTriangles); + _triangles.reserve(estimatedNumTriangles); + _centers.reserve(estimatedNumTriangles); + + + + osg::TriangleIndexFunctor collectTriangleIndices; + collectTriangleIndices._kdTree = this; + geometry->accept(collectTriangleIndices); + + _primitiveIndices.reserve(vertices->size()); + + + + KdLeaf leaf(0, _primitiveIndices.size()); + + int leafNum = addLeaf(leaf); + + osg::BoundingBox bb = _bb; + int nodeNum = divide(options, bb, leafNum, 0); + +#ifdef VERBOSE_OUTPUT + osg::notify(osg::NOTICE)<<"Root nodeNum="<=dimensions[1]) + { + if (dimensions[0]>=dimensions[2]) axis = 0; + else axis = 2; + } + else if (dimensions[1]>=dimensions[2]) axis = 1; + else axis = 2; + + _axisStack.push_back(axis); + dimensions[axis] /= 2.0f; + +#ifdef VERBOSE_OUTPUT + osg::notify(osg::NOTICE)<<" "<mid)) { --right; } + + while(leftmid)) { --right; } + + if (left kdTree = dynamic_cast(_kdTreePrototype->cloneType()); - if (kdTree->build(geom)) + if (kdTree->build(_buildOptions, geom)) { geom->setShape(kdTree.get()); }