1 | /** |
---|
2 | @file AABSPTree.h |
---|
3 | |
---|
4 | @maintainer Morgan McGuire, matrix@graphics3d.com |
---|
5 | |
---|
6 | @created 2004-01-11 |
---|
7 | @edited 2007-02-16 |
---|
8 | |
---|
9 | Copyright 2000-2007, Morgan McGuire. |
---|
10 | All rights reserved. |
---|
11 | |
---|
12 | */ |
---|
13 | |
---|
14 | #ifndef G3D_AABSPTREE_H |
---|
15 | #define G3D_AABSPTREE_H |
---|
16 | |
---|
17 | #include "VMapTools.h" |
---|
18 | |
---|
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> |
---|
36 | |
---|
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 |
---|
40 | |
---|
41 | inline void getBounds(const G3D::Vector3& v, G3D::AABox& out) { |
---|
42 | out = G3D::AABox(v); |
---|
43 | } |
---|
44 | |
---|
45 | |
---|
46 | inline void getBounds(const G3D::AABox& a, G3D::AABox& out) { |
---|
47 | out = a; |
---|
48 | } |
---|
49 | |
---|
50 | inline void getBounds(const G3D::Sphere& s, G3D::AABox& out) { |
---|
51 | s.getBounds(out); |
---|
52 | } |
---|
53 | |
---|
54 | |
---|
55 | inline void getBounds(const G3D::Box& b, G3D::AABox& out) { |
---|
56 | b.getBounds(out); |
---|
57 | } |
---|
58 | |
---|
59 | |
---|
60 | inline void getBounds(const G3D::Triangle& t, G3D::AABox& out) { |
---|
61 | t.getBounds(out); |
---|
62 | } |
---|
63 | |
---|
64 | |
---|
65 | |
---|
66 | inline void getBounds(const G3D::Vector3* v, G3D::AABox& out) { |
---|
67 | out = G3D::AABox(*v); |
---|
68 | } |
---|
69 | |
---|
70 | |
---|
71 | inline void getBounds(const G3D::AABox* a, G3D::AABox& out) { |
---|
72 | getBounds(*a, out); |
---|
73 | } |
---|
74 | |
---|
75 | inline void getBounds(const G3D::Sphere* s, G3D::AABox& out) { |
---|
76 | s->getBounds(out); |
---|
77 | } |
---|
78 | |
---|
79 | |
---|
80 | inline void getBounds(const G3D::Box* b, G3D::AABox& out) { |
---|
81 | b->getBounds(out); |
---|
82 | } |
---|
83 | |
---|
84 | inline void getBounds(const G3D::Triangle* t, G3D::AABox& out) { |
---|
85 | t->getBounds(out); |
---|
86 | } |
---|
87 | namespace G3D { |
---|
88 | namespace _internal { |
---|
89 | |
---|
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. |
---|
94 | */ |
---|
95 | template<class Type> |
---|
96 | class Indirector { |
---|
97 | public: |
---|
98 | Type* handle; |
---|
99 | |
---|
100 | inline Indirector(Type* h) : handle(h) {} |
---|
101 | |
---|
102 | inline Indirector() : handle(NULL) {} |
---|
103 | |
---|
104 | /** Returns true iff the values referenced by the handles are equivalent. */ |
---|
105 | inline bool operator==(const Indirector& m) { |
---|
106 | return *handle == *(m.handle); |
---|
107 | } |
---|
108 | |
---|
109 | inline bool operator==(const Type& m) { |
---|
110 | return *handle == m; |
---|
111 | } |
---|
112 | |
---|
113 | inline size_t hashCode() const { |
---|
114 | return handle->hashCode(); |
---|
115 | } |
---|
116 | }; |
---|
117 | } // namespace internal |
---|
118 | } // namespace G3D |
---|
119 | |
---|
120 | template <class Handle> |
---|
121 | struct GHashCode<typename G3D::_internal::Indirector<Handle> > |
---|
122 | { |
---|
123 | size_t operator()(const G3D::_internal::Indirector<Handle>& key) const { return key.hashCode(); } |
---|
124 | }; |
---|
125 | |
---|
126 | namespace G3D { |
---|
127 | |
---|
128 | /** |
---|
129 | A set that supports spatial queries using an axis-aligned |
---|
130 | BSP tree for speed. |
---|
131 | |
---|
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. |
---|
135 | |
---|
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). |
---|
139 | |
---|
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. |
---|
144 | |
---|
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: |
---|
148 | |
---|
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> |
---|
153 | |
---|
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. |
---|
157 | |
---|
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. |
---|
167 | |
---|
168 | |
---|
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. |
---|
172 | |
---|
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.) |
---|
179 | |
---|
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. |
---|
184 | |
---|
185 | */ |
---|
186 | namespace _AABSPTree { |
---|
187 | |
---|
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. |
---|
193 | */ |
---|
194 | template<class TValue> |
---|
195 | class Handle { |
---|
196 | public: |
---|
197 | /** The bounds of each object are constrained to AABox::maxFinite */ |
---|
198 | AABox bounds; |
---|
199 | |
---|
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; |
---|
205 | |
---|
206 | TValue value; |
---|
207 | |
---|
208 | Handle<TValue>() {} |
---|
209 | |
---|
210 | inline Handle<TValue>(const TValue& v) : value(v) { |
---|
211 | getBounds(v, bounds); |
---|
212 | bounds = bounds.intersect(AABox::maxFinite()); |
---|
213 | center = bounds.center(); |
---|
214 | } |
---|
215 | |
---|
216 | inline bool operator==(const Handle<TValue>& other) const { |
---|
217 | return (*value).operator==(*other.value); |
---|
218 | } |
---|
219 | |
---|
220 | inline size_t hashCode() const { |
---|
221 | return value->hashCode(); |
---|
222 | } |
---|
223 | }; |
---|
224 | |
---|
225 | template<> |
---|
226 | class Handle<Triangle> { |
---|
227 | public: |
---|
228 | /** The bounds of each object are constrained to AABox::maxFinite */ |
---|
229 | AABox bounds; |
---|
230 | |
---|
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; |
---|
236 | |
---|
237 | Triangle value; |
---|
238 | |
---|
239 | Handle<Triangle>() {} |
---|
240 | |
---|
241 | inline Handle<Triangle>(const Triangle& v) : value(v) { |
---|
242 | getBounds(v, bounds); |
---|
243 | bounds = bounds.intersect(AABox::maxFinite()); |
---|
244 | center = bounds.center(); |
---|
245 | } |
---|
246 | |
---|
247 | inline bool operator==(const Handle<Triangle>& other) const { |
---|
248 | return value.operator==(other.value); |
---|
249 | } |
---|
250 | |
---|
251 | inline size_t hashCode() const { |
---|
252 | return value.hashCode(); |
---|
253 | } |
---|
254 | }; |
---|
255 | } |
---|
256 | |
---|
257 | template<class T> class AABSPTree { |
---|
258 | protected: |
---|
259 | public: |
---|
260 | |
---|
261 | |
---|
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) { |
---|
267 | |
---|
268 | Vector3 lo = Vector3::inf(); |
---|
269 | Vector3 hi = -lo; |
---|
270 | |
---|
271 | for (int p = beginIndex; p <= endIndex; ++p) { |
---|
272 | lo = lo.min(point[p]->bounds.low()); |
---|
273 | hi = hi.max(point[p]->bounds.high()); |
---|
274 | } |
---|
275 | |
---|
276 | return AABox(lo, hi); |
---|
277 | } |
---|
278 | |
---|
279 | /** Compares centers */ |
---|
280 | class CenterComparator { |
---|
281 | public: |
---|
282 | Vector3::Axis sortAxis; |
---|
283 | |
---|
284 | CenterComparator(Vector3::Axis a) : sortAxis(a) {} |
---|
285 | |
---|
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]; |
---|
289 | |
---|
290 | if (a < b) { |
---|
291 | return 1; |
---|
292 | } else if (a > b) { |
---|
293 | return -1; |
---|
294 | } else { |
---|
295 | return 0; |
---|
296 | } |
---|
297 | } |
---|
298 | }; |
---|
299 | |
---|
300 | |
---|
301 | /** Compares bounds for strict >, <, or overlap*/ |
---|
302 | class BoundsComparator { |
---|
303 | public: |
---|
304 | Vector3::Axis sortAxis; |
---|
305 | |
---|
306 | BoundsComparator(Vector3::Axis a) : sortAxis(a) {} |
---|
307 | |
---|
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; |
---|
311 | |
---|
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; |
---|
318 | } |
---|
319 | } |
---|
320 | }; |
---|
321 | |
---|
322 | |
---|
323 | /** Compares bounds to the sort location */ |
---|
324 | class Comparator { |
---|
325 | public: |
---|
326 | Vector3::Axis sortAxis; |
---|
327 | float sortLocation; |
---|
328 | |
---|
329 | Comparator(Vector3::Axis a, float l) : sortAxis(a), sortLocation(l) {} |
---|
330 | |
---|
331 | inline int operator()(_AABSPTree::Handle<T>* ignore, const _AABSPTree::Handle<T>* handle) const { |
---|
332 | const AABox& box = handle->bounds; |
---|
333 | debugAssert(ignore == NULL); |
---|
334 | |
---|
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; |
---|
344 | } |
---|
345 | } |
---|
346 | }; |
---|
347 | |
---|
348 | // Using System::malloc with this class provided no speed improvement. |
---|
349 | class Node { |
---|
350 | public: |
---|
351 | |
---|
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; |
---|
355 | |
---|
356 | Vector3::Axis splitAxis; |
---|
357 | |
---|
358 | /** Location along the specified axis */ |
---|
359 | float splitLocation; |
---|
360 | |
---|
361 | /** child[0] contains all values strictly |
---|
362 | smaller than splitLocation along splitAxis. |
---|
363 | |
---|
364 | child[1] contains all values strictly |
---|
365 | larger. |
---|
366 | |
---|
367 | Both may be NULL if there are not enough |
---|
368 | values to bother recursing. |
---|
369 | */ |
---|
370 | Node* child[2]; |
---|
371 | |
---|
372 | /** Array of values at this node (i.e., values |
---|
373 | straddling the split plane + all values if |
---|
374 | this is a leaf node). |
---|
375 | |
---|
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. |
---|
379 | */ |
---|
380 | Array<_AABSPTree::Handle<T> * > valueArray; |
---|
381 | |
---|
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. |
---|
387 | */ |
---|
388 | Array<AABox> boundsArray; |
---|
389 | |
---|
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; |
---|
397 | } |
---|
398 | } |
---|
399 | |
---|
400 | /** |
---|
401 | Doesn't clone children. |
---|
402 | */ |
---|
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; |
---|
409 | } |
---|
410 | } |
---|
411 | |
---|
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; |
---|
419 | } |
---|
420 | |
---|
421 | boundsArray.resize(valueArray.size()); |
---|
422 | for (int i = 0; i < valueArray.size(); ++i) { |
---|
423 | boundsArray[i] = valueArray[i]->bounds; |
---|
424 | } |
---|
425 | } |
---|
426 | |
---|
427 | /** Deletes the children (but not the values) */ |
---|
428 | ~Node() { |
---|
429 | for (int i = 0; i < 2; ++i) { |
---|
430 | delete child[i]; |
---|
431 | } |
---|
432 | } |
---|
433 | |
---|
434 | /** Returns true if this node is a leaf (no children) */ |
---|
435 | inline bool isLeaf() const { |
---|
436 | return (child[0] == NULL) && (child[1] == NULL); |
---|
437 | } |
---|
438 | |
---|
439 | |
---|
440 | /** |
---|
441 | Recursively appends all handles and children's handles |
---|
442 | to the array. |
---|
443 | */ |
---|
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); |
---|
449 | } |
---|
450 | } |
---|
451 | } |
---|
452 | |
---|
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); |
---|
456 | |
---|
457 | debugAssert(lo == splitBounds.low()); |
---|
458 | debugAssert(hi == splitBounds.high()); |
---|
459 | |
---|
460 | for (int i = 0; i < valueArray.length(); ++i) { |
---|
461 | const AABox& b = valueArray[i]->bounds; |
---|
462 | debugAssert(b == boundsArray[i]); |
---|
463 | |
---|
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]); |
---|
468 | } |
---|
469 | } |
---|
470 | |
---|
471 | if (child[0] || child[1]) { |
---|
472 | debugAssert(lo[splitAxis] < splitLocation); |
---|
473 | debugAssert(hi[splitAxis] > splitLocation); |
---|
474 | } |
---|
475 | |
---|
476 | Vector3 newLo = lo; |
---|
477 | newLo[splitAxis] = splitLocation; |
---|
478 | Vector3 newHi = hi; |
---|
479 | newHi[splitAxis] = splitLocation; |
---|
480 | |
---|
481 | if (child[0] != NULL) { |
---|
482 | child[0]->verifyNode(lo, newHi); |
---|
483 | } |
---|
484 | |
---|
485 | if (child[1] != NULL) { |
---|
486 | child[1]->verifyNode(newLo, hi); |
---|
487 | } |
---|
488 | } |
---|
489 | |
---|
490 | #if 0 |
---|
491 | /** |
---|
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. |
---|
495 | */ |
---|
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); |
---|
506 | } |
---|
507 | } |
---|
508 | } |
---|
509 | |
---|
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); |
---|
521 | } |
---|
522 | } |
---|
523 | } |
---|
524 | #endif |
---|
525 | /** Returns the deepest node that completely contains bounds. */ |
---|
526 | Node* findDeepestContainingNode(const AABox& bounds) { |
---|
527 | |
---|
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); |
---|
534 | } |
---|
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); |
---|
540 | } |
---|
541 | } |
---|
542 | |
---|
543 | // There was no containing child, so this node is the |
---|
544 | // deepest containing node. |
---|
545 | return this; |
---|
546 | } |
---|
547 | |
---|
548 | |
---|
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 { |
---|
557 | |
---|
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); |
---|
564 | } |
---|
565 | } |
---|
566 | |
---|
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); |
---|
570 | } |
---|
571 | |
---|
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); |
---|
575 | } |
---|
576 | } |
---|
577 | |
---|
578 | /** |
---|
579 | Recurse through the tree, assigning splitBounds fields. |
---|
580 | */ |
---|
581 | void assignSplitBounds(const AABox& myBounds) { |
---|
582 | splitBounds = myBounds; |
---|
583 | |
---|
584 | AABox childBounds[2]; |
---|
585 | myBounds.split(splitAxis, splitLocation, childBounds[0], childBounds[1]); |
---|
586 | |
---|
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)); |
---|
592 | } |
---|
593 | # endif |
---|
594 | |
---|
595 | for (int c = 0; c < 2; ++c) { |
---|
596 | if (child[c]) { |
---|
597 | child[c]->assignSplitBounds(childBounds[c]); |
---|
598 | } |
---|
599 | } |
---|
600 | } |
---|
601 | |
---|
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); |
---|
610 | |
---|
611 | bool canHitThisNode = (alreadyInsideBounds || |
---|
612 | (rayWillHitBounds && ((location - ray.origin).squaredLength() < square(distance)))); |
---|
613 | |
---|
614 | return canHitThisNode; |
---|
615 | } |
---|
616 | |
---|
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; |
---|
625 | |
---|
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; |
---|
629 | } |
---|
630 | |
---|
631 | // Test for intersection against every object at this node. |
---|
632 | for (int v = 0; v < valueArray.size(); ++v) { |
---|
633 | bool canHitThisObject = true; |
---|
634 | |
---|
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); |
---|
643 | |
---|
644 | canHitThisObject = (alreadyInsideBounds || |
---|
645 | (rayWillHitBounds && ((location - ray.origin).squaredLength() < square(distance)))); |
---|
646 | } |
---|
647 | |
---|
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); |
---|
653 | } |
---|
654 | if(pStopAtFirstHit && distance < enterDistance) |
---|
655 | return; |
---|
656 | } |
---|
657 | |
---|
658 | // There are three cases to consider next: |
---|
659 | // |
---|
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 |
---|
663 | |
---|
664 | enum {NONE = -1}; |
---|
665 | int firstChild = NONE; |
---|
666 | int secondChild = NONE; |
---|
667 | |
---|
668 | if (ray.origin[splitAxis] < splitLocation) { |
---|
669 | |
---|
670 | // The ray starts on the small side |
---|
671 | firstChild = 0; |
---|
672 | |
---|
673 | if (ray.direction[splitAxis] > 0) { |
---|
674 | // The ray will eventually reach the other side |
---|
675 | secondChild = 1; |
---|
676 | } |
---|
677 | |
---|
678 | } else if (ray.origin[splitAxis] > splitLocation) { |
---|
679 | |
---|
680 | // The ray starts on the large side |
---|
681 | firstChild = 1; |
---|
682 | |
---|
683 | if (ray.direction[splitAxis] < 0) { |
---|
684 | secondChild = 0; |
---|
685 | } |
---|
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; |
---|
694 | } |
---|
695 | } |
---|
696 | |
---|
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; |
---|
702 | } |
---|
703 | |
---|
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; |
---|
713 | } |
---|
714 | } |
---|
715 | |
---|
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); |
---|
719 | } |
---|
720 | |
---|
721 | } |
---|
722 | }; |
---|
723 | |
---|
724 | |
---|
725 | /** |
---|
726 | Recursively subdivides the subarray. |
---|
727 | |
---|
728 | Clears the source array as soon as it is no longer needed. |
---|
729 | |
---|
730 | Call assignSplitBounds() on the root node after making a tree. |
---|
731 | */ |
---|
732 | Node* makeNode( |
---|
733 | Array<_AABSPTree::Handle<T> * >& source, |
---|
734 | int valuesPerNode, |
---|
735 | int numMeanSplits, |
---|
736 | Array<_AABSPTree::Handle<T> * >& temp) { |
---|
737 | |
---|
738 | Node* node = NULL; |
---|
739 | |
---|
740 | if (source.size() <= valuesPerNode) { |
---|
741 | // Make a new leaf node |
---|
742 | node = new Node(source); |
---|
743 | |
---|
744 | // Set the pointers in the memberTable |
---|
745 | for (int i = 0; i < source.size(); ++i) { |
---|
746 | memberTable.set(Member(source[i]), node); |
---|
747 | } |
---|
748 | source.clear(); |
---|
749 | |
---|
750 | } else { |
---|
751 | // Make a new internal node |
---|
752 | node = new Node(); |
---|
753 | |
---|
754 | const AABox bounds = computeBounds(source, 0, source.size() - 1); |
---|
755 | const Vector3 extent = bounds.high() - bounds.low(); |
---|
756 | |
---|
757 | Vector3::Axis splitAxis = extent.primaryAxis(); |
---|
758 | |
---|
759 | float splitLocation; |
---|
760 | |
---|
761 | // Arrays for holding the children |
---|
762 | Array<_AABSPTree::Handle<T> * > lt, gt; |
---|
763 | |
---|
764 | if (numMeanSplits <= 0) { |
---|
765 | |
---|
766 | source.medianPartition(lt, node->valueArray, gt, temp, CenterComparator(splitAxis)); |
---|
767 | |
---|
768 | // Choose the split location to be the center of whatever fell in the center |
---|
769 | splitLocation = node->valueArray[0]->center[splitAxis]; |
---|
770 | |
---|
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; |
---|
780 | } |
---|
781 | } |
---|
782 | |
---|
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; |
---|
790 | } |
---|
791 | } |
---|
792 | |
---|
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; |
---|
800 | } |
---|
801 | } |
---|
802 | |
---|
803 | // Note: numMeanSplits may have been increased by the code in the previous case above in order to |
---|
804 | // force a re-partition. |
---|
805 | |
---|
806 | if (numMeanSplits > 0) { |
---|
807 | // Split along the mean |
---|
808 | splitLocation = (bounds.high()[splitAxis] + |
---|
809 | bounds.low()[splitAxis]) / 2.0; |
---|
810 | |
---|
811 | source.partition(NULL, lt, node->valueArray, gt, Comparator(splitAxis, splitLocation)); |
---|
812 | |
---|
813 | // The Comparator ensures that elements are strictly on the correct side of the split |
---|
814 | } |
---|
815 | |
---|
816 | |
---|
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); |
---|
824 | } |
---|
825 | |
---|
826 | for (int i = 0; i < gt.size(); ++i) { |
---|
827 | const AABox& bounds = gt[i]->bounds; |
---|
828 | debugAssert(bounds.low()[splitAxis] > splitLocation); |
---|
829 | } |
---|
830 | |
---|
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); |
---|
835 | } |
---|
836 | # endif |
---|
837 | |
---|
838 | // The source array is no longer needed |
---|
839 | source.clear(); |
---|
840 | |
---|
841 | node->splitAxis = splitAxis; |
---|
842 | node->splitLocation = splitLocation; |
---|
843 | |
---|
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); |
---|
850 | } |
---|
851 | |
---|
852 | if (lt.size() > 0) { |
---|
853 | node->child[0] = makeNode(lt, valuesPerNode, numMeanSplits - 1, temp); |
---|
854 | } |
---|
855 | |
---|
856 | if (gt.size() > 0) { |
---|
857 | node->child[1] = makeNode(gt, valuesPerNode, numMeanSplits - 1, temp); |
---|
858 | } |
---|
859 | |
---|
860 | } |
---|
861 | |
---|
862 | return node; |
---|
863 | } |
---|
864 | |
---|
865 | /** |
---|
866 | Recursively clone the passed in node tree, setting |
---|
867 | pointers for members in the memberTable as appropriate. |
---|
868 | called by the assignment operator. |
---|
869 | */ |
---|
870 | Node* cloneTree(Node* src) { |
---|
871 | Node* dst = new Node(*src); |
---|
872 | |
---|
873 | // Make back pointers |
---|
874 | for (int i = 0; i < dst->valueArray.size(); ++i) { |
---|
875 | memberTable.set(Member(dst->valueArray[i]), dst); |
---|
876 | } |
---|
877 | |
---|
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]); |
---|
882 | } |
---|
883 | } |
---|
884 | |
---|
885 | return dst; |
---|
886 | } |
---|
887 | |
---|
888 | /** |
---|
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. |
---|
891 | */ |
---|
892 | typedef _internal::Indirector<_AABSPTree::Handle<T> > Member; |
---|
893 | |
---|
894 | typedef Table<Member, Node*> MemberTable; |
---|
895 | |
---|
896 | /** Maps members to the node containing them */ |
---|
897 | MemberTable memberTable; |
---|
898 | |
---|
899 | Node* root; |
---|
900 | |
---|
901 | public: |
---|
902 | |
---|
903 | /** To construct a balanced tree, insert the elements and then call |
---|
904 | AABSPTree::balance(). */ |
---|
905 | AABSPTree() : root(NULL) {} |
---|
906 | |
---|
907 | |
---|
908 | AABSPTree(const AABSPTree& src) : root(NULL) { |
---|
909 | *this = src; |
---|
910 | } |
---|
911 | |
---|
912 | |
---|
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; |
---|
918 | } |
---|
919 | |
---|
920 | |
---|
921 | ~AABSPTree() { |
---|
922 | clear(); |
---|
923 | } |
---|
924 | |
---|
925 | /** |
---|
926 | Throws out all elements of the set. |
---|
927 | */ |
---|
928 | void clear() { |
---|
929 | typedef typename Table<_internal::Indirector<_AABSPTree::Handle<T> >, Node* >::Iterator It; |
---|
930 | |
---|
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; |
---|
938 | } |
---|
939 | memberTable.clear(); |
---|
940 | |
---|
941 | // Delete the tree structure itself |
---|
942 | delete root; |
---|
943 | root = NULL; |
---|
944 | } |
---|
945 | |
---|
946 | size_t size() const { |
---|
947 | return memberTable.size(); |
---|
948 | } |
---|
949 | |
---|
950 | /** |
---|
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. |
---|
954 | */ |
---|
955 | void insert(const T& value) { |
---|
956 | if (contains(value)) { |
---|
957 | // Already in the set |
---|
958 | return; |
---|
959 | } |
---|
960 | |
---|
961 | _AABSPTree::Handle<T>* h = new _AABSPTree::Handle<T>(value); |
---|
962 | |
---|
963 | if (root == NULL) { |
---|
964 | // This is the first node; create a root node |
---|
965 | root = new Node(); |
---|
966 | } |
---|
967 | |
---|
968 | Node* node = root->findDeepestContainingNode(h->bounds); |
---|
969 | |
---|
970 | // Insert into the node |
---|
971 | node->valueArray.append(h); |
---|
972 | node->boundsArray.append(h->bounds); |
---|
973 | |
---|
974 | // Insert into the node table |
---|
975 | Member m(h); |
---|
976 | memberTable.set(m, node); |
---|
977 | } |
---|
978 | |
---|
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); |
---|
1000 | } |
---|
1001 | |
---|
1002 | } else { |
---|
1003 | // Insert at appropriate tree depth. |
---|
1004 | for (int i = 0; i < valueArray.size(); ++i) { |
---|
1005 | insert(valueArray[i]); |
---|
1006 | } |
---|
1007 | } |
---|
1008 | } |
---|
1009 | |
---|
1010 | |
---|
1011 | /** |
---|
1012 | Returns true if this object is in the set, otherwise |
---|
1013 | returns false. O(1) time. |
---|
1014 | */ |
---|
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)); |
---|
1019 | } |
---|
1020 | |
---|
1021 | |
---|
1022 | /** |
---|
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. |
---|
1026 | |
---|
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. |
---|
1031 | */ |
---|
1032 | void remove(const T& value) { |
---|
1033 | debugAssertM(contains(value), |
---|
1034 | "Tried to remove an element from a " |
---|
1035 | "AABSPTree that was not present"); |
---|
1036 | |
---|
1037 | // Get the list of elements at the node |
---|
1038 | _AABSPTree::Handle<T> h(value); |
---|
1039 | Member m(&h); |
---|
1040 | |
---|
1041 | Array<_AABSPTree::Handle<T> * >& list = memberTable[m]->valueArray; |
---|
1042 | |
---|
1043 | _AABSPTree::Handle<T>* ptr = NULL; |
---|
1044 | |
---|
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]; |
---|
1051 | |
---|
1052 | // Remove the handle from the node |
---|
1053 | list.fastRemove(i); |
---|
1054 | |
---|
1055 | // Remove the corresponding bounds |
---|
1056 | memberTable[m]->boundsArray.fastRemove(i); |
---|
1057 | break; |
---|
1058 | } |
---|
1059 | } |
---|
1060 | |
---|
1061 | // Remove the member |
---|
1062 | memberTable.remove(m); |
---|
1063 | |
---|
1064 | // Delete the handle data structure |
---|
1065 | delete ptr; |
---|
1066 | ptr = NULL; |
---|
1067 | } |
---|
1068 | |
---|
1069 | |
---|
1070 | /** |
---|
1071 | If the element is in the set, it is removed. |
---|
1072 | The element is then inserted. |
---|
1073 | |
---|
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. |
---|
1080 | */ |
---|
1081 | void update(const T& value) { |
---|
1082 | if (contains(value)) { |
---|
1083 | remove(value); |
---|
1084 | } |
---|
1085 | insert(value); |
---|
1086 | } |
---|
1087 | |
---|
1088 | |
---|
1089 | /** |
---|
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). |
---|
1094 | |
---|
1095 | @param valuesPerNode Maximum number of elements to put at |
---|
1096 | a node. |
---|
1097 | |
---|
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. |
---|
1103 | |
---|
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. |
---|
1109 | */ |
---|
1110 | void balance(int valuesPerNode = 5, int numMeanSplits = 3) { |
---|
1111 | if (root == NULL) { |
---|
1112 | // Tree is empty |
---|
1113 | return; |
---|
1114 | } |
---|
1115 | |
---|
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); |
---|
1121 | |
---|
1122 | // Delete the child; this will delete all structure below it |
---|
1123 | delete root->child[c]; |
---|
1124 | root->child[c] = NULL; |
---|
1125 | } |
---|
1126 | } |
---|
1127 | |
---|
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); |
---|
1133 | |
---|
1134 | // Throw away the old root node |
---|
1135 | delete oldRoot; |
---|
1136 | oldRoot = NULL; |
---|
1137 | |
---|
1138 | // Walk the tree, assigning splitBounds. We start with unbounded |
---|
1139 | // space. This will override the current member table. |
---|
1140 | root->assignSplitBounds(AABox::maxFinite()); |
---|
1141 | |
---|
1142 | # ifdef _DEBUG |
---|
1143 | // Ensure that the balanced tree is till correct |
---|
1144 | root->verifyNode(Vector3::minFinite(), Vector3::maxFinite()); |
---|
1145 | # endif |
---|
1146 | } |
---|
1147 | |
---|
1148 | protected: |
---|
1149 | |
---|
1150 | /** |
---|
1151 | @param parentMask The mask that this node returned from culledBy. |
---|
1152 | */ |
---|
1153 | static void getIntersectingMembers( |
---|
1154 | const Array<Plane>& plane, |
---|
1155 | Array<T>& members, |
---|
1156 | Node* node, |
---|
1157 | uint32 parentMask) { |
---|
1158 | |
---|
1159 | int dummy; |
---|
1160 | |
---|
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); |
---|
1165 | } |
---|
1166 | |
---|
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); |
---|
1171 | } |
---|
1172 | } |
---|
1173 | } else { |
---|
1174 | |
---|
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); |
---|
1179 | } |
---|
1180 | } |
---|
1181 | |
---|
1182 | uint32 childMask = 0xFFFFFF; |
---|
1183 | |
---|
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); |
---|
1190 | } |
---|
1191 | } |
---|
1192 | } |
---|
1193 | } |
---|
1194 | |
---|
1195 | public: |
---|
1196 | |
---|
1197 | /** |
---|
1198 | Returns all members inside the set of planes. |
---|
1199 | @param members The results are appended to this array. |
---|
1200 | */ |
---|
1201 | void getIntersectingMembers(const Array<Plane>& plane, Array<T>& members) const { |
---|
1202 | if (root == NULL) { |
---|
1203 | return; |
---|
1204 | } |
---|
1205 | |
---|
1206 | getIntersectingMembers(plane, members, root, 0xFFFFFF); |
---|
1207 | } |
---|
1208 | |
---|
1209 | /** |
---|
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. |
---|
1213 | |
---|
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. |
---|
1221 | */ |
---|
1222 | void getIntersectingMembers(const GCamera::Frustum& frustum, Array<T>& members) const { |
---|
1223 | Array<Plane> plane; |
---|
1224 | |
---|
1225 | for (int i = 0; i < frustum.faceArray.size(); ++i) { |
---|
1226 | plane.append(frustum.faceArray[i].plane); |
---|
1227 | } |
---|
1228 | |
---|
1229 | getIntersectingMembers(plane, members); |
---|
1230 | } |
---|
1231 | |
---|
1232 | /** |
---|
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. |
---|
1236 | */ |
---|
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>; |
---|
1245 | |
---|
1246 | /** True if this is the "end" iterator instance */ |
---|
1247 | bool isEnd; |
---|
1248 | |
---|
1249 | /** The box that we're testing against. */ |
---|
1250 | AABox box; |
---|
1251 | |
---|
1252 | /** Node that we're currently looking at. Undefined if isEnd |
---|
1253 | is true. */ |
---|
1254 | Node* node; |
---|
1255 | |
---|
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; |
---|
1262 | |
---|
1263 | /** The next index of current->valueArray to return. |
---|
1264 | Undefined when isEnd is true.*/ |
---|
1265 | int nextValueArrayIndex; |
---|
1266 | |
---|
1267 | BoxIntersectionIterator() : isEnd(true) {} |
---|
1268 | |
---|
1269 | BoxIntersectionIterator(const AABox& b, const Node* root) : |
---|
1270 | isEnd(root == NULL), box(b), |
---|
1271 | node(const_cast<Node*>(root)), nextValueArrayIndex(-1) { |
---|
1272 | |
---|
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); |
---|
1279 | } |
---|
1280 | |
---|
1281 | public: |
---|
1282 | |
---|
1283 | inline bool operator!=(const BoxIntersectionIterator& other) const { |
---|
1284 | return ! (*this == other); |
---|
1285 | } |
---|
1286 | |
---|
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; |
---|
1300 | } |
---|
1301 | |
---|
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; |
---|
1306 | } |
---|
1307 | } |
---|
1308 | |
---|
1309 | // We failed to find a difference; they must be the same |
---|
1310 | return true; |
---|
1311 | } |
---|
1312 | } |
---|
1313 | |
---|
1314 | /** |
---|
1315 | Pre increment. |
---|
1316 | */ |
---|
1317 | BoxIntersectionIterator& operator++() { |
---|
1318 | ++nextValueArrayIndex; |
---|
1319 | |
---|
1320 | bool foundIntersection = false; |
---|
1321 | while (! isEnd && ! foundIntersection) { |
---|
1322 | |
---|
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. |
---|
1329 | |
---|
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]); |
---|
1335 | } |
---|
1336 | |
---|
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]); |
---|
1342 | } |
---|
1343 | |
---|
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; |
---|
1352 | } |
---|
1353 | } |
---|
1354 | |
---|
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. |
---|
1363 | } |
---|
1364 | } |
---|
1365 | } |
---|
1366 | |
---|
1367 | return *this; |
---|
1368 | } |
---|
1369 | |
---|
1370 | private: |
---|
1371 | /** |
---|
1372 | Post increment (much slower than preincrement!). Intentionally overloaded to preclude accidentally slow code. |
---|
1373 | */ |
---|
1374 | BoxIntersectionIterator operator++(int); |
---|
1375 | /*{ |
---|
1376 | BoxIntersectionIterator old = *this; |
---|
1377 | ++this; |
---|
1378 | return old; |
---|
1379 | }*/ |
---|
1380 | |
---|
1381 | public: |
---|
1382 | |
---|
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; |
---|
1388 | } |
---|
1389 | |
---|
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); |
---|
1395 | } |
---|
1396 | |
---|
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); |
---|
1402 | } |
---|
1403 | }; |
---|
1404 | |
---|
1405 | |
---|
1406 | /** |
---|
1407 | Iterates through the members that intersect the box |
---|
1408 | */ |
---|
1409 | BoxIntersectionIterator beginBoxIntersection(const AABox& box) const { |
---|
1410 | return BoxIntersectionIterator(box, root); |
---|
1411 | } |
---|
1412 | |
---|
1413 | BoxIntersectionIterator endBoxIntersection() const { |
---|
1414 | // The "end" iterator instance |
---|
1415 | return BoxIntersectionIterator(); |
---|
1416 | } |
---|
1417 | |
---|
1418 | /** |
---|
1419 | Appends all members whose bounds intersect the box. |
---|
1420 | See also AABSPTree::beginBoxIntersection. |
---|
1421 | */ |
---|
1422 | void getIntersectingMembers(const AABox& box, Array<T>& members) const { |
---|
1423 | if (root == NULL) { |
---|
1424 | return; |
---|
1425 | } |
---|
1426 | root->getIntersectingMembers(box, Sphere(Vector3::zero(), 0), members, false); |
---|
1427 | } |
---|
1428 | |
---|
1429 | |
---|
1430 | /** |
---|
1431 | Invoke a callback for every member along a ray until the closest intersection is found. |
---|
1432 | |
---|
1433 | @param callback either a function or an instance of a class with an overloaded operator() of the form: |
---|
1434 | |
---|
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: |
---|
1438 | |
---|
1439 | <pre> |
---|
1440 | class Entity { |
---|
1441 | public: |
---|
1442 | |
---|
1443 | void intersect(const Ray& ray, float& maxDist, Vector3& outLocation, Vector3& outNormal) { |
---|
1444 | float d = maxDist; |
---|
1445 | |
---|
1446 | // ... search for intersection distance d |
---|
1447 | |
---|
1448 | if ((d > 0) && (d < maxDist)) { |
---|
1449 | // Intersection occured |
---|
1450 | maxDist = d; |
---|
1451 | outLocation = ...; |
---|
1452 | outNormal = ...; |
---|
1453 | } |
---|
1454 | } |
---|
1455 | }; |
---|
1456 | |
---|
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; |
---|
1463 | |
---|
1464 | void operator()(const Ray& ray, const Entity* entity, float& distance) { |
---|
1465 | entity->intersect(ray, distance, hitLocation, hitNormal); |
---|
1466 | } |
---|
1467 | }; |
---|
1468 | |
---|
1469 | AABSPTree<Entity*> scene; |
---|
1470 | |
---|
1471 | Intersection intersection; |
---|
1472 | float distance = inf(); |
---|
1473 | scene.intersectRay(camera.worldRay(x, y), intersection, distance); |
---|
1474 | </pre> |
---|
1475 | |
---|
1476 | |
---|
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. |
---|
1479 | |
---|
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. |
---|
1482 | */ |
---|
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 { |
---|
1490 | |
---|
1491 | root->intersectRay(ray, intersectCallback, distance, pStopAtFirstHit, intersectCallbackIsFast); |
---|
1492 | |
---|
1493 | } |
---|
1494 | |
---|
1495 | |
---|
1496 | /** |
---|
1497 | @param members The results are appended to this array. |
---|
1498 | */ |
---|
1499 | void getIntersectingMembers(const Sphere& sphere, Array<T>& members) const { |
---|
1500 | if (root == NULL) { |
---|
1501 | return; |
---|
1502 | } |
---|
1503 | |
---|
1504 | AABox box; |
---|
1505 | sphere.getBounds(box); |
---|
1506 | root->getIntersectingMembers(box, sphere, members, true); |
---|
1507 | |
---|
1508 | } |
---|
1509 | #if 0 |
---|
1510 | /** |
---|
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. |
---|
1514 | */ |
---|
1515 | void serializeStructure(BinaryOutput& bo) const { |
---|
1516 | Node::serializeStructure(root, bo); |
---|
1517 | } |
---|
1518 | |
---|
1519 | /** Clears the member table */ |
---|
1520 | void deserializeStructure(BinaryInput& bi) { |
---|
1521 | clear(); |
---|
1522 | root = Node::deserializeStructure(bi); |
---|
1523 | } |
---|
1524 | #endif |
---|
1525 | /** |
---|
1526 | Returns an array of all members of the set. See also AABSPTree::begin. |
---|
1527 | */ |
---|
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); |
---|
1533 | } |
---|
1534 | } |
---|
1535 | |
---|
1536 | |
---|
1537 | /** |
---|
1538 | C++ STL style iterator variable. See begin(). |
---|
1539 | Overloads the -> (dereference) operator, so this acts like a pointer |
---|
1540 | to the current member. |
---|
1541 | */ |
---|
1542 | class Iterator { |
---|
1543 | private: |
---|
1544 | friend class AABSPTree<T>; |
---|
1545 | |
---|
1546 | // Note: this is a Table iterator, we are currently defining |
---|
1547 | // Set iterator |
---|
1548 | typename Table<Member, Node*>::Iterator it; |
---|
1549 | |
---|
1550 | Iterator(const typename Table<Member, Node*>::Iterator& it) : it(it) {} |
---|
1551 | |
---|
1552 | public: |
---|
1553 | |
---|
1554 | inline bool operator!=(const Iterator& other) const { |
---|
1555 | return !(*this == other); |
---|
1556 | } |
---|
1557 | |
---|
1558 | bool operator==(const Iterator& other) const { |
---|
1559 | return it == other.it; |
---|
1560 | } |
---|
1561 | |
---|
1562 | /** |
---|
1563 | Pre increment. |
---|
1564 | */ |
---|
1565 | Iterator& operator++() { |
---|
1566 | ++it; |
---|
1567 | return *this; |
---|
1568 | } |
---|
1569 | |
---|
1570 | private: |
---|
1571 | /** |
---|
1572 | Post increment (slower than preincrement). Intentionally unimplemented to prevent slow code. |
---|
1573 | */ |
---|
1574 | Iterator operator++(int);/* { |
---|
1575 | Iterator old = *this; |
---|
1576 | ++(*this); |
---|
1577 | return old; |
---|
1578 | }*/ |
---|
1579 | public: |
---|
1580 | |
---|
1581 | const T& operator*() const { |
---|
1582 | return it->key.handle->value; |
---|
1583 | } |
---|
1584 | |
---|
1585 | T* operator->() const { |
---|
1586 | return &(it->key.handle->value); |
---|
1587 | } |
---|
1588 | |
---|
1589 | operator T*() const { |
---|
1590 | return &(it->key.handle->value); |
---|
1591 | } |
---|
1592 | }; |
---|
1593 | |
---|
1594 | |
---|
1595 | /** |
---|
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. |
---|
1600 | */ |
---|
1601 | Iterator begin() const { |
---|
1602 | return Iterator(memberTable.begin()); |
---|
1603 | } |
---|
1604 | |
---|
1605 | |
---|
1606 | /** |
---|
1607 | C++ STL style iterator method. Returns one after the last iterator |
---|
1608 | element. |
---|
1609 | */ |
---|
1610 | Iterator end() const { |
---|
1611 | return Iterator(memberTable.end()); |
---|
1612 | } |
---|
1613 | }; |
---|
1614 | |
---|
1615 | } |
---|
1616 | |
---|
1617 | #endif |
---|
1618 | |
---|
1619 | |
---|
1620 | |
---|