diff options
Diffstat (limited to 'libraries/ode-0.9/ode/src/collision_quadtreespace.cpp')
-rw-r--r-- | libraries/ode-0.9/ode/src/collision_quadtreespace.cpp | 584 |
1 files changed, 584 insertions, 0 deletions
diff --git a/libraries/ode-0.9/ode/src/collision_quadtreespace.cpp b/libraries/ode-0.9/ode/src/collision_quadtreespace.cpp new file mode 100644 index 0000000..86a1833 --- /dev/null +++ b/libraries/ode-0.9/ode/src/collision_quadtreespace.cpp | |||
@@ -0,0 +1,584 @@ | |||
1 | /************************************************************************* | ||
2 | * * | ||
3 | * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * | ||
4 | * All rights reserved. Email: russ@q12.org Web: www.q12.org * | ||
5 | * * | ||
6 | * This library is free software; you can redistribute it and/or * | ||
7 | * modify it under the terms of EITHER: * | ||
8 | * (1) The GNU Lesser General Public License as published by the Free * | ||
9 | * Software Foundation; either version 2.1 of the License, or (at * | ||
10 | * your option) any later version. The text of the GNU Lesser * | ||
11 | * General Public License is included with this library in the * | ||
12 | * file LICENSE.TXT. * | ||
13 | * (2) The BSD-style license that is included with this library in * | ||
14 | * the file LICENSE-BSD.TXT. * | ||
15 | * * | ||
16 | * This library is distributed in the hope that it will be useful, * | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * | ||
19 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. * | ||
20 | * * | ||
21 | *************************************************************************/ | ||
22 | |||
23 | // QuadTreeSpace by Erwin de Vries. | ||
24 | |||
25 | #include <ode/common.h> | ||
26 | #include <ode/matrix.h> | ||
27 | #include <ode/collision_space.h> | ||
28 | #include <ode/collision.h> | ||
29 | #include "collision_kernel.h" | ||
30 | |||
31 | #include "collision_space_internal.h" | ||
32 | |||
33 | |||
34 | #define AXIS0 0 | ||
35 | #define AXIS1 1 | ||
36 | #define UP 2 | ||
37 | |||
38 | //#define DRAWBLOCKS | ||
39 | |||
40 | const int SPLITAXIS = 2; | ||
41 | const int SPLITS = SPLITAXIS * SPLITAXIS; | ||
42 | |||
43 | #define GEOM_ENABLED(g) (g)->gflags & GEOM_ENABLED | ||
44 | |||
45 | class Block{ | ||
46 | public: | ||
47 | dReal MinX, MaxX; | ||
48 | dReal MinZ, MaxZ; | ||
49 | |||
50 | dGeomID First; | ||
51 | int GeomCount; | ||
52 | |||
53 | Block* Parent; | ||
54 | Block* Children; | ||
55 | |||
56 | void Create(const dVector3 Center, const dVector3 Extents, Block* Parent, int Depth, Block*& Blocks); | ||
57 | |||
58 | void Collide(void* UserData, dNearCallback* Callback); | ||
59 | void Collide(dGeomID Object, dGeomID g, void* UserData, dNearCallback* Callback); | ||
60 | |||
61 | void CollideLocal(dGeomID Object, void* UserData, dNearCallback* Callback); | ||
62 | |||
63 | void AddObject(dGeomID Object); | ||
64 | void DelObject(dGeomID Object); | ||
65 | void Traverse(dGeomID Object); | ||
66 | |||
67 | bool Inside(const dReal* AABB); | ||
68 | |||
69 | Block* GetBlock(const dReal* AABB); | ||
70 | Block* GetBlockChild(const dReal* AABB); | ||
71 | }; | ||
72 | |||
73 | |||
74 | #ifdef DRAWBLOCKS | ||
75 | #include "..\..\Include\drawstuff\\drawstuff.h" | ||
76 | |||
77 | static void DrawBlock(Block* Block){ | ||
78 | dVector3 v[8]; | ||
79 | v[0][AXIS0] = Block->MinX; | ||
80 | v[0][UP] = REAL(-1.0); | ||
81 | v[0][AXIS1] = Block->MinZ; | ||
82 | |||
83 | v[1][AXIS0] = Block->MinX; | ||
84 | v[1][UP] = REAL(-1.0); | ||
85 | v[1][AXIS1] = Block->MaxZ; | ||
86 | |||
87 | v[2][AXIS0] = Block->MaxX; | ||
88 | v[2][UP] = REAL(-1.0); | ||
89 | v[2][AXIS1] = Block->MinZ; | ||
90 | |||
91 | v[3][AXIS0] = Block->MaxX; | ||
92 | v[3][UP] = REAL(-1.0); | ||
93 | v[3][AXIS1] = Block->MaxZ; | ||
94 | |||
95 | v[4][AXIS0] = Block->MinX; | ||
96 | v[4][UP] = REAL(1.0); | ||
97 | v[4][AXIS1] = Block->MinZ; | ||
98 | |||
99 | v[5][AXIS0] = Block->MinX; | ||
100 | v[5][UP] = REAL(1.0); | ||
101 | v[5][AXIS1] = Block->MaxZ; | ||
102 | |||
103 | v[6][AXIS0] = Block->MaxX; | ||
104 | v[6][UP] = REAL(1.0); | ||
105 | v[6][AXIS1] = Block->MinZ; | ||
106 | |||
107 | v[7][AXIS0] = Block->MaxX; | ||
108 | v[7][UP] = REAL(1.0); | ||
109 | v[7][AXIS1] = Block->MaxZ; | ||
110 | |||
111 | // Bottom | ||
112 | dsDrawLine(v[0], v[1]); | ||
113 | dsDrawLine(v[1], v[3]); | ||
114 | dsDrawLine(v[3], v[2]); | ||
115 | dsDrawLine(v[2], v[0]); | ||
116 | |||
117 | // Top | ||
118 | dsDrawLine(v[4], v[5]); | ||
119 | dsDrawLine(v[5], v[7]); | ||
120 | dsDrawLine(v[7], v[6]); | ||
121 | dsDrawLine(v[6], v[4]); | ||
122 | |||
123 | // Sides | ||
124 | dsDrawLine(v[0], v[4]); | ||
125 | dsDrawLine(v[1], v[5]); | ||
126 | dsDrawLine(v[2], v[6]); | ||
127 | dsDrawLine(v[3], v[7]); | ||
128 | } | ||
129 | #endif //DRAWBLOCKS | ||
130 | |||
131 | |||
132 | void Block::Create(const dVector3 Center, const dVector3 Extents, Block* Parent, int Depth, Block*& Blocks){ | ||
133 | GeomCount = 0; | ||
134 | First = 0; | ||
135 | |||
136 | MinX = Center[AXIS0] - Extents[AXIS0]; | ||
137 | MaxX = Center[AXIS0] + Extents[AXIS0]; | ||
138 | |||
139 | MinZ = Center[AXIS1] - Extents[AXIS1]; | ||
140 | MaxZ = Center[AXIS1] + Extents[AXIS1]; | ||
141 | |||
142 | this->Parent = Parent; | ||
143 | if (Depth > 0){ | ||
144 | Children = Blocks; | ||
145 | Blocks += SPLITS; | ||
146 | |||
147 | dVector3 ChildExtents; | ||
148 | ChildExtents[AXIS0] = Extents[AXIS0] / SPLITAXIS; | ||
149 | ChildExtents[AXIS1] = Extents[AXIS1] / SPLITAXIS; | ||
150 | ChildExtents[UP] = Extents[UP]; | ||
151 | |||
152 | for (int i = 0; i < SPLITAXIS; i++){ | ||
153 | for (int j = 0; j < SPLITAXIS; j++){ | ||
154 | int Index = i * SPLITAXIS + j; | ||
155 | |||
156 | dVector3 ChildCenter; | ||
157 | ChildCenter[AXIS0] = Center[AXIS0] - Extents[AXIS0] + ChildExtents[AXIS0] + i * (ChildExtents[AXIS0] * 2); | ||
158 | ChildCenter[AXIS1] = Center[AXIS1] - Extents[AXIS1] + ChildExtents[AXIS1] + j * (ChildExtents[AXIS1] * 2); | ||
159 | ChildCenter[UP] = Center[UP]; | ||
160 | |||
161 | Children[Index].Create(ChildCenter, ChildExtents, this, Depth - 1, Blocks); | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | else Children = 0; | ||
166 | } | ||
167 | |||
168 | void Block::Collide(void* UserData, dNearCallback* Callback){ | ||
169 | #ifdef DRAWBLOCKS | ||
170 | DrawBlock(this); | ||
171 | #endif | ||
172 | // Collide the local list | ||
173 | dxGeom* g = First; | ||
174 | while (g){ | ||
175 | if (GEOM_ENABLED(g)){ | ||
176 | Collide(g, g->next, UserData, Callback); | ||
177 | } | ||
178 | g = g->next; | ||
179 | } | ||
180 | |||
181 | // Recurse for children | ||
182 | if (Children){ | ||
183 | for (int i = 0; i < SPLITS; i++){ | ||
184 | if (Children[i].GeomCount <= 1){ // Early out | ||
185 | continue; | ||
186 | } | ||
187 | Children[i].Collide(UserData, Callback); | ||
188 | } | ||
189 | } | ||
190 | } | ||
191 | |||
192 | void Block::Collide(dxGeom* g1, dxGeom* g2, void* UserData, dNearCallback* Callback){ | ||
193 | #ifdef DRAWBLOCKS | ||
194 | DrawBlock(this); | ||
195 | #endif | ||
196 | // Collide against local list | ||
197 | while (g2){ | ||
198 | if (GEOM_ENABLED(g2)){ | ||
199 | collideAABBs (g1, g2, UserData, Callback); | ||
200 | } | ||
201 | g2 = g2->next; | ||
202 | } | ||
203 | |||
204 | // Collide against children | ||
205 | if (Children){ | ||
206 | for (int i = 0; i < SPLITS; i++){ | ||
207 | // Early out for empty blocks | ||
208 | if (Children[i].GeomCount == 0){ | ||
209 | continue; | ||
210 | } | ||
211 | |||
212 | // Does the geom's AABB collide with the block? | ||
213 | // Dont do AABB tests for single geom blocks. | ||
214 | if (Children[i].GeomCount == 1 && Children[i].First){ | ||
215 | // | ||
216 | } | ||
217 | else if (true){ | ||
218 | if (g1->aabb[AXIS0 * 2 + 0] > Children[i].MaxX || | ||
219 | g1->aabb[AXIS0 * 2 + 1] < Children[i].MinX || | ||
220 | g1->aabb[AXIS1 * 2 + 0] > Children[i].MaxZ || | ||
221 | g1->aabb[AXIS1 * 2 + 1] < Children[i].MinZ) continue; | ||
222 | } | ||
223 | Children[i].Collide(g1, Children[i].First, UserData, Callback); | ||
224 | } | ||
225 | } | ||
226 | } | ||
227 | |||
228 | void Block::CollideLocal(dxGeom* g1, void* UserData, dNearCallback* Callback){ | ||
229 | // Collide against local list | ||
230 | dxGeom* g2 = First; | ||
231 | while (g2){ | ||
232 | if (GEOM_ENABLED(g2)){ | ||
233 | collideAABBs (g1, g2, UserData, Callback); | ||
234 | } | ||
235 | g2 = g2->next; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | void Block::AddObject(dGeomID Object){ | ||
240 | // Add the geom | ||
241 | Object->next = First; | ||
242 | First = Object; | ||
243 | Object->tome = (dxGeom**)this; | ||
244 | |||
245 | // Now traverse upwards to tell that we have a geom | ||
246 | Block* Block = this; | ||
247 | do{ | ||
248 | Block->GeomCount++; | ||
249 | Block = Block->Parent; | ||
250 | } | ||
251 | while (Block); | ||
252 | } | ||
253 | |||
254 | void Block::DelObject(dGeomID Object){ | ||
255 | // Del the geom | ||
256 | dxGeom* g = First; | ||
257 | dxGeom* Last = 0; | ||
258 | while (g){ | ||
259 | if (g == Object){ | ||
260 | if (Last){ | ||
261 | Last->next = g->next; | ||
262 | } | ||
263 | else First = g->next; | ||
264 | |||
265 | break; | ||
266 | } | ||
267 | Last = g; | ||
268 | g = g->next; | ||
269 | } | ||
270 | |||
271 | Object->tome = 0; | ||
272 | |||
273 | // Now traverse upwards to tell that we have lost a geom | ||
274 | Block* Block = this; | ||
275 | do{ | ||
276 | Block->GeomCount--; | ||
277 | Block = Block->Parent; | ||
278 | } | ||
279 | while (Block); | ||
280 | } | ||
281 | |||
282 | void Block::Traverse(dGeomID Object){ | ||
283 | Block* NewBlock = GetBlock(Object->aabb); | ||
284 | |||
285 | if (NewBlock != this){ | ||
286 | // Remove the geom from the old block and add it to the new block. | ||
287 | // This could be more optimal, but the loss should be very small. | ||
288 | DelObject(Object); | ||
289 | NewBlock->AddObject(Object); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | bool Block::Inside(const dReal* AABB){ | ||
294 | return AABB[AXIS0 * 2 + 0] >= MinX && AABB[AXIS0 * 2 + 1] <= MaxX && AABB[AXIS1 * 2 + 0] >= MinZ && AABB[AXIS1 * 2 + 1] <= MaxZ; | ||
295 | } | ||
296 | |||
297 | Block* Block::GetBlock(const dReal* AABB){ | ||
298 | if (Inside(AABB)){ | ||
299 | return GetBlockChild(AABB); // Child or this will have a good block | ||
300 | } | ||
301 | else if (Parent){ | ||
302 | return Parent->GetBlock(AABB); // Parent has a good block | ||
303 | } | ||
304 | else return this; // We are at the root, so we have little choice | ||
305 | } | ||
306 | |||
307 | Block* Block::GetBlockChild(const dReal* AABB){ | ||
308 | if (Children){ | ||
309 | for (int i = 0; i < SPLITS; i++){ | ||
310 | if (Children[i].Inside(AABB)){ | ||
311 | return Children[i].GetBlockChild(AABB); // Child will have good block | ||
312 | } | ||
313 | } | ||
314 | } | ||
315 | return this; // This is the best block | ||
316 | } | ||
317 | |||
318 | //**************************************************************************** | ||
319 | // quadtree space | ||
320 | |||
321 | struct dxQuadTreeSpace : public dxSpace{ | ||
322 | Block* Blocks; // Blocks[0] is the root | ||
323 | |||
324 | dArray<dxGeom*> DirtyList; | ||
325 | |||
326 | dxQuadTreeSpace(dSpaceID _space, dVector3 Center, dVector3 Extents, int Depth); | ||
327 | ~dxQuadTreeSpace(); | ||
328 | |||
329 | dxGeom* getGeom(int i); | ||
330 | |||
331 | void add(dxGeom* g); | ||
332 | void remove(dxGeom* g); | ||
333 | void dirty(dxGeom* g); | ||
334 | |||
335 | void computeAABB(); | ||
336 | |||
337 | void cleanGeoms(); | ||
338 | void collide(void* UserData, dNearCallback* Callback); | ||
339 | void collide2(void* UserData, dxGeom* g1, dNearCallback* Callback); | ||
340 | |||
341 | // Temp data | ||
342 | Block* CurrentBlock; // Only used while enumerating | ||
343 | int* CurrentChild; // Only used while enumerating | ||
344 | int CurrentLevel; // Only used while enumerating | ||
345 | dxGeom* CurrentObject; // Only used while enumerating | ||
346 | int CurrentIndex; | ||
347 | }; | ||
348 | |||
349 | dxQuadTreeSpace::dxQuadTreeSpace(dSpaceID _space, dVector3 Center, dVector3 Extents, int Depth) : dxSpace(_space){ | ||
350 | type = dQuadTreeSpaceClass; | ||
351 | |||
352 | int BlockCount = 0; | ||
353 | for (int i = 0; i <= Depth; i++){ | ||
354 | BlockCount += (int)pow((dReal)SPLITS, i); | ||
355 | } | ||
356 | |||
357 | Blocks = (Block*)dAlloc(BlockCount * sizeof(Block)); | ||
358 | Block* Blocks = this->Blocks + 1; // This pointer gets modified! | ||
359 | |||
360 | this->Blocks[0].Create(Center, Extents, 0, Depth, Blocks); | ||
361 | |||
362 | CurrentBlock = 0; | ||
363 | CurrentChild = (int*)dAlloc((Depth + 1) * sizeof(int)); | ||
364 | CurrentLevel = 0; | ||
365 | CurrentObject = 0; | ||
366 | CurrentIndex = -1; | ||
367 | |||
368 | // Init AABB. We initialize to infinity because it is not illegal for an object to be outside of the tree. Its simply inserted in the root block | ||
369 | aabb[0] = -dInfinity; | ||
370 | aabb[1] = dInfinity; | ||
371 | aabb[2] = -dInfinity; | ||
372 | aabb[3] = dInfinity; | ||
373 | aabb[4] = -dInfinity; | ||
374 | aabb[5] = dInfinity; | ||
375 | } | ||
376 | |||
377 | dxQuadTreeSpace::~dxQuadTreeSpace(){ | ||
378 | int Depth = 0; | ||
379 | Block* Current = &Blocks[0]; | ||
380 | while (Current){ | ||
381 | Depth++; | ||
382 | Current = Current->Children; | ||
383 | } | ||
384 | |||
385 | int BlockCount = 0; | ||
386 | for (int i = 0; i < Depth; i++){ | ||
387 | BlockCount += (int)pow((dReal)SPLITS, i); | ||
388 | } | ||
389 | |||
390 | dFree(Blocks, BlockCount * sizeof(Block)); | ||
391 | dFree(CurrentChild, (Depth + 1) * sizeof(int)); | ||
392 | } | ||
393 | |||
394 | dxGeom* dxQuadTreeSpace::getGeom(int Index){ | ||
395 | dUASSERT(Index >= 0 && Index < count, "index out of range"); | ||
396 | |||
397 | //@@@ | ||
398 | dDebug (0,"dxQuadTreeSpace::getGeom() not yet implemented"); | ||
399 | |||
400 | return 0; | ||
401 | |||
402 | // This doesnt work | ||
403 | |||
404 | /*if (CurrentIndex == Index){ | ||
405 | // Loop through all objects in the local list | ||
406 | CHILDRECURSE: | ||
407 | if (CurrentObject){ | ||
408 | dGeomID g = CurrentObject; | ||
409 | CurrentObject = CurrentObject->next; | ||
410 | CurrentIndex++; | ||
411 | |||
412 | #ifdef DRAWBLOCKS | ||
413 | DrawBlock(CurrentBlock); | ||
414 | #endif //DRAWBLOCKS | ||
415 | return g; | ||
416 | } | ||
417 | else{ | ||
418 | // Now lets loop through our children. Starting at index 0. | ||
419 | if (CurrentBlock->Children){ | ||
420 | CurrentChild[CurrentLevel] = 0; | ||
421 | PARENTRECURSE: | ||
422 | for (int& i = CurrentChild[CurrentLevel]; i < SPLITS; i++){ | ||
423 | if (CurrentBlock->Children[i].GeomCount == 0){ | ||
424 | continue; | ||
425 | } | ||
426 | CurrentBlock = &CurrentBlock->Children[i]; | ||
427 | CurrentObject = CurrentBlock->First; | ||
428 | |||
429 | i++; | ||
430 | |||
431 | CurrentLevel++; | ||
432 | goto CHILDRECURSE; | ||
433 | } | ||
434 | } | ||
435 | } | ||
436 | |||
437 | // Now lets go back to the parent so it can continue processing its other children. | ||
438 | if (CurrentBlock->Parent){ | ||
439 | CurrentBlock = CurrentBlock->Parent; | ||
440 | CurrentLevel--; | ||
441 | goto PARENTRECURSE; | ||
442 | } | ||
443 | } | ||
444 | else{ | ||
445 | CurrentBlock = &Blocks[0]; | ||
446 | CurrentLevel = 0; | ||
447 | CurrentObject = CurrentObject; | ||
448 | CurrentIndex = 0; | ||
449 | |||
450 | // Other states are already set | ||
451 | CurrentObject = CurrentBlock->First; | ||
452 | } | ||
453 | |||
454 | |||
455 | if (current_geom && current_index == Index - 1){ | ||
456 | //current_geom = current_geom->next; // next | ||
457 | current_index = Index; | ||
458 | return current_geom; | ||
459 | } | ||
460 | else for (int i = 0; i < Index; i++){ // this will be verrrrrrry slow | ||
461 | getGeom(i); | ||
462 | }*/ | ||
463 | |||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | void dxQuadTreeSpace::add(dxGeom* g){ | ||
468 | CHECK_NOT_LOCKED (this); | ||
469 | dAASSERT(g); | ||
470 | dUASSERT(g->parent_space == 0 && g->next == 0, "geom is already in a space"); | ||
471 | |||
472 | g->gflags |= GEOM_DIRTY | GEOM_AABB_BAD; | ||
473 | DirtyList.push(g); | ||
474 | |||
475 | // add | ||
476 | g->parent_space = this; | ||
477 | Blocks[0].GetBlock(g->aabb)->AddObject(g); // Add to best block | ||
478 | count++; | ||
479 | |||
480 | // enumerator has been invalidated | ||
481 | current_geom = 0; | ||
482 | |||
483 | dGeomMoved(this); | ||
484 | } | ||
485 | |||
486 | void dxQuadTreeSpace::remove(dxGeom* g){ | ||
487 | CHECK_NOT_LOCKED(this); | ||
488 | dAASSERT(g); | ||
489 | dUASSERT(g->parent_space == this,"object is not in this space"); | ||
490 | |||
491 | // remove | ||
492 | ((Block*)g->tome)->DelObject(g); | ||
493 | count--; | ||
494 | |||
495 | for (int i = 0; i < DirtyList.size(); i++){ | ||
496 | if (DirtyList[i] == g){ | ||
497 | DirtyList.remove(i); | ||
498 | // (mg) there can be multiple instances of a dirty object on stack be sure to remove ALL and not just first, for this we decrement i | ||
499 | --i; | ||
500 | } | ||
501 | } | ||
502 | |||
503 | // safeguard | ||
504 | g->next = 0; | ||
505 | g->tome = 0; | ||
506 | g->parent_space = 0; | ||
507 | |||
508 | // enumerator has been invalidated | ||
509 | current_geom = 0; | ||
510 | |||
511 | // the bounding box of this space (and that of all the parents) may have | ||
512 | // changed as a consequence of the removal. | ||
513 | dGeomMoved(this); | ||
514 | } | ||
515 | |||
516 | void dxQuadTreeSpace::dirty(dxGeom* g){ | ||
517 | DirtyList.push(g); | ||
518 | } | ||
519 | |||
520 | void dxQuadTreeSpace::computeAABB(){ | ||
521 | // | ||
522 | } | ||
523 | |||
524 | void dxQuadTreeSpace::cleanGeoms(){ | ||
525 | // compute the AABBs of all dirty geoms, and clear the dirty flags | ||
526 | lock_count++; | ||
527 | |||
528 | for (int i = 0; i < DirtyList.size(); i++){ | ||
529 | dxGeom* g = DirtyList[i]; | ||
530 | if (IS_SPACE(g)){ | ||
531 | ((dxSpace*)g)->cleanGeoms(); | ||
532 | } | ||
533 | g->recomputeAABB(); | ||
534 | g->gflags &= (~(GEOM_DIRTY|GEOM_AABB_BAD)); | ||
535 | |||
536 | ((Block*)g->tome)->Traverse(g); | ||
537 | } | ||
538 | DirtyList.setSize(0); | ||
539 | |||
540 | lock_count--; | ||
541 | } | ||
542 | |||
543 | void dxQuadTreeSpace::collide(void* UserData, dNearCallback* Callback){ | ||
544 | dAASSERT(Callback); | ||
545 | |||
546 | lock_count++; | ||
547 | cleanGeoms(); | ||
548 | |||
549 | Blocks[0].Collide(UserData, Callback); | ||
550 | |||
551 | lock_count--; | ||
552 | } | ||
553 | |||
554 | void dxQuadTreeSpace::collide2(void* UserData, dxGeom* g1, dNearCallback* Callback){ | ||
555 | dAASSERT(g1 && Callback); | ||
556 | |||
557 | lock_count++; | ||
558 | cleanGeoms(); | ||
559 | g1->recomputeAABB(); | ||
560 | |||
561 | if (g1->parent_space == this){ | ||
562 | // The block the geom is in | ||
563 | Block* CurrentBlock = (Block*)g1->tome; | ||
564 | |||
565 | // Collide against block and its children | ||
566 | CurrentBlock->Collide(g1, CurrentBlock->First, UserData, Callback); | ||
567 | |||
568 | // Collide against parents | ||
569 | while (true){ | ||
570 | CurrentBlock = CurrentBlock->Parent; | ||
571 | if (!CurrentBlock){ | ||
572 | break; | ||
573 | } | ||
574 | CurrentBlock->CollideLocal(g1, UserData, Callback); | ||
575 | } | ||
576 | } | ||
577 | else Blocks[0].Collide(g1, Blocks[0].First, UserData, Callback); | ||
578 | |||
579 | lock_count--; | ||
580 | } | ||
581 | |||
582 | dSpaceID dQuadTreeSpaceCreate(dxSpace* space, dVector3 Center, dVector3 Extents, int Depth){ | ||
583 | return new dxQuadTreeSpace(space, Center, Extents, Depth); | ||
584 | } | ||