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