The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

285 lines
7.8KB

  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 "b2Collision.h"
  21. #include "../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. juce::int32 parent;
  36. juce::int32 next;
  37. };
  38. juce::int32 child1;
  39. juce::int32 child2;
  40. // leaf = 0, free node = -1
  41. juce::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. juce::int32 CreateProxy(const b2AABB& aabb, void* userData);
  60. /// Destroy a proxy. This asserts if the id is invalid.
  61. void DestroyProxy(juce::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(juce::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(juce::int32 proxyId) const;
  70. /// Get the fat AABB for a proxy.
  71. const b2AABB& GetFatAABB(juce::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. juce::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. juce::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. private:
  98. juce::int32 AllocateNode();
  99. void FreeNode(juce::int32 node);
  100. void InsertLeaf(juce::int32 node);
  101. void RemoveLeaf(juce::int32 node);
  102. juce::int32 Balance(juce::int32 index);
  103. juce::int32 ComputeHeight() const;
  104. juce::int32 ComputeHeight(juce::int32 nodeId) const;
  105. void ValidateStructure(juce::int32 index) const;
  106. void ValidateMetrics(juce::int32 index) const;
  107. juce::int32 m_root;
  108. b2TreeNode* m_nodes;
  109. juce::int32 m_nodeCount;
  110. juce::int32 m_nodeCapacity;
  111. juce::int32 m_freeList;
  112. /// This is used to incrementally traverse the tree for re-balancing.
  113. juce::uint32 m_path;
  114. juce::int32 m_insertionCount;
  115. };
  116. inline void* b2DynamicTree::GetUserData(juce::int32 proxyId) const
  117. {
  118. b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
  119. return m_nodes[proxyId].userData;
  120. }
  121. inline const b2AABB& b2DynamicTree::GetFatAABB(juce::int32 proxyId) const
  122. {
  123. b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
  124. return m_nodes[proxyId].aabb;
  125. }
  126. template <typename T>
  127. inline void b2DynamicTree::Query(T* callback, const b2AABB& aabb) const
  128. {
  129. b2GrowableStack<juce::int32, 256> stack;
  130. stack.Push(m_root);
  131. while (stack.GetCount() > 0)
  132. {
  133. juce::int32 nodeId = stack.Pop();
  134. if (nodeId == b2_nullNode)
  135. {
  136. continue;
  137. }
  138. const b2TreeNode* node = m_nodes + nodeId;
  139. if (b2TestOverlap(node->aabb, aabb))
  140. {
  141. if (node->IsLeaf())
  142. {
  143. bool proceed = callback->QueryCallback(nodeId);
  144. if (proceed == false)
  145. {
  146. return;
  147. }
  148. }
  149. else
  150. {
  151. stack.Push(node->child1);
  152. stack.Push(node->child2);
  153. }
  154. }
  155. }
  156. }
  157. template <typename T>
  158. inline void b2DynamicTree::RayCast(T* callback, const b2RayCastInput& input) const
  159. {
  160. b2Vec2 p1 = input.p1;
  161. b2Vec2 p2 = input.p2;
  162. b2Vec2 r = p2 - p1;
  163. b2Assert(r.LengthSquared() > 0.0f);
  164. r.Normalize();
  165. // v is perpendicular to the segment.
  166. b2Vec2 v = b2Cross(1.0f, r);
  167. b2Vec2 abs_v = b2Abs(v);
  168. // Separating axis for segment (Gino, p80).
  169. // |dot(v, p1 - c)| > dot(|v|, h)
  170. float32 maxFraction = input.maxFraction;
  171. // Build a bounding box for the segment.
  172. b2AABB segmentAABB;
  173. {
  174. b2Vec2 t = p1 + maxFraction * (p2 - p1);
  175. segmentAABB.lowerBound = b2Min(p1, t);
  176. segmentAABB.upperBound = b2Max(p1, t);
  177. }
  178. b2GrowableStack<juce::int32, 256> stack;
  179. stack.Push(m_root);
  180. while (stack.GetCount() > 0)
  181. {
  182. juce::int32 nodeId = stack.Pop();
  183. if (nodeId == b2_nullNode)
  184. {
  185. continue;
  186. }
  187. const b2TreeNode* node = m_nodes + nodeId;
  188. if (b2TestOverlap(node->aabb, segmentAABB) == false)
  189. {
  190. continue;
  191. }
  192. // Separating axis for segment (Gino, p80).
  193. // |dot(v, p1 - c)| > dot(|v|, h)
  194. b2Vec2 c = node->aabb.GetCenter();
  195. b2Vec2 h = node->aabb.GetExtents();
  196. float32 separation = b2Abs(b2Dot(v, p1 - c)) - b2Dot(abs_v, h);
  197. if (separation > 0.0f)
  198. {
  199. continue;
  200. }
  201. if (node->IsLeaf())
  202. {
  203. b2RayCastInput subInput;
  204. subInput.p1 = input.p1;
  205. subInput.p2 = input.p2;
  206. subInput.maxFraction = maxFraction;
  207. float32 value = callback->RayCastCallback(subInput, nodeId);
  208. if (value == 0.0f)
  209. {
  210. // The client has terminated the ray cast.
  211. return;
  212. }
  213. if (value > 0.0f)
  214. {
  215. // Update segment bounding box.
  216. maxFraction = value;
  217. b2Vec2 t = p1 + maxFraction * (p2 - p1);
  218. segmentAABB.lowerBound = b2Min(p1, t);
  219. segmentAABB.upperBound = b2Max(p1, t);
  220. }
  221. }
  222. else
  223. {
  224. stack.Push(node->child1);
  225. stack.Push(node->child2);
  226. }
  227. }
  228. }
  229. #endif