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 | } |
---|