Added btGhostObject and btPairCachingGhostObject functionality.
It is a fast way to keep track of overlapping objects in an area, and doing rayTest and convexSweepTest for overlapping objects, instead of btCollisionWorld::rayTest/convexSweepTest. Updated KinematicCharacterController to use btPairCachingGhostObject.
This commit is contained in:
@@ -33,7 +33,8 @@ int gFindPairs =0;
|
||||
|
||||
btHashedOverlappingPairCache::btHashedOverlappingPairCache():
|
||||
m_overlapFilterCallback(0),
|
||||
m_blockedForChanges(false)
|
||||
m_blockedForChanges(false),
|
||||
m_ghostPairCallback(0)
|
||||
{
|
||||
int initialAllocatedSize= 2;
|
||||
m_overlappingPairArray.reserve(initialAllocatedSize);
|
||||
@@ -238,6 +239,11 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
|
||||
int count = m_overlappingPairArray.size();
|
||||
int oldCapacity = m_overlappingPairArray.capacity();
|
||||
void* mem = &m_overlappingPairArray.expand();
|
||||
|
||||
//this is where we add an actual pair, so also call the 'ghost'
|
||||
if (m_ghostPairCallback)
|
||||
m_ghostPairCallback->addOverlappingPair(proxy0,proxy1);
|
||||
|
||||
int newCapacity = m_overlappingPairArray.capacity();
|
||||
|
||||
if (oldCapacity < newCapacity)
|
||||
@@ -317,6 +323,9 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
|
||||
|
||||
int lastPairIndex = m_overlappingPairArray.size() - 1;
|
||||
|
||||
if (m_ghostPairCallback)
|
||||
m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
|
||||
|
||||
// If the removed pair is the last pair, we are done.
|
||||
if (lastPairIndex == pairIndex)
|
||||
{
|
||||
@@ -399,6 +408,8 @@ void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
|
||||
btBroadphasePair& pair = m_overlappingPairArray[findIndex];
|
||||
void* userData = pair.m_userInfo;
|
||||
cleanOverlappingPair(pair,dispatcher);
|
||||
if (m_ghostPairCallback)
|
||||
m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
|
||||
|
||||
m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
|
||||
m_overlappingPairArray.pop_back();
|
||||
@@ -426,8 +437,12 @@ btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseP
|
||||
|
||||
void* mem = &m_overlappingPairArray.expand();
|
||||
btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
|
||||
|
||||
gOverlappingPairs++;
|
||||
gAddedPairs++;
|
||||
|
||||
if (m_ghostPairCallback)
|
||||
m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
|
||||
return pair;
|
||||
|
||||
}
|
||||
@@ -493,7 +508,8 @@ void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback*
|
||||
btSortedOverlappingPairCache::btSortedOverlappingPairCache():
|
||||
m_blockedForChanges(false),
|
||||
m_hasDeferredRemoval(true),
|
||||
m_overlapFilterCallback(0)
|
||||
m_overlapFilterCallback(0),
|
||||
m_ghostPairCallback(0)
|
||||
{
|
||||
int initialAllocatedSize= 2;
|
||||
m_overlappingPairArray.reserve(initialAllocatedSize);
|
||||
|
||||
@@ -83,6 +83,8 @@ public:
|
||||
|
||||
virtual bool hasDeferredRemoval() = 0;
|
||||
|
||||
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0;
|
||||
|
||||
};
|
||||
|
||||
/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
|
||||
@@ -253,10 +255,16 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
|
||||
{
|
||||
m_ghostPairCallback = ghostPairCallback;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
btAlignedObjectArray<int> m_hashTable;
|
||||
btAlignedObjectArray<int> m_next;
|
||||
btOverlappingPairCallback* m_ghostPairCallback;
|
||||
|
||||
};
|
||||
|
||||
@@ -280,6 +288,8 @@ class btSortedOverlappingPairCache : public btOverlappingPairCache
|
||||
//if set, use the callback instead of the built in filter in needBroadphaseCollision
|
||||
btOverlapFilterCallback* m_overlapFilterCallback;
|
||||
|
||||
btOverlappingPairCallback* m_ghostPairCallback;
|
||||
|
||||
public:
|
||||
|
||||
btSortedOverlappingPairCache();
|
||||
@@ -355,12 +365,17 @@ class btSortedOverlappingPairCache : public btOverlappingPairCache
|
||||
return m_hasDeferredRemoval;
|
||||
}
|
||||
|
||||
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
|
||||
{
|
||||
m_ghostPairCallback = ghostPairCallback;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and testing.
|
||||
///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
|
||||
class btNullPairCache : public btOverlappingPairCache
|
||||
{
|
||||
|
||||
@@ -414,6 +429,10 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
|
||||
{
|
||||
}
|
||||
|
||||
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/)
|
||||
{
|
||||
return 0;
|
||||
@@ -427,6 +446,7 @@ public:
|
||||
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -17,7 +17,6 @@ subject to the following restrictions:
|
||||
#define COLLISION_CREATE_FUNC
|
||||
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray;
|
||||
class btCollisionAlgorithm;
|
||||
class btCollisionObject;
|
||||
|
||||
|
||||
@@ -29,8 +29,11 @@ struct btBroadphaseProxy;
|
||||
class btCollisionShape;
|
||||
#include "LinearMath/btMotionState.h"
|
||||
#include "LinearMath/btAlignedAllocator.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
|
||||
|
||||
typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray;
|
||||
|
||||
|
||||
/// btCollisionObject can be used to manage collision detection objects.
|
||||
/// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy.
|
||||
|
||||
@@ -71,7 +71,7 @@ class btBroadphaseInterface;
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "LinearMath/btTransform.h"
|
||||
#include "btCollisionObject.h"
|
||||
#include "btCollisionDispatcher.h" //for definition of btCollisionObjectArray
|
||||
#include "btCollisionDispatcher.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
|
||||
|
||||
@@ -14,16 +14,149 @@ subject to the following restrictions:
|
||||
*/
|
||||
|
||||
#include "btGhostObject.h"
|
||||
#include "btCollisionWorld.h"
|
||||
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||
#include "LinearMath/btAabbUtil2.h"
|
||||
|
||||
btGhostObject::btGhostObject()
|
||||
{
|
||||
m_internalType = CO_GHOST_OBJECT;
|
||||
|
||||
m_overlappingPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
|
||||
m_overlappingPairCache->setOverlapFilterCallback(&m_ghostOverlapFilterCallback);
|
||||
}
|
||||
|
||||
btGhostObject::~btGhostObject()
|
||||
{
|
||||
btAlignedFree(m_overlappingPairCache);
|
||||
///btGhostObject should have been removed from the world, so no overlapping objects
|
||||
btAssert(!m_overlappingObjects.size());
|
||||
}
|
||||
|
||||
|
||||
void btGhostObject::addOverlappingObject(btBroadphaseProxy* otherProxy)
|
||||
{
|
||||
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
|
||||
btAssert(otherObject);
|
||||
int index = m_overlappingObjects.findLinearSearch(otherObject);
|
||||
if (index==m_overlappingObjects.size())
|
||||
{
|
||||
m_overlappingObjects.push_back(otherObject);
|
||||
}
|
||||
}
|
||||
|
||||
void btGhostObject::removeOverlappingObject(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher)
|
||||
{
|
||||
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
|
||||
btAssert(otherObject);
|
||||
int index = m_overlappingObjects.findLinearSearch(otherObject);
|
||||
if (index<m_overlappingObjects.size())
|
||||
{
|
||||
m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
|
||||
m_overlappingObjects.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
btPairCachingGhostObject::btPairCachingGhostObject()
|
||||
{
|
||||
m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
|
||||
}
|
||||
|
||||
btPairCachingGhostObject::~btPairCachingGhostObject()
|
||||
{
|
||||
btAlignedFree( m_hashPairCache );
|
||||
}
|
||||
|
||||
void btPairCachingGhostObject::addOverlappingObject(btBroadphaseProxy* otherProxy)
|
||||
{
|
||||
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
|
||||
btAssert(otherObject);
|
||||
int index = m_overlappingObjects.findLinearSearch(otherObject);
|
||||
if (index==m_overlappingObjects.size())
|
||||
{
|
||||
m_overlappingObjects.push_back(otherObject);
|
||||
m_hashPairCache->addOverlappingPair(getBroadphaseHandle(),otherProxy);
|
||||
}
|
||||
}
|
||||
|
||||
void btPairCachingGhostObject::removeOverlappingObject(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher)
|
||||
{
|
||||
btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
|
||||
btAssert(otherObject);
|
||||
int index = m_overlappingObjects.findLinearSearch(otherObject);
|
||||
if (index<m_overlappingObjects.size())
|
||||
{
|
||||
m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
|
||||
m_overlappingObjects.pop_back();
|
||||
m_hashPairCache->removeOverlappingPair(getBroadphaseHandle(),otherProxy,dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btScalar allowedCcdPenetration, btCollisionWorld::ConvexResultCallback& resultCallback) const
|
||||
{
|
||||
btTransform convexFromTrans,convexToTrans;
|
||||
convexFromTrans = convexFromWorld;
|
||||
convexToTrans = convexToWorld;
|
||||
btVector3 castShapeAabbMin, castShapeAabbMax;
|
||||
/* Compute AABB that encompasses angular movement */
|
||||
{
|
||||
btVector3 linVel, angVel;
|
||||
btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel);
|
||||
btTransform R;
|
||||
R.setIdentity ();
|
||||
R.setRotation (convexFromTrans.getRotation());
|
||||
castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
|
||||
}
|
||||
|
||||
/// go over all objects, and if the ray intersects their aabb + cast shape aabb,
|
||||
// do a ray-shape query using convexCaster (CCD)
|
||||
int i;
|
||||
for (i=0;i<m_overlappingObjects.size();i++)
|
||||
{
|
||||
btCollisionObject* collisionObject= m_overlappingObjects[i];
|
||||
//only perform raycast if filterMask matches
|
||||
if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
|
||||
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
|
||||
btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
|
||||
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
|
||||
AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
|
||||
btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
|
||||
btVector3 hitNormal;
|
||||
if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
|
||||
{
|
||||
btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans,
|
||||
collisionObject,
|
||||
collisionObject->getCollisionShape(),
|
||||
collisionObject->getWorldTransform(),
|
||||
resultCallback,
|
||||
allowedCcdPenetration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
|
||||
{
|
||||
btTransform rayFromTrans;
|
||||
rayFromTrans.setIdentity();
|
||||
rayFromTrans.setOrigin(rayFromWorld);
|
||||
btTransform rayToTrans;
|
||||
rayToTrans.setIdentity();
|
||||
rayToTrans.setOrigin(rayToWorld);
|
||||
|
||||
|
||||
int i;
|
||||
for (i=0;i<m_overlappingObjects.size();i++)
|
||||
{
|
||||
btCollisionObject* collisionObject= m_overlappingObjects[i];
|
||||
//only perform raycast if filterMask matches
|
||||
if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
|
||||
{
|
||||
btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,
|
||||
collisionObject,
|
||||
collisionObject->getCollisionShape(),
|
||||
collisionObject->getWorldTransform(),
|
||||
resultCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,11 @@ subject to the following restrictions:
|
||||
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
|
||||
#include "LinearMath/btAlignedAllocator.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
|
||||
#include "btCollisionWorld.h"
|
||||
|
||||
///work-in-progress, not complete
|
||||
class btConvexShape;
|
||||
|
||||
class btDispatcher;
|
||||
|
||||
///The btGhostObject can keep track of all objects that are overlapping
|
||||
///By default, this overlap is based on the AABB
|
||||
@@ -32,20 +35,7 @@ ATTRIBUTE_ALIGNED16(class) btGhostObject : public btCollisionObject
|
||||
{
|
||||
protected:
|
||||
|
||||
btOverlappingPairCache* m_overlappingPairCache;
|
||||
|
||||
struct btGhostOverlapFilterCallback : public btOverlapFilterCallback
|
||||
{
|
||||
bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
|
||||
{
|
||||
bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
|
||||
collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
|
||||
return collides;
|
||||
}
|
||||
};
|
||||
|
||||
btGhostOverlapFilterCallback m_ghostOverlapFilterCallback;
|
||||
|
||||
btAlignedObjectArray<btCollisionObject*> m_overlappingObjects;
|
||||
|
||||
public:
|
||||
|
||||
@@ -53,33 +43,41 @@ public:
|
||||
|
||||
virtual ~btGhostObject();
|
||||
|
||||
void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btScalar allowedCcdPenetration,btCollisionWorld::ConvexResultCallback& resultCallback) const;
|
||||
|
||||
virtual void addOverlappingObject(btCollisionObject* otherObject);
|
||||
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
|
||||
|
||||
virtual void removeOverlappingObject(btCollisionObject* otherObject);
|
||||
virtual void addOverlappingObject(btBroadphaseProxy* otherProxy);
|
||||
|
||||
btOverlappingPairCache* getPairCache()
|
||||
virtual void removeOverlappingObject(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher);
|
||||
|
||||
int getNumOverlappingObjects() const
|
||||
{
|
||||
return m_overlappingPairCache;
|
||||
};
|
||||
|
||||
const btOverlappingPairCache* getPairCache() const
|
||||
{
|
||||
return m_overlappingPairCache;
|
||||
};
|
||||
|
||||
btBroadphasePairArray& getOverlappingPairArray()
|
||||
{
|
||||
return m_overlappingPairCache->getOverlappingPairArray();
|
||||
return m_overlappingObjects.size();
|
||||
}
|
||||
|
||||
btOverlappingPairCache* getOverlappingPairCache()
|
||||
btCollisionObject* getOverlappingObject(int index)
|
||||
{
|
||||
return m_overlappingPairCache;
|
||||
return m_overlappingObjects[index];
|
||||
}
|
||||
|
||||
const btCollisionObject* getOverlappingObject(int index) const
|
||||
{
|
||||
return m_overlappingObjects[index];
|
||||
}
|
||||
|
||||
btAlignedObjectArray<btCollisionObject*>& getOverlappingPairs()
|
||||
{
|
||||
return m_overlappingObjects;
|
||||
}
|
||||
|
||||
const btAlignedObjectArray<btCollisionObject*> getOverlappingPairs() const
|
||||
{
|
||||
return m_overlappingObjects;
|
||||
}
|
||||
|
||||
//
|
||||
// Cast
|
||||
// internal cast
|
||||
//
|
||||
|
||||
static const btGhostObject* upcast(const btCollisionObject* colObj)
|
||||
@@ -95,11 +93,31 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class btPairCachingGhostObject : public btGhostObject
|
||||
{
|
||||
btHashedOverlappingPairCache* m_hashPairCache;
|
||||
|
||||
public:
|
||||
|
||||
btPairCachingGhostObject();
|
||||
|
||||
virtual ~btPairCachingGhostObject();
|
||||
|
||||
virtual void addOverlappingObject(btBroadphaseProxy* otherProxy);
|
||||
|
||||
virtual void removeOverlappingObject(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher);
|
||||
|
||||
btHashedOverlappingPairCache* getOverlappingPairCache()
|
||||
{
|
||||
return m_hashPairCache;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
///btGhostPairCache keeps track of overlapping objects that have AABB overlap with the ghost
|
||||
class btGhostPairCallback : public btOverlappingPairCallback
|
||||
{
|
||||
@@ -121,9 +139,10 @@ public:
|
||||
btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
|
||||
btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
|
||||
if (ghost0)
|
||||
ghost0->addOverlappingObject(colObj1);
|
||||
ghost0->addOverlappingObject(proxy1);
|
||||
if (ghost1)
|
||||
ghost1->addOverlappingObject(colObj0);
|
||||
ghost1->addOverlappingObject(proxy0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
|
||||
@@ -133,9 +152,10 @@ public:
|
||||
btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
|
||||
btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
|
||||
if (ghost0)
|
||||
ghost0->removeOverlappingObject(colObj1);
|
||||
ghost0->removeOverlappingObject(proxy1,dispatcher);
|
||||
if (ghost1)
|
||||
ghost1->removeOverlappingObject(colObj0);
|
||||
ghost1->removeOverlappingObject(proxy0,dispatcher);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher)
|
||||
|
||||
@@ -19,7 +19,7 @@ subject to the following restrictions:
|
||||
#include "BulletCollision/CollisionDispatch/btUnionFind.h"
|
||||
#include "btCollisionCreateFunc.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
|
||||
#include "btCollisionObject.h"
|
||||
|
||||
class btCollisionObject;
|
||||
class btCollisionWorld;
|
||||
|
||||
Reference in New Issue
Block a user