File indexing completed on 2025-08-03 03:49:55
0001 /* 0002 * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com 0003 * 0004 * This software is provided 'as-is', without any express or implied 0005 * warranty. In no event will the authors be held liable for any damages 0006 * arising from the use of this software. 0007 * Permission is granted to anyone to use this software for any purpose, 0008 * including commercial applications, and to alter it and redistribute it 0009 * freely, subject to the following restrictions: 0010 * 1. The origin of this software must not be misrepresented; you must not 0011 * claim that you wrote the original software. If you use this software 0012 * in a product, an acknowledgment in the product documentation would be 0013 * appreciated but is not required. 0014 * 2. Altered source versions must be plainly marked as such, and must not be 0015 * misrepresented as being the original software. 0016 * 3. This notice may not be removed or altered from any source distribution. 0017 */ 0018 0019 #ifndef B2_BROAD_PHASE_H 0020 #define B2_BROAD_PHASE_H 0021 0022 #include <Box2D/Common/b2Settings.h> 0023 #include <Box2D/Collision/b2Collision.h> 0024 #include <Box2D/Collision/b2DynamicTree.h> 0025 #include <algorithm> 0026 0027 struct b2Pair 0028 { 0029 int32 proxyIdA; 0030 int32 proxyIdB; 0031 int32 next; 0032 }; 0033 0034 /// The broad-phase is used for computing pairs and performing volume queries and ray casts. 0035 /// This broad-phase does not persist pairs. Instead, this reports potentially new pairs. 0036 /// It is up to the client to consume the new pairs and to track subsequent overlap. 0037 class b2BroadPhase 0038 { 0039 public: 0040 0041 enum 0042 { 0043 e_nullProxy = -1 0044 }; 0045 0046 b2BroadPhase(); 0047 ~b2BroadPhase(); 0048 0049 /// Create a proxy with an initial AABB. Pairs are not reported until 0050 /// UpdatePairs is called. 0051 int32 CreateProxy(const b2AABB& aabb, void* userData); 0052 0053 /// Destroy a proxy. It is up to the client to remove any pairs. 0054 void DestroyProxy(int32 proxyId); 0055 0056 /// Call MoveProxy as many times as you like, then when you are done 0057 /// call UpdatePairs to finalized the proxy pairs (for your time step). 0058 void MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement); 0059 0060 /// Get the fat AABB for a proxy. 0061 const b2AABB& GetFatAABB(int32 proxyId) const; 0062 0063 /// Get user data from a proxy. Returns NULL if the id is invalid. 0064 void* GetUserData(int32 proxyId) const; 0065 0066 /// Test overlap of fat AABBs. 0067 bool TestOverlap(int32 proxyIdA, int32 proxyIdB) const; 0068 0069 /// Get the number of proxies. 0070 int32 GetProxyCount() const; 0071 0072 /// Update the pairs. This results in pair callbacks. This can only add pairs. 0073 template <typename T> 0074 void UpdatePairs(T* callback); 0075 0076 /// Query an AABB for overlapping proxies. The callback class 0077 /// is called for each proxy that overlaps the supplied AABB. 0078 template <typename T> 0079 void Query(T* callback, const b2AABB& aabb) const; 0080 0081 /// Ray-cast against the proxies in the tree. This relies on the callback 0082 /// to perform a exact ray-cast in the case were the proxy contains a shape. 0083 /// The callback also performs the any collision filtering. This has performance 0084 /// roughly equal to k * log(n), where k is the number of collisions and n is the 0085 /// number of proxies in the tree. 0086 /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1). 0087 /// @param callback a callback class that is called for each proxy that is hit by the ray. 0088 template <typename T> 0089 void RayCast(T* callback, const b2RayCastInput& input) const; 0090 0091 /// Compute the height of the embedded tree. 0092 int32 ComputeHeight() const; 0093 0094 private: 0095 0096 friend class b2DynamicTree; 0097 0098 void BufferMove(int32 proxyId); 0099 void UnBufferMove(int32 proxyId); 0100 0101 bool QueryCallback(int32 proxyId); 0102 0103 b2DynamicTree m_tree; 0104 0105 int32 m_proxyCount; 0106 0107 int32* m_moveBuffer; 0108 int32 m_moveCapacity; 0109 int32 m_moveCount; 0110 0111 b2Pair* m_pairBuffer; 0112 int32 m_pairCapacity; 0113 int32 m_pairCount; 0114 0115 int32 m_queryProxyId; 0116 }; 0117 0118 /// This is used to sort pairs. 0119 inline bool b2PairLessThan(const b2Pair& pair1, const b2Pair& pair2) 0120 { 0121 if (pair1.proxyIdA < pair2.proxyIdA) 0122 { 0123 return true; 0124 } 0125 0126 if (pair1.proxyIdA == pair2.proxyIdA) 0127 { 0128 return pair1.proxyIdB < pair2.proxyIdB; 0129 } 0130 0131 return false; 0132 } 0133 0134 inline void* b2BroadPhase::GetUserData(int32 proxyId) const 0135 { 0136 return m_tree.GetUserData(proxyId); 0137 } 0138 0139 inline bool b2BroadPhase::TestOverlap(int32 proxyIdA, int32 proxyIdB) const 0140 { 0141 const b2AABB& aabbA = m_tree.GetFatAABB(proxyIdA); 0142 const b2AABB& aabbB = m_tree.GetFatAABB(proxyIdB); 0143 return b2TestOverlap(aabbA, aabbB); 0144 } 0145 0146 inline const b2AABB& b2BroadPhase::GetFatAABB(int32 proxyId) const 0147 { 0148 return m_tree.GetFatAABB(proxyId); 0149 } 0150 0151 inline int32 b2BroadPhase::GetProxyCount() const 0152 { 0153 return m_proxyCount; 0154 } 0155 0156 inline int32 b2BroadPhase::ComputeHeight() const 0157 { 0158 return m_tree.ComputeHeight(); 0159 } 0160 0161 template <typename T> 0162 void b2BroadPhase::UpdatePairs(T* callback) 0163 { 0164 // Reset pair buffer 0165 m_pairCount = 0; 0166 0167 // Perform tree queries for all moving proxies. 0168 for (int32 i = 0; i < m_moveCount; ++i) 0169 { 0170 m_queryProxyId = m_moveBuffer[i]; 0171 if (m_queryProxyId == e_nullProxy) 0172 { 0173 continue; 0174 } 0175 0176 // We have to query the tree with the fat AABB so that 0177 // we don't fail to create a pair that may touch later. 0178 const b2AABB& fatAABB = m_tree.GetFatAABB(m_queryProxyId); 0179 0180 // Query tree, create pairs and add them pair buffer. 0181 m_tree.Query(this, fatAABB); 0182 } 0183 0184 // Reset move buffer 0185 m_moveCount = 0; 0186 0187 // Sort the pair buffer to expose duplicates. 0188 std::sort(m_pairBuffer, m_pairBuffer + m_pairCount, b2PairLessThan); 0189 0190 // Send the pairs back to the client. 0191 int32 i = 0; 0192 while (i < m_pairCount) 0193 { 0194 b2Pair* primaryPair = m_pairBuffer + i; 0195 void* userDataA = m_tree.GetUserData(primaryPair->proxyIdA); 0196 void* userDataB = m_tree.GetUserData(primaryPair->proxyIdB); 0197 0198 callback->AddPair(userDataA, userDataB); 0199 ++i; 0200 0201 // Skip any duplicate pairs. 0202 while (i < m_pairCount) 0203 { 0204 b2Pair* pair = m_pairBuffer + i; 0205 if (pair->proxyIdA != primaryPair->proxyIdA || pair->proxyIdB != primaryPair->proxyIdB) 0206 { 0207 break; 0208 } 0209 ++i; 0210 } 0211 } 0212 0213 // Try to keep the tree balanced. 0214 m_tree.Rebalance(4); 0215 } 0216 0217 template <typename T> 0218 inline void b2BroadPhase::Query(T* callback, const b2AABB& aabb) const 0219 { 0220 m_tree.Query(callback, aabb); 0221 } 0222 0223 template <typename T> 0224 inline void b2BroadPhase::RayCast(T* callback, const b2RayCastInput& input) const 0225 { 0226 m_tree.RayCast(callback, input); 0227 } 0228 0229 #endif