b2_dynamic_tree.cpp
Go to the documentation of this file.
1 // MIT License
2 
3 // Copyright (c) 2019 Erin Catto
4 
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 #include "box2d/b2_dynamic_tree.h"
23 #include <string.h>
24 
26 {
28 
29  m_nodeCapacity = 16;
30  m_nodeCount = 0;
32  memset(m_nodes, 0, m_nodeCapacity * sizeof(b2TreeNode));
33 
34  // Build a linked list for the free list.
35  for (int32 i = 0; i < m_nodeCapacity - 1; ++i)
36  {
37  m_nodes[i].next = i + 1;
38  m_nodes[i].height = -1;
39  }
40  m_nodes[m_nodeCapacity-1].next = b2_nullNode;
41  m_nodes[m_nodeCapacity-1].height = -1;
42  m_freeList = 0;
43 
44  m_insertionCount = 0;
45 }
46 
48 {
49  // This frees the entire tree in one shot.
50  b2Free(m_nodes);
51 }
52 
53 // Allocate a node from the pool. Grow the pool if necessary.
55 {
56  // Expand the node pool as needed.
57  if (m_freeList == b2_nullNode)
58  {
60 
61  // The free list is empty. Rebuild a bigger pool.
62  b2TreeNode* oldNodes = m_nodes;
63  m_nodeCapacity *= 2;
65  memcpy(m_nodes, oldNodes, m_nodeCount * sizeof(b2TreeNode));
66  b2Free(oldNodes);
67 
68  // Build a linked list for the free list. The parent
69  // pointer becomes the "next" pointer.
70  for (int32 i = m_nodeCount; i < m_nodeCapacity - 1; ++i)
71  {
72  m_nodes[i].next = i + 1;
73  m_nodes[i].height = -1;
74  }
75  m_nodes[m_nodeCapacity-1].next = b2_nullNode;
76  m_nodes[m_nodeCapacity-1].height = -1;
78  }
79 
80  // Peel a node off the free list.
81  int32 nodeId = m_freeList;
82  m_freeList = m_nodes[nodeId].next;
83  m_nodes[nodeId].parent = b2_nullNode;
84  m_nodes[nodeId].child1 = b2_nullNode;
85  m_nodes[nodeId].child2 = b2_nullNode;
86  m_nodes[nodeId].height = 0;
87  m_nodes[nodeId].userData = nullptr;
88  m_nodes[nodeId].moved = false;
89  ++m_nodeCount;
90  return nodeId;
91 }
92 
93 // Return a node to the pool.
95 {
96  b2Assert(0 <= nodeId && nodeId < m_nodeCapacity);
97  b2Assert(0 < m_nodeCount);
98  m_nodes[nodeId].next = m_freeList;
99  m_nodes[nodeId].height = -1;
100  m_freeList = nodeId;
101  --m_nodeCount;
102 }
103 
104 // Create a proxy in the tree as a leaf node. We return the index
105 // of the node instead of a pointer so that we can grow
106 // the node pool.
107 int32 b2DynamicTree::CreateProxy(const b2AABB& aabb, void* userData)
108 {
109  int32 proxyId = AllocateNode();
110 
111  // Fatten the aabb.
113  m_nodes[proxyId].aabb.lowerBound = aabb.lowerBound - r;
114  m_nodes[proxyId].aabb.upperBound = aabb.upperBound + r;
115  m_nodes[proxyId].userData = userData;
116  m_nodes[proxyId].height = 0;
117  m_nodes[proxyId].moved = true;
118 
119  InsertLeaf(proxyId);
120 
121  return proxyId;
122 }
123 
125 {
126  b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
127  b2Assert(m_nodes[proxyId].IsLeaf());
128 
129  RemoveLeaf(proxyId);
130  FreeNode(proxyId);
131 }
132 
133 bool b2DynamicTree::MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement)
134 {
135  b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
136 
137  b2Assert(m_nodes[proxyId].IsLeaf());
138 
139  // Extend AABB
140  b2AABB fatAABB;
142  fatAABB.lowerBound = aabb.lowerBound - r;
143  fatAABB.upperBound = aabb.upperBound + r;
144 
145  // Predict AABB movement
146  b2Vec2 d = b2_aabbMultiplier * displacement;
147 
148  if (d.x < 0.0f)
149  {
150  fatAABB.lowerBound.x += d.x;
151  }
152  else
153  {
154  fatAABB.upperBound.x += d.x;
155  }
156 
157  if (d.y < 0.0f)
158  {
159  fatAABB.lowerBound.y += d.y;
160  }
161  else
162  {
163  fatAABB.upperBound.y += d.y;
164  }
165 
166  const b2AABB& treeAABB = m_nodes[proxyId].aabb;
167  if (treeAABB.Contains(aabb))
168  {
169  // The tree AABB still contains the object, but it might be too large.
170  // Perhaps the object was moving fast but has since gone to sleep.
171  // The huge AABB is larger than the new fat AABB.
172  b2AABB hugeAABB;
173  hugeAABB.lowerBound = fatAABB.lowerBound - 4.0f * r;
174  hugeAABB.upperBound = fatAABB.upperBound + 4.0f * r;
175 
176  if (hugeAABB.Contains(treeAABB))
177  {
178  // The tree AABB contains the object AABB and the tree AABB is
179  // not too large. No tree update needed.
180  return false;
181  }
182 
183  // Otherwise the tree AABB is huge and needs to be shrunk
184  }
185 
186  RemoveLeaf(proxyId);
187 
188  m_nodes[proxyId].aabb = fatAABB;
189 
190  InsertLeaf(proxyId);
191 
192  m_nodes[proxyId].moved = true;
193 
194  return true;
195 }
196 
198 {
200 
201  if (m_root == b2_nullNode)
202  {
203  m_root = leaf;
205  return;
206  }
207 
208  // Find the best sibling for this node
209  b2AABB leafAABB = m_nodes[leaf].aabb;
210  int32 index = m_root;
211  while (m_nodes[index].IsLeaf() == false)
212  {
213  int32 child1 = m_nodes[index].child1;
214  int32 child2 = m_nodes[index].child2;
215 
216  float area = m_nodes[index].aabb.GetPerimeter();
217 
218  b2AABB combinedAABB;
219  combinedAABB.Combine(m_nodes[index].aabb, leafAABB);
220  float combinedArea = combinedAABB.GetPerimeter();
221 
222  // Cost of creating a new parent for this node and the new leaf
223  float cost = 2.0f * combinedArea;
224 
225  // Minimum cost of pushing the leaf further down the tree
226  float inheritanceCost = 2.0f * (combinedArea - area);
227 
228  // Cost of descending into child1
229  float cost1;
230  if (m_nodes[child1].IsLeaf())
231  {
232  b2AABB aabb;
233  aabb.Combine(leafAABB, m_nodes[child1].aabb);
234  cost1 = aabb.GetPerimeter() + inheritanceCost;
235  }
236  else
237  {
238  b2AABB aabb;
239  aabb.Combine(leafAABB, m_nodes[child1].aabb);
240  float oldArea = m_nodes[child1].aabb.GetPerimeter();
241  float newArea = aabb.GetPerimeter();
242  cost1 = (newArea - oldArea) + inheritanceCost;
243  }
244 
245  // Cost of descending into child2
246  float cost2;
247  if (m_nodes[child2].IsLeaf())
248  {
249  b2AABB aabb;
250  aabb.Combine(leafAABB, m_nodes[child2].aabb);
251  cost2 = aabb.GetPerimeter() + inheritanceCost;
252  }
253  else
254  {
255  b2AABB aabb;
256  aabb.Combine(leafAABB, m_nodes[child2].aabb);
257  float oldArea = m_nodes[child2].aabb.GetPerimeter();
258  float newArea = aabb.GetPerimeter();
259  cost2 = newArea - oldArea + inheritanceCost;
260  }
261 
262  // Descend according to the minimum cost.
263  if (cost < cost1 && cost < cost2)
264  {
265  break;
266  }
267 
268  // Descend
269  if (cost1 < cost2)
270  {
271  index = child1;
272  }
273  else
274  {
275  index = child2;
276  }
277  }
278 
279  int32 sibling = index;
280 
281  // Create a new parent.
282  int32 oldParent = m_nodes[sibling].parent;
283  int32 newParent = AllocateNode();
284  m_nodes[newParent].parent = oldParent;
285  m_nodes[newParent].userData = nullptr;
286  m_nodes[newParent].aabb.Combine(leafAABB, m_nodes[sibling].aabb);
287  m_nodes[newParent].height = m_nodes[sibling].height + 1;
288 
289  if (oldParent != b2_nullNode)
290  {
291  // The sibling was not the root.
292  if (m_nodes[oldParent].child1 == sibling)
293  {
294  m_nodes[oldParent].child1 = newParent;
295  }
296  else
297  {
298  m_nodes[oldParent].child2 = newParent;
299  }
300 
301  m_nodes[newParent].child1 = sibling;
302  m_nodes[newParent].child2 = leaf;
303  m_nodes[sibling].parent = newParent;
304  m_nodes[leaf].parent = newParent;
305  }
306  else
307  {
308  // The sibling was the root.
309  m_nodes[newParent].child1 = sibling;
310  m_nodes[newParent].child2 = leaf;
311  m_nodes[sibling].parent = newParent;
312  m_nodes[leaf].parent = newParent;
313  m_root = newParent;
314  }
315 
316  // Walk back up the tree fixing heights and AABBs
317  index = m_nodes[leaf].parent;
318  while (index != b2_nullNode)
319  {
320  index = Balance(index);
321 
322  int32 child1 = m_nodes[index].child1;
323  int32 child2 = m_nodes[index].child2;
324 
325  b2Assert(child1 != b2_nullNode);
326  b2Assert(child2 != b2_nullNode);
327 
328  m_nodes[index].height = 1 + b2Max(m_nodes[child1].height, m_nodes[child2].height);
329  m_nodes[index].aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb);
330 
331  index = m_nodes[index].parent;
332  }
333 
334  //Validate();
335 }
336 
338 {
339  if (leaf == m_root)
340  {
342  return;
343  }
344 
345  int32 parent = m_nodes[leaf].parent;
346  int32 grandParent = m_nodes[parent].parent;
347  int32 sibling;
348  if (m_nodes[parent].child1 == leaf)
349  {
350  sibling = m_nodes[parent].child2;
351  }
352  else
353  {
354  sibling = m_nodes[parent].child1;
355  }
356 
357  if (grandParent != b2_nullNode)
358  {
359  // Destroy parent and connect sibling to grandParent.
360  if (m_nodes[grandParent].child1 == parent)
361  {
362  m_nodes[grandParent].child1 = sibling;
363  }
364  else
365  {
366  m_nodes[grandParent].child2 = sibling;
367  }
368  m_nodes[sibling].parent = grandParent;
369  FreeNode(parent);
370 
371  // Adjust ancestor bounds.
372  int32 index = grandParent;
373  while (index != b2_nullNode)
374  {
375  index = Balance(index);
376 
377  int32 child1 = m_nodes[index].child1;
378  int32 child2 = m_nodes[index].child2;
379 
380  m_nodes[index].aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb);
381  m_nodes[index].height = 1 + b2Max(m_nodes[child1].height, m_nodes[child2].height);
382 
383  index = m_nodes[index].parent;
384  }
385  }
386  else
387  {
388  m_root = sibling;
389  m_nodes[sibling].parent = b2_nullNode;
390  FreeNode(parent);
391  }
392 
393  //Validate();
394 }
395 
396 // Perform a left or right rotation if node A is imbalanced.
397 // Returns the new root index.
399 {
400  b2Assert(iA != b2_nullNode);
401 
402  b2TreeNode* A = m_nodes + iA;
403  if (A->IsLeaf() || A->height < 2)
404  {
405  return iA;
406  }
407 
408  int32 iB = A->child1;
409  int32 iC = A->child2;
410  b2Assert(0 <= iB && iB < m_nodeCapacity);
411  b2Assert(0 <= iC && iC < m_nodeCapacity);
412 
413  b2TreeNode* B = m_nodes + iB;
414  b2TreeNode* C = m_nodes + iC;
415 
416  int32 balance = C->height - B->height;
417 
418  // Rotate C up
419  if (balance > 1)
420  {
421  int32 iF = C->child1;
422  int32 iG = C->child2;
423  b2TreeNode* F = m_nodes + iF;
424  b2TreeNode* G = m_nodes + iG;
425  b2Assert(0 <= iF && iF < m_nodeCapacity);
426  b2Assert(0 <= iG && iG < m_nodeCapacity);
427 
428  // Swap A and C
429  C->child1 = iA;
430  C->parent = A->parent;
431  A->parent = iC;
432 
433  // A's old parent should point to C
434  if (C->parent != b2_nullNode)
435  {
436  if (m_nodes[C->parent].child1 == iA)
437  {
438  m_nodes[C->parent].child1 = iC;
439  }
440  else
441  {
442  b2Assert(m_nodes[C->parent].child2 == iA);
443  m_nodes[C->parent].child2 = iC;
444  }
445  }
446  else
447  {
448  m_root = iC;
449  }
450 
451  // Rotate
452  if (F->height > G->height)
453  {
454  C->child2 = iF;
455  A->child2 = iG;
456  G->parent = iA;
457  A->aabb.Combine(B->aabb, G->aabb);
458  C->aabb.Combine(A->aabb, F->aabb);
459 
460  A->height = 1 + b2Max(B->height, G->height);
461  C->height = 1 + b2Max(A->height, F->height);
462  }
463  else
464  {
465  C->child2 = iG;
466  A->child2 = iF;
467  F->parent = iA;
468  A->aabb.Combine(B->aabb, F->aabb);
469  C->aabb.Combine(A->aabb, G->aabb);
470 
471  A->height = 1 + b2Max(B->height, F->height);
472  C->height = 1 + b2Max(A->height, G->height);
473  }
474 
475  return iC;
476  }
477 
478  // Rotate B up
479  if (balance < -1)
480  {
481  int32 iD = B->child1;
482  int32 iE = B->child2;
483  b2TreeNode* D = m_nodes + iD;
484  b2TreeNode* E = m_nodes + iE;
485  b2Assert(0 <= iD && iD < m_nodeCapacity);
486  b2Assert(0 <= iE && iE < m_nodeCapacity);
487 
488  // Swap A and B
489  B->child1 = iA;
490  B->parent = A->parent;
491  A->parent = iB;
492 
493  // A's old parent should point to B
494  if (B->parent != b2_nullNode)
495  {
496  if (m_nodes[B->parent].child1 == iA)
497  {
498  m_nodes[B->parent].child1 = iB;
499  }
500  else
501  {
502  b2Assert(m_nodes[B->parent].child2 == iA);
503  m_nodes[B->parent].child2 = iB;
504  }
505  }
506  else
507  {
508  m_root = iB;
509  }
510 
511  // Rotate
512  if (D->height > E->height)
513  {
514  B->child2 = iD;
515  A->child1 = iE;
516  E->parent = iA;
517  A->aabb.Combine(C->aabb, E->aabb);
518  B->aabb.Combine(A->aabb, D->aabb);
519 
520  A->height = 1 + b2Max(C->height, E->height);
521  B->height = 1 + b2Max(A->height, D->height);
522  }
523  else
524  {
525  B->child2 = iE;
526  A->child1 = iD;
527  D->parent = iA;
528  A->aabb.Combine(C->aabb, D->aabb);
529  B->aabb.Combine(A->aabb, E->aabb);
530 
531  A->height = 1 + b2Max(C->height, D->height);
532  B->height = 1 + b2Max(A->height, E->height);
533  }
534 
535  return iB;
536  }
537 
538  return iA;
539 }
540 
542 {
543  if (m_root == b2_nullNode)
544  {
545  return 0;
546  }
547 
548  return m_nodes[m_root].height;
549 }
550 
551 //
553 {
554  if (m_root == b2_nullNode)
555  {
556  return 0.0f;
557  }
558 
559  const b2TreeNode* root = m_nodes + m_root;
560  float rootArea = root->aabb.GetPerimeter();
561 
562  float totalArea = 0.0f;
563  for (int32 i = 0; i < m_nodeCapacity; ++i)
564  {
565  const b2TreeNode* node = m_nodes + i;
566  if (node->height < 0)
567  {
568  // Free node in pool
569  continue;
570  }
571 
572  totalArea += node->aabb.GetPerimeter();
573  }
574 
575  return totalArea / rootArea;
576 }
577 
578 // Compute the height of a sub-tree.
580 {
581  b2Assert(0 <= nodeId && nodeId < m_nodeCapacity);
582  b2TreeNode* node = m_nodes + nodeId;
583 
584  if (node->IsLeaf())
585  {
586  return 0;
587  }
588 
589  int32 height1 = ComputeHeight(node->child1);
590  int32 height2 = ComputeHeight(node->child2);
591  return 1 + b2Max(height1, height2);
592 }
593 
595 {
596  int32 height = ComputeHeight(m_root);
597  return height;
598 }
599 
601 {
602  if (index == b2_nullNode)
603  {
604  return;
605  }
606 
607  if (index == m_root)
608  {
609  b2Assert(m_nodes[index].parent == b2_nullNode);
610  }
611 
612  const b2TreeNode* node = m_nodes + index;
613 
614  int32 child1 = node->child1;
615  int32 child2 = node->child2;
616 
617  if (node->IsLeaf())
618  {
619  b2Assert(child1 == b2_nullNode);
620  b2Assert(child2 == b2_nullNode);
621  b2Assert(node->height == 0);
622  return;
623  }
624 
625  b2Assert(0 <= child1 && child1 < m_nodeCapacity);
626  b2Assert(0 <= child2 && child2 < m_nodeCapacity);
627 
628  b2Assert(m_nodes[child1].parent == index);
629  b2Assert(m_nodes[child2].parent == index);
630 
631  ValidateStructure(child1);
632  ValidateStructure(child2);
633 }
634 
636 {
637  if (index == b2_nullNode)
638  {
639  return;
640  }
641 
642  const b2TreeNode* node = m_nodes + index;
643 
644  int32 child1 = node->child1;
645  int32 child2 = node->child2;
646 
647  if (node->IsLeaf())
648  {
649  b2Assert(child1 == b2_nullNode);
650  b2Assert(child2 == b2_nullNode);
651  b2Assert(node->height == 0);
652  return;
653  }
654 
655  b2Assert(0 <= child1 && child1 < m_nodeCapacity);
656  b2Assert(0 <= child2 && child2 < m_nodeCapacity);
657 
658  int32 height1 = m_nodes[child1].height;
659  int32 height2 = m_nodes[child2].height;
660  int32 height;
661  height = 1 + b2Max(height1, height2);
662  b2Assert(node->height == height);
663 
664  b2AABB aabb;
665  aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb);
666 
667  b2Assert(aabb.lowerBound == node->aabb.lowerBound);
668  b2Assert(aabb.upperBound == node->aabb.upperBound);
669 
670  ValidateMetrics(child1);
671  ValidateMetrics(child2);
672 }
673 
675 {
676 #if defined(b2DEBUG)
679 
680  int32 freeCount = 0;
681  int32 freeIndex = m_freeList;
682  while (freeIndex != b2_nullNode)
683  {
684  b2Assert(0 <= freeIndex && freeIndex < m_nodeCapacity);
685  freeIndex = m_nodes[freeIndex].next;
686  ++freeCount;
687  }
688 
690 
691  b2Assert(m_nodeCount + freeCount == m_nodeCapacity);
692 #endif
693 }
694 
696 {
697  int32 maxBalance = 0;
698  for (int32 i = 0; i < m_nodeCapacity; ++i)
699  {
700  const b2TreeNode* node = m_nodes + i;
701  if (node->height <= 1)
702  {
703  continue;
704  }
705 
706  b2Assert(node->IsLeaf() == false);
707 
708  int32 child1 = node->child1;
709  int32 child2 = node->child2;
710  int32 balance = b2Abs(m_nodes[child2].height - m_nodes[child1].height);
711  maxBalance = b2Max(maxBalance, balance);
712  }
713 
714  return maxBalance;
715 }
716 
718 {
719  int32* nodes = (int32*)b2Alloc(m_nodeCount * sizeof(int32));
720  int32 count = 0;
721 
722  // Build array of leaves. Free the rest.
723  for (int32 i = 0; i < m_nodeCapacity; ++i)
724  {
725  if (m_nodes[i].height < 0)
726  {
727  // free node in pool
728  continue;
729  }
730 
731  if (m_nodes[i].IsLeaf())
732  {
734  nodes[count] = i;
735  ++count;
736  }
737  else
738  {
739  FreeNode(i);
740  }
741  }
742 
743  while (count > 1)
744  {
745  float minCost = b2_maxFloat;
746  int32 iMin = -1, jMin = -1;
747  for (int32 i = 0; i < count; ++i)
748  {
749  b2AABB aabbi = m_nodes[nodes[i]].aabb;
750 
751  for (int32 j = i + 1; j < count; ++j)
752  {
753  b2AABB aabbj = m_nodes[nodes[j]].aabb;
754  b2AABB b;
755  b.Combine(aabbi, aabbj);
756  float cost = b.GetPerimeter();
757  if (cost < minCost)
758  {
759  iMin = i;
760  jMin = j;
761  minCost = cost;
762  }
763  }
764  }
765 
766  int32 index1 = nodes[iMin];
767  int32 index2 = nodes[jMin];
768  b2TreeNode* child1 = m_nodes + index1;
769  b2TreeNode* child2 = m_nodes + index2;
770 
771  int32 parentIndex = AllocateNode();
772  b2TreeNode* parent = m_nodes + parentIndex;
773  parent->child1 = index1;
774  parent->child2 = index2;
775  parent->height = 1 + b2Max(child1->height, child2->height);
776  parent->aabb.Combine(child1->aabb, child2->aabb);
777  parent->parent = b2_nullNode;
778 
779  child1->parent = parentIndex;
780  child2->parent = parentIndex;
781 
782  nodes[jMin] = nodes[count-1];
783  nodes[iMin] = parentIndex;
784  --count;
785  }
786 
787  m_root = nodes[0];
788  b2Free(nodes);
789 
790  Validate();
791 }
792 
793 void b2DynamicTree::ShiftOrigin(const b2Vec2& newOrigin)
794 {
795  // Build array of leaves. Free the rest.
796  for (int32 i = 0; i < m_nodeCapacity; ++i)
797  {
798  m_nodes[i].aabb.lowerBound -= newOrigin;
799  m_nodes[i].aabb.upperBound -= newOrigin;
800  }
801 }
d
#define b2_aabbExtension
Definition: b2_common.h:56
void * b2Alloc(int32 size)
Implement this function to use your own memory allocator.
Definition: b2_settings.h:100
~b2DynamicTree()
Destroy the tree, freeing the node pool.
void Combine(const b2AABB &aabb)
Combine an AABB into this one.
Definition: b2_collision.h:194
bool MoveProxy(int32 proxyId, const b2AABB &aabb1, const b2Vec2 &displacement)
b2Vec2 lowerBound
the lower vertex
Definition: b2_collision.h:220
void Validate() const
Validate this tree. For testing.
b2AABB aabb
Enlarged AABB.
void ValidateMetrics(int32 index) const
float x
Definition: b2_math.h:128
float y
Definition: b2_math.h:128
bool Contains(const b2AABB &aabb) const
Does this aabb contain the provided AABB.
Definition: b2_collision.h:208
void RemoveLeaf(int32 node)
int32 GetHeight() const
int32 Balance(int32 index)
void ValidateStructure(int32 index) const
A 2D column vector.
Definition: b2_math.h:41
b2TreeNode * m_nodes
signed int int32
Definition: b2_types.h:28
int32 ComputeHeight() const
void DestroyProxy(int32 proxyId)
Destroy a proxy. This asserts if the id is invalid.
void FreeNode(int32 node)
void InsertLeaf(int32 node)
void RebuildBottomUp()
Build an optimal tree. Very expensive. For testing.
T b2Max(T a, T b)
Definition: b2_math.h:637
bool IsLeaf() const
void ShiftOrigin(const b2Vec2 &newOrigin)
int32 CreateProxy(const b2AABB &aabb, void *userData)
Create a proxy. Provide a tight fitting AABB and a userData pointer.
void * userData
b2DynamicTree()
Constructing the tree initializes the node pool.
float GetAreaRatio() const
Get the ratio of the sum of the node areas to the root area.
A node in the dynamic tree. The client does not interact with this directly.
An axis aligned bounding box.
Definition: b2_collision.h:168
void b2Free(void *mem)
If you implement b2Alloc, you should also implement this function.
Definition: b2_settings.h:106
float GetPerimeter() const
Get the perimeter length.
Definition: b2_collision.h:186
#define b2_aabbMultiplier
Definition: b2_common.h:61
T b2Abs(T a)
Definition: b2_math.h:610
#define b2_maxFloat
Definition: b2_common.h:39
int32 GetMaxBalance() const
#define b2_nullNode
#define b2Assert(A)
Definition: b2_common.h:37
b2Vec2 upperBound
the upper vertex
Definition: b2_collision.h:221


mvsim
Author(s):
autogenerated on Tue Jul 4 2023 03:08:19