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() > 0)
100 btVector3 color(255,255,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->setShapeIdentifiers(-1,-1,partId,triangleIndex);
172 // cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex);
173 // cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
174 colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
175 colAlgo->~btCollisionAlgorithm();
176 ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
179 ob->internalSetTemporaryCollisionShape( tmpShape );
180 triIndex.m_childShape = tm;
181 m_shapeCache.insert(triKey,triIndex);
191 void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
193 m_dispatchInfoPtr = &dispatchInfo;
194 m_collisionMarginTriangle = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION);
195 m_resultOut = resultOut;
198 btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax;
199 m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax);
200 btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5);
201 btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5);
203 btTransform softTransform;
204 softTransform.setIdentity();
205 softTransform.setOrigin(softBodyCenter);
207 btTransform convexInTriangleSpace;
208 convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * softTransform;
209 btTransformAabb(halfExtents,m_collisionMarginTriangle,convexInTriangleSpace,m_aabbMin,m_aabbMax);
212 void btSoftBodyConcaveCollisionAlgorithm::clearCache()
214 m_btSoftBodyTriangleCallback.clearCache();
218 void btSoftBodyConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
222 btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
223 btCollisionObject* triBody = m_isSwapped ? body0 : body1;
225 if (triBody->getCollisionShape()->isConcave())
229 btCollisionObject* triOb = triBody;
230 btConcaveShape* concaveShape = static_cast<btConcaveShape*>( triOb->getCollisionShape());
232 // if (convexBody->getCollisionShape()->isConvex())
234 btScalar collisionMarginTriangle = concaveShape->getMargin();
236 // resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
237 m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut);
239 //Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here.
240 //m_dispatcher->clearManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
242 // m_btSoftBodyTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody);
245 concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax());
247 // resultOut->refreshContactPoints();
256 btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
260 btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
261 btCollisionObject* triBody = m_isSwapped ? body0 : body1;
264 //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
266 //only perform CCD above a certain threshold, this prevents blocking on the long run
267 //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
268 btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
269 if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
274 //const btVector3& from = convexbody->m_worldTransform.getOrigin();
275 //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
276 //todo: only do if the motion exceeds the 'radius'
278 btTransform triInv = triBody->getWorldTransform().inverse();
279 btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
280 btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
282 struct LocalTriangleSphereCastCallback : public btTriangleCallback
284 btTransform m_ccdSphereFromTrans;
285 btTransform m_ccdSphereToTrans;
286 btTransform m_meshTransform;
288 btScalar m_ccdSphereRadius;
289 btScalar m_hitFraction;
292 LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
293 :m_ccdSphereFromTrans(from),
294 m_ccdSphereToTrans(to),
295 m_ccdSphereRadius(ccdSphereRadius),
296 m_hitFraction(hitFraction)
301 virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
305 //do a swept sphere for now
308 btConvexCast::CastResult castResult;
309 castResult.m_fraction = m_hitFraction;
310 btSphereShape pointShape(m_ccdSphereRadius);
311 btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
312 btVoronoiSimplexSolver simplexSolver;
313 btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
314 //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
315 //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
318 if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
319 ident,ident,castResult))
321 if (m_hitFraction > castResult.m_fraction)
322 m_hitFraction = castResult.m_fraction;
333 if (triBody->getCollisionShape()->isConcave())
335 btVector3 rayAabbMin = convexFromLocal.getOrigin();
336 rayAabbMin.setMin(convexToLocal.getOrigin());
337 btVector3 rayAabbMax = convexFromLocal.getOrigin();
338 rayAabbMax.setMax(convexToLocal.getOrigin());
339 btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
340 rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
341 rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
343 btScalar curHitFraction = btScalar(1.); //is this available?
344 LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
345 convexbody->getCcdSweptSphereRadius(),curHitFraction);
347 raycastCallback.m_hitFraction = convexbody->getHitFraction();
349 btCollisionObject* concavebody = triBody;
351 btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
355 triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
360 if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
362 convexbody->setHitFraction( raycastCallback.m_hitFraction);
363 return raycastCallback.m_hitFraction;