Blender V2.61 - r43446

btSimulationIslandManager.cpp

Go to the documentation of this file.
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 }