SIMD_FORCE_INLINE bool operator() (const btPersistentManifold* lhs, const btPersistentManifold* rhs) const { return ( (getIslandId(lhs) < getIslandId(rhs)) || ((getIslandId(lhs) == getIslandId(rhs)) && lhs->getBody0()->getBroadphaseHandle()->m_uniqueId < rhs->getBody0()->getBroadphaseHandle()->m_uniqueId) ||((getIslandId(lhs) == getIslandId(rhs)) && (lhs->getBody0()->getBroadphaseHandle()->m_uniqueId == rhs->getBody0()->getBroadphaseHandle()->m_uniqueId) && (lhs->getBody1()->getBroadphaseHandle()->m_uniqueId < rhs->getBody1()->getBroadphaseHandle()->m_uniqueId)) ); }
void btSimulationIslandManager::addManifoldsToIslands( btDispatcher* dispatcher ) { // walk all the manifolds, activating bodies touched by kinematic objects, and add each manifold to its Island int maxNumManifolds = dispatcher->getNumManifolds(); for ( int i = 0; i < maxNumManifolds; i++ ) { btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal( i ); const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>( manifold->getBody0() ); const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>( manifold->getBody1() ); ///@todo: check sleeping conditions! if ( ( ( colObj0 ) && colObj0->getActivationState() != ISLAND_SLEEPING ) || ( ( colObj1 ) && colObj1->getActivationState() != ISLAND_SLEEPING ) ) { //kinematic objects don't merge islands, but wake up all connected objects if ( colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING ) { if ( colObj0->hasContactResponse() ) colObj1->activate(); } if ( colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING ) { if ( colObj1->hasContactResponse() ) colObj0->activate(); } //filtering for response if ( dispatcher->needsResponse( colObj0, colObj1 ) ) { // scatter manifolds into various islands int islandId = getIslandId( manifold ); // if island not sleeping, if ( Island* island = getIsland( islandId ) ) { island->manifoldArray.push_back( manifold ); } } } } }
///@todo: this is random access, it can be walked 'cache friendly'! void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback) { btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); buildIslands(dispatcher,collisionWorld); int endIslandIndex=1; int startIslandIndex; int numElem = getUnionFind().getNumElements(); BT_PROFILE("processIslands"); if(!m_splitIslands) { btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer(); int maxNumManifolds = dispatcher->getNumManifolds(); callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1); } else { // Sort manifolds, based on islands // Sort the vector using predicate and std::sort //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); int numManifolds = int (m_islandmanifold.size()); //we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) m_islandmanifold.quickSort(btPersistentManifoldSortPredicate()); //now process all active islands (sets of manifolds for now) int startManifoldIndex = 0; int endManifoldIndex = 1; //int islandId; // printf("Start Islands\n"); //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex) { int islandId = getUnionFind().getElement(startIslandIndex).m_id; bool islandSleeping = false; for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++) { int i = getUnionFind().getElement(endIslandIndex).m_sz; btCollisionObject* colObj0 = collisionObjects[i]; m_islandBodies.push_back(colObj0); if (!colObj0->isActive()) islandSleeping = true; } //find the accompanying contact manifold for this islandId int numIslandManifolds = 0; btPersistentManifold** startManifold = 0; if (startManifoldIndex<numManifolds) { int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]); if (curIslandId == islandId) { startManifold = &m_islandmanifold[startManifoldIndex]; for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++) { } /// Process the actual simulation, only if not sleeping/deactivated numIslandManifolds = endManifoldIndex-startManifoldIndex; } } if (!islandSleeping) { callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); // printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); } if (numIslandManifolds) { startManifoldIndex = endManifoldIndex; } m_islandBodies.resize(0); } } // else if(!splitIslands) }
SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs ) { return getIslandId(lhs) < getIslandId(rhs); }
// // todo: this is random access, it can be walked 'cache friendly'! // void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback) { /*if (0) { int maxNumManifolds = dispatcher->getNumManifolds(); btCollisionDispatcher* colDis = (btCollisionDispatcher*)dispatcher; btPersistentManifold** manifold = colDis->getInternalManifoldPointer(); callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, 0); return; } */ BEGIN_PROFILE("islandUnionFindAndHeapSort"); //we are going to sort the unionfind array, and store the element id in the size //afterwards, we clean unionfind, to make sure no-one uses it anymore getUnionFind().sortIslands(); int numElem = getUnionFind().getNumElements(); int endIslandIndex=1; int startIslandIndex; //update the sleeping state for bodies, if all are sleeping for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex) { int islandId = getUnionFind().getElement(startIslandIndex).m_id; for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++) { } //int numSleeping = 0; bool allSleeping = true; int idx; for (idx=startIslandIndex;idx<endIslandIndex;idx++) { int i = getUnionFind().getElement(idx).m_sz; btCollisionObject* colObj0 = collisionObjects[i]; if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) { printf("error in island management\n"); } assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); if (colObj0->getIslandTag() == islandId) { if (colObj0->getActivationState()== ACTIVE_TAG) { allSleeping = false; } if (colObj0->getActivationState()== DISABLE_DEACTIVATION) { allSleeping = false; } } } if (allSleeping) { int idx; for (idx=startIslandIndex;idx<endIslandIndex;idx++) { int i = getUnionFind().getElement(idx).m_sz; btCollisionObject* colObj0 = collisionObjects[i]; if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) { printf("error in island management\n"); } assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); if (colObj0->getIslandTag() == islandId) { colObj0->setActivationState( ISLAND_SLEEPING ); } } } else { int idx; for (idx=startIslandIndex;idx<endIslandIndex;idx++) { int i = getUnionFind().getElement(idx).m_sz; btCollisionObject* colObj0 = collisionObjects[i]; if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) { printf("error in island management\n"); } assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); if (colObj0->getIslandTag() == islandId) { if ( colObj0->getActivationState() == ISLAND_SLEEPING) { colObj0->setActivationState( WANTS_DEACTIVATION); } } } } } btAlignedObjectArray<btPersistentManifold*> islandmanifold; int i; int maxNumManifolds = dispatcher->getNumManifolds(); islandmanifold.reserve(maxNumManifolds); for (i=0;i<maxNumManifolds ;i++) { btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i); btCollisionObject* colObj0 = static_cast<btCollisionObject*>(manifold->getBody0()); btCollisionObject* colObj1 = static_cast<btCollisionObject*>(manifold->getBody1()); //todo: check sleeping conditions! if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) || ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING)) { //kinematic objects don't merge islands, but wake up all connected objects if (colObj0->isStaticOrKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) { colObj1->activate(); } if (colObj1->isStaticOrKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) { colObj0->activate(); } //filtering for response if (dispatcher->needsResponse(colObj0,colObj1)) islandmanifold.push_back(manifold); } } int numManifolds = int (islandmanifold.size()); // Sort manifolds, based on islands // Sort the vector using predicate and std::sort //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); //we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) islandmanifold.heapSort(btPersistentManifoldSortPredicate()); //now process all active islands (sets of manifolds for now) int startManifoldIndex = 0; int endManifoldIndex = 1; //int islandId; END_PROFILE("islandUnionFindAndHeapSort"); btAlignedObjectArray<btCollisionObject*> islandBodies; //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex) { int islandId = getUnionFind().getElement(startIslandIndex).m_id; bool islandSleeping = false; for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++) { int i = getUnionFind().getElement(endIslandIndex).m_sz; btCollisionObject* colObj0 = collisionObjects[i]; islandBodies.push_back(colObj0); if (!colObj0->isActive()) islandSleeping = true; } //find the accompanying contact manifold for this islandId int numIslandManifolds = 0; btPersistentManifold** startManifold = 0; if (startManifoldIndex<numManifolds) { int curIslandId = getIslandId(islandmanifold[startManifoldIndex]); if (curIslandId == islandId) { startManifold = &islandmanifold[startManifoldIndex]; for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(islandmanifold[endManifoldIndex]));endManifoldIndex++) { } /// Process the actual simulation, only if not sleeping/deactivated numIslandManifolds = endManifoldIndex-startManifoldIndex; } } if (!islandSleeping) { callback->ProcessIsland(&islandBodies[0],islandBodies.size(),startManifold,numIslandManifolds, islandId); } if (numIslandManifolds) { startManifoldIndex = endManifoldIndex; } islandBodies.resize(0); } }