WIP example for real-time collision detection features of Bullet

This commit is contained in:
erwin coumans
2015-10-18 14:01:25 -07:00
parent abb7e22027
commit 7ac497d6f2
15 changed files with 355 additions and 92 deletions

View File

@@ -29,9 +29,10 @@ Bullet2CollisionSdk::~Bullet2CollisionSdk()
m_internalData = 0;
}
plCollisionWorldHandle Bullet2CollisionSdk::createCollisionWorld()
plCollisionWorldHandle Bullet2CollisionSdk::createCollisionWorld(int /*maxNumObjsCapacity*/, int /*maxNumShapesCapacity*/, int /*maxNumPairsCapacity*/)
{
m_internalData->m_collisionConfig = new btDefaultCollisionConfiguration;
m_internalData->m_dispatcher = new btCollisionDispatcher(m_internalData->m_collisionConfig);
m_internalData->m_aabbBroadphase = new btDbvtBroadphase();
m_internalData->m_collisionWorld = new btCollisionWorld(m_internalData->m_dispatcher,
@@ -58,13 +59,13 @@ void Bullet2CollisionSdk::deleteCollisionWorld(plCollisionWorldHandle worldHandl
}
}
plCollisionShapeHandle Bullet2CollisionSdk::createSphereShape(plReal radius)
plCollisionShapeHandle Bullet2CollisionSdk::createSphereShape(plCollisionWorldHandle /*worldHandle*/, plReal radius)
{
btSphereShape* sphereShape = new btSphereShape(radius);
return (plCollisionShapeHandle) sphereShape;
}
void Bullet2CollisionSdk::deleteShape(plCollisionShapeHandle shapeHandle)
void Bullet2CollisionSdk::deleteShape(plCollisionWorldHandle /*worldHandle*/, plCollisionShapeHandle shapeHandle)
{
btCollisionShape* shape = (btCollisionShape*) shapeHandle;
delete shape;
@@ -91,7 +92,7 @@ void Bullet2CollisionSdk::removeCollisionObject(plCollisionWorldHandle worldHand
}
}
plCollisionObjectHandle Bullet2CollisionSdk::createCollisionObject( void* user_data, plCollisionShapeHandle shapeHandle ,
plCollisionObjectHandle Bullet2CollisionSdk::createCollisionObject( void* userPointer, int userIndex, plCollisionShapeHandle shapeHandle ,
plVector3 startPosition,plQuaternion startOrientation )
{
@@ -100,6 +101,8 @@ plCollisionObjectHandle Bullet2CollisionSdk::createCollisionObject( void* user_
if (colShape)
{
btCollisionObject* colObj= new btCollisionObject;
colObj->setUserIndex(userIndex);
colObj->setUserPointer(userPointer);
colObj->setCollisionShape(colShape);
btTransform tr;
tr.setOrigin(btVector3(startPosition[0],startPosition[1],startPosition[2]));
@@ -115,6 +118,16 @@ void Bullet2CollisionSdk::deleteCollisionObject(plCollisionObjectHandle bodyHand
btCollisionObject* colObj = (btCollisionObject*) bodyHandle;
delete colObj;
}
void Bullet2CollisionSdk::setCollisionObjectTransform(plCollisionObjectHandle bodyHandle,
plVector3 position,plQuaternion orientation )
{
btCollisionObject* colObj = (btCollisionObject*) bodyHandle;
btTransform tr;
tr.setOrigin(btVector3(position[0],position[1],position[2]));
tr.setRotation(btQuaternion(orientation[0],orientation[1],orientation[2],orientation[3]));
colObj->setWorldTransform(tr);
}
struct Bullet2ContactResultCallback : public btCollisionWorld::ContactResultCallback
{
@@ -122,7 +135,10 @@ struct Bullet2ContactResultCallback : public btCollisionWorld::ContactResultCa
lwContactPoint* m_pointsOut;
int m_pointCapacity;
Bullet2ContactResultCallback() :m_numContacts(0)
Bullet2ContactResultCallback(lwContactPoint* pointsOut, int pointCapacity) :
m_numContacts(0),
m_pointsOut(pointsOut),
m_pointCapacity(pointCapacity)
{
}
virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1)
@@ -134,6 +150,12 @@ struct Bullet2ContactResultCallback : public btCollisionWorld::ContactResultCa
ptOut.m_normalOnB[0] = cp.m_normalWorldOnB.getX();
ptOut.m_normalOnB[1] = cp.m_normalWorldOnB.getY();
ptOut.m_normalOnB[2] = cp.m_normalWorldOnB.getZ();
ptOut.m_ptOnAWorld[0] = cp.m_positionWorldOnA[0];
ptOut.m_ptOnAWorld[1] = cp.m_positionWorldOnA[1];
ptOut.m_ptOnAWorld[2] = cp.m_positionWorldOnA[2];
ptOut.m_ptOnBWorld[0] = cp.m_positionWorldOnB[0];
ptOut.m_ptOnBWorld[1] = cp.m_positionWorldOnB[1];
ptOut.m_ptOnBWorld[2] = cp.m_positionWorldOnB[2];
m_numContacts++;
}
@@ -150,7 +172,7 @@ int Bullet2CollisionSdk::collide(plCollisionWorldHandle worldHandle,plCollisionO
btAssert(world && colObjA && colObjB);
if (world == m_internalData->m_collisionWorld && colObjA && colObjB)
{
Bullet2ContactResultCallback cb;
Bullet2ContactResultCallback cb(pointsOut,pointCapacity);
world->contactPairTest(colObjA,colObjB,cb);
return cb.m_numContacts;
}
@@ -158,13 +180,22 @@ int Bullet2CollisionSdk::collide(plCollisionWorldHandle worldHandle,plCollisionO
}
static plNearCallback gTmpFilter;
static int gContactCount = 0;
static int gNearCallbackCount = 0;
static plCollisionSdkHandle gCollisionSdk = 0;
static plCollisionWorldHandle gCollisionWorldHandle = 0;
static void* gUserData = 0;
void Bullet2NearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
{
if (gTmpFilter)
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
plCollisionObjectHandle obA =(plCollisionObjectHandle) colObj0;
plCollisionObjectHandle obB =(plCollisionObjectHandle) colObj1;
if(gTmpFilter)
{
gContactCount++;
gTmpFilter(gCollisionSdk,gCollisionWorldHandle, gUserData,obA,obB);
gNearCallbackCount++;
}
}
@@ -174,8 +205,10 @@ void Bullet2CollisionSdk::collideWorld( plCollisionWorldHandle worldHandle,
btCollisionWorld* world = (btCollisionWorld*) worldHandle;
//chain the near-callback
gTmpFilter = filter;
gContactCount = 0;
gNearCallbackCount = 0;
gUserData = userData;
gCollisionSdk = (plCollisionSdkHandle)this;
gCollisionWorldHandle = worldHandle;
m_internalData->m_dispatcher->setNearCallback(Bullet2NearCallback);
world->performDiscreteCollisionDetection();
gTmpFilter = 0;

View File

@@ -13,20 +13,22 @@ public:
virtual ~Bullet2CollisionSdk();
virtual plCollisionWorldHandle createCollisionWorld();
virtual plCollisionWorldHandle createCollisionWorld(int maxNumObjsCapacity, int maxNumShapesCapacity, int maxNumPairsCapacity);
virtual void deleteCollisionWorld(plCollisionWorldHandle worldHandle);
virtual plCollisionShapeHandle createSphereShape(plReal radius);
virtual plCollisionShapeHandle createSphereShape(plCollisionWorldHandle worldHandle, plReal radius);
virtual void deleteShape(plCollisionShapeHandle shape);
virtual void deleteShape(plCollisionWorldHandle worldHandle, plCollisionShapeHandle shape);
virtual void addCollisionObject(plCollisionWorldHandle world, plCollisionObjectHandle object);
virtual void removeCollisionObject(plCollisionWorldHandle world, plCollisionObjectHandle object);
virtual plCollisionObjectHandle createCollisionObject( void* user_data, plCollisionShapeHandle cshape ,
virtual plCollisionObjectHandle createCollisionObject( void* userPointer, int userIndex, plCollisionShapeHandle cshape ,
plVector3 startPosition,plQuaternion startOrientation );
virtual void deleteCollisionObject(plCollisionObjectHandle body);
virtual void setCollisionObjectTransform(plCollisionObjectHandle body,
plVector3 position,plQuaternion orientation );
virtual int collide(plCollisionWorldHandle world,plCollisionObjectHandle colA, plCollisionObjectHandle colB,
lwContactPoint* pointsOut, int pointCapacity);

View File

@@ -11,20 +11,22 @@ public:
{
}
virtual plCollisionWorldHandle createCollisionWorld() = 0;
virtual plCollisionWorldHandle createCollisionWorld(int maxNumObjsCapacity, int maxNumShapesCapacity, int maxNumPairsCapacity) = 0;
virtual void deleteCollisionWorld(plCollisionWorldHandle worldHandle) = 0;
virtual plCollisionShapeHandle createSphereShape(plReal radius) = 0;
virtual plCollisionShapeHandle createSphereShape(plCollisionWorldHandle worldHandle, plReal radius) = 0;
virtual void deleteShape(plCollisionShapeHandle shape) = 0;
virtual void deleteShape(plCollisionWorldHandle worldHandle, plCollisionShapeHandle shape) = 0;
virtual void addCollisionObject(plCollisionWorldHandle world, plCollisionObjectHandle object)=0;
virtual void removeCollisionObject(plCollisionWorldHandle world, plCollisionObjectHandle object)=0;
virtual plCollisionObjectHandle createCollisionObject( void* user_data, plCollisionShapeHandle cshape ,
virtual plCollisionObjectHandle createCollisionObject( void* userPointer, int userIndex, plCollisionShapeHandle cshape ,
plVector3 startPosition,plQuaternion startOrientation )=0;
virtual void deleteCollisionObject(plCollisionObjectHandle body)=0;
virtual void setCollisionObjectTransform(plCollisionObjectHandle body,
plVector3 position,plQuaternion orientation )=0;
virtual int collide(plCollisionWorldHandle world,plCollisionObjectHandle colA, plCollisionObjectHandle colB,
lwContactPoint* pointsOut, int pointCapacity)=0;

View File

@@ -0,0 +1,112 @@
#include "RealTimeBullet3CollisionSdk.h"
#include "Bullet3Common/b3AlignedObjectArray.h"
#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
struct RTB3CollisionWorld
{
b3AlignedObjectArray<b3Collidable> m_collidables;
b3AlignedObjectArray<b3GpuChildShape> m_childShapes;
b3AlignedObjectArray<b3CompoundOverlappingPair> m_compoundOverlappingPairs;
int m_nextFreeShapeIndex;
int m_nextFreeCollidableIndex;
RTB3CollisionWorld()
:m_nextFreeCollidableIndex(0),
m_nextFreeShapeIndex(0)
{
}
};
struct RealTimeBullet3CollisionSdkInternalData
{
b3AlignedObjectArray<RTB3CollisionWorld*> m_collisionWorlds;
};
RealTimeBullet3CollisionSdk::RealTimeBullet3CollisionSdk()
{
int szCol = sizeof(b3Collidable);
int szShap = sizeof(b3GpuChildShape);
int szComPair = sizeof(b3CompoundOverlappingPair);
m_internalData = new RealTimeBullet3CollisionSdkInternalData;
}
RealTimeBullet3CollisionSdk::~RealTimeBullet3CollisionSdk()
{
delete m_internalData;
m_internalData=0;
}
plCollisionWorldHandle RealTimeBullet3CollisionSdk::createCollisionWorld(int maxNumObjsCapacity, int maxNumShapesCapacity, int maxNumPairsCapacity)
{
RTB3CollisionWorld* world = new RTB3CollisionWorld();
world->m_collidables.resize(maxNumObjsCapacity);
world->m_childShapes.resize(maxNumShapesCapacity);
world->m_compoundOverlappingPairs.resize(maxNumPairsCapacity);
m_internalData->m_collisionWorlds.push_back(world);
return (plCollisionWorldHandle) world;
}
void RealTimeBullet3CollisionSdk::deleteCollisionWorld(plCollisionWorldHandle worldHandle)
{
RTB3CollisionWorld* world = (RTB3CollisionWorld*) worldHandle;
int loc = m_internalData->m_collisionWorlds.findLinearSearch(world);
b3Assert(loc >=0 && loc<m_internalData->m_collisionWorlds.size());
if (loc >=0 && loc<m_internalData->m_collisionWorlds.size())
{
m_internalData->m_collisionWorlds.remove(world);
delete world;
}
}
plCollisionShapeHandle RealTimeBullet3CollisionSdk::createSphereShape(plCollisionWorldHandle worldHandle, plReal radius)
{
int index = 10;
return (plCollisionShapeHandle) index;
}
void RealTimeBullet3CollisionSdk::deleteShape(plCollisionWorldHandle worldHandle, plCollisionShapeHandle shape)
{
//deleting shapes would involve a garbage collection phase, and mess up all user indices
//this would be solved by one more in-direction, at some performance penalty for certain operations
//for now, we don't delete and eventually run out-of-shapes
}
void RealTimeBullet3CollisionSdk::addCollisionObject(plCollisionWorldHandle world, plCollisionObjectHandle object)
{
}
void RealTimeBullet3CollisionSdk::removeCollisionObject(plCollisionWorldHandle world, plCollisionObjectHandle object)
{
}
plCollisionObjectHandle RealTimeBullet3CollisionSdk::createCollisionObject( void* userPointer, int userIndex, plCollisionShapeHandle cshape ,
plVector3 startPosition,plQuaternion startOrientation )
{
return 0;
}
void RealTimeBullet3CollisionSdk::deleteCollisionObject(plCollisionObjectHandle body)
{
}
void RealTimeBullet3CollisionSdk::setCollisionObjectTransform(plCollisionObjectHandle body,
plVector3 position,plQuaternion orientation )
{
}
int RealTimeBullet3CollisionSdk::collide(plCollisionWorldHandle world,plCollisionObjectHandle colA, plCollisionObjectHandle colB,
lwContactPoint* pointsOut, int pointCapacity)
{
return 0;
}
void RealTimeBullet3CollisionSdk::collideWorld( plCollisionWorldHandle world,
plNearCallback filter, void* userData)
{
}
plCollisionSdkHandle RealTimeBullet3CollisionSdk::createRealTimeBullet3CollisionSdkHandle()
{
return (plCollisionSdkHandle) new RealTimeBullet3CollisionSdk();
}

View File

@@ -0,0 +1,42 @@
#ifndef REAL_TIME_COLLISION_SDK_H
#define REAL_TIME_COLLISION_SDK_H
#include "CollisionSdkInterface.h"
class RealTimeBullet3CollisionSdk : public CollisionSdkInterface
{
struct RealTimeBullet3CollisionSdkInternalData* m_internalData;
public:
RealTimeBullet3CollisionSdk();
virtual ~RealTimeBullet3CollisionSdk();
virtual plCollisionWorldHandle createCollisionWorld(int maxNumObjsCapacity, int maxNumShapesCapacity, int maxNumPairsCapacity);
virtual void deleteCollisionWorld(plCollisionWorldHandle worldHandle);
virtual plCollisionShapeHandle createSphereShape(plCollisionWorldHandle worldHandle, plReal radius);
virtual void deleteShape(plCollisionWorldHandle worldHandle, plCollisionShapeHandle shape);
virtual void addCollisionObject(plCollisionWorldHandle world, plCollisionObjectHandle object);
virtual void removeCollisionObject(plCollisionWorldHandle world, plCollisionObjectHandle object);
virtual plCollisionObjectHandle createCollisionObject( void* userPointer, int userIndex, plCollisionShapeHandle cshape ,
plVector3 startPosition,plQuaternion startOrientation );
virtual void deleteCollisionObject(plCollisionObjectHandle body);
virtual void setCollisionObjectTransform(plCollisionObjectHandle body,
plVector3 position,plQuaternion orientation );
virtual int collide(plCollisionWorldHandle world,plCollisionObjectHandle colA, plCollisionObjectHandle colB,
lwContactPoint* pointsOut, int pointCapacity);
virtual void collideWorld( plCollisionWorldHandle world,
plNearCallback filter, void* userData);
static plCollisionSdkHandle createRealTimeBullet3CollisionSdkHandle();
};
#endif //REAL_TIME_COLLISION_SDK_H