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:
@@ -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());
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -482,3 +482,8 @@ void btMultiSapBroadphase::printStats()
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher)
|
||||
{
|
||||
// not yet
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -324,5 +324,7 @@ bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseP
|
||||
return aabbOverlap(p0,p1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void btSimpleBroadphase::resetPool(btDispatcher* dispatcher)
|
||||
{
|
||||
//not yet
|
||||
}
|
||||
|
||||
@@ -108,6 +108,9 @@ protected:
|
||||
return proxy0;
|
||||
}
|
||||
|
||||
///reset broadphase internal structures, to ensure determinism/reproducability
|
||||
virtual void resetPool(btDispatcher* dispatcher);
|
||||
|
||||
|
||||
void validate();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user