Bullet Collision Detection & Physics Library
btConvexConcaveCollisionAlgorithm.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 
16 
18 #include "LinearMath/btQuickprof.h"
31 
33 : btActivatingCollisionAlgorithm(ci,body0Wrap,body1Wrap),
34 m_btConvexTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped),
35 m_isSwapped(isSwapped)
36 {
37 }
38 
40 {
41 }
42 
44 {
46  {
48  }
49 }
50 
51 
53  m_dispatcher(dispatcher),
54  m_dispatchInfoPtr(0)
55 {
56  m_convexBodyWrap = isSwapped? body1Wrap:body0Wrap;
57  m_triBodyWrap = isSwapped? body0Wrap:body1Wrap;
58 
59  //
60  // create the manifold from the dispatcher 'manifold pool'
61  //
63 
64  clearCache();
65 }
66 
68 {
69  clearCache();
71 
72 }
73 
74 
76 {
78 }
79 
80 
82 partId, int triangleIndex)
83 {
84  BT_PROFILE("btConvexTriangleCallback::processTriangle");
85 
87  {
88  return;
89  }
90 
91  //just for debugging purposes
92  //printf("triangle %d",m_triangleCount++);
93 
94 
95 
98 
99 
100 
101 #if 0
102 
105  {
107  btVector3 color(1,1,0);
108  btTransform& tr = ob->getWorldTransform();
109  m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
110  m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
111  m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
112  }
113 #endif
114 
116  {
117  btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
119 
120 
121  btCollisionObjectWrapper triObWrap(m_triBodyWrap,&tm,m_triBodyWrap->getCollisionObject(),m_triBodyWrap->getWorldTransform(),partId,triangleIndex);//correct transform?
122  btCollisionAlgorithm* colAlgo = 0;
123 
125  {
127  }
128  else
129  {
131  }
132  const btCollisionObjectWrapper* tmpWrap = 0;
133 
135  {
136  tmpWrap = m_resultOut->getBody0Wrap();
137  m_resultOut->setBody0Wrap(&triObWrap);
138  m_resultOut->setShapeIdentifiersA(partId,triangleIndex);
139  }
140  else
141  {
142  tmpWrap = m_resultOut->getBody1Wrap();
143  m_resultOut->setBody1Wrap(&triObWrap);
144  m_resultOut->setShapeIdentifiersB(partId,triangleIndex);
145  }
146 
147  colAlgo->processCollision(m_convexBodyWrap,&triObWrap,*m_dispatchInfoPtr,m_resultOut);
148 
150  {
151  m_resultOut->setBody0Wrap(tmpWrap);
152  } else
153  {
154  m_resultOut->setBody1Wrap(tmpWrap);
155  }
156 
157 
158 
159  colAlgo->~btCollisionAlgorithm();
161  }
162 
163 }
164 
165 
166 
167 void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle, const btDispatcherInfo& dispatchInfo, const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut)
168 {
169  m_convexBodyWrap = convexBodyWrap;
170  m_triBodyWrap = triBodyWrap;
171 
172  m_dispatchInfoPtr = &dispatchInfo;
173  m_collisionMarginTriangle = collisionMarginTriangle;
174  m_resultOut = resultOut;
175 
176  //recalc aabbs
177  btTransform convexInTriangleSpace;
179  const btCollisionShape* convexShape = static_cast<const btCollisionShape*>(m_convexBodyWrap->getCollisionShape());
180  //CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
181  convexShape->getAabb(convexInTriangleSpace, m_aabbMin, m_aabbMax);
182  btScalar extraMargin = collisionMarginTriangle + resultOut->m_closestPointDistanceThreshold;
183 
184  btVector3 extra(extraMargin, extraMargin, extraMargin);
185 
186  m_aabbMax += extra;
187  m_aabbMin -= extra;
188 
189 }
190 
192 {
193  m_btConvexTriangleCallback.clearCache();
194 
195 }
196 
198 {
199  BT_PROFILE("btConvexConcaveCollisionAlgorithm::processCollision");
200 
201  const btCollisionObjectWrapper* convexBodyWrap = m_isSwapped ? body1Wrap : body0Wrap;
202  const btCollisionObjectWrapper* triBodyWrap = m_isSwapped ? body0Wrap : body1Wrap;
203 
204  if (triBodyWrap->getCollisionShape()->isConcave())
205  {
206  if (triBodyWrap->getCollisionShape()->getShapeType() == SDF_SHAPE_PROXYTYPE)
207  {
208  btSdfCollisionShape* sdfShape = (btSdfCollisionShape*)triBodyWrap->getCollisionShape();
209  if (convexBodyWrap->getCollisionShape()->isConvex())
210  {
211 
212  btConvexShape* convex = (btConvexShape*)convexBodyWrap->getCollisionShape();
213  btAlignedObjectArray<btVector3> queryVertices;
214 
215  if (convex->isPolyhedral())
216  {
218  for (int v = 0; v < poly->getNumVertices(); v++)
219  {
220  btVector3 vtx;
221  poly->getVertex(v, vtx);
222  queryVertices.push_back(vtx);
223  }
224  }
225  btScalar maxDist = SIMD_EPSILON;
226 
227  if (convex->getShapeType() == SPHERE_SHAPE_PROXYTYPE)
228  {
229  queryVertices.push_back(btVector3(0, 0, 0));
230  btSphereShape* sphere = (btSphereShape*)convex;
231  maxDist = sphere->getRadius() + SIMD_EPSILON;
232 
233  }
234  if (queryVertices.size())
235  {
236  resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
237  //m_btConvexTriangleCallback.m_manifoldPtr->clearManifold();
238 
240  for (int v = 0; v < queryVertices.size(); v++)
241  {
242  const btVector3& vtx = queryVertices[v];
243  btVector3 vtxWorldSpace = convexBodyWrap->getWorldTransform()*vtx;
244  btVector3 vtxInSdf = triBodyWrap->getWorldTransform().invXform(vtxWorldSpace);
245 
246  btVector3 normalLocal;
247  btScalar dist;
248  if (sdfShape->queryPoint(vtxInSdf, dist, normalLocal))
249  {
250  if (dist <= maxDist)
251  {
252  normalLocal.safeNormalize();
253  btVector3 normal = triBodyWrap->getWorldTransform().getBasis()*normalLocal;
254 
255  if (convex->getShapeType() == SPHERE_SHAPE_PROXYTYPE)
256  {
257  btSphereShape* sphere = (btSphereShape*)convex;
258  dist -= sphere->getRadius();
259  vtxWorldSpace -= sphere->getRadius()*normal;
260 
261  }
262  resultOut->addContactPoint(normal,vtxWorldSpace-normal*dist, dist);
263  }
264  }
265  }
266  resultOut->refreshContactPoints();
267  }
268 
269  }
270  } else
271  {
272  const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>( triBodyWrap->getCollisionShape());
273 
274  if (convexBodyWrap->getCollisionShape()->isConvex())
275  {
276  btScalar collisionMarginTriangle = concaveShape->getMargin();
277 
278  resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
279  m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,convexBodyWrap,triBodyWrap,resultOut);
280 
281  m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBodyWrap->getCollisionObject(),triBodyWrap->getCollisionObject());
282 
283  concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax());
284 
285  resultOut->refreshContactPoints();
286 
287  m_btConvexTriangleCallback.clearWrapperData();
288 
289  }
290  }
291 
292  }
293 
294 }
295 
296 
298 {
299  (void)resultOut;
300  (void)dispatchInfo;
301  btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
302  btCollisionObject* triBody = m_isSwapped ? body0 : body1;
303 
304 
305  //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
306 
307  //only perform CCD above a certain threshold, this prevents blocking on the long run
308  //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
309  btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
310  if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
311  {
312  return btScalar(1.);
313  }
314 
315  //const btVector3& from = convexbody->m_worldTransform.getOrigin();
316  //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
317  //todo: only do if the motion exceeds the 'radius'
318 
319  btTransform triInv = triBody->getWorldTransform().inverse();
320  btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
321  btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
322 
323  struct LocalTriangleSphereCastCallback : public btTriangleCallback
324  {
325  btTransform m_ccdSphereFromTrans;
326  btTransform m_ccdSphereToTrans;
327  btTransform m_meshTransform;
328 
329  btScalar m_ccdSphereRadius;
330  btScalar m_hitFraction;
331 
332 
333  LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
334  :m_ccdSphereFromTrans(from),
335  m_ccdSphereToTrans(to),
336  m_ccdSphereRadius(ccdSphereRadius),
337  m_hitFraction(hitFraction)
338  {
339  }
340 
341 
342  virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
343  {
344  BT_PROFILE("processTriangle");
345  (void)partId;
346  (void)triangleIndex;
347  //do a swept sphere for now
348  btTransform ident;
349  ident.setIdentity();
350  btConvexCast::CastResult castResult;
351  castResult.m_fraction = m_hitFraction;
352  btSphereShape pointShape(m_ccdSphereRadius);
353  btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
354  btVoronoiSimplexSolver simplexSolver;
355  btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
356  //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
357  //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
358  //local space?
359 
360  if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
361  ident,ident,castResult))
362  {
363  if (m_hitFraction > castResult.m_fraction)
364  m_hitFraction = castResult.m_fraction;
365  }
366 
367  }
368 
369  };
370 
371 
372 
373 
374 
375  if (triBody->getCollisionShape()->isConcave())
376  {
377  btVector3 rayAabbMin = convexFromLocal.getOrigin();
378  rayAabbMin.setMin(convexToLocal.getOrigin());
379  btVector3 rayAabbMax = convexFromLocal.getOrigin();
380  rayAabbMax.setMax(convexToLocal.getOrigin());
381  btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
382  rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
383  rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
384 
385  btScalar curHitFraction = btScalar(1.); //is this available?
386  LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
387  convexbody->getCcdSweptSphereRadius(),curHitFraction);
388 
389  raycastCallback.m_hitFraction = convexbody->getHitFraction();
390 
391  btCollisionObject* concavebody = triBody;
392 
393  btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
394 
395  if (triangleMesh)
396  {
397  triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
398  }
399 
400 
401 
402  if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
403  {
404  convexbody->setHitFraction( raycastCallback.m_hitFraction);
405  return raycastCallback.m_hitFraction;
406  }
407  }
408 
409  return btScalar(1.);
410 
411 }
virtual void releaseManifold(btPersistentManifold *manifold)=0
#define SIMD_EPSILON
Definition: btScalar.h:521
virtual void processCollision(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)
void push_back(const T &_Val)
int getShapeType() const
const btDispatcherInfo * m_dispatchInfoPtr
btScalar getCcdSweptSphereRadius() const
Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
virtual void drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)=0
virtual btCollisionAlgorithm * findAlgorithm(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, btPersistentManifold *sharedManifold, ebtDispatcherQueryType queryType)=0
void setPersistentManifold(btPersistentManifold *manifoldPtr)
void setIdentity()
Set this transformation to the identity.
Definition: btTransform.h:172
This class is not enabled yet (work-in-progress) to more aggressively activate objects.
virtual void getVertex(int i, btVector3 &vtx) const =0
The btCollisionShape class provides an interface for collision shapes that can be shared among btColl...
void setHitFraction(btScalar hitFraction)
The btSphereShape implements an implicit sphere, centered around a local origin with radius...
Definition: btSphereShape.h:22
btManifoldResult is a helper class to manage contact results.
class btIDebugDraw * m_debugDraw
Definition: btDispatcher.h:59
const btCollisionObjectWrapper * getBody1Wrap() const
virtual void processAllTriangles(btTriangleCallback *callback, const btVector3 &aabbMin, const btVector3 &aabbMax) const =0
virtual void getAabb(const btTransform &t, btVector3 &aabbMin, btVector3 &aabbMax) const =0
getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t...
btVector3 & safeNormalize()
Definition: btVector3.h:292
The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape...
Definition: btConvexShape.h:31
const btTransform & getInterpolationWorldTransform() const
virtual void setShapeIdentifiersA(int partId0, int index0)
setShapeIdentifiersA/B provides experimental support for per-triangle material / custom material comb...
bool isConcave() const
virtual void addContactPoint(const btVector3 &normalOnBInWorld, const btVector3 &pointInWorld, btScalar depth)
btTransform & getWorldTransform()
virtual void setMargin(btScalar margin)
RayResult stores the closest result alternatively, add a callback method to decide about closest/all ...
Definition: btConvexCast.h:36
const btCollisionObjectWrapper * m_convexBodyWrap
btScalar m_closestPointDistanceThreshold
int size() const
return the number of elements in the array
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:117
btVoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points...
The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTrian...
const btCollisionObjectWrapper * getBody0Wrap() const
btScalar calculateTimeOfImpact(btCollisionObject *body0, btCollisionObject *body1, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)
virtual bool calcTimeOfImpact(const btTransform &fromA, const btTransform &toA, const btTransform &fromB, const btTransform &toB, CastResult &result)
SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (...
const btTransform & getWorldTransform() const
btCollisionObject can be used to manage collision detection objects.
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes.
void setTimeStepAndCounters(btScalar collisionMarginTriangle, const btDispatcherInfo &dispatchInfo, const btCollisionObjectWrapper *convexBodyWrap, const btCollisionObjectWrapper *triBodyWrap, btManifoldResult *resultOut)
const btCollisionObject * getBody0Internal() const
virtual void freeCollisionAlgorithm(void *ptr)=0
virtual btPersistentManifold * getNewManifold(const btCollisionObject *b0, const btCollisionObject *b1)=0
btTransform inverse() const
Return the inverse of this transform.
Definition: btTransform.h:188
virtual int getNumVertices() const =0
virtual void setShapeIdentifiersB(int partId1, int index1)
const btCollisionShape * getCollisionShape() const
btScalar getHitFraction() const
btVector3 invXform(const btVector3 &inVec) const
Definition: btTransform.h:223
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
#define BT_PROFILE(name)
Definition: btQuickprof.h:216
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
btSubsimplexConvexCast implements Gino van den Bergens&#39; paper "Ray Casting against bteral Convex Obje...
bool queryPoint(const btVector3 &ptInSDF, btScalar &distOut, btVector3 &normal)
bool isConvex() const
bool isPolyhedral() const
The btConcaveShape class provides an interface for non-moving (static) concave shapes.
virtual int getDebugMode() const =0
void setBody1Wrap(const btCollisionObjectWrapper *obj1Wrap)
virtual void processTriangle(btVector3 *triangle, int partId, int triangleIndex)
virtual void getAllContactManifolds(btManifoldArray &manifoldArray)
const btCollisionObjectWrapper * m_triBodyWrap
btConvexConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo &ci, const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, bool isSwapped)
btConvexTriangleCallback(btDispatcher *dispatcher, const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, bool isSwapped)
btScalar getRadius() const
Definition: btSphereShape.h:50
virtual btScalar getMargin() const
void setBody0Wrap(const btCollisionObjectWrapper *obj0Wrap)
void setMax(const btVector3 &other)
Set each element to the max of the current values and the values of another btVector3.
Definition: btVector3.h:621
The btDispatcher interface class can be used in combination with broadphase to dispatch calculations ...
Definition: btDispatcher.h:77
btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatche...
const btCollisionShape * getCollisionShape() const
bool TestTriangleAgainstAabb2(const btVector3 *vertices, const btVector3 &aabbMin, const btVector3 &aabbMax)
conservative test for overlap between triangle and aabb
Definition: btAabbUtil2.h:59
void setMin(const btVector3 &other)
Set each element to the min of the current values and the values of another btVector3.
Definition: btVector3.h:638
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:292
const btCollisionObject * getCollisionObject() const
virtual void clearManifold(btPersistentManifold *manifold)=0