1 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3 * OPCODE - Optimized Collision Detection
4 * Copyright (C) 2001 Pierre Terdiman
5 * Homepage: http://www.codercorner.com/Opcode.htm
7 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11 * Contains code for an AABB collider.
12 * \file OPC_AABBCollider.cpp
13 * \author Pierre Terdiman
14 * \date January, 1st, 2002
16 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
18 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
20 * Contains an AABB-vs-tree collider.
23 * \author Pierre Terdiman
25 * \date January, 1st, 2002
27 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
29 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
33 using namespace Opcode
;
35 #include "OPC_BoxBoxOverlap.h"
36 #include "OPC_TriBoxOverlap.h"
38 #define SET_CONTACT(prim_index, flag) \
39 /* Set contact status */ \
41 mTouchedPrimitives->Add(udword(prim_index));
43 //! AABB-triangle test
44 #define AABB_PRIM(prim_index, flag) \
45 /* Request vertices from the app */ \
46 VertexPointers VP; ConversionArea VC; mIMesh->GetTriangle(VP, prim_index, VC); \
47 mLeafVerts[0] = *VP.Vertex[0]; \
48 mLeafVerts[1] = *VP.Vertex[1]; \
49 mLeafVerts[2] = *VP.Vertex[2]; \
50 /* Perform triangle-box overlap test */ \
53 SET_CONTACT(prim_index, flag) \
56 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
60 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
61 AABBCollider::AABBCollider()
65 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
69 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
70 AABBCollider::~AABBCollider()
74 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
76 * Generic collision query for generic OPCODE models. After the call, access the results:
77 * - with GetContactStatus()
78 * - with GetNbTouchedPrimitives()
79 * - with GetTouchedPrimitives()
81 * \param cache [in/out] a box cache
82 * \param box [in] collision AABB in world space
83 * \param model [in] Opcode model to collide with
84 * \return true if success
85 * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
87 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
88 bool AABBCollider::Collide(AABBCache
& cache
, const CollisionAABB
& box
, const Model
& model
)
91 if(!Setup(&model
)) return false;
93 // Init collision query
94 if(InitQuery(cache
, box
)) return true;
96 if(!model
.HasLeafNodes())
98 if(model
.IsQuantized())
100 const AABBQuantizedNoLeafTree
* Tree
= static_cast<const AABBQuantizedNoLeafTree
*>(model
.GetTree());
102 // Setup dequantization coeffs
103 mCenterCoeff
= Tree
->mCenterCoeff
;
104 mExtentsCoeff
= Tree
->mExtentsCoeff
;
106 // Perform collision query
107 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree
->GetNodes());
108 else _Collide(Tree
->GetNodes());
112 const AABBNoLeafTree
* Tree
= static_cast<const AABBNoLeafTree
*>(model
.GetTree());
114 // Perform collision query
115 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree
->GetNodes());
116 else _Collide(Tree
->GetNodes());
121 if(model
.IsQuantized())
123 const AABBQuantizedTree
* Tree
= static_cast<const AABBQuantizedTree
*>(model
.GetTree());
125 // Setup dequantization coeffs
126 mCenterCoeff
= Tree
->mCenterCoeff
;
127 mExtentsCoeff
= Tree
->mExtentsCoeff
;
129 // Perform collision query
130 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree
->GetNodes());
131 else _Collide(Tree
->GetNodes());
135 const AABBCollisionTree
* Tree
= static_cast<const AABBCollisionTree
*>(model
.GetTree());
137 // Perform collision query
138 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree
->GetNodes());
139 else _Collide(Tree
->GetNodes());
145 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
147 * Initializes a collision query :
148 * - reset stats & contact status
149 * - check temporal coherence
151 * \param cache [in/out] a box cache
152 * \param box [in] AABB in world space
153 * \return TRUE if we can return immediately
155 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
156 BOOL
AABBCollider::InitQuery(AABBCache
& cache
, const CollisionAABB
& box
)
158 // 1) Call the base method
159 VolumeCollider::InitQuery();
161 // 2) Keep track of the query box
164 // 3) Setup destination pointer
165 mTouchedPrimitives
= &cache
.TouchedPrimitives
;
167 // 4) Special case: 1-triangle meshes [Opcode 1.3]
168 if(mCurrentModel
&& mCurrentModel
->HasSingleNode())
170 if(!SkipPrimitiveTests())
172 // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
173 mTouchedPrimitives
->Reset();
175 // Perform overlap test between the unique triangle and the box (and set contact status if needed)
176 AABB_PRIM(udword(0), OPC_CONTACT
)
178 // Return immediately regardless of status
183 // 5) Check temporal coherence :
184 if(TemporalCoherenceEnabled())
186 // Here we use temporal coherence
187 // => check results from previous frame before performing the collision query
188 if(FirstContactEnabled())
190 // We're only interested in the first contact found => test the unique previously touched face
191 if(mTouchedPrimitives
->GetNbEntries())
193 // Get index of previously touched face = the first entry in the array
194 udword PreviouslyTouchedFace
= mTouchedPrimitives
->GetEntry(0);
196 // Then reset the array:
197 // - if the overlap test below is successful, the index we'll get added back anyway
198 // - if it isn't, then the array should be reset anyway for the normal query
199 mTouchedPrimitives
->Reset();
201 // Perform overlap test between the cached triangle and the box (and set contact status if needed)
202 AABB_PRIM(PreviouslyTouchedFace
, OPC_TEMPORAL_CONTACT
)
204 // Return immediately if possible
205 if(GetContactStatus()) return TRUE
;
207 // else no face has been touched during previous query
208 // => we'll have to perform a normal query
212 // We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious):
213 if(IsCacheValid(cache
) && mBox
.IsInside(cache
.FatBox
))
215 // - if N is included in P, return previous list
216 // => we simply leave the list (mTouchedFaces) unchanged
218 // Set contact status if needed
219 if(mTouchedPrimitives
->GetNbEntries()) mFlags
|= OPC_TEMPORAL_CONTACT
;
221 // In any case we don't need to do a query
226 // - else do the query using a fat N
228 // Reset cache since we'll about to perform a real query
229 mTouchedPrimitives
->Reset();
231 // Make a fat box so that coherence will work for subsequent frames
232 mBox
.mExtents
*= cache
.FatCoeff
;
234 // Update cache with query data (signature for cached faces)
241 // Here we don't use temporal coherence => do a normal query
242 mTouchedPrimitives
->Reset();
245 // 5) Precompute min & max bounds if needed
246 mMin
= box
.mCenter
- box
.mExtents
;
247 mMax
= box
.mCenter
+ box
.mExtents
;
252 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
254 * Collision query for vanilla AABB trees.
255 * \param cache [in/out] a box cache
256 * \param box [in] collision AABB in world space
257 * \param tree [in] AABB tree
258 * \return true if success
260 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
261 bool AABBCollider::Collide(AABBCache
& cache
, const CollisionAABB
& box
, const AABBTree
* tree
)
263 // This is typically called for a scene tree, full of -AABBs-, not full of triangles.
264 // So we don't really have "primitives" to deal with. Hence it doesn't work with
265 // "FirstContact" + "TemporalCoherence".
266 ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) );
269 if(!tree
) return false;
271 // Init collision query
272 if(InitQuery(cache
, box
)) return true;
274 // Perform collision query
280 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
282 * Checks the AABB completely contains the box. In which case we can end the query sooner.
283 * \param bc [in] box center
284 * \param be [in] box extents
285 * \return true if the AABB contains the whole box
287 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
288 inline_ BOOL
AABBCollider::AABBContainsBox(const Point
& bc
, const Point
& be
)
290 if(mMin
.x
> bc
.x
- be
.x
) return FALSE
;
291 if(mMin
.y
> bc
.y
- be
.y
) return FALSE
;
292 if(mMin
.z
> bc
.z
- be
.z
) return FALSE
;
294 if(mMax
.x
< bc
.x
+ be
.x
) return FALSE
;
295 if(mMax
.y
< bc
.y
+ be
.y
) return FALSE
;
296 if(mMax
.z
< bc
.z
+ be
.z
) return FALSE
;
301 #define TEST_BOX_IN_AABB(center, extents) \
302 if(AABBContainsBox(center, extents)) \
304 /* Set contact status */ \
305 mFlags |= OPC_CONTACT; \
310 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
312 * Recursive collision query for normal AABB trees.
313 * \param node [in] current collision node
315 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
316 void AABBCollider::_Collide(const AABBCollisionNode
* node
)
318 // Perform AABB-AABB overlap test
319 if(!AABBAABBOverlap(node
->mAABB
.mExtents
, node
->mAABB
.mCenter
)) return;
321 TEST_BOX_IN_AABB(node
->mAABB
.mCenter
, node
->mAABB
.mExtents
)
325 AABB_PRIM(node
->GetPrimitive(), OPC_CONTACT
)
329 _Collide(node
->GetPos());
331 if(ContactFound()) return;
333 _Collide(node
->GetNeg());
337 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
339 * Recursive collision query for normal AABB trees, without primitive tests.
340 * \param node [in] current collision node
342 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
343 void AABBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode
* node
)
345 // Perform AABB-AABB overlap test
346 if(!AABBAABBOverlap(node
->mAABB
.mExtents
, node
->mAABB
.mCenter
)) return;
348 TEST_BOX_IN_AABB(node
->mAABB
.mCenter
, node
->mAABB
.mExtents
)
352 SET_CONTACT(node
->GetPrimitive(), OPC_CONTACT
)
356 _CollideNoPrimitiveTest(node
->GetPos());
358 if(ContactFound()) return;
360 _CollideNoPrimitiveTest(node
->GetNeg());
364 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
366 * Recursive collision query for quantized AABB trees.
367 * \param node [in] current collision node
369 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
370 void AABBCollider::_Collide(const AABBQuantizedNode
* node
)
373 const QuantizedAABB
& Box
= node
->mAABB
;
374 const Point
Center(float(Box
.mCenter
[0]) * mCenterCoeff
.x
, float(Box
.mCenter
[1]) * mCenterCoeff
.y
, float(Box
.mCenter
[2]) * mCenterCoeff
.z
);
375 const Point
Extents(float(Box
.mExtents
[0]) * mExtentsCoeff
.x
, float(Box
.mExtents
[1]) * mExtentsCoeff
.y
, float(Box
.mExtents
[2]) * mExtentsCoeff
.z
);
377 // Perform AABB-AABB overlap test
378 if(!AABBAABBOverlap(Extents
, Center
)) return;
380 TEST_BOX_IN_AABB(Center
, Extents
)
384 AABB_PRIM(node
->GetPrimitive(), OPC_CONTACT
)
388 _Collide(node
->GetPos());
390 if(ContactFound()) return;
392 _Collide(node
->GetNeg());
396 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
398 * Recursive collision query for quantized AABB trees, without primitive tests.
399 * \param node [in] current collision node
401 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
402 void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode
* node
)
405 const QuantizedAABB
& Box
= node
->mAABB
;
406 const Point
Center(float(Box
.mCenter
[0]) * mCenterCoeff
.x
, float(Box
.mCenter
[1]) * mCenterCoeff
.y
, float(Box
.mCenter
[2]) * mCenterCoeff
.z
);
407 const Point
Extents(float(Box
.mExtents
[0]) * mExtentsCoeff
.x
, float(Box
.mExtents
[1]) * mExtentsCoeff
.y
, float(Box
.mExtents
[2]) * mExtentsCoeff
.z
);
409 // Perform AABB-AABB overlap test
410 if(!AABBAABBOverlap(Extents
, Center
)) return;
412 TEST_BOX_IN_AABB(Center
, Extents
)
416 SET_CONTACT(node
->GetPrimitive(), OPC_CONTACT
)
420 _CollideNoPrimitiveTest(node
->GetPos());
422 if(ContactFound()) return;
424 _CollideNoPrimitiveTest(node
->GetNeg());
428 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
430 * Recursive collision query for no-leaf AABB trees.
431 * \param node [in] current collision node
433 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
434 void AABBCollider::_Collide(const AABBNoLeafNode
* node
)
436 // Perform AABB-AABB overlap test
437 if(!AABBAABBOverlap(node
->mAABB
.mExtents
, node
->mAABB
.mCenter
)) return;
439 TEST_BOX_IN_AABB(node
->mAABB
.mCenter
, node
->mAABB
.mExtents
)
441 if(node
->HasPosLeaf()) { AABB_PRIM(node
->GetPosPrimitive(), OPC_CONTACT
) }
442 else _Collide(node
->GetPos());
444 if(ContactFound()) return;
446 if(node
->HasNegLeaf()) { AABB_PRIM(node
->GetNegPrimitive(), OPC_CONTACT
) }
447 else _Collide(node
->GetNeg());
450 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
452 * Recursive collision query for no-leaf AABB trees, without primitive tests.
453 * \param node [in] current collision node
455 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
456 void AABBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode
* node
)
458 // Perform AABB-AABB overlap test
459 if(!AABBAABBOverlap(node
->mAABB
.mExtents
, node
->mAABB
.mCenter
)) return;
461 TEST_BOX_IN_AABB(node
->mAABB
.mCenter
, node
->mAABB
.mExtents
)
463 if(node
->HasPosLeaf()) { SET_CONTACT(node
->GetPosPrimitive(), OPC_CONTACT
) }
464 else _CollideNoPrimitiveTest(node
->GetPos());
466 if(ContactFound()) return;
468 if(node
->HasNegLeaf()) { SET_CONTACT(node
->GetNegPrimitive(), OPC_CONTACT
) }
469 else _CollideNoPrimitiveTest(node
->GetNeg());
472 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
474 * Recursive collision query for quantized no-leaf AABB trees.
475 * \param node [in] current collision node
477 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
478 void AABBCollider::_Collide(const AABBQuantizedNoLeafNode
* node
)
481 const QuantizedAABB
& Box
= node
->mAABB
;
482 const Point
Center(float(Box
.mCenter
[0]) * mCenterCoeff
.x
, float(Box
.mCenter
[1]) * mCenterCoeff
.y
, float(Box
.mCenter
[2]) * mCenterCoeff
.z
);
483 const Point
Extents(float(Box
.mExtents
[0]) * mExtentsCoeff
.x
, float(Box
.mExtents
[1]) * mExtentsCoeff
.y
, float(Box
.mExtents
[2]) * mExtentsCoeff
.z
);
485 // Perform AABB-AABB overlap test
486 if(!AABBAABBOverlap(Extents
, Center
)) return;
488 TEST_BOX_IN_AABB(Center
, Extents
)
490 if(node
->HasPosLeaf()) { AABB_PRIM(node
->GetPosPrimitive(), OPC_CONTACT
) }
491 else _Collide(node
->GetPos());
493 if(ContactFound()) return;
495 if(node
->HasNegLeaf()) { AABB_PRIM(node
->GetNegPrimitive(), OPC_CONTACT
) }
496 else _Collide(node
->GetNeg());
499 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
501 * Recursive collision query for quantized no-leaf AABB trees, without primitive tests.
502 * \param node [in] current collision node
504 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
505 void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode
* node
)
508 const QuantizedAABB
& Box
= node
->mAABB
;
509 const Point
Center(float(Box
.mCenter
[0]) * mCenterCoeff
.x
, float(Box
.mCenter
[1]) * mCenterCoeff
.y
, float(Box
.mCenter
[2]) * mCenterCoeff
.z
);
510 const Point
Extents(float(Box
.mExtents
[0]) * mExtentsCoeff
.x
, float(Box
.mExtents
[1]) * mExtentsCoeff
.y
, float(Box
.mExtents
[2]) * mExtentsCoeff
.z
);
512 // Perform AABB-AABB overlap test
513 if(!AABBAABBOverlap(Extents
, Center
)) return;
515 TEST_BOX_IN_AABB(Center
, Extents
)
517 if(node
->HasPosLeaf()) { SET_CONTACT(node
->GetPosPrimitive(), OPC_CONTACT
) }
518 else _CollideNoPrimitiveTest(node
->GetPos());
520 if(ContactFound()) return;
522 if(node
->HasNegLeaf()) { SET_CONTACT(node
->GetNegPrimitive(), OPC_CONTACT
) }
523 else _CollideNoPrimitiveTest(node
->GetNeg());
526 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
528 * Recursive collision query for vanilla AABB trees.
529 * \param node [in] current collision node
531 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
532 void AABBCollider::_Collide(const AABBTreeNode
* node
)
534 // Perform AABB-AABB overlap test
535 Point Center
, Extents
;
536 node
->GetAABB()->GetCenter(Center
);
537 node
->GetAABB()->GetExtents(Extents
);
538 if(!AABBAABBOverlap(Center
, Extents
)) return;
540 if(node
->IsLeaf() || AABBContainsBox(Center
, Extents
))
542 mFlags
|= OPC_CONTACT
;
543 mTouchedPrimitives
->Add(node
->GetPrimitives(), node
->GetNbPrimitives());
547 _Collide(node
->GetPos());
548 _Collide(node
->GetNeg());
555 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
559 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
560 HybridAABBCollider::HybridAABBCollider()
564 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
568 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
569 HybridAABBCollider::~HybridAABBCollider()
573 bool HybridAABBCollider::Collide(AABBCache
& cache
, const CollisionAABB
& box
, const HybridModel
& model
)
575 // We don't want primitive tests here!
576 mFlags
|= OPC_NO_PRIMITIVE_TESTS
;
579 if(!Setup(&model
)) return false;
581 // Init collision query
582 if(InitQuery(cache
, box
)) return true;
584 // Special case for 1-leaf trees
585 if(mCurrentModel
&& mCurrentModel
->HasSingleNode())
587 // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
588 udword Nb
= mIMesh
->GetNbTriangles();
590 // Loop through all triangles
591 for(udword i
=0;i
<Nb
;i
++)
593 AABB_PRIM(i
, OPC_CONTACT
)
598 // Override destination array since we're only going to get leaf boxes here
599 mTouchedBoxes
.Reset();
600 mTouchedPrimitives
= &mTouchedBoxes
;
602 // Now, do the actual query against leaf boxes
603 if(!model
.HasLeafNodes())
605 if(model
.IsQuantized())
607 const AABBQuantizedNoLeafTree
* Tree
= static_cast<const AABBQuantizedNoLeafTree
*>(model
.GetTree());
609 // Setup dequantization coeffs
610 mCenterCoeff
= Tree
->mCenterCoeff
;
611 mExtentsCoeff
= Tree
->mExtentsCoeff
;
613 // Perform collision query - we don't want primitive tests here!
614 _CollideNoPrimitiveTest(Tree
->GetNodes());
618 const AABBNoLeafTree
* Tree
= static_cast<const AABBNoLeafTree
*>(model
.GetTree());
620 // Perform collision query - we don't want primitive tests here!
621 _CollideNoPrimitiveTest(Tree
->GetNodes());
626 if(model
.IsQuantized())
628 const AABBQuantizedTree
* Tree
= static_cast<const AABBQuantizedTree
*>(model
.GetTree());
630 // Setup dequantization coeffs
631 mCenterCoeff
= Tree
->mCenterCoeff
;
632 mExtentsCoeff
= Tree
->mExtentsCoeff
;
634 // Perform collision query - we don't want primitive tests here!
635 _CollideNoPrimitiveTest(Tree
->GetNodes());
639 const AABBCollisionTree
* Tree
= static_cast<const AABBCollisionTree
*>(model
.GetTree());
641 // Perform collision query - we don't want primitive tests here!
642 _CollideNoPrimitiveTest(Tree
->GetNodes());
646 // We only have a list of boxes so far
647 if(GetContactStatus())
649 // Reset contact status, since it currently only reflects collisions with leaf boxes
650 Collider::InitQuery();
652 // Change dest container so that we can use built-in overlap tests and get collided primitives
653 cache
.TouchedPrimitives
.Reset();
654 mTouchedPrimitives
= &cache
.TouchedPrimitives
;
656 // Read touched leaf boxes
657 udword Nb
= mTouchedBoxes
.GetNbEntries();
658 const udword
* Touched
= mTouchedBoxes
.GetEntries();
660 const LeafTriangles
* LT
= model
.GetLeafTriangles();
661 const udword
* Indices
= model
.GetIndices();
663 // Loop through touched leaves
666 const LeafTriangles
& CurrentLeaf
= LT
[*Touched
++];
668 // Each leaf box has a set of triangles
669 udword NbTris
= CurrentLeaf
.GetNbTriangles();
672 const udword
* T
= &Indices
[CurrentLeaf
.GetTriangleIndex()];
674 // Loop through triangles and test each of them
677 udword TriangleIndex
= *T
++;
678 AABB_PRIM(TriangleIndex
, OPC_CONTACT
)
683 udword BaseIndex
= CurrentLeaf
.GetTriangleIndex();
685 // Loop through triangles and test each of them
688 udword TriangleIndex
= BaseIndex
++;
689 AABB_PRIM(TriangleIndex
, OPC_CONTACT
)