Blender V2.61 - r43446
|
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