3
Bullet Continuous Collision Detection and Physics Library
4
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
6
This software is provided 'as-is', without any express or implied warranty.
7
In no event will the authors be held liable for any damages arising from the use of this software.
8
Permission is granted to anyone to use this software for any purpose,
9
including commercial applications, and to alter it and redistribute it freely,
10
subject to the following restrictions:
12
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.
13
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
14
3. This notice may not be removed or altered from any source distribution.
18
#include "LinearMath/btScalar.h"
19
#include "btSimulationIslandManager.h"
20
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
21
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
22
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
23
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
26
#include "LinearMath/btQuickprof.h"
28
btSimulationIslandManager::btSimulationIslandManager():
33
btSimulationIslandManager::~btSimulationIslandManager()
38
void btSimulationIslandManager::initUnionFind(int n)
44
void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld)
48
btOverlappingPairCache* pairCachePtr = colWorld->getPairCache();
49
const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs();
50
btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr();
52
for (int i=0;i<numOverlappingPairs;i++)
54
const btBroadphasePair& collisionPair = pairPtr[i];
55
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
56
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
58
if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
59
((colObj1) && ((colObj1)->mergesSimulationIslands())))
62
m_unionFind.unite((colObj0)->getIslandTag(),
63
(colObj1)->getIslandTag());
69
#ifdef STATIC_SIMULATION_ISLAND_OPTIMIZATION
70
void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
73
// put the index into m_controllers into m_tag
78
for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
80
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
81
//Adding filtering here
82
if (!collisionObject->isStaticOrKinematicObject())
84
collisionObject->setIslandTag(index++);
86
collisionObject->setCompanionId(-1);
87
collisionObject->setHitFraction(btScalar(1.));
92
initUnionFind( index );
94
findUnions(dispatcher,colWorld);
97
void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
99
// put the islandId ('find' value) into m_tag
103
for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
105
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
106
if (!collisionObject->isStaticOrKinematicObject())
108
collisionObject->setIslandTag( m_unionFind.find(index) );
109
//Set the correct object offset in Collision Object Array
110
m_unionFind.getElement(index).m_sz = i;
111
collisionObject->setCompanionId(-1);
115
collisionObject->setIslandTag(-1);
116
collisionObject->setCompanionId(-2);
123
#else //STATIC_SIMULATION_ISLAND_OPTIMIZATION
124
void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
127
initUnionFind( int (colWorld->getCollisionObjectArray().size()));
129
// put the index into m_controllers into m_tag
134
for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
136
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
137
collisionObject->setIslandTag(index);
138
collisionObject->setCompanionId(-1);
139
collisionObject->setHitFraction(btScalar(1.));
146
findUnions(dispatcher,colWorld);
149
void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
151
// put the islandId ('find' value) into m_tag
157
for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
159
btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
160
if (!collisionObject->isStaticOrKinematicObject())
162
collisionObject->setIslandTag( m_unionFind.find(index) );
163
collisionObject->setCompanionId(-1);
166
collisionObject->setIslandTag(-1);
167
collisionObject->setCompanionId(-2);
174
#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
176
inline int getIslandId(const btPersistentManifold* lhs)
179
const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
180
const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
181
islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag();
188
/// function object that routes calls to operator<
189
class btPersistentManifoldSortPredicate
193
SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs )
195
return getIslandId(lhs) < getIslandId(rhs);
200
void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld)
203
BT_PROFILE("islandUnionFindAndQuickSort");
205
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
207
m_islandmanifold.resize(0);
209
//we are going to sort the unionfind array, and store the element id in the size
210
//afterwards, we clean unionfind, to make sure no-one uses it anymore
212
getUnionFind().sortIslands();
213
int numElem = getUnionFind().getNumElements();
215
int endIslandIndex=1;
216
int startIslandIndex;
219
//update the sleeping state for bodies, if all are sleeping
220
for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
222
int islandId = getUnionFind().getElement(startIslandIndex).m_id;
223
for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
227
//int numSleeping = 0;
229
bool allSleeping = true;
232
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
234
int i = getUnionFind().getElement(idx).m_sz;
236
btCollisionObject* colObj0 = collisionObjects[i];
237
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
239
// printf("error in island management\n");
242
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
243
if (colObj0->getIslandTag() == islandId)
245
if (colObj0->getActivationState()== ACTIVE_TAG)
249
if (colObj0->getActivationState()== DISABLE_DEACTIVATION)
260
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
262
int i = getUnionFind().getElement(idx).m_sz;
263
btCollisionObject* colObj0 = collisionObjects[i];
264
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
266
// printf("error in island management\n");
269
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
271
if (colObj0->getIslandTag() == islandId)
273
colObj0->setActivationState( ISLAND_SLEEPING );
280
for (idx=startIslandIndex;idx<endIslandIndex;idx++)
282
int i = getUnionFind().getElement(idx).m_sz;
284
btCollisionObject* colObj0 = collisionObjects[i];
285
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
287
// printf("error in island management\n");
290
btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
292
if (colObj0->getIslandTag() == islandId)
294
if ( colObj0->getActivationState() == ISLAND_SLEEPING)
296
colObj0->setActivationState( WANTS_DEACTIVATION);
297
colObj0->setDeactivationTime(0.f);
306
int maxNumManifolds = dispatcher->getNumManifolds();
308
//#define SPLIT_ISLANDS 1
309
//#ifdef SPLIT_ISLANDS
312
//#endif //SPLIT_ISLANDS
315
for (i=0;i<maxNumManifolds ;i++)
317
btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
319
btCollisionObject* colObj0 = static_cast<btCollisionObject*>(manifold->getBody0());
320
btCollisionObject* colObj1 = static_cast<btCollisionObject*>(manifold->getBody1());
322
///@todo: check sleeping conditions!
323
if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
324
((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
327
//kinematic objects don't merge islands, but wake up all connected objects
328
if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
332
if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
338
//filtering for response
339
if (dispatcher->needsResponse(colObj0,colObj1))
340
m_islandmanifold.push_back(manifold);
348
///@todo: this is random access, it can be walked 'cache friendly'!
349
void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback)
351
btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
353
buildIslands(dispatcher,collisionWorld);
355
int endIslandIndex=1;
356
int startIslandIndex;
357
int numElem = getUnionFind().getNumElements();
359
BT_PROFILE("processIslands");
363
btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
364
int maxNumManifolds = dispatcher->getNumManifolds();
365
callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1);
369
// Sort manifolds, based on islands
370
// Sort the vector using predicate and std::sort
371
//std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate);
373
int numManifolds = int (m_islandmanifold.size());
375
//we should do radix sort, it it much faster (O(n) instead of O (n log2(n))
376
m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
378
//now process all active islands (sets of manifolds for now)
380
int startManifoldIndex = 0;
381
int endManifoldIndex = 1;
387
// printf("Start Islands\n");
389
//traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
390
for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
392
int islandId = getUnionFind().getElement(startIslandIndex).m_id;
395
bool islandSleeping = true;
397
for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
399
int i = getUnionFind().getElement(endIslandIndex).m_sz;
400
btCollisionObject* colObj0 = collisionObjects[i];
401
m_islandBodies.push_back(colObj0);
402
if (colObj0->isActive())
403
islandSleeping = false;
407
//find the accompanying contact manifold for this islandId
408
int numIslandManifolds = 0;
409
btPersistentManifold** startManifold = 0;
411
if (startManifoldIndex<numManifolds)
413
int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
414
if (curIslandId == islandId)
416
startManifold = &m_islandmanifold[startManifoldIndex];
418
for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++)
422
/// Process the actual simulation, only if not sleeping/deactivated
423
numIslandManifolds = endManifoldIndex-startManifoldIndex;
430
callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId);
431
// printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds);
434
if (numIslandManifolds)
436
startManifoldIndex = endManifoldIndex;
439
m_islandBodies.resize(0);
441
} // else if(!splitIslands)