2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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:
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.
17 #include "btSoftBodyConcaveCollisionAlgorithm.h"
18 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
19 #include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
20 #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
21 #include "BulletCollision/CollisionShapes/btConcaveShape.h"
22 #include "BulletCollision/CollisionDispatch/btManifoldResult.h"
23 #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
24 #include "BulletCollision/CollisionShapes/btTriangleShape.h"
25 #include "BulletCollision/CollisionShapes/btSphereShape.h"
26 #include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
27 #include "BulletCollision/CollisionShapes/btConvexHullShape.h"
31 #include "LinearMath/btIDebugDraw.h"
32 #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
33 #include "BulletSoftBody/btSoftBody.h"
35 #define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06)//make this configurable
37 btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
38 : btCollisionAlgorithm(ci),
39 m_isSwapped(isSwapped),
40 m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped)
46 btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm()
52 btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped):
53 m_dispatcher(dispatcher),
56 m_softBody = (btSoftBody*) (isSwapped? body1:body0);
57 m_triBody = isSwapped? body0:body1;
60 // create the manifold from the dispatcher 'manifold pool'
62 // m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody);
67 btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback()
70 // m_dispatcher->releaseManifold( m_manifoldPtr );
75 void btSoftBodyTriangleCallback::clearCache()
77 for (int i=0;i<m_shapeCache.size();i++)
79 btTriIndex* tmp = m_shapeCache.getAtIndex(i);
81 btAssert(tmp->m_childShape);
82 m_softBody->getWorldInfo()->m_sparsesdf.RemoveReferences(tmp->m_childShape);//necessary?
83 delete tmp->m_childShape;
89 void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
91 //just for debugging purposes
92 //printf("triangle %d",m_triangleCount++);
93 btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody);
94 btCollisionAlgorithmConstructionInfo ci;
95 ci.m_dispatcher1 = m_dispatcher;
97 ///debug drawing of the overlapping triangles
98 if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe)
100 btVector3 color(1,1,0);
101 btTransform& tr = ob->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);
107 btTriIndex triIndex(partId,triangleIndex,0);
108 btHashKey<btTriIndex> triKey(triIndex.getUid());
111 btTriIndex* shapeIndex = m_shapeCache[triKey];
114 btCollisionShape* tm = shapeIndex->m_childShape;
117 //copy over user pointers to temporary shape
118 tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer());
120 btCollisionShape* tmpShape = ob->getCollisionShape();
121 ob->internalSetTemporaryCollisionShape( tm );
124 btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr);
126 colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
127 colAlgo->~btCollisionAlgorithm();
128 ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
129 ob->internalSetTemporaryCollisionShape( tmpShape);
133 //aabb filter is already applied!
135 //btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject);
137 // if (m_softBody->getCollisionShape()->getShapeType()==
140 btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]);
142 normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION;
143 // other=(triangle[0]+triangle[1]+triangle[2])*0.333333f;
144 // other+=normal*22.f;
145 btVector3 pts[6] = {triangle[0]+normal,
152 btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6);
155 // btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other);
157 //btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
158 // tm.setMargin(m_collisionMarginTriangle);
160 //copy over user pointers to temporary shape
161 tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer());
163 btCollisionShape* tmpShape = ob->getCollisionShape();
164 ob->internalSetTemporaryCollisionShape( tm );
167 btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr);
168 ///this should use the btDispatcher, so the actual registered algorithm is used
169 // btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody);
171 //m_resultOut->setShapeIdentifiersB(partId,triangleIndex);
172 // cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
173 colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
174 colAlgo->~btCollisionAlgorithm();
175 ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
178 ob->internalSetTemporaryCollisionShape( tmpShape );
179 triIndex.m_childShape = tm;
180 m_shapeCache.insert(triKey,triIndex);
190 void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
192 m_dispatchInfoPtr = &dispatchInfo;
193 m_collisionMarginTriangle = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION);
194 m_resultOut = resultOut;
197 btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax;
198 m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax);
199 btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5);
200 btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5);
202 btTransform softTransform;
203 softTransform.setIdentity();
204 softTransform.setOrigin(softBodyCenter);
206 btTransform convexInTriangleSpace;
207 convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * softTransform;
208 btTransformAabb(halfExtents,m_collisionMarginTriangle,convexInTriangleSpace,m_aabbMin,m_aabbMax);
211 void btSoftBodyConcaveCollisionAlgorithm::clearCache()
213 m_btSoftBodyTriangleCallback.clearCache();
217 void btSoftBodyConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
221 //btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
222 btCollisionObject* triBody = m_isSwapped ? body0 : body1;
224 if (triBody->getCollisionShape()->isConcave())
228 btCollisionObject* triOb = triBody;
229 btConcaveShape* concaveShape = static_cast<btConcaveShape*>( triOb->getCollisionShape());
231 // if (convexBody->getCollisionShape()->isConvex())
233 btScalar collisionMarginTriangle = concaveShape->getMargin();
235 // resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
236 m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut);
238 //Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here.
239 //m_dispatcher->clearManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
241 // m_btSoftBodyTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody);
244 concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax());
246 // resultOut->refreshContactPoints();
255 btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
259 btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
260 btCollisionObject* triBody = m_isSwapped ? body0 : body1;
263 //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
265 //only perform CCD above a certain threshold, this prevents blocking on the long run
266 //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
267 btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
268 if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
273 //const btVector3& from = convexbody->m_worldTransform.getOrigin();
274 //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
275 //todo: only do if the motion exceeds the 'radius'
277 btTransform triInv = triBody->getWorldTransform().inverse();
278 btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
279 btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
281 struct LocalTriangleSphereCastCallback : public btTriangleCallback
283 btTransform m_ccdSphereFromTrans;
284 btTransform m_ccdSphereToTrans;
285 btTransform m_meshTransform;
287 btScalar m_ccdSphereRadius;
288 btScalar m_hitFraction;
291 LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
292 :m_ccdSphereFromTrans(from),
293 m_ccdSphereToTrans(to),
294 m_ccdSphereRadius(ccdSphereRadius),
295 m_hitFraction(hitFraction)
300 virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
304 //do a swept sphere for now
307 btConvexCast::CastResult castResult;
308 castResult.m_fraction = m_hitFraction;
309 btSphereShape pointShape(m_ccdSphereRadius);
310 btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
311 btVoronoiSimplexSolver simplexSolver;
312 btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
313 //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
314 //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
317 if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
318 ident,ident,castResult))
320 if (m_hitFraction > castResult.m_fraction)
321 m_hitFraction = castResult.m_fraction;
332 if (triBody->getCollisionShape()->isConcave())
334 btVector3 rayAabbMin = convexFromLocal.getOrigin();
335 rayAabbMin.setMin(convexToLocal.getOrigin());
336 btVector3 rayAabbMax = convexFromLocal.getOrigin();
337 rayAabbMax.setMax(convexToLocal.getOrigin());
338 btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
339 rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
340 rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
342 btScalar curHitFraction = btScalar(1.); //is this available?
343 LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
344 convexbody->getCcdSweptSphereRadius(),curHitFraction);
346 raycastCallback.m_hitFraction = convexbody->getHitFraction();
348 btCollisionObject* concavebody = triBody;
350 btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
354 triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
359 if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
361 convexbody->setHitFraction( raycastCallback.m_hitFraction);
362 return raycastCallback.m_hitFraction;