b2DynamicTree.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /*
  2. * Copyright (c) 2009 Erin Catto http://www.box2d.org
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. * Permission is granted to anyone to use this software for any purpose,
  8. * including commercial applications, and to alter it and redistribute it
  9. * freely, subject to the following restrictions:
  10. * 1. The origin of this software must not be misrepresented; you must not
  11. * claim that you wrote the original software. If you use this software
  12. * in a product, an acknowledgment in the product documentation would be
  13. * appreciated but is not required.
  14. * 2. Altered source versions must be plainly marked as such, and must not be
  15. * misrepresented as being the original software.
  16. * 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #ifndef B2_DYNAMIC_TREE_H
  19. #define B2_DYNAMIC_TREE_H
  20. #include <Box2D/Collision/b2Collision.h>
  21. #include <Box2D/Common/b2GrowableStack.h>
  22. #define b2_nullNode (-1)
  23. /// A node in the dynamic tree. The client does not interact with this directly.
  24. struct b2TreeNode
  25. {
  26. bool IsLeaf() const
  27. {
  28. return child1 == b2_nullNode;
  29. }
  30. /// Enlarged AABB
  31. b2AABB aabb;
  32. void* userData;
  33. union
  34. {
  35. int32 parent;
  36. int32 next;
  37. };
  38. int32 child1;
  39. int32 child2;
  40. // leaf = 0, free node = -1
  41. int32 height;
  42. };
  43. /// A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt.
  44. /// A dynamic tree arranges data in a binary tree to accelerate
  45. /// queries such as volume queries and ray casts. Leafs are proxies
  46. /// with an AABB. In the tree we expand the proxy AABB by b2_fatAABBFactor
  47. /// so that the proxy AABB is bigger than the client object. This allows the client
  48. /// object to move by small amounts without triggering a tree update.
  49. ///
  50. /// Nodes are pooled and relocatable, so we use node indices rather than pointers.
  51. class b2DynamicTree
  52. {
  53. public:
  54. /// Constructing the tree initializes the node pool.
  55. b2DynamicTree();
  56. /// Destroy the tree, freeing the node pool.
  57. ~b2DynamicTree();
  58. /// Create a proxy. Provide a tight fitting AABB and a userData pointer.
  59. int32 CreateProxy(const b2AABB& aabb, void* userData);
  60. /// Destroy a proxy. This asserts if the id is invalid.
  61. void DestroyProxy(int32 proxyId);
  62. /// Move a proxy with a swepted AABB. If the proxy has moved outside of its fattened AABB,
  63. /// then the proxy is removed from the tree and re-inserted. Otherwise
  64. /// the function returns immediately.
  65. /// @return true if the proxy was re-inserted.
  66. bool MoveProxy(int32 proxyId, const b2AABB& aabb1, const b2Vec2& displacement);
  67. /// Get proxy user data.
  68. /// @return the proxy user data or 0 if the id is invalid.
  69. void* GetUserData(int32 proxyId) const;
  70. /// Get the fat AABB for a proxy.
  71. const b2AABB& GetFatAABB(int32 proxyId) const;
  72. /// Query an AABB for overlapping proxies. The callback class
  73. /// is called for each proxy that overlaps the supplied AABB.
  74. template <typename T>
  75. void Query(T* callback, const b2AABB& aabb) const;
  76. /// Ray-cast against the proxies in the tree. This relies on the callback
  77. /// to perform a exact ray-cast in the case were the proxy contains a shape.
  78. /// The callback also performs the any collision filtering. This has performance
  79. /// roughly equal to k * log(n), where k is the number of collisions and n is the
  80. /// number of proxies in the tree.
  81. /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
  82. /// @param callback a callback class that is called for each proxy that is hit by the ray.
  83. template <typename T>
  84. void RayCast(T* callback, const b2RayCastInput& input) const;
  85. /// Validate this tree. For testing.
  86. void Validate() const;
  87. /// Compute the height of the binary tree in O(N) time. Should not be
  88. /// called often.
  89. int32 GetHeight() const;
  90. /// Get the maximum balance of an node in the tree. The balance is the difference
  91. /// in height of the two children of a node.
  92. int32 GetMaxBalance() const;
  93. /// Get the ratio of the sum of the node areas to the root area.
  94. float32 GetAreaRatio() const;
  95. /// Build an optimal tree. Very expensive. For testing.
  96. void RebuildBottomUp();
  97. /// Shift the world origin. Useful for large worlds.
  98. /// The shift formula is: position -= newOrigin
  99. /// @param newOrigin the new origin with respect to the old origin
  100. void ShiftOrigin(const b2Vec2& newOrigin);
  101. private:
  102. int32 AllocateNode();
  103. void FreeNode(int32 node);
  104. void InsertLeaf(int32 node);
  105. void RemoveLeaf(int32 node);
  106. int32 Balance(int32 index);
  107. int32 ComputeHeight() const;
  108. int32 ComputeHeight(int32 nodeId) const;
  109. void ValidateStructure(int32 index) const;
  110. void ValidateMetrics(int32 index) const;
  111. int32 m_root;
  112. b2TreeNode* m_nodes;
  113. int32 m_nodeCount;
  114. int32 m_nodeCapacity;
  115. int32 m_freeList;
  116. /// This is used to incrementally traverse the tree for re-balancing.
  117. uint32 m_path;
  118. int32 m_insertionCount;
  119. };
  120. inline void* b2DynamicTree::GetUserData(int32 proxyId) const
  121. {
  122. b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
  123. return m_nodes[proxyId].userData;
  124. }
  125. inline const b2AABB& b2DynamicTree::GetFatAABB(int32 proxyId) const
  126. {
  127. b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
  128. return m_nodes[proxyId].aabb;
  129. }
  130. template <typename T>
  131. inline void b2DynamicTree::Query(T* callback, const b2AABB& aabb) const
  132. {
  133. b2GrowableStack<int32, 256> stack;
  134. stack.Push(m_root);
  135. while (stack.GetCount() > 0)
  136. {
  137. int32 nodeId = stack.Pop();
  138. if (nodeId == b2_nullNode)
  139. {
  140. continue;
  141. }
  142. const b2TreeNode* node = m_nodes + nodeId;
  143. if (b2TestOverlap(node->aabb, aabb))
  144. {
  145. if (node->IsLeaf())
  146. {
  147. bool proceed = callback->QueryCallback(nodeId);
  148. if (proceed == false)
  149. {
  150. return;
  151. }
  152. }
  153. else
  154. {
  155. stack.Push(node->child1);
  156. stack.Push(node->child2);
  157. }
  158. }
  159. }
  160. }
  161. template <typename T>
  162. inline void b2DynamicTree::RayCast(T* callback, const b2RayCastInput& input) const
  163. {
  164. b2Vec2 p1 = input.p1;
  165. b2Vec2 p2 = input.p2;
  166. b2Vec2 r = p2 - p1;
  167. b2Assert(r.LengthSquared() > 0.0f);
  168. r.Normalize();
  169. // v is perpendicular to the segment.
  170. b2Vec2 v = b2Cross(1.0f, r);
  171. b2Vec2 abs_v = b2Abs(v);
  172. // Separating axis for segment (Gino, p80).
  173. // |dot(v, p1 - c)| > dot(|v|, h)
  174. float32 maxFraction = input.maxFraction;
  175. // Build a bounding box for the segment.
  176. b2AABB segmentAABB;
  177. {
  178. b2Vec2 t = p1 + maxFraction * (p2 - p1);
  179. segmentAABB.lowerBound = b2Min(p1, t);
  180. segmentAABB.upperBound = b2Max(p1, t);
  181. }
  182. b2GrowableStack<int32, 256> stack;
  183. stack.Push(m_root);
  184. while (stack.GetCount() > 0)
  185. {
  186. int32 nodeId = stack.Pop();
  187. if (nodeId == b2_nullNode)
  188. {
  189. continue;
  190. }
  191. const b2TreeNode* node = m_nodes + nodeId;
  192. if (b2TestOverlap(node->aabb, segmentAABB) == false)
  193. {
  194. continue;
  195. }
  196. // Separating axis for segment (Gino, p80).
  197. // |dot(v, p1 - c)| > dot(|v|, h)
  198. b2Vec2 c = node->aabb.GetCenter();
  199. b2Vec2 h = node->aabb.GetExtents();
  200. float32 separation = b2Abs(b2Dot(v, p1 - c)) - b2Dot(abs_v, h);
  201. if (separation > 0.0f)
  202. {
  203. continue;
  204. }
  205. if (node->IsLeaf())
  206. {
  207. b2RayCastInput subInput;
  208. subInput.p1 = input.p1;
  209. subInput.p2 = input.p2;
  210. subInput.maxFraction = maxFraction;
  211. float32 value = callback->RayCastCallback(subInput, nodeId);
  212. if (value == 0.0f)
  213. {
  214. // The client has terminated the ray cast.
  215. return;
  216. }
  217. if (value > 0.0f)
  218. {
  219. // Update segment bounding box.
  220. maxFraction = value;
  221. b2Vec2 t = p1 + maxFraction * (p2 - p1);
  222. segmentAABB.lowerBound = b2Min(p1, t);
  223. segmentAABB.upperBound = b2Max(p1, t);
  224. }
  225. }
  226. else
  227. {
  228. stack.Push(node->child1);
  229. stack.Push(node->child2);
  230. }
  231. }
  232. }
  233. #endif