fairly large refactoring of dispatcher/simulation island management, to allow for parallel simulation.

This commit is contained in:
ejcoumans
2006-07-01 00:22:15 +00:00
parent 8e91b0cd68
commit 2d80bae6e3
16 changed files with 424 additions and 283 deletions

View File

@@ -21,6 +21,7 @@ struct BroadphaseProxy;
class RigidBody;
struct CollisionObject;
class ManifoldResult;
class OverlappingPairCache;
enum CollisionDispatcherId
{
@@ -80,10 +81,17 @@ public:
virtual bool NeedsCollision(BroadphaseProxy& proxy0,BroadphaseProxy& proxy1) = 0;
virtual bool NeedsResponse(const CollisionObject& colObj0,const CollisionObject& colObj1)=0;
virtual ManifoldResult* GetNewManifoldResult(CollisionObject* obj0,CollisionObject* obj1,PersistentManifold* manifold) =0;
virtual void ReleaseManifoldResult(ManifoldResult*)=0;
virtual void DispatchAllCollisionPairs(OverlappingPairCache* pairCache,DispatcherInfo& dispatchInfo)=0;
virtual int GetNumManifolds() const = 0;
virtual PersistentManifold* GetManifoldByIndexInternal(int index) = 0;
};

View File

@@ -28,34 +28,7 @@ subject to the following restrictions:
int gNumManifold = 0;
void CollisionDispatcher::FindUnions()
{
if (m_useIslands)
{
for (int i=0;i<GetNumManifolds();i++)
{
const PersistentManifold* manifold = this->GetManifoldByIndexInternal(i);
//static objects (invmass 0.f) don't merge !
const CollisionObject* colObj0 = static_cast<const CollisionObject*>(manifold->GetBody0());
const CollisionObject* colObj1 = static_cast<const CollisionObject*>(manifold->GetBody1());
if (colObj0 && colObj1 && NeedsResponse(*colObj0,*colObj1))
{
if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
((colObj1) && ((colObj1)->mergesSimulationIslands())))
{
m_unionFind.unite((colObj0)->m_islandTag1,
(colObj1)->m_islandTag1);
}
}
}
}
}
@@ -122,96 +95,6 @@ void CollisionDispatcher::ReleaseManifold(PersistentManifold* manifold)
}
//
// todo: this is random access, it can be walked 'cache friendly'!
//
void CollisionDispatcher::BuildAndProcessIslands(CollisionObjectArray& collisionObjects, IslandCallback* callback)
{
int numBodies = collisionObjects.size();
for (int islandId=0;islandId<numBodies;islandId++)
{
std::vector<PersistentManifold*> islandmanifold;
//int numSleeping = 0;
bool allSleeping = true;
int i;
for (i=0;i<numBodies;i++)
{
CollisionObject* colObj0 = collisionObjects[i];
if (colObj0->m_islandTag1 == islandId)
{
if (colObj0->GetActivationState()== ACTIVE_TAG)
{
allSleeping = false;
}
if (colObj0->GetActivationState()== DISABLE_DEACTIVATION)
{
allSleeping = false;
}
}
}
for (i=0;i<GetNumManifolds();i++)
{
PersistentManifold* manifold = this->GetManifoldByIndexInternal(i);
//filtering for response
CollisionObject* colObj0 = static_cast<CollisionObject*>(manifold->GetBody0());
CollisionObject* colObj1 = static_cast<CollisionObject*>(manifold->GetBody1());
{
if (((colObj0) && (colObj0)->m_islandTag1 == (islandId)) ||
((colObj1) && (colObj1)->m_islandTag1 == (islandId)))
{
if (NeedsResponse(*colObj0,*colObj1))
islandmanifold.push_back(manifold);
}
}
}
if (allSleeping)
{
int i;
for (i=0;i<numBodies;i++)
{
CollisionObject* colObj0 = collisionObjects[i];
if (colObj0->m_islandTag1 == islandId)
{
colObj0->SetActivationState( ISLAND_SLEEPING );
}
}
} else
{
int i;
for (i=0;i<numBodies;i++)
{
CollisionObject* colObj0 = collisionObjects[i];
if (colObj0->m_islandTag1 == islandId)
{
if ( colObj0->GetActivationState() == ISLAND_SLEEPING)
{
colObj0->SetActivationState( WANTS_DEACTIVATION);
}
}
}
/// Process the actual simulation, only if not sleeping/deactivated
if (islandmanifold.size())
{
callback->ProcessIsland(&islandmanifold[0],islandmanifold.size());
}
}
}
}

View File

@@ -18,7 +18,7 @@ subject to the following restrictions:
#include "BroadphaseCollision/Dispatcher.h"
#include "NarrowPhaseCollision/PersistentManifold.h"
#include "CollisionDispatch/UnionFind.h"
#include "CollisionDispatch/ManifoldResult.h"
#include "BroadphaseCollision/BroadphaseProxy.h"
@@ -40,7 +40,7 @@ class CollisionDispatcher : public Dispatcher
std::vector<PersistentManifold*> m_manifoldsPtr;
UnionFind m_unionFind;
bool m_useIslands;
@@ -50,14 +50,9 @@ class CollisionDispatcher : public Dispatcher
public:
UnionFind& GetUnionFind() { return m_unionFind;}
struct IslandCallback
{
virtual ~IslandCallback() {};
virtual void ProcessIsland(PersistentManifold** manifolds,int numManifolds) = 0;
};
int GetNumManifolds() const
@@ -75,14 +70,6 @@ public:
return m_manifoldsPtr[index];
}
void InitUnionFind(int n)
{
if (m_useIslands)
m_unionFind.reset(n);
}
void FindUnions();
int m_count;
CollisionDispatcher ();
@@ -93,8 +80,6 @@ public:
virtual void ReleaseManifold(PersistentManifold* manifold);
virtual void BuildAndProcessIslands(CollisionObjectArray& collisionObjects, IslandCallback* callback);
///allows the user to get contact point callbacks
virtual ManifoldResult* GetNewManifoldResult(CollisionObject* obj0,CollisionObject* obj1,PersistentManifold* manifold);
@@ -120,6 +105,8 @@ public:
virtual void DispatchAllCollisionPairs(OverlappingPairCache* pairCache,DispatcherInfo& dispatchInfo);
};
#endif //COLLISION__DISPATCHER_H

View File

@@ -52,61 +52,10 @@ CollisionWorld::~CollisionWorld()
}
void CollisionWorld::UpdateActivationState()
{
m_dispatcher->InitUnionFind(m_collisionObjects.size());
// put the index into m_controllers into m_tag
{
std::vector<CollisionObject*>::iterator i;
int index = 0;
for (i=m_collisionObjects.begin();
!(i==m_collisionObjects.end()); i++)
{
CollisionObject* collisionObject= (*i);
collisionObject->m_islandTag1 = index;
collisionObject->m_hitFraction = 1.f;
index++;
}
}
// do the union find
m_dispatcher->FindUnions();
}
void CollisionWorld::StoreIslandActivationState()
{
// put the islandId ('find' value) into m_tag
{
UnionFind& unionFind = m_dispatcher->GetUnionFind();
std::vector<CollisionObject*>::iterator i;
int index = 0;
for (i=m_collisionObjects.begin();
!(i==m_collisionObjects.end()); i++)
{
CollisionObject* collisionObject= (*i);
if (collisionObject->mergesSimulationIslands())
{
collisionObject->m_islandTag1 = unionFind.find(index);
} else
{
collisionObject->m_islandTag1 = -1;
}
index++;
}
}
}
@@ -153,7 +102,7 @@ void CollisionWorld::PerformDiscreteCollisionDetection()
m_pairCache->SetAabb(m_collisionObjects[i]->m_broadphaseHandle,aabbMin,aabbMax);
}
CollisionDispatcher* dispatcher = GetDispatcher();
Dispatcher* dispatcher = GetDispatcher();
if (dispatcher)
dispatcher->DispatchAllCollisionPairs(m_pairCache,dispatchInfo);

View File

@@ -84,7 +84,7 @@ class CollisionWorld
std::vector<CollisionObject*> m_collisionObjects;
CollisionDispatcher* m_dispatcher;
CollisionDispatcher* m_dispatcher1;
OverlappingPairCache* m_pairCache;
@@ -92,15 +92,13 @@ class CollisionWorld
public:
CollisionWorld(CollisionDispatcher* dispatcher,OverlappingPairCache* pairCache)
:m_dispatcher(dispatcher),
:m_dispatcher1(dispatcher),
m_pairCache(pairCache)
{
}
virtual ~CollisionWorld();
virtual void UpdateActivationState();
virtual void StoreIslandActivationState();
BroadphaseInterface* GetBroadphase()
{
@@ -113,9 +111,9 @@ public:
}
CollisionDispatcher* GetDispatcher()
Dispatcher* GetDispatcher()
{
return m_dispatcher;
return m_dispatcher1;
}
///LocalShapeInfo gives extra information for complex shapes

View File

@@ -0,0 +1,200 @@
#include "SimulationIslandManager.h"
#include "BroadphaseCollision/Dispatcher.h"
#include "NarrowPhaseCollision/PersistentManifold.h"
#include "CollisionDispatch/CollisionObject.h"
#include "CollisionDispatch/CollisionWorld.h"
SimulationIslandManager::SimulationIslandManager()
{
}
void SimulationIslandManager::InitUnionFind(int n)
{
m_unionFind.reset(n);
}
void SimulationIslandManager::FindUnions(Dispatcher* dispatcher)
{
{
for (int i=0;i<dispatcher->GetNumManifolds();i++)
{
const PersistentManifold* manifold = dispatcher->GetManifoldByIndexInternal(i);
//static objects (invmass 0.f) don't merge !
const CollisionObject* colObj0 = static_cast<const CollisionObject*>(manifold->GetBody0());
const CollisionObject* colObj1 = static_cast<const CollisionObject*>(manifold->GetBody1());
if (colObj0 && colObj1 && dispatcher->NeedsResponse(*colObj0,*colObj1))
{
if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
((colObj1) && ((colObj1)->mergesSimulationIslands())))
{
m_unionFind.unite((colObj0)->m_islandTag1,
(colObj1)->m_islandTag1);
}
}
}
}
}
void SimulationIslandManager::UpdateActivationState(CollisionWorld* colWorld,Dispatcher* dispatcher)
{
InitUnionFind(colWorld->GetCollisionObjectArray().size());
// put the index into m_controllers into m_tag
{
std::vector<CollisionObject*>::iterator i;
int index = 0;
for (i=colWorld->GetCollisionObjectArray().begin();
!(i==colWorld->GetCollisionObjectArray().end()); i++)
{
CollisionObject* collisionObject= (*i);
collisionObject->m_islandTag1 = index;
collisionObject->m_hitFraction = 1.f;
index++;
}
}
// do the union find
FindUnions(dispatcher);
}
void SimulationIslandManager::StoreIslandActivationState(CollisionWorld* colWorld)
{
// put the islandId ('find' value) into m_tag
{
std::vector<CollisionObject*>::iterator i;
int index = 0;
for (i=colWorld->GetCollisionObjectArray().begin();
!(i==colWorld->GetCollisionObjectArray().end()); i++)
{
CollisionObject* collisionObject= (*i);
if (collisionObject->mergesSimulationIslands())
{
collisionObject->m_islandTag1 = m_unionFind.find(index);
} else
{
collisionObject->m_islandTag1 = -1;
}
index++;
}
}
}
//
// todo: this is random access, it can be walked 'cache friendly'!
//
void SimulationIslandManager::BuildAndProcessIslands(Dispatcher* dispatcher,CollisionObjectArray& collisionObjects, IslandCallback* callback)
{
int numBodies = collisionObjects.size();
for (int islandId=0;islandId<numBodies;islandId++)
{
std::vector<PersistentManifold*> islandmanifold;
//int numSleeping = 0;
bool allSleeping = true;
int i;
for (i=0;i<numBodies;i++)
{
CollisionObject* colObj0 = collisionObjects[i];
if (colObj0->m_islandTag1 == islandId)
{
if (colObj0->GetActivationState()== ACTIVE_TAG)
{
allSleeping = false;
}
if (colObj0->GetActivationState()== DISABLE_DEACTIVATION)
{
allSleeping = false;
}
}
}
for (i=0;i<dispatcher->GetNumManifolds();i++)
{
PersistentManifold* manifold = dispatcher->GetManifoldByIndexInternal(i);
//filtering for response
CollisionObject* colObj0 = static_cast<CollisionObject*>(manifold->GetBody0());
CollisionObject* colObj1 = static_cast<CollisionObject*>(manifold->GetBody1());
{
if (((colObj0) && (colObj0)->m_islandTag1 == (islandId)) ||
((colObj1) && (colObj1)->m_islandTag1 == (islandId)))
{
if (dispatcher->NeedsResponse(*colObj0,*colObj1))
islandmanifold.push_back(manifold);
}
}
}
if (allSleeping)
{
int i;
for (i=0;i<numBodies;i++)
{
CollisionObject* colObj0 = collisionObjects[i];
if (colObj0->m_islandTag1 == islandId)
{
colObj0->SetActivationState( ISLAND_SLEEPING );
}
}
} else
{
int i;
for (i=0;i<numBodies;i++)
{
CollisionObject* colObj0 = collisionObjects[i];
if (colObj0->m_islandTag1 == islandId)
{
if ( colObj0->GetActivationState() == ISLAND_SLEEPING)
{
colObj0->SetActivationState( WANTS_DEACTIVATION);
}
}
}
/// Process the actual simulation, only if not sleeping/deactivated
if (islandmanifold.size())
{
callback->ProcessIsland(&islandmanifold[0],islandmanifold.size());
}
}
}
}

View File

@@ -0,0 +1,58 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
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.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SIMULATION_ISLAND_MANAGER_H
#define SIMULATION_ISLAND_MANAGER_H
#include "CollisionDispatch/UnionFind.h"
#include "CollisionCreateFunc.h"
class CollisionWorld;
class Dispatcher;
///SimulationIslandManager creates and handles simulation islands, using UnionFind
class SimulationIslandManager
{
UnionFind m_unionFind;
public:
SimulationIslandManager();
void InitUnionFind(int n);
UnionFind& GetUnionFind() { return m_unionFind;}
virtual void UpdateActivationState(CollisionWorld* colWorld,Dispatcher* dispatcher);
virtual void StoreIslandActivationState(CollisionWorld* world);
void FindUnions(Dispatcher* dispatcher);
struct IslandCallback
{
virtual ~IslandCallback() {};
virtual void ProcessIsland(class PersistentManifold** manifolds,int numManifolds) = 0;
};
void BuildAndProcessIslands(Dispatcher* dispatcher,CollisionObjectArray& collisionObjects, IslandCallback* callback);
};
#endif //SIMULATION_ISLAND_MANAGER_H