4 @maintainer Morgan McGuire, matrix@graphics3d.com
9 Copyright 2000-2007, Morgan McGuire.
14 #ifndef G3D_AABSPTREE_H
15 #define G3D_AABSPTREE_H
17 #include "VMapTools.h"
19 #include "G3D/platform.h"
20 #include "G3D/Array.h"
21 #include "G3D/Table.h"
22 #include "G3D/Vector3.h"
23 #include "G3D/AABox.h"
24 #include "G3D/Sphere.h"
26 #include "G3D/Triangle.h"
28 #include "G3D/GCamera.h"
30 #include "G3D/BinaryInput.h"
31 #include "G3D/BinaryOutput.h"
33 #include "G3D/CollisionDetection.h"
34 #include "G3D/GCamera.h"
37 // If defined, in debug mode the tree is checked for consistency
38 // as a way of detecting corruption due to implementation bugs
39 // #define VERIFY_TREE
41 inline void getBounds(const G3D::Vector3
& v
, G3D::AABox
& out
) {
46 inline void getBounds(const G3D::AABox
& a
, G3D::AABox
& out
) {
50 inline void getBounds(const G3D::Sphere
& s
, G3D::AABox
& out
) {
55 inline void getBounds(const G3D::Box
& b
, G3D::AABox
& out
) {
60 inline void getBounds(const G3D::Triangle
& t
, G3D::AABox
& out
) {
66 inline void getBounds(const G3D::Vector3
* v
, G3D::AABox
& out
) {
71 inline void getBounds(const G3D::AABox
* a
, G3D::AABox
& out
) {
75 inline void getBounds(const G3D::Sphere
* s
, G3D::AABox
& out
) {
80 inline void getBounds(const G3D::Box
* b
, G3D::AABox
& out
) {
84 inline void getBounds(const G3D::Triangle
* t
, G3D::AABox
& out
) {
91 Wraps a pointer value so that it can be treated as the instance itself;
92 convenient for inserting pointers into a Table but using the
93 object equality instead of pointer equality.
100 inline Indirector(Type
* h
) : handle(h
) {}
102 inline Indirector() : handle(NULL
) {}
104 /** Returns true iff the values referenced by the handles are equivalent. */
105 inline bool operator==(const Indirector
& m
) {
106 return *handle
== *(m
.handle
);
109 inline bool operator==(const Type
& m
) {
113 inline size_t hashCode() const {
114 return handle
->hashCode();
117 } // namespace internal
120 template <class Handle
>
121 struct GHashCode
<typename
G3D::_internal::Indirector
<Handle
> >
123 size_t operator()(const G3D::_internal::Indirector
<Handle
>& key
) const { return key
.hashCode(); }
129 A set that supports spatial queries using an axis-aligned
132 AABSPTree allows you to quickly find objects in 3D that lie within
133 a box or along a ray. For large sets of objects it is much faster
134 than testing each object for a collision.
136 AABSPTree is as powerful as but more general than a Quad Tree, Oct
137 Tree, or KD Tree, but less general than an unconstrained BSP tree
138 (which is much slower to create).
141 are arranged into an axis-aligned BSP-tree according to their
142 axis-aligned bounds. This increases the cost of insertion to
143 O(log n) but allows fast overlap queries.
145 <B>Template Parameters</B>
146 <DT>The template parameter <I>T</I> must be one for which
147 the following functions are all overloaded:
149 <P><CODE>void ::getBounds(const T&, G3D::AABox&);</CODE>
150 <DT><CODE>bool ::operator==(const T&, const T&);</CODE>
151 <DT><CODE>unsigned int ::hashCode(const T&);</CODE>
152 <DT><CODE>T::T();</CODE> <I>(public constructor of no arguments)</I>
154 G3D provides these for common classes like G3D::Vector3 and G3D::Sphere.
155 If you use a custom class, or a pointer to a custom class, you will need
156 to define those functions.
158 <B>Moving %Set Members</B>
159 <DT>It is important that objects do not move without updating the
160 AABSPTree. If the axis-aligned bounds of an object are about
161 to change, AABSPTree::remove it before they change and
162 AABSPTree::insert it again afterward. For objects
163 where the hashCode and == operator are invariant with respect
165 you can use the AABSPTree::update method as a shortcut to
166 insert/remove an object in one step after it has moved.
169 Note: Do not mutate any value once it has been inserted into AABSPTree. Values
170 are copied interally. All AABSPTree iterators convert to pointers to constant
171 values to reinforce this.
173 If you want to mutate the objects you intend to store in a AABSPTree
174 simply insert <I>pointers</I> to your objects instead of the objects
175 themselves, and ensure that the above operations are defined. (And
176 actually, because values are copied, if your values are large you may
177 want to insert pointers anyway, to save space and make the balance
181 Although designed as a 3D-data structure, you can use the AABSPTree
182 for data distributed along 2 or 1 axes by simply returning bounds
183 that are always zero along one or more dimensions.
186 namespace _AABSPTree
{
188 /** Wrapper for a value that includes a cache of its bounds.
189 Except for the test value used in a set-query operation, there
190 is only ever one instance of the handle associated with any
191 value and the memberTable and Nodes maintain pointers to that
192 heap-allocated value.
194 template<class TValue
>
197 /** The bounds of each object are constrained to AABox::maxFinite */
200 /** Center of bounds. We cache this value to avoid recomputing it
201 during the median sort, and because MSVC 6 std::sort goes into
202 an infinite loop if we compute the midpoint on the fly (possibly
203 a floating point roundoff issue, where B<A and A<B both are true).*/
210 inline Handle
<TValue
>(const TValue
& v
) : value(v
) {
211 getBounds(v
, bounds
);
212 bounds
= bounds
.intersect(AABox::maxFinite());
213 center
= bounds
.center();
216 inline bool operator==(const Handle
<TValue
>& other
) const {
217 return (*value
).operator==(*other
.value
);
220 inline size_t hashCode() const {
221 return value
->hashCode();
226 class Handle
<Triangle
> {
228 /** The bounds of each object are constrained to AABox::maxFinite */
231 /** Center of bounds. We cache this value to avoid recomputing it
232 during the median sort, and because MSVC 6 std::sort goes into
233 an infinite loop if we compute the midpoint on the fly (possibly
234 a floating point roundoff issue, where B<A and A<B both are true).*/
239 Handle
<Triangle
>() {}
241 inline Handle
<Triangle
>(const Triangle
& v
) : value(v
) {
242 getBounds(v
, bounds
);
243 bounds
= bounds
.intersect(AABox::maxFinite());
244 center
= bounds
.center();
247 inline bool operator==(const Handle
<Triangle
>& other
) const {
248 return value
.operator==(other
.value
);
251 inline size_t hashCode() const {
252 return value
.hashCode();
257 template<class T
> class AABSPTree
{
262 /** Returns the bounds of the sub array. Used by makeNode. */
263 static AABox
computeBounds(
264 const Array
<_AABSPTree::Handle
<T
>*>& point
,
268 Vector3 lo
= Vector3::inf();
271 for (int p
= beginIndex
; p
<= endIndex
; ++p
) {
272 lo
= lo
.min(point
[p
]->bounds
.low());
273 hi
= hi
.max(point
[p
]->bounds
.high());
276 return AABox(lo
, hi
);
279 /** Compares centers */
280 class CenterComparator
{
282 Vector3::Axis sortAxis
;
284 CenterComparator(Vector3::Axis a
) : sortAxis(a
) {}
286 inline int operator()(_AABSPTree::Handle
<T
>* A
, const _AABSPTree::Handle
<T
>* B
) const {
287 float a
= A
->center
[sortAxis
];
288 float b
= B
->center
[sortAxis
];
301 /** Compares bounds for strict >, <, or overlap*/
302 class BoundsComparator
{
304 Vector3::Axis sortAxis
;
306 BoundsComparator(Vector3::Axis a
) : sortAxis(a
) {}
308 inline int operator()(_AABSPTree::Handle
<T
>* A
, const _AABSPTree::Handle
<T
>* B
) const {
309 const AABox
& a
= A
->bounds
;
310 const AABox
& b
= B
->bounds
;
312 if (a
.high()[sortAxis
] < b
.low()[sortAxis
]) {
314 } else if (a
.low()[sortAxis
] > b
.high()[sortAxis
]) {
323 /** Compares bounds to the sort location */
326 Vector3::Axis sortAxis
;
329 Comparator(Vector3::Axis a
, float l
) : sortAxis(a
), sortLocation(l
) {}
331 inline int operator()(_AABSPTree::Handle
<T
>* ignore
, const _AABSPTree::Handle
<T
>* handle
) const {
332 const AABox
& box
= handle
->bounds
;
333 debugAssert(ignore
== NULL
);
335 if (box
.high()[sortAxis
] < sortLocation
) {
336 // Box is strictly below the sort location
338 } else if (box
.low()[sortAxis
] > sortLocation
) {
339 // Box is strictly above the sort location
342 // Box overlaps the sort location
348 // Using System::malloc with this class provided no speed improvement.
352 /** Spatial bounds on all values at this node and its children, based purely on
353 the parent's splitting planes. May be infinite. */
356 Vector3::Axis splitAxis
;
358 /** Location along the specified axis */
361 /** child[0] contains all values strictly
362 smaller than splitLocation along splitAxis.
364 child[1] contains all values strictly
367 Both may be NULL if there are not enough
368 values to bother recursing.
372 /** Array of values at this node (i.e., values
373 straddling the split plane + all values if
374 this is a leaf node).
376 This is an array of pointers because that minimizes
377 data movement during tree building, which accounts
378 for about 15% of the time cost of tree building.
380 Array
<_AABSPTree::Handle
<T
> * > valueArray
;
382 /** For each object in the value array, a copy of its bounds.
383 Packing these into an array at the node level
384 instead putting them in the valueArray improves
385 cache coherence, which is about a 3x performance
386 increase when performing intersection computations.
388 Array
<AABox
> boundsArray
;
390 /** Creates node with NULL children */
392 splitAxis
= Vector3::X_AXIS
;
394 splitBounds
= AABox(-Vector3::inf(), Vector3::inf());
395 for (int i
= 0; i
< 2; ++i
) {
401 Doesn't clone children.
403 Node(const Node
& other
) : valueArray(other
.valueArray
), boundsArray(other
.boundsArray
) {
404 splitAxis
= other
.splitAxis
;
405 splitLocation
= other
.splitLocation
;
406 splitBounds
= other
.splitBounds
;
407 for (int i
= 0; i
< 2; ++i
) {
412 /** Copies the specified subarray of pt into point, NULLs the children.
413 Assumes a second pass will set splitBounds. */
414 Node(const Array
<_AABSPTree::Handle
<T
> * >& pt
) : valueArray(pt
) {
415 splitAxis
= Vector3::X_AXIS
;
417 for (int i
= 0; i
< 2; ++i
) {
421 boundsArray
.resize(valueArray
.size());
422 for (int i
= 0; i
< valueArray
.size(); ++i
) {
423 boundsArray
[i
] = valueArray
[i
]->bounds
;
427 /** Deletes the children (but not the values) */
429 for (int i
= 0; i
< 2; ++i
) {
434 /** Returns true if this node is a leaf (no children) */
435 inline bool isLeaf() const {
436 return (child
[0] == NULL
) && (child
[1] == NULL
);
441 Recursively appends all handles and children's handles
444 void getHandles(Array
<_AABSPTree::Handle
<T
> * >& handleArray
) const {
445 handleArray
.append(valueArray
);
446 for (int i
= 0; i
< 2; ++i
) {
447 if (child
[i
] != NULL
) {
448 child
[i
]->getHandles(handleArray
);
453 void verifyNode(const Vector3
& lo
, const Vector3
& hi
) {
454 // debugPrintf("Verifying: split %d @ %f [%f, %f, %f], [%f, %f, %f]\n",
455 // splitAxis, splitLocation, lo.x, lo.y, lo.z, hi.x, hi.y, hi.z);
457 debugAssert(lo
== splitBounds
.low());
458 debugAssert(hi
== splitBounds
.high());
460 for (int i
= 0; i
< valueArray
.length(); ++i
) {
461 const AABox
& b
= valueArray
[i
]->bounds
;
462 debugAssert(b
== boundsArray
[i
]);
464 for(int axis
= 0; axis
< 3; ++axis
) {
465 debugAssert(b
.low()[axis
] <= b
.high()[axis
]);
466 debugAssert(b
.low()[axis
] >= lo
[axis
]);
467 debugAssert(b
.high()[axis
] <= hi
[axis
]);
471 if (child
[0] || child
[1]) {
472 debugAssert(lo
[splitAxis
] < splitLocation
);
473 debugAssert(hi
[splitAxis
] > splitLocation
);
477 newLo
[splitAxis
] = splitLocation
;
479 newHi
[splitAxis
] = splitLocation
;
481 if (child
[0] != NULL
) {
482 child
[0]->verifyNode(lo
, newHi
);
485 if (child
[1] != NULL
) {
486 child
[1]->verifyNode(newLo
, hi
);
492 Stores the locations of the splitting planes (the structure but not the content)
493 so that the tree can be quickly rebuilt from a previous configuration without
496 static void serializeStructure(const Node
* n
, BinaryOutput
& bo
) {
501 n
->splitBounds
.serialize(bo
);
502 serialize(n
->splitAxis
, bo
);
503 bo
.writeFloat32(n
->splitLocation
);
504 for (int c
= 0; c
< 2; ++c
) {
505 serializeStructure(n
->child
[c
], bo
);
510 /** Clears the member table */
511 static Node
* deserializeStructure(BinaryInput
& bi
) {
512 if (bi
.readUInt8() == 0) {
515 Node
* n
= new Node();
516 n
->splitBounds
.deserialize(bi
);
517 deserialize(n
->splitAxis
, bi
);
518 n
->splitLocation
= bi
.readFloat32();
519 for (int c
= 0; c
< 2; ++c
) {
520 n
->child
[c
] = deserializeStructure(bi
);
525 /** Returns the deepest node that completely contains bounds. */
526 Node
* findDeepestContainingNode(const AABox
& bounds
) {
528 // See which side of the splitting plane the bounds are on
529 if (bounds
.high()[splitAxis
] < splitLocation
) {
530 // Bounds are on the low side. Recurse into the child
532 if (child
[0] != NULL
) {
533 return child
[0]->findDeepestContainingNode(bounds
);
535 } else if (bounds
.low()[splitAxis
] > splitLocation
) {
536 // Bounds are on the high side, recurse into the child
538 if (child
[1] != NULL
) {
539 return child
[1]->findDeepestContainingNode(bounds
);
543 // There was no containing child, so this node is the
544 // deepest containing node.
549 /** Appends all members that intersect the box.
550 If useSphere is true, members that pass the box test
551 face a second test against the sphere. */
552 void getIntersectingMembers(
554 const Sphere
& sphere
,
556 bool useSphere
) const {
558 // Test all values at this node
559 for (int v
= 0; v
< boundsArray
.size(); ++v
) {
560 const AABox
& bounds
= boundsArray
[v
];
561 if (bounds
.intersects(box
) &&
562 (! useSphere
|| bounds
.intersects(sphere
))) {
563 members
.append(valueArray
[v
]->value
);
567 // If the left child overlaps the box, recurse into it
568 if ((child
[0] != NULL
) && (box
.low()[splitAxis
] < splitLocation
)) {
569 child
[0]->getIntersectingMembers(box
, sphere
, members
, useSphere
);
572 // If the right child overlaps the box, recurse into it
573 if ((child
[1] != NULL
) && (box
.high()[splitAxis
] > splitLocation
)) {
574 child
[1]->getIntersectingMembers(box
, sphere
, members
, useSphere
);
579 Recurse through the tree, assigning splitBounds fields.
581 void assignSplitBounds(const AABox
& myBounds
) {
582 splitBounds
= myBounds
;
584 AABox childBounds
[2];
585 myBounds
.split(splitAxis
, splitLocation
, childBounds
[0], childBounds
[1]);
587 # if defined(G3D_DEBUG) && defined(VERIFY_TREE)
589 for (int v
= 0; v
< boundsArray
.size(); ++v
) {
590 const AABox
& bounds
= boundsArray
[v
];
591 debugAssert(myBounds
.contains(bounds
));
595 for (int c
= 0; c
< 2; ++c
) {
597 child
[c
]->assignSplitBounds(childBounds
[c
]);
602 /** Returns true if the ray intersects this node */
603 bool intersects(const Ray
& ray
, float distance
) const {
604 // See if the ray will ever hit this node or its children
606 bool alreadyInsideBounds
= false;
607 bool rayWillHitBounds
=
608 VMAP::MyCollisionDetection::collisionLocationForMovingPointFixedAABox(
609 ray
.origin
, ray
.direction
, splitBounds
, location
, alreadyInsideBounds
);
611 bool canHitThisNode
= (alreadyInsideBounds
||
612 (rayWillHitBounds
&& ((location
- ray
.origin
).squaredLength() < square(distance
))));
614 return canHitThisNode
;
617 template<typename RayCallback
>
620 RayCallback
& intersectCallback
,
622 bool pStopAtFirstHit
,
623 bool intersectCallbackIsFast
) const {
624 float enterDistance
= distance
;
626 if (! intersects(ray
, distance
)) {
627 // The ray doesn't hit this node, so it can't hit the children of the node.
631 // Test for intersection against every object at this node.
632 for (int v
= 0; v
< valueArray
.size(); ++v
) {
633 bool canHitThisObject
= true;
635 if (! intersectCallbackIsFast
) {
638 const AABox
& bounds
= boundsArray
[v
];
639 bool alreadyInsideBounds
= false;
640 bool rayWillHitBounds
=
641 VMAP::MyCollisionDetection::collisionLocationForMovingPointFixedAABox(
642 ray
.origin
, ray
.direction
, bounds
, location
, alreadyInsideBounds
);
644 canHitThisObject
= (alreadyInsideBounds
||
645 (rayWillHitBounds
&& ((location
- ray
.origin
).squaredLength() < square(distance
))));
648 if (canHitThisObject
) {
649 // It is possible that this ray hits this object. Look for the intersection using the
651 const T
& value
= valueArray
[v
]->value
;
652 intersectCallback(ray
, value
, pStopAtFirstHit
, distance
);
654 if(pStopAtFirstHit
&& distance
< enterDistance
)
658 // There are three cases to consider next:
660 // 1. the ray can start on one side of the splitting plane and never enter the other,
661 // 2. the ray can start on one side and enter the other, and
662 // 3. the ray can travel exactly down the splitting plane
665 int firstChild
= NONE
;
666 int secondChild
= NONE
;
668 if (ray
.origin
[splitAxis
] < splitLocation
) {
670 // The ray starts on the small side
673 if (ray
.direction
[splitAxis
] > 0) {
674 // The ray will eventually reach the other side
678 } else if (ray
.origin
[splitAxis
] > splitLocation
) {
680 // The ray starts on the large side
683 if (ray
.direction
[splitAxis
] < 0) {
687 // The ray starts on the splitting plane
688 if (ray
.direction
[splitAxis
] < 0) {
689 // ...and goes to the small side
691 } else if (ray
.direction
[splitAxis
] > 0) {
692 // ...and goes to the large side
697 // Test on the side closer to the ray origin.
698 if ((firstChild
!= NONE
) && child
[firstChild
]) {
699 child
[firstChild
]->intersectRay(ray
, intersectCallback
, distance
, pStopAtFirstHit
, intersectCallbackIsFast
);
700 if(pStopAtFirstHit
&& distance
< enterDistance
)
704 if (ray
.direction
[splitAxis
] != 0) {
705 // See if there was an intersection before hitting the splitting plane.
706 // If so, there is no need to look on the far side and recursion terminates.
707 float distanceToSplittingPlane
= (splitLocation
- ray
.origin
[splitAxis
]) / ray
.direction
[splitAxis
];
708 if (distanceToSplittingPlane
> distance
) {
709 // We aren't going to hit anything else before hitting the splitting plane,
710 // so don't bother looking on the far side of the splitting plane at the other
716 // Test on the side farther from the ray origin.
717 if ((secondChild
!= NONE
) && child
[secondChild
]) {
718 child
[secondChild
]->intersectRay(ray
, intersectCallback
, distance
, pStopAtFirstHit
, intersectCallbackIsFast
);
726 Recursively subdivides the subarray.
728 Clears the source array as soon as it is no longer needed.
730 Call assignSplitBounds() on the root node after making a tree.
733 Array
<_AABSPTree::Handle
<T
> * >& source
,
736 Array
<_AABSPTree::Handle
<T
> * >& temp
) {
740 if (source
.size() <= valuesPerNode
) {
741 // Make a new leaf node
742 node
= new Node(source
);
744 // Set the pointers in the memberTable
745 for (int i
= 0; i
< source
.size(); ++i
) {
746 memberTable
.set(Member(source
[i
]), node
);
751 // Make a new internal node
754 const AABox bounds
= computeBounds(source
, 0, source
.size() - 1);
755 const Vector3 extent
= bounds
.high() - bounds
.low();
757 Vector3::Axis splitAxis
= extent
.primaryAxis();
761 // Arrays for holding the children
762 Array
<_AABSPTree::Handle
<T
> * > lt
, gt
;
764 if (numMeanSplits
<= 0) {
766 source
.medianPartition(lt
, node
->valueArray
, gt
, temp
, CenterComparator(splitAxis
));
768 // Choose the split location to be the center of whatever fell in the center
769 splitLocation
= node
->valueArray
[0]->center
[splitAxis
];
771 // Some of the elements in the lt or gt array might really overlap the split location.
772 // Move them as needed.
773 for (int i
= 0; i
< lt
.size(); ++i
) {
774 const AABox
& bounds
= lt
[i
]->bounds
;
775 if ((bounds
.low()[splitAxis
] <= splitLocation
) && (bounds
.high()[splitAxis
] >= splitLocation
)) {
776 node
->valueArray
.append(lt
[i
]);
777 // Remove this element and process the new one that
778 // is swapped in in its place.
779 lt
.fastRemove(i
); --i
;
783 for (int i
= 0; i
< gt
.size(); ++i
) {
784 const AABox
& bounds
= gt
[i
]->bounds
;
785 if ((bounds
.low()[splitAxis
] <= splitLocation
) && (bounds
.high()[splitAxis
] >= splitLocation
)) {
786 node
->valueArray
.append(gt
[i
]);
787 // Remove this element and process the new one that
788 // is swapped in in its place.
789 gt
.fastRemove(i
); --i
;
793 if ((node
->valueArray
.size() > (source
.size() / 2)) &&
794 (source
.size() > 6)) {
795 // This was a bad partition; we ended up putting the splitting plane right in the middle of most of the
796 // objects. We could try to split on a different axis, or use a different partition (e.g., the extents mean,
797 // or geometric mean). This implementation falls back on the extents mean, since that case is already handled
803 // Note: numMeanSplits may have been increased by the code in the previous case above in order to
804 // force a re-partition.
806 if (numMeanSplits
> 0) {
807 // Split along the mean
808 splitLocation
= (bounds
.high()[splitAxis
] +
809 bounds
.low()[splitAxis
]) / 2.0;
811 source
.partition(NULL
, lt
, node
->valueArray
, gt
, Comparator(splitAxis
, splitLocation
));
813 // The Comparator ensures that elements are strictly on the correct side of the split
817 # if defined(G3D_DEBUG) && defined(VERIFY_TREE)
818 debugAssert(lt
.size() + node
->valueArray
.size() + gt
.size() == source
.size());
819 // Verify that all objects ended up on the correct side of the split.
820 // (i.e., make sure that the Array partition was correct)
821 for (int i
= 0; i
< lt
.size(); ++i
) {
822 const AABox
& bounds
= lt
[i
]->bounds
;
823 debugAssert(bounds
.high()[splitAxis
] < splitLocation
);
826 for (int i
= 0; i
< gt
.size(); ++i
) {
827 const AABox
& bounds
= gt
[i
]->bounds
;
828 debugAssert(bounds
.low()[splitAxis
] > splitLocation
);
831 for (int i
= 0; i
< node
->valueArray
.size(); ++i
) {
832 const AABox
& bounds
= node
->valueArray
[i
]->bounds
;
833 debugAssert(bounds
.high()[splitAxis
] >= splitLocation
);
834 debugAssert(bounds
.low()[splitAxis
] <= splitLocation
);
838 // The source array is no longer needed
841 node
->splitAxis
= splitAxis
;
842 node
->splitLocation
= splitLocation
;
844 // Update the bounds array and member table
845 node
->boundsArray
.resize(node
->valueArray
.size());
846 for (int i
= 0; i
< node
->valueArray
.size(); ++i
) {
847 _AABSPTree::Handle
<T
> * v
= node
->valueArray
[i
];
848 node
->boundsArray
[i
] = v
->bounds
;
849 memberTable
.set(Member(v
), node
);
853 node
->child
[0] = makeNode(lt
, valuesPerNode
, numMeanSplits
- 1, temp
);
857 node
->child
[1] = makeNode(gt
, valuesPerNode
, numMeanSplits
- 1, temp
);
866 Recursively clone the passed in node tree, setting
867 pointers for members in the memberTable as appropriate.
868 called by the assignment operator.
870 Node
* cloneTree(Node
* src
) {
871 Node
* dst
= new Node(*src
);
873 // Make back pointers
874 for (int i
= 0; i
< dst
->valueArray
.size(); ++i
) {
875 memberTable
.set(Member(dst
->valueArray
[i
]), dst
);
879 for (int i
= 0; i
< 2; ++i
) {
880 if (src
->child
[i
] != NULL
) {
881 dst
->child
[i
] = cloneTree(src
->child
[i
]);
889 Wrapper for a Handle; used to create a memberTable that acts like Table<Handle, Node*> but
890 stores only Handle* internally to avoid memory copies.
892 typedef _internal::Indirector
<_AABSPTree::Handle
<T
> > Member
;
894 typedef Table
<Member
, Node
*> MemberTable
;
896 /** Maps members to the node containing them */
897 MemberTable memberTable
;
903 /** To construct a balanced tree, insert the elements and then call
904 AABSPTree::balance(). */
905 AABSPTree() : root(NULL
) {}
908 AABSPTree(const AABSPTree
& src
) : root(NULL
) {
913 AABSPTree
& operator=(const AABSPTree
& src
) {
915 // Clone tree takes care of filling out the memberTable.
916 root
= cloneTree(src
.root
);
926 Throws out all elements of the set.
929 typedef typename Table
<_internal::Indirector
<_AABSPTree::Handle
<T
> >, Node
* >::Iterator It
;
931 // Delete all handles stored in the member table
932 It cur
= memberTable
.begin();
933 It end
= memberTable
.end();
935 delete cur
->key
.handle
;
936 cur
->key
.handle
= NULL
;
941 // Delete the tree structure itself
946 size_t size() const {
947 return memberTable
.size();
951 Inserts an object into the set if it is not
952 already present. O(log n) time. Does not
953 cause the tree to be balanced.
955 void insert(const T
& value
) {
956 if (contains(value
)) {
957 // Already in the set
961 _AABSPTree::Handle
<T
>* h
= new _AABSPTree::Handle
<T
>(value
);
964 // This is the first node; create a root node
968 Node
* node
= root
->findDeepestContainingNode(h
->bounds
);
970 // Insert into the node
971 node
->valueArray
.append(h
);
972 node
->boundsArray
.append(h
->bounds
);
974 // Insert into the node table
976 memberTable
.set(m
, node
);
979 /** Inserts each elements in the array in turn. If the tree
980 begins empty (no structure and no elements), this is faster
981 than inserting each element in turn. You still need to balance
982 the tree at the end.*/
983 void insert(const Array
<T
>& valueArray
) {
985 // Optimized case for an empty tree; don't bother
986 // searching or reallocating the root node's valueArray
987 // as we incrementally insert.
989 root
->valueArray
.resize(valueArray
.size());
990 root
->boundsArray
.resize(root
->valueArray
.size());
991 for (int i
= 0; i
< valueArray
.size(); ++i
) {
992 // Insert in opposite order so that we have the exact same
993 // data structure as if we inserted each (i.e., order is reversed
995 _AABSPTree::Handle
<T
>* h
= new _AABSPTree::Handle
<T
>(valueArray
[i
]);
996 int j
= valueArray
.size() - i
- 1;
997 root
->valueArray
[j
] = h
;
998 root
->boundsArray
[j
] = h
->bounds
;
999 memberTable
.set(Member(h
), root
);
1003 // Insert at appropriate tree depth.
1004 for (int i
= 0; i
< valueArray
.size(); ++i
) {
1005 insert(valueArray
[i
]);
1012 Returns true if this object is in the set, otherwise
1013 returns false. O(1) time.
1015 bool contains(const T
& value
) {
1016 // Temporarily create a handle and member
1017 _AABSPTree::Handle
<T
> h(value
);
1018 return memberTable
.containsKey(Member(&h
));
1023 Removes an object from the set in O(1) time.
1024 It is an error to remove members that are not already
1025 present. May unbalance the tree.
1027 Removing an element never causes a node (split plane) to be removed...
1028 nodes are only changed when the tree is rebalanced. This behavior
1029 is desirable because it allows the split planes to be serialized,
1030 and then deserialized into an empty tree which can be repopulated.
1032 void remove(const T
& value
) {
1033 debugAssertM(contains(value
),
1034 "Tried to remove an element from a "
1035 "AABSPTree that was not present");
1037 // Get the list of elements at the node
1038 _AABSPTree::Handle
<T
> h(value
);
1041 Array
<_AABSPTree::Handle
<T
> * >& list
= memberTable
[m
]->valueArray
;
1043 _AABSPTree::Handle
<T
>* ptr
= NULL
;
1045 // Find the element and remove it
1046 for (int i
= list
.length() - 1; i
>= 0; --i
) {
1047 if (list
[i
]->value
== value
) {
1048 // This was the element. Grab the pointer so that
1049 // we can delete it below
1052 // Remove the handle from the node
1055 // Remove the corresponding bounds
1056 memberTable
[m
]->boundsArray
.fastRemove(i
);
1061 // Remove the member
1062 memberTable
.remove(m
);
1064 // Delete the handle data structure
1071 If the element is in the set, it is removed.
1072 The element is then inserted.
1074 This is useful when the == and hashCode methods
1075 on <I>T</I> are independent of the bounds. In
1076 that case, you may call update(v) to insert an
1077 element for the first time and call update(v)
1078 again every time it moves to keep the tree
1081 void update(const T
& value
) {
1082 if (contains(value
)) {
1090 Rebalances the tree (slow). Call when objects
1091 have moved substantially from their original positions
1092 (which unbalances the tree and causes the spatial
1093 queries to be slow).
1095 @param valuesPerNode Maximum number of elements to put at
1098 @param numMeanSplits numMeanSplits = 0 gives a
1099 fully axis aligned BSP-tree, where the balance operation attempts to balance
1100 the tree so that every splitting plane has an equal number of left
1101 and right children (i.e. it is a <B>median</B> split along that axis).
1102 This tends to maximize average performance.
1104 You can override this behavior by
1105 setting a number of <B>mean</B> (average) splits. numMeanSplits = MAX_INT
1106 creates a full oct-tree, which tends to optimize peak performance at the expense of
1107 average performance. It tends to have better clustering behavior when
1108 members are not uniformly distributed.
1110 void balance(int valuesPerNode
= 5, int numMeanSplits
= 3) {
1116 // Get all handles and delete the old tree structure
1117 Node
* oldRoot
= root
;
1118 for (int c
= 0; c
< 2; ++c
) {
1119 if (root
->child
[c
] != NULL
) {
1120 root
->child
[c
]->getHandles(root
->valueArray
);
1122 // Delete the child; this will delete all structure below it
1123 delete root
->child
[c
];
1124 root
->child
[c
] = NULL
;
1128 Array
<_AABSPTree::Handle
<T
> * > temp
;
1129 // Make a new root. Work with a copy of the value array because
1130 // makeNode clears the source array as it progresses
1131 Array
<_AABSPTree::Handle
<T
> * > copy(oldRoot
->valueArray
);
1132 root
= makeNode(copy
, valuesPerNode
, numMeanSplits
, temp
);
1134 // Throw away the old root node
1138 // Walk the tree, assigning splitBounds. We start with unbounded
1139 // space. This will override the current member table.
1140 root
->assignSplitBounds(AABox::maxFinite());
1143 // Ensure that the balanced tree is till correct
1144 root
->verifyNode(Vector3::minFinite(), Vector3::maxFinite());
1151 @param parentMask The mask that this node returned from culledBy.
1153 static void getIntersectingMembers(
1154 const Array
<Plane
>& plane
,
1157 uint32 parentMask
) {
1161 if (parentMask
== 0) {
1162 // None of these planes can cull anything
1163 for (int v
= node
->valueArray
.size() - 1; v
>= 0; --v
) {
1164 members
.append(node
->valueArray
[v
]->value
);
1167 // Iterate through child nodes
1168 for (int c
= 0; c
< 2; ++c
) {
1169 if (node
->child
[c
]) {
1170 getIntersectingMembers(plane
, members
, node
->child
[c
], 0);
1175 // Test values at this node against remaining planes
1176 for (int v
= node
->boundsArray
.size() - 1; v
>= 0; --v
) {
1177 if (! node
->boundsArray
[v
].culledBy(plane
, dummy
, parentMask
)) {
1178 members
.append(node
->valueArray
[v
]->value
);
1182 uint32 childMask
= 0xFFFFFF;
1184 // Iterate through child nodes
1185 for (int c
= 0; c
< 2; ++c
) {
1186 if (node
->child
[c
] &&
1187 ! node
->child
[c
]->splitBounds
.culledBy(plane
, dummy
, parentMask
, childMask
)) {
1188 // This node was not culled
1189 getIntersectingMembers(plane
, members
, node
->child
[c
], childMask
);
1198 Returns all members inside the set of planes.
1199 @param members The results are appended to this array.
1201 void getIntersectingMembers(const Array
<Plane
>& plane
, Array
<T
>& members
) const {
1206 getIntersectingMembers(plane
, members
, root
, 0xFFFFFF);
1210 Typically used to find all visible
1211 objects inside the view frustum (see also GCamera::getClipPlanes)... i.e. all objects
1212 <B>not<B> culled by frustum.
1216 Array<Object*> visible;
1217 tree.getIntersectingMembers(camera.frustum(), visible);
1218 // ... Draw all objects in the visible array.
1220 @param members The results are appended to this array.
1222 void getIntersectingMembers(const GCamera::Frustum
& frustum
, Array
<T
>& members
) const {
1225 for (int i
= 0; i
< frustum
.faceArray
.size(); ++i
) {
1226 plane
.append(frustum
.faceArray
[i
].plane
);
1229 getIntersectingMembers(plane
, members
);
1233 C++ STL style iterator variable. See beginBoxIntersection().
1234 The iterator overloads the -> (dereference) operator, so this
1235 acts like a pointer to the current member.
1237 // This iterator turns Node::getIntersectingMembers into a
1238 // coroutine. It first translates that method from recursive to
1239 // stack based, then captures the system state (analogous to a Scheme
1240 // continuation) after each element is appended to the member array,
1241 // and allowing the computation to be restarted.
1242 class BoxIntersectionIterator
{
1244 friend class AABSPTree
<T
>;
1246 /** True if this is the "end" iterator instance */
1249 /** The box that we're testing against. */
1252 /** Node that we're currently looking at. Undefined if isEnd
1256 /** Nodes waiting to be processed */
1257 // We could use backpointers within the tree and careful
1258 // state management to avoid ever storing the stack-- but
1259 // it is much easier this way and only inefficient if the
1260 // caller uses post increment (which they shouldn't!).
1263 /** The next index of current->valueArray to return.
1264 Undefined when isEnd is true.*/
1265 int nextValueArrayIndex
;
1267 BoxIntersectionIterator() : isEnd(true) {}
1269 BoxIntersectionIterator(const AABox
& b
, const Node
* root
) :
1270 isEnd(root
== NULL
), box(b
),
1271 node(const_cast<Node
*>(root
)), nextValueArrayIndex(-1) {
1273 // We intentionally start at the "-1" index of the current
1274 // node so we can use the preincrement operator to move
1275 // ourselves to element 0 instead of repeating all of the
1276 // code from the preincrement method. Note that this might
1277 // cause us to become the "end" instance.
1283 inline bool operator!=(const BoxIntersectionIterator
& other
) const {
1284 return ! (*this == other
);
1287 bool operator==(const BoxIntersectionIterator
& other
) const {
1290 } else if (other
.isEnd
) {
1293 // Two non-end iterators; see if they match. This is kind of
1294 // silly; users shouldn't call == on iterators in general unless
1295 // one of them is the end iterator.
1296 if ((box
!= other
.box
) || (node
!= other
.node
) ||
1297 (nextValueArrayIndex
!= other
.nextValueArrayIndex
) ||
1298 (stack
.length() != other
.stack
.length())) {
1302 // See if the stacks are the same
1303 for (int i
= 0; i
< stack
.length(); ++i
) {
1304 if (stack
[i
] != other
.stack
[i
]) {
1309 // We failed to find a difference; they must be the same
1317 BoxIntersectionIterator
& operator++() {
1318 ++nextValueArrayIndex
;
1320 bool foundIntersection
= false;
1321 while (! isEnd
&& ! foundIntersection
) {
1323 // Search for the next node if we've exhausted this one
1324 while ((! isEnd
) && (nextValueArrayIndex
>= node
->valueArray
.length())) {
1325 // If we entered this loop, then the iterator has exhausted the elements at
1326 // node (possibly because it just switched to a child node with no members).
1327 // This loop continues until it finds a node with members or reaches
1328 // the end of the whole intersection search.
1330 // If the right child overlaps the box, push it onto the stack for
1332 if ((node
->child
[1] != NULL
) &&
1333 (box
.high()[node
->splitAxis
] > node
->splitLocation
)) {
1334 stack
.push(node
->child
[1]);
1337 // If the left child overlaps the box, push it onto the stack for
1339 if ((node
->child
[0] != NULL
) &&
1340 (box
.low()[node
->splitAxis
] < node
->splitLocation
)) {
1341 stack
.push(node
->child
[0]);
1344 if (stack
.length() > 0) {
1345 // Go on to the next node (which may be either one of the ones we
1346 // just pushed, or one from farther back the tree).
1348 nextValueArrayIndex
= 0;
1350 // That was the last node; we're done iterating
1355 // Search for the next intersection at this node until we run out of children
1356 while (! isEnd
&& ! foundIntersection
&& (nextValueArrayIndex
< node
->valueArray
.length())) {
1357 if (box
.intersects(node
->boundsArray
[nextValueArrayIndex
])) {
1358 foundIntersection
= true;
1360 ++nextValueArrayIndex
;
1361 // If we exhaust this node, we'll loop around the master loop
1362 // to find a new node.
1372 Post increment (much slower than preincrement!). Intentionally overloaded to preclude accidentally slow code.
1374 BoxIntersectionIterator
operator++(int);
1376 BoxIntersectionIterator old = *this;
1383 /** Overloaded dereference operator so the iterator can masquerade as a pointer
1385 const T
& operator*() const {
1386 alwaysAssertM(! isEnd
, "Can't dereference the end element of an iterator");
1387 return node
->valueArray
[nextValueArrayIndex
]->value
;
1390 /** Overloaded dereference operator so the iterator can masquerade as a pointer
1392 T
const * operator->() const {
1393 alwaysAssertM(! isEnd
, "Can't dereference the end element of an iterator");
1394 return &(stack
.last()->valueArray
[nextValueArrayIndex
]->value
);
1397 /** Overloaded cast operator so the iterator can masquerade as a pointer
1399 operator T
*() const {
1400 alwaysAssertM(! isEnd
, "Can't dereference the end element of an iterator");
1401 return &(stack
.last()->valueArray
[nextValueArrayIndex
]->value
);
1407 Iterates through the members that intersect the box
1409 BoxIntersectionIterator
beginBoxIntersection(const AABox
& box
) const {
1410 return BoxIntersectionIterator(box
, root
);
1413 BoxIntersectionIterator
endBoxIntersection() const {
1414 // The "end" iterator instance
1415 return BoxIntersectionIterator();
1419 Appends all members whose bounds intersect the box.
1420 See also AABSPTree::beginBoxIntersection.
1422 void getIntersectingMembers(const AABox
& box
, Array
<T
>& members
) const {
1426 root
->getIntersectingMembers(box
, Sphere(Vector3::zero(), 0), members
, false);
1431 Invoke a callback for every member along a ray until the closest intersection is found.
1433 @param callback either a function or an instance of a class with an overloaded operator() of the form:
1435 <code>void callback(const Ray& ray, const T& object, float& distance)</code>. If the ray hits the object
1436 before travelling distance <code>distance</code>, updates <code>distance</code> with the new distance to
1437 the intersection, otherwise leaves it unmodified. A common example is:
1443 void intersect(const Ray& ray, float& maxDist, Vector3& outLocation, Vector3& outNormal) {
1446 // ... search for intersection distance d
1448 if ((d > 0) && (d < maxDist)) {
1449 // Intersection occured
1457 // Finds the surface normal and location of the first intersection with the scene
1458 class Intersection {
1460 Entity* closestEntity;
1461 Vector3 hitLocation;
1464 void operator()(const Ray& ray, const Entity* entity, float& distance) {
1465 entity->intersect(ray, distance, hitLocation, hitNormal);
1469 AABSPTree<Entity*> scene;
1471 Intersection intersection;
1472 float distance = inf();
1473 scene.intersectRay(camera.worldRay(x, y), intersection, distance);
1477 @param distance When the method is invoked, this is the maximum distance that the tree should search for an intersection.
1478 On return, this is set to the distance to the first intersection encountered.
1480 @param intersectCallbackIsFast If false, each object's bounds are tested before the intersectCallback is invoked.
1481 If the intersect callback runs at the same speed or faster than AABox-ray intersection, set this to true.
1483 template<typename RayCallback
>
1486 RayCallback
& intersectCallback
,
1488 bool pStopAtFirstHit
,
1489 bool intersectCallbackIsFast
= false) const {
1491 root
->intersectRay(ray
, intersectCallback
, distance
, pStopAtFirstHit
, intersectCallbackIsFast
);
1497 @param members The results are appended to this array.
1499 void getIntersectingMembers(const Sphere
& sphere
, Array
<T
>& members
) const {
1505 sphere
.getBounds(box
);
1506 root
->getIntersectingMembers(box
, sphere
, members
, true);
1511 Stores the locations of the splitting planes (the structure but not the content)
1512 so that the tree can be quickly rebuilt from a previous configuration without
1515 void serializeStructure(BinaryOutput
& bo
) const {
1516 Node::serializeStructure(root
, bo
);
1519 /** Clears the member table */
1520 void deserializeStructure(BinaryInput
& bi
) {
1522 root
= Node::deserializeStructure(bi
);
1526 Returns an array of all members of the set. See also AABSPTree::begin.
1528 void getMembers(Array
<T
>& members
) const {
1530 memberTable
.getKeys(temp
);
1531 for (int i
= 0; i
< temp
.size(); ++i
) {
1532 members
.append(temp
[i
].handle
->value
);
1538 C++ STL style iterator variable. See begin().
1539 Overloads the -> (dereference) operator, so this acts like a pointer
1540 to the current member.
1544 friend class AABSPTree
<T
>;
1546 // Note: this is a Table iterator, we are currently defining
1548 typename Table
<Member
, Node
*>::Iterator it
;
1550 Iterator(const typename Table
<Member
, Node
*>::Iterator
& it
) : it(it
) {}
1554 inline bool operator!=(const Iterator
& other
) const {
1555 return !(*this == other
);
1558 bool operator==(const Iterator
& other
) const {
1559 return it
== other
.it
;
1565 Iterator
& operator++() {
1572 Post increment (slower than preincrement). Intentionally unimplemented to prevent slow code.
1574 Iterator
operator++(int);/* {
1575 Iterator old = *this;
1581 const T
& operator*() const {
1582 return it
->key
.handle
->value
;
1585 T
* operator->() const {
1586 return &(it
->key
.handle
->value
);
1589 operator T
*() const {
1590 return &(it
->key
.handle
->value
);
1596 C++ STL style iterator method. Returns the first member.
1597 Use preincrement (++entry) to get to the next element (iteration
1598 order is arbitrary).
1599 Do not modify the set while iterating.
1601 Iterator
begin() const {
1602 return Iterator(memberTable
.begin());
1607 C++ STL style iterator method. Returns one after the last iterator
1610 Iterator
end() const {
1611 return Iterator(memberTable
.end());