Bullet Collision Detection & Physics Library
btSoftBodyConcaveCollisionAlgorithm.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 
29 
30 
34 
35 #define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06)//make this configurable
36 
39 m_isSwapped(isSwapped),
40 m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0Wrap,body1Wrap,isSwapped)
41 {
42 }
43 
44 
45 
47 {
48 }
49 
50 
51 
53 m_dispatcher(dispatcher),
54 m_dispatchInfoPtr(0)
55 {
56  m_softBody = (isSwapped? (btSoftBody*)body1Wrap->getCollisionObject():(btSoftBody*)body0Wrap->getCollisionObject());
57  m_triBody = isSwapped? body0Wrap->getCollisionObject():body1Wrap->getCollisionObject();
58 
59  //
60  // create the manifold from the dispatcher 'manifold pool'
61  //
62  // m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody);
63 
64  clearCache();
65 }
66 
68 {
69  clearCache();
70  // m_dispatcher->releaseManifold( m_manifoldPtr );
71 
72 }
73 
74 
76 {
77  for (int i=0;i<m_shapeCache.size();i++)
78  {
80  btAssert(tmp);
81  btAssert(tmp->m_childShape);
83  delete tmp->m_childShape;
84  }
86 }
87 
88 
89 void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
90 {
91  //just for debugging purposes
92  //printf("triangle %d",m_triangleCount++);
93 
96 
99  {
100  btVector3 color(1,1,0);
101  const btTransform& tr = m_triBody->getWorldTransform();
102  m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
103  m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
104  m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
105  }
106 
107  btTriIndex triIndex(partId,triangleIndex,0);
108  btHashKey<btTriIndex> triKey(triIndex.getUid());
109 
110 
111  btTriIndex* shapeIndex = m_shapeCache[triKey];
112  if (shapeIndex)
113  {
114  btCollisionShape* tm = shapeIndex->m_childShape;
115  btAssert(tm);
116 
117  //copy over user pointers to temporary shape
119 
121  //btCollisionObjectWrapper triBody(0,tm, ob, btTransform::getIdentity());//ob->getWorldTransform());//??
122  btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform(),partId, triangleIndex);
124  btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0, algoType);//m_manifoldPtr);
125 
126  colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut);
127  colAlgo->~btCollisionAlgorithm();
129 
130  return;
131  }
132 
133  //aabb filter is already applied!
134 
135  //btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject);
136 
137  // if (m_softBody->getCollisionShape()->getShapeType()==
138  {
139  // btVector3 other;
140  btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]);
141  normal.normalize();
143  // other=(triangle[0]+triangle[1]+triangle[2])*0.333333f;
144  // other+=normal*22.f;
145  btVector3 pts[6] = {triangle[0]+normal,
146  triangle[1]+normal,
147  triangle[2]+normal,
148  triangle[0]-normal,
149  triangle[1]-normal,
150  triangle[2]-normal};
151 
152  btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6);
153 
154 
155  // btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other);
156 
157  //btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
158  // tm.setMargin(m_collisionMarginTriangle);
159 
160  //copy over user pointers to temporary shape
162 
163 
165  btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform(),partId, triangleIndex);//btTransform::getIdentity());//??
166 
168  btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0, algoType);//m_manifoldPtr);
169 
170  colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut);
171  colAlgo->~btCollisionAlgorithm();
173 
174  triIndex.m_childShape = tm;
175  m_shapeCache.insert(triKey,triIndex);
176 
177  }
178 
179 
180 
181 }
182 
183 
184 
185 void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btCollisionObjectWrapper* triBodyWrap, const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
186 {
187  m_dispatchInfoPtr = &dispatchInfo;
189  m_resultOut = resultOut;
190 
191 
192  btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax;
193  m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax);
194  btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5);
195  btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5);
196 
197  btTransform softTransform;
198  softTransform.setIdentity();
199  softTransform.setOrigin(softBodyCenter);
200 
201  btTransform convexInTriangleSpace;
202  convexInTriangleSpace = triBodyWrap->getWorldTransform().inverse() * softTransform;
203  btTransformAabb(halfExtents,m_collisionMarginTriangle,convexInTriangleSpace,m_aabbMin,m_aabbMax);
204 }
205 
207 {
208  m_btSoftBodyTriangleCallback.clearCache();
209 
210 }
211 
213 {
214 
215 
216  //btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
217  const btCollisionObjectWrapper* triBody = m_isSwapped ? body0Wrap : body1Wrap;
218 
219  if (triBody->getCollisionShape()->isConcave())
220  {
221 
222 
223  const btCollisionObject* triOb = triBody->getCollisionObject();
224  const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>( triOb->getCollisionShape());
225 
226  // if (convexBody->getCollisionShape()->isConvex())
227  {
228  btScalar collisionMarginTriangle = concaveShape->getMargin();
229 
230  // resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
231  m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,triBody,dispatchInfo,resultOut);
232 
233 
234  concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax());
235 
236  // resultOut->refreshContactPoints();
237 
238  }
239 
240  }
241 
242 }
243 
244 
246 {
247  (void)resultOut;
248  (void)dispatchInfo;
249  btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
250  btCollisionObject* triBody = m_isSwapped ? body0 : body1;
251 
252 
253  //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
254 
255  //only perform CCD above a certain threshold, this prevents blocking on the long run
256  //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
257  btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
258  if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
259  {
260  return btScalar(1.);
261  }
262 
263  //const btVector3& from = convexbody->m_worldTransform.getOrigin();
264  //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
265  //todo: only do if the motion exceeds the 'radius'
266 
267  btTransform triInv = triBody->getWorldTransform().inverse();
268  btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
269  btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
270 
271  struct LocalTriangleSphereCastCallback : public btTriangleCallback
272  {
273  btTransform m_ccdSphereFromTrans;
274  btTransform m_ccdSphereToTrans;
275  btTransform m_meshTransform;
276 
277  btScalar m_ccdSphereRadius;
278  btScalar m_hitFraction;
279 
280 
281  LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
282  :m_ccdSphereFromTrans(from),
283  m_ccdSphereToTrans(to),
284  m_ccdSphereRadius(ccdSphereRadius),
285  m_hitFraction(hitFraction)
286  {
287  }
288 
289 
290  virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
291  {
292  (void)partId;
293  (void)triangleIndex;
294  //do a swept sphere for now
295  btTransform ident;
296  ident.setIdentity();
297  btConvexCast::CastResult castResult;
298  castResult.m_fraction = m_hitFraction;
299  btSphereShape pointShape(m_ccdSphereRadius);
300  btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
301  btVoronoiSimplexSolver simplexSolver;
302  btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
303  //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
304  //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
305  //local space?
306 
307  if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
308  ident,ident,castResult))
309  {
310  if (m_hitFraction > castResult.m_fraction)
311  m_hitFraction = castResult.m_fraction;
312  }
313 
314  }
315 
316  };
317 
318 
319 
320 
321 
322  if (triBody->getCollisionShape()->isConcave())
323  {
324  btVector3 rayAabbMin = convexFromLocal.getOrigin();
325  rayAabbMin.setMin(convexToLocal.getOrigin());
326  btVector3 rayAabbMax = convexFromLocal.getOrigin();
327  rayAabbMax.setMax(convexToLocal.getOrigin());
328  btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
329  rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
330  rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
331 
332  btScalar curHitFraction = btScalar(1.); //is this available?
333  LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
334  convexbody->getCcdSweptSphereRadius(),curHitFraction);
335 
336  raycastCallback.m_hitFraction = convexbody->getHitFraction();
337 
338  btCollisionObject* concavebody = triBody;
339 
340  btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
341 
342  if (triangleMesh)
343  {
344  triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
345  }
346 
347 
348 
349  if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
350  {
351  convexbody->setHitFraction( raycastCallback.m_hitFraction);
352  return raycastCallback.m_hitFraction;
353  }
354  }
355 
356  return btScalar(1.);
357 
358 }
void setOrigin(const btVector3 &origin)
Set the translational element.
Definition: btTransform.h:150
void clear()
Definition: btHashMap.h:460
btScalar getCcdSweptSphereRadius() const
Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
virtual void processCollision(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)
virtual void processCollision(const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)=0
btSoftBodyTriangleCallback(btDispatcher *dispatcher, const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, bool isSwapped)
btSoftBodyConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo &ci, const btCollisionObjectWrapper *body0Wrap, const btCollisionObjectWrapper *body1Wrap, bool isSwapped)
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
virtual void processTriangle(btVector3 *triangle, int partId, int triangleIndex)
int size() const
Definition: btHashMap.h:372
void setIdentity()
Set this transformation to the identity.
Definition: btTransform.h:172
#define btAssert(x)
Definition: btScalar.h:131
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
virtual void processAllTriangles(btTriangleCallback *callback, const btVector3 &aabbMin, const btVector3 &aabbMax) const =0
btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition: btVector3.h:309
void setUserPointer(void *userPtr)
optional user data pointer
const btTransform & getInterpolationWorldTransform() const
virtual void getAabb(btVector3 &aabbMin, btVector3 &aabbMax) const
Definition: btSoftBody.h:953
btSparseSdf< 3 > m_sparsesdf
Definition: btSoftBody.h:53
bool isConcave() const
int RemoveReferences(btCollisionShape *pcs)
Definition: btSparseSDF.h:136
btTransform & getWorldTransform()
btSoftBodyWorldInfo * getWorldInfo()
Definition: btSoftBody.h:702
RayResult stores the closest result alternatively, add a callback method to decide about closest/all ...
Definition: btConvexCast.h:36
btScalar m_closestPointDistanceThreshold
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...
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.
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:262
void * getUserPointer() const
virtual void freeCollisionAlgorithm(void *ptr)=0
btTransform inverse() const
Return the inverse of this transform.
Definition: btTransform.h:188
const btCollisionShape * getCollisionShape() const
btScalar getHitFraction() const
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
const Value * getAtIndex(int index) const
Definition: btHashMap.h:377
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...
The btConcaveShape class provides an interface for non-moving (static) concave shapes.
void setTimeStepAndCounters(btScalar collisionMarginTriangle, const btCollisionObjectWrapper *triObjWrap, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)
virtual int getDebugMode() const =0
The btConvexHullShape implements an implicit convex hull of an array of vertices. ...
virtual btScalar getMargin() const
void btTransformAabb(const btVector3 &halfExtents, btScalar margin, const btTransform &t, btVector3 &aabbMinOut, btVector3 &aabbMaxOut)
Definition: btAabbUtil2.h:182
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
btHashMap< btHashKey< btTriIndex >, btTriIndex > m_shapeCache
class btCollisionShape * m_childShape
The btSoftBody is an class to simulate cloth and volumetric soft bodies.
Definition: btSoftBody.h:71
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
ebtDispatcherQueryType
Definition: btDispatcher.h:69
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
btScalar calculateTimeOfImpact(btCollisionObject *body0, btCollisionObject *body1, const btDispatcherInfo &dispatchInfo, btManifoldResult *resultOut)
#define BT_SOFTBODY_TRIANGLE_EXTRUSION