b2_broad_phase.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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_BROAD_PHASE_H
  19. #define B2_BROAD_PHASE_H
  20. #include "b2_api.h"
  21. #include "b2_settings.h"
  22. #include "b2_collision.h"
  23. #include "b2_dynamic_tree.h"
  24. struct B2_API 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 B2_API 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 nullptr 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. float 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. inline void* b2BroadPhase::GetUserData(int32 proxyId) const
  101. {
  102. return m_tree.GetUserData(proxyId);
  103. }
  104. inline bool b2BroadPhase::TestOverlap(int32 proxyIdA, int32 proxyIdB) const
  105. {
  106. const b2AABB& aabbA = m_tree.GetFatAABB(proxyIdA);
  107. const b2AABB& aabbB = m_tree.GetFatAABB(proxyIdB);
  108. return b2TestOverlap(aabbA, aabbB);
  109. }
  110. inline const b2AABB& b2BroadPhase::GetFatAABB(int32 proxyId) const
  111. {
  112. return m_tree.GetFatAABB(proxyId);
  113. }
  114. inline int32 b2BroadPhase::GetProxyCount() const
  115. {
  116. return m_proxyCount;
  117. }
  118. inline int32 b2BroadPhase::GetTreeHeight() const
  119. {
  120. return m_tree.GetHeight();
  121. }
  122. inline int32 b2BroadPhase::GetTreeBalance() const
  123. {
  124. return m_tree.GetMaxBalance();
  125. }
  126. inline float b2BroadPhase::GetTreeQuality() const
  127. {
  128. return m_tree.GetAreaRatio();
  129. }
  130. template <typename T>
  131. void b2BroadPhase::UpdatePairs(T* callback)
  132. {
  133. // Reset pair buffer
  134. m_pairCount = 0;
  135. // Perform tree queries for all moving proxies.
  136. for (int32 i = 0; i < m_moveCount; ++i)
  137. {
  138. m_queryProxyId = m_moveBuffer[i];
  139. if (m_queryProxyId == e_nullProxy)
  140. {
  141. continue;
  142. }
  143. // We have to query the tree with the fat AABB so that
  144. // we don't fail to create a pair that may touch later.
  145. const b2AABB& fatAABB = m_tree.GetFatAABB(m_queryProxyId);
  146. // Query tree, create pairs and add them pair buffer.
  147. m_tree.Query(this, fatAABB);
  148. }
  149. // Send pairs to caller
  150. for (int32 i = 0; i < m_pairCount; ++i)
  151. {
  152. b2Pair* primaryPair = m_pairBuffer + i;
  153. void* userDataA = m_tree.GetUserData(primaryPair->proxyIdA);
  154. void* userDataB = m_tree.GetUserData(primaryPair->proxyIdB);
  155. callback->AddPair(userDataA, userDataB);
  156. }
  157. // Clear move flags
  158. for (int32 i = 0; i < m_moveCount; ++i)
  159. {
  160. int32 proxyId = m_moveBuffer[i];
  161. if (proxyId == e_nullProxy)
  162. {
  163. continue;
  164. }
  165. m_tree.ClearMoved(proxyId);
  166. }
  167. // Reset move buffer
  168. m_moveCount = 0;
  169. }
  170. template <typename T>
  171. inline void b2BroadPhase::Query(T* callback, const b2AABB& aabb) const
  172. {
  173. m_tree.Query(callback, aabb);
  174. }
  175. template <typename T>
  176. inline void b2BroadPhase::RayCast(T* callback, const b2RayCastInput& input) const
  177. {
  178. m_tree.RayCast(callback, input);
  179. }
  180. inline void b2BroadPhase::ShiftOrigin(const b2Vec2& newOrigin)
  181. {
  182. m_tree.ShiftOrigin(newOrigin);
  183. }
  184. #endif