b2BroadPhase.h 6.8 KB

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