1 /* 2 Bullet Continuous Collision Detection and Physics Library 3 Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org 4 5 This software is provided 'as-is', without any express or implied warranty. 6 In no event will the authors be held liable for any damages arising from the use of this software. 7 Permission is granted to anyone to use this software for any purpose, 8 including commercial applications, and to alter it and redistribute it freely, 9 subject to the following restrictions: 10 11 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. 12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 3. This notice may not be removed or altered from any source distribution. 14 15 */ 16 17 #include "btCompoundCompoundCollisionAlgorithm.h" 18 #include "BulletCollision/CollisionDispatch/btCollisionObject.h" 19 #include "BulletCollision/CollisionShapes/btCompoundShape.h" 20 #include "BulletCollision/BroadphaseCollision/btDbvt.h" 21 #include "LinearMath/btIDebugDraw.h" 22 #include "LinearMath/btAabbUtil2.h" 23 #include "BulletCollision/CollisionDispatch/btManifoldResult.h" 24 #include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h" 25 26 27 btShapePairCallback gCompoundCompoundChildShapePairCallback = 0; 28 29 btCompoundCompoundCollisionAlgorithm::btCompoundCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,bool isSwapped) 30 :btCompoundCollisionAlgorithm(ci,body0Wrap,body1Wrap,isSwapped) 31 { 32 33 void* ptr = btAlignedAlloc(sizeof(btHashedSimplePairCache),16); 34 m_childCollisionAlgorithmCache= new(ptr) btHashedSimplePairCache(); 35 36 const btCollisionObjectWrapper* col0ObjWrap = body0Wrap; 37 btAssert (col0ObjWrap->getCollisionShape()->isCompound()); 38 39 const btCollisionObjectWrapper* col1ObjWrap = body1Wrap; 40 btAssert (col1ObjWrap->getCollisionShape()->isCompound()); 41 42 const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape()); 43 m_compoundShapeRevision0 = compoundShape0->getUpdateRevision(); 44 45 const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape()); 46 m_compoundShapeRevision1 = compoundShape1->getUpdateRevision(); 47 48 49 } 50 51 52 btCompoundCompoundCollisionAlgorithm::~btCompoundCompoundCollisionAlgorithm() 53 { 54 removeChildAlgorithms(); 55 m_childCollisionAlgorithmCache->~btHashedSimplePairCache(); 56 btAlignedFree(m_childCollisionAlgorithmCache); 57 } 58 59 void btCompoundCompoundCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray) 60 { 61 int i; 62 btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray(); 63 for (i=0;i<pairs.size();i++) 64 { 65 if (pairs[i].m_userPointer) 66 { 67 68 ((btCollisionAlgorithm*)pairs[i].m_userPointer)->getAllContactManifolds(manifoldArray); 69 } 70 } 71 } 72 73 74 void btCompoundCompoundCollisionAlgorithm::removeChildAlgorithms() 75 { 76 btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray(); 77 78 int numChildren = pairs.size(); 79 int i; 80 for (i=0;i<numChildren;i++) 81 { 82 if (pairs[i].m_userPointer) 83 { 84 btCollisionAlgorithm* algo = (btCollisionAlgorithm*) pairs[i].m_userPointer; 85 algo->~btCollisionAlgorithm(); 86 m_dispatcher->freeCollisionAlgorithm(algo); 87 } 88 } 89 m_childCollisionAlgorithmCache->removeAllPairs(); 90 } 91 92 struct btCompoundCompoundLeafCallback : btDbvt::ICollide 93 { 94 int m_numOverlapPairs; 95 96 97 const btCollisionObjectWrapper* m_compound0ColObjWrap; 98 const btCollisionObjectWrapper* m_compound1ColObjWrap; 99 btDispatcher* m_dispatcher; 100 const btDispatcherInfo& m_dispatchInfo; 101 btManifoldResult* m_resultOut; 102 103 104 class btHashedSimplePairCache* m_childCollisionAlgorithmCache; 105 106 btPersistentManifold* m_sharedManifold; 107 108 btCompoundCompoundLeafCallback (const btCollisionObjectWrapper* compound1ObjWrap, 109 const btCollisionObjectWrapper* compound0ObjWrap, 110 btDispatcher* dispatcher, 111 const btDispatcherInfo& dispatchInfo, 112 btManifoldResult* resultOut, 113 btHashedSimplePairCache* childAlgorithmsCache, 114 btPersistentManifold* sharedManifold) 115 :m_numOverlapPairs(0),m_compound0ColObjWrap(compound1ObjWrap),m_compound1ColObjWrap(compound0ObjWrap),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut), 116 m_childCollisionAlgorithmCache(childAlgorithmsCache), 117 m_sharedManifold(sharedManifold) 118 { 119 120 } 121 122 123 124 125 void Process(const btDbvtNode* leaf0,const btDbvtNode* leaf1) 126 { 127 m_numOverlapPairs++; 128 129 130 int childIndex0 = leaf0->dataAsInt; 131 int childIndex1 = leaf1->dataAsInt; 132 133 134 btAssert(childIndex0>=0); 135 btAssert(childIndex1>=0); 136 137 138 const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(m_compound0ColObjWrap->getCollisionShape()); 139 btAssert(childIndex0<compoundShape0->getNumChildShapes()); 140 141 const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(m_compound1ColObjWrap->getCollisionShape()); 142 btAssert(childIndex1<compoundShape1->getNumChildShapes()); 143 144 const btCollisionShape* childShape0 = compoundShape0->getChildShape(childIndex0); 145 const btCollisionShape* childShape1 = compoundShape1->getChildShape(childIndex1); 146 147 //backup 148 btTransform orgTrans0 = m_compound0ColObjWrap->getWorldTransform(); 149 const btTransform& childTrans0 = compoundShape0->getChildTransform(childIndex0); 150 btTransform newChildWorldTrans0 = orgTrans0*childTrans0 ; 151 152 btTransform orgTrans1 = m_compound1ColObjWrap->getWorldTransform(); 153 const btTransform& childTrans1 = compoundShape1->getChildTransform(childIndex1); 154 btTransform newChildWorldTrans1 = orgTrans1*childTrans1 ; 155 156 157 //perform an AABB check first 158 btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; 159 childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0); 160 childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1); 161 162 if (gCompoundCompoundChildShapePairCallback) 163 { 164 if (!gCompoundCompoundChildShapePairCallback(childShape0,childShape1)) 165 return; 166 } 167 168 if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) 169 { 170 btCollisionObjectWrapper compoundWrap0(this->m_compound0ColObjWrap,childShape0, m_compound0ColObjWrap->getCollisionObject(),newChildWorldTrans0,-1,childIndex0); 171 btCollisionObjectWrapper compoundWrap1(this->m_compound1ColObjWrap,childShape1,m_compound1ColObjWrap->getCollisionObject(),newChildWorldTrans1,-1,childIndex1); 172 173 174 btSimplePair* pair = m_childCollisionAlgorithmCache->findPair(childIndex0,childIndex1); 175 176 btCollisionAlgorithm* colAlgo = 0; 177 178 if (pair) 179 { 180 colAlgo = (btCollisionAlgorithm*)pair->m_userPointer; 181 182 } else 183 { 184 colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0,&compoundWrap1,m_sharedManifold); 185 pair = m_childCollisionAlgorithmCache->addOverlappingPair(childIndex0,childIndex1); 186 btAssert(pair); 187 pair->m_userPointer = colAlgo; 188 } 189 190 btAssert(colAlgo); 191 192 const btCollisionObjectWrapper* tmpWrap0 = 0; 193 const btCollisionObjectWrapper* tmpWrap1 = 0; 194 195 tmpWrap0 = m_resultOut->getBody0Wrap(); 196 tmpWrap1 = m_resultOut->getBody1Wrap(); 197 198 m_resultOut->setBody0Wrap(&compoundWrap0); 199 m_resultOut->setBody1Wrap(&compoundWrap1); 200 201 m_resultOut->setShapeIdentifiersA(-1,childIndex0); 202 m_resultOut->setShapeIdentifiersB(-1,childIndex1); 203 204 205 colAlgo->processCollision(&compoundWrap0,&compoundWrap1,m_dispatchInfo,m_resultOut); 206 207 m_resultOut->setBody0Wrap(tmpWrap0); 208 m_resultOut->setBody1Wrap(tmpWrap1); 209 210 211 212 } 213 } 214 }; 215 216 217 static DBVT_INLINE bool MyIntersect( const btDbvtAabbMm& a, 218 const btDbvtAabbMm& b, const btTransform& xform) 219 { 220 btVector3 newmin,newmax; 221 btTransformAabb(b.Mins(),b.Maxs(),0.f,xform,newmin,newmax); 222 btDbvtAabbMm newb = btDbvtAabbMm::FromMM(newmin,newmax); 223 return Intersect(a,newb); 224 } 225 226 227 static inline void MycollideTT( const btDbvtNode* root0, 228 const btDbvtNode* root1, 229 const btTransform& xform, 230 btCompoundCompoundLeafCallback* callback) 231 { 232 233 if(root0&&root1) 234 { 235 int depth=1; 236 int treshold=btDbvt::DOUBLE_STACKSIZE-4; 237 btAlignedObjectArray<btDbvt::sStkNN> stkStack; 238 stkStack.resize(btDbvt::DOUBLE_STACKSIZE); 239 stkStack[0]=btDbvt::sStkNN(root0,root1); 240 do { 241 btDbvt::sStkNN p=stkStack[--depth]; 242 if(MyIntersect(p.a->volume,p.b->volume,xform)) 243 { 244 if(depth>treshold) 245 { 246 stkStack.resize(stkStack.size()*2); 247 treshold=stkStack.size()-4; 248 } 249 if(p.a->isinternal()) 250 { 251 if(p.b->isinternal()) 252 { 253 stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b->childs[0]); 254 stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b->childs[0]); 255 stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b->childs[1]); 256 stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b->childs[1]); 257 } 258 else 259 { 260 stkStack[depth++]=btDbvt::sStkNN(p.a->childs[0],p.b); 261 stkStack[depth++]=btDbvt::sStkNN(p.a->childs[1],p.b); 262 } 263 } 264 else 265 { 266 if(p.b->isinternal()) 267 { 268 stkStack[depth++]=btDbvt::sStkNN(p.a,p.b->childs[0]); 269 stkStack[depth++]=btDbvt::sStkNN(p.a,p.b->childs[1]); 270 } 271 else 272 { 273 callback->Process(p.a,p.b); 274 } 275 } 276 } 277 } while(depth); 278 } 279 } 280 281 void btCompoundCompoundCollisionAlgorithm::processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) 282 { 283 284 const btCollisionObjectWrapper* col0ObjWrap = body0Wrap; 285 const btCollisionObjectWrapper* col1ObjWrap= body1Wrap; 286 287 btAssert (col0ObjWrap->getCollisionShape()->isCompound()); 288 btAssert (col1ObjWrap->getCollisionShape()->isCompound()); 289 const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape()); 290 const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape()); 291 292 const btDbvt* tree0 = compoundShape0->getDynamicAabbTree(); 293 const btDbvt* tree1 = compoundShape1->getDynamicAabbTree(); 294 if (!tree0 || !tree1) 295 { 296 return btCompoundCollisionAlgorithm::processCollision(body0Wrap,body1Wrap,dispatchInfo,resultOut); 297 } 298 ///btCompoundShape might have changed: 299 ////make sure the internal child collision algorithm caches are still valid 300 if ((compoundShape0->getUpdateRevision() != m_compoundShapeRevision0) || (compoundShape1->getUpdateRevision() != m_compoundShapeRevision1)) 301 { 302 ///clear all 303 removeChildAlgorithms(); 304 m_compoundShapeRevision0 = compoundShape0->getUpdateRevision(); 305 m_compoundShapeRevision1 = compoundShape1->getUpdateRevision(); 306 307 } 308 309 310 ///we need to refresh all contact manifolds 311 ///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep 312 ///so we should add a 'refreshManifolds' in the btCollisionAlgorithm 313 { 314 int i; 315 btManifoldArray manifoldArray; 316 btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray(); 317 for (i=0;i<pairs.size();i++) 318 { 319 if (pairs[i].m_userPointer) 320 { 321 btCollisionAlgorithm* algo = (btCollisionAlgorithm*) pairs[i].m_userPointer; 322 algo->getAllContactManifolds(manifoldArray); 323 for (int m=0;m<manifoldArray.size();m++) 324 { 325 if (manifoldArray[m]->getNumContacts()) 326 { 327 resultOut->setPersistentManifold(manifoldArray[m]); 328 resultOut->refreshContactPoints(); 329 resultOut->setPersistentManifold(0); 330 } 331 } 332 manifoldArray.resize(0); 333 } 334 } 335 } 336 337 338 339 340 btCompoundCompoundLeafCallback callback(col0ObjWrap,col1ObjWrap,this->m_dispatcher,dispatchInfo,resultOut,this->m_childCollisionAlgorithmCache,m_sharedManifold); 341 342 343 const btTransform xform=col0ObjWrap->getWorldTransform().inverse()*col1ObjWrap->getWorldTransform(); 344 MycollideTT(tree0->m_root,tree1->m_root,xform,&callback); 345 346 //printf("#compound-compound child/leaf overlap =%d \r",callback.m_numOverlapPairs); 347 348 //remove non-overlapping child pairs 349 350 { 351 btAssert(m_removePairs.size()==0); 352 353 //iterate over all children, perform an AABB check inside ProcessChildShape 354 btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray(); 355 356 int i; 357 btManifoldArray manifoldArray; 358 359 360 361 362 363 btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; 364 365 for (i=0;i<pairs.size();i++) 366 { 367 if (pairs[i].m_userPointer) 368 { 369 btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer; 370 371 { 372 btTransform orgTrans0; 373 const btCollisionShape* childShape0 = 0; 374 375 btTransform newChildWorldTrans0; 376 btTransform orgInterpolationTrans0; 377 childShape0 = compoundShape0->getChildShape(pairs[i].m_indexA); 378 orgTrans0 = col0ObjWrap->getWorldTransform(); 379 orgInterpolationTrans0 = col0ObjWrap->getWorldTransform(); 380 const btTransform& childTrans0 = compoundShape0->getChildTransform(pairs[i].m_indexA); 381 newChildWorldTrans0 = orgTrans0*childTrans0 ; 382 childShape0->getAabb(newChildWorldTrans0,aabbMin0,aabbMax0); 383 } 384 385 { 386 btTransform orgInterpolationTrans1; 387 const btCollisionShape* childShape1 = 0; 388 btTransform orgTrans1; 389 btTransform newChildWorldTrans1; 390 391 childShape1 = compoundShape1->getChildShape(pairs[i].m_indexB); 392 orgTrans1 = col1ObjWrap->getWorldTransform(); 393 orgInterpolationTrans1 = col1ObjWrap->getWorldTransform(); 394 const btTransform& childTrans1 = compoundShape1->getChildTransform(pairs[i].m_indexB); 395 newChildWorldTrans1 = orgTrans1*childTrans1 ; 396 childShape1->getAabb(newChildWorldTrans1,aabbMin1,aabbMax1); 397 } 398 399 400 401 if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) 402 { 403 algo->~btCollisionAlgorithm(); 404 m_dispatcher->freeCollisionAlgorithm(algo); 405 m_removePairs.push_back(btSimplePair(pairs[i].m_indexA,pairs[i].m_indexB)); 406 } 407 } 408 } 409 for (int i=0;i<m_removePairs.size();i++) 410 { 411 m_childCollisionAlgorithmCache->removeOverlappingPair(m_removePairs[i].m_indexA,m_removePairs[i].m_indexB); 412 } 413 m_removePairs.clear(); 414 } 415 416 } 417 418 btScalar btCompoundCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) 419 { 420 btAssert(0); 421 return 0.f; 422 423 } 424 425 426 427