OPC_SphereCollider.cpp
Go to the documentation of this file.
1 /*
3  * OPCODE - Optimized Collision Detection
4  * Copyright (C) 2001 Pierre Terdiman
5  * Homepage: http://www.codercorner.com/Opcode.htm
6  */
8 
10 
16 
19 
31 
34 // Precompiled Header
35 #include "Stdafx.h"
36 
37 using namespace Opcode;
38 
39 #include "OPC_SphereAABBOverlap.h"
40 #include "OPC_SphereTriOverlap.h"
41 
42 #define SET_CONTACT(prim_index, flag) \
43  /* Set contact status */ \
44  mFlags |= flag; \
45  mTouchedPrimitives->Add(prim_index);
46 
48 #define SPHERE_PRIM(prim_index, flag) \
49  /* Request vertices from the app */ \
50  VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \
51  \
52  /* Perform sphere-tri overlap test */ \
53  if(SphereTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \
54  { \
55  SET_CONTACT(prim_index, flag) \
56  }
57 
59 
64 {
65  mCenter.Zero();
66  mRadius2 = 0.0f;
67 }
68 
70 
75 {
76 }
77 
79 
93 bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds, const Matrix4x4* worldm)
95 {
96  // Checkings
97  if(!Setup(&model)) return false;
98 
99  // Init collision query
100  if(InitQuery(cache, sphere, worlds, worldm)) return true;
101 
102  if(!model.HasLeafNodes())
103  {
104  if(model.IsQuantized())
105  {
106  const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
107 
108  // Setup dequantization coeffs
109  mCenterCoeff = Tree->mCenterCoeff;
111 
112  // Perform collision query
113  if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
114  else _Collide(Tree->GetNodes());
115  }
116  else
117  {
118  const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
119 
120  // Perform collision query
121  if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
122  else _Collide(Tree->GetNodes());
123  }
124  }
125  else
126  {
127  if(model.IsQuantized())
128  {
129  const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
130 
131  // Setup dequantization coeffs
132  mCenterCoeff = Tree->mCenterCoeff;
134 
135  // Perform collision query
136  if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
137  else _Collide(Tree->GetNodes());
138  }
139  else
140  {
141  const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
142 
143  // Perform collision query
144  if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes());
145  else _Collide(Tree->GetNodes());
146  }
147  }
148  return true;
149 }
150 
152 
165 BOOL SphereCollider::InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds, const Matrix4x4* worldm)
167 {
168  // 1) Call the base method
170 
171  // 2) Compute sphere in model space:
172  // - Precompute R^2
173  mRadius2 = sphere.mRadius * sphere.mRadius;
174  // - Compute center position
175  mCenter = sphere.mCenter;
176  // -> to world space
177  if(worlds) mCenter *= *worlds;
178  // -> to model space
179  if(worldm)
180  {
181  // Invert model matrix
182  Matrix4x4 InvWorldM;
183  InvertPRMatrix(InvWorldM, *worldm);
184 
185  mCenter *= InvWorldM;
186  }
187 
188  // 3) Setup destination pointer
190 
191  // 4) Special case: 1-triangle meshes [Opcode 1.3]
193  {
194  if(!SkipPrimitiveTests())
195  {
196  // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0.
198 
199  // Perform overlap test between the unique triangle and the sphere (and set contact status if needed)
201 
202  // Return immediately regardless of status
203  return TRUE;
204  }
205  }
206 
207  // 5) Check temporal coherence :
209  {
210  // Here we use temporal coherence
211  // => check results from previous frame before performing the collision query
212  if(FirstContactEnabled())
213  {
214  // We're only interested in the first contact found => test the unique previously touched face
216  {
217  // Get index of previously touched face = the first entry in the array
218  udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0);
219 
220  // Then reset the array:
221  // - if the overlap test below is successful, the index we'll get added back anyway
222  // - if it isn't, then the array should be reset anyway for the normal query
224 
225  // Perform overlap test between the cached triangle and the sphere (and set contact status if needed)
226  SPHERE_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT)
227 
228  // Return immediately if possible
229  if(GetContactStatus()) return TRUE;
230  }
231  // else no face has been touched during previous query
232  // => we'll have to perform a normal query
233  }
234  else
235  {
236  // We're interested in all contacts =>test the new real sphere N(ew) against the previous fat sphere P(revious):
237  float r = sqrtf(cache.FatRadius2) - sphere.mRadius;
238  if(IsCacheValid(cache) && cache.Center.SquareDistance(mCenter) < r*r)
239  {
240  // - if N is included in P, return previous list
241  // => we simply leave the list (mTouchedFaces) unchanged
242 
243  // Set contact status if needed
245 
246  // In any case we don't need to do a query
247  return TRUE;
248  }
249  else
250  {
251  // - else do the query using a fat N
252 
253  // Reset cache since we'll about to perform a real query
255 
256  // Make a fat sphere so that coherence will work for subsequent frames
257  mRadius2 *= cache.FatCoeff;
258 // mRadius2 = (sphere.mRadius * cache.FatCoeff)*(sphere.mRadius * cache.FatCoeff);
259 
260  // Update cache with query data (signature for cached faces)
261  cache.Center = mCenter;
262  cache.FatRadius2 = mRadius2;
263  }
264  }
265  }
266  else
267  {
268  // Here we don't use temporal coherence => do a normal query
270  }
271 
272  return FALSE;
273 }
274 
276 
283 bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree)
285 {
286  // This is typically called for a scene tree, full of -AABBs-, not full of triangles.
287  // So we don't really have "primitives" to deal with. Hence it doesn't work with
288  // "FirstContact" + "TemporalCoherence".
290 
291  // Checkings
292  if(!tree) return false;
293 
294  // Init collision query
295  if(InitQuery(cache, sphere)) return true;
296 
297  // Perform collision query
298  _Collide(tree);
299 
300  return true;
301 }
302 
304 
312 {
313  // I assume if all 8 box vertices are inside the sphere, so does the whole box.
314  // Sounds ok but maybe there's a better way?
315  Point p;
316  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;
317  p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
318  p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
319  p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
320  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;
321  p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
322  p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
323  p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE;
324 
325  return TRUE;
326 }
327 
328 #define TEST_BOX_IN_SPHERE(center, extents) \
329  if(SphereContainsBox(center, extents)) \
330  { \
331  /* Set contact status */ \
332  mFlags |= OPC_CONTACT; \
333  _Dump(node); \
334  return; \
335  }
336 
338 
344 {
345  // Perform Sphere-AABB overlap test
346  if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
347 
348  TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents)
349 
350  if(node->IsLeaf())
351  {
352  SPHERE_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 
365 
371 {
372  // Perform Sphere-AABB overlap test
373  if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
374 
375  TEST_BOX_IN_SPHERE(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 
392 
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 Sphere-AABB overlap test
405  if(!SphereAABBOverlap(Center, Extents)) return;
406 
407  TEST_BOX_IN_SPHERE(Center, Extents)
408 
409  if(node->IsLeaf())
410  {
411  SPHERE_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 
424 
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 Sphere-AABB overlap test
437  if(!SphereAABBOverlap(Center, Extents)) return;
438 
439  TEST_BOX_IN_SPHERE(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 
456 
462 {
463  // Perform Sphere-AABB overlap test
464  if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
465 
466  TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents)
467 
468  if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
469  else _Collide(node->GetPos());
470 
471  if(ContactFound()) return;
472 
473  if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
474  else _Collide(node->GetNeg());
475 }
476 
478 
484 {
485  // Perform Sphere-AABB overlap test
486  if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return;
487 
488  TEST_BOX_IN_SPHERE(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 
500 
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 Sphere-AABB overlap test
513  if(!SphereAABBOverlap(Center, Extents)) return;
514 
515  TEST_BOX_IN_SPHERE(Center, Extents)
516 
517  if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) }
518  else _Collide(node->GetPos());
519 
520  if(ContactFound()) return;
521 
522  if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) }
523  else _Collide(node->GetNeg());
524 }
525 
527 
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 Sphere-AABB overlap test
540  if(!SphereAABBOverlap(Center, Extents)) return;
541 
542  TEST_BOX_IN_SPHERE(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 
554 
558 void SphereCollider::_Collide(const AABBTreeNode* node)
560 {
561  // Perform Sphere-AABB overlap test
562  Point Center, Extents;
563  node->GetAABB()->GetCenter(Center);
564  node->GetAABB()->GetExtents(Extents);
565  if(!SphereAABBOverlap(Center, Extents)) return;
566 
567  if(node->IsLeaf() || SphereContainsBox(Center, Extents))
568  {
569  mFlags |= OPC_CONTACT;
571  }
572  else
573  {
574  _Collide(node->GetPos());
575  _Collide(node->GetNeg());
576  }
577 }
578 
579 
580 
581 
582 
583 
584 
586 
591 {
592 }
593 
595 
600 {
601 }
602 
603 bool HybridSphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds, const Matrix4x4* worldm)
604 {
605  // We don't want primitive tests here!
607 
608  // Checkings
609  if(!Setup(&model)) return false;
610 
611  // Init collision query
612  if(InitQuery(cache, sphere, worlds, worldm)) return true;
613 
614  // Special case for 1-leaf trees
616  {
617  // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles
618  udword Nb = mIMesh->GetNbTriangles();
619 
620  // Loop through all triangles
621  for(udword i=0;i<Nb;i++)
622  {
624  }
625  return true;
626  }
627 
628  // Override destination array since we're only going to get leaf boxes here
629  mTouchedBoxes.Reset();
630  mTouchedPrimitives = &mTouchedBoxes;
631 
632  // Now, do the actual query against leaf boxes
633  if(!model.HasLeafNodes())
634  {
635  if(model.IsQuantized())
636  {
637  const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree();
638 
639  // Setup dequantization coeffs
640  mCenterCoeff = Tree->mCenterCoeff;
642 
643  // Perform collision query - we don't want primitive tests here!
644  _CollideNoPrimitiveTest(Tree->GetNodes());
645  }
646  else
647  {
648  const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree();
649 
650  // Perform collision query - we don't want primitive tests here!
651  _CollideNoPrimitiveTest(Tree->GetNodes());
652  }
653  }
654  else
655  {
656  if(model.IsQuantized())
657  {
658  const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree();
659 
660  // Setup dequantization coeffs
661  mCenterCoeff = Tree->mCenterCoeff;
663 
664  // Perform collision query - we don't want primitive tests here!
665  _CollideNoPrimitiveTest(Tree->GetNodes());
666  }
667  else
668  {
669  const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree();
670 
671  // Perform collision query - we don't want primitive tests here!
672  _CollideNoPrimitiveTest(Tree->GetNodes());
673  }
674  }
675 
676  // We only have a list of boxes so far
677  if(GetContactStatus())
678  {
679  // Reset contact status, since it currently only reflects collisions with leaf boxes
681 
682  // Change dest container so that we can use built-in overlap tests and get collided primitives
683  cache.TouchedPrimitives.Reset();
685 
686  // Read touched leaf boxes
687  udword Nb = mTouchedBoxes.GetNbEntries();
688  const udword* Touched = mTouchedBoxes.GetEntries();
689 
690  const LeafTriangles* LT = model.GetLeafTriangles();
691  const udword* Indices = model.GetIndices();
692 
693  // Loop through touched leaves
694  while(Nb--)
695  {
696  const LeafTriangles& CurrentLeaf = LT[*Touched++];
697 
698  // Each leaf box has a set of triangles
699  udword NbTris = CurrentLeaf.GetNbTriangles();
700  if(Indices)
701  {
702  const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()];
703 
704  // Loop through triangles and test each of them
705  while(NbTris--)
706  {
707  udword TriangleIndex = *T++;
708  SPHERE_PRIM(TriangleIndex, OPC_CONTACT)
709  }
710  }
711  else
712  {
713  udword BaseIndex = CurrentLeaf.GetTriangleIndex();
714 
715  // Loop through triangles and test each of them
716  while(NbTris--)
717  {
718  udword TriangleIndex = BaseIndex++;
719  SPHERE_PRIM(TriangleIndex, OPC_CONTACT)
720  }
721  }
722  }
723  }
724 
725  return true;
726 }
inline_ BOOL HasSingleNode() const
Definition: Opcode.h:140
const MeshInterface * mIMesh
User-defined mesh interface.
Definition: Opcode.h:149
inline_ const udword * GetIndices() const
Definition: Opcode.h:95
virtual inline_ void InitQuery()
Definition: Opcode.h:174
inline_ BOOL SkipPrimitiveTests() const
Definition: Opcode.h:93
bool Collide(SphereCache &cache, const Sphere &sphere, const HybridModel &model, const Matrix4x4 *worlds=null, const Matrix4x4 *worldm=null)
inline_ const udword * GetPrimitives() const
Definition: Opcode.h:89
#define FALSE
Definition: OPC_IceHook.h:9
Container TouchedPrimitives
Indices of touched primitives.
Definition: Opcode.h:29
#define SET_CONTACT(prim_index, flag)
const BaseModel * mCurrentModel
Current model for collision query (owner of touched faces)
Definition: Opcode.h:147
inline_ BOOL SphereContainsBox(const Point &bc, const Point &be)
#define TEST_BOX_IN_SPHERE(center, extents)
#define TRUE
Definition: OPC_IceHook.h:13
#define inline_
uword mExtents[3]
Quantized extents.
Definition: Opcode.h:115
inline_ Point & Zero()
Clears the vector.
Definition: OPC_IceHook.h:45
png_uint_32 i
Definition: png.h:2735
inline_ BOOL ContactFound() const
Definition: Opcode.h:77
inline_ BOOL TemporalCoherenceEnabled() const
Definition: Opcode.h:69
bool Collide(SphereCache &cache, const Sphere &sphere, const Model &model, const Matrix4x4 *worlds=null, const Matrix4x4 *worldm=null)
Leaf descriptor.
Definition: Opcode.h:25
inline_ udword GetNbEntries() const
Returns the current number of entries.
Definition: OPC_IceHook.h:171
sword mCenter[3]
Quantized center.
Definition: Opcode.h:114
float FatRadius2
Sphere used when performing the query resulting in cached faces.
Definition: Opcode.h:31
float mRadius
Sphere radius.
Definition: OPC_IceHook.h:140
inline_ void Reset()
Definition: OPC_IceHook.h:126
#define SPHERE_PRIM(prim_index, flag)
Sphere-triangle overlap test.
inline_ const AABBOptimizedTree * GetTree() const
Definition: Opcode.h:99
float mRadius2
Sphere radius squared.
Definition: Opcode.h:66
inline_ BOOL GetContactStatus() const
Definition: Opcode.h:53
Point mCenter
Sphere center.
Definition: OPC_IceHook.h:139
int BOOL
Another boolean type.
Definition: IceTypes.h:102
unsigned int udword
sizeof(udword) must be 4
Definition: IceTypes.h:65
inline_ BOOL IsCacheValid(VolumeCache &cache)
Definition: Opcode.h:121
inline_ udword GetNbTriangles() const
Definition: Opcode.h:35
inline_ BOOL IsQuantized() const
Definition: Opcode.h:132
inline_ BOOL SphereAABBOverlap(const Point &center, const Point &extents)
inline_ BOOL Setup(const BaseModel *model)
Definition: Opcode.h:159
void _Collide(const AABBCollisionNode *node)
udword mFlags
Bit flags.
Definition: Opcode.h:146
inline_ Container & Add(udword entry)
Definition: OPC_IceHook.h:48
Final contact status after a collision query.
Definition: Opcode.h:28
void _CollideNoPrimitiveTest(const AABBCollisionNode *node)
#define ASSERT(exp)
Definition: OPC_IceHook.h:24
ICEMATHS_API void InvertPRMatrix(Matrix4x4 &dest, const Matrix4x4 &src)
Point mCenter
Sphere center.
Definition: Opcode.h:65
inline_ udword GetNbTriangles() const
Definition: Opcode.h:61
inline_ udword GetTriangleIndex() const
Definition: Opcode.h:43
inline_ udword GetEntry(udword i) const
Returns ith entry.
Definition: OPC_IceHook.h:172
inline_ udword GetNbPrimitives() const
Definition: Opcode.h:90
Point Center
Sphere used when performing the query resulting in cached faces.
Definition: Opcode.h:30
float FatCoeff
mRadius2 multiplier used to create a fat sphere
Definition: Opcode.h:33
inline_ BOOL HasLeafNodes() const
Definition: Opcode.h:124
Container * mTouchedPrimitives
List of touched primitives.
Definition: Opcode.h:94
inline_ float SquareDistance(const Point &b) const
Computes square distance to another point.
Definition: OPC_IceHook.h:318
Keep or discard primitive-bv tests in leaf nodes (volume-mesh queries)
Definition: Opcode.h:30
inline_ BOOL FirstContactEnabled() const
Definition: Opcode.h:61
inline_ const LeafTriangles * GetLeafTriangles() const
Definition: Opcode.h:87


openhrp3
Author(s): AIST, General Robotix Inc., Nakamura Lab of Dept. of Mechano Informatics at University of Tokyo
autogenerated on Sat May 8 2021 02:42:39