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:
erwin.coumans
2008-10-18 01:33:23 +00:00
parent 7f52613c45
commit 4cbb3f2e7b
14 changed files with 488 additions and 569 deletions

View File

@@ -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;

View File

@@ -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.

View File

@@ -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"

View File

@@ -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);
}
}
}

View File

@@ -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)

View File

@@ -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;