///@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) }
///@todo: this is random access, it can be walked 'cache friendly'! void btSimulationIslandManager::buildAndProcessIslands( btDispatcher* dispatcher, btCollisionWorld* collisionWorld, btAlignedObjectArray<btTypedConstraint*>& constraints, IslandCallback* callback ) { btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray(); buildIslands(dispatcher,collisionWorld); BT_PROFILE("processIslands"); if(!m_splitIslands) { btPersistentManifold** manifolds = dispatcher->getInternalManifoldPointer(); int maxNumManifolds = dispatcher->getNumManifolds(); for ( int i = 0; i < maxNumManifolds; i++ ) { btPersistentManifold* manifold = manifolds[ 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(); } } } btTypedConstraint** constraintsPtr = constraints.size() ? &constraints[ 0 ] : NULL; callback->processIsland(&collisionObjects[0], collisionObjects.size(), manifolds, maxNumManifolds, constraintsPtr, constraints.size(), -1 ); } else { initIslandPools(); //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated addBodiesToIslands( collisionWorld ); addManifoldsToIslands( dispatcher ); addConstraintsToIslands( constraints ); // m_activeIslands array should now contain all non-sleeping Islands, and each Island should // have all the necessary bodies, manifolds and constraints. // if we want to merge islands with small batch counts, if ( m_minimumSolverBatchSize > 1 ) { mergeIslands(); } // dispatch islands to solver m_islandDispatch( &m_activeIslands, callback ); } }