Blender V2.61 - r43446

btCompoundCollisionAlgorithm.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 #include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
00017 #include "BulletCollision/CollisionDispatch/btCollisionObject.h"
00018 #include "BulletCollision/CollisionShapes/btCompoundShape.h"
00019 #include "BulletCollision/BroadphaseCollision/btDbvt.h"
00020 #include "LinearMath/btIDebugDraw.h"
00021 #include "LinearMath/btAabbUtil2.h"
00022 #include "btManifoldResult.h"
00023 
00024 btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
00025 :btActivatingCollisionAlgorithm(ci,body0,body1),
00026 m_isSwapped(isSwapped),
00027 m_sharedManifold(ci.m_manifold)
00028 {
00029     m_ownsManifold = false;
00030 
00031     btCollisionObject* colObj = m_isSwapped? body1 : body0;
00032     btAssert (colObj->getCollisionShape()->isCompound());
00033     
00034     btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
00035     m_compoundShapeRevision = compoundShape->getUpdateRevision();
00036     
00037     preallocateChildAlgorithms(body0,body1);
00038 }
00039 
00040 void    btCompoundCollisionAlgorithm::preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1)
00041 {
00042     btCollisionObject* colObj = m_isSwapped? body1 : body0;
00043     btCollisionObject* otherObj = m_isSwapped? body0 : body1;
00044     btAssert (colObj->getCollisionShape()->isCompound());
00045     
00046     btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
00047 
00048     int numChildren = compoundShape->getNumChildShapes();
00049     int i;
00050     
00051     m_childCollisionAlgorithms.resize(numChildren);
00052     for (i=0;i<numChildren;i++)
00053     {
00054         if (compoundShape->getDynamicAabbTree())
00055         {
00056             m_childCollisionAlgorithms[i] = 0;
00057         } else
00058         {
00059             btCollisionShape* tmpShape = colObj->getCollisionShape();
00060             btCollisionShape* childShape = compoundShape->getChildShape(i);
00061             colObj->internalSetTemporaryCollisionShape( childShape );
00062             m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(colObj,otherObj,m_sharedManifold);
00063             colObj->internalSetTemporaryCollisionShape( tmpShape );
00064         }
00065     }
00066 }
00067 
00068 void    btCompoundCollisionAlgorithm::removeChildAlgorithms()
00069 {
00070     int numChildren = m_childCollisionAlgorithms.size();
00071     int i;
00072     for (i=0;i<numChildren;i++)
00073     {
00074         if (m_childCollisionAlgorithms[i])
00075         {
00076             m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
00077             m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
00078         }
00079     }
00080 }
00081 
00082 btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
00083 {
00084     removeChildAlgorithms();
00085 }
00086 
00087 
00088 
00089 
00090 struct  btCompoundLeafCallback : btDbvt::ICollide
00091 {
00092 
00093 public:
00094 
00095     btCollisionObject* m_compoundColObj;
00096     btCollisionObject* m_otherObj;
00097     btDispatcher* m_dispatcher;
00098     const btDispatcherInfo& m_dispatchInfo;
00099     btManifoldResult*   m_resultOut;
00100     btCollisionAlgorithm**  m_childCollisionAlgorithms;
00101     btPersistentManifold*   m_sharedManifold;
00102 
00103 
00104 
00105 
00106     btCompoundLeafCallback (btCollisionObject* compoundObj,btCollisionObject* otherObj,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult*  resultOut,btCollisionAlgorithm**    childCollisionAlgorithms,btPersistentManifold*  sharedManifold)
00107         :m_compoundColObj(compoundObj),m_otherObj(otherObj),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
00108         m_childCollisionAlgorithms(childCollisionAlgorithms),
00109         m_sharedManifold(sharedManifold)
00110     {
00111 
00112     }
00113 
00114 
00115     void    ProcessChildShape(btCollisionShape* childShape,int index)
00116     {
00117         btAssert(index>=0);
00118         btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
00119         btAssert(index<compoundShape->getNumChildShapes());
00120 
00121 
00122         //backup
00123         btTransform orgTrans = m_compoundColObj->getWorldTransform();
00124         btTransform orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform();
00125         const btTransform& childTrans = compoundShape->getChildTransform(index);
00126         btTransform newChildWorldTrans = orgTrans*childTrans ;
00127 
00128         //perform an AABB check first
00129         btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
00130         childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
00131         m_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1);
00132 
00133         if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
00134         {
00135 
00136             m_compoundColObj->setWorldTransform( newChildWorldTrans);
00137             m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans);
00138 
00139             //the contactpoint is still projected back using the original inverted worldtrans
00140             btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape();
00141             m_compoundColObj->internalSetTemporaryCollisionShape( childShape );
00142 
00143             if (!m_childCollisionAlgorithms[index])
00144                 m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold);
00145 
00147             if (m_resultOut->getBody0Internal() == m_compoundColObj)
00148             {
00149                 m_resultOut->setShapeIdentifiersA(-1,index);
00150             } else
00151             {
00152                 m_resultOut->setShapeIdentifiersB(-1,index);
00153             }
00154 
00155             m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut);
00156             if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
00157             {
00158                 btVector3 worldAabbMin,worldAabbMax;
00159                 m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
00160                 m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
00161             }
00162             
00163             //revert back transform
00164             m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape);
00165             m_compoundColObj->setWorldTransform(  orgTrans );
00166             m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans);
00167         }
00168     }
00169     void        Process(const btDbvtNode* leaf)
00170     {
00171         int index = leaf->dataAsInt;
00172 
00173         btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
00174         btCollisionShape* childShape = compoundShape->getChildShape(index);
00175         if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
00176         {
00177             btVector3 worldAabbMin,worldAabbMax;
00178             btTransform orgTrans = m_compoundColObj->getWorldTransform();
00179             btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
00180             m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
00181         }
00182         ProcessChildShape(childShape,index);
00183 
00184     }
00185 };
00186 
00187 
00188 
00189 
00190 
00191 
00192 void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00193 {
00194     btCollisionObject* colObj = m_isSwapped? body1 : body0;
00195     btCollisionObject* otherObj = m_isSwapped? body0 : body1;
00196 
00197     
00198 
00199     btAssert (colObj->getCollisionShape()->isCompound());
00200     btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
00201 
00204     if (compoundShape->getUpdateRevision() != m_compoundShapeRevision)
00205     {
00207         removeChildAlgorithms();
00208         
00209         preallocateChildAlgorithms(body0,body1);
00210     }
00211 
00212 
00213     btDbvt* tree = compoundShape->getDynamicAabbTree();
00214     //use a dynamic aabb tree to cull potential child-overlaps
00215     btCompoundLeafCallback  callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
00216 
00220     {
00221         int i;
00222         btManifoldArray manifoldArray;
00223         for (i=0;i<m_childCollisionAlgorithms.size();i++)
00224         {
00225             if (m_childCollisionAlgorithms[i])
00226             {
00227                 m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
00228                 for (int m=0;m<manifoldArray.size();m++)
00229                 {
00230                     if (manifoldArray[m]->getNumContacts())
00231                     {
00232                         resultOut->setPersistentManifold(manifoldArray[m]);
00233                         resultOut->refreshContactPoints();
00234                         resultOut->setPersistentManifold(0);//??necessary?
00235                     }
00236                 }
00237                 manifoldArray.resize(0);
00238             }
00239         }
00240     }
00241 
00242     if (tree)
00243     {
00244 
00245         btVector3 localAabbMin,localAabbMax;
00246         btTransform otherInCompoundSpace;
00247         otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform();
00248         otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
00249 
00250         const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
00251         //process all children, that overlap with  the given AABB bounds
00252         tree->collideTV(tree->m_root,bounds,callback);
00253 
00254     } else
00255     {
00256         //iterate over all children, perform an AABB check inside ProcessChildShape
00257         int numChildren = m_childCollisionAlgorithms.size();
00258         int i;
00259         for (i=0;i<numChildren;i++)
00260         {
00261             callback.ProcessChildShape(compoundShape->getChildShape(i),i);
00262         }
00263     }
00264 
00265     {
00266                 //iterate over all children, perform an AABB check inside ProcessChildShape
00267         int numChildren = m_childCollisionAlgorithms.size();
00268         int i;
00269         btManifoldArray manifoldArray;
00270         btCollisionShape* childShape = 0;
00271         btTransform orgTrans;
00272         btTransform orgInterpolationTrans;
00273         btTransform newChildWorldTrans;
00274         btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;        
00275         
00276         for (i=0;i<numChildren;i++)
00277         {
00278             if (m_childCollisionAlgorithms[i])
00279             {
00280                 childShape = compoundShape->getChildShape(i);
00281             //if not longer overlapping, remove the algorithm
00282                 orgTrans = colObj->getWorldTransform();
00283                 orgInterpolationTrans = colObj->getInterpolationWorldTransform();
00284                 const btTransform& childTrans = compoundShape->getChildTransform(i);
00285                 newChildWorldTrans = orgTrans*childTrans ;
00286 
00287                 //perform an AABB check first
00288                 childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
00289                 otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1);
00290 
00291                 if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
00292                 {
00293                     m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
00294                     m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
00295                     m_childCollisionAlgorithms[i] = 0;
00296                 }
00297             }
00298         }
00299     }
00300 }
00301 
00302 btScalar    btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00303 {
00304 
00305     btCollisionObject* colObj = m_isSwapped? body1 : body0;
00306     btCollisionObject* otherObj = m_isSwapped? body0 : body1;
00307 
00308     btAssert (colObj->getCollisionShape()->isCompound());
00309     
00310     btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
00311 
00312     //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
00313     //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals
00314     //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means:
00315     //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1
00316     //then use each overlapping node AABB against Tree0
00317     //and vise versa.
00318 
00319     btScalar hitFraction = btScalar(1.);
00320 
00321     int numChildren = m_childCollisionAlgorithms.size();
00322     int i;
00323     btTransform orgTrans;
00324     btScalar frac;
00325     for (i=0;i<numChildren;i++)
00326     {
00327         //temporarily exchange parent btCollisionShape with childShape, and recurse
00328         btCollisionShape* childShape = compoundShape->getChildShape(i);
00329 
00330         //backup
00331         orgTrans = colObj->getWorldTransform();
00332     
00333         const btTransform& childTrans = compoundShape->getChildTransform(i);
00334         //btTransform   newChildWorldTrans = orgTrans*childTrans ;
00335         colObj->setWorldTransform( orgTrans*childTrans );
00336 
00337         btCollisionShape* tmpShape = colObj->getCollisionShape();
00338         colObj->internalSetTemporaryCollisionShape( childShape );
00339         frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
00340         if (frac<hitFraction)
00341         {
00342             hitFraction = frac;
00343         }
00344         //revert back
00345         colObj->internalSetTemporaryCollisionShape( tmpShape);
00346         colObj->setWorldTransform( orgTrans);
00347     }
00348     return hitFraction;
00349 
00350 }
00351 
00352 
00353