Blender  V2.59
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