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 }

Generated on Mon Feb 15 22:17:06 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1