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