b2_dynamic_tree.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. // MIT License
  2. // Copyright (c) 2019 Erin Catto
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. // The above copyright notice and this permission notice shall be included in all
  10. // copies or substantial portions of the Software.
  11. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  17. // SOFTWARE.
  18. #ifndef B2_DYNAMIC_TREE_H
  19. #define B2_DYNAMIC_TREE_H
  20. #include "b2_api.h"
  21. #include "b2_collision.h"
  22. #include "b2_growable_stack.h"
  23. #define b2_nullNode (-1)
  24. /// A node in the dynamic tree. The client does not interact with this directly.
  25. struct B2_API b2TreeNode
  26. {
  27. bool IsLeaf() const
  28. {
  29. return child1 == b2_nullNode;
  30. }
  31. /// Enlarged AABB
  32. b2AABB aabb;
  33. void* userData;
  34. union
  35. {
  36. int32 parent;
  37. int32 next;
  38. };
  39. int32 child1;
  40. int32 child2;
  41. // leaf = 0, free node = -1
  42. int32 height;
  43. bool moved;
  44. };
  45. /// A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt.
  46. /// A dynamic tree arranges data in a binary tree to accelerate
  47. /// queries such as volume queries and ray casts. Leafs are proxies
  48. /// with an AABB. In the tree we expand the proxy AABB by b2_fatAABBFactor
  49. /// so that the proxy AABB is bigger than the client object. This allows the client
  50. /// object to move by small amounts without triggering a tree update.
  51. ///
  52. /// Nodes are pooled and relocatable, so we use node indices rather than pointers.
  53. class B2_API b2DynamicTree
  54. {
  55. public:
  56. /// Constructing the tree initializes the node pool.
  57. b2DynamicTree();
  58. /// Destroy the tree, freeing the node pool.
  59. ~b2DynamicTree();
  60. /// Create a proxy. Provide a tight fitting AABB and a userData pointer.
  61. int32 CreateProxy(const b2AABB& aabb, void* userData);
  62. /// Destroy a proxy. This asserts if the id is invalid.
  63. void DestroyProxy(int32 proxyId);
  64. /// Move a proxy with a swepted AABB. If the proxy has moved outside of its fattened AABB,
  65. /// then the proxy is removed from the tree and re-inserted. Otherwise
  66. /// the function returns immediately.
  67. /// @return true if the proxy was re-inserted.
  68. bool MoveProxy(int32 proxyId, const b2AABB& aabb1, const b2Vec2& displacement);
  69. /// Get proxy user data.
  70. /// @return the proxy user data or 0 if the id is invalid.
  71. void* GetUserData(int32 proxyId) const;
  72. bool WasMoved(int32 proxyId) const;
  73. void ClearMoved(int32 proxyId);
  74. /// Get the fat AABB for a proxy.
  75. const b2AABB& GetFatAABB(int32 proxyId) const;
  76. /// Query an AABB for overlapping proxies. The callback class
  77. /// is called for each proxy that overlaps the supplied AABB.
  78. template <typename T>
  79. void Query(T* callback, const b2AABB& aabb) const;
  80. /// Ray-cast against the proxies in the tree. This relies on the callback
  81. /// to perform a exact ray-cast in the case were the proxy contains a shape.
  82. /// The callback also performs the any collision filtering. This has performance
  83. /// roughly equal to k * log(n), where k is the number of collisions and n is the
  84. /// number of proxies in the tree.
  85. /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
  86. /// @param callback a callback class that is called for each proxy that is hit by the ray.
  87. template <typename T>
  88. void RayCast(T* callback, const b2RayCastInput& input) const;
  89. /// Validate this tree. For testing.
  90. void Validate() const;
  91. /// Compute the height of the binary tree in O(N) time. Should not be
  92. /// called often.
  93. int32 GetHeight() const;
  94. /// Get the maximum balance of an node in the tree. The balance is the difference
  95. /// in height of the two children of a node.
  96. int32 GetMaxBalance() const;
  97. /// Get the ratio of the sum of the node areas to the root area.
  98. float GetAreaRatio() const;
  99. /// Build an optimal tree. Very expensive. For testing.
  100. void RebuildBottomUp();
  101. /// Shift the world origin. Useful for large worlds.
  102. /// The shift formula is: position -= newOrigin
  103. /// @param newOrigin the new origin with respect to the old origin
  104. void ShiftOrigin(const b2Vec2& newOrigin);
  105. private:
  106. int32 AllocateNode();
  107. void FreeNode(int32 node);
  108. void InsertLeaf(int32 node);
  109. void RemoveLeaf(int32 node);
  110. int32 Balance(int32 index);
  111. int32 ComputeHeight() const;
  112. int32 ComputeHeight(int32 nodeId) const;
  113. void ValidateStructure(int32 index) const;
  114. void ValidateMetrics(int32 index) const;
  115. int32 m_root;
  116. b2TreeNode* m_nodes;
  117. int32 m_nodeCount;
  118. int32 m_nodeCapacity;
  119. int32 m_freeList;
  120. int32 m_insertionCount;
  121. };
  122. inline void* b2DynamicTree::GetUserData(int32 proxyId) const
  123. {
  124. b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
  125. return m_nodes[proxyId].userData;
  126. }
  127. inline bool b2DynamicTree::WasMoved(int32 proxyId) const
  128. {
  129. b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
  130. return m_nodes[proxyId].moved;
  131. }
  132. inline void b2DynamicTree::ClearMoved(int32 proxyId)
  133. {
  134. b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
  135. m_nodes[proxyId].moved = false;
  136. }
  137. inline const b2AABB& b2DynamicTree::GetFatAABB(int32 proxyId) const
  138. {
  139. b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
  140. return m_nodes[proxyId].aabb;
  141. }
  142. template <typename T>
  143. inline void b2DynamicTree::Query(T* callback, const b2AABB& aabb) const
  144. {
  145. b2GrowableStack<int32, 256> stack;
  146. stack.Push(m_root);
  147. while (stack.GetCount() > 0)
  148. {
  149. int32 nodeId = stack.Pop();
  150. if (nodeId == b2_nullNode)
  151. {
  152. continue;
  153. }
  154. const b2TreeNode* node = m_nodes + nodeId;
  155. if (b2TestOverlap(node->aabb, aabb))
  156. {
  157. if (node->IsLeaf())
  158. {
  159. bool proceed = callback->QueryCallback(nodeId);
  160. if (proceed == false)
  161. {
  162. return;
  163. }
  164. }
  165. else
  166. {
  167. stack.Push(node->child1);
  168. stack.Push(node->child2);
  169. }
  170. }
  171. }
  172. }
  173. template <typename T>
  174. inline void b2DynamicTree::RayCast(T* callback, const b2RayCastInput& input) const
  175. {
  176. b2Vec2 p1 = input.p1;
  177. b2Vec2 p2 = input.p2;
  178. b2Vec2 r = p2 - p1;
  179. b2Assert(r.LengthSquared() > 0.0f);
  180. r.Normalize();
  181. // v is perpendicular to the segment.
  182. b2Vec2 v = b2Cross(1.0f, r);
  183. b2Vec2 abs_v = b2Abs(v);
  184. // Separating axis for segment (Gino, p80).
  185. // |dot(v, p1 - c)| > dot(|v|, h)
  186. float maxFraction = input.maxFraction;
  187. // Build a bounding box for the segment.
  188. b2AABB segmentAABB;
  189. {
  190. b2Vec2 t = p1 + maxFraction * (p2 - p1);
  191. segmentAABB.lowerBound = b2Min(p1, t);
  192. segmentAABB.upperBound = b2Max(p1, t);
  193. }
  194. b2GrowableStack<int32, 256> stack;
  195. stack.Push(m_root);
  196. while (stack.GetCount() > 0)
  197. {
  198. int32 nodeId = stack.Pop();
  199. if (nodeId == b2_nullNode)
  200. {
  201. continue;
  202. }
  203. const b2TreeNode* node = m_nodes + nodeId;
  204. if (b2TestOverlap(node->aabb, segmentAABB) == false)
  205. {
  206. continue;
  207. }
  208. // Separating axis for segment (Gino, p80).
  209. // |dot(v, p1 - c)| > dot(|v|, h)
  210. b2Vec2 c = node->aabb.GetCenter();
  211. b2Vec2 h = node->aabb.GetExtents();
  212. float separation = b2Abs(b2Dot(v, p1 - c)) - b2Dot(abs_v, h);
  213. if (separation > 0.0f)
  214. {
  215. continue;
  216. }
  217. if (node->IsLeaf())
  218. {
  219. b2RayCastInput subInput;
  220. subInput.p1 = input.p1;
  221. subInput.p2 = input.p2;
  222. subInput.maxFraction = maxFraction;
  223. float value = callback->RayCastCallback(subInput, nodeId);
  224. if (value == 0.0f)
  225. {
  226. // The client has terminated the ray cast.
  227. return;
  228. }
  229. if (value > 0.0f)
  230. {
  231. // Update segment bounding box.
  232. maxFraction = value;
  233. b2Vec2 t = p1 + maxFraction * (p2 - p1);
  234. segmentAABB.lowerBound = b2Min(p1, t);
  235. segmentAABB.upperBound = b2Max(p1, t);
  236. }
  237. }
  238. else
  239. {
  240. stack.Push(node->child1);
  241. stack.Push(node->child2);
  242. }
  243. }
  244. }
  245. #endif