Blender V2.61 - r43446

btSoftRigidDynamicsWorld.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 "btSoftRigidDynamicsWorld.h"
00018 #include "LinearMath/btQuickprof.h"
00019 
00020 //softbody & helpers
00021 #include "btSoftBody.h"
00022 #include "btSoftBodyHelpers.h"
00023 #include "btSoftBodySolvers.h"
00024 #include "btDefaultSoftBodySolver.h"
00025 #include "LinearMath/btSerializer.h"
00026 
00027 
00028 btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(
00029     btDispatcher* dispatcher,
00030     btBroadphaseInterface* pairCache,
00031     btConstraintSolver* constraintSolver,
00032     btCollisionConfiguration* collisionConfiguration,
00033     btSoftBodySolver *softBodySolver ) : 
00034         btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration),
00035         m_softBodySolver( softBodySolver ),
00036         m_ownsSolver(false)
00037 {
00038     if( !m_softBodySolver )
00039     {
00040         void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver),16);
00041         m_softBodySolver = new(ptr) btDefaultSoftBodySolver();
00042         m_ownsSolver = true;
00043     }
00044 
00045     m_drawFlags         =   fDrawFlags::Std;
00046     m_drawNodeTree      =   true;
00047     m_drawFaceTree      =   false;
00048     m_drawClusterTree   =   false;
00049     m_sbi.m_broadphase = pairCache;
00050     m_sbi.m_dispatcher = dispatcher;
00051     m_sbi.m_sparsesdf.Initialize();
00052     m_sbi.m_sparsesdf.Reset();
00053 
00054     m_sbi.air_density       =   (btScalar)1.2;
00055     m_sbi.water_density =   0;
00056     m_sbi.water_offset      =   0;
00057     m_sbi.water_normal      =   btVector3(0,0,0);
00058     m_sbi.m_gravity.setValue(0,-10,0);
00059 
00060     m_sbi.m_sparsesdf.Initialize();
00061 
00062 
00063 }
00064 
00065 btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld()
00066 {
00067     if (m_ownsSolver)
00068     {
00069         m_softBodySolver->~btSoftBodySolver();
00070         btAlignedFree(m_softBodySolver);
00071     }
00072 }
00073 
00074 void    btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
00075 {
00076     btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep );
00077     {
00078         BT_PROFILE("predictUnconstraintMotionSoftBody");
00079         m_softBodySolver->predictMotion( timeStep );
00080     }
00081 }
00082 
00083 void    btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep )
00084 {
00085 
00086     // Let the solver grab the soft bodies and if necessary optimize for it
00087     m_softBodySolver->optimize( getSoftBodyArray() );
00088 
00089     if( !m_softBodySolver->checkInitialized() )
00090     {
00091         btAssert( "Solver initialization failed\n" );
00092     }
00093 
00094     btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep );
00095 
00097     solveSoftBodiesConstraints( timeStep );
00098 
00099     //self collisions
00100     for ( int i=0;i<m_softBodies.size();i++)
00101     {
00102         btSoftBody* psb=(btSoftBody*)m_softBodies[i];
00103         psb->defaultCollisionHandler(psb);
00104     }
00105 
00107     m_softBodySolver->updateSoftBodies( );
00108     
00109     // End solver-wise simulation step
00110     // ///////////////////////////////
00111 
00112 }
00113 
00114 void    btSoftRigidDynamicsWorld::solveSoftBodiesConstraints( btScalar timeStep )
00115 {
00116     BT_PROFILE("solveSoftConstraints");
00117 
00118     if(m_softBodies.size())
00119     {
00120         btSoftBody::solveClusters(m_softBodies);
00121     }
00122 
00123     // Solve constraints solver-wise
00124     m_softBodySolver->solveConstraints( timeStep * m_softBodySolver->getTimeScale() );
00125 
00126 }
00127 
00128 void    btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body,short int collisionFilterGroup,short int collisionFilterMask)
00129 {
00130     m_softBodies.push_back(body);
00131 
00132     // Set the soft body solver that will deal with this body
00133     // to be the world's solver
00134     body->setSoftBodySolver( m_softBodySolver );
00135 
00136     btCollisionWorld::addCollisionObject(body,
00137         collisionFilterGroup,
00138         collisionFilterMask);
00139 
00140 }
00141 
00142 void    btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body)
00143 {
00144     m_softBodies.remove(body);
00145 
00146     btCollisionWorld::removeCollisionObject(body);
00147 }
00148 
00149 void    btSoftRigidDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
00150 {
00151     btSoftBody* body = btSoftBody::upcast(collisionObject);
00152     if (body)
00153         removeSoftBody(body);
00154     else
00155         btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
00156 }
00157 
00158 void    btSoftRigidDynamicsWorld::debugDrawWorld()
00159 {
00160     btDiscreteDynamicsWorld::debugDrawWorld();
00161 
00162     if (getDebugDrawer())
00163     {
00164         int i;
00165         for (  i=0;i<this->m_softBodies.size();i++)
00166         {
00167             btSoftBody* psb=(btSoftBody*)this->m_softBodies[i];
00168             if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe))
00169             {
00170                 btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer);
00171                 btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags);
00172             }
00173             
00174             if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
00175             {
00176                 if(m_drawNodeTree)      btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer);
00177                 if(m_drawFaceTree)      btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer);
00178                 if(m_drawClusterTree)   btSoftBodyHelpers::DrawClusterTree(psb,m_debugDrawer);
00179             }
00180         }       
00181     }   
00182 }
00183 
00184 
00185 
00186 
00187 struct btSoftSingleRayCallback : public btBroadphaseRayCallback
00188 {
00189     btVector3   m_rayFromWorld;
00190     btVector3   m_rayToWorld;
00191     btTransform m_rayFromTrans;
00192     btTransform m_rayToTrans;
00193     btVector3   m_hitNormal;
00194 
00195     const btSoftRigidDynamicsWorld* m_world;
00196     btCollisionWorld::RayResultCallback&    m_resultCallback;
00197 
00198     btSoftSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btSoftRigidDynamicsWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
00199     :m_rayFromWorld(rayFromWorld),
00200     m_rayToWorld(rayToWorld),
00201     m_world(world),
00202     m_resultCallback(resultCallback)
00203     {
00204         m_rayFromTrans.setIdentity();
00205         m_rayFromTrans.setOrigin(m_rayFromWorld);
00206         m_rayToTrans.setIdentity();
00207         m_rayToTrans.setOrigin(m_rayToWorld);
00208 
00209         btVector3 rayDir = (rayToWorld-rayFromWorld);
00210 
00211         rayDir.normalize ();
00213         m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
00214         m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
00215         m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
00216         m_signs[0] = m_rayDirectionInverse[0] < 0.0;
00217         m_signs[1] = m_rayDirectionInverse[1] < 0.0;
00218         m_signs[2] = m_rayDirectionInverse[2] < 0.0;
00219 
00220         m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld);
00221 
00222     }
00223 
00224     
00225 
00226     virtual bool    process(const btBroadphaseProxy* proxy)
00227     {
00229         if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
00230             return false;
00231 
00232         btCollisionObject*  collisionObject = (btCollisionObject*)proxy->m_clientObject;
00233 
00234         //only perform raycast if filterMask matches
00235         if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) 
00236         {
00237             //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
00238             //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
00239 #if 0
00240 #ifdef RECALCULATE_AABB
00241             btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
00242             collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
00243 #else
00244             //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
00245             const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
00246             const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
00247 #endif
00248 #endif
00249             //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
00250             //culling already done by broadphase
00251             //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
00252             {
00253                 m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans,
00254                     collisionObject,
00255                         collisionObject->getCollisionShape(),
00256                         collisionObject->getWorldTransform(),
00257                         m_resultCallback);
00258             }
00259         }
00260         return true;
00261     }
00262 };
00263 
00264 void    btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
00265 {
00266     BT_PROFILE("rayTest");
00269     btSoftSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
00270 
00271 #ifndef USE_BRUTEFORCE_RAYBROADPHASE
00272     m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
00273 #else
00274     for (int i=0;i<this->getNumCollisionObjects();i++)
00275     {
00276         rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
00277     }   
00278 #endif //USE_BRUTEFORCE_RAYBROADPHASE
00279 
00280 }
00281 
00282 
00283 void    btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
00284                       btCollisionObject* collisionObject,
00285                       const btCollisionShape* collisionShape,
00286                       const btTransform& colObjWorldTransform,
00287                       RayResultCallback& resultCallback)
00288 {
00289     if (collisionShape->isSoftBody()) {
00290         btSoftBody* softBody = btSoftBody::upcast(collisionObject);
00291         if (softBody) {
00292             btSoftBody::sRayCast softResult;
00293             if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult)) 
00294             {
00295                 
00296                 if (softResult.fraction<= resultCallback.m_closestHitFraction)
00297                 {
00298 
00299                     btCollisionWorld::LocalShapeInfo shapeInfo;
00300                     shapeInfo.m_shapePart = 0;
00301                     shapeInfo.m_triangleIndex = softResult.index;
00302                     // get the normal
00303                     btVector3 normal = softBody->m_faces[softResult.index].m_normal;
00304                     btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
00305                     if (normal.dot(rayDir) > 0) {
00306                         // normal always point toward origin of the ray
00307                         normal = -normal;
00308                     }
00309                     btCollisionWorld::LocalRayResult rayResult
00310                         (collisionObject,
00311                          &shapeInfo,
00312                          normal,
00313                          softResult.fraction);
00314                     bool    normalInWorldSpace = true;
00315                     resultCallback.addSingleResult(rayResult,normalInWorldSpace);
00316                 }
00317             }
00318         }
00319     } 
00320     else {
00321         btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,collisionObject,collisionShape,colObjWorldTransform,resultCallback);
00322     }
00323 }
00324 
00325 
00326 void    btSoftRigidDynamicsWorld::serializeSoftBodies(btSerializer* serializer)
00327 {
00328     int i;
00329     //serialize all collision objects
00330     for (i=0;i<m_collisionObjects.size();i++)
00331     {
00332         btCollisionObject* colObj = m_collisionObjects[i];
00333         if (colObj->getInternalType() & btCollisionObject::CO_SOFT_BODY)
00334         {
00335             int len = colObj->calculateSerializeBufferSize();
00336             btChunk* chunk = serializer->allocate(len,1);
00337             const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
00338             serializer->finalizeChunk(chunk,structType,BT_SOFTBODY_CODE,colObj);
00339         }
00340     }
00341 
00342 }
00343 
00344 void    btSoftRigidDynamicsWorld::serialize(btSerializer* serializer)
00345 {
00346 
00347     serializer->startSerialization();
00348 
00349     serializeSoftBodies(serializer);
00350 
00351     serializeRigidBodies(serializer);
00352 
00353     serializeCollisionObjects(serializer);
00354 
00355     serializer->finishSerialization();
00356 }
00357 
00358