Make the btDbvtBroadphase deterministic/reproducable, by sorting the btBroadphasePair using unique ID, instead of proxy address.

The btAxisSweep3 didn't suffer from this issue, because proxies were always allocated in-order, as part of an array.
This commit is contained in:
erwin.coumans
2008-12-08 20:16:29 +00:00
parent 65cdd7146f
commit 6db1b932fd
5 changed files with 16 additions and 27 deletions

View File

@@ -187,7 +187,7 @@ BT_DECLARE_ALIGNED_ALLOCATOR();
{ {
//keep them sorted, so the std::set operations work //keep them sorted, so the std::set operations work
if (&proxy0 < &proxy1) if (proxy0.m_uniqueId < proxy1.m_uniqueId)
{ {
m_pProxy0 = &proxy0; m_pProxy0 = &proxy0;
m_pProxy1 = &proxy1; m_pProxy1 = &proxy1;
@@ -228,8 +228,8 @@ class btBroadphasePairSortPredicate
bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b )
{ {
return a.m_pProxy0 > b.m_pProxy0 || return a.m_pProxy0->m_uniqueId > b.m_pProxy0->m_uniqueId ||
(a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 > b.m_pProxy1) || (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1->m_uniqueId > b.m_pProxy1->m_uniqueId) ||
(a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm); (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm);
} }
}; };

View File

@@ -146,9 +146,7 @@ struct btDbvtAabbMm
DBVT_INLINE btScalar ProjectMinimum(const btVector3& v,unsigned signs) const; DBVT_INLINE btScalar ProjectMinimum(const btVector3& v,unsigned signs) const;
DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
const btDbvtAabbMm& b); const btDbvtAabbMm& b);
DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
const btDbvtAabbMm& b,
const btTransform& xform);
DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
const btVector3& b); const btVector3& b);
@@ -530,21 +528,7 @@ DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
#endif #endif
} }
//
DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
const btDbvtAabbMm& b,
const btTransform& xform)
{
const btVector3 d0=xform*b.Center()-a.Center();
const btVector3 d1=d0*xform.getBasis();
btScalar s0[2]={0,0};
btScalar s1[2]={dot(xform.getOrigin(),d0),s1[0]};
a.AddSpan(d0,s0[0],s0[1]);
b.AddSpan(d1,s1[0],s1[1]);
if(s0[0]>(s1[1])) return(false);
if(s0[1]<(s1[0])) return(false);
return(true);
}
// //
DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,

View File

@@ -100,7 +100,8 @@ struct btDbvtTreeCollider : btDbvt::ICollide
btDbvtProxy* pa=(btDbvtProxy*)na->data; btDbvtProxy* pa=(btDbvtProxy*)na->data;
btDbvtProxy* pb=(btDbvtProxy*)nb->data; btDbvtProxy* pb=(btDbvtProxy*)nb->data;
#if DBVT_BP_SORTPAIRS #if DBVT_BP_SORTPAIRS
if(pa>pb) btSwap(pa,pb); if(pa->m_uniqueId>pb->m_uniqueId)
btSwap(pa,pb);
#endif #endif
pbp->m_paircache->addOverlappingPair(pa,pb); pbp->m_paircache->addOverlappingPair(pa,pb);
++pbp->m_newpairs; ++pbp->m_newpairs;
@@ -411,7 +412,8 @@ void btDbvtBroadphase::collide(btDispatcher* dispatcher)
if(!Intersect(pa->leaf->volume,pb->leaf->volume)) if(!Intersect(pa->leaf->volume,pb->leaf->volume))
{ {
#if DBVT_BP_SORTPAIRS #if DBVT_BP_SORTPAIRS
if(pa>pb) btSwap(pa,pb); if(pa->m_uniqueId>pb->m_uniqueId)
btSwap(pa,pb);
#endif #endif
m_paircache->removeOverlappingPair(pa,pb,dispatcher); m_paircache->removeOverlappingPair(pa,pb,dispatcher);
--ni;--i; --ni;--i;

View File

@@ -24,7 +24,7 @@ subject to the following restrictions:
// //
#define DBVT_BP_PROFILE 0 #define DBVT_BP_PROFILE 0
#define DBVT_BP_SORTPAIRS 1 //#define DBVT_BP_SORTPAIRS 1
#define DBVT_BP_PREVENTFALSEUPDATE 0 #define DBVT_BP_PREVENTFALSEUPDATE 0
#define DBVT_BP_ACCURATESLEEPING 0 #define DBVT_BP_ACCURATESLEEPING 0
#define DBVT_BP_ENABLE_BENCHMARK 0 #define DBVT_BP_ENABLE_BENCHMARK 0

View File

@@ -135,7 +135,8 @@ void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroad
btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{ {
gFindPairs++; gFindPairs++;
if(proxy0>proxy1) btSwap(proxy0,proxy1); if(proxy0->m_uniqueId>proxy1->m_uniqueId)
btSwap(proxy0,proxy1);
int proxyId1 = proxy0->getUid(); int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid(); int proxyId2 = proxy1->getUid();
@@ -211,7 +212,8 @@ void btHashedOverlappingPairCache::growTables()
btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{ {
if(proxy0>proxy1) btSwap(proxy0,proxy1); if(proxy0->m_uniqueId>proxy1->m_uniqueId)
btSwap(proxy0,proxy1);
int proxyId1 = proxy0->getUid(); int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid(); int proxyId2 = proxy1->getUid();
@@ -270,7 +272,8 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher) void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
{ {
gRemovePairs++; gRemovePairs++;
if(proxy0>proxy1) btSwap(proxy0,proxy1); if(proxy0->m_uniqueId>proxy1->m_uniqueId)
btSwap(proxy0,proxy1);
int proxyId1 = proxy0->getUid(); int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid(); int proxyId2 = proxy1->getUid();