Blender V2.61 - r43446
|
00001 /* 00002 Bullet Continuous Collision Detection and Physics Library 00003 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ 00004 00005 This software is provided 'as-is', without any express or implied warranty. 00006 In no event will the authors be held liable for any damages arising from the use of this software. 00007 Permission is granted to anyone to use this software for any purpose, 00008 including commercial applications, and to alter it and redistribute it freely, 00009 subject to the following restrictions: 00010 00011 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. 00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 00013 3. This notice may not be removed or altered from any source distribution. 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 // create the manifold from the dispatcher 'manifold pool' 00061 // 00062 // m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody); 00063 00064 clearCache(); 00065 } 00066 00067 btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback() 00068 { 00069 clearCache(); 00070 // m_dispatcher->releaseManifold( m_manifoldPtr ); 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);//necessary? 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 //just for debugging purposes 00092 //printf("triangle %d",m_triangleCount++); 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 //copy over user pointers to temporary shape 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);//m_manifoldPtr); 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 //aabb filter is already applied! 00134 00135 //btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject); 00136 00137 // if (m_softBody->getCollisionShape()->getShapeType()== 00138 { 00139 // btVector3 other; 00140 btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]); 00141 normal.normalize(); 00142 normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION; 00143 // other=(triangle[0]+triangle[1]+triangle[2])*0.333333f; 00144 // other+=normal*22.f; 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 // btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other); 00156 00157 //btTriangleShape tm(triangle[0],triangle[1],triangle[2]); 00158 // tm.setMargin(m_collisionMarginTriangle); 00159 00160 //copy over user pointers to temporary shape 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);//m_manifoldPtr); 00169 // btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody); 00170 00171 //m_resultOut->setShapeIdentifiersB(partId,triangleIndex); 00172 // cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); 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 //btCollisionObject* convexBody = m_isSwapped ? body1 : body0; 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 // if (convexBody->getCollisionShape()->isConvex()) 00232 { 00233 btScalar collisionMarginTriangle = concaveShape->getMargin(); 00234 00235 // resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr); 00236 m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut); 00237 00238 //Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here. 00239 //m_dispatcher->clearManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr); 00240 00241 // m_btSoftBodyTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody); 00242 00243 00244 concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax()); 00245 00246 // resultOut->refreshContactPoints(); 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 //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast) 00264 00265 //only perform CCD above a certain threshold, this prevents blocking on the long run 00266 //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame... 00267 btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2(); 00268 if (squareMot0 < convexbody->getCcdSquareMotionThreshold()) 00269 { 00270 return btScalar(1.); 00271 } 00272 00273 //const btVector3& from = convexbody->m_worldTransform.getOrigin(); 00274 //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin(); 00275 //todo: only do if the motion exceeds the 'radius' 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 //do a swept sphere for now 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 //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); 00314 //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); 00315 //local space? 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.); //is this available? 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 }