KdTree 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
  2. *
  3. * This library is open source and may be redistributed and/or modified under
  4. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  5. * (at your option) any later version. The full license is in LICENSE file
  6. * included with this distribution, and on the openscenegraph.org website.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * OpenSceneGraph Public License for more details.
  12. */
  13. #ifndef OSG_KDTREE
  14. #define OSG_KDTREE 1
  15. #include <osg/Shape>
  16. #include <osg/Geometry>
  17. #include <map>
  18. namespace osg
  19. {
  20. /** Implementation of a kdtree for Geometry leaves, to enable fast intersection tests.*/
  21. class OSG_EXPORT KdTree : public osg::Shape
  22. {
  23. public:
  24. KdTree();
  25. KdTree(const KdTree& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
  26. META_Shape(osg, KdTree)
  27. struct OSG_EXPORT BuildOptions
  28. {
  29. BuildOptions();
  30. unsigned int _numVerticesProcessed;
  31. unsigned int _targetNumTrianglesPerLeaf;
  32. unsigned int _maxNumLevels;
  33. };
  34. /** Build the kdtree from the specified source geometry object.
  35. * retun true on success. */
  36. virtual bool build(BuildOptions& buildOptions, osg::Geometry* geometry);
  37. void setVertices(osg::Vec3Array* vertices) { _vertices = vertices; }
  38. const osg::Vec3Array* getVertices() const { return _vertices.get(); }
  39. typedef std::vector< unsigned int > Indices;
  40. // index in the VertexIndices vector
  41. void setPrimitiveIndices(const Indices& indices) { _primitiveIndices = indices; }
  42. Indices& getPrimitiveIndices() { return _primitiveIndices; }
  43. const Indices& getPrimitiveIndices() const { return _primitiveIndices; }
  44. // vector containing the primitive vertex index data packed as no_vertice_indices then vertex indices ie. for points it's (1, p0), for lines (2, p0, p1) etc.
  45. void setVertexIndices(const Indices& indices) { _vertexIndices = indices; }
  46. Indices& getVertexIndices() { return _vertexIndices; }
  47. const Indices& getVertexIndices() const { return _vertexIndices; }
  48. inline unsigned int addPoint(unsigned int p0)
  49. {
  50. unsigned int i = _vertexIndices.size();
  51. _vertexIndices.push_back(_primitiveIndices.size() + _degenerateCount);
  52. _vertexIndices.push_back(1);
  53. _vertexIndices.push_back(p0);
  54. _primitiveIndices.push_back(i);
  55. return i;
  56. }
  57. inline unsigned int addLine(unsigned int p0, unsigned int p1)
  58. {
  59. unsigned int i = _vertexIndices.size();
  60. _vertexIndices.push_back(_primitiveIndices.size() + _degenerateCount);
  61. _vertexIndices.push_back(2);
  62. _vertexIndices.push_back(p0);
  63. _vertexIndices.push_back(p1);
  64. _primitiveIndices.push_back(i);
  65. return i;
  66. }
  67. inline unsigned int addTriangle(unsigned int p0, unsigned int p1, unsigned int p2)
  68. {
  69. unsigned int i = _vertexIndices.size();
  70. _vertexIndices.push_back(_primitiveIndices.size() + _degenerateCount);
  71. _vertexIndices.push_back(3);
  72. _vertexIndices.push_back(p0);
  73. _vertexIndices.push_back(p1);
  74. _vertexIndices.push_back(p2);
  75. _primitiveIndices.push_back(i);
  76. return i;
  77. }
  78. inline unsigned int addQuad(unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3)
  79. {
  80. unsigned int i = _vertexIndices.size();
  81. _vertexIndices.push_back(_primitiveIndices.size() + _degenerateCount);
  82. _vertexIndices.push_back(4);
  83. _vertexIndices.push_back(p0);
  84. _vertexIndices.push_back(p1);
  85. _vertexIndices.push_back(p2);
  86. _vertexIndices.push_back(p3);
  87. _primitiveIndices.push_back(i);
  88. return i;
  89. }
  90. typedef int value_type;
  91. struct KdNode
  92. {
  93. KdNode():
  94. first(0),
  95. second(0) {}
  96. KdNode(value_type f, value_type s):
  97. first(f),
  98. second(s) {}
  99. osg::BoundingBox bb;
  100. value_type first;
  101. value_type second;
  102. };
  103. typedef std::vector< KdNode > KdNodeList;
  104. int addNode(const KdNode& node)
  105. {
  106. int num = static_cast<int>(_kdNodes.size());
  107. _kdNodes.push_back(node);
  108. return num;
  109. }
  110. KdNode& getNode(int nodeNum) { return _kdNodes[nodeNum]; }
  111. const KdNode& getNode(int nodeNum) const { return _kdNodes[nodeNum]; }
  112. KdNodeList& getNodes() { return _kdNodes; }
  113. const KdNodeList& getNodes() const { return _kdNodes; }
  114. template<class IntersectFunctor>
  115. void intersect(IntersectFunctor& functor, const KdNode& node) const
  116. {
  117. if (node.first<0)
  118. {
  119. // treat as a leaf
  120. int istart = -node.first-1;
  121. int iend = istart + node.second;
  122. for(int i=istart; i<iend; ++i)
  123. {
  124. unsigned int primitiveIndex = _primitiveIndices[i];
  125. unsigned int originalPIndex = _vertexIndices[primitiveIndex++];
  126. unsigned int numVertices = _vertexIndices[primitiveIndex++];
  127. switch(numVertices)
  128. {
  129. case(1): functor.intersect(_vertices.get(), originalPIndex, _vertexIndices[primitiveIndex]); break;
  130. case(2): functor.intersect(_vertices.get(), originalPIndex, _vertexIndices[primitiveIndex], _vertexIndices[primitiveIndex+1]); break;
  131. case(3): functor.intersect(_vertices.get(), originalPIndex, _vertexIndices[primitiveIndex], _vertexIndices[primitiveIndex+1], _vertexIndices[primitiveIndex+2]); break;
  132. case(4): functor.intersect(_vertices.get(), originalPIndex, _vertexIndices[primitiveIndex], _vertexIndices[primitiveIndex+1], _vertexIndices[primitiveIndex+2], _vertexIndices[primitiveIndex+3]); break;
  133. default : OSG_NOTICE<<"Warning: KdTree::intersect() encounted unsupported primitive size of "<<numVertices<<std::endl; break;
  134. }
  135. }
  136. }
  137. else if (functor.enter(node.bb))
  138. {
  139. if (node.first>0) intersect(functor, _kdNodes[node.first]);
  140. if (node.second>0) intersect(functor, _kdNodes[node.second]);
  141. functor.leave();
  142. }
  143. }
  144. unsigned int _degenerateCount;
  145. protected:
  146. osg::ref_ptr<osg::Vec3Array> _vertices;
  147. Indices _primitiveIndices;
  148. Indices _vertexIndices;
  149. KdNodeList _kdNodes;
  150. };
  151. class OSG_EXPORT KdTreeBuilder : public osg::NodeVisitor
  152. {
  153. public:
  154. KdTreeBuilder();
  155. KdTreeBuilder(const KdTreeBuilder& rhs);
  156. META_NodeVisitor(osg, KdTreeBuilder)
  157. virtual KdTreeBuilder* clone() { return new KdTreeBuilder(*this); }
  158. void apply(Geometry& geometry);
  159. KdTree::BuildOptions _buildOptions;
  160. osg::ref_ptr<osg::KdTree> _kdTreePrototype;
  161. protected:
  162. virtual ~KdTreeBuilder() {}
  163. };
  164. }
  165. #endif