AABBTreeBuilder.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <Jolt/Jolt.h>
  5. #include <Jolt/AABBTree/AABBTreeBuilder.h>
  6. JPH_NAMESPACE_BEGIN
  7. uint AABBTreeBuilder::Node::GetMinDepth(const Array<Node> &inNodes) const
  8. {
  9. if (HasChildren())
  10. {
  11. uint left = inNodes[mChild[0]].GetMinDepth(inNodes);
  12. uint right = inNodes[mChild[1]].GetMinDepth(inNodes);
  13. return min(left, right) + 1;
  14. }
  15. else
  16. return 1;
  17. }
  18. uint AABBTreeBuilder::Node::GetMaxDepth(const Array<Node> &inNodes) const
  19. {
  20. if (HasChildren())
  21. {
  22. uint left = inNodes[mChild[0]].GetMaxDepth(inNodes);
  23. uint right = inNodes[mChild[1]].GetMaxDepth(inNodes);
  24. return max(left, right) + 1;
  25. }
  26. else
  27. return 1;
  28. }
  29. uint AABBTreeBuilder::Node::GetNodeCount(const Array<Node> &inNodes) const
  30. {
  31. if (HasChildren())
  32. return inNodes[mChild[0]].GetNodeCount(inNodes) + inNodes[mChild[1]].GetNodeCount(inNodes) + 1;
  33. else
  34. return 1;
  35. }
  36. uint AABBTreeBuilder::Node::GetLeafNodeCount(const Array<Node> &inNodes) const
  37. {
  38. if (HasChildren())
  39. return inNodes[mChild[0]].GetLeafNodeCount(inNodes) + inNodes[mChild[1]].GetLeafNodeCount(inNodes);
  40. else
  41. return 1;
  42. }
  43. uint AABBTreeBuilder::Node::GetTriangleCountInTree(const Array<Node> &inNodes) const
  44. {
  45. if (HasChildren())
  46. return inNodes[mChild[0]].GetTriangleCountInTree(inNodes) + inNodes[mChild[1]].GetTriangleCountInTree(inNodes);
  47. else
  48. return GetTriangleCount();
  49. }
  50. void AABBTreeBuilder::Node::GetTriangleCountPerNode(const Array<Node> &inNodes, float &outAverage, uint &outMin, uint &outMax) const
  51. {
  52. outMin = INT_MAX;
  53. outMax = 0;
  54. outAverage = 0;
  55. uint avg_divisor = 0;
  56. GetTriangleCountPerNodeInternal(inNodes, outAverage, avg_divisor, outMin, outMax);
  57. if (avg_divisor > 0)
  58. outAverage /= avg_divisor;
  59. }
  60. float AABBTreeBuilder::Node::CalculateSAHCost(const Array<Node> &inNodes, float inCostTraversal, float inCostLeaf) const
  61. {
  62. float surface_area = mBounds.GetSurfaceArea();
  63. return surface_area > 0.0f? CalculateSAHCostInternal(inNodes, inCostTraversal / surface_area, inCostLeaf / surface_area) : 0.0f;
  64. }
  65. void AABBTreeBuilder::Node::GetNChildren(const Array<Node> &inNodes, uint inN, Array<const Node*> &outChildren) const
  66. {
  67. JPH_ASSERT(outChildren.empty());
  68. // Check if there is anything to expand
  69. if (!HasChildren())
  70. return;
  71. // Start with the children of this node
  72. outChildren.push_back(&inNodes[mChild[0]]);
  73. outChildren.push_back(&inNodes[mChild[1]]);
  74. size_t next = 0;
  75. bool all_triangles = true;
  76. while (outChildren.size() < inN)
  77. {
  78. // If we have looped over all nodes, start over with the first node again
  79. if (next >= outChildren.size())
  80. {
  81. // If there only triangle nodes left, we have to terminate
  82. if (all_triangles)
  83. return;
  84. next = 0;
  85. all_triangles = true;
  86. }
  87. // Try to expand this node into its two children
  88. const Node *to_expand = outChildren[next];
  89. if (to_expand->HasChildren())
  90. {
  91. outChildren.erase(outChildren.begin() + next);
  92. outChildren.push_back(&inNodes[to_expand->mChild[0]]);
  93. outChildren.push_back(&inNodes[to_expand->mChild[1]]);
  94. all_triangles = false;
  95. }
  96. else
  97. {
  98. ++next;
  99. }
  100. }
  101. }
  102. float AABBTreeBuilder::Node::CalculateSAHCostInternal(const Array<Node> &inNodes, float inCostTraversalDivSurfaceArea, float inCostLeafDivSurfaceArea) const
  103. {
  104. if (HasChildren())
  105. return inCostTraversalDivSurfaceArea * mBounds.GetSurfaceArea()
  106. + inNodes[mChild[0]].CalculateSAHCostInternal(inNodes, inCostTraversalDivSurfaceArea, inCostLeafDivSurfaceArea)
  107. + inNodes[mChild[1]].CalculateSAHCostInternal(inNodes, inCostTraversalDivSurfaceArea, inCostLeafDivSurfaceArea);
  108. else
  109. return inCostLeafDivSurfaceArea * mBounds.GetSurfaceArea() * GetTriangleCount();
  110. }
  111. void AABBTreeBuilder::Node::GetTriangleCountPerNodeInternal(const Array<Node> &inNodes, float &outAverage, uint &outAverageDivisor, uint &outMin, uint &outMax) const
  112. {
  113. if (HasChildren())
  114. {
  115. inNodes[mChild[0]].GetTriangleCountPerNodeInternal(inNodes, outAverage, outAverageDivisor, outMin, outMax);
  116. inNodes[mChild[1]].GetTriangleCountPerNodeInternal(inNodes, outAverage, outAverageDivisor, outMin, outMax);
  117. }
  118. else
  119. {
  120. outAverage += GetTriangleCount();
  121. outAverageDivisor++;
  122. outMin = min(outMin, GetTriangleCount());
  123. outMax = max(outMax, GetTriangleCount());
  124. }
  125. }
  126. AABBTreeBuilder::AABBTreeBuilder(TriangleSplitter &inSplitter, uint inMaxTrianglesPerLeaf) :
  127. mTriangleSplitter(inSplitter),
  128. mMaxTrianglesPerLeaf(inMaxTrianglesPerLeaf)
  129. {
  130. }
  131. AABBTreeBuilder::Node *AABBTreeBuilder::Build(AABBTreeBuilderStats &outStats)
  132. {
  133. TriangleSplitter::Range initial = mTriangleSplitter.GetInitialRange();
  134. // Worst case for number of nodes: 1 leaf node per triangle. At each level above, the number of nodes is half that of the level below.
  135. // This means that at most we'll be allocating 2x the number of triangles in nodes.
  136. mNodes.reserve(2 * initial.Count());
  137. mTriangles.reserve(initial.Count());
  138. // Build the tree
  139. Node &root = mNodes[BuildInternal(initial)];
  140. // Collect stats
  141. float avg_triangles_per_leaf;
  142. uint min_triangles_per_leaf, max_triangles_per_leaf;
  143. root.GetTriangleCountPerNode(mNodes, avg_triangles_per_leaf, min_triangles_per_leaf, max_triangles_per_leaf);
  144. mTriangleSplitter.GetStats(outStats.mSplitterStats);
  145. outStats.mSAHCost = root.CalculateSAHCost(mNodes, 1.0f, 1.0f);
  146. outStats.mMinDepth = root.GetMinDepth(mNodes);
  147. outStats.mMaxDepth = root.GetMaxDepth(mNodes);
  148. outStats.mNodeCount = root.GetNodeCount(mNodes);
  149. outStats.mLeafNodeCount = root.GetLeafNodeCount(mNodes);
  150. outStats.mMaxTrianglesPerLeaf = mMaxTrianglesPerLeaf;
  151. outStats.mTreeMinTrianglesPerLeaf = min_triangles_per_leaf;
  152. outStats.mTreeMaxTrianglesPerLeaf = max_triangles_per_leaf;
  153. outStats.mTreeAvgTrianglesPerLeaf = avg_triangles_per_leaf;
  154. return &root;
  155. }
  156. uint AABBTreeBuilder::BuildInternal(const TriangleSplitter::Range &inTriangles)
  157. {
  158. // Check if there are too many triangles left
  159. if (inTriangles.Count() > mMaxTrianglesPerLeaf)
  160. {
  161. // Split triangles in two batches
  162. TriangleSplitter::Range left, right;
  163. if (!mTriangleSplitter.Split(inTriangles, left, right))
  164. {
  165. // When the trace below triggers:
  166. //
  167. // This code builds a tree structure to accelerate collision detection.
  168. // At top level it will start with all triangles in a mesh and then divides the triangles into two batches.
  169. // This process repeats until until the batch size is smaller than mMaxTrianglePerLeaf.
  170. //
  171. // It uses a TriangleSplitter to find a good split. When this warning triggers, the splitter was not able
  172. // to create a reasonable split for the triangles. This usually happens when the triangles in a batch are
  173. // intersecting. They could also be overlapping when projected on the 3 coordinate axis.
  174. //
  175. // To solve this issue, you could try to pass your mesh through a mesh cleaning / optimization algorithm.
  176. // You could also inspect the triangles that cause this issue and see if that part of the mesh can be fixed manually.
  177. //
  178. // When you do not fix this warning, the tree will be less efficient for collision detection, but it will still work.
  179. JPH_IF_DEBUG(Trace("AABBTreeBuilder: Doing random split for %d triangles (max per node: %u)!", (int)inTriangles.Count(), mMaxTrianglesPerLeaf);)
  180. int half = inTriangles.Count() / 2;
  181. JPH_ASSERT(half > 0);
  182. left = TriangleSplitter::Range(inTriangles.mBegin, inTriangles.mBegin + half);
  183. right = TriangleSplitter::Range(inTriangles.mBegin + half, inTriangles.mEnd);
  184. }
  185. // Recursively build
  186. const uint node_index = (uint)mNodes.size();
  187. mNodes.push_back(Node());
  188. uint left_index = BuildInternal(left);
  189. uint right_index = BuildInternal(right);
  190. Node &node = mNodes[node_index];
  191. node.mChild[0] = left_index;
  192. node.mChild[1] = right_index;
  193. node.mBounds = mNodes[node.mChild[0]].mBounds;
  194. node.mBounds.Encapsulate(mNodes[node.mChild[1]].mBounds);
  195. return node_index;
  196. }
  197. // Create leaf node
  198. const uint node_index = (uint)mNodes.size();
  199. mNodes.push_back(Node());
  200. Node &node = mNodes.back();
  201. node.mTrianglesBegin = (uint)mTriangles.size();
  202. node.mNumTriangles = inTriangles.mEnd - inTriangles.mBegin;
  203. const VertexList &v = mTriangleSplitter.GetVertices();
  204. for (uint i = inTriangles.mBegin; i < inTriangles.mEnd; ++i)
  205. {
  206. const IndexedTriangle &t = mTriangleSplitter.GetTriangle(i);
  207. mTriangles.push_back(t);
  208. node.mBounds.Encapsulate(v, t);
  209. }
  210. return node_index;
  211. }
  212. JPH_NAMESPACE_END