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.

249 lines
6.9KB

  1. /*
  2. * Copyright (c) 2006-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_BROAD_PHASE_H
  19. #define B2_BROAD_PHASE_H
  20. #include "../Common/b2Settings.h"
  21. #include "b2Collision.h"
  22. #include "b2DynamicTree.h"
  23. #include <algorithm>
  24. struct b2Pair
  25. {
  26. juce::int32 proxyIdA;
  27. juce::int32 proxyIdB;
  28. juce::int32 next;
  29. };
  30. /// The broad-phase is used for computing pairs and performing volume queries and ray casts.
  31. /// This broad-phase does not persist pairs. Instead, this reports potentially new pairs.
  32. /// It is up to the client to consume the new pairs and to track subsequent overlap.
  33. class b2BroadPhase
  34. {
  35. public:
  36. enum
  37. {
  38. e_nullProxy = -1
  39. };
  40. b2BroadPhase();
  41. ~b2BroadPhase();
  42. /// Create a proxy with an initial AABB. Pairs are not reported until
  43. /// UpdatePairs is called.
  44. juce::int32 CreateProxy(const b2AABB& aabb, void* userData);
  45. /// Destroy a proxy. It is up to the client to remove any pairs.
  46. void DestroyProxy(juce::int32 proxyId);
  47. /// Call MoveProxy as many times as you like, then when you are done
  48. /// call UpdatePairs to finalized the proxy pairs (for your time step).
  49. void MoveProxy(juce::int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement);
  50. /// Call to trigger a re-processing of it's pairs on the next call to UpdatePairs.
  51. void TouchProxy(juce::int32 proxyId);
  52. /// Get the fat AABB for a proxy.
  53. const b2AABB& GetFatAABB(juce::int32 proxyId) const;
  54. /// Get user data from a proxy. Returns NULL if the id is invalid.
  55. void* GetUserData(juce::int32 proxyId) const;
  56. /// Test overlap of fat AABBs.
  57. bool TestOverlap(juce::int32 proxyIdA, juce::int32 proxyIdB) const;
  58. /// Get the number of proxies.
  59. juce::int32 GetProxyCount() const;
  60. /// Update the pairs. This results in pair callbacks. This can only add pairs.
  61. template <typename T>
  62. void UpdatePairs(T* callback);
  63. /// Query an AABB for overlapping proxies. The callback class
  64. /// is called for each proxy that overlaps the supplied AABB.
  65. template <typename T>
  66. void Query(T* callback, const b2AABB& aabb) const;
  67. /// Ray-cast against the proxies in the tree. This relies on the callback
  68. /// to perform a exact ray-cast in the case were the proxy contains a shape.
  69. /// The callback also performs the any collision filtering. This has performance
  70. /// roughly equal to k * log(n), where k is the number of collisions and n is the
  71. /// number of proxies in the tree.
  72. /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
  73. /// @param callback a callback class that is called for each proxy that is hit by the ray.
  74. template <typename T>
  75. void RayCast(T* callback, const b2RayCastInput& input) const;
  76. /// Get the height of the embedded tree.
  77. juce::int32 GetTreeHeight() const;
  78. /// Get the balance of the embedded tree.
  79. juce::int32 GetTreeBalance() const;
  80. /// Get the quality metric of the embedded tree.
  81. float32 GetTreeQuality() const;
  82. private:
  83. friend class b2DynamicTree;
  84. void BufferMove(juce::int32 proxyId);
  85. void UnBufferMove(juce::int32 proxyId);
  86. bool QueryCallback(juce::int32 proxyId);
  87. b2DynamicTree m_tree;
  88. juce::int32 m_proxyCount;
  89. juce::int32* m_moveBuffer;
  90. juce::int32 m_moveCapacity;
  91. juce::int32 m_moveCount;
  92. b2Pair* m_pairBuffer;
  93. juce::int32 m_pairCapacity;
  94. juce::int32 m_pairCount;
  95. juce::int32 m_queryProxyId;
  96. };
  97. /// This is used to sort pairs.
  98. inline bool b2PairLessThan(const b2Pair& pair1, const b2Pair& pair2)
  99. {
  100. if (pair1.proxyIdA < pair2.proxyIdA)
  101. {
  102. return true;
  103. }
  104. if (pair1.proxyIdA == pair2.proxyIdA)
  105. {
  106. return pair1.proxyIdB < pair2.proxyIdB;
  107. }
  108. return false;
  109. }
  110. inline void* b2BroadPhase::GetUserData(juce::int32 proxyId) const
  111. {
  112. return m_tree.GetUserData(proxyId);
  113. }
  114. inline bool b2BroadPhase::TestOverlap(juce::int32 proxyIdA, juce::int32 proxyIdB) const
  115. {
  116. const b2AABB& aabbA = m_tree.GetFatAABB(proxyIdA);
  117. const b2AABB& aabbB = m_tree.GetFatAABB(proxyIdB);
  118. return b2TestOverlap(aabbA, aabbB);
  119. }
  120. inline const b2AABB& b2BroadPhase::GetFatAABB(juce::int32 proxyId) const
  121. {
  122. return m_tree.GetFatAABB(proxyId);
  123. }
  124. inline juce::int32 b2BroadPhase::GetProxyCount() const
  125. {
  126. return m_proxyCount;
  127. }
  128. inline juce::int32 b2BroadPhase::GetTreeHeight() const
  129. {
  130. return m_tree.GetHeight();
  131. }
  132. inline juce::int32 b2BroadPhase::GetTreeBalance() const
  133. {
  134. return m_tree.GetMaxBalance();
  135. }
  136. inline float32 b2BroadPhase::GetTreeQuality() const
  137. {
  138. return m_tree.GetAreaRatio();
  139. }
  140. template <typename T>
  141. void b2BroadPhase::UpdatePairs(T* callback)
  142. {
  143. // Reset pair buffer
  144. m_pairCount = 0;
  145. // Perform tree queries for all moving proxies.
  146. for (juce::int32 i = 0; i < m_moveCount; ++i)
  147. {
  148. m_queryProxyId = m_moveBuffer[i];
  149. if (m_queryProxyId == e_nullProxy)
  150. {
  151. continue;
  152. }
  153. // We have to query the tree with the fat AABB so that
  154. // we don't fail to create a pair that may touch later.
  155. const b2AABB& fatAABB = m_tree.GetFatAABB(m_queryProxyId);
  156. // Query tree, create pairs and add them pair buffer.
  157. m_tree.Query(this, fatAABB);
  158. }
  159. // Reset move buffer
  160. m_moveCount = 0;
  161. // Sort the pair buffer to expose duplicates.
  162. std::sort(m_pairBuffer, m_pairBuffer + m_pairCount, b2PairLessThan);
  163. // Send the pairs back to the client.
  164. juce::int32 i = 0;
  165. while (i < m_pairCount)
  166. {
  167. b2Pair* primaryPair = m_pairBuffer + i;
  168. void* userDataA = m_tree.GetUserData(primaryPair->proxyIdA);
  169. void* userDataB = m_tree.GetUserData(primaryPair->proxyIdB);
  170. callback->AddPair(userDataA, userDataB);
  171. ++i;
  172. // Skip any duplicate pairs.
  173. while (i < m_pairCount)
  174. {
  175. b2Pair* pair = m_pairBuffer + i;
  176. if (pair->proxyIdA != primaryPair->proxyIdA || pair->proxyIdB != primaryPair->proxyIdB)
  177. {
  178. break;
  179. }
  180. ++i;
  181. }
  182. }
  183. // Try to keep the tree balanced.
  184. //m_tree.Rebalance(4);
  185. }
  186. template <typename T>
  187. inline void b2BroadPhase::Query(T* callback, const b2AABB& aabb) const
  188. {
  189. m_tree.Query(callback, aabb);
  190. }
  191. template <typename T>
  192. inline void b2BroadPhase::RayCast(T* callback, const b2RayCastInput& input) const
  193. {
  194. m_tree.RayCast(callback, input);
  195. }
  196. #endif