00001
00002
00003
00004
00005
00006
00008
00010
00016
00017
00019
00027
00028
00030
00031 #include "Stdafx.h"
00032
00033 using namespace Opcode;
00034
00035 #include "OPC_PlanesAABBOverlap.h"
00036 #include "OPC_PlanesTriOverlap.h"
00037
00038 #define SET_CONTACT(prim_index, flag) \
00039 \
00040 mFlags |= flag; \
00041 mTouchedPrimitives->Add(prim_index);
00042
00044 #define PLANES_PRIM(prim_index, flag) \
00045 \
00046 mIMesh->GetTriangle(mVP, prim_index); \
00047 \
00048 if(PlanesTriOverlap(clip_mask)) \
00049 { \
00050 SET_CONTACT(prim_index, flag) \
00051 }
00052
00054
00057
00058 PlanesCollider::PlanesCollider() :
00059 collisionPairInserter(NULL),
00060 mNbPlanes (0),
00061 mPlanes (null)
00062 {
00063 }
00064
00066
00069
00070 PlanesCollider::~PlanesCollider()
00071 {
00072 DELETEARRAY(mPlanes);
00073 }
00074
00076
00080
00081 const char* PlanesCollider::ValidateSettings()
00082 {
00083 if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!";
00084
00085 return VolumeCollider::ValidateSettings();
00086 }
00087
00089
00103
00104 bool PlanesCollider::Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const Model& model, const Matrix4x4* worldm)
00105 {
00106
00107 if(!Setup(&model)) return false;
00108
00109
00110 if(InitQuery(cache, planes, nb_planes, worldm)) return true;
00111
00112 udword PlaneMask = (1<<nb_planes)-1;
00113
00114 if(!model.HasLeafNodes())
00115 {
00116 if(model.IsQuantized())
00117 {
00118 const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
00119
00120
00121 mCenterCoeff = Tree->mCenterCoeff;
00122 mExtentsCoeff = Tree->mExtentsCoeff;
00123
00124
00125 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
00126 else _Collide(Tree->GetNodes(), PlaneMask);
00127 }
00128 else
00129 {
00130 const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
00131
00132
00133 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
00134 else _Collide(Tree->GetNodes(), PlaneMask);
00135 }
00136 }
00137 else
00138 {
00139 if(model.IsQuantized())
00140 {
00141 const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
00142
00143
00144 mCenterCoeff = Tree->mCenterCoeff;
00145 mExtentsCoeff = Tree->mExtentsCoeff;
00146
00147
00148 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
00149 else _Collide(Tree->GetNodes(), PlaneMask);
00150 }
00151 else
00152 {
00153 const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
00154
00155
00156 if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
00157 else _Collide(Tree->GetNodes(), PlaneMask);
00158 }
00159 }
00160 return true;
00161 }
00162
00164
00177
00178 BOOL PlanesCollider::InitQuery(PlanesCache& cache, const Plane* planes, udword nb_planes, const Matrix4x4* worldm)
00179 {
00180
00181 VolumeCollider::InitQuery();
00182
00183
00184 if(nb_planes>mNbPlanes)
00185 {
00186 DELETEARRAY(mPlanes);
00187 mPlanes = new Plane[nb_planes];
00188 }
00189 mNbPlanes = nb_planes;
00190
00191 if(worldm)
00192 {
00193 Matrix4x4 InvWorldM;
00194 InvertPRMatrix(InvWorldM, *worldm);
00195
00196
00197 for(udword i=0;i<nb_planes;i++) TransformPlane(mPlanes[i], planes[i], InvWorldM);
00198 }
00199 else CopyMemory(mPlanes, planes, nb_planes*sizeof(Plane));
00200
00201
00202 mTouchedPrimitives = &cache.TouchedPrimitives;
00203
00204
00205 if(mCurrentModel && mCurrentModel->HasSingleNode())
00206 {
00207 if(!SkipPrimitiveTests())
00208 {
00209
00210 mTouchedPrimitives->Reset();
00211
00212
00213 udword clip_mask = (1<<mNbPlanes)-1;
00214 PLANES_PRIM(udword(0), OPC_CONTACT)
00215
00216
00217 return TRUE;
00218 }
00219 }
00220
00221
00222 if(TemporalCoherenceEnabled())
00223 {
00224
00225
00226 if(FirstContactEnabled())
00227 {
00228
00229 if(mTouchedPrimitives->GetNbEntries())
00230 {
00231
00232 udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
00233
00234
00235
00236
00237 mTouchedPrimitives->Reset();
00238
00239
00240 udword clip_mask = (1<<mNbPlanes)-1;
00241 PLANES_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
00242
00243
00244 if(GetContactStatus()) return TRUE;
00245 }
00246
00247
00248 }
00249 else mTouchedPrimitives->Reset();
00250 }
00251 else
00252 {
00253
00254 mTouchedPrimitives->Reset();
00255 }
00256
00257 return FALSE;
00258 }
00259
00260 #define TEST_CLIP_MASK \
00261 \
00262 \
00263 if(!OutClipMask) \
00264 { \
00265 \
00266 mFlags |= OPC_CONTACT; \
00267 _Dump(node); \
00268 return; \
00269 }
00270
00272
00276
00277 void PlanesCollider::_Collide(const AABBCollisionNode* node, udword clip_mask)
00278 {
00279
00280 udword OutClipMask;
00281 if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return;
00282
00283 TEST_CLIP_MASK
00284
00285
00286 if(node->IsLeaf())
00287 {
00288 PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT)
00289 }
00290 else
00291 {
00292 _Collide(node->GetPos(), OutClipMask);
00293
00294 if(ContactFound()) return;
00295
00296 _Collide(node->GetNeg(), OutClipMask);
00297 }
00298 }
00299
00301
00305
00306 void PlanesCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node, udword clip_mask)
00307 {
00308
00309 udword OutClipMask;
00310 if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return;
00311
00312 TEST_CLIP_MASK
00313
00314
00315 if(node->IsLeaf())
00316 {
00317 SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
00318 }
00319 else
00320 {
00321 _CollideNoPrimitiveTest(node->GetPos(), OutClipMask);
00322
00323 if(ContactFound()) return;
00324
00325 _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask);
00326 }
00327 }
00328
00330
00334
00335 void PlanesCollider::_Collide(const AABBQuantizedNode* node, udword clip_mask)
00336 {
00337
00338 const QuantizedAABB& Box = node->mAABB;
00339 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
00340 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
00341
00342
00343 udword OutClipMask;
00344 if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return;
00345
00346 TEST_CLIP_MASK
00347
00348
00349 if(node->IsLeaf())
00350 {
00351 PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT)
00352 }
00353 else
00354 {
00355 _Collide(node->GetPos(), OutClipMask);
00356
00357 if(ContactFound()) return;
00358
00359 _Collide(node->GetNeg(), OutClipMask);
00360 }
00361 }
00362
00364
00368
00369 void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node, udword clip_mask)
00370 {
00371
00372 const QuantizedAABB& Box = node->mAABB;
00373 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
00374 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
00375
00376
00377 udword OutClipMask;
00378 if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return;
00379
00380 TEST_CLIP_MASK
00381
00382
00383 if(node->IsLeaf())
00384 {
00385 SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
00386 }
00387 else
00388 {
00389 _CollideNoPrimitiveTest(node->GetPos(), OutClipMask);
00390
00391 if(ContactFound()) return;
00392
00393 _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask);
00394 }
00395 }
00396
00398
00402
00403 void PlanesCollider::_Collide(const AABBNoLeafNode* node, udword clip_mask)
00404 {
00405
00406 udword OutClipMask;
00407 if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return;
00408
00409 TEST_CLIP_MASK
00410
00411
00412 if(node->HasPosLeaf()) { PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
00413 else _Collide(node->GetPos(), OutClipMask);
00414
00415 if(ContactFound()) return;
00416
00417 if(node->HasNegLeaf()) { PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
00418 else _Collide(node->GetNeg(), OutClipMask);
00419 }
00420
00422
00426
00427 void PlanesCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node, udword clip_mask)
00428 {
00429
00430 udword OutClipMask;
00431 if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return;
00432
00433 TEST_CLIP_MASK
00434
00435
00436 if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
00437 else _CollideNoPrimitiveTest(node->GetPos(), OutClipMask);
00438
00439 if(ContactFound()) return;
00440
00441 if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
00442 else _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask);
00443 }
00444
00446
00450
00451 void PlanesCollider::_Collide(const AABBQuantizedNoLeafNode* node, udword clip_mask)
00452 {
00453
00454 const QuantizedAABB& Box = node->mAABB;
00455 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
00456 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
00457
00458
00459 udword OutClipMask;
00460 if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return;
00461
00462 TEST_CLIP_MASK
00463
00464
00465 if(node->HasPosLeaf()) { PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
00466 else _Collide(node->GetPos(), OutClipMask);
00467
00468 if(ContactFound()) return;
00469
00470 if(node->HasNegLeaf()) { PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
00471 else _Collide(node->GetNeg(), OutClipMask);
00472 }
00473
00475
00479
00480 void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node, udword clip_mask)
00481 {
00482
00483 const QuantizedAABB& Box = node->mAABB;
00484 const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
00485 const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
00486
00487
00488 udword OutClipMask;
00489 if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return;
00490
00491 TEST_CLIP_MASK
00492
00493
00494 if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
00495 else _CollideNoPrimitiveTest(node->GetPos(), OutClipMask);
00496
00497 if(ContactFound()) return;
00498
00499 if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
00500 else _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask);
00501 }
00502
00503
00504
00505
00506
00507
00508
00510
00513
00514 HybridPlanesCollider::HybridPlanesCollider()
00515 {
00516 }
00517
00519
00522
00523 HybridPlanesCollider::~HybridPlanesCollider()
00524 {
00525 }
00526
00527 bool HybridPlanesCollider::Collide(PlanesCache& cache, const Plane* planes, udword nb_planes, const HybridModel& model, const Matrix4x4* worldm)
00528 {
00529
00530 mFlags |= OPC_NO_PRIMITIVE_TESTS;
00531
00532
00533 if(!Setup(&model)) return false;
00534
00535
00536 if(InitQuery(cache, planes, nb_planes, worldm)) return true;
00537
00538
00539 if(mCurrentModel && mCurrentModel->HasSingleNode())
00540 {
00541
00542 udword Nb = mIMesh->GetNbTriangles();
00543
00544
00545 udword clip_mask = (1<<mNbPlanes)-1;
00546 for(udword i=0;i<Nb;i++)
00547 {
00548 PLANES_PRIM(i, OPC_CONTACT)
00549 }
00550 return true;
00551 }
00552
00553
00554 mTouchedBoxes.Reset();
00555 mTouchedPrimitives = &mTouchedBoxes;
00556
00557 udword PlaneMask = (1<<nb_planes)-1;
00558
00559
00560 if(!model.HasLeafNodes())
00561 {
00562 if(model.IsQuantized())
00563 {
00564 const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
00565
00566
00567 mCenterCoeff = Tree->mCenterCoeff;
00568 mExtentsCoeff = Tree->mExtentsCoeff;
00569
00570
00571 _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
00572 }
00573 else
00574 {
00575 const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
00576
00577
00578 _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
00579 }
00580 }
00581 else
00582 {
00583 if(model.IsQuantized())
00584 {
00585 const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
00586
00587
00588 mCenterCoeff = Tree->mCenterCoeff;
00589 mExtentsCoeff = Tree->mExtentsCoeff;
00590
00591
00592 _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
00593 }
00594 else
00595 {
00596 const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
00597
00598
00599 _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask);
00600 }
00601 }
00602
00603
00604 if(GetContactStatus())
00605 {
00606
00607 Collider::InitQuery();
00608
00609
00610 cache.TouchedPrimitives.Reset();
00611 mTouchedPrimitives = &cache.TouchedPrimitives;
00612
00613
00614 udword Nb = mTouchedBoxes.GetNbEntries();
00615 const udword* Touched = mTouchedBoxes.GetEntries();
00616
00617 const LeafTriangles* LT = model.GetLeafTriangles();
00618 const udword* Indices = model.GetIndices();
00619
00620
00621 udword clip_mask = (1<<mNbPlanes)-1;
00622 while(Nb--)
00623 {
00624 const LeafTriangles& CurrentLeaf = LT[*Touched++];
00625
00626
00627 udword NbTris = CurrentLeaf.GetNbTriangles();
00628 if(Indices)
00629 {
00630 const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
00631
00632
00633 while(NbTris--)
00634 {
00635 udword TriangleIndex = *T++;
00636 PLANES_PRIM(TriangleIndex, OPC_CONTACT)
00637 }
00638 }
00639 else
00640 {
00641 udword BaseIndex = CurrentLeaf.GetTriangleIndex();
00642
00643
00644 while(NbTris--)
00645 {
00646 udword TriangleIndex = BaseIndex++;
00647 PLANES_PRIM(TriangleIndex, OPC_CONTACT)
00648 }
00649 }
00650 }
00651 }
00652
00653 return true;
00654 }