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;