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                 
00118                 btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
00119 
00120 
00121                 //backup
00122                 btTransform     orgTrans = m_compoundColObj->getWorldTransform();
00123                 btTransform     orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform();
00124                 const btTransform& childTrans = compoundShape->getChildTransform(index);
00125                 btTransform     newChildWorldTrans = orgTrans*childTrans ;
00126 
00127                 //perform an AABB check first
00128                 btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
00129                 childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
00130                 m_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1);
00131 
00132                 if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
00133                 {
00134 
00135                         m_compoundColObj->setWorldTransform( newChildWorldTrans);
00136                         m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans);
00137 
00138                         //the contactpoint is still projected back using the original inverted worldtrans
00139                         btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape();
00140                         m_compoundColObj->internalSetTemporaryCollisionShape( childShape );
00141 
00142                         if (!m_childCollisionAlgorithms[index])
00143                                 m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold);
00144 
00146                         if (m_resultOut->getBody0Internal() == m_compoundColObj)
00147                         {
00148                                 m_resultOut->setShapeIdentifiersA(-1,index);
00149                         } else
00150                         {
00151                                 m_resultOut->setShapeIdentifiersB(-1,index);
00152                         }
00153 
00154                         m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut);
00155                         if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
00156                         {
00157                                 btVector3 worldAabbMin,worldAabbMax;
00158                                 m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
00159                                 m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
00160                         }
00161                         
00162                         //revert back transform
00163                         m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape);
00164                         m_compoundColObj->setWorldTransform(  orgTrans );
00165                         m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans);
00166                 }
00167         }
00168         void            Process(const btDbvtNode* leaf)
00169         {
00170                 int index = leaf->dataAsInt;
00171 
00172                 btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
00173                 btCollisionShape* childShape = compoundShape->getChildShape(index);
00174                 if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
00175                 {
00176                         btVector3 worldAabbMin,worldAabbMax;
00177                         btTransform     orgTrans = m_compoundColObj->getWorldTransform();
00178                         btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
00179                         m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
00180                 }
00181                 ProcessChildShape(childShape,index);
00182 
00183         }
00184 };
00185 
00186 
00187 
00188 
00189 
00190 
00191 void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
00192 {
00193         btCollisionObject* colObj = m_isSwapped? body1 : body0;
00194         btCollisionObject* otherObj = m_isSwapped? body0 : body1;
00195 
00196         
00197 
00198         btAssert (colObj->getCollisionShape()->isCompound());
00199         btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
00200 
00203         if (compoundShape->getUpdateRevision() != m_compoundShapeRevision)
00204         {
00206                 removeChildAlgorithms();
00207                 
00208                 preallocateChildAlgorithms(body0,body1);
00209         }
00210 
00211 
00212         btDbvt* tree = compoundShape->getDynamicAabbTree();
00213         //use a dynamic aabb tree to cull potential child-overlaps
00214         btCompoundLeafCallback  callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
00215 
00219         {
00220                 int i;
00221                 btManifoldArray manifoldArray;
00222                 for (i=0;i<m_childCollisionAlgorithms.size();i++)
00223                 {
00224                         if (m_childCollisionAlgorithms[i])
00225                         {
00226                                 m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
00227                                 for (int m=0;m<manifoldArray.size();m++)
00228                                 {
00229                                         if (manifoldArray[m]->getNumContacts())
00230                                         {
00231                                                 resultOut->setPersistentManifold(manifoldArray[m]);
00232                                                 resultOut->refreshContactPoints();
00233                                                 resultOut->setPersistentManifold(0);//??necessary?
00234                                         }
00235                                 }
00236                                 manifoldArray.clear();
00237                         }
00238                 }
00239         }
00240 
00241         if (tree)
00242         {
00243 
00244                 btVector3 localAabbMin,localAabbMax;
00245                 btTransform otherInCompoundSpace;
00246                 otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform();
00247                 otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
00248 
00249                 const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
00250                 //process all children, that overlap with  the given AABB bounds
00251                 tree->collideTV(tree->m_root,bounds,callback);
00252 
00253         } else
00254         {
00255                 //iterate over all children, perform an AABB check inside ProcessChildShape
00256                 int numChildren = m_childCollisionAlgorithms.size();
00257                 int i;
00258                 for (i=0;i<numChildren;i++)
00259                 {
00260                         callback.ProcessChildShape(compoundShape->getChildShape(i),i);
00261                 }
00262         }
00263 
00264         {
00265                                 //iterate over all children, perform an AABB check inside ProcessChildShape
00266                 int numChildren = m_childCollisionAlgorithms.size();
00267                 int i;
00268                 btManifoldArray manifoldArray;
00269 
00270                 for (i=0;i<numChildren;i++)
00271                 {
00272                         if (m_childCollisionAlgorithms[i])
00273                         {
00274                                 btCollisionShape* childShape = compoundShape->getChildShape(i);
00275                         //if not longer overlapping, remove the algorithm
00276                                 btTransform     orgTrans = colObj->getWorldTransform();
00277                                 btTransform     orgInterpolationTrans = colObj->getInterpolationWorldTransform();
00278                                 const btTransform& childTrans = compoundShape->getChildTransform(i);
00279                                 btTransform     newChildWorldTrans = orgTrans*childTrans ;
00280 
00281                                 //perform an AABB check first
00282                                 btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
00283                                 childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
00284                                 otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1);
00285 
00286                                 if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
00287                                 {
00288                                         m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
00289                                         m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
00290                                         m_childCollisionAlgorithms[i] = 0;
00291                                 }
00292 
00293                         }
00294                         
00295                 }
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         for (i=0;i<numChildren;i++)
00324         {
00325                 //temporarily exchange parent btCollisionShape with childShape, and recurse
00326                 btCollisionShape* childShape = compoundShape->getChildShape(i);
00327 
00328                 //backup
00329                 btTransform     orgTrans = colObj->getWorldTransform();
00330         
00331                 const btTransform& childTrans = compoundShape->getChildTransform(i);
00332                 //btTransform   newChildWorldTrans = orgTrans*childTrans ;
00333                 colObj->setWorldTransform( orgTrans*childTrans );
00334 
00335                 btCollisionShape* tmpShape = colObj->getCollisionShape();
00336                 colObj->internalSetTemporaryCollisionShape( childShape );
00337                 btScalar frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
00338                 if (frac<hitFraction)
00339                 {
00340                         hitFraction = frac;
00341                 }
00342                 //revert back
00343                 colObj->internalSetTemporaryCollisionShape( tmpShape);
00344                 colObj->setWorldTransform( orgTrans);
00345         }
00346         return hitFraction;
00347 
00348 }
00349 
00350 
00351 

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