Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Opcode::SphereCollider Class Reference

#include <Opcode.h>

Inheritance diagram for Opcode::SphereCollider:
Opcode::VolumeCollider Opcode::Collider Opcode::HybridSphereCollider

Public Member Functions

 SphereCollider ()
 
virtual ~SphereCollider ()
 
bool Collide (SphereCache &cache, const Sphere &sphere, const Model &model, const Matrix4x4 *worlds=null, const Matrix4x4 *worldm=null)
 
bool Collide (SphereCache &cache, const Sphere &sphere, const AABBTree *tree)
 
- Public Member Functions inherited from Opcode::VolumeCollider
 VolumeCollider ()
 
virtual ~VolumeCollider ()=0
 
inline_ udword GetNbTouchedPrimitives () const
 
inline_ const udwordGetTouchedPrimitives () const
 
inline_ udword GetNbVolumeBVTests () const
 
inline_ udword GetNbVolumePrimTests () const
 
 override (Collider) const char *ValidateSettings()
 
- Public Member Functions inherited from Opcode::Collider
 Collider ()
 
virtual ~Collider ()
 
inline_ BOOL GetContactStatus () const
 
inline_ BOOL FirstContactEnabled () const
 
inline_ BOOL TemporalCoherenceEnabled () const
 
inline_ BOOL ContactFound () const
 
inline_ BOOL TemporalHit () const
 
inline_ BOOL SkipPrimitiveTests () const
 
inline_ void SetFirstContact (bool flag)
 
inline_ void SetTemporalCoherence (bool flag)
 
inline_ void SetPrimitiveTests (bool flag)
 
virtual const char * ValidateSettings ()=0
 

Protected Member Functions

void _Collide (const AABBCollisionNode *node)
 
void _Collide (const AABBNoLeafNode *node)
 
void _Collide (const AABBQuantizedNode *node)
 
void _Collide (const AABBQuantizedNoLeafNode *node)
 
void _Collide (const AABBTreeNode *node)
 
void _CollideNoPrimitiveTest (const AABBCollisionNode *node)
 
void _CollideNoPrimitiveTest (const AABBNoLeafNode *node)
 
void _CollideNoPrimitiveTest (const AABBQuantizedNode *node)
 
void _CollideNoPrimitiveTest (const AABBQuantizedNoLeafNode *node)
 
inline_ bool SphereContainsBox (const Point &bc, const Point &be)
 
inline_ bool SphereAABBOverlap (const Point &center, const Point &extents)
 
bool SphereTriOverlap (const Point &vert0, const Point &vert1, const Point &vert2)
 
bool InitQuery (SphereCache &cache, const Sphere &sphere, const Matrix4x4 *worlds=null, const Matrix4x4 *worldm=null)
 
- Protected Member Functions inherited from Opcode::VolumeCollider
void _Dump (const AABBCollisionNode *node)
 
void _Dump (const AABBNoLeafNode *node)
 
void _Dump (const AABBQuantizedNode *node)
 
void _Dump (const AABBQuantizedNoLeafNode *node)
 
 override (Collider) inline_ void InitQuery()
 
inline_ BOOL IsCacheValid (VolumeCache &cache)
 
- Protected Member Functions inherited from Opcode::Collider
inline_ BOOL Setup (const BaseModel *model)
 
virtual inline_ void InitQuery ()
 

Protected Attributes

Point mCenter
 Sphere center. More...
 
float mRadius2
 Sphere radius squared. More...
 
- Protected Attributes inherited from Opcode::VolumeCollider
ContainermTouchedPrimitives
 List of touched primitives. More...
 
Point mCenterCoeff
 
Point mExtentsCoeff
 
udword mNbVolumeBVTests
 Number of Volume-BV tests. More...
 
udword mNbVolumePrimTests
 Number of Volume-Primitive tests. More...
 
- Protected Attributes inherited from Opcode::Collider
udword mFlags
 Bit flags. More...
 
const BaseModelmCurrentModel
 Current model for collision query (owner of touched faces) More...
 
const MeshInterfacemIMesh
 User-defined mesh interface. More...
 

Detailed Description

Definition at line 36 of file Opcode.h.

Constructor & Destructor Documentation

SphereCollider::SphereCollider ( )

Constructor.

Definition at line 64 of file OPC_SphereCollider.cpp.

65 {
66  mCenter.Zero();
67  mRadius2 = 0.0f;
68 }
SphereCollider::~SphereCollider ( )
virtual

Destructor.

Definition at line 75 of file OPC_SphereCollider.cpp.

76 {
77 }

Member Function Documentation

void SphereCollider::_Collide ( const AABBCollisionNode node)
protected

Recursive collision query for normal AABB trees.

Parameters
node[in] current collision node

Definition at line 344 of file OPC_SphereCollider.cpp.

345 {
346  // Perform Sphere-AABB overlap test
347  if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
348 
349  TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents)
350 
351  if(node->IsLeaf())
352  {
353  SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT)
354  }
355  else
356  {
357  _Collide(node->GetPos());
358 
359  if(ContactFound()) return;
360 
361  _Collide(node->GetNeg());
362  }
363 }
void SphereCollider::_Collide ( const AABBNoLeafNode node)
protected

Recursive collision query for no-leaf AABB trees.

Parameters
node[in] current collision node

Definition at line 462 of file OPC_SphereCollider.cpp.

463 {
464  // Perform Sphere-AABB overlap test
465  if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
466 
467  TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents)
468 
469  if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
470  else _Collide(node->GetPos());
471 
472  if(ContactFound()) return;
473 
474  if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
475  else _Collide(node->GetNeg());
476 }
void SphereCollider::_Collide ( const AABBQuantizedNode node)
protected

Recursive collision query for quantized AABB trees.

Parameters
node[in] current collision node

Definition at line 398 of file OPC_SphereCollider.cpp.

399 {
400  // Dequantize box
401  const QuantizedAABB& Box = node->mAABB;
402  const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
403  const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
404 
405  // Perform Sphere-AABB overlap test
406  if(!SphereAABBOverlap(Center, Extents)) return;
407 
408  TEST_BOX_IN_SPHERE(Center, Extents)
409 
410  if(node->IsLeaf())
411  {
412  SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT)
413  }
414  else
415  {
416  _Collide(node->GetPos());
417 
418  if(ContactFound()) return;
419 
420  _Collide(node->GetNeg());
421  }
422 }
void SphereCollider::_Collide ( const AABBQuantizedNoLeafNode node)
protected

Recursive collision query for quantized no-leaf AABB trees.

Parameters
node[in] current collision node

Definition at line 506 of file OPC_SphereCollider.cpp.

507 {
508  // Dequantize box
509  const QuantizedAABB& Box = node->mAABB;
510  const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
511  const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
512 
513  // Perform Sphere-AABB overlap test
514  if(!SphereAABBOverlap(Center, Extents)) return;
515 
516  TEST_BOX_IN_SPHERE(Center, Extents)
517 
518  if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
519  else _Collide(node->GetPos());
520 
521  if(ContactFound()) return;
522 
523  if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
524  else _Collide(node->GetNeg());
525 }
void SphereCollider::_Collide ( const AABBTreeNode node)
protected

Recursive collision query for vanilla AABB trees.

Parameters
node[in] current collision node

Definition at line 560 of file OPC_SphereCollider.cpp.

561 {
562  // Perform Sphere-AABB overlap test
563  Point Center, Extents;
564  node->GetAABB()->GetCenter(Center);
565  node->GetAABB()->GetExtents(Extents);
566  if(!SphereAABBOverlap(Center, Extents)) return;
567 
568  if(node->IsLeaf() || SphereContainsBox(Center, Extents))
569  {
570  mFlags |= OPC_CONTACT;
572  }
573  else
574  {
575  _Collide(node->GetPos());
576  _Collide(node->GetNeg());
577  }
578 }
void SphereCollider::_CollideNoPrimitiveTest ( const AABBCollisionNode node)
protected

Recursive collision query for normal AABB trees, without primitive tests.

Parameters
node[in] current collision node

Definition at line 371 of file OPC_SphereCollider.cpp.

Referenced by Opcode::HybridSphereCollider::Collide().

372 {
373  // Perform Sphere-AABB overlap test
374  if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
375 
376  TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents)
377 
378  if(node->IsLeaf())
379  {
380  SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
381  }
382  else
383  {
384  _CollideNoPrimitiveTest(node->GetPos());
385 
386  if(ContactFound()) return;
387 
388  _CollideNoPrimitiveTest(node->GetNeg());
389  }
390 }
void SphereCollider::_CollideNoPrimitiveTest ( const AABBNoLeafNode node)
protected

Recursive collision query for no-leaf AABB trees, without primitive tests.

Parameters
node[in] current collision node

Definition at line 484 of file OPC_SphereCollider.cpp.

485 {
486  // Perform Sphere-AABB overlap test
487  if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
488 
489  TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents)
490 
491  if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
492  else _CollideNoPrimitiveTest(node->GetPos());
493 
494  if(ContactFound()) return;
495 
496  if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
497  else _CollideNoPrimitiveTest(node->GetNeg());
498 }
void SphereCollider::_CollideNoPrimitiveTest ( const AABBQuantizedNode node)
protected

Recursive collision query for quantized AABB trees, without primitive tests.

Parameters
node[in] current collision node

Definition at line 430 of file OPC_SphereCollider.cpp.

431 {
432  // Dequantize box
433  const QuantizedAABB& Box = node->mAABB;
434  const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
435  const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
436 
437  // Perform Sphere-AABB overlap test
438  if(!SphereAABBOverlap(Center, Extents)) return;
439 
440  TEST_BOX_IN_SPHERE(Center, Extents)
441 
442  if(node->IsLeaf())
443  {
444  SET_CONTACT(node->GetPrimitive(), OPC_CONTACT)
445  }
446  else
447  {
448  _CollideNoPrimitiveTest(node->GetPos());
449 
450  if(ContactFound()) return;
451 
452  _CollideNoPrimitiveTest(node->GetNeg());
453  }
454 }
void SphereCollider::_CollideNoPrimitiveTest ( const AABBQuantizedNoLeafNode node)
protected

Recursive collision query for quantized no-leaf AABB trees, without primitive tests.

Parameters
node[in] current collision node

Definition at line 533 of file OPC_SphereCollider.cpp.

534 {
535  // Dequantize box
536  const QuantizedAABB& Box = node->mAABB;
537  const Point Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z);
538  const Point Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z);
539 
540  // Perform Sphere-AABB overlap test
541  if(!SphereAABBOverlap(Center, Extents)) return;
542 
543  TEST_BOX_IN_SPHERE(Center, Extents)
544 
545  if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) }
546  else _CollideNoPrimitiveTest(node->GetPos());
547 
548  if(ContactFound()) return;
549 
550  if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) }
551  else _CollideNoPrimitiveTest(node->GetNeg());
552 }
bool SphereCollider::Collide ( SphereCache cache,
const Sphere sphere,
const Model model,
const Matrix4x4 worlds = null,
const Matrix4x4 worldm = null 
)

Generic collision query for generic OPCODE models. After the call, access the results:

Parameters
cache[in/out] a sphere cache
sphere[in] collision sphere in local space
model[in] Opcode model to collide with
worlds[in] sphere's world matrix, or null
worldm[in] model's world matrix, or null
Returns
true if success
Warning
SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.

Definition at line 95 of file OPC_SphereCollider.cpp.

96 {
97  // Checkings
98  if(!Setup(&model)) return false;
99 
100  // Init collision query
101  if(InitQuery(cache, sphere, worlds, worldm)) return true;
102 
103  if(!model.HasLeafNodes())
104  {
105  if(model.IsQuantized())
106  {
107  const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
108 
109  // Setup dequantization coeffs
110  mCenterCoeff = Tree->mCenterCoeff;
112 
113  // Perform collision query
114  if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
115  else _Collide(Tree->GetNodes());
116  }
117  else
118  {
119  const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
120 
121  // Perform collision query
122  if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
123  else _Collide(Tree->GetNodes());
124  }
125  }
126  else
127  {
128  if(model.IsQuantized())
129  {
130  const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
131 
132  // Setup dequantization coeffs
133  mCenterCoeff = Tree->mCenterCoeff;
135 
136  // Perform collision query
137  if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
138  else _Collide(Tree->GetNodes());
139  }
140  else
141  {
142  const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
143 
144  // Perform collision query
145  if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
146  else _Collide(Tree->GetNodes());
147  }
148  }
149  return true;
150 }
bool SphereCollider::Collide ( SphereCache cache,
const Sphere sphere,
const AABBTree tree 
)

Collision query for vanilla AABB trees.

Parameters
cache[in/out] a sphere cache
sphere[in] collision sphere in world space
tree[in] AABB tree
Returns
true if success

Definition at line 285 of file OPC_SphereCollider.cpp.

286 {
287  // This is typically called for a scene tree, full of -AABBs-, not full of triangles.
288  // So we don't really have "primitives" to deal with. Hence it doesn't work with
289  // "FirstContact" + "TemporalCoherence".
291 
292  // Checkings
293  if(!tree) return false;
294 
295  // Init collision query
296  if(InitQuery(cache, sphere)) return true;
297 
298  // Perform collision query
299  _Collide(tree);
300 
301  return true;
302 }
bool SphereCollider::InitQuery ( SphereCache cache,
const Sphere sphere,
const Matrix4x4 worlds = null,
const Matrix4x4 worldm = null 
)
protected

Initializes a collision query :

  • reset stats & contact status
  • setup matrices
  • check temporal coherence
Parameters
cache[in/out] a sphere cache
sphere[in] sphere in local space
worlds[in] sphere's world matrix, or null
worldm[in] model's world matrix, or null
Returns
TRUE if we can return immediately
Warning
SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.

Definition at line 167 of file OPC_SphereCollider.cpp.

168 {
169  // 1) Call the base method
171 
172  // 2) Compute sphere in model space:
173  // - Precompute R^2
174  mRadius2 = sphere.mRadius * sphere.mRadius;
175  // - Compute center position
176  mCenter = sphere.mCenter;
177  // -> to world space
178  if(worlds) mCenter *= *worlds;
179  // -> to model space
180  if(worldm)
181  {
182  // Invert model matrix
183  Matrix4x4 InvWorldM;
184  InvertPRMatrix(InvWorldM, *worldm);
185 
186  mCenter *= InvWorldM;
187  }
188 
189  // 3) Setup destination pointer
191 
192  // 4) Special case: 1-triangle meshes [Opcode 1.3]
194  {
195  if(!SkipPrimitiveTests())
196  {
197  // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
199 
200  // Perform overlap test between the unique triangle and the sphere (and set contact status if needed)
202 
203  // Return immediately regardless of status
204  return TRUE;
205  }
206  }
207 
208  // 5) Check temporal coherence :
210  {
211  // Here we use temporal coherence
212  // => check results from previous frame before performing the collision query
213  if(FirstContactEnabled())
214  {
215  // We're only interested in the first contact found => test the unique previously touched face
217  {
218  // Get index of previously touched face = the first entry in the array
219  udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
220 
221  // Then reset the array:
222  // - if the overlap test below is successful, the index we'll get added back anyway
223  // - if it isn't, then the array should be reset anyway for the normal query
225 
226  // Perform overlap test between the cached triangle and the sphere (and set contact status if needed)
227  SPHERE_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
228 
229  // Return immediately if possible
230  if(GetContactStatus()) return TRUE;
231  }
232  // else no face has been touched during previous query
233  // => we'll have to perform a normal query
234  }
235  else
236  {
237  // We're interested in all contacts =>test the new real sphere N(ew) against the previous fat sphere P(revious):
238  float r = sqrtf(cache.FatRadius2) - sphere.mRadius;
239  if(IsCacheValid(cache) && cache.Center.SquareDistance(mCenter) < r*r)
240  {
241  // - if N is included in P, return previous list
242  // => we simply leave the list (mTouchedFaces) unchanged
243 
244  // Set contact status if needed
246 
247  // In any case we don't need to do a query
248  return TRUE;
249  }
250  else
251  {
252  // - else do the query using a fat N
253 
254  // Reset cache since we'll about to perform a real query
256 
257  // Make a fat sphere so that coherence will work for subsequent frames
258  mRadius2 *= cache.FatCoeff;
259 // mRadius2 = (sphere.mRadius * cache.FatCoeff)*(sphere.mRadius * cache.FatCoeff);
260 
261  // Update cache with query data (signature for cached faces)
262  cache.Center = mCenter;
263  cache.FatRadius2 = mRadius2;
264  }
265  }
266  }
267  else
268  {
269  // Here we don't use temporal coherence => do a normal query
271  }
272 
273  return FALSE;
274 }
inline_ bool Opcode::SphereCollider::SphereAABBOverlap ( const Point center,
const Point extents 
)
protected
inline_ bool SphereCollider::SphereContainsBox ( const Point bc,
const Point be 
)
protected

Checks the sphere completely contains the box. In which case we can end the query sooner.

Parameters
bc[in] box center
be[in] box extents
Returns
true if the sphere contains the whole box

Definition at line 312 of file OPC_SphereCollider.cpp.

313 {
314  // I assume if all 8 box vertices are inside the sphere, so does the whole box.
315  // Sounds ok but maybe there's a better way?
316  Point p;
317  p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z+be.z; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
318  p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
319  p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
320  p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
321  p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z-be.z; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
322  p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
323  p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
324  p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
325 
326  return TRUE;
327 }
bool Opcode::SphereCollider::SphereTriOverlap ( const Point vert0,
const Point vert1,
const Point vert2 
)
protected

Member Data Documentation

Point Opcode::SphereCollider::mCenter
protected

Sphere center.

Definition at line 65 of file Opcode.h.

float Opcode::SphereCollider::mRadius2
protected

Sphere radius squared.

Definition at line 66 of file Opcode.h.


The documentation for this class was generated from the following files: