File indexing completed on 2025-08-03 03:49:56

0001 /*
0002 * Copyright (c) 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_DYNAMIC_TREE_H
0020 #define B2_DYNAMIC_TREE_H
0021 
0022 #include <Box2D/Collision/b2Collision.h>
0023 #include <Box2D/Common/b2GrowableStack.h>
0024 
0025 /// A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt.
0026 
0027 #define b2_nullNode (-1)
0028 
0029 /// A node in the dynamic tree. The client does not interact with this directly.
0030 struct b2DynamicTreeNode
0031 {
0032     bool IsLeaf() const
0033     {
0034         return child1 == b2_nullNode;
0035     }
0036 
0037     /// This is the fattened AABB.
0038     b2AABB aabb;
0039 
0040     void* userData;
0041 
0042     union
0043     {
0044         int32 parent;
0045         int32 next;
0046     };
0047 
0048     int32 child1;
0049     int32 child2;
0050     int32 leafCount;
0051 };
0052 
0053 /// A dynamic tree arranges data in a binary tree to accelerate
0054 /// queries such as volume queries and ray casts. Leafs are proxies
0055 /// with an AABB. In the tree we expand the proxy AABB by b2_fatAABBFactor
0056 /// so that the proxy AABB is bigger than the client object. This allows the client
0057 /// object to move by small amounts without triggering a tree update.
0058 ///
0059 /// Nodes are pooled and relocatable, so we use node indices rather than pointers.
0060 class b2DynamicTree
0061 {
0062 public:
0063 
0064     /// Constructing the tree initializes the node pool.
0065     b2DynamicTree();
0066 
0067     /// Destroy the tree, freeing the node pool.
0068     ~b2DynamicTree();
0069 
0070     /// Create a proxy. Provide a tight fitting AABB and a userData pointer.
0071     int32 CreateProxy(const b2AABB& aabb, void* userData);
0072 
0073     /// Destroy a proxy. This asserts if the id is invalid.
0074     void DestroyProxy(int32 proxyId);
0075 
0076     /// Move a proxy with a swept AABB. If the proxy has moved outside of its fattened AABB,
0077     /// then the proxy is removed from the tree and re-inserted. Otherwise
0078     /// the function returns immediately.
0079     /// @return true if the proxy was re-inserted.
0080     bool MoveProxy(int32 proxyId, const b2AABB& aabb1, const b2Vec2& displacement);
0081 
0082     /// Perform some iterations to re-balance the tree.
0083     void Rebalance(int32 iterations);
0084 
0085     /// Get proxy user data.
0086     /// @return the proxy user data or 0 if the id is invalid.
0087     void* GetUserData(int32 proxyId) const;
0088 
0089     /// Get the fat AABB for a proxy.
0090     const b2AABB& GetFatAABB(int32 proxyId) const;
0091 
0092     /// Compute the height of the binary tree in O(N) time. Should not be
0093     /// called often.
0094     int32 ComputeHeight() const;
0095 
0096     /// Query an AABB for overlapping proxies. The callback class
0097     /// is called for each proxy that overlaps the supplied AABB.
0098     template <typename T>
0099     void Query(T* callback, const b2AABB& aabb) const;
0100 
0101     /// Ray-cast against the proxies in the tree. This relies on the callback
0102     /// to perform a exact ray-cast in the case were the proxy contains a shape.
0103     /// The callback also performs the any collision filtering. This has performance
0104     /// roughly equal to k * log(n), where k is the number of collisions and n is the
0105     /// number of proxies in the tree.
0106     /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
0107     /// @param callback a callback class that is called for each proxy that is hit by the ray.
0108     template <typename T>
0109     void RayCast(T* callback, const b2RayCastInput& input) const;
0110 
0111     void Validate() const;
0112 
0113 private:
0114 
0115     int32 AllocateNode();
0116     void FreeNode(int32 node);
0117 
0118     void InsertLeaf(int32 node);
0119     void RemoveLeaf(int32 node);
0120 
0121     int32 ComputeHeight(int32 nodeId) const;
0122     
0123     int32 CountLeaves(int32 nodeId) const;
0124 
0125     int32 m_root;
0126 
0127     b2DynamicTreeNode* m_nodes;
0128     int32 m_nodeCount;
0129     int32 m_nodeCapacity;
0130 
0131     int32 m_freeList;
0132 
0133     /// This is used incrementally traverse the tree for re-balancing.
0134     uint32 m_path;
0135 
0136     int32 m_insertionCount;
0137 };
0138 
0139 inline void* b2DynamicTree::GetUserData(int32 proxyId) const
0140 {
0141     b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
0142     return m_nodes[proxyId].userData;
0143 }
0144 
0145 inline const b2AABB& b2DynamicTree::GetFatAABB(int32 proxyId) const
0146 {
0147     b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
0148     return m_nodes[proxyId].aabb;
0149 }
0150 
0151 template <typename T>
0152 inline void b2DynamicTree::Query(T* callback, const b2AABB& aabb) const
0153 {
0154     b2GrowableStack<int32, 256> stack;
0155     stack.Push(m_root);
0156 
0157     while (stack.GetCount() > 0)
0158     {
0159         int32 nodeId = stack.Pop();
0160         if (nodeId == b2_nullNode)
0161         {
0162             continue;
0163         }
0164 
0165         const b2DynamicTreeNode* node = m_nodes + nodeId;
0166 
0167         if (b2TestOverlap(node->aabb, aabb))
0168         {
0169             if (node->IsLeaf())
0170             {
0171                 bool proceed = callback->QueryCallback(nodeId);
0172                 if (proceed == false)
0173                 {
0174                     return;
0175                 }
0176             }
0177             else
0178             {
0179                 stack.Push(node->child1);
0180                 stack.Push(node->child2);
0181             }
0182         }
0183     }
0184 }
0185 
0186 template <typename T>
0187 inline void b2DynamicTree::RayCast(T* callback, const b2RayCastInput& input) const
0188 {
0189     b2Vec2 p1 = input.p1;
0190     b2Vec2 p2 = input.p2;
0191     b2Vec2 r = p2 - p1;
0192     b2Assert(r.LengthSquared() > 0.0f);
0193     r.Normalize();
0194 
0195     // v is perpendicular to the segment.
0196     b2Vec2 v = b2Cross(1.0f, r);
0197     b2Vec2 abs_v = b2Abs(v);
0198 
0199     // Separating axis for segment (Gino, p80).
0200     // |dot(v, p1 - c)| > dot(|v|, h)
0201 
0202     qreal maxFraction = input.maxFraction;
0203 
0204     // Build a bounding box for the segment.
0205     b2AABB segmentAABB;
0206     {
0207         b2Vec2 t = p1 + maxFraction * (p2 - p1);
0208         segmentAABB.lowerBound = b2Min(p1, t);
0209         segmentAABB.upperBound = b2Max(p1, t);
0210     }
0211 
0212     b2GrowableStack<int32, 256> stack;
0213     stack.Push(m_root);
0214 
0215     while (stack.GetCount() > 0)
0216     {
0217         int32 nodeId = stack.Pop();
0218         if (nodeId == b2_nullNode)
0219         {
0220             continue;
0221         }
0222 
0223         const b2DynamicTreeNode* node = m_nodes + nodeId;
0224 
0225         if (b2TestOverlap(node->aabb, segmentAABB) == false)
0226         {
0227             continue;
0228         }
0229 
0230         // Separating axis for segment (Gino, p80).
0231         // |dot(v, p1 - c)| > dot(|v|, h)
0232         b2Vec2 c = node->aabb.GetCenter();
0233         b2Vec2 h = node->aabb.GetExtents();
0234         qreal separation = b2Abs(b2Dot(v, p1 - c)) - b2Dot(abs_v, h);
0235         if (separation > 0.0f)
0236         {
0237             continue;
0238         }
0239 
0240         if (node->IsLeaf())
0241         {
0242             b2RayCastInput subInput;
0243             subInput.p1 = input.p1;
0244             subInput.p2 = input.p2;
0245             subInput.maxFraction = maxFraction;
0246 
0247             qreal value = callback->RayCastCallback(subInput, nodeId);
0248 
0249             if (value == 0.0f)
0250             {
0251                 // The client has terminated the ray cast.
0252                 return;
0253             }
0254 
0255             if (value > 0.0f)
0256             {
0257                 // Update segment bounding box.
0258                 maxFraction = value;
0259                 b2Vec2 t = p1 + maxFraction * (p2 - p1);
0260                 segmentAABB.lowerBound = b2Min(p1, t);
0261                 segmentAABB.upperBound = b2Max(p1, t);
0262             }
0263         }
0264         else
0265         {
0266             stack.Push(node->child1);
0267             stack.Push(node->child2);
0268         }
0269     }
0270 }
0271 
0272 #endif