[9175] Remove duplicate fclose call.
[getmangos.git] / contrib / vmap_debugger / G3D / AABSPTree.h
blob543f06a881ec5635869842e27ee5f5cac37da8fb
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<typename 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) {
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
798 // below.
799 numMeanSplits = 1;
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);
836 # endif
838 // The source array is no longer needed
839 source.clear();
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);
852 if (lt.size() > 0) {
853 node->child[0] = makeNode(lt, valuesPerNode, numMeanSplits - 1, temp);
856 if (gt.size() > 0) {
857 node->child[1] = makeNode(gt, valuesPerNode, numMeanSplits - 1, temp);
862 return node;
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);
878 // Clone children
879 for (int i = 0; i < 2; ++i) {
880 if (src->child[i] != NULL) {
881 dst->child[i] = cloneTree(src->child[i]);
885 return dst;
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;
899 Node* root;
901 public:
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) {
909 *this = src;
913 AABSPTree& operator=(const AABSPTree& src) {
914 delete root;
915 // Clone tree takes care of filling out the memberTable.
916 root = cloneTree(src.root);
917 return *this;
921 ~AABSPTree() {
922 clear();
926 Throws out all elements of the set.
928 void clear() {
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();
934 while (cur != end) {
935 delete cur->key.handle;
936 cur->key.handle = NULL;
937 ++cur;
939 memberTable.clear();
941 // Delete the tree structure itself
942 delete root;
943 root = NULL;
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
958 return;
961 _AABSPTree::Handle<T>* h = new _AABSPTree::Handle<T>(value);
963 if (root == NULL) {
964 // This is the first node; create a root node
965 root = new 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
975 Member m(h);
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) {
984 if (root == NULL) {
985 // Optimized case for an empty tree; don't bother
986 // searching or reallocating the root node's valueArray
987 // as we incrementally insert.
988 root = new Node();
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
994 // from array).
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);
1002 } else {
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);
1039 Member m(&h);
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
1050 ptr = list[i];
1052 // Remove the handle from the node
1053 list.fastRemove(i);
1055 // Remove the corresponding bounds
1056 memberTable[m]->boundsArray.fastRemove(i);
1057 break;
1061 // Remove the member
1062 memberTable.remove(m);
1064 // Delete the handle data structure
1065 delete ptr;
1066 ptr = NULL;
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
1079 up to date.
1081 void update(const T& value) {
1082 if (contains(value)) {
1083 remove(value);
1085 insert(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
1096 a node.
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) {
1111 if (root == NULL) {
1112 // Tree is empty
1113 return;
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
1135 delete oldRoot;
1136 oldRoot = NULL;
1138 // Walk the tree, assigning splitBounds. We start with unbounded
1139 // space. This will override the current member table.
1140 root->assignSplitBounds(AABox::maxFinite());
1142 # ifdef _DEBUG
1143 // Ensure that the balanced tree is till correct
1144 root->verifyNode(Vector3::minFinite(), Vector3::maxFinite());
1145 # endif
1148 protected:
1151 @param parentMask The mask that this node returned from culledBy.
1153 static void getIntersectingMembers(
1154 const Array<Plane>& plane,
1155 Array<T>& members,
1156 Node* node,
1157 uint32 parentMask) {
1159 int dummy;
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);
1173 } else {
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);
1195 public:
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 {
1202 if (root == NULL) {
1203 return;
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.
1214 Example:
1215 <PRE>
1216 Array<Object*> visible;
1217 tree.getIntersectingMembers(camera.frustum(), visible);
1218 // ... Draw all objects in the visible array.
1219 </PRE>
1220 @param members The results are appended to this array.
1222 void getIntersectingMembers(const GCamera::Frustum& frustum, Array<T>& members) const {
1223 Array<Plane> plane;
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 {
1243 private:
1244 friend class AABSPTree<T>;
1246 /** True if this is the "end" iterator instance */
1247 bool isEnd;
1249 /** The box that we're testing against. */
1250 AABox box;
1252 /** Node that we're currently looking at. Undefined if isEnd
1253 is true. */
1254 Node* node;
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!).
1261 Array<Node*> stack;
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.
1278 ++(*this);
1281 public:
1283 inline bool operator!=(const BoxIntersectionIterator& other) const {
1284 return ! (*this == other);
1287 bool operator==(const BoxIntersectionIterator& other) const {
1288 if (isEnd) {
1289 return other.isEnd;
1290 } else if (other.isEnd) {
1291 return false;
1292 } else {
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())) {
1299 return false;
1302 // See if the stacks are the same
1303 for (int i = 0; i < stack.length(); ++i) {
1304 if (stack[i] != other.stack[i]) {
1305 return false;
1309 // We failed to find a difference; they must be the same
1310 return true;
1315 Pre increment.
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
1331 // processing.
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
1338 // processing.
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).
1347 node = stack.pop();
1348 nextValueArrayIndex = 0;
1349 } else {
1350 // That was the last node; we're done iterating
1351 isEnd = true;
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;
1359 } else {
1360 ++nextValueArrayIndex;
1361 // If we exhaust this node, we'll loop around the master loop
1362 // to find a new node.
1367 return *this;
1370 private:
1372 Post increment (much slower than preincrement!). Intentionally overloaded to preclude accidentally slow code.
1374 BoxIntersectionIterator operator++(int);
1376 BoxIntersectionIterator old = *this;
1377 ++this;
1378 return old;
1381 public:
1383 /** Overloaded dereference operator so the iterator can masquerade as a pointer
1384 to a member */
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
1391 to a member */
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
1398 to a member */
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 {
1423 if (root == NULL) {
1424 return;
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:
1439 <pre>
1440 class Entity {
1441 public:
1443 void intersect(const Ray& ray, float& maxDist, Vector3& outLocation, Vector3& outNormal) {
1444 float d = maxDist;
1446 // ... search for intersection distance d
1448 if ((d > 0) && (d < maxDist)) {
1449 // Intersection occured
1450 maxDist = d;
1451 outLocation = ...;
1452 outNormal = ...;
1457 // Finds the surface normal and location of the first intersection with the scene
1458 class Intersection {
1459 public:
1460 Entity* closestEntity;
1461 Vector3 hitLocation;
1462 Vector3 hitNormal;
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);
1474 </pre>
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>
1484 void intersectRay(
1485 const Ray& ray,
1486 RayCallback& intersectCallback,
1487 float& distance,
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 {
1500 if (root == NULL) {
1501 return;
1504 AABox box;
1505 sphere.getBounds(box);
1506 root->getIntersectingMembers(box, sphere, members, true);
1509 #if 0
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
1513 calling balance.
1515 void serializeStructure(BinaryOutput& bo) const {
1516 Node::serializeStructure(root, bo);
1519 /** Clears the member table */
1520 void deserializeStructure(BinaryInput& bi) {
1521 clear();
1522 root = Node::deserializeStructure(bi);
1524 #endif
1526 Returns an array of all members of the set. See also AABSPTree::begin.
1528 void getMembers(Array<T>& members) const {
1529 Array<Member> temp;
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.
1542 class Iterator {
1543 private:
1544 friend class AABSPTree<T>;
1546 // Note: this is a Table iterator, we are currently defining
1547 // Set iterator
1548 typename Table<Member, Node*>::Iterator it;
1550 Iterator(const typename Table<Member, Node*>::Iterator& it) : it(it) {}
1552 public:
1554 inline bool operator!=(const Iterator& other) const {
1555 return !(*this == other);
1558 bool operator==(const Iterator& other) const {
1559 return it == other.it;
1563 Pre increment.
1565 Iterator& operator++() {
1566 ++it;
1567 return *this;
1570 private:
1572 Post increment (slower than preincrement). Intentionally unimplemented to prevent slow code.
1574 Iterator operator++(int);/* {
1575 Iterator old = *this;
1576 ++(*this);
1577 return old;
1579 public:
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
1608 element.
1610 Iterator end() const {
1611 return Iterator(memberTable.end());
1617 #endif