Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ode/ode-0.9/OPCODE/OPC_LSSCollider.cpp @ 216

Last change on this file since 216 was 216, checked in by mathiask, 16 years ago

[Physik] add ode-0.9

File size: 26.2 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2/*
3 *      OPCODE - Optimized Collision Detection
4 *      Copyright (C) 2001 Pierre Terdiman
5 *      Homepage: http://www.codercorner.com/Opcode.htm
6 */
7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8
9///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10/**
11 *      Contains code for an LSS collider.
12 *      \file           OPC_LSSCollider.cpp
13 *      \author         Pierre Terdiman
14 *      \date           December, 28, 2002
15 */
16///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17
18///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19/**
20 *      Contains a lss-vs-tree collider.
21 *
22 *      \class          LSSCollider
23 *      \author         Pierre Terdiman
24 *      \version        1.3
25 *      \date           December, 28, 2002
26*/
27///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
28
29///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30// Precompiled Header
31#include "Stdafx.h"
32
33using namespace Opcode;
34
35#include "OPC_LSSAABBOverlap.h"
36#include "OPC_LSSTriOverlap.h"
37
38#define SET_CONTACT(prim_index, flag)                                                                   \
39        /* Set contact status */                                                                                        \
40        mFlags |= flag;                                                                                                         \
41        mTouchedPrimitives->Add(udword(prim_index));
42
43//! LSS-triangle overlap test
44#define LSS_PRIM(prim_index, flag)                                                                              \
45        /* Request vertices from the app */                                                                     \
46        VertexPointers VP;      mIMesh->GetTriangle(VP, prim_index);                    \
47                                                                                                                                                \
48        /* Perform LSS-tri overlap test */                                                                      \
49        if(LSSTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2]))          \
50        {                                                                                                                                       \
51                SET_CONTACT(prim_index, flag)                                                                   \
52        }
53
54///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
55/**
56 *      Constructor.
57 */
58///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
59LSSCollider::LSSCollider()
60{
61//      mCenter.Zero();
62//      mRadius2 = 0.0f;
63}
64
65///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
66/**
67 *      Destructor.
68 */
69///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
70LSSCollider::~LSSCollider()
71{
72}
73
74///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
75/**
76 *      Generic collision query for generic OPCODE models. After the call, access the results:
77 *      - with GetContactStatus()
78 *      - with GetNbTouchedPrimitives()
79 *      - with GetTouchedPrimitives()
80 *
81 *      \param          cache                   [in/out] an lss cache
82 *      \param          lss                             [in] collision lss in local space
83 *      \param          model                   [in] Opcode model to collide with
84 *      \param          worldl                  [in] lss world matrix, or null
85 *      \param          worldm                  [in] model's world matrix, or null
86 *      \return         true if success
87 *      \warning        SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
88 */
89///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
90bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl, const Matrix4x4* worldm)
91{
92        // Checkings
93        if(!Setup(&model))      return false;
94
95        // Init collision query
96        if(InitQuery(cache, lss, worldl, worldm))       return true;
97
98        if(!model.HasLeafNodes())
99        {
100                if(model.IsQuantized())
101                {
102                        const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
103
104                        // Setup dequantization coeffs
105                        mCenterCoeff    = Tree->mCenterCoeff;
106                        mExtentsCoeff   = Tree->mExtentsCoeff;
107
108                        // Perform collision query
109                        if(SkipPrimitiveTests())        _CollideNoPrimitiveTest(Tree->GetNodes());
110                        else                                            _Collide(Tree->GetNodes());
111                }
112                else
113                {
114                        const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
115
116                        // Perform collision query
117                        if(SkipPrimitiveTests())        _CollideNoPrimitiveTest(Tree->GetNodes());
118                        else                                            _Collide(Tree->GetNodes());
119                }
120        }
121        else
122        {
123                if(model.IsQuantized())
124                {
125                        const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
126
127                        // Setup dequantization coeffs
128                        mCenterCoeff    = Tree->mCenterCoeff;
129                        mExtentsCoeff   = Tree->mExtentsCoeff;
130
131                        // Perform collision query
132                        if(SkipPrimitiveTests())        _CollideNoPrimitiveTest(Tree->GetNodes());
133                        else                                            _Collide(Tree->GetNodes());
134                }
135                else
136                {
137                        const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
138
139                        // Perform collision query
140                        if(SkipPrimitiveTests())        _CollideNoPrimitiveTest(Tree->GetNodes());
141                        else                                            _Collide(Tree->GetNodes());
142                }
143        }
144
145        return true;
146}
147
148///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
149/**
150 *      Initializes a collision query :
151 *      - reset stats & contact status
152 *      - setup matrices
153 *      - check temporal coherence
154 *
155 *      \param          cache           [in/out] an lss cache
156 *      \param          lss                     [in] lss in local space
157 *      \param          worldl          [in] lss world matrix, or null
158 *      \param          worldm          [in] model's world matrix, or null
159 *      \return         TRUE if we can return immediately
160 *      \warning        SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
161 */
162///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
163BOOL LSSCollider::InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl, const Matrix4x4* worldm)
164{
165        // 1) Call the base method
166        VolumeCollider::InitQuery();
167
168        // 2) Compute LSS in model space:
169        // - Precompute R^2
170        mRadius2 = lss.mRadius * lss.mRadius;
171        // - Compute segment
172        mSeg.mP0 = lss.mP0;
173        mSeg.mP1 = lss.mP1;
174        // -> to world space
175        if(worldl)
176        {
177                mSeg.mP0 *= *worldl;
178                mSeg.mP1 *= *worldl;
179        }
180        // -> to model space
181        if(worldm)
182        {
183                // Invert model matrix
184                Matrix4x4 InvWorldM;
185                InvertPRMatrix(InvWorldM, *worldm);
186
187                mSeg.mP0 *= InvWorldM;
188                mSeg.mP1 *= InvWorldM;
189        }
190
191        // 3) Setup destination pointer
192        mTouchedPrimitives = &cache.TouchedPrimitives;
193
194        // 4) Special case: 1-triangle meshes [Opcode 1.3]
195        if(mCurrentModel && mCurrentModel->HasSingleNode())
196        {
197                if(!SkipPrimitiveTests())
198                {
199                        // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
200                        mTouchedPrimitives->Reset();
201
202                        // Perform overlap test between the unique triangle and the LSS (and set contact status if needed)
203                        LSS_PRIM(udword(0), OPC_CONTACT)
204
205                        // Return immediately regardless of status
206                        return TRUE;
207                }
208        }
209
210        // 5) Check temporal coherence :
211        if(TemporalCoherenceEnabled())
212        {
213                // Here we use temporal coherence
214                // => check results from previous frame before performing the collision query
215                if(FirstContactEnabled())
216                {
217                        // We're only interested in the first contact found => test the unique previously touched face
218                        if(mTouchedPrimitives->GetNbEntries())
219                        {
220                                // Get index of previously touched face = the first entry in the array
221                                udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
222
223                                // Then reset the array:
224                                // - if the overlap test below is successful, the index we'll get added back anyway
225                                // - if it isn't, then the array should be reset anyway for the normal query
226                                mTouchedPrimitives->Reset();
227
228                                // Perform overlap test between the cached triangle and the LSS (and set contact status if needed)
229                                LSS_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
230
231                                // Return immediately if possible
232                                if(GetContactStatus())  return TRUE;
233                        }
234                        // else no face has been touched during previous query
235                        // => we'll have to perform a normal query
236                }
237                else
238                {
239                        // We're interested in all contacts =>test the new real LSS N(ew) against the previous fat LSS P(revious):
240
241                        // ### rewrite this
242
243                        LSS Test(mSeg, lss.mRadius);    // in model space
244                        LSS Previous(cache.Previous, sqrtf(cache.Previous.mRadius));
245
246//                      if(cache.Previous.Contains(Test))
247                        if(IsCacheValid(cache) && Previous.Contains(Test))
248                        {
249                                // - if N is included in P, return previous list
250                                // => we simply leave the list (mTouchedFaces) unchanged
251
252                                // Set contact status if needed
253                                if(mTouchedPrimitives->GetNbEntries())  mFlags |= OPC_TEMPORAL_CONTACT;
254
255                                // In any case we don't need to do a query
256                                return TRUE;
257                        }
258                        else
259                        {
260                                // - else do the query using a fat N
261
262                                // Reset cache since we'll about to perform a real query
263                                mTouchedPrimitives->Reset();
264
265                                // Make a fat sphere so that coherence will work for subsequent frames
266                                mRadius2 *= cache.FatCoeff;
267//                              mRadius2 = (lss.mRadius * cache.FatCoeff)*(lss.mRadius * cache.FatCoeff);
268
269
270                                // Update cache with query data (signature for cached faces)
271                                cache.Previous.mP0 = mSeg.mP0;
272                                cache.Previous.mP1 = mSeg.mP1;
273                                cache.Previous.mRadius = mRadius2;
274                        }
275                }
276        }
277        else
278        {
279                // Here we don't use temporal coherence => do a normal query
280                mTouchedPrimitives->Reset();
281        }
282
283        return FALSE;
284}
285
286///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
287/**
288 *      Collision query for vanilla AABB trees.
289 *      \param          cache           [in/out] an lss cache
290 *      \param          lss                     [in] collision lss in world space
291 *      \param          tree            [in] AABB tree
292 *      \return         true if success
293 */
294///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
295bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree)
296{
297        // This is typically called for a scene tree, full of -AABBs-, not full of triangles.
298        // So we don't really have "primitives" to deal with. Hence it doesn't work with
299        // "FirstContact" + "TemporalCoherence".
300        ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) );
301
302        // Checkings
303        if(!tree)       return false;
304
305        // Init collision query
306        if(InitQuery(cache, lss))       return true;
307
308        // Perform collision query
309        _Collide(tree);
310
311        return true;
312}
313
314///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
315/**
316 *      Checks the LSS completely contains the box. In which case we can end the query sooner.
317 *      \param          bc      [in] box center
318 *      \param          be      [in] box extents
319 *      \return         true if the LSS contains the whole box
320 */
321///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
322inline_ BOOL LSSCollider::LSSContainsBox(const Point& bc, const Point& be)
323{
324        // Not implemented
325        return FALSE;
326}
327
328#define TEST_BOX_IN_LSS(center, extents)        \
329        if(LSSContainsBox(center, extents))             \
330        {                                                                               \
331                /* Set contact status */                        \
332                mFlags |= OPC_CONTACT;                          \
333                _Dump(node);                                            \
334                return;                                                         \
335        }
336
337///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
338/**
339 *      Recursive collision query for normal AABB trees.
340 *      \param          node    [in] current collision node
341 */
342///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
343void LSSCollider::_Collide(const AABBCollisionNode* node)
344{
345        // Perform LSS-AABB overlap test
346        if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))  return;
347
348        TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
349
350        if(node->IsLeaf())
351        {
352                LSS_PRIM(node->GetPrimitive(), OPC_CONTACT)
353        }
354        else
355        {
356                _Collide(node->GetPos());
357
358                if(ContactFound()) return;
359
360                _Collide(node->GetNeg());
361        }
362}
363
364///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
365/**
366 *      Recursive collision query for normal AABB trees, without primitive tests.
367 *      \param          node    [in] current collision node
368 */
369///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
370void LSSCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node)
371{
372        // Perform LSS-AABB overlap test
373        if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))  return;
374
375        TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
376
377        if(node->IsLeaf())
378        {
379                SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
380        }
381        else
382        {
383                _CollideNoPrimitiveTest(node->GetPos());
384
385                if(ContactFound()) return;
386
387                _CollideNoPrimitiveTest(node->GetNeg());
388        }
389}
390
391///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
392/**
393 *      Recursive collision query for quantized AABB trees.
394 *      \param          node    [in] current collision node
395 */
396///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
397void LSSCollider::_Collide(const AABBQuantizedNode* node)
398{
399        // Dequantize box
400        const QuantizedAABB& Box = node->mAABB;
401        const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
402        const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
403
404        // Perform LSS-AABB overlap test
405        if(!LSSAABBOverlap(Center, Extents))    return;
406
407        TEST_BOX_IN_LSS(Center, Extents)
408
409        if(node->IsLeaf())
410        {
411                LSS_PRIM(node->GetPrimitive(), OPC_CONTACT)
412        }
413        else
414        {
415                _Collide(node->GetPos());
416
417                if(ContactFound()) return;
418
419                _Collide(node->GetNeg());
420        }
421}
422
423///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
424/**
425 *      Recursive collision query for quantized AABB trees, without primitive tests.
426 *      \param          node    [in] current collision node
427 */
428///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
429void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node)
430{
431        // Dequantize box
432        const QuantizedAABB& Box = node->mAABB;
433        const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
434        const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
435
436        // Perform LSS-AABB overlap test
437        if(!LSSAABBOverlap(Center, Extents))    return;
438
439        TEST_BOX_IN_LSS(Center, Extents)
440
441        if(node->IsLeaf())
442        {
443                SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
444        }
445        else
446        {
447                _CollideNoPrimitiveTest(node->GetPos());
448
449                if(ContactFound()) return;
450
451                _CollideNoPrimitiveTest(node->GetNeg());
452        }
453}
454
455///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
456/**
457 *      Recursive collision query for no-leaf AABB trees.
458 *      \param          node    [in] current collision node
459 */
460///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
461void LSSCollider::_Collide(const AABBNoLeafNode* node)
462{
463        // Perform LSS-AABB overlap test
464        if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))  return;
465
466        TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
467
468        if(node->HasPosLeaf())  { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
469        else                                    _Collide(node->GetPos());
470
471        if(ContactFound()) return;
472
473        if(node->HasNegLeaf())  { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
474        else                                    _Collide(node->GetNeg());
475}
476
477///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
478/**
479 *      Recursive collision query for no-leaf AABB trees, without primitive tests.
480 *      \param          node    [in] current collision node
481 */
482///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
483void LSSCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node)
484{
485        // Perform LSS-AABB overlap test
486        if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents))  return;
487
488        TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents)
489
490        if(node->HasPosLeaf())  { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
491        else                                    _CollideNoPrimitiveTest(node->GetPos());
492
493        if(ContactFound()) return;
494
495        if(node->HasNegLeaf())  { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
496        else                                    _CollideNoPrimitiveTest(node->GetNeg());
497}
498
499///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
500/**
501 *      Recursive collision query for quantized no-leaf AABB trees.
502 *      \param          node    [in] current collision node
503 */
504///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
505void LSSCollider::_Collide(const AABBQuantizedNoLeafNode* node)
506{
507        // Dequantize box
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);
511
512        // Perform LSS-AABB overlap test
513        if(!LSSAABBOverlap(Center, Extents))    return;
514
515        TEST_BOX_IN_LSS(Center, Extents)
516
517        if(node->HasPosLeaf())  { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
518        else                                    _Collide(node->GetPos());
519
520        if(ContactFound()) return;
521
522        if(node->HasNegLeaf())  { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
523        else                                    _Collide(node->GetNeg());
524}
525
526///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
527/**
528 *      Recursive collision query for quantized no-leaf AABB trees, without primitive tests.
529 *      \param          node    [in] current collision node
530 */
531///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
532void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node)
533{
534        // Dequantize box
535        const QuantizedAABB& Box = node->mAABB;
536        const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
537        const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
538
539        // Perform LSS-AABB overlap test
540        if(!LSSAABBOverlap(Center, Extents))    return;
541
542        TEST_BOX_IN_LSS(Center, Extents)
543
544        if(node->HasPosLeaf())  { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
545        else                                    _CollideNoPrimitiveTest(node->GetPos());
546
547        if(ContactFound()) return;
548
549        if(node->HasNegLeaf())  { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
550        else                                    _CollideNoPrimitiveTest(node->GetNeg());
551}
552
553///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
554/**
555 *      Recursive collision query for vanilla AABB trees.
556 *      \param          node    [in] current collision node
557 */
558///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
559void LSSCollider::_Collide(const AABBTreeNode* node)
560{
561        // Perform LSS-AABB overlap test
562        Point Center, Extents;
563        node->GetAABB()->GetCenter(Center);
564        node->GetAABB()->GetExtents(Extents);
565        if(!LSSAABBOverlap(Center, Extents))    return;
566
567        if(node->IsLeaf() || LSSContainsBox(Center, Extents))
568        {
569                mFlags |= OPC_CONTACT;
570                mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives());
571        }
572        else
573        {
574                _Collide(node->GetPos());
575                _Collide(node->GetNeg());
576        }
577}
578
579
580
581
582
583
584///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
585/**
586 *      Constructor.
587 */
588///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
589HybridLSSCollider::HybridLSSCollider()
590{
591}
592
593///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
594/**
595 *      Destructor.
596 */
597///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
598HybridLSSCollider::~HybridLSSCollider()
599{
600}
601
602bool HybridLSSCollider::Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl, const Matrix4x4* worldm)
603{
604        // We don't want primitive tests here!
605        mFlags |= OPC_NO_PRIMITIVE_TESTS;
606
607        // Checkings
608        if(!Setup(&model))      return false;
609
610        // Init collision query
611        if(InitQuery(cache, lss, worldl, worldm))       return true;
612
613        // Special case for 1-leaf trees
614        if(mCurrentModel && mCurrentModel->HasSingleNode())
615        {
616                // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
617                udword Nb = mIMesh->GetNbTriangles();
618
619                // Loop through all triangles
620                for(udword i=0;i<Nb;i++)
621                {
622                        LSS_PRIM(i, OPC_CONTACT)
623                }
624                return true;
625        }
626
627        // Override destination array since we're only going to get leaf boxes here
628        mTouchedBoxes.Reset();
629        mTouchedPrimitives = &mTouchedBoxes;
630
631        // Now, do the actual query against leaf boxes
632        if(!model.HasLeafNodes())
633        {
634                if(model.IsQuantized())
635                {
636                        const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
637
638                        // Setup dequantization coeffs
639                        mCenterCoeff    = Tree->mCenterCoeff;
640                        mExtentsCoeff   = Tree->mExtentsCoeff;
641
642                        // Perform collision query - we don't want primitive tests here!
643                        _CollideNoPrimitiveTest(Tree->GetNodes());
644                }
645                else
646                {
647                        const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
648
649                        // Perform collision query - we don't want primitive tests here!
650                        _CollideNoPrimitiveTest(Tree->GetNodes());
651                }
652        }
653        else
654        {
655                if(model.IsQuantized())
656                {
657                        const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
658
659                        // Setup dequantization coeffs
660                        mCenterCoeff    = Tree->mCenterCoeff;
661                        mExtentsCoeff   = Tree->mExtentsCoeff;
662
663                        // Perform collision query - we don't want primitive tests here!
664                        _CollideNoPrimitiveTest(Tree->GetNodes());
665                }
666                else
667                {
668                        const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
669
670                        // Perform collision query - we don't want primitive tests here!
671                        _CollideNoPrimitiveTest(Tree->GetNodes());
672                }
673        }
674
675        // We only have a list of boxes so far
676        if(GetContactStatus())
677        {
678                // Reset contact status, since it currently only reflects collisions with leaf boxes
679                Collider::InitQuery();
680
681                // Change dest container so that we can use built-in overlap tests and get collided primitives
682                cache.TouchedPrimitives.Reset();
683                mTouchedPrimitives = &cache.TouchedPrimitives;
684
685                // Read touched leaf boxes
686                udword Nb = mTouchedBoxes.GetNbEntries();
687                const udword* Touched = mTouchedBoxes.GetEntries();
688
689                const LeafTriangles* LT = model.GetLeafTriangles();
690                const udword* Indices = model.GetIndices();
691
692                // Loop through touched leaves
693                while(Nb--)
694                {
695                        const LeafTriangles& CurrentLeaf = LT[*Touched++];
696
697                        // Each leaf box has a set of triangles
698                        udword NbTris = CurrentLeaf.GetNbTriangles();
699                        if(Indices)
700                        {
701                                const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
702
703                                // Loop through triangles and test each of them
704                                while(NbTris--)
705                                {
706                                        udword TriangleIndex = *T++;
707                                        LSS_PRIM(TriangleIndex, OPC_CONTACT)
708                                }
709                        }
710                        else
711                        {
712                                udword BaseIndex = CurrentLeaf.GetTriangleIndex();
713
714                                // Loop through triangles and test each of them
715                                while(NbTris--)
716                                {
717                                        udword TriangleIndex = BaseIndex++;
718                                        LSS_PRIM(TriangleIndex, OPC_CONTACT)
719                                }
720                        }
721                }
722        }
723
724        return true;
725}
Note: See TracBrowser for help on using the repository browser.