Blender V2.61 - r43446

btSoftBodyConcaveCollisionAlgorithm.cpp

Go to the documentation of this file.
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 }