Some work-in-progress on making btDbvtBroadphase deterministic. When using the btSortedOverlappingPairCache, it seems deterministic now. todo: when using btHashedOverlappingPairCache.

This commit is contained in:
erwin.coumans
2009-02-10 03:50:58 +00:00
parent bd5a7f623d
commit 2a10a61f50
11 changed files with 207 additions and 160 deletions

View File

@@ -1261,10 +1261,28 @@ void DemoApplication::clientResetScene()
int numObjects = 0;
if (m_dynamicsWorld)
{
m_dynamicsWorld->stepSimulation(1.f/60.f,0);
numObjects = m_dynamicsWorld->getNumCollisionObjects();
}
#ifdef TEST_DETERMINISM
btCollisionObjectArray copyArray = m_dynamicsWorld->getCollisionObjectArray();
for (int i=0;i<copyArray.size();i++)
{
btRigidBody* body = btRigidBody::upcast(copyArray[i]);
if (body)
m_dynamicsWorld->removeRigidBody(body);
}
for (int i=0;i<copyArray.size();i++)
{
btRigidBody* body = btRigidBody::upcast(copyArray[i]);
if (body)
m_dynamicsWorld->addRigidBody(btRigidBody::upcast(copyArray[i]));
}
#endif //TEST_DETERMINISM
for (int i=0;i<numObjects;i++)
{
btCollisionObject* colObj = m_dynamicsWorld->getCollisionObjectArray()[i];
@@ -1277,7 +1295,9 @@ void DemoApplication::clientResetScene()
myMotionState->m_graphicsWorldTrans = myMotionState->m_startWorldTrans;
body->setCenterOfMassTransform( myMotionState->m_graphicsWorldTrans );
colObj->setInterpolationWorldTransform( myMotionState->m_startWorldTrans );
colObj->forceActivationState(ACTIVE_TAG);
colObj->activate();
colObj->setDeactivationTime(0);
//colObj->setActivationState(WANTS_DEACTIVATION);
}
//removed cached contact points
@@ -1291,15 +1311,11 @@ void DemoApplication::clientResetScene()
}
}
btAxisSweep3* sap = (btAxisSweep3*)m_dynamicsWorld->getBroadphase();
sap->resetPool();
/*
//quickly search some issue at a certain simulation frame, pressing space to reset
int fixed=18;
for (int i=0;i<fixed;i++)
{
getDynamicsWorld()->stepSimulation(1./60.f,1);
}
*/
}
m_dynamicsWorld->getBroadphase()->resetPool(getDynamicsWorld()->getDispatcher());
m_dynamicsWorld->getPairCache()->sortOverlappingPairs(getDynamicsWorld()->getDispatcher());
}

View File

@@ -139,7 +139,7 @@ public:
void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
void resetPool();
virtual void resetPool(btDispatcher* dispatcher);
void processAllOverlappingPairs(btOverlapCallback* callback);
@@ -588,7 +588,7 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle,bt
}
template <typename BP_FP_INT_TYPE>
void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool()
void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* dispatcher)
{
if (m_numHandles == 0)
{
@@ -611,86 +611,8 @@ void btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatche
if (m_pairCache->hasDeferredRemoval())
{
btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
int i;
btBroadphasePair previousPair;
previousPair.m_pProxy0 = 0;
previousPair.m_pProxy1 = 0;
previousPair.m_algorithm = 0;
for (i=0;i<overlappingPairArray.size();i++)
{
btBroadphasePair& pair = overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
previousPair = pair;
bool needsRemoval = false;
if (!isDuplicate)
{
bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
if (hasOverlap)
{
needsRemoval = false;//callback->processOverlap(pair);
} else
{
needsRemoval = true;
m_pairCache->performDeferredRemoval(dispatcher);
}
} else
{
//remove duplicate
needsRemoval = true;
//should have no algorithm
btAssert(!pair.m_algorithm);
}
if (needsRemoval)
{
m_pairCache->cleanOverlappingPair(pair,dispatcher);
// m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
// m_overlappingPairArray.pop_back();
pair.m_pProxy0 = 0;
pair.m_pProxy1 = 0;
m_invalidPair++;
gOverlappingPairs--;
}
}
///if you don't like to skip the invalid pairs in the array, execute following code:
#define CLEAN_INVALID_PAIRS 1
#ifdef CLEAN_INVALID_PAIRS
//perform a sort, to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
m_invalidPair = 0;
#endif//CLEAN_INVALID_PAIRS
//printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
}
}

View File

@@ -64,6 +64,9 @@ public:
///will add some transform later
virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0;
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher)=0;
virtual void printStats() = 0;
};

View File

@@ -344,70 +344,9 @@ void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
if (m_paircache->hasDeferredRemoval())
{
btBroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
int invalidPair = 0;
int i;
btBroadphasePair previousPair;
previousPair.m_pProxy0 = 0;
previousPair.m_pProxy1 = 0;
previousPair.m_algorithm = 0;
for (i=0;i<overlappingPairArray.size();i++)
{
btBroadphasePair& pair = overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
previousPair = pair;
bool needsRemoval = false;
if (!isDuplicate)
{
btDbvtProxy* pa=(btDbvtProxy*)pair.m_pProxy0;
btDbvtProxy* pb=(btDbvtProxy*)pair.m_pProxy1;
bool hasOverlap = Intersect(pa->leaf->volume,pb->leaf->volume);
if (hasOverlap)
{
needsRemoval = false;//callback->processOverlap(pair);
} else
{
needsRemoval = true;
}
} else
{
//remove duplicate
needsRemoval = true;
//should have no algorithm
btAssert(!pair.m_algorithm);
m_paircache->performDeferredRemoval(dispatcher);
}
if (needsRemoval)
{
m_paircache->cleanOverlappingPair(pair,dispatcher);
pair.m_pProxy0 = 0;
pair.m_pProxy1 = 0;
invalidPair++;
}
}
//perform a sort, to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
}
}
//
@@ -536,6 +475,30 @@ void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aab
aabbMax=bounds.Maxs();
}
void btDbvtBroadphase::resetPool(btDispatcher* dispatcher)
{
return;
m_sets[0].optimizeBottomUp();
m_sets[1].optimizeBottomUp();
btDbvtProxy* current=m_stageRoots[m_stageCurrent];
if(current)
{
btDbvtTreeCollider collider(this);
do {
btDbvtProxy* next=current->links[1];
listremove(current,m_stageRoots[current->stage]);
listappend(current,m_stageRoots[m_stageCurrent]);
current->stage = m_stageCurrent;
current = next;
} while(current);
}
}
//
void btDbvtBroadphase::printStats()
{}
@@ -668,3 +631,4 @@ void btDbvtBroadphase::benchmark(btBroadphaseInterface*)
#if DBVT_BP_PROFILE
#undef SPC
#endif

View File

@@ -114,6 +114,10 @@ struct btDbvtBroadphase : btBroadphaseInterface
void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
void printStats();
static void benchmark(btBroadphaseInterface*);
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
};
#endif

View File

@@ -482,3 +482,8 @@ void btMultiSapBroadphase::printStats()
*/
}
void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher)
{
// not yet
}

View File

@@ -143,6 +143,9 @@ public:
void quicksort (btBroadphasePairArray& a, int lo, int hi);
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
};
#endif //BT_MULTI_SAP_BROADPHASE

View File

@@ -19,6 +19,7 @@ subject to the following restrictions:
#include "btDispatcher.h"
#include "btCollisionAlgorithm.h"
#include "LinearMath/btAabbUtil2.h"
#include <stdio.h>
@@ -395,6 +396,35 @@ void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback*
}
}
void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
{
///need to keep hashmap in sync with pair address, so rebuild all
btBroadphasePairArray tmpPairs;
int i;
for (i=0;i<m_overlappingPairArray.size();i++)
{
tmpPairs.push_back(m_overlappingPairArray[i]);
}
for (i=0;i<tmpPairs.size();i++)
{
removeOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1,dispatcher);
}
for (i = 0; i < m_next.size(); i++)
{
m_next[i] = BT_NULL_PAIR;
}
tmpPairs.quickSort(btBroadphasePairSortPredicate());
for (i=0;i<tmpPairs.size();i++)
{
addOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1);
}
}
void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher )
@@ -493,8 +523,9 @@ void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback*
if (callback->processOverlap(*pair))
{
cleanOverlappingPair(*pair,dispatcher);
m_overlappingPairArray.swap(i,m_overlappingPairArray.capacity()-1);
pair->m_pProxy0 = 0;
pair->m_pProxy1 = 0;
m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
m_overlappingPairArray.pop_back();
gOverlappingPairs--;
} else
@@ -594,3 +625,76 @@ void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroad
processAllOverlappingPairs(&removeCallback,dispatcher);
}
void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
{
//should already be sorted
}
void btSortedOverlappingPairCache::performDeferredRemoval(btDispatcher* dispatcher)
{
btBroadphasePairArray& overlappingPairArray = getOverlappingPairArray();
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
int invalidPair = 0;
int i;
btBroadphasePair previousPair;
previousPair.m_pProxy0 = 0;
previousPair.m_pProxy1 = 0;
previousPair.m_algorithm = 0;
for (i=0;i<overlappingPairArray.size();i++)
{
btBroadphasePair& pair = overlappingPairArray[i];
bool isDuplicate = (pair == previousPair);
previousPair = pair;
bool needsRemoval = false;
if (!isDuplicate)
{
bool hasOverlap = TestAabbAgainstAabb2(pair.m_pProxy0->m_aabbMin,pair.m_pProxy0->m_aabbMax,pair.m_pProxy1->m_aabbMin,pair.m_pProxy1->m_aabbMax);
if (hasOverlap)
{
needsRemoval = false;
} else
{
needsRemoval = true;
}
} else
{
//remove duplicate
needsRemoval = true;
//should have no algorithm
btAssert(!pair.m_algorithm);
}
if (needsRemoval)
{
cleanOverlappingPair(pair,dispatcher);
pair.m_pProxy0 = 0;
pair.m_pProxy1 = 0;
invalidPair++;
}
}
//perform a sort, to sort 'invalid' pairs to the end
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
}

View File

@@ -84,6 +84,10 @@ public:
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0;
virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0;
virtual void performDeferredRemoval(btDispatcher* dispatcher) = 0;
};
/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
@@ -259,7 +263,14 @@ private:
m_ghostPairCallback = ghostPairCallback;
}
public:
virtual void sortOverlappingPairs(btDispatcher* dispatcher);
virtual void performDeferredRemoval(btDispatcher* dispatcher)
{
}
protected:
btAlignedObjectArray<int> m_hashTable;
btAlignedObjectArray<int> m_next;
@@ -369,6 +380,10 @@ class btSortedOverlappingPairCache : public btOverlappingPairCache
m_ghostPairCallback = ghostPairCallback;
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher);
void performDeferredRemoval(btDispatcher* dispatcher);
};
@@ -447,7 +462,13 @@ public:
{
}
virtual void sortOverlappingPairs(btDispatcher* dispatcher)
{
}
virtual void performDeferredRemoval(btDispatcher* dispatcher)
{
}
};

View File

@@ -324,5 +324,7 @@ bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseP
return aabbOverlap(p0,p1);
}
void btSimpleBroadphase::resetPool(btDispatcher* dispatcher)
{
//not yet
}

View File

@@ -108,6 +108,9 @@ protected:
return proxy0;
}
///reset broadphase internal structures, to ensure determinism/reproducability
virtual void resetPool(btDispatcher* dispatcher);
void validate();