00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "btSoftBodyConcaveCollisionAlgorithm.h"
00018 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
00019 #include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
00020 #include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
00021 #include "BulletCollision/CollisionShapes/btConcaveShape.h"
00022 #include "BulletCollision/CollisionDispatch/btManifoldResult.h"
00023 #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
00024 #include "BulletCollision/CollisionShapes/btTriangleShape.h"
00025 #include "BulletCollision/CollisionShapes/btSphereShape.h"
00026 #include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
00027 #include "BulletCollision/CollisionShapes/btConvexHullShape.h"
00028
00029
00030
00031 #include "LinearMath/btIDebugDraw.h"
00032 #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
00033 #include "BulletSoftBody/btSoftBody.h"
00034
00035 #define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06)//make this configurable
00036
00037 btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
00038 : btCollisionAlgorithm(ci),
00039 m_isSwapped(isSwapped),
00040 m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped)
00041 {
00042 }
00043
00044
00045
00046 btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm()
00047 {
00048 }
00049
00050
00051
00052 btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped):
00053 m_dispatcher(dispatcher),
00054 m_dispatchInfoPtr(0)
00055 {
00056 m_softBody = (btSoftBody*) (isSwapped? body1:body0);
00057 m_triBody = isSwapped? body0:body1;
00058
00059
00060
00061
00062
00063
00064 clearCache();
00065 }
00066
00067 btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback()
00068 {
00069 clearCache();
00070
00071
00072 }
00073
00074
00075 void btSoftBodyTriangleCallback::clearCache()
00076 {
00077 for (int i=0;i<m_shapeCache.size();i++)
00078 {
00079 btTriIndex* tmp = m_shapeCache.getAtIndex(i);
00080 btAssert(tmp);
00081 btAssert(tmp->m_childShape);
00082 m_softBody->getWorldInfo()->m_sparsesdf.RemoveReferences(tmp->m_childShape);
00083 delete tmp->m_childShape;
00084 }
00085 m_shapeCache.clear();
00086 }
00087
00088
00089 void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
00090 {
00091
00092
00093 btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody);
00094 btCollisionAlgorithmConstructionInfo ci;
00095 ci.m_dispatcher1 = m_dispatcher;
00096
00098 if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe)
00099 {
00100 btVector3 color(1,1,0);
00101 btTransform& tr = ob->getWorldTransform();
00102 m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
00103 m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
00104 m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
00105 }
00106
00107 btTriIndex triIndex(partId,triangleIndex,0);
00108 btHashKey<btTriIndex> triKey(triIndex.getUid());
00109
00110
00111 btTriIndex* shapeIndex = m_shapeCache[triKey];
00112 if (shapeIndex)
00113 {
00114 btCollisionShape* tm = shapeIndex->m_childShape;
00115 btAssert(tm);
00116
00117
00118 tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer());
00119
00120 btCollisionShape* tmpShape = ob->getCollisionShape();
00121 ob->internalSetTemporaryCollisionShape( tm );
00122
00123
00124 btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);
00125
00126 colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
00127 colAlgo->~btCollisionAlgorithm();
00128 ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
00129 ob->internalSetTemporaryCollisionShape( tmpShape);
00130 return;
00131 }
00132
00133
00134
00135
00136
00137
00138 {
00139
00140 btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]);
00141 normal.normalize();
00142 normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION;
00143
00144
00145 btVector3 pts[6] = {triangle[0]+normal,
00146 triangle[1]+normal,
00147 triangle[2]+normal,
00148 triangle[0]-normal,
00149 triangle[1]-normal,
00150 triangle[2]-normal};
00151
00152 btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6);
00153
00154
00155
00156
00157
00158
00159
00160
00161 tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer());
00162
00163 btCollisionShape* tmpShape = ob->getCollisionShape();
00164 ob->internalSetTemporaryCollisionShape( tm );
00165
00166
00167 btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);
00169
00170
00171
00172
00173 colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
00174 colAlgo->~btCollisionAlgorithm();
00175 ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
00176
00177
00178 ob->internalSetTemporaryCollisionShape( tmpShape );
00179 triIndex.m_childShape = tm;
00180 m_shapeCache.insert(triKey,triIndex);
00181
00182 }
00183
00184
00185
00186 }
00187
00188
00189
00190 void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00191 {
00192 m_dispatchInfoPtr = &dispatchInfo;
00193 m_collisionMarginTriangle = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION);
00194 m_resultOut = resultOut;
00195
00196
00197 btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax;
00198 m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax);
00199 btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5);
00200 btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5);
00201
00202 btTransform softTransform;
00203 softTransform.setIdentity();
00204 softTransform.setOrigin(softBodyCenter);
00205
00206 btTransform convexInTriangleSpace;
00207 convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * softTransform;
00208 btTransformAabb(halfExtents,m_collisionMarginTriangle,convexInTriangleSpace,m_aabbMin,m_aabbMax);
00209 }
00210
00211 void btSoftBodyConcaveCollisionAlgorithm::clearCache()
00212 {
00213 m_btSoftBodyTriangleCallback.clearCache();
00214
00215 }
00216
00217 void btSoftBodyConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00218 {
00219
00220
00221
00222 btCollisionObject* triBody = m_isSwapped ? body0 : body1;
00223
00224 if (triBody->getCollisionShape()->isConcave())
00225 {
00226
00227
00228 btCollisionObject* triOb = triBody;
00229 btConcaveShape* concaveShape = static_cast<btConcaveShape*>( triOb->getCollisionShape());
00230
00231
00232 {
00233 btScalar collisionMarginTriangle = concaveShape->getMargin();
00234
00235
00236 m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut);
00237
00238
00239
00240
00241
00242
00243
00244 concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax());
00245
00246
00247
00248 }
00249
00250 }
00251
00252 }
00253
00254
00255 btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00256 {
00257 (void)resultOut;
00258 (void)dispatchInfo;
00259 btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
00260 btCollisionObject* triBody = m_isSwapped ? body0 : body1;
00261
00262
00263
00264
00265
00266
00267 btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
00268 if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
00269 {
00270 return btScalar(1.);
00271 }
00272
00273
00274
00275
00276
00277 btTransform triInv = triBody->getWorldTransform().inverse();
00278 btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
00279 btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
00280
00281 struct LocalTriangleSphereCastCallback : public btTriangleCallback
00282 {
00283 btTransform m_ccdSphereFromTrans;
00284 btTransform m_ccdSphereToTrans;
00285 btTransform m_meshTransform;
00286
00287 btScalar m_ccdSphereRadius;
00288 btScalar m_hitFraction;
00289
00290
00291 LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
00292 :m_ccdSphereFromTrans(from),
00293 m_ccdSphereToTrans(to),
00294 m_ccdSphereRadius(ccdSphereRadius),
00295 m_hitFraction(hitFraction)
00296 {
00297 }
00298
00299
00300 virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
00301 {
00302 (void)partId;
00303 (void)triangleIndex;
00304
00305 btTransform ident;
00306 ident.setIdentity();
00307 btConvexCast::CastResult castResult;
00308 castResult.m_fraction = m_hitFraction;
00309 btSphereShape pointShape(m_ccdSphereRadius);
00310 btTriangleShape triShape(triangle[0],triangle[1],triangle[2]);
00311 btVoronoiSimplexSolver simplexSolver;
00312 btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
00313
00314
00315
00316
00317 if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
00318 ident,ident,castResult))
00319 {
00320 if (m_hitFraction > castResult.m_fraction)
00321 m_hitFraction = castResult.m_fraction;
00322 }
00323
00324 }
00325
00326 };
00327
00328
00329
00330
00331
00332 if (triBody->getCollisionShape()->isConcave())
00333 {
00334 btVector3 rayAabbMin = convexFromLocal.getOrigin();
00335 rayAabbMin.setMin(convexToLocal.getOrigin());
00336 btVector3 rayAabbMax = convexFromLocal.getOrigin();
00337 rayAabbMax.setMax(convexToLocal.getOrigin());
00338 btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
00339 rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
00340 rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
00341
00342 btScalar curHitFraction = btScalar(1.);
00343 LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
00344 convexbody->getCcdSweptSphereRadius(),curHitFraction);
00345
00346 raycastCallback.m_hitFraction = convexbody->getHitFraction();
00347
00348 btCollisionObject* concavebody = triBody;
00349
00350 btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
00351
00352 if (triangleMesh)
00353 {
00354 triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
00355 }
00356
00357
00358
00359 if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
00360 {
00361 convexbody->setHitFraction( raycastCallback.m_hitFraction);
00362 return raycastCallback.m_hitFraction;
00363 }
00364 }
00365
00366 return btScalar(1.);
00367
00368 }