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 #include <Box2D/Collision/b2DynamicTree.h> 0020 #include <cstring> 0021 #include <cfloat> 0022 using namespace std; 0023 0024 b2DynamicTree::b2DynamicTree() 0025 { 0026 m_root = b2_nullNode; 0027 0028 m_nodeCapacity = 16; 0029 m_nodeCount = 0; 0030 m_nodes = (b2DynamicTreeNode*)b2Alloc(m_nodeCapacity * sizeof(b2DynamicTreeNode)); 0031 memset(static_cast<void*>(m_nodes), 0, m_nodeCapacity * sizeof(b2DynamicTreeNode)); 0032 0033 // Build a linked list for the free list. 0034 for (int32 i = 0; i < m_nodeCapacity - 1; ++i) 0035 { 0036 m_nodes[i].next = i + 1; 0037 } 0038 m_nodes[m_nodeCapacity-1].next = b2_nullNode; 0039 m_freeList = 0; 0040 0041 m_path = 0; 0042 0043 m_insertionCount = 0; 0044 } 0045 0046 b2DynamicTree::~b2DynamicTree() 0047 { 0048 // This frees the entire tree in one shot. 0049 b2Free(m_nodes); 0050 } 0051 0052 // Allocate a node from the pool. Grow the pool if necessary. 0053 int32 b2DynamicTree::AllocateNode() 0054 { 0055 // Expand the node pool as needed. 0056 if (m_freeList == b2_nullNode) 0057 { 0058 b2Assert(m_nodeCount == m_nodeCapacity); 0059 0060 // The free list is empty. Rebuild a bigger pool. 0061 b2DynamicTreeNode* oldNodes = m_nodes; 0062 m_nodeCapacity *= 2; 0063 m_nodes = (b2DynamicTreeNode*)b2Alloc(m_nodeCapacity * sizeof(b2DynamicTreeNode)); 0064 memcpy(m_nodes, oldNodes, m_nodeCount * sizeof(b2DynamicTreeNode)); 0065 b2Free(oldNodes); 0066 0067 // Build a linked list for the free list. The parent 0068 // pointer becomes the "next" pointer. 0069 for (int32 i = m_nodeCount; i < m_nodeCapacity - 1; ++i) 0070 { 0071 m_nodes[i].next = i + 1; 0072 } 0073 m_nodes[m_nodeCapacity-1].next = b2_nullNode; 0074 m_freeList = m_nodeCount; 0075 } 0076 0077 // Peel a node off the free list. 0078 int32 nodeId = m_freeList; 0079 m_freeList = m_nodes[nodeId].next; 0080 m_nodes[nodeId].parent = b2_nullNode; 0081 m_nodes[nodeId].child1 = b2_nullNode; 0082 m_nodes[nodeId].child2 = b2_nullNode; 0083 m_nodes[nodeId].leafCount = 0; 0084 ++m_nodeCount; 0085 return nodeId; 0086 } 0087 0088 // Return a node to the pool. 0089 void b2DynamicTree::FreeNode(int32 nodeId) 0090 { 0091 b2Assert(0 <= nodeId && nodeId < m_nodeCapacity); 0092 b2Assert(0 < m_nodeCount); 0093 m_nodes[nodeId].next = m_freeList; 0094 m_freeList = nodeId; 0095 --m_nodeCount; 0096 } 0097 0098 // Create a proxy in the tree as a leaf node. We return the index 0099 // of the node instead of a pointer so that we can grow 0100 // the node pool. 0101 int32 b2DynamicTree::CreateProxy(const b2AABB& aabb, void* userData) 0102 { 0103 int32 proxyId = AllocateNode(); 0104 0105 // Fatten the aabb. 0106 b2Vec2 r(b2_aabbExtension, b2_aabbExtension); 0107 m_nodes[proxyId].aabb.lowerBound = aabb.lowerBound - r; 0108 m_nodes[proxyId].aabb.upperBound = aabb.upperBound + r; 0109 m_nodes[proxyId].userData = userData; 0110 m_nodes[proxyId].leafCount = 1; 0111 0112 InsertLeaf(proxyId); 0113 0114 return proxyId; 0115 } 0116 0117 void b2DynamicTree::DestroyProxy(int32 proxyId) 0118 { 0119 b2Assert(0 <= proxyId && proxyId < m_nodeCapacity); 0120 b2Assert(m_nodes[proxyId].IsLeaf()); 0121 0122 RemoveLeaf(proxyId); 0123 FreeNode(proxyId); 0124 } 0125 0126 bool b2DynamicTree::MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement) 0127 { 0128 b2Assert(0 <= proxyId && proxyId < m_nodeCapacity); 0129 0130 b2Assert(m_nodes[proxyId].IsLeaf()); 0131 0132 if (m_nodes[proxyId].aabb.Contains(aabb)) 0133 { 0134 return false; 0135 } 0136 0137 RemoveLeaf(proxyId); 0138 0139 // Extend AABB. 0140 b2AABB b = aabb; 0141 b2Vec2 r(b2_aabbExtension, b2_aabbExtension); 0142 b.lowerBound = b.lowerBound - r; 0143 b.upperBound = b.upperBound + r; 0144 0145 // Predict AABB displacement. 0146 b2Vec2 d = b2_aabbMultiplier * displacement; 0147 0148 if (d.x < 0.0f) 0149 { 0150 b.lowerBound.x += d.x; 0151 } 0152 else 0153 { 0154 b.upperBound.x += d.x; 0155 } 0156 0157 if (d.y < 0.0f) 0158 { 0159 b.lowerBound.y += d.y; 0160 } 0161 else 0162 { 0163 b.upperBound.y += d.y; 0164 } 0165 0166 m_nodes[proxyId].aabb = b; 0167 0168 InsertLeaf(proxyId); 0169 return true; 0170 } 0171 0172 void b2DynamicTree::InsertLeaf(int32 leaf) 0173 { 0174 ++m_insertionCount; 0175 0176 if (m_root == b2_nullNode) 0177 { 0178 m_root = leaf; 0179 m_nodes[m_root].parent = b2_nullNode; 0180 return; 0181 } 0182 0183 // Find the best sibling for this node 0184 b2AABB leafAABB = m_nodes[leaf].aabb; 0185 int32 sibling = m_root; 0186 while (m_nodes[sibling].IsLeaf() == false) 0187 { 0188 int32 child1 = m_nodes[sibling].child1; 0189 int32 child2 = m_nodes[sibling].child2; 0190 0191 // Expand the node's AABB. 0192 m_nodes[sibling].aabb.Combine(leafAABB); 0193 m_nodes[sibling].leafCount += 1; 0194 0195 qreal siblingArea = m_nodes[sibling].aabb.GetPerimeter(); 0196 b2AABB parentAABB; 0197 parentAABB.Combine(m_nodes[sibling].aabb, leafAABB); 0198 qreal parentArea = parentAABB.GetPerimeter(); 0199 qreal cost1 = 2.0f * parentArea; 0200 0201 qreal inheritanceCost = 2.0f * (parentArea - siblingArea); 0202 0203 qreal cost2; 0204 if (m_nodes[child1].IsLeaf()) 0205 { 0206 b2AABB aabb; 0207 aabb.Combine(leafAABB, m_nodes[child1].aabb); 0208 cost2 = aabb.GetPerimeter() + inheritanceCost; 0209 } 0210 else 0211 { 0212 b2AABB aabb; 0213 aabb.Combine(leafAABB, m_nodes[child1].aabb); 0214 qreal oldArea = m_nodes[child1].aabb.GetPerimeter(); 0215 qreal newArea = aabb.GetPerimeter(); 0216 cost2 = (newArea - oldArea) + inheritanceCost; 0217 } 0218 0219 qreal cost3; 0220 if (m_nodes[child2].IsLeaf()) 0221 { 0222 b2AABB aabb; 0223 aabb.Combine(leafAABB, m_nodes[child2].aabb); 0224 cost3 = aabb.GetPerimeter() + inheritanceCost; 0225 } 0226 else 0227 { 0228 b2AABB aabb; 0229 aabb.Combine(leafAABB, m_nodes[child2].aabb); 0230 qreal oldArea = m_nodes[child2].aabb.GetPerimeter(); 0231 qreal newArea = aabb.GetPerimeter(); 0232 cost3 = newArea - oldArea + inheritanceCost; 0233 } 0234 0235 // Descend according to the minimum cost. 0236 if (cost1 < cost2 && cost1 < cost3) 0237 { 0238 break; 0239 } 0240 0241 // Expand the node's AABB to account for the new leaf. 0242 m_nodes[sibling].aabb.Combine(leafAABB); 0243 0244 // Descend 0245 if (cost2 < cost3) 0246 { 0247 sibling = child1; 0248 } 0249 else 0250 { 0251 sibling = child2; 0252 } 0253 } 0254 0255 // Create a new parent for the siblings. 0256 int32 oldParent = m_nodes[sibling].parent; 0257 int32 newParent = AllocateNode(); 0258 m_nodes[newParent].parent = oldParent; 0259 m_nodes[newParent].userData = NULL; 0260 m_nodes[newParent].aabb.Combine(leafAABB, m_nodes[sibling].aabb); 0261 m_nodes[newParent].leafCount = m_nodes[sibling].leafCount + 1; 0262 0263 if (oldParent != b2_nullNode) 0264 { 0265 // The sibling was not the root. 0266 if (m_nodes[oldParent].child1 == sibling) 0267 { 0268 m_nodes[oldParent].child1 = newParent; 0269 } 0270 else 0271 { 0272 m_nodes[oldParent].child2 = newParent; 0273 } 0274 0275 m_nodes[newParent].child1 = sibling; 0276 m_nodes[newParent].child2 = leaf; 0277 m_nodes[sibling].parent = newParent; 0278 m_nodes[leaf].parent = newParent; 0279 } 0280 else 0281 { 0282 // The sibling was the root. 0283 m_nodes[newParent].child1 = sibling; 0284 m_nodes[newParent].child2 = leaf; 0285 m_nodes[sibling].parent = newParent; 0286 m_nodes[leaf].parent = newParent; 0287 m_root = newParent; 0288 } 0289 } 0290 0291 void b2DynamicTree::RemoveLeaf(int32 leaf) 0292 { 0293 if (leaf == m_root) 0294 { 0295 m_root = b2_nullNode; 0296 return; 0297 } 0298 0299 int32 parent = m_nodes[leaf].parent; 0300 int32 grandParent = m_nodes[parent].parent; 0301 int32 sibling; 0302 if (m_nodes[parent].child1 == leaf) 0303 { 0304 sibling = m_nodes[parent].child2; 0305 } 0306 else 0307 { 0308 sibling = m_nodes[parent].child1; 0309 } 0310 0311 if (grandParent != b2_nullNode) 0312 { 0313 // Destroy parent and connect sibling to grandParent. 0314 if (m_nodes[grandParent].child1 == parent) 0315 { 0316 m_nodes[grandParent].child1 = sibling; 0317 } 0318 else 0319 { 0320 m_nodes[grandParent].child2 = sibling; 0321 } 0322 m_nodes[sibling].parent = grandParent; 0323 FreeNode(parent); 0324 0325 // Adjust ancestor bounds. 0326 parent = grandParent; 0327 while (parent != b2_nullNode) 0328 { 0329 //b2AABB oldAABB = m_nodes[parent].aabb; 0330 m_nodes[parent].aabb.Combine(m_nodes[m_nodes[parent].child1].aabb, m_nodes[m_nodes[parent].child2].aabb); 0331 0332 b2Assert(m_nodes[parent].leafCount > 0); 0333 m_nodes[parent].leafCount -= 1; 0334 0335 parent = m_nodes[parent].parent; 0336 } 0337 } 0338 else 0339 { 0340 m_root = sibling; 0341 m_nodes[sibling].parent = b2_nullNode; 0342 FreeNode(parent); 0343 } 0344 } 0345 0346 void b2DynamicTree::Rebalance(int32 iterations) 0347 { 0348 if (m_root == b2_nullNode) 0349 { 0350 return; 0351 } 0352 0353 // Rebalance the tree by removing and re-inserting leaves. 0354 for (int32 i = 0; i < iterations; ++i) 0355 { 0356 int32 node = m_root; 0357 0358 uint32 bit = 0; 0359 while (m_nodes[node].IsLeaf() == false) 0360 { 0361 int32* children = &m_nodes[node].child1; 0362 0363 // Child selector based on a bit in the path 0364 int32 selector = (m_path >> bit) & 1; 0365 0366 // Select the child nod 0367 node = children[selector]; 0368 0369 // Keep bit between 0 and 31 because m_path has 32 bits 0370 // bit = (bit + 1) % 31 0371 bit = (bit + 1) & 0x1F; 0372 } 0373 ++m_path; 0374 0375 RemoveLeaf(node); 0376 InsertLeaf(node); 0377 } 0378 } 0379 0380 // Compute the height of a sub-tree. 0381 int32 b2DynamicTree::ComputeHeight(int32 nodeId) const 0382 { 0383 if (nodeId == b2_nullNode) 0384 { 0385 return 0; 0386 } 0387 0388 b2Assert(0 <= nodeId && nodeId < m_nodeCapacity); 0389 b2DynamicTreeNode* node = m_nodes + nodeId; 0390 int32 height1 = ComputeHeight(node->child1); 0391 int32 height2 = ComputeHeight(node->child2); 0392 return 1 + b2Max(height1, height2); 0393 } 0394 0395 int32 b2DynamicTree::ComputeHeight() const 0396 { 0397 return ComputeHeight(m_root); 0398 } 0399 0400 int32 b2DynamicTree::CountLeaves(int32 nodeId) const 0401 { 0402 if (nodeId == b2_nullNode) 0403 { 0404 return 0; 0405 } 0406 0407 b2Assert(0 <= nodeId && nodeId < m_nodeCapacity); 0408 b2DynamicTreeNode* node = m_nodes + nodeId; 0409 0410 if (node->IsLeaf()) 0411 { 0412 b2Assert(node->leafCount == 1); 0413 return 1; 0414 } 0415 0416 int32 count1 = CountLeaves(node->child1); 0417 int32 count2 = CountLeaves(node->child2); 0418 int32 count = count1 + count2; 0419 b2Assert(count == node->leafCount); 0420 return count; 0421 } 0422 0423 void b2DynamicTree::Validate() const 0424 { 0425 CountLeaves(m_root); 0426 }