Blender V2.61 - r43446
|
00001 00002 /* 00003 Bullet Continuous Collision Detection and Physics Library 00004 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ 00005 00006 This software is provided 'as-is', without any express or implied warranty. 00007 In no event will the authors be held liable for any damages arising from the use of this software. 00008 Permission is granted to anyone to use this software for any purpose, 00009 including commercial applications, and to alter it and redistribute it freely, 00010 subject to the following restrictions: 00011 00012 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. 00013 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 00014 3. This notice may not be removed or altered from any source distribution. 00015 */ 00016 00017 00018 #include "LinearMath/btScalar.h" 00019 #include "btSimulationIslandManager.h" 00020 #include "BulletCollision/BroadphaseCollision/btDispatcher.h" 00021 #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" 00022 #include "BulletCollision/CollisionDispatch/btCollisionObject.h" 00023 #include "BulletCollision/CollisionDispatch/btCollisionWorld.h" 00024 00025 //#include <stdio.h> 00026 #include "LinearMath/btQuickprof.h" 00027 00028 btSimulationIslandManager::btSimulationIslandManager(): 00029 m_splitIslands(true) 00030 { 00031 } 00032 00033 btSimulationIslandManager::~btSimulationIslandManager() 00034 { 00035 } 00036 00037 00038 void btSimulationIslandManager::initUnionFind(int n) 00039 { 00040 m_unionFind.reset(n); 00041 } 00042 00043 00044 void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld) 00045 { 00046 00047 { 00048 btOverlappingPairCache* pairCachePtr = colWorld->getPairCache(); 00049 const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs(); 00050 btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr(); 00051 00052 for (int i=0;i<numOverlappingPairs;i++) 00053 { 00054 const btBroadphasePair& collisionPair = pairPtr[i]; 00055 btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; 00056 btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; 00057 00058 if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && 00059 ((colObj1) && ((colObj1)->mergesSimulationIslands()))) 00060 { 00061 00062 m_unionFind.unite((colObj0)->getIslandTag(), 00063 (colObj1)->getIslandTag()); 00064 } 00065 } 00066 } 00067 } 00068 00069 #ifdef STATIC_SIMULATION_ISLAND_OPTIMIZATION 00070 void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher) 00071 { 00072 00073 // put the index into m_controllers into m_tag 00074 int index = 0; 00075 { 00076 00077 int i; 00078 for (i=0;i<colWorld->getCollisionObjectArray().size(); i++) 00079 { 00080 btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; 00081 //Adding filtering here 00082 if (!collisionObject->isStaticOrKinematicObject()) 00083 { 00084 collisionObject->setIslandTag(index++); 00085 } 00086 collisionObject->setCompanionId(-1); 00087 collisionObject->setHitFraction(btScalar(1.)); 00088 } 00089 } 00090 // do the union find 00091 00092 initUnionFind( index ); 00093 00094 findUnions(dispatcher,colWorld); 00095 } 00096 00097 void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld) 00098 { 00099 // put the islandId ('find' value) into m_tag 00100 { 00101 int index = 0; 00102 int i; 00103 for (i=0;i<colWorld->getCollisionObjectArray().size();i++) 00104 { 00105 btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; 00106 if (!collisionObject->isStaticOrKinematicObject()) 00107 { 00108 collisionObject->setIslandTag( m_unionFind.find(index) ); 00109 //Set the correct object offset in Collision Object Array 00110 m_unionFind.getElement(index).m_sz = i; 00111 collisionObject->setCompanionId(-1); 00112 index++; 00113 } else 00114 { 00115 collisionObject->setIslandTag(-1); 00116 collisionObject->setCompanionId(-2); 00117 } 00118 } 00119 } 00120 } 00121 00122 00123 #else //STATIC_SIMULATION_ISLAND_OPTIMIZATION 00124 void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher) 00125 { 00126 00127 initUnionFind( int (colWorld->getCollisionObjectArray().size())); 00128 00129 // put the index into m_controllers into m_tag 00130 { 00131 00132 int index = 0; 00133 int i; 00134 for (i=0;i<colWorld->getCollisionObjectArray().size(); i++) 00135 { 00136 btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; 00137 collisionObject->setIslandTag(index); 00138 collisionObject->setCompanionId(-1); 00139 collisionObject->setHitFraction(btScalar(1.)); 00140 index++; 00141 00142 } 00143 } 00144 // do the union find 00145 00146 findUnions(dispatcher,colWorld); 00147 } 00148 00149 void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld) 00150 { 00151 // put the islandId ('find' value) into m_tag 00152 { 00153 00154 00155 int index = 0; 00156 int i; 00157 for (i=0;i<colWorld->getCollisionObjectArray().size();i++) 00158 { 00159 btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; 00160 if (!collisionObject->isStaticOrKinematicObject()) 00161 { 00162 collisionObject->setIslandTag( m_unionFind.find(index) ); 00163 collisionObject->setCompanionId(-1); 00164 } else 00165 { 00166 collisionObject->setIslandTag(-1); 00167 collisionObject->setCompanionId(-2); 00168 } 00169 index++; 00170 } 00171 } 00172 } 00173 00174 #endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION 00175 00176 inline int getIslandId(const btPersistentManifold* lhs) 00177 { 00178 int islandId; 00179 const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0()); 00180 const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1()); 00181 islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag(); 00182 return islandId; 00183 00184 } 00185 00186 00187 00189 class btPersistentManifoldSortPredicate 00190 { 00191 public: 00192 00193 SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs ) 00194 { 00195 return getIslandId(lhs) < getIslandId(rhs); 00196 } 00197 }; 00198 00199 00200 void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld) 00201 { 00202 00203 BT_PROFILE("islandUnionFindAndQuickSort"); 00204 00205 btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); 00206 00207 m_islandmanifold.resize(0); 00208 00209 //we are going to sort the unionfind array, and store the element id in the size 00210 //afterwards, we clean unionfind, to make sure no-one uses it anymore 00211 00212 getUnionFind().sortIslands(); 00213 int numElem = getUnionFind().getNumElements(); 00214 00215 int endIslandIndex=1; 00216 int startIslandIndex; 00217 00218 00219 //update the sleeping state for bodies, if all are sleeping 00220 for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex) 00221 { 00222 int islandId = getUnionFind().getElement(startIslandIndex).m_id; 00223 for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++) 00224 { 00225 } 00226 00227 //int numSleeping = 0; 00228 00229 bool allSleeping = true; 00230 00231 int idx; 00232 for (idx=startIslandIndex;idx<endIslandIndex;idx++) 00233 { 00234 int i = getUnionFind().getElement(idx).m_sz; 00235 00236 btCollisionObject* colObj0 = collisionObjects[i]; 00237 if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) 00238 { 00239 // printf("error in island management\n"); 00240 } 00241 00242 btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); 00243 if (colObj0->getIslandTag() == islandId) 00244 { 00245 if (colObj0->getActivationState()== ACTIVE_TAG) 00246 { 00247 allSleeping = false; 00248 } 00249 if (colObj0->getActivationState()== DISABLE_DEACTIVATION) 00250 { 00251 allSleeping = false; 00252 } 00253 } 00254 } 00255 00256 00257 if (allSleeping) 00258 { 00259 int idx; 00260 for (idx=startIslandIndex;idx<endIslandIndex;idx++) 00261 { 00262 int i = getUnionFind().getElement(idx).m_sz; 00263 btCollisionObject* colObj0 = collisionObjects[i]; 00264 if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) 00265 { 00266 // printf("error in island management\n"); 00267 } 00268 00269 btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); 00270 00271 if (colObj0->getIslandTag() == islandId) 00272 { 00273 colObj0->setActivationState( ISLAND_SLEEPING ); 00274 } 00275 } 00276 } else 00277 { 00278 00279 int idx; 00280 for (idx=startIslandIndex;idx<endIslandIndex;idx++) 00281 { 00282 int i = getUnionFind().getElement(idx).m_sz; 00283 00284 btCollisionObject* colObj0 = collisionObjects[i]; 00285 if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) 00286 { 00287 // printf("error in island management\n"); 00288 } 00289 00290 btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); 00291 00292 if (colObj0->getIslandTag() == islandId) 00293 { 00294 if ( colObj0->getActivationState() == ISLAND_SLEEPING) 00295 { 00296 colObj0->setActivationState( WANTS_DEACTIVATION); 00297 colObj0->setDeactivationTime(0.f); 00298 } 00299 } 00300 } 00301 } 00302 } 00303 00304 00305 int i; 00306 int maxNumManifolds = dispatcher->getNumManifolds(); 00307 00308 //#define SPLIT_ISLANDS 1 00309 //#ifdef SPLIT_ISLANDS 00310 00311 00312 //#endif //SPLIT_ISLANDS 00313 00314 00315 for (i=0;i<maxNumManifolds ;i++) 00316 { 00317 btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i); 00318 00319 btCollisionObject* colObj0 = static_cast<btCollisionObject*>(manifold->getBody0()); 00320 btCollisionObject* colObj1 = static_cast<btCollisionObject*>(manifold->getBody1()); 00321 00323 if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) || 00324 ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING)) 00325 { 00326 00327 //kinematic objects don't merge islands, but wake up all connected objects 00328 if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) 00329 { 00330 colObj1->activate(); 00331 } 00332 if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) 00333 { 00334 colObj0->activate(); 00335 } 00336 if(m_splitIslands) 00337 { 00338 //filtering for response 00339 if (dispatcher->needsResponse(colObj0,colObj1)) 00340 m_islandmanifold.push_back(manifold); 00341 } 00342 } 00343 } 00344 } 00345 00346 00347 00349 void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback) 00350 { 00351 btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); 00352 00353 buildIslands(dispatcher,collisionWorld); 00354 00355 int endIslandIndex=1; 00356 int startIslandIndex; 00357 int numElem = getUnionFind().getNumElements(); 00358 00359 BT_PROFILE("processIslands"); 00360 00361 if(!m_splitIslands) 00362 { 00363 btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer(); 00364 int maxNumManifolds = dispatcher->getNumManifolds(); 00365 callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1); 00366 } 00367 else 00368 { 00369 // Sort manifolds, based on islands 00370 // Sort the vector using predicate and std::sort 00371 //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); 00372 00373 int numManifolds = int (m_islandmanifold.size()); 00374 00375 //we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) 00376 m_islandmanifold.quickSort(btPersistentManifoldSortPredicate()); 00377 00378 //now process all active islands (sets of manifolds for now) 00379 00380 int startManifoldIndex = 0; 00381 int endManifoldIndex = 1; 00382 00383 //int islandId; 00384 00385 00386 00387 // printf("Start Islands\n"); 00388 00389 //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated 00390 for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex) 00391 { 00392 int islandId = getUnionFind().getElement(startIslandIndex).m_id; 00393 00394 00395 bool islandSleeping = true; 00396 00397 for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++) 00398 { 00399 int i = getUnionFind().getElement(endIslandIndex).m_sz; 00400 btCollisionObject* colObj0 = collisionObjects[i]; 00401 m_islandBodies.push_back(colObj0); 00402 if (colObj0->isActive()) 00403 islandSleeping = false; 00404 } 00405 00406 00407 //find the accompanying contact manifold for this islandId 00408 int numIslandManifolds = 0; 00409 btPersistentManifold** startManifold = 0; 00410 00411 if (startManifoldIndex<numManifolds) 00412 { 00413 int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]); 00414 if (curIslandId == islandId) 00415 { 00416 startManifold = &m_islandmanifold[startManifoldIndex]; 00417 00418 for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++) 00419 { 00420 00421 } 00423 numIslandManifolds = endManifoldIndex-startManifoldIndex; 00424 } 00425 00426 } 00427 00428 if (!islandSleeping) 00429 { 00430 callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); 00431 // printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); 00432 } 00433 00434 if (numIslandManifolds) 00435 { 00436 startManifoldIndex = endManifoldIndex; 00437 } 00438 00439 m_islandBodies.resize(0); 00440 } 00441 } // else if(!splitIslands) 00442 00443 }