1
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3
* OPCODE - Optimized Collision Detection
4
* Copyright (C) 2001 Pierre Terdiman
5
* Homepage: http://www.codercorner.com/Opcode.htm
7
* OPCODE modifications for scaled model support (and other things)
8
* Copyright (C) 2004 Gilvan Maia (gilvan 'at' vdl.ufc.br)
9
* Check http://www.vdl.ufc.br/gilvan/coll/opcode/index.htm for updates.
12
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
14
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16
* Contains code for an LSS collider.
17
* \file OPC_LSSCollider.cpp
18
* \author Pierre Terdiman
19
* \date December, 28, 2002
21
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
23
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
25
* Contains a lss-vs-tree collider.
28
* \author Pierre Terdiman
30
* \date December, 28, 2002
32
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
34
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
36
#include "Opcode/Stdafx.h"
38
using namespace Opcode;
40
#include "Opcode/OPC_LSSAABBOverlap.h"
41
#include "Opcode/OPC_LSSTriOverlap.h"
43
#define SET_CONTACT(prim_index, flag) \
44
/* Set contact status */ \
46
mTouchedPrimitives->Add(prim_index);
48
//! LSS-triangle overlap test
49
#define LSS_PRIM(prim_index, flag) \
50
/* Request vertices from the app */ \
51
VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \
53
/* Perform LSS-tri overlap test */ \
54
if(LSSTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \
56
SET_CONTACT(prim_index, flag) \
59
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
63
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
64
LSSCollider::LSSCollider()
70
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
74
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
75
LSSCollider::~LSSCollider()
79
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81
* Generic collision query for generic OPCODE models. After the call, access the results:
82
* - with GetContactStatus()
83
* - with GetNbTouchedPrimitives()
84
* - with GetTouchedPrimitives()
86
* \param cache [in/out] an lss cache
87
* \param lss [in] collision lss in local space
88
* \param model [in] Opcode model to collide with
89
* \param worldl [in] lss world matrix, or null
90
* \param worldm [in] model's world matrix, or null
91
* \return true if success
92
* \warning SCALE NOT SUPPORTED IN LSS WORLD MATRIX. The LSS matrix must contain rotation & translation parts only.
94
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
95
bool LSSCollider::Collide(LSSCache& cache, const IceMaths::LSS& lss, const Model& model, const IceMaths::Matrix4x4* worldl, const IceMaths::Matrix4x4* worldm)
98
if(!Setup(&model)) return false;
100
// Init collision query
101
if(InitQuery(cache, lss, worldl, worldm)) return true;
103
if(!model.HasLeafNodes())
105
if(model.IsQuantized())
107
const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
109
// Setup dequantization coeffs
110
mCenterCoeff = Tree->mCenterCoeff;
111
mExtentsCoeff = Tree->mExtentsCoeff;
113
// Perform collision query
114
if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
115
else _Collide(Tree->GetNodes());
119
const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
121
// Perform collision query
122
if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
123
else _Collide(Tree->GetNodes());
128
if(model.IsQuantized())
130
const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
132
// Setup dequantization coeffs
133
mCenterCoeff = Tree->mCenterCoeff;
134
mExtentsCoeff = Tree->mExtentsCoeff;
136
// Perform collision query
137
if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
138
else _Collide(Tree->GetNodes());
142
const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
144
// Perform collision query
145
if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
146
else _Collide(Tree->GetNodes());
153
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
155
* Initializes a collision query :
156
* - reset stats & contact status
158
* - check temporal coherence
160
* \param cache [in/out] an lss cache
161
* \param lss [in] lss in local space
162
* \param worldl [in] lss world matrix, or null
163
* \param worldm [in] model's world matrix, or null
164
* \return TRUE if we can return immediately
165
* \warning SCALE NOT SUPPORTED IN LSS WORLD MATRIX. The matrix must contain rotation & translation parts only.
167
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
168
BOOL LSSCollider::InitQuery(LSSCache& cache, const IceMaths::LSS& lss, const IceMaths::Matrix4x4* worldl, const IceMaths::Matrix4x4* worldm)
170
// 1) Call the base method
171
VolumeCollider::InitQuery();
173
// 2) Compute LSS in model space:
175
mRadius2 = lss.mRadius * lss.mRadius;
188
// Matrix normalization & scaling stripping
189
IceMaths::Matrix4x4 normWorldm;
190
IceMaths::NormalizePRSMatrix( normWorldm, mLocalScale, *worldm );
192
// Invert model matrix
193
IceMaths::Matrix4x4 InvWorldM;
194
IceMaths::InvertPRMatrix(InvWorldM, normWorldm);
196
mSeg.mP0 *= InvWorldM;
197
mSeg.mP1 *= InvWorldM;
200
mLocalScale.Set(1.0,1.0,1.0);
203
// 3) Setup destination pointer
204
mTouchedPrimitives = &cache.TouchedPrimitives;
206
// 4) Special case: 1-triangle meshes [Opcode 1.3]
207
if(mCurrentModel && mCurrentModel->HasSingleNode())
209
if(!SkipPrimitiveTests())
211
// We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
212
mTouchedPrimitives->Reset();
214
// Perform overlap test between the unique triangle and the LSS (and set contact status if needed)
215
LSS_PRIM(udword(0), OPC_CONTACT)
217
// Return immediately regardless of status
222
// 5) Check temporal coherence :
223
if(TemporalCoherenceEnabled())
225
// Here we use temporal coherence
226
// => check results from previous frame before performing the collision query
227
if(FirstContactEnabled())
229
// We're only interested in the first contact found => test the unique previously touched face
230
if(mTouchedPrimitives->GetNbEntries())
232
// Get index of previously touched face = the first entry in the array
233
udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
235
// Then reset the array:
236
// - if the overlap test below is successful, the index we'll get added back anyway
237
// - if it isn't, then the array should be reset anyway for the normal query
238
mTouchedPrimitives->Reset();
240
// Perform overlap test between the cached triangle and the LSS (and set contact status if needed)
241
LSS_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
243
// Return immediately if possible
244
if(GetContactStatus()) return TRUE;
246
// else no face has been touched during previous query
247
// => we'll have to perform a normal query
251
// We're interested in all contacts =>test the new real LSS N(ew) against the previous fat LSS P(revious):
255
IceMaths::LSS Test(mSeg, lss.mRadius); // in model space
256
IceMaths::LSS Previous(cache.Previous, sqrtf(cache.Previous.mRadius));
258
// if(cache.Previous.Contains(Test))
259
if(IsCacheValid(cache) && Previous.Contains(Test))
261
// - if N is included in P, return previous list
262
// => we simply leave the list (mTouchedFaces) unchanged
264
// Set contact status if needed
265
if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT;
267
// In any case we don't need to do a query
272
// - else do the query using a fat N
274
// Reset cache since we'll about to perform a real query
275
mTouchedPrimitives->Reset();
277
// Make a fat sphere so that coherence will work for subsequent frames
278
mRadius2 *= cache.FatCoeff;
279
// mRadius2 = (lss.mRadius * cache.FatCoeff)*(lss.mRadius * cache.FatCoeff);
282
// Update cache with query data (signature for cached faces)
283
cache.Previous.mP0 = mSeg.mP0;
284
cache.Previous.mP1 = mSeg.mP1;
285
cache.Previous.mRadius = mRadius2;
291
// Here we don't use temporal coherence => do a normal query
292
mTouchedPrimitives->Reset();
298
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
300
* Collision query for vanilla AABB trees.
301
* \param cache [in/out] an lss cache
302
* \param lss [in] collision lss in world space
303
* \param tree [in] AABB tree
304
* \return true if success
306
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
307
bool LSSCollider::Collide(LSSCache& cache, const IceMaths::LSS& lss, const AABBTree* tree)
309
// This is typically called for a scene tree, full of -AABBs-, not full of triangles.
310
// So we don't really have "primitives" to deal with. Hence it doesn't work with
311
// "FirstContact" + "TemporalCoherence".
312
ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) );
315
if(!tree) return false;
317
// Init collision query
318
if(InitQuery(cache, lss)) return true;
320
// Perform collision query
326
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
328
* Checks the LSS completely contains the box. In which case we can end the query sooner.
329
* \param bc [in] box center
330
* \param be [in] box extents
331
* \return true if the LSS contains the whole box
333
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
334
inline_ BOOL LSSCollider::LSSContainsBox(const IceMaths::Point& bc, const IceMaths::Point& be)
340
#define TEST_BOX_IN_LSS(center, extents) \
341
if(LSSContainsBox(center, extents)) \
343
/* Set contact status */ \
344
mFlags |= OPC_CONTACT; \
349
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
351
* Recursive collision query for normal AABB trees.
352
* \param node [in] current collision node
354
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
355
void LSSCollider::_Collide(const AABBCollisionNode* node)
357
// Perform LSS-AABB overlap test
358
if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
360
TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
364
LSS_PRIM(node->GetPrimitive(), OPC_CONTACT)
368
_Collide(node->GetPos());
370
if(ContactFound()) return;
372
_Collide(node->GetNeg());
376
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
378
* Recursive collision query for normal AABB trees, without primitive tests.
379
* \param node [in] current collision node
381
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
382
void LSSCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node)
384
// Perform LSS-AABB overlap test
385
if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
387
TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
391
SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
395
_CollideNoPrimitiveTest(node->GetPos());
397
if(ContactFound()) return;
399
_CollideNoPrimitiveTest(node->GetNeg());
403
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
405
* Recursive collision query for quantized AABB trees.
406
* \param node [in] current collision node
408
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
409
void LSSCollider::_Collide(const AABBQuantizedNode* node)
412
const QuantizedAABB& Box = node->mAABB;
413
const IceMaths::Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
414
const IceMaths::Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
416
// Perform LSS-AABB overlap test
417
if(!LSSAABBOverlap(Center, Extents)) return;
419
TEST_BOX_IN_LSS(Center, Extents)
423
LSS_PRIM(node->GetPrimitive(), OPC_CONTACT)
427
_Collide(node->GetPos());
429
if(ContactFound()) return;
431
_Collide(node->GetNeg());
435
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
437
* Recursive collision query for quantized AABB trees, without primitive tests.
438
* \param node [in] current collision node
440
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
441
void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node)
444
const QuantizedAABB& Box = node->mAABB;
445
const IceMaths::Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
446
const IceMaths::Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
448
// Perform LSS-AABB overlap test
449
if(!LSSAABBOverlap(Center, Extents)) return;
451
TEST_BOX_IN_LSS(Center, Extents)
455
SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
459
_CollideNoPrimitiveTest(node->GetPos());
461
if(ContactFound()) return;
463
_CollideNoPrimitiveTest(node->GetNeg());
467
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
469
* Recursive collision query for no-leaf AABB trees.
470
* \param node [in] current collision node
472
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
473
void LSSCollider::_Collide(const AABBNoLeafNode* node)
475
// Perform LSS-AABB overlap test
476
if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
478
TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
480
if(node->HasPosLeaf()) { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
481
else _Collide(node->GetPos());
483
if(ContactFound()) return;
485
if(node->HasNegLeaf()) { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
486
else _Collide(node->GetNeg());
489
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
491
* Recursive collision query for no-leaf AABB trees, without primitive tests.
492
* \param node [in] current collision node
494
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
495
void LSSCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node)
497
// Perform LSS-AABB overlap test
498
if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
500
TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
502
if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
503
else _CollideNoPrimitiveTest(node->GetPos());
505
if(ContactFound()) return;
507
if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
508
else _CollideNoPrimitiveTest(node->GetNeg());
511
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
513
* Recursive collision query for quantized no-leaf AABB trees.
514
* \param node [in] current collision node
516
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
517
void LSSCollider::_Collide(const AABBQuantizedNoLeafNode* node)
520
const QuantizedAABB& Box = node->mAABB;
521
const IceMaths::Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
522
const IceMaths::Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
524
// Perform LSS-AABB overlap test
525
if(!LSSAABBOverlap(Center, Extents)) return;
527
TEST_BOX_IN_LSS(Center, Extents)
529
if(node->HasPosLeaf()) { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
530
else _Collide(node->GetPos());
532
if(ContactFound()) return;
534
if(node->HasNegLeaf()) { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
535
else _Collide(node->GetNeg());
538
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
540
* Recursive collision query for quantized no-leaf AABB trees, without primitive tests.
541
* \param node [in] current collision node
543
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
544
void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node)
547
const QuantizedAABB& Box = node->mAABB;
548
const IceMaths::Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
549
const IceMaths::Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
551
// Perform LSS-AABB overlap test
552
if(!LSSAABBOverlap(Center, Extents)) return;
554
TEST_BOX_IN_LSS(Center, Extents)
556
if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
557
else _CollideNoPrimitiveTest(node->GetPos());
559
if(ContactFound()) return;
561
if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
562
else _CollideNoPrimitiveTest(node->GetNeg());
565
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
567
* Recursive collision query for vanilla AABB trees.
568
* \param node [in] current collision node
570
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
571
void LSSCollider::_Collide(const AABBTreeNode* node)
573
// Perform LSS-AABB overlap test
574
IceMaths::Point Center, Extents;
575
node->GetAABB()->GetCenter(Center);
576
node->GetAABB()->GetExtents(Extents);
577
if(!LSSAABBOverlap(Center, Extents)) return;
579
if(node->IsLeaf() || LSSContainsBox(Center, Extents))
581
mFlags |= OPC_CONTACT;
582
mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives());
586
_Collide(node->GetPos());
587
_Collide(node->GetNeg());
596
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
600
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
601
HybridLSSCollider::HybridLSSCollider()
605
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
609
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
610
HybridLSSCollider::~HybridLSSCollider()
614
bool HybridLSSCollider::Collide(LSSCache& cache, const IceMaths::LSS& lss, const HybridModel& model, const IceMaths::Matrix4x4* worldl, const IceMaths::Matrix4x4* worldm)
616
// We don't want primitive tests here!
617
mFlags |= OPC_NO_PRIMITIVE_TESTS;
620
if(!Setup(&model)) return false;
622
// Init collision query
623
if(InitQuery(cache, lss, worldl, worldm)) return true;
625
// Special case for 1-leaf trees
626
if(mCurrentModel && mCurrentModel->HasSingleNode())
628
// Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
629
udword Nb = mIMesh->GetNbTriangles();
631
// Loop through all triangles
632
for(udword i=0;i<Nb;i++)
634
LSS_PRIM(i, OPC_CONTACT)
639
// Override destination array since we're only going to get leaf boxes here
640
mTouchedBoxes.Reset();
641
mTouchedPrimitives = &mTouchedBoxes;
643
// Now, do the actual query against leaf boxes
644
if(!model.HasLeafNodes())
646
if(model.IsQuantized())
648
const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
650
// Setup dequantization coeffs
651
mCenterCoeff = Tree->mCenterCoeff;
652
mExtentsCoeff = Tree->mExtentsCoeff;
654
// Perform collision query - we don't want primitive tests here!
655
_CollideNoPrimitiveTest(Tree->GetNodes());
659
const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
661
// Perform collision query - we don't want primitive tests here!
662
_CollideNoPrimitiveTest(Tree->GetNodes());
667
if(model.IsQuantized())
669
const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
671
// Setup dequantization coeffs
672
mCenterCoeff = Tree->mCenterCoeff;
673
mExtentsCoeff = Tree->mExtentsCoeff;
675
// Perform collision query - we don't want primitive tests here!
676
_CollideNoPrimitiveTest(Tree->GetNodes());
680
const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
682
// Perform collision query - we don't want primitive tests here!
683
_CollideNoPrimitiveTest(Tree->GetNodes());
687
// We only have a list of boxes so far
688
if(GetContactStatus())
690
// Reset contact status, since it currently only reflects collisions with leaf boxes
691
Collider::InitQuery();
693
// Change dest container so that we can use built-in overlap tests and get collided primitives
694
cache.TouchedPrimitives.Reset();
695
mTouchedPrimitives = &cache.TouchedPrimitives;
697
// Read touched leaf boxes
698
udword Nb = mTouchedBoxes.GetNbEntries();
699
const udword* Touched = mTouchedBoxes.GetEntries();
701
const LeafTriangles* LT = model.GetLeafTriangles();
702
const udword* Indices = model.GetIndices();
704
// Loop through touched leaves
707
const LeafTriangles& CurrentLeaf = LT[*Touched++];
709
// Each leaf box has a set of triangles
710
udword NbTris = CurrentLeaf.GetNbTriangles();
713
const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
715
// Loop through triangles and test each of them
718
udword TriangleIndex = *T++;
719
LSS_PRIM(TriangleIndex, OPC_CONTACT)
724
udword BaseIndex = CurrentLeaf.GetTriangleIndex();
726
// Loop through triangles and test each of them
729
udword TriangleIndex = BaseIndex++;
730
LSS_PRIM(TriangleIndex, OPC_CONTACT)