[7272] Trailing whitespace cleaning
[getmangos.git] / src / shared / vmap / AABSPTree.h
blobad615e58c04bc2250a04eb6f9ea4e5a46ed94043
1 /**
2 @file AABSPTree.h
4 @maintainer Morgan McGuire, matrix@graphics3d.com
6 @created 2004-01-11
7 @edited 2007-02-16
9 Copyright 2000-2007, Morgan McGuire.
10 All rights reserved.
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"
25 #include "G3D/Box.h"
26 #include "G3D/Triangle.h"
27 #include "G3D/Ray.h"
28 #include "G3D/GCamera.h"
29 #if 0
30 #include "G3D/BinaryInput.h"
31 #include "G3D/BinaryOutput.h"
32 #endif
33 #include "G3D/CollisionDetection.h"
34 #include "G3D/GCamera.h"
35 #include <algorithm>
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) {
42 out = G3D::AABox(v);
46 inline void getBounds(const G3D::AABox& a, G3D::AABox& out) {
47 out = a;
50 inline void getBounds(const G3D::Sphere& s, G3D::AABox& out) {
51 s.getBounds(out);
55 inline void getBounds(const G3D::Box& b, G3D::AABox& out) {
56 b.getBounds(out);
60 inline void getBounds(const G3D::Triangle& t, G3D::AABox& out) {
61 t.getBounds(out);
66 inline void getBounds(const G3D::Vector3* v, G3D::AABox& out) {
67 out = G3D::AABox(*v);
71 inline void getBounds(const G3D::AABox* a, G3D::AABox& out) {
72 getBounds(*a, out);
75 inline void getBounds(const G3D::Sphere* s, G3D::AABox& out) {
76 s->getBounds(out);
80 inline void getBounds(const G3D::Box* b, G3D::AABox& out) {
81 b->getBounds(out);
84 inline void getBounds(const G3D::Triangle* t, G3D::AABox& out) {
85 t->getBounds(out);
87 namespace G3D {
88 namespace _internal {
90 /**
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.
95 template<class Type>
96 class Indirector {
97 public:
98 Type* handle;
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) {
110 return *handle == m;
113 inline size_t hashCode() const {
114 return handle->hashCode();
117 } // namespace internal
118 } // namespace G3D
120 template <class Handle>
121 struct GHashCode< G3D::_internal::Indirector<Handle> >
123 size_t operator()(const G3D::_internal::Indirector<Handle>& key) const { return key.hashCode(); }
126 namespace G3D {
129 A set that supports spatial queries using an axis-aligned
130 BSP tree for speed.
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).
140 Internally, objects
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
164 to the 3D position,
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
178 operation faster.)
180 <B>Dimensions</B>
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>
195 class Handle {
196 public:
197 /** The bounds of each object are constrained to AABox::maxFinite */
198 AABox bounds;
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).*/
204 Vector3 center;
206 TValue value;
208 Handle<TValue>() {}
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();
225 template<>
226 class Handle<Triangle> {
227 public:
228 /** The bounds of each object are constrained to AABox::maxFinite */
229 AABox bounds;
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).*/
235 Vector3 center;
237 Triangle value;
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 {
258 protected:
259 public:
262 /** Returns the bounds of the sub array. Used by makeNode. */
263 static AABox computeBounds(
264 const Array<_AABSPTree::Handle<T>*>& point,
265 int beginIndex,
266 int endIndex) {
268 Vector3 lo = Vector3::inf();
269 Vector3 hi = -lo;
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 {
281 public:
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];
290 if (a < b) {
291 return 1;
292 } else if (a > b) {
293 return -1;
294 } else {
295 return 0;
301 /** Compares bounds for strict >, <, or overlap*/
302 class BoundsComparator {
303 public:
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]) {
313 return 1;
314 } else if (a.low()[sortAxis] > b.high()[sortAxis]) {
315 return -1;
316 } else {
317 return 0;
323 /** Compares bounds to the sort location */
324 class Comparator {
325 public:
326 Vector3::Axis sortAxis;
327 float sortLocation;
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
337 return -1;
338 } else if (box.low()[sortAxis] > sortLocation) {
339 // Box is strictly above the sort location
340 return 1;
341 } else {
342 // Box overlaps the sort location
343 return 0;
348 // Using System::malloc with this class provided no speed improvement.
349 class Node {
350 public:
352 /** Spatial bounds on all values at this node and its children, based purely on
353 the parent's splitting planes. May be infinite. */
354 AABox splitBounds;
356 Vector3::Axis splitAxis;
358 /** Location along the specified axis */
359 float splitLocation;
361 /** child[0] contains all values strictly
362 smaller than splitLocation along splitAxis.
364 child[1] contains all values strictly
365 larger.
367 Both may be NULL if there are not enough
368 values to bother recursing.
370 Node* child[2];
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 */
391 Node() {
392 splitAxis = Vector3::X_AXIS;
393 splitLocation = 0;
394 splitBounds = AABox(-Vector3::inf(), Vector3::inf());
395 for (int i = 0; i < 2; ++i) {
396 child[i] = NULL;
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) {
408 child[i] = NULL;
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;
416 splitLocation = 0;
417 for (int i = 0; i < 2; ++i) {
418 child[i] = NULL;
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) */
428 ~Node() {
429 for (int i = 0; i < 2; ++i) {
430 delete child[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
442 to the array.
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);
476 Vector3 newLo = lo;
477 newLo[splitAxis] = splitLocation;
478 Vector3 newHi = hi;
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);
490 #if 0
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
494 calling balance.
496 static void serializeStructure(const Node* n, BinaryOutput& bo) {
497 if (n == NULL) {
498 bo.writeUInt8(0);
499 } else {
500 bo.writeUInt8(1);
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) {
513 return NULL;
514 } else {
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);
524 #endif
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
531 // if it exists.
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
537 // if it exists.
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.
545 return this;
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(
553 const AABox& box,
554 const Sphere& sphere,
555 Array<T>& members,
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)
588 // Verify the split
589 for (int v = 0; v < boundsArray.size(); ++v) {
590 const AABox& bounds = boundsArray[v];
591 debugAssert(myBounds.contains(bounds));
593 # endif
595 for (int c = 0; c < 2; ++c) {
596 if (child[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
605 Vector3 location;
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>
618 void intersectRay(
619 const Ray& ray,
620 RayCallback& intersectCallback,
621 float& distance,
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.
628 return;
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) {
636 // See if
637 Vector3 location;
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
650 // callback.
651 const T& value = valueArray[v]->value;
652 intersectCallback(ray, value, pStopAtFirstHit, distance);
654 if(pStopAtFirstHit && distance < enterDistance)
655 return;
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
664 enum {NONE = -1};
665 int firstChild = NONE;
666 int secondChild = NONE;
668 if (ray.origin[splitAxis] < splitLocation) {
670 // The ray starts on the small side
671 firstChild = 0;
673 if (ray.direction[splitAxis] > 0) {
674 // The ray will eventually reach the other side
675 secondChild = 1;
678 } else if (ray.origin[splitAxis] > splitLocation) {
680 // The ray starts on the large side
681 firstChild = 1;
683 if (ray.direction[splitAxis] < 0) {
684 secondChild = 0;
686 } else {
687 // The ray starts on the splitting plane
688 if (ray.direction[splitAxis] < 0) {
689 // ...and goes to the small side
690 firstChild = 0;
691 } else if (ray.direction[splitAxis] > 0) {
692 // ...and goes to the large side
693 firstChild = 1;
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)
701 return;
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
711 // child.
712 return;
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.
732 Node* makeNode(
733 Array<_AABSPTree::Handle<T> * >& source,
734 int valuesPerNode,
735 int numMeanSplits,
736 Array<_AABSPTree::Handle<T> * >& temp) {
738 Node* node = NULL;
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);
748 source.clear();
750 } else {
751 // Make a new internal node
752 node = new 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();
759 float splitLocation;
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)
775 const AABox& lt_bounds = lt[i]->bounds;
776 if ((bounds.low()[splitAxis] <= splitLocation) && (lt_bounds.high()[splitAxis] >= splitLocation))
778 node->valueArray.append(lt[i]);
779 // Remove this element and process the new one that
780 // is swapped in in its place.
781 lt.fastRemove(i); --i;
785 for (int i = 0; i < gt.size(); ++i)
787 const AABox& gt_bounds = gt[i]->bounds;
788 if ((bounds.low()[splitAxis] <= splitLocation) && (gt_bounds.high()[splitAxis] >= splitLocation))
790 node->valueArray.append(gt[i]);
791 // Remove this element and process the new one that
792 // is swapped in in its place.
793 gt.fastRemove(i); --i;
797 if ((node->valueArray.size() > (source.size() / 2)) &&
798 (source.size() > 6)) {
799 // This was a bad partition; we ended up putting the splitting plane right in the middle of most of the
800 // objects. We could try to split on a different axis, or use a different partition (e.g., the extents mean,
801 // or geometric mean). This implementation falls back on the extents mean, since that case is already handled
802 // below.
803 numMeanSplits = 1;
807 // Note: numMeanSplits may have been increased by the code in the previous case above in order to
808 // force a re-partition.
810 if (numMeanSplits > 0) {
811 // Split along the mean
812 splitLocation = (bounds.high()[splitAxis] +
813 bounds.low()[splitAxis]) / 2.0;
815 source.partition(NULL, lt, node->valueArray, gt, Comparator(splitAxis, splitLocation));
817 // The Comparator ensures that elements are strictly on the correct side of the split
821 # if defined(G3D_DEBUG) && defined(VERIFY_TREE)
822 debugAssert(lt.size() + node->valueArray.size() + gt.size() == source.size());
823 // Verify that all objects ended up on the correct side of the split.
824 // (i.e., make sure that the Array partition was correct)
825 for (int i = 0; i < lt.size(); ++i) {
826 const AABox& lt_bounds = lt[i]->bounds;
827 debugAssert(lt_bounds.high()[splitAxis] < splitLocation);
830 for (int i = 0; i < gt.size(); ++i) {
831 const AABox& gt_bounds = gt[i]->bounds;
832 debugAssert(gt_bounds.low()[splitAxis] > splitLocation);
835 for (int i = 0; i < node->valueArray.size(); ++i)
837 const AABox& node_bounds = node->valueArray[i]->bounds;
838 debugAssert(node_bounds.high()[splitAxis] >= splitLocation);
839 debugAssert(node_bounds.low()[splitAxis] <= splitLocation);
841 # endif
843 // The source array is no longer needed
844 source.clear();
846 node->splitAxis = splitAxis;
847 node->splitLocation = splitLocation;
849 // Update the bounds array and member table
850 node->boundsArray.resize(node->valueArray.size());
851 for (int i = 0; i < node->valueArray.size(); ++i) {
852 _AABSPTree::Handle<T> * v = node->valueArray[i];
853 node->boundsArray[i] = v->bounds;
854 memberTable.set(Member(v), node);
857 if (lt.size() > 0) {
858 node->child[0] = makeNode(lt, valuesPerNode, numMeanSplits - 1, temp);
861 if (gt.size() > 0) {
862 node->child[1] = makeNode(gt, valuesPerNode, numMeanSplits - 1, temp);
867 return node;
871 Recursively clone the passed in node tree, setting
872 pointers for members in the memberTable as appropriate.
873 called by the assignment operator.
875 Node* cloneTree(Node* src) {
876 Node* dst = new Node(*src);
878 // Make back pointers
879 for (int i = 0; i < dst->valueArray.size(); ++i) {
880 memberTable.set(Member(dst->valueArray[i]), dst);
883 // Clone children
884 for (int i = 0; i < 2; ++i) {
885 if (src->child[i] != NULL) {
886 dst->child[i] = cloneTree(src->child[i]);
890 return dst;
894 Wrapper for a Handle; used to create a memberTable that acts like Table<Handle, Node*> but
895 stores only Handle* internally to avoid memory copies.
897 typedef _internal::Indirector<_AABSPTree::Handle<T> > Member;
899 typedef Table<Member, Node*> MemberTable;
901 /** Maps members to the node containing them */
902 MemberTable memberTable;
904 Node* root;
906 public:
908 /** To construct a balanced tree, insert the elements and then call
909 AABSPTree::balance(). */
910 AABSPTree() : root(NULL) {}
913 AABSPTree(const AABSPTree& src) : root(NULL) {
914 *this = src;
918 AABSPTree& operator=(const AABSPTree& src) {
919 delete root;
920 // Clone tree takes care of filling out the memberTable.
921 root = cloneTree(src.root);
922 return *this;
926 ~AABSPTree() {
927 clear();
931 Throws out all elements of the set.
933 void clear()
935 typedef typename Table<_internal::Indirector<_AABSPTree::Handle<T> >, Node* >::Iterator It;
937 // Delete all handles stored in the member table
938 It tab_cur = memberTable.begin();
939 It tab_end = memberTable.end();
940 while (tab_cur != tab_end) {
941 delete tab_cur->key.handle;
942 tab_cur->key.handle = NULL;
943 ++tab_cur;
945 memberTable.clear();
947 // Delete the tree structure itself
948 delete root;
949 root = NULL;
952 size_t size() const {
953 return memberTable.size();
957 Inserts an object into the set if it is not
958 already present. O(log n) time. Does not
959 cause the tree to be balanced.
961 void insert(const T& value) {
962 if (contains(value)) {
963 // Already in the set
964 return;
967 _AABSPTree::Handle<T>* h = new _AABSPTree::Handle<T>(value);
969 if (root == NULL) {
970 // This is the first node; create a root node
971 root = new Node();
974 Node* node = root->findDeepestContainingNode(h->bounds);
976 // Insert into the node
977 node->valueArray.append(h);
978 node->boundsArray.append(h->bounds);
980 // Insert into the node table
981 Member m(h);
982 memberTable.set(m, node);
985 /** Inserts each elements in the array in turn. If the tree
986 begins empty (no structure and no elements), this is faster
987 than inserting each element in turn. You still need to balance
988 the tree at the end.*/
989 void insert(const Array<T>& valueArray) {
990 if (root == NULL) {
991 // Optimized case for an empty tree; don't bother
992 // searching or reallocating the root node's valueArray
993 // as we incrementally insert.
994 root = new Node();
995 root->valueArray.resize(valueArray.size());
996 root->boundsArray.resize(root->valueArray.size());
997 for (int i = 0; i < valueArray.size(); ++i) {
998 // Insert in opposite order so that we have the exact same
999 // data structure as if we inserted each (i.e., order is reversed
1000 // from array).
1001 _AABSPTree::Handle<T>* h = new _AABSPTree::Handle<T>(valueArray[i]);
1002 int j = valueArray.size() - i - 1;
1003 root->valueArray[j] = h;
1004 root->boundsArray[j] = h->bounds;
1005 memberTable.set(Member(h), root);
1008 } else {
1009 // Insert at appropriate tree depth.
1010 for (int i = 0; i < valueArray.size(); ++i) {
1011 insert(valueArray[i]);
1018 Returns true if this object is in the set, otherwise
1019 returns false. O(1) time.
1021 bool contains(const T& value) {
1022 // Temporarily create a handle and member
1023 _AABSPTree::Handle<T> h(value);
1024 return memberTable.containsKey(Member(&h));
1029 Removes an object from the set in O(1) time.
1030 It is an error to remove members that are not already
1031 present. May unbalance the tree.
1033 Removing an element never causes a node (split plane) to be removed...
1034 nodes are only changed when the tree is rebalanced. This behavior
1035 is desirable because it allows the split planes to be serialized,
1036 and then deserialized into an empty tree which can be repopulated.
1038 void remove(const T& value) {
1039 debugAssertM(contains(value),
1040 "Tried to remove an element from a "
1041 "AABSPTree that was not present");
1043 // Get the list of elements at the node
1044 _AABSPTree::Handle<T> h(value);
1045 Member m(&h);
1047 Array<_AABSPTree::Handle<T> * >& list = memberTable[m]->valueArray;
1049 _AABSPTree::Handle<T>* ptr = NULL;
1051 // Find the element and remove it
1052 for (int i = list.length() - 1; i >= 0; --i) {
1053 if (list[i]->value == value) {
1054 // This was the element. Grab the pointer so that
1055 // we can delete it below
1056 ptr = list[i];
1058 // Remove the handle from the node
1059 list.fastRemove(i);
1061 // Remove the corresponding bounds
1062 memberTable[m]->boundsArray.fastRemove(i);
1063 break;
1067 // Remove the member
1068 memberTable.remove(m);
1070 // Delete the handle data structure
1071 delete ptr;
1072 ptr = NULL;
1077 If the element is in the set, it is removed.
1078 The element is then inserted.
1080 This is useful when the == and hashCode methods
1081 on <I>T</I> are independent of the bounds. In
1082 that case, you may call update(v) to insert an
1083 element for the first time and call update(v)
1084 again every time it moves to keep the tree
1085 up to date.
1087 void update(const T& value) {
1088 if (contains(value)) {
1089 remove(value);
1091 insert(value);
1096 Rebalances the tree (slow). Call when objects
1097 have moved substantially from their original positions
1098 (which unbalances the tree and causes the spatial
1099 queries to be slow).
1101 @param valuesPerNode Maximum number of elements to put at
1102 a node.
1104 @param numMeanSplits numMeanSplits = 0 gives a
1105 fully axis aligned BSP-tree, where the balance operation attempts to balance
1106 the tree so that every splitting plane has an equal number of left
1107 and right children (i.e. it is a <B>median</B> split along that axis).
1108 This tends to maximize average performance.
1110 You can override this behavior by
1111 setting a number of <B>mean</B> (average) splits. numMeanSplits = MAX_INT
1112 creates a full oct-tree, which tends to optimize peak performance at the expense of
1113 average performance. It tends to have better clustering behavior when
1114 members are not uniformly distributed.
1116 void balance(int valuesPerNode = 5, int numMeanSplits = 3) {
1117 if (root == NULL) {
1118 // Tree is empty
1119 return;
1122 // Get all handles and delete the old tree structure
1123 Node* oldRoot = root;
1124 for (int c = 0; c < 2; ++c) {
1125 if (root->child[c] != NULL) {
1126 root->child[c]->getHandles(root->valueArray);
1128 // Delete the child; this will delete all structure below it
1129 delete root->child[c];
1130 root->child[c] = NULL;
1134 Array<_AABSPTree::Handle<T> * > temp;
1135 // Make a new root. Work with a copy of the value array because
1136 // makeNode clears the source array as it progresses
1137 Array<_AABSPTree::Handle<T> * > copy(oldRoot->valueArray);
1138 root = makeNode(copy, valuesPerNode, numMeanSplits, temp);
1140 // Throw away the old root node
1141 delete oldRoot;
1142 oldRoot = NULL;
1144 // Walk the tree, assigning splitBounds. We start with unbounded
1145 // space. This will override the current member table.
1146 root->assignSplitBounds(AABox::maxFinite());
1148 # ifdef _DEBUG
1149 // Ensure that the balanced tree is till correct
1150 root->verifyNode(Vector3::minFinite(), Vector3::maxFinite());
1151 # endif
1154 protected:
1157 @param parentMask The mask that this node returned from culledBy.
1159 static void getIntersectingMembers(
1160 const Array<Plane>& plane,
1161 Array<T>& members,
1162 Node* node,
1163 uint32 parentMask) {
1165 int dummy;
1167 if (parentMask == 0) {
1168 // None of these planes can cull anything
1169 for (int v = node->valueArray.size() - 1; v >= 0; --v) {
1170 members.append(node->valueArray[v]->value);
1173 // Iterate through child nodes
1174 for (int c = 0; c < 2; ++c) {
1175 if (node->child[c]) {
1176 getIntersectingMembers(plane, members, node->child[c], 0);
1179 } else {
1181 // Test values at this node against remaining planes
1182 for (int v = node->boundsArray.size() - 1; v >= 0; --v) {
1183 if (! node->boundsArray[v].culledBy(plane, dummy, parentMask)) {
1184 members.append(node->valueArray[v]->value);
1188 uint32 childMask = 0xFFFFFF;
1190 // Iterate through child nodes
1191 for (int c = 0; c < 2; ++c) {
1192 if (node->child[c] &&
1193 ! node->child[c]->splitBounds.culledBy(plane, dummy, parentMask, childMask)) {
1194 // This node was not culled
1195 getIntersectingMembers(plane, members, node->child[c], childMask);
1201 public:
1204 Returns all members inside the set of planes.
1205 @param members The results are appended to this array.
1207 void getIntersectingMembers(const Array<Plane>& plane, Array<T>& members) const {
1208 if (root == NULL) {
1209 return;
1212 getIntersectingMembers(plane, members, root, 0xFFFFFF);
1216 Typically used to find all visible
1217 objects inside the view frustum (see also GCamera::getClipPlanes)... i.e. all objects
1218 <B>not<B> culled by frustum.
1220 Example:
1221 <PRE>
1222 Array<Object*> visible;
1223 tree.getIntersectingMembers(camera.frustum(), visible);
1224 // ... Draw all objects in the visible array.
1225 </PRE>
1226 @param members The results are appended to this array.
1228 void getIntersectingMembers(const GCamera::Frustum& frustum, Array<T>& members) const {
1229 Array<Plane> plane;
1231 for (int i = 0; i < frustum.faceArray.size(); ++i) {
1232 plane.append(frustum.faceArray[i].plane);
1235 getIntersectingMembers(plane, members);
1239 C++ STL style iterator variable. See beginBoxIntersection().
1240 The iterator overloads the -> (dereference) operator, so this
1241 acts like a pointer to the current member.
1243 // This iterator turns Node::getIntersectingMembers into a
1244 // coroutine. It first translates that method from recursive to
1245 // stack based, then captures the system state (analogous to a Scheme
1246 // continuation) after each element is appended to the member array,
1247 // and allowing the computation to be restarted.
1248 class BoxIntersectionIterator {
1249 private:
1250 friend class AABSPTree<T>;
1252 /** True if this is the "end" iterator instance */
1253 bool isEnd;
1255 /** The box that we're testing against. */
1256 AABox box;
1258 /** Node that we're currently looking at. Undefined if isEnd
1259 is true. */
1260 Node* node;
1262 /** Nodes waiting to be processed */
1263 // We could use backpointers within the tree and careful
1264 // state management to avoid ever storing the stack-- but
1265 // it is much easier this way and only inefficient if the
1266 // caller uses post increment (which they shouldn't!).
1267 Array<Node*> stack;
1269 /** The next index of current->valueArray to return.
1270 Undefined when isEnd is true.*/
1271 int nextValueArrayIndex;
1273 BoxIntersectionIterator() : isEnd(true) {}
1275 BoxIntersectionIterator(const AABox& b, const Node* root) :
1276 isEnd(root == NULL), box(b),
1277 node(const_cast<Node*>(root)), nextValueArrayIndex(-1) {
1279 // We intentionally start at the "-1" index of the current
1280 // node so we can use the preincrement operator to move
1281 // ourselves to element 0 instead of repeating all of the
1282 // code from the preincrement method. Note that this might
1283 // cause us to become the "end" instance.
1284 ++(*this);
1287 public:
1289 inline bool operator!=(const BoxIntersectionIterator& other) const {
1290 return ! (*this == other);
1293 bool operator==(const BoxIntersectionIterator& other) const {
1294 if (isEnd) {
1295 return other.isEnd;
1296 } else if (other.isEnd) {
1297 return false;
1298 } else {
1299 // Two non-end iterators; see if they match. This is kind of
1300 // silly; users shouldn't call == on iterators in general unless
1301 // one of them is the end iterator.
1302 if ((box != other.box) || (node != other.node) ||
1303 (nextValueArrayIndex != other.nextValueArrayIndex) ||
1304 (stack.length() != other.stack.length())) {
1305 return false;
1308 // See if the stacks are the same
1309 for (int i = 0; i < stack.length(); ++i) {
1310 if (stack[i] != other.stack[i]) {
1311 return false;
1315 // We failed to find a difference; they must be the same
1316 return true;
1321 Pre increment.
1323 BoxIntersectionIterator& operator++() {
1324 ++nextValueArrayIndex;
1326 bool foundIntersection = false;
1327 while (! isEnd && ! foundIntersection) {
1329 // Search for the next node if we've exhausted this one
1330 while ((! isEnd) && (nextValueArrayIndex >= node->valueArray.length())) {
1331 // If we entered this loop, then the iterator has exhausted the elements at
1332 // node (possibly because it just switched to a child node with no members).
1333 // This loop continues until it finds a node with members or reaches
1334 // the end of the whole intersection search.
1336 // If the right child overlaps the box, push it onto the stack for
1337 // processing.
1338 if ((node->child[1] != NULL) &&
1339 (box.high()[node->splitAxis] > node->splitLocation)) {
1340 stack.push(node->child[1]);
1343 // If the left child overlaps the box, push it onto the stack for
1344 // processing.
1345 if ((node->child[0] != NULL) &&
1346 (box.low()[node->splitAxis] < node->splitLocation)) {
1347 stack.push(node->child[0]);
1350 if (stack.length() > 0) {
1351 // Go on to the next node (which may be either one of the ones we
1352 // just pushed, or one from farther back the tree).
1353 node = stack.pop();
1354 nextValueArrayIndex = 0;
1355 } else {
1356 // That was the last node; we're done iterating
1357 isEnd = true;
1361 // Search for the next intersection at this node until we run out of children
1362 while (! isEnd && ! foundIntersection && (nextValueArrayIndex < node->valueArray.length())) {
1363 if (box.intersects(node->boundsArray[nextValueArrayIndex])) {
1364 foundIntersection = true;
1365 } else {
1366 ++nextValueArrayIndex;
1367 // If we exhaust this node, we'll loop around the master loop
1368 // to find a new node.
1373 return *this;
1376 private:
1378 Post increment (much slower than preincrement!). Intentionally overloaded to preclude accidentally slow code.
1380 BoxIntersectionIterator operator++(int);
1382 BoxIntersectionIterator old = *this;
1383 ++this;
1384 return old;
1387 public:
1389 /** Overloaded dereference operator so the iterator can masquerade as a pointer
1390 to a member */
1391 const T& operator*() const {
1392 alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator");
1393 return node->valueArray[nextValueArrayIndex]->value;
1396 /** Overloaded dereference operator so the iterator can masquerade as a pointer
1397 to a member */
1398 T const * operator->() const {
1399 alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator");
1400 return &(stack.last()->valueArray[nextValueArrayIndex]->value);
1403 /** Overloaded cast operator so the iterator can masquerade as a pointer
1404 to a member */
1405 operator T*() const {
1406 alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator");
1407 return &(stack.last()->valueArray[nextValueArrayIndex]->value);
1413 Iterates through the members that intersect the box
1415 BoxIntersectionIterator beginBoxIntersection(const AABox& box) const {
1416 return BoxIntersectionIterator(box, root);
1419 BoxIntersectionIterator endBoxIntersection() const {
1420 // The "end" iterator instance
1421 return BoxIntersectionIterator();
1425 Appends all members whose bounds intersect the box.
1426 See also AABSPTree::beginBoxIntersection.
1428 void getIntersectingMembers(const AABox& box, Array<T>& members) const {
1429 if (root == NULL) {
1430 return;
1432 root->getIntersectingMembers(box, Sphere(Vector3::zero(), 0), members, false);
1437 Invoke a callback for every member along a ray until the closest intersection is found.
1439 @param callback either a function or an instance of a class with an overloaded operator() of the form:
1441 <code>void callback(const Ray& ray, const T& object, float& distance)</code>. If the ray hits the object
1442 before travelling distance <code>distance</code>, updates <code>distance</code> with the new distance to
1443 the intersection, otherwise leaves it unmodified. A common example is:
1445 <pre>
1446 class Entity {
1447 public:
1449 void intersect(const Ray& ray, float& maxDist, Vector3& outLocation, Vector3& outNormal) {
1450 float d = maxDist;
1452 // ... search for intersection distance d
1454 if ((d > 0) && (d < maxDist)) {
1455 // Intersection occured
1456 maxDist = d;
1457 outLocation = ...;
1458 outNormal = ...;
1463 // Finds the surface normal and location of the first intersection with the scene
1464 class Intersection {
1465 public:
1466 Entity* closestEntity;
1467 Vector3 hitLocation;
1468 Vector3 hitNormal;
1470 void operator()(const Ray& ray, const Entity* entity, float& distance) {
1471 entity->intersect(ray, distance, hitLocation, hitNormal);
1475 AABSPTree<Entity*> scene;
1477 Intersection intersection;
1478 float distance = inf();
1479 scene.intersectRay(camera.worldRay(x, y), intersection, distance);
1480 </pre>
1483 @param distance When the method is invoked, this is the maximum distance that the tree should search for an intersection.
1484 On return, this is set to the distance to the first intersection encountered.
1486 @param intersectCallbackIsFast If false, each object's bounds are tested before the intersectCallback is invoked.
1487 If the intersect callback runs at the same speed or faster than AABox-ray intersection, set this to true.
1489 template<typename RayCallback>
1490 void intersectRay(
1491 const Ray& ray,
1492 RayCallback& intersectCallback,
1493 float& distance,
1494 bool pStopAtFirstHit,
1495 bool intersectCallbackIsFast = false) const {
1497 root->intersectRay(ray, intersectCallback, distance, pStopAtFirstHit, intersectCallbackIsFast);
1503 @param members The results are appended to this array.
1505 void getIntersectingMembers(const Sphere& sphere, Array<T>& members) const {
1506 if (root == NULL) {
1507 return;
1510 AABox box;
1511 sphere.getBounds(box);
1512 root->getIntersectingMembers(box, sphere, members, true);
1515 #if 0
1517 Stores the locations of the splitting planes (the structure but not the content)
1518 so that the tree can be quickly rebuilt from a previous configuration without
1519 calling balance.
1521 void serializeStructure(BinaryOutput& bo) const {
1522 Node::serializeStructure(root, bo);
1525 /** Clears the member table */
1526 void deserializeStructure(BinaryInput& bi) {
1527 clear();
1528 root = Node::deserializeStructure(bi);
1530 #endif
1532 Returns an array of all members of the set. See also AABSPTree::begin.
1534 void getMembers(Array<T>& members) const {
1535 Array<Member> temp;
1536 memberTable.getKeys(temp);
1537 for (int i = 0; i < temp.size(); ++i) {
1538 members.append(temp[i].handle->value);
1545 #endif