add option for btDbvtBroadphase (comparison)
This commit is contained in:
@@ -113,6 +113,6 @@
|
||||
include "../src/Bullet3Common"
|
||||
include "../src/Bullet3Geometry"
|
||||
include "../src/Bullet3Collision"
|
||||
|
||||
include "../test/b3DynamicBvhBroadphase"
|
||||
|
||||
end
|
||||
|
||||
@@ -38,9 +38,9 @@ public:
|
||||
:useOpenCL(true),
|
||||
preferredOpenCLPlatformIndex(-1),
|
||||
preferredOpenCLDeviceIndex(-1),
|
||||
arraySizeX(10),
|
||||
arraySizeY(30),
|
||||
arraySizeZ(10),
|
||||
arraySizeX(30),
|
||||
arraySizeY(20),
|
||||
arraySizeZ(30),
|
||||
m_useConcaveMesh(false),
|
||||
gapX(14.3),
|
||||
gapY(14.0),
|
||||
|
||||
@@ -66,12 +66,13 @@ int selectedDemo = 0;
|
||||
GpuDemo::CreateFunc* allDemos[]=
|
||||
{
|
||||
// ConcaveCompound2Scene::MyCreateFunc,
|
||||
ConcaveSphereScene::MyCreateFunc,
|
||||
|
||||
|
||||
|
||||
GpuBoxPlaneScene::MyCreateFunc,
|
||||
GpuConvexPlaneScene::MyCreateFunc,
|
||||
|
||||
ConcaveSphereScene::MyCreateFunc,
|
||||
|
||||
GpuCompoundScene::MyCreateFunc,
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ function createProject(vendor)
|
||||
"gwen",
|
||||
"Bullet3Common",
|
||||
"Bullet3Geometry",
|
||||
"Bullet3Collision",
|
||||
"Bullet3Dynamics"
|
||||
}
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ void ConcaveScene::createConcaveMesh(const ConstructionInfo& ci, const char* fil
|
||||
float mass = 0.f;
|
||||
b3Vector3 position(0,0,0);
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index,false);
|
||||
index++;
|
||||
}
|
||||
|
||||
@@ -286,13 +286,15 @@ void ConcaveScene::setupScene(const ConstructionInfo& ci)
|
||||
btVector4 color(0,0,1,1);
|
||||
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f,position,orn,colIndex,index,false);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
createDynamicObjects(ci);
|
||||
|
||||
m_data->m_rigidBodyPipeline->writeAllInstancesToGpu();
|
||||
|
||||
float camPos[4]={0,0,0,0};//65.5,4.5,65.5,0};
|
||||
//float camPos[4]={1,12.5,1.5,0};
|
||||
m_instancingRenderer->setCameraPitch(45);
|
||||
@@ -345,7 +347,7 @@ void ConcaveScene::createDynamicObjects(const ConstructionInfo& ci)
|
||||
curColor&=3;
|
||||
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index,false);
|
||||
|
||||
index++;
|
||||
}
|
||||
@@ -572,7 +574,7 @@ void ConcaveCompound2Scene::createDynamicObjects(const ConstructionInfo& ci)
|
||||
curColor&=3;
|
||||
btVector4 scaling(1,1,1,1);
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index,false);
|
||||
|
||||
index++;
|
||||
}
|
||||
@@ -687,7 +689,7 @@ b3Vector3 childPositions[3] = {
|
||||
curColor&=3;
|
||||
btVector4 scaling(1,1,1,1);
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index,false);
|
||||
|
||||
index++;
|
||||
}
|
||||
@@ -746,7 +748,7 @@ void ConcaveSphereScene::createDynamicObjects(const ConstructionInfo& ci)
|
||||
curColor&=3;
|
||||
btVector4 scaling(radius,radius,radius,1);
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(prevGraphicsShapeIndex,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index,false);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
@@ -122,13 +122,16 @@ void GpuCompoundScene::setupScene(const ConstructionInfo& ci)
|
||||
curColor&=3;
|
||||
btVector4 scaling(1,1,1,1);
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index,false);
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_data->m_rigidBodyPipeline->writeAllInstancesToGpu();
|
||||
|
||||
|
||||
float camPos[4]={0,0,0};//65.5,4.5,65.5,0};
|
||||
//float camPos[4]={1,12.5,1.5,0};
|
||||
m_instancingRenderer->setCameraTargetPosition(camPos);
|
||||
@@ -219,7 +222,7 @@ void GpuCompoundScene::createStaticEnvironment(const ConstructionInfo& ci)
|
||||
curColor&=3;
|
||||
btVector4 scaling(radius,radius,radius,1);
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(prevGraphicsShapeIndex,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index,false);
|
||||
|
||||
index++;
|
||||
|
||||
@@ -247,5 +250,5 @@ void GpuCompoundPlaneScene::createStaticEnvironment(const ConstructionInfo& ci)
|
||||
|
||||
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f,position,orn,colIndex,index,false);
|
||||
}
|
||||
@@ -27,6 +27,8 @@ void GpuConvexScene::setupScene(const ConstructionInfo& ci)
|
||||
|
||||
index+=createDynamicsObjects(ci);
|
||||
|
||||
m_data->m_rigidBodyPipeline->writeAllInstancesToGpu();
|
||||
|
||||
|
||||
float camPos[4]={ci.arraySizeX,ci.arraySizeY/2,ci.arraySizeZ,0};
|
||||
//float camPos[4]={1,12.5,1.5,0};
|
||||
@@ -101,7 +103,7 @@ int GpuConvexScene::createDynamicsObjects2(const ConstructionInfo& ci, const flo
|
||||
curColor&=3;
|
||||
btVector4 scaling(1,1,1,1);
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index,false);
|
||||
|
||||
index++;
|
||||
}
|
||||
@@ -132,7 +134,7 @@ void GpuConvexScene::createStaticEnvironment(const ConstructionInfo& ci)
|
||||
btVector4 color(0,0,1,1);
|
||||
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f,position,orn,colIndex,index,false);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -155,6 +157,6 @@ void GpuConvexPlaneScene::createStaticEnvironment(const ConstructionInfo& ci)
|
||||
|
||||
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f,position,orn,colIndex,index,false);
|
||||
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "gpu_rigidbody/host/b3GpuNarrowPhase.h"
|
||||
#include "gpu_rigidbody/host/b3Config.h"
|
||||
#include "GpuRigidBodyDemoInternalData.h"
|
||||
#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h"
|
||||
|
||||
static btKeyboardCallback oldCallback = 0;
|
||||
extern bool gReset;
|
||||
@@ -111,8 +112,9 @@ void GpuRigidBodyDemo::initPhysics(const ConstructionInfo& ci)
|
||||
b3GpuSapBroadphase* bp = new b3GpuSapBroadphase(m_clData->m_clContext,m_clData->m_clDevice,m_clData->m_clQueue);
|
||||
m_data->m_np = np;
|
||||
m_data->m_bp = bp;
|
||||
b3DynamicBvhBroadphase* broadphaseDbvt = new b3DynamicBvhBroadphase(config.m_maxConvexBodies);
|
||||
|
||||
m_data->m_rigidBodyPipeline = new b3GpuRigidBodyPipeline(m_clData->m_clContext,m_clData->m_clDevice,m_clData->m_clQueue, np, bp);
|
||||
m_data->m_rigidBodyPipeline = new b3GpuRigidBodyPipeline(m_clData->m_clContext,m_clData->m_clDevice,m_clData->m_clQueue, np, bp,broadphaseDbvt);
|
||||
|
||||
|
||||
setupScene(ci);
|
||||
|
||||
@@ -31,7 +31,7 @@ void GpuSphereScene::setupScene(const ConstructionInfo& ci)
|
||||
int group=1;
|
||||
int mask=1;
|
||||
int index=0;
|
||||
|
||||
bool writeInstanceToGpu = false;
|
||||
|
||||
if (0)
|
||||
{
|
||||
@@ -95,7 +95,7 @@ void GpuSphereScene::setupScene(const ConstructionInfo& ci)
|
||||
curColor&=3;
|
||||
btVector4 scaling(radius,radius,radius,1);
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(prevGraphicsShapeIndex,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index, writeInstanceToGpu);
|
||||
|
||||
index++;
|
||||
|
||||
@@ -152,7 +152,7 @@ void GpuSphereScene::setupScene(const ConstructionInfo& ci)
|
||||
curColor&=3;
|
||||
btVector4 scaling(radius,radius,radius,1);
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(prevGraphicsShapeIndex,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(mass,position,orn,colIndex,index, writeInstanceToGpu);
|
||||
|
||||
index++;
|
||||
}
|
||||
@@ -182,12 +182,17 @@ void GpuSphereScene::setupScene(const ConstructionInfo& ci)
|
||||
btVector4 color(0,0,1,1);
|
||||
|
||||
int id = ci.m_instancingRenderer->registerGraphicsInstance(shapeId,position,orn,color,scaling);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(1.f,position,orn,colIndex,index);
|
||||
int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(1.f,position,orn,colIndex,index,false);
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!writeInstanceToGpu)
|
||||
{
|
||||
m_data->m_rigidBodyPipeline->writeAllInstancesToGpu();
|
||||
}
|
||||
|
||||
float camPos[4]={ci.arraySizeX,ci.arraySizeY/2,ci.arraySizeZ,0};
|
||||
//float camPos[4]={1,12.5,1.5,0};
|
||||
m_instancingRenderer->setCameraTargetPosition(camPos);
|
||||
|
||||
@@ -882,6 +882,11 @@ int b3GpuNarrowPhase::registerRigidBody(int collidableIndex, float mass, const f
|
||||
return m_data->m_numAcceleratedRigidBodies++;
|
||||
}
|
||||
|
||||
int b3GpuNarrowPhase::getNumRigidBodies() const
|
||||
{
|
||||
return m_data->m_numAcceleratedRigidBodies;
|
||||
}
|
||||
|
||||
void b3GpuNarrowPhase::writeAllBodiesToGpu()
|
||||
{
|
||||
m_data->m_bodyBufferGPU->resize(m_data->m_numAcceleratedRigidBodies);
|
||||
|
||||
@@ -72,6 +72,7 @@ public:
|
||||
|
||||
cl_mem getAabbBufferGpu();
|
||||
|
||||
int getNumRigidBodies() const;
|
||||
|
||||
int allocateCollidable();
|
||||
|
||||
|
||||
@@ -11,12 +11,16 @@
|
||||
#include "parallel_primitives/host/btLauncherCL.h"
|
||||
#include "Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h"
|
||||
|
||||
#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h"
|
||||
|
||||
//#define TEST_OTHER_GPU_SOLVER
|
||||
|
||||
bool useDbvt = true;
|
||||
bool useBullet2CpuSolver = false;
|
||||
bool dumpContactStats = false;
|
||||
|
||||
#ifdef TEST_OTHER_GPU_SOLVER
|
||||
#include "btGpuJacobiSolver.h"
|
||||
#include "b3PgsJacobiSolver.h"
|
||||
#endif //TEST_OTHER_GPU_SOLVER
|
||||
|
||||
#include "Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h"
|
||||
@@ -27,9 +31,9 @@
|
||||
#include "Bullet3Common/b3Quickprof.h"
|
||||
#include "b3Config.h"
|
||||
|
||||
bool dumpContactStats = false;
|
||||
|
||||
b3GpuRigidBodyPipeline::b3GpuRigidBodyPipeline(cl_context ctx,cl_device_id device, cl_command_queue q,class b3GpuNarrowPhase* narrowphase, class b3GpuSapBroadphase* broadphaseSap )
|
||||
|
||||
b3GpuRigidBodyPipeline::b3GpuRigidBodyPipeline(cl_context ctx,cl_device_id device, cl_command_queue q,class b3GpuNarrowPhase* narrowphase, class b3GpuSapBroadphase* broadphaseSap , class b3DynamicBvhBroadphase* broadphaseDbvt)
|
||||
{
|
||||
m_data = new b3GpuRigidBodyPipelineInternalData;
|
||||
m_data->m_context = ctx;
|
||||
@@ -37,16 +41,18 @@ b3GpuRigidBodyPipeline::b3GpuRigidBodyPipeline(cl_context ctx,cl_device_id devic
|
||||
m_data->m_queue = q;
|
||||
|
||||
m_data->m_solver = new b3PgsJacobiSolver();
|
||||
b3Config config;
|
||||
m_data->m_allAabbsGPU = new btOpenCLArray<b3SapAabb>(ctx,q,config.m_maxConvexBodies);
|
||||
m_data->m_overlappingPairsGPU = new btOpenCLArray<btBroadphasePair>(ctx,q,config.m_maxBroadphasePairs);
|
||||
|
||||
|
||||
#ifdef TEST_OTHER_GPU_SOLVER
|
||||
m_data->m_solver3 = new btGpuJacobiSolver(ctx,device,q,config.m_maxBroadphasePairs);
|
||||
#endif // TEST_OTHER_GPU_SOLVER
|
||||
b3Config config;
|
||||
|
||||
m_data->m_solver2 = new b3GpuBatchingPgsSolver(ctx,device,q,config.m_maxBroadphasePairs);
|
||||
|
||||
|
||||
|
||||
m_data->m_broadphaseDbvt = broadphaseDbvt;
|
||||
m_data->m_broadphaseSap = broadphaseSap;
|
||||
m_data->m_narrowphase = narrowphase;
|
||||
|
||||
@@ -75,6 +81,8 @@ b3GpuRigidBodyPipeline::~b3GpuRigidBodyPipeline()
|
||||
clReleaseKernel(m_data->m_integrateTransformsKernel);
|
||||
|
||||
delete m_data->m_solver;
|
||||
delete m_data->m_allAabbsGPU;
|
||||
delete m_data->m_overlappingPairsGPU;
|
||||
|
||||
#ifdef TEST_OTHER_GPU_SOLVER
|
||||
delete m_data->m_solver3;
|
||||
@@ -94,15 +102,40 @@ void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
|
||||
setupGpuAabbsFull();
|
||||
}
|
||||
|
||||
int numPairs =0;
|
||||
|
||||
//compute overlapping pairs
|
||||
{
|
||||
//m_data->m_broadphaseSap->calculateOverlappingPairsHost();
|
||||
m_data->m_broadphaseSap->calculateOverlappingPairs();
|
||||
|
||||
if (useDbvt)
|
||||
{
|
||||
{
|
||||
BT_PROFILE("setAabb");
|
||||
m_data->m_allAabbsGPU->copyToHost(m_data->m_allAabbsCPU);
|
||||
for (int i=0;i<m_data->m_allAabbsCPU.size();i++)
|
||||
{
|
||||
btBroadphaseProxy* proxy = &m_data->m_broadphaseDbvt->m_proxies[i];
|
||||
b3Vector3 aabbMin(m_data->m_allAabbsCPU[i].m_min[0],m_data->m_allAabbsCPU[i].m_min[1],m_data->m_allAabbsCPU[i].m_min[2]);
|
||||
b3Vector3 aabbMax(m_data->m_allAabbsCPU[i].m_max[0],m_data->m_allAabbsCPU[i].m_max[1],m_data->m_allAabbsCPU[i].m_max[2]);
|
||||
m_data->m_broadphaseDbvt->setAabb(proxy,aabbMin,aabbMax,0);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
BT_PROFILE("calculateOverlappingPairs");
|
||||
m_data->m_broadphaseDbvt->calculateOverlappingPairs();
|
||||
}
|
||||
numPairs = m_data->m_broadphaseDbvt->getOverlappingPairCache()->getNumOverlappingPairs();
|
||||
} else
|
||||
{
|
||||
m_data->m_broadphaseSap->calculateOverlappingPairs();
|
||||
numPairs = m_data->m_broadphaseSap->getNumOverlap();
|
||||
}
|
||||
}
|
||||
|
||||
//compute contact points
|
||||
|
||||
int numPairs = m_data->m_broadphaseSap->getNumOverlap();
|
||||
|
||||
int numContacts = 0;
|
||||
|
||||
|
||||
@@ -110,8 +143,19 @@ void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
|
||||
|
||||
if (numPairs)
|
||||
{
|
||||
cl_mem pairs = m_data->m_broadphaseSap->getOverlappingPairBuffer();
|
||||
cl_mem aabbsWS = m_data->m_broadphaseSap->getAabbBufferWS();
|
||||
cl_mem pairs =0;
|
||||
cl_mem aabbsWS =0;
|
||||
if (useDbvt)
|
||||
{
|
||||
BT_PROFILE("m_overlappingPairsGPU->copyFromHost");
|
||||
m_data->m_overlappingPairsGPU->copyFromHost(m_data->m_broadphaseDbvt->getOverlappingPairCache()->getOverlappingPairArray());
|
||||
pairs = m_data->m_overlappingPairsGPU->getBufferCL();
|
||||
aabbsWS = m_data->m_allAabbsGPU->getBufferCL();
|
||||
} else
|
||||
{
|
||||
pairs = m_data->m_broadphaseSap->getOverlappingPairBuffer();
|
||||
aabbsWS = m_data->m_broadphaseSap->getAabbBufferWS();
|
||||
}
|
||||
|
||||
|
||||
m_data->m_narrowphase->computeContacts(pairs,numPairs,aabbsWS,numBodies);
|
||||
@@ -149,7 +193,7 @@ void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
|
||||
btOpenCLArray<b3Contact4> gpuContacts(m_data->m_context,m_data->m_queue,0,true);
|
||||
gpuContacts.setFromOpenCLBuffer(m_data->m_narrowphase->getContactsGpu(),m_data->m_narrowphase->getNumContactsGpu());
|
||||
|
||||
bool useBullet2CpuSolver = false;
|
||||
|
||||
if (useBullet2CpuSolver)
|
||||
{
|
||||
b3AlignedObjectArray<b3RigidBodyCL> hostBodies;
|
||||
@@ -271,7 +315,15 @@ void b3GpuRigidBodyPipeline::setupGpuAabbsFull()
|
||||
launcher.setBuffer(collidables);
|
||||
cl_mem localAabbs = m_data->m_narrowphase->getAabbBufferGpu();
|
||||
launcher.setBuffer(localAabbs);
|
||||
cl_mem worldAabbs = m_data->m_broadphaseSap->getAabbBufferWS();
|
||||
|
||||
cl_mem worldAabbs =0;
|
||||
if (useDbvt)
|
||||
{
|
||||
worldAabbs = m_data->m_allAabbsGPU->getBufferCL();
|
||||
} else
|
||||
{
|
||||
worldAabbs = m_data->m_broadphaseSap->getAabbBufferWS();
|
||||
}
|
||||
launcher.setBuffer(worldAabbs);
|
||||
launcher.launch1D(numBodies);
|
||||
oclCHECKERROR(ciErrNum, CL_SUCCESS);
|
||||
@@ -290,12 +342,19 @@ int b3GpuRigidBodyPipeline::getNumBodies() const
|
||||
}
|
||||
|
||||
|
||||
void b3GpuRigidBodyPipeline::writeAllInstancesToGpu()
|
||||
{
|
||||
m_data->m_allAabbsGPU->copyFromHost(m_data->m_allAabbsCPU);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int b3GpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collidableIndex, int userIndex)
|
||||
int b3GpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collidableIndex, int userIndex, bool writeInstanceToGpu)
|
||||
{
|
||||
b3Vector3 aabbMin(0,0,0),aabbMax(0,0,0);
|
||||
|
||||
int bodyIndex = m_data->m_narrowphase->getNumRigidBodies();
|
||||
|
||||
|
||||
if (collidableIndex>=0)
|
||||
{
|
||||
b3SapAabb localAabb = m_data->m_narrowphase->getLocalSpaceAabb(collidableIndex);
|
||||
@@ -308,21 +367,39 @@ int b3GpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* po
|
||||
t.setOrigin(b3Vector3(position[0],position[1],position[2]));
|
||||
t.setRotation(b3Quaternion(orientation[0],orientation[1],orientation[2],orientation[3]));
|
||||
btTransformAabb(localAabbMin,localAabbMax, margin,t,aabbMin,aabbMax);
|
||||
if (mass)
|
||||
if (useDbvt)
|
||||
{
|
||||
m_data->m_broadphaseSap->createProxy(aabbMin,aabbMax,userIndex,1,1);//m_dispatcher);
|
||||
m_data->m_broadphaseDbvt->createProxy(aabbMin,aabbMax,bodyIndex,0,1,1);
|
||||
b3SapAabb aabb;
|
||||
for (int i=0;i<3;i++)
|
||||
{
|
||||
aabb.m_min[i] = aabbMin[i];
|
||||
aabb.m_max[i] = aabbMax[i];
|
||||
aabb.m_minIndices[3] = bodyIndex;
|
||||
}
|
||||
m_data->m_allAabbsCPU.push_back(aabb);
|
||||
if (writeInstanceToGpu)
|
||||
{
|
||||
m_data->m_allAabbsGPU->copyFromHost(m_data->m_allAabbsCPU);
|
||||
}
|
||||
} else
|
||||
{
|
||||
m_data->m_broadphaseSap->createLargeProxy(aabbMin,aabbMax,userIndex,1,1);//m_dispatcher);
|
||||
if (mass)
|
||||
{
|
||||
m_data->m_broadphaseSap->createProxy(aabbMin,aabbMax,userIndex,1,1);//m_dispatcher);
|
||||
} else
|
||||
{
|
||||
m_data->m_broadphaseSap->createLargeProxy(aabbMin,aabbMax,userIndex,1,1);//m_dispatcher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool writeToGpu = false;
|
||||
int bodyIndex = -1;
|
||||
|
||||
|
||||
|
||||
bodyIndex = m_data->m_narrowphase->registerRigidBody(collidableIndex,mass,position,orientation,&aabbMin.getX(),&aabbMax.getX(),writeToGpu);
|
||||
|
||||
|
||||
/*
|
||||
if (mass>0.f)
|
||||
m_numDynamicPhysicsInstances++;
|
||||
|
||||
@@ -12,7 +12,8 @@ protected:
|
||||
|
||||
public:
|
||||
|
||||
b3GpuRigidBodyPipeline(cl_context ctx,cl_device_id device, cl_command_queue q , class b3GpuNarrowPhase* narrowphase, class b3GpuSapBroadphase* broadphaseSap);
|
||||
|
||||
b3GpuRigidBodyPipeline(cl_context ctx,cl_device_id device, cl_command_queue q , class b3GpuNarrowPhase* narrowphase, class b3GpuSapBroadphase* broadphaseSap, class b3DynamicBvhBroadphase* broadphaseDbvt);
|
||||
virtual ~b3GpuRigidBodyPipeline();
|
||||
|
||||
void stepSimulation(float deltaTime);
|
||||
@@ -29,7 +30,9 @@ public:
|
||||
//int registerCompoundShape(b3AlignedObjectArray<btGpuChildShape>* childShapes);
|
||||
|
||||
|
||||
int registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, int userData);
|
||||
int registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, int userData, bool writeInstanceToGpu);
|
||||
//if you passed "writeInstanceToGpu" false in the registerPhysicsInstance method (for performance) you need to call writeAllInstancesToGpu after all instances are registered
|
||||
void writeAllInstancesToGpu();
|
||||
|
||||
cl_mem getBodyBuffer();
|
||||
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
#include "../../parallel_primitives/host/btOpenCLArray.h"
|
||||
#include "../../gpu_narrowphase/host/b3Collidable.h"
|
||||
|
||||
#include "gpu_broadphase/host/b3SapAabb.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#include "Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h"
|
||||
|
||||
struct b3GpuRigidBodyPipelineInternalData
|
||||
{
|
||||
@@ -23,6 +29,12 @@ struct b3GpuRigidBodyPipelineInternalData
|
||||
class btGpuJacobiSolver* m_solver3;
|
||||
|
||||
class b3GpuSapBroadphase* m_broadphaseSap;
|
||||
|
||||
class b3DynamicBvhBroadphase* m_broadphaseDbvt;
|
||||
btOpenCLArray<b3SapAabb>* m_allAabbsGPU;
|
||||
b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU;
|
||||
btOpenCLArray<btBroadphasePair>* m_overlappingPairsGPU;
|
||||
|
||||
|
||||
class b3GpuNarrowPhase* m_narrowphase;
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
#ifndef B3_BROADPHASE_CALLBACK_H
|
||||
#define B3_BROADPHASE_CALLBACK_H
|
||||
|
||||
#include "Bullet3Common/b3Vector3.h"
|
||||
struct btBroadphaseProxy;
|
||||
|
||||
|
||||
struct btBroadphaseAabbCallback
|
||||
{
|
||||
virtual ~btBroadphaseAabbCallback() {}
|
||||
virtual bool process(const btBroadphaseProxy* proxy) = 0;
|
||||
};
|
||||
|
||||
|
||||
struct btBroadphaseRayCallback : public btBroadphaseAabbCallback
|
||||
{
|
||||
///added some cached data to accelerate ray-AABB tests
|
||||
b3Vector3 m_rayDirectionInverse;
|
||||
unsigned int m_signs[3];
|
||||
b3Scalar m_lambda_max;
|
||||
|
||||
virtual ~btBroadphaseRayCallback() {}
|
||||
};
|
||||
|
||||
#endif //B3_BROADPHASE_CALLBACK_H
|
||||
1295
src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp
Normal file
1295
src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1270
src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h
Normal file
1270
src/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,794 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
///b3DynamicBvhBroadphase implementation by Nathanael Presson
|
||||
|
||||
#include "b3DynamicBvhBroadphase.h"
|
||||
#include "b3OverlappingPair.h"
|
||||
|
||||
//
|
||||
// Profiling
|
||||
//
|
||||
|
||||
#if DBVT_BP_PROFILE||DBVT_BP_ENABLE_BENCHMARK
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if DBVT_BP_PROFILE
|
||||
struct ProfileScope
|
||||
{
|
||||
__forceinline ProfileScope(btClock& clock,unsigned long& value) :
|
||||
m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds())
|
||||
{
|
||||
}
|
||||
__forceinline ~ProfileScope()
|
||||
{
|
||||
(*m_value)+=m_clock->getTimeMicroseconds()-m_base;
|
||||
}
|
||||
btClock* m_clock;
|
||||
unsigned long* m_value;
|
||||
unsigned long m_base;
|
||||
};
|
||||
#define SPC(_value_) ProfileScope spc_scope(m_clock,_value_)
|
||||
#else
|
||||
#define SPC(_value_)
|
||||
#endif
|
||||
|
||||
//
|
||||
// Helpers
|
||||
//
|
||||
|
||||
//
|
||||
template <typename T>
|
||||
static inline void listappend(T* item,T*& list)
|
||||
{
|
||||
item->links[0]=0;
|
||||
item->links[1]=list;
|
||||
if(list) list->links[0]=item;
|
||||
list=item;
|
||||
}
|
||||
|
||||
//
|
||||
template <typename T>
|
||||
static inline void listremove(T* item,T*& list)
|
||||
{
|
||||
if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1];
|
||||
if(item->links[1]) item->links[1]->links[0]=item->links[0];
|
||||
}
|
||||
|
||||
//
|
||||
template <typename T>
|
||||
static inline int listcount(T* root)
|
||||
{
|
||||
int n=0;
|
||||
while(root) { ++n;root=root->links[1]; }
|
||||
return(n);
|
||||
}
|
||||
|
||||
//
|
||||
template <typename T>
|
||||
static inline void clear(T& value)
|
||||
{
|
||||
static const struct ZeroDummy : T {} zerodummy;
|
||||
value=zerodummy;
|
||||
}
|
||||
|
||||
//
|
||||
// Colliders
|
||||
//
|
||||
|
||||
/* Tree collider */
|
||||
struct btDbvtTreeCollider : b3DynamicBvh::ICollide
|
||||
{
|
||||
b3DynamicBvhBroadphase* pbp;
|
||||
btDbvtProxy* proxy;
|
||||
btDbvtTreeCollider(b3DynamicBvhBroadphase* p) : pbp(p) {}
|
||||
void Process(const btDbvtNode* na,const btDbvtNode* nb)
|
||||
{
|
||||
if(na!=nb)
|
||||
{
|
||||
btDbvtProxy* pa=(btDbvtProxy*)na->data;
|
||||
btDbvtProxy* pb=(btDbvtProxy*)nb->data;
|
||||
#if DBVT_BP_SORTPAIRS
|
||||
if(pa->m_uniqueId>pb->m_uniqueId)
|
||||
btSwap(pa,pb);
|
||||
#endif
|
||||
pbp->m_paircache->addOverlappingPair(pa->getUid(),pb->getUid());
|
||||
++pbp->m_newpairs;
|
||||
}
|
||||
}
|
||||
void Process(const btDbvtNode* n)
|
||||
{
|
||||
Process(n,proxy->leaf);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// b3DynamicBvhBroadphase
|
||||
//
|
||||
|
||||
//
|
||||
b3DynamicBvhBroadphase::b3DynamicBvhBroadphase(int proxyCapacity, b3OverlappingPairCache* paircache)
|
||||
{
|
||||
m_deferedcollide = false;
|
||||
m_needcleanup = true;
|
||||
m_releasepaircache = (paircache!=0)?false:true;
|
||||
m_prediction = 0;
|
||||
m_stageCurrent = 0;
|
||||
m_fixedleft = 0;
|
||||
m_fupdates = 1;
|
||||
m_dupdates = 0;
|
||||
m_cupdates = 10;
|
||||
m_newpairs = 1;
|
||||
m_updates_call = 0;
|
||||
m_updates_done = 0;
|
||||
m_updates_ratio = 0;
|
||||
m_paircache = paircache? paircache : new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
|
||||
|
||||
m_pid = 0;
|
||||
m_cid = 0;
|
||||
for(int i=0;i<=STAGECOUNT;++i)
|
||||
{
|
||||
m_stageRoots[i]=0;
|
||||
}
|
||||
#if DBVT_BP_PROFILE
|
||||
clear(m_profiling);
|
||||
#endif
|
||||
m_proxies.resize(proxyCapacity);
|
||||
}
|
||||
|
||||
//
|
||||
b3DynamicBvhBroadphase::~b3DynamicBvhBroadphase()
|
||||
{
|
||||
if(m_releasepaircache)
|
||||
{
|
||||
m_paircache->~b3OverlappingPairCache();
|
||||
btAlignedFree(m_paircache);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
btBroadphaseProxy* b3DynamicBvhBroadphase::createProxy( const b3Vector3& aabbMin,
|
||||
const b3Vector3& aabbMax,
|
||||
int objectId,
|
||||
void* userPtr,
|
||||
short int collisionFilterGroup,
|
||||
short int collisionFilterMask)
|
||||
{
|
||||
btDbvtProxy* mem = &m_proxies[objectId];
|
||||
btDbvtProxy* proxy=new(mem) btDbvtProxy( aabbMin,aabbMax,userPtr,
|
||||
collisionFilterGroup,
|
||||
collisionFilterMask);
|
||||
|
||||
btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
|
||||
|
||||
//bproxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
|
||||
proxy->stage = m_stageCurrent;
|
||||
proxy->m_uniqueId = objectId;
|
||||
proxy->leaf = m_sets[0].insert(aabb,proxy);
|
||||
listappend(proxy,m_stageRoots[m_stageCurrent]);
|
||||
if(!m_deferedcollide)
|
||||
{
|
||||
btDbvtTreeCollider collider(this);
|
||||
collider.proxy=proxy;
|
||||
m_sets[0].collideTV(m_sets[0].m_root,aabb,collider);
|
||||
m_sets[1].collideTV(m_sets[1].m_root,aabb,collider);
|
||||
}
|
||||
return(proxy);
|
||||
}
|
||||
|
||||
//
|
||||
void b3DynamicBvhBroadphase::destroyProxy( btBroadphaseProxy* absproxy,
|
||||
btDispatcher* dispatcher)
|
||||
{
|
||||
btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
|
||||
if(proxy->stage==STAGECOUNT)
|
||||
m_sets[1].remove(proxy->leaf);
|
||||
else
|
||||
m_sets[0].remove(proxy->leaf);
|
||||
listremove(proxy,m_stageRoots[proxy->stage]);
|
||||
m_paircache->removeOverlappingPairsContainingProxy(proxy->getUid(),dispatcher);
|
||||
|
||||
m_needcleanup=true;
|
||||
}
|
||||
|
||||
void b3DynamicBvhBroadphase::getAabb(btBroadphaseProxy* absproxy,b3Vector3& aabbMin, b3Vector3& aabbMax ) const
|
||||
{
|
||||
btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
|
||||
aabbMin = proxy->m_aabbMin;
|
||||
aabbMax = proxy->m_aabbMax;
|
||||
}
|
||||
|
||||
struct BroadphaseRayTester : b3DynamicBvh::ICollide
|
||||
{
|
||||
btBroadphaseRayCallback& m_rayCallback;
|
||||
BroadphaseRayTester(btBroadphaseRayCallback& orgCallback)
|
||||
:m_rayCallback(orgCallback)
|
||||
{
|
||||
}
|
||||
void Process(const btDbvtNode* leaf)
|
||||
{
|
||||
btDbvtProxy* proxy=(btDbvtProxy*)leaf->data;
|
||||
m_rayCallback.process(proxy);
|
||||
}
|
||||
};
|
||||
|
||||
void b3DynamicBvhBroadphase::rayTest(const b3Vector3& rayFrom,const b3Vector3& rayTo, btBroadphaseRayCallback& rayCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax)
|
||||
{
|
||||
BroadphaseRayTester callback(rayCallback);
|
||||
|
||||
m_sets[0].rayTestInternal( m_sets[0].m_root,
|
||||
rayFrom,
|
||||
rayTo,
|
||||
rayCallback.m_rayDirectionInverse,
|
||||
rayCallback.m_signs,
|
||||
rayCallback.m_lambda_max,
|
||||
aabbMin,
|
||||
aabbMax,
|
||||
callback);
|
||||
|
||||
m_sets[1].rayTestInternal( m_sets[1].m_root,
|
||||
rayFrom,
|
||||
rayTo,
|
||||
rayCallback.m_rayDirectionInverse,
|
||||
rayCallback.m_signs,
|
||||
rayCallback.m_lambda_max,
|
||||
aabbMin,
|
||||
aabbMax,
|
||||
callback);
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct BroadphaseAabbTester : b3DynamicBvh::ICollide
|
||||
{
|
||||
btBroadphaseAabbCallback& m_aabbCallback;
|
||||
BroadphaseAabbTester(btBroadphaseAabbCallback& orgCallback)
|
||||
:m_aabbCallback(orgCallback)
|
||||
{
|
||||
}
|
||||
void Process(const btDbvtNode* leaf)
|
||||
{
|
||||
btDbvtProxy* proxy=(btDbvtProxy*)leaf->data;
|
||||
m_aabbCallback.process(proxy);
|
||||
}
|
||||
};
|
||||
|
||||
void b3DynamicBvhBroadphase::aabbTest(const b3Vector3& aabbMin,const b3Vector3& aabbMax,btBroadphaseAabbCallback& aabbCallback)
|
||||
{
|
||||
BroadphaseAabbTester callback(aabbCallback);
|
||||
|
||||
const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(aabbMin,aabbMax);
|
||||
//process all children, that overlap with the given AABB bounds
|
||||
m_sets[0].collideTV(m_sets[0].m_root,bounds,callback);
|
||||
m_sets[1].collideTV(m_sets[1].m_root,bounds,callback);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
void b3DynamicBvhBroadphase::setAabb( btBroadphaseProxy* absproxy,
|
||||
const b3Vector3& aabbMin,
|
||||
const b3Vector3& aabbMax,
|
||||
btDispatcher* /*dispatcher*/)
|
||||
{
|
||||
btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
|
||||
ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
|
||||
#if DBVT_BP_PREVENTFALSEUPDATE
|
||||
if(NotEqual(aabb,proxy->leaf->volume))
|
||||
#endif
|
||||
{
|
||||
bool docollide=false;
|
||||
if(proxy->stage==STAGECOUNT)
|
||||
{/* fixed -> dynamic set */
|
||||
m_sets[1].remove(proxy->leaf);
|
||||
proxy->leaf=m_sets[0].insert(aabb,proxy);
|
||||
docollide=true;
|
||||
}
|
||||
else
|
||||
{/* dynamic set */
|
||||
++m_updates_call;
|
||||
if(Intersect(proxy->leaf->volume,aabb))
|
||||
{/* Moving */
|
||||
|
||||
const b3Vector3 delta=aabbMin-proxy->m_aabbMin;
|
||||
b3Vector3 velocity(((proxy->m_aabbMax-proxy->m_aabbMin)/2)*m_prediction);
|
||||
if(delta[0]<0) velocity[0]=-velocity[0];
|
||||
if(delta[1]<0) velocity[1]=-velocity[1];
|
||||
if(delta[2]<0) velocity[2]=-velocity[2];
|
||||
if (
|
||||
#ifdef DBVT_BP_MARGIN
|
||||
m_sets[0].update(proxy->leaf,aabb,velocity,DBVT_BP_MARGIN)
|
||||
#else
|
||||
m_sets[0].update(proxy->leaf,aabb,velocity)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
++m_updates_done;
|
||||
docollide=true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{/* Teleporting */
|
||||
m_sets[0].update(proxy->leaf,aabb);
|
||||
++m_updates_done;
|
||||
docollide=true;
|
||||
}
|
||||
}
|
||||
listremove(proxy,m_stageRoots[proxy->stage]);
|
||||
proxy->m_aabbMin = aabbMin;
|
||||
proxy->m_aabbMax = aabbMax;
|
||||
proxy->stage = m_stageCurrent;
|
||||
listappend(proxy,m_stageRoots[m_stageCurrent]);
|
||||
if(docollide)
|
||||
{
|
||||
m_needcleanup=true;
|
||||
if(!m_deferedcollide)
|
||||
{
|
||||
btDbvtTreeCollider collider(this);
|
||||
m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
|
||||
m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
void b3DynamicBvhBroadphase::setAabbForceUpdate( btBroadphaseProxy* absproxy,
|
||||
const b3Vector3& aabbMin,
|
||||
const b3Vector3& aabbMax,
|
||||
btDispatcher* /*dispatcher*/)
|
||||
{
|
||||
btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
|
||||
ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
|
||||
bool docollide=false;
|
||||
if(proxy->stage==STAGECOUNT)
|
||||
{/* fixed -> dynamic set */
|
||||
m_sets[1].remove(proxy->leaf);
|
||||
proxy->leaf=m_sets[0].insert(aabb,proxy);
|
||||
docollide=true;
|
||||
}
|
||||
else
|
||||
{/* dynamic set */
|
||||
++m_updates_call;
|
||||
/* Teleporting */
|
||||
m_sets[0].update(proxy->leaf,aabb);
|
||||
++m_updates_done;
|
||||
docollide=true;
|
||||
}
|
||||
listremove(proxy,m_stageRoots[proxy->stage]);
|
||||
proxy->m_aabbMin = aabbMin;
|
||||
proxy->m_aabbMax = aabbMax;
|
||||
proxy->stage = m_stageCurrent;
|
||||
listappend(proxy,m_stageRoots[m_stageCurrent]);
|
||||
if(docollide)
|
||||
{
|
||||
m_needcleanup=true;
|
||||
if(!m_deferedcollide)
|
||||
{
|
||||
btDbvtTreeCollider collider(this);
|
||||
m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
|
||||
m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
void b3DynamicBvhBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
|
||||
{
|
||||
collide(dispatcher);
|
||||
#if DBVT_BP_PROFILE
|
||||
if(0==(m_pid%DBVT_BP_PROFILING_RATE))
|
||||
{
|
||||
printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs());
|
||||
unsigned int total=m_profiling.m_total;
|
||||
if(total<=0) total=1;
|
||||
printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE);
|
||||
printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE);
|
||||
printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE);
|
||||
printf("total: %uus\r\n",total/DBVT_BP_PROFILING_RATE);
|
||||
const unsigned long sum=m_profiling.m_ddcollide+
|
||||
m_profiling.m_fdcollide+
|
||||
m_profiling.m_cleanup;
|
||||
printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE);
|
||||
printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE));
|
||||
clear(m_profiling);
|
||||
m_clock.reset();
|
||||
}
|
||||
#endif
|
||||
|
||||
performDeferredRemoval(dispatcher);
|
||||
|
||||
}
|
||||
|
||||
void b3DynamicBvhBroadphase::performDeferredRemoval(btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
if (m_paircache->hasDeferredRemoval())
|
||||
{
|
||||
|
||||
btBroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
|
||||
|
||||
//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
|
||||
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
|
||||
|
||||
int invalidPair = 0;
|
||||
|
||||
|
||||
int i;
|
||||
|
||||
btBroadphasePair previousPair(-1,-1);
|
||||
|
||||
|
||||
|
||||
for (i=0;i<overlappingPairArray.size();i++)
|
||||
{
|
||||
|
||||
btBroadphasePair& pair = overlappingPairArray[i];
|
||||
|
||||
bool isDuplicate = (pair == previousPair);
|
||||
|
||||
previousPair = pair;
|
||||
|
||||
bool needsRemoval = false;
|
||||
|
||||
if (!isDuplicate)
|
||||
{
|
||||
//important to perform AABB check that is consistent with the broadphase
|
||||
btDbvtProxy* pa=&m_proxies[pair.x];
|
||||
btDbvtProxy* pb=&m_proxies[pair.y];
|
||||
bool hasOverlap = Intersect(pa->leaf->volume,pb->leaf->volume);
|
||||
|
||||
if (hasOverlap)
|
||||
{
|
||||
needsRemoval = false;
|
||||
} else
|
||||
{
|
||||
needsRemoval = true;
|
||||
}
|
||||
} else
|
||||
{
|
||||
//remove duplicate
|
||||
needsRemoval = true;
|
||||
//should have no algorithm
|
||||
}
|
||||
|
||||
if (needsRemoval)
|
||||
{
|
||||
m_paircache->cleanOverlappingPair(pair,dispatcher);
|
||||
|
||||
pair.x = -1;
|
||||
pair.y = -1;
|
||||
invalidPair++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//perform a sort, to sort 'invalid' pairs to the end
|
||||
overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
|
||||
overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
void b3DynamicBvhBroadphase::collide(btDispatcher* dispatcher)
|
||||
{
|
||||
/*printf("---------------------------------------------------------\n");
|
||||
printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
|
||||
printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
|
||||
printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++)
|
||||
{
|
||||
printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
|
||||
getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
SPC(m_profiling.m_total);
|
||||
/* optimize */
|
||||
m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100);
|
||||
if(m_fixedleft)
|
||||
{
|
||||
const int count=1+(m_sets[1].m_leaves*m_fupdates)/100;
|
||||
m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100);
|
||||
m_fixedleft=btMax<int>(0,m_fixedleft-count);
|
||||
}
|
||||
/* dynamic -> fixed set */
|
||||
m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
|
||||
btDbvtProxy* current=m_stageRoots[m_stageCurrent];
|
||||
if(current)
|
||||
{
|
||||
btDbvtTreeCollider collider(this);
|
||||
do {
|
||||
btDbvtProxy* next=current->links[1];
|
||||
listremove(current,m_stageRoots[current->stage]);
|
||||
listappend(current,m_stageRoots[STAGECOUNT]);
|
||||
#if DBVT_BP_ACCURATESLEEPING
|
||||
m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher);
|
||||
collider.proxy=current;
|
||||
b3DynamicBvh::collideTV(m_sets[0].m_root,current->aabb,collider);
|
||||
b3DynamicBvh::collideTV(m_sets[1].m_root,current->aabb,collider);
|
||||
#endif
|
||||
m_sets[0].remove(current->leaf);
|
||||
ATTRIBUTE_ALIGNED16(btDbvtVolume) curAabb=btDbvtVolume::FromMM(current->m_aabbMin,current->m_aabbMax);
|
||||
current->leaf = m_sets[1].insert(curAabb,current);
|
||||
current->stage = STAGECOUNT;
|
||||
current = next;
|
||||
} while(current);
|
||||
m_fixedleft=m_sets[1].m_leaves;
|
||||
m_needcleanup=true;
|
||||
}
|
||||
/* collide dynamics */
|
||||
{
|
||||
btDbvtTreeCollider collider(this);
|
||||
if(m_deferedcollide)
|
||||
{
|
||||
SPC(m_profiling.m_fdcollide);
|
||||
m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[1].m_root,collider);
|
||||
}
|
||||
if(m_deferedcollide)
|
||||
{
|
||||
SPC(m_profiling.m_ddcollide);
|
||||
m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[0].m_root,collider);
|
||||
}
|
||||
}
|
||||
/* clean up */
|
||||
if(m_needcleanup)
|
||||
{
|
||||
SPC(m_profiling.m_cleanup);
|
||||
btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray();
|
||||
if(pairs.size()>0)
|
||||
{
|
||||
|
||||
int ni=btMin(pairs.size(),btMax<int>(m_newpairs,(pairs.size()*m_cupdates)/100));
|
||||
for(int i=0;i<ni;++i)
|
||||
{
|
||||
btBroadphasePair& p=pairs[(m_cid+i)%pairs.size()];
|
||||
btDbvtProxy* pa=&m_proxies[p.x];
|
||||
btDbvtProxy* pb=&m_proxies[p.y];
|
||||
if(!Intersect(pa->leaf->volume,pb->leaf->volume))
|
||||
{
|
||||
#if DBVT_BP_SORTPAIRS
|
||||
if(pa->m_uniqueId>pb->m_uniqueId)
|
||||
btSwap(pa,pb);
|
||||
#endif
|
||||
m_paircache->removeOverlappingPair(pa->getUid(),pb->getUid(),dispatcher);
|
||||
--ni;--i;
|
||||
}
|
||||
}
|
||||
if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0;
|
||||
}
|
||||
}
|
||||
++m_pid;
|
||||
m_newpairs=1;
|
||||
m_needcleanup=false;
|
||||
if(m_updates_call>0)
|
||||
{ m_updates_ratio=m_updates_done/(b3Scalar)m_updates_call; }
|
||||
else
|
||||
{ m_updates_ratio=0; }
|
||||
m_updates_done/=2;
|
||||
m_updates_call/=2;
|
||||
}
|
||||
|
||||
//
|
||||
void b3DynamicBvhBroadphase::optimize()
|
||||
{
|
||||
m_sets[0].optimizeTopDown();
|
||||
m_sets[1].optimizeTopDown();
|
||||
}
|
||||
|
||||
//
|
||||
b3OverlappingPairCache* b3DynamicBvhBroadphase::getOverlappingPairCache()
|
||||
{
|
||||
return(m_paircache);
|
||||
}
|
||||
|
||||
//
|
||||
const b3OverlappingPairCache* b3DynamicBvhBroadphase::getOverlappingPairCache() const
|
||||
{
|
||||
return(m_paircache);
|
||||
}
|
||||
|
||||
//
|
||||
void b3DynamicBvhBroadphase::getBroadphaseAabb(b3Vector3& aabbMin,b3Vector3& aabbMax) const
|
||||
{
|
||||
|
||||
ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds;
|
||||
|
||||
if(!m_sets[0].empty())
|
||||
if(!m_sets[1].empty()) Merge( m_sets[0].m_root->volume,
|
||||
m_sets[1].m_root->volume,bounds);
|
||||
else
|
||||
bounds=m_sets[0].m_root->volume;
|
||||
else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume;
|
||||
else
|
||||
bounds=btDbvtVolume::FromCR(b3Vector3(0,0,0),0);
|
||||
aabbMin=bounds.Mins();
|
||||
aabbMax=bounds.Maxs();
|
||||
}
|
||||
|
||||
void b3DynamicBvhBroadphase::resetPool(btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
|
||||
if (!totalObjects)
|
||||
{
|
||||
//reset internal dynamic tree data structures
|
||||
m_sets[0].clear();
|
||||
m_sets[1].clear();
|
||||
|
||||
m_deferedcollide = false;
|
||||
m_needcleanup = true;
|
||||
m_stageCurrent = 0;
|
||||
m_fixedleft = 0;
|
||||
m_fupdates = 1;
|
||||
m_dupdates = 0;
|
||||
m_cupdates = 10;
|
||||
m_newpairs = 1;
|
||||
m_updates_call = 0;
|
||||
m_updates_done = 0;
|
||||
m_updates_ratio = 0;
|
||||
|
||||
m_pid = 0;
|
||||
m_cid = 0;
|
||||
for(int i=0;i<=STAGECOUNT;++i)
|
||||
{
|
||||
m_stageRoots[i]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
void b3DynamicBvhBroadphase::printStats()
|
||||
{}
|
||||
|
||||
//
|
||||
#if DBVT_BP_ENABLE_BENCHMARK
|
||||
|
||||
struct btBroadphaseBenchmark
|
||||
{
|
||||
struct Experiment
|
||||
{
|
||||
const char* name;
|
||||
int object_count;
|
||||
int update_count;
|
||||
int spawn_count;
|
||||
int iterations;
|
||||
b3Scalar speed;
|
||||
b3Scalar amplitude;
|
||||
};
|
||||
struct Object
|
||||
{
|
||||
b3Vector3 center;
|
||||
b3Vector3 extents;
|
||||
btBroadphaseProxy* proxy;
|
||||
b3Scalar time;
|
||||
void update(b3Scalar speed,b3Scalar amplitude,btBroadphaseInterface* pbi)
|
||||
{
|
||||
time += speed;
|
||||
center[0] = btCos(time*(b3Scalar)2.17)*amplitude+
|
||||
btSin(time)*amplitude/2;
|
||||
center[1] = btCos(time*(b3Scalar)1.38)*amplitude+
|
||||
btSin(time)*amplitude;
|
||||
center[2] = btSin(time*(b3Scalar)0.777)*amplitude;
|
||||
pbi->setAabb(proxy,center-extents,center+extents,0);
|
||||
}
|
||||
};
|
||||
static int UnsignedRand(int range=RAND_MAX-1) { return(rand()%(range+1)); }
|
||||
static b3Scalar UnitRand() { return(UnsignedRand(16384)/(b3Scalar)16384); }
|
||||
static void OutputTime(const char* name,btClock& c,unsigned count=0)
|
||||
{
|
||||
const unsigned long us=c.getTimeMicroseconds();
|
||||
const unsigned long ms=(us+500)/1000;
|
||||
const b3Scalar sec=us/(b3Scalar)(1000*1000);
|
||||
if(count>0)
|
||||
printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec);
|
||||
else
|
||||
printf("%s : %u us (%u ms)\r\n",name,us,ms);
|
||||
}
|
||||
};
|
||||
|
||||
void b3DynamicBvhBroadphase::benchmark(btBroadphaseInterface* pbi)
|
||||
{
|
||||
static const btBroadphaseBenchmark::Experiment experiments[]=
|
||||
{
|
||||
{"1024o.10%",1024,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},
|
||||
/*{"4096o.10%",4096,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},
|
||||
{"8192o.10%",8192,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},*/
|
||||
};
|
||||
static const int nexperiments=sizeof(experiments)/sizeof(experiments[0]);
|
||||
b3AlignedObjectArray<btBroadphaseBenchmark::Object*> objects;
|
||||
btClock wallclock;
|
||||
/* Begin */
|
||||
for(int iexp=0;iexp<nexperiments;++iexp)
|
||||
{
|
||||
const btBroadphaseBenchmark::Experiment& experiment=experiments[iexp];
|
||||
const int object_count=experiment.object_count;
|
||||
const int update_count=(object_count*experiment.update_count)/100;
|
||||
const int spawn_count=(object_count*experiment.spawn_count)/100;
|
||||
const b3Scalar speed=experiment.speed;
|
||||
const b3Scalar amplitude=experiment.amplitude;
|
||||
printf("Experiment #%u '%s':\r\n",iexp,experiment.name);
|
||||
printf("\tObjects: %u\r\n",object_count);
|
||||
printf("\tUpdate: %u\r\n",update_count);
|
||||
printf("\tSpawn: %u\r\n",spawn_count);
|
||||
printf("\tSpeed: %f\r\n",speed);
|
||||
printf("\tAmplitude: %f\r\n",amplitude);
|
||||
srand(180673);
|
||||
/* Create objects */
|
||||
wallclock.reset();
|
||||
objects.reserve(object_count);
|
||||
for(int i=0;i<object_count;++i)
|
||||
{
|
||||
btBroadphaseBenchmark::Object* po=new btBroadphaseBenchmark::Object();
|
||||
po->center[0]=btBroadphaseBenchmark::UnitRand()*50;
|
||||
po->center[1]=btBroadphaseBenchmark::UnitRand()*50;
|
||||
po->center[2]=btBroadphaseBenchmark::UnitRand()*50;
|
||||
po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2;
|
||||
po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2;
|
||||
po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2;
|
||||
po->time=btBroadphaseBenchmark::UnitRand()*2000;
|
||||
po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0);
|
||||
objects.push_back(po);
|
||||
}
|
||||
btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock);
|
||||
/* First update */
|
||||
wallclock.reset();
|
||||
for(int i=0;i<objects.size();++i)
|
||||
{
|
||||
objects[i]->update(speed,amplitude,pbi);
|
||||
}
|
||||
btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock);
|
||||
/* Updates */
|
||||
wallclock.reset();
|
||||
for(int i=0;i<experiment.iterations;++i)
|
||||
{
|
||||
for(int j=0;j<update_count;++j)
|
||||
{
|
||||
objects[j]->update(speed,amplitude,pbi);
|
||||
}
|
||||
pbi->calculateOverlappingPairs(0);
|
||||
}
|
||||
btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations);
|
||||
/* Clean up */
|
||||
wallclock.reset();
|
||||
for(int i=0;i<objects.size();++i)
|
||||
{
|
||||
pbi->destroyProxy(objects[i]->proxy,0);
|
||||
delete objects[i];
|
||||
}
|
||||
objects.resize(0);
|
||||
btBroadphaseBenchmark::OutputTime("\tRelease",wallclock);
|
||||
}
|
||||
|
||||
}
|
||||
#else
|
||||
/*void b3DynamicBvhBroadphase::benchmark(btBroadphaseInterface*)
|
||||
{}
|
||||
*/
|
||||
#endif
|
||||
|
||||
#if DBVT_BP_PROFILE
|
||||
#undef SPC
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
///b3DynamicBvhBroadphase implementation by Nathanael Presson
|
||||
#ifndef BT_DBVT_BROADPHASE_H
|
||||
#define BT_DBVT_BROADPHASE_H
|
||||
|
||||
#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h"
|
||||
#include "Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h"
|
||||
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||
|
||||
#include "b3BroadphaseCallback.h"
|
||||
|
||||
//
|
||||
// Compile time config
|
||||
//
|
||||
|
||||
#define DBVT_BP_PROFILE 0
|
||||
//#define DBVT_BP_SORTPAIRS 1
|
||||
#define DBVT_BP_PREVENTFALSEUPDATE 0
|
||||
#define DBVT_BP_ACCURATESLEEPING 0
|
||||
#define DBVT_BP_ENABLE_BENCHMARK 0
|
||||
#define DBVT_BP_MARGIN (b3Scalar)0.05
|
||||
|
||||
#if DBVT_BP_PROFILE
|
||||
#define DBVT_BP_PROFILING_RATE 256
|
||||
#include "LinearMath/btQuickprof.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy
|
||||
{
|
||||
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
///optional filtering to cull potential collisions
|
||||
enum CollisionFilterGroups
|
||||
{
|
||||
DefaultFilter = 1,
|
||||
StaticFilter = 2,
|
||||
KinematicFilter = 4,
|
||||
DebrisFilter = 8,
|
||||
SensorTrigger = 16,
|
||||
CharacterFilter = 32,
|
||||
AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
|
||||
};
|
||||
|
||||
//Usually the client btCollisionObject or Rigidbody class
|
||||
void* m_clientObject;
|
||||
short int m_collisionFilterGroup;
|
||||
short int m_collisionFilterMask;
|
||||
void* m_multiSapParentProxy;
|
||||
int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
|
||||
|
||||
b3Vector3 m_aabbMin;
|
||||
b3Vector3 m_aabbMax;
|
||||
|
||||
SIMD_FORCE_INLINE int getUid() const
|
||||
{
|
||||
return m_uniqueId;
|
||||
}
|
||||
|
||||
//used for memory pools
|
||||
btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0)
|
||||
{
|
||||
}
|
||||
|
||||
btBroadphaseProxy(const b3Vector3& aabbMin,const b3Vector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0)
|
||||
:m_clientObject(userPtr),
|
||||
m_collisionFilterGroup(collisionFilterGroup),
|
||||
m_collisionFilterMask(collisionFilterMask),
|
||||
m_aabbMin(aabbMin),
|
||||
m_aabbMax(aabbMax)
|
||||
{
|
||||
m_multiSapParentProxy = multiSapParentProxy;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// btDbvtProxy
|
||||
//
|
||||
struct btDbvtProxy : btBroadphaseProxy
|
||||
{
|
||||
/* Fields */
|
||||
//btDbvtAabbMm aabb;
|
||||
btDbvtNode* leaf;
|
||||
btDbvtProxy* links[2];
|
||||
int stage;
|
||||
/* ctor */
|
||||
|
||||
explicit btDbvtProxy() {}
|
||||
btDbvtProxy(const b3Vector3& aabbMin,const b3Vector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
|
||||
btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask)
|
||||
{
|
||||
links[0]=links[1]=0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef b3AlignedObjectArray<btDbvtProxy*> btDbvtProxyArray;
|
||||
|
||||
///The b3DynamicBvhBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see b3DynamicBvh).
|
||||
///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
|
||||
///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
|
||||
struct b3DynamicBvhBroadphase
|
||||
{
|
||||
/* Config */
|
||||
enum {
|
||||
DYNAMIC_SET = 0, /* Dynamic set index */
|
||||
FIXED_SET = 1, /* Fixed set index */
|
||||
STAGECOUNT = 2 /* Number of stages */
|
||||
};
|
||||
/* Fields */
|
||||
b3DynamicBvh m_sets[2]; // Dbvt sets
|
||||
btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list
|
||||
|
||||
b3AlignedObjectArray<btDbvtProxy> m_proxies;
|
||||
b3OverlappingPairCache* m_paircache; // Pair cache
|
||||
b3Scalar m_prediction; // Velocity prediction
|
||||
int m_stageCurrent; // Current stage
|
||||
int m_fupdates; // % of fixed updates per frame
|
||||
int m_dupdates; // % of dynamic updates per frame
|
||||
int m_cupdates; // % of cleanup updates per frame
|
||||
int m_newpairs; // Number of pairs created
|
||||
int m_fixedleft; // Fixed optimization left
|
||||
unsigned m_updates_call; // Number of updates call
|
||||
unsigned m_updates_done; // Number of updates done
|
||||
b3Scalar m_updates_ratio; // m_updates_done/m_updates_call
|
||||
int m_pid; // Parse id
|
||||
int m_cid; // Cleanup index
|
||||
bool m_releasepaircache; // Release pair cache on delete
|
||||
bool m_deferedcollide; // Defere dynamic/static collision to collide call
|
||||
bool m_needcleanup; // Need to run cleanup?
|
||||
#if DBVT_BP_PROFILE
|
||||
btClock m_clock;
|
||||
struct {
|
||||
unsigned long m_total;
|
||||
unsigned long m_ddcollide;
|
||||
unsigned long m_fdcollide;
|
||||
unsigned long m_cleanup;
|
||||
unsigned long m_jobcount;
|
||||
} m_profiling;
|
||||
#endif
|
||||
/* Methods */
|
||||
b3DynamicBvhBroadphase(int proxyCapacity, b3OverlappingPairCache* paircache=0);
|
||||
~b3DynamicBvhBroadphase();
|
||||
void collide(btDispatcher* dispatcher);
|
||||
void optimize();
|
||||
|
||||
/* btBroadphaseInterface Implementation */
|
||||
btBroadphaseProxy* createProxy(const b3Vector3& aabbMin,const b3Vector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask);
|
||||
virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
|
||||
virtual void setAabb(btBroadphaseProxy* proxy,const b3Vector3& aabbMin,const b3Vector3& aabbMax,btDispatcher* dispatcher);
|
||||
virtual void rayTest(const b3Vector3& rayFrom,const b3Vector3& rayTo, btBroadphaseRayCallback& rayCallback, const b3Vector3& aabbMin=b3Vector3(0,0,0), const b3Vector3& aabbMax = b3Vector3(0,0,0));
|
||||
virtual void aabbTest(const b3Vector3& aabbMin, const b3Vector3& aabbMax, btBroadphaseAabbCallback& callback);
|
||||
|
||||
virtual void getAabb(btBroadphaseProxy* proxy,b3Vector3& aabbMin, b3Vector3& aabbMax ) const;
|
||||
virtual void calculateOverlappingPairs(btDispatcher* dispatcher=0);
|
||||
virtual b3OverlappingPairCache* getOverlappingPairCache();
|
||||
virtual const b3OverlappingPairCache* getOverlappingPairCache() const;
|
||||
virtual void getBroadphaseAabb(b3Vector3& aabbMin,b3Vector3& aabbMax) const;
|
||||
virtual void printStats();
|
||||
|
||||
|
||||
///reset broadphase internal structures, to ensure determinism/reproducability
|
||||
virtual void resetPool(btDispatcher* dispatcher);
|
||||
|
||||
void performDeferredRemoval(btDispatcher* dispatcher);
|
||||
|
||||
void setVelocityPrediction(b3Scalar prediction)
|
||||
{
|
||||
m_prediction = prediction;
|
||||
}
|
||||
b3Scalar getVelocityPrediction() const
|
||||
{
|
||||
return m_prediction;
|
||||
}
|
||||
|
||||
///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
|
||||
///it is not part of the btBroadphaseInterface but specific to b3DynamicBvhBroadphase.
|
||||
///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see
|
||||
///http://code.google.com/p/bullet/issues/detail?id=223
|
||||
void setAabbForceUpdate( btBroadphaseProxy* absproxy,const b3Vector3& aabbMin,const b3Vector3& aabbMax,btDispatcher* /*dispatcher*/);
|
||||
|
||||
//static void benchmark(btBroadphaseInterface*);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
45
src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h
Normal file
45
src/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef B3_OVERLAPPING_PAIR_H
|
||||
#define B3_OVERLAPPING_PAIR_H
|
||||
|
||||
#include "Bullet3Common/btInt2.h"
|
||||
|
||||
//typedef btInt2 btBroadphasePair;
|
||||
struct btBroadphasePair : public btInt2
|
||||
{
|
||||
explicit btBroadphasePair(){}
|
||||
btBroadphasePair(int xx,int yy)
|
||||
{
|
||||
if (xx < yy)
|
||||
{
|
||||
x = xx;
|
||||
y = yy;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = yy;
|
||||
y = xx;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class btBroadphasePairSortPredicate
|
||||
{
|
||||
public:
|
||||
|
||||
bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) const
|
||||
{
|
||||
const int uidA0 = a.x;
|
||||
const int uidB0 = b.x;
|
||||
const int uidA1 = a.y;
|
||||
const int uidB1 = b.y;
|
||||
return uidA0 > uidB0 || (uidA0 == uidB0 && uidA1 > uidB1);
|
||||
}
|
||||
};
|
||||
|
||||
SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b)
|
||||
{
|
||||
return (a.x == b.x ) && (a.y == b.y );
|
||||
}
|
||||
|
||||
#endif //B3_OVERLAPPING_PAIR_H
|
||||
|
||||
@@ -0,0 +1,639 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "b3OverlappingPairCache.h"
|
||||
|
||||
//#include "btDispatcher.h"
|
||||
//#include "btCollisionAlgorithm.h"
|
||||
#include "Bullet3Geometry/b3AabbUtil.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int gOverlappingPairs = 0;
|
||||
|
||||
int gRemovePairs =0;
|
||||
int gAddedPairs =0;
|
||||
int gFindPairs =0;
|
||||
|
||||
|
||||
|
||||
|
||||
btHashedOverlappingPairCache::btHashedOverlappingPairCache():
|
||||
m_overlapFilterCallback(0),
|
||||
m_blockedForChanges(false)
|
||||
{
|
||||
int initialAllocatedSize= 2;
|
||||
m_overlappingPairArray.reserve(initialAllocatedSize);
|
||||
growTables();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
btHashedOverlappingPairCache::~btHashedOverlappingPairCache()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
|
||||
{
|
||||
/* if (pair.m_algorithm)
|
||||
{
|
||||
{
|
||||
pair.m_algorithm->~btCollisionAlgorithm();
|
||||
dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
|
||||
pair.m_algorithm=0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void btHashedOverlappingPairCache::cleanProxyFromPairs(int proxy,btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
class CleanPairCallback : public btOverlapCallback
|
||||
{
|
||||
int m_cleanProxy;
|
||||
b3OverlappingPairCache* m_pairCache;
|
||||
btDispatcher* m_dispatcher;
|
||||
|
||||
public:
|
||||
CleanPairCallback(int cleanProxy,b3OverlappingPairCache* pairCache,btDispatcher* dispatcher)
|
||||
:m_cleanProxy(cleanProxy),
|
||||
m_pairCache(pairCache),
|
||||
m_dispatcher(dispatcher)
|
||||
{
|
||||
}
|
||||
virtual bool processOverlap(btBroadphasePair& pair)
|
||||
{
|
||||
if ((pair.x == m_cleanProxy) ||
|
||||
(pair.y == m_cleanProxy))
|
||||
{
|
||||
m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CleanPairCallback cleanPairs(proxy,this,dispatcher);
|
||||
|
||||
processAllOverlappingPairs(&cleanPairs,dispatcher);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(int proxy,btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
class RemovePairCallback : public btOverlapCallback
|
||||
{
|
||||
int m_obsoleteProxy;
|
||||
|
||||
public:
|
||||
RemovePairCallback(int obsoleteProxy)
|
||||
:m_obsoleteProxy(obsoleteProxy)
|
||||
{
|
||||
}
|
||||
virtual bool processOverlap(btBroadphasePair& pair)
|
||||
{
|
||||
return ((pair.x == m_obsoleteProxy) ||
|
||||
(pair.y == m_obsoleteProxy));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
RemovePairCallback removeCallback(proxy);
|
||||
|
||||
processAllOverlappingPairs(&removeCallback,dispatcher);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
btBroadphasePair* btHashedOverlappingPairCache::findPair(int proxy0, int proxy1)
|
||||
{
|
||||
gFindPairs++;
|
||||
if(proxy0 >proxy1)
|
||||
btSwap(proxy0,proxy1);
|
||||
int proxyId1 = proxy0;
|
||||
int proxyId2 = proxy1;
|
||||
|
||||
/*if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);*/
|
||||
|
||||
int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
|
||||
|
||||
if (hash >= m_hashTable.size())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int index = m_hashTable[hash];
|
||||
while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
|
||||
{
|
||||
index = m_next[index];
|
||||
}
|
||||
|
||||
if (index == BT_NULL_PAIR)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
btAssert(index < m_overlappingPairArray.size());
|
||||
|
||||
return &m_overlappingPairArray[index];
|
||||
}
|
||||
|
||||
//#include <stdio.h>
|
||||
|
||||
void btHashedOverlappingPairCache::growTables()
|
||||
{
|
||||
|
||||
int newCapacity = m_overlappingPairArray.capacity();
|
||||
|
||||
if (m_hashTable.size() < newCapacity)
|
||||
{
|
||||
//grow hashtable and next table
|
||||
int curHashtableSize = m_hashTable.size();
|
||||
|
||||
m_hashTable.resize(newCapacity);
|
||||
m_next.resize(newCapacity);
|
||||
|
||||
|
||||
int i;
|
||||
|
||||
for (i= 0; i < newCapacity; ++i)
|
||||
{
|
||||
m_hashTable[i] = BT_NULL_PAIR;
|
||||
}
|
||||
for (i = 0; i < newCapacity; ++i)
|
||||
{
|
||||
m_next[i] = BT_NULL_PAIR;
|
||||
}
|
||||
|
||||
for(i=0;i<curHashtableSize;i++)
|
||||
{
|
||||
|
||||
const btBroadphasePair& pair = m_overlappingPairArray[i];
|
||||
int proxyId1 = pair.x;
|
||||
int proxyId2 = pair.y;
|
||||
/*if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);*/
|
||||
int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
|
||||
m_next[i] = m_hashTable[hashValue];
|
||||
m_hashTable[hashValue] = i;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(int proxy0, int proxy1)
|
||||
{
|
||||
if(proxy0>proxy1)
|
||||
btSwap(proxy0,proxy1);
|
||||
int proxyId1 = proxy0;
|
||||
int proxyId2 = proxy1;
|
||||
|
||||
/*if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);*/
|
||||
|
||||
int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
|
||||
|
||||
|
||||
btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
|
||||
if (pair != NULL)
|
||||
{
|
||||
return pair;
|
||||
}
|
||||
/*for(int i=0;i<m_overlappingPairArray.size();++i)
|
||||
{
|
||||
if( (m_overlappingPairArray[i].m_pProxy0==proxy0)&&
|
||||
(m_overlappingPairArray[i].m_pProxy1==proxy1))
|
||||
{
|
||||
printf("Adding duplicated %u<>%u\r\n",proxyId1,proxyId2);
|
||||
internalFindPair(proxy0, proxy1, hash);
|
||||
}
|
||||
}*/
|
||||
int count = m_overlappingPairArray.size();
|
||||
int oldCapacity = m_overlappingPairArray.capacity();
|
||||
void* mem = &m_overlappingPairArray.expandNonInitializing();
|
||||
|
||||
//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)
|
||||
{
|
||||
growTables();
|
||||
//hash with new capacity
|
||||
hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
|
||||
}
|
||||
|
||||
pair = new (mem) btBroadphasePair(proxy0,proxy1);
|
||||
|
||||
// pair->m_pProxy0 = proxy0;
|
||||
// pair->m_pProxy1 = proxy1;
|
||||
//pair->m_algorithm = 0;
|
||||
//pair->m_internalTmpValue = 0;
|
||||
|
||||
|
||||
m_next[count] = m_hashTable[hash];
|
||||
m_hashTable[hash] = count;
|
||||
|
||||
return pair;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void* btHashedOverlappingPairCache::removeOverlappingPair(int proxy0, int proxy1,btDispatcher* dispatcher)
|
||||
{
|
||||
gRemovePairs++;
|
||||
if(proxy0>proxy1)
|
||||
btSwap(proxy0,proxy1);
|
||||
int proxyId1 = proxy0;
|
||||
int proxyId2 = proxy1;
|
||||
|
||||
/*if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);*/
|
||||
|
||||
int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
|
||||
|
||||
btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
|
||||
if (pair == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
cleanOverlappingPair(*pair,dispatcher);
|
||||
|
||||
|
||||
|
||||
int pairIndex = int(pair - &m_overlappingPairArray[0]);
|
||||
btAssert(pairIndex < m_overlappingPairArray.size());
|
||||
|
||||
// Remove the pair from the hash table.
|
||||
int index = m_hashTable[hash];
|
||||
btAssert(index != BT_NULL_PAIR);
|
||||
|
||||
int previous = BT_NULL_PAIR;
|
||||
while (index != pairIndex)
|
||||
{
|
||||
previous = index;
|
||||
index = m_next[index];
|
||||
}
|
||||
|
||||
if (previous != BT_NULL_PAIR)
|
||||
{
|
||||
btAssert(m_next[previous] == pairIndex);
|
||||
m_next[previous] = m_next[pairIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hashTable[hash] = m_next[pairIndex];
|
||||
}
|
||||
|
||||
// We now move the last pair into spot of the
|
||||
// pair being removed. We need to fix the hash
|
||||
// table indices to support the move.
|
||||
|
||||
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)
|
||||
{
|
||||
m_overlappingPairArray.pop_back();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Remove the last pair from the hash table.
|
||||
const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
|
||||
/* missing swap here too, Nat. */
|
||||
int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->x), static_cast<unsigned int>(last->y)) & (m_overlappingPairArray.capacity()-1));
|
||||
|
||||
index = m_hashTable[lastHash];
|
||||
btAssert(index != BT_NULL_PAIR);
|
||||
|
||||
previous = BT_NULL_PAIR;
|
||||
while (index != lastPairIndex)
|
||||
{
|
||||
previous = index;
|
||||
index = m_next[index];
|
||||
}
|
||||
|
||||
if (previous != BT_NULL_PAIR)
|
||||
{
|
||||
btAssert(m_next[previous] == lastPairIndex);
|
||||
m_next[previous] = m_next[lastPairIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hashTable[lastHash] = m_next[lastPairIndex];
|
||||
}
|
||||
|
||||
// Copy the last pair into the remove pair's spot.
|
||||
m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
|
||||
|
||||
// Insert the last pair into the hash table
|
||||
m_next[pairIndex] = m_hashTable[lastHash];
|
||||
m_hashTable[lastHash] = pairIndex;
|
||||
|
||||
m_overlappingPairArray.pop_back();
|
||||
|
||||
return 0;
|
||||
}
|
||||
//#include <stdio.h>
|
||||
|
||||
void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
|
||||
for (i=0;i<m_overlappingPairArray.size();)
|
||||
{
|
||||
|
||||
btBroadphasePair* pair = &m_overlappingPairArray[i];
|
||||
if (callback->processOverlap(*pair))
|
||||
{
|
||||
removeOverlappingPair(pair->x,pair->y,dispatcher);
|
||||
|
||||
gOverlappingPairs--;
|
||||
} else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
|
||||
{
|
||||
///need to keep hashmap in sync with pair address, so rebuild all
|
||||
btBroadphasePairArray tmpPairs;
|
||||
int i;
|
||||
for (i=0;i<m_overlappingPairArray.size();i++)
|
||||
{
|
||||
tmpPairs.push_back(m_overlappingPairArray[i]);
|
||||
}
|
||||
|
||||
for (i=0;i<tmpPairs.size();i++)
|
||||
{
|
||||
removeOverlappingPair(tmpPairs[i].x,tmpPairs[i].y,dispatcher);
|
||||
}
|
||||
|
||||
for (i = 0; i < m_next.size(); i++)
|
||||
{
|
||||
m_next[i] = BT_NULL_PAIR;
|
||||
}
|
||||
|
||||
tmpPairs.quickSort(btBroadphasePairSortPredicate());
|
||||
|
||||
for (i=0;i<tmpPairs.size();i++)
|
||||
{
|
||||
addOverlappingPair(tmpPairs[i].x ,tmpPairs[i].y);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void* btSortedOverlappingPairCache::removeOverlappingPair(int proxy0,int proxy1, btDispatcher* dispatcher )
|
||||
{
|
||||
if (!hasDeferredRemoval())
|
||||
{
|
||||
btBroadphasePair findPair(proxy0,proxy1);
|
||||
|
||||
|
||||
int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
|
||||
if (findIndex < m_overlappingPairArray.size())
|
||||
{
|
||||
gOverlappingPairs--;
|
||||
btBroadphasePair& pair = m_overlappingPairArray[findIndex];
|
||||
|
||||
cleanOverlappingPair(pair,dispatcher);
|
||||
//if (m_ghostPairCallback)
|
||||
// m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
|
||||
|
||||
m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
|
||||
m_overlappingPairArray.pop_back();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(int proxy0,int proxy1)
|
||||
{
|
||||
//don't add overlap with own
|
||||
btAssert(proxy0 != proxy1);
|
||||
|
||||
if (!needsBroadphaseCollision(proxy0,proxy1))
|
||||
return 0;
|
||||
|
||||
void* mem = &m_overlappingPairArray.expandNonInitializing();
|
||||
btBroadphasePair* pair = new (mem) btBroadphasePair(proxy0,proxy1);
|
||||
|
||||
|
||||
gOverlappingPairs++;
|
||||
gAddedPairs++;
|
||||
|
||||
// if (m_ghostPairCallback)
|
||||
// m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
|
||||
return pair;
|
||||
|
||||
}
|
||||
|
||||
///this findPair becomes really slow. Either sort the list to speedup the query, or
|
||||
///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
|
||||
///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
|
||||
///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
|
||||
btBroadphasePair* btSortedOverlappingPairCache::findPair(int proxy0,int proxy1)
|
||||
{
|
||||
if (!needsBroadphaseCollision(proxy0,proxy1))
|
||||
return 0;
|
||||
|
||||
btBroadphasePair tmpPair(proxy0,proxy1);
|
||||
int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
|
||||
|
||||
if (findIndex < m_overlappingPairArray.size())
|
||||
{
|
||||
//btAssert(it != m_overlappingPairSet.end());
|
||||
btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
|
||||
return pair;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//#include <stdio.h>
|
||||
|
||||
void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
for (i=0;i<m_overlappingPairArray.size();)
|
||||
{
|
||||
|
||||
btBroadphasePair* pair = &m_overlappingPairArray[i];
|
||||
if (callback->processOverlap(*pair))
|
||||
{
|
||||
cleanOverlappingPair(*pair,dispatcher);
|
||||
pair->x = -1;
|
||||
pair->y = -1;
|
||||
m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
|
||||
m_overlappingPairArray.pop_back();
|
||||
gOverlappingPairs--;
|
||||
} else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
btSortedOverlappingPairCache::btSortedOverlappingPairCache():
|
||||
m_blockedForChanges(false),
|
||||
m_hasDeferredRemoval(true),
|
||||
m_overlapFilterCallback(0)
|
||||
|
||||
{
|
||||
int initialAllocatedSize= 2;
|
||||
m_overlappingPairArray.reserve(initialAllocatedSize);
|
||||
}
|
||||
|
||||
btSortedOverlappingPairCache::~btSortedOverlappingPairCache()
|
||||
{
|
||||
}
|
||||
|
||||
void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
|
||||
{
|
||||
/* if (pair.m_algorithm)
|
||||
{
|
||||
{
|
||||
pair.m_algorithm->~btCollisionAlgorithm();
|
||||
dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
|
||||
pair.m_algorithm=0;
|
||||
gRemovePairs--;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void btSortedOverlappingPairCache::cleanProxyFromPairs(int proxy,btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
class CleanPairCallback : public btOverlapCallback
|
||||
{
|
||||
int m_cleanProxy;
|
||||
b3OverlappingPairCache* m_pairCache;
|
||||
btDispatcher* m_dispatcher;
|
||||
|
||||
public:
|
||||
CleanPairCallback(int cleanProxy,b3OverlappingPairCache* pairCache,btDispatcher* dispatcher)
|
||||
:m_cleanProxy(cleanProxy),
|
||||
m_pairCache(pairCache),
|
||||
m_dispatcher(dispatcher)
|
||||
{
|
||||
}
|
||||
virtual bool processOverlap(btBroadphasePair& pair)
|
||||
{
|
||||
if ((pair.x == m_cleanProxy) ||
|
||||
(pair.y == m_cleanProxy))
|
||||
{
|
||||
m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CleanPairCallback cleanPairs(proxy,this,dispatcher);
|
||||
|
||||
processAllOverlappingPairs(&cleanPairs,dispatcher);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(int proxy,btDispatcher* dispatcher)
|
||||
{
|
||||
|
||||
class RemovePairCallback : public btOverlapCallback
|
||||
{
|
||||
int m_obsoleteProxy;
|
||||
|
||||
public:
|
||||
RemovePairCallback(int obsoleteProxy)
|
||||
:m_obsoleteProxy(obsoleteProxy)
|
||||
{
|
||||
}
|
||||
virtual bool processOverlap(btBroadphasePair& pair)
|
||||
{
|
||||
return ((pair.x == m_obsoleteProxy) ||
|
||||
(pair.y == m_obsoleteProxy));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
RemovePairCallback removeCallback(proxy);
|
||||
|
||||
processAllOverlappingPairs(&removeCallback,dispatcher);
|
||||
}
|
||||
|
||||
void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
|
||||
{
|
||||
//should already be sorted
|
||||
}
|
||||
|
||||
@@ -0,0 +1,474 @@
|
||||
/*
|
||||
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 BT_OVERLAPPING_PAIR_CACHE_H
|
||||
#define BT_OVERLAPPING_PAIR_CACHE_H
|
||||
|
||||
#include "Bullet3Common/btInt2.h"
|
||||
#include "Bullet3Common/b3AlignedObjectArray.h"
|
||||
|
||||
class btDispatcher;
|
||||
#include "b3OverlappingPair.h"
|
||||
|
||||
|
||||
|
||||
typedef b3AlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
|
||||
|
||||
struct btOverlapCallback
|
||||
{
|
||||
virtual ~btOverlapCallback()
|
||||
{}
|
||||
//return true for deletion of the pair
|
||||
virtual bool processOverlap(btBroadphasePair& pair) = 0;
|
||||
|
||||
};
|
||||
|
||||
struct btOverlapFilterCallback
|
||||
{
|
||||
virtual ~btOverlapFilterCallback()
|
||||
{}
|
||||
// return true when pairs need collision
|
||||
virtual bool needBroadphaseCollision(int proxy0,int proxy1) const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
extern int gRemovePairs;
|
||||
extern int gAddedPairs;
|
||||
extern int gFindPairs;
|
||||
|
||||
const int BT_NULL_PAIR=0xffffffff;
|
||||
|
||||
///The b3OverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
|
||||
///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations.
|
||||
class b3OverlappingPairCache
|
||||
{
|
||||
public:
|
||||
virtual ~b3OverlappingPairCache() {} // this is needed so we can get to the derived class destructor
|
||||
|
||||
virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0;
|
||||
|
||||
virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
|
||||
|
||||
virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
|
||||
|
||||
virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0;
|
||||
|
||||
virtual int getNumOverlappingPairs() const = 0;
|
||||
|
||||
virtual void cleanProxyFromPairs(int proxy,btDispatcher* dispatcher) = 0;
|
||||
|
||||
virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
|
||||
|
||||
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0;
|
||||
|
||||
virtual btBroadphasePair* findPair(int proxy0, int proxy1) = 0;
|
||||
|
||||
virtual bool hasDeferredRemoval() = 0;
|
||||
|
||||
//virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0;
|
||||
|
||||
virtual btBroadphasePair* addOverlappingPair(int proxy0,int proxy1)=0;
|
||||
virtual void* removeOverlappingPair(int proxy0,int proxy1,btDispatcher* dispatcher)=0;
|
||||
virtual void removeOverlappingPairsContainingProxy(int /*proxy0*/,btDispatcher* /*dispatcher*/)=0;
|
||||
|
||||
virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
|
||||
class btHashedOverlappingPairCache : public b3OverlappingPairCache
|
||||
{
|
||||
btBroadphasePairArray m_overlappingPairArray;
|
||||
btOverlapFilterCallback* m_overlapFilterCallback;
|
||||
bool m_blockedForChanges;
|
||||
|
||||
|
||||
public:
|
||||
btHashedOverlappingPairCache();
|
||||
virtual ~btHashedOverlappingPairCache();
|
||||
|
||||
|
||||
virtual void removeOverlappingPairsContainingProxy(int proxy,btDispatcher* dispatcher);
|
||||
|
||||
virtual void* removeOverlappingPair(int proxy0,int proxy1,btDispatcher* dispatcher);
|
||||
|
||||
SIMD_FORCE_INLINE bool needsBroadphaseCollision(int proxy0,int proxy1) const
|
||||
{
|
||||
if (m_overlapFilterCallback)
|
||||
return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
|
||||
|
||||
bool collides = true;//(proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
|
||||
//collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
|
||||
|
||||
return collides;
|
||||
}
|
||||
|
||||
// Add a pair and return the new pair. If the pair already exists,
|
||||
// no new pair is created and the old one is returned.
|
||||
virtual btBroadphasePair* addOverlappingPair(int proxy0,int proxy1)
|
||||
{
|
||||
gAddedPairs++;
|
||||
|
||||
if (!needsBroadphaseCollision(proxy0,proxy1))
|
||||
return 0;
|
||||
|
||||
return internalAddPair(proxy0,proxy1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cleanProxyFromPairs(int proxy,btDispatcher* dispatcher);
|
||||
|
||||
|
||||
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
|
||||
|
||||
virtual btBroadphasePair* getOverlappingPairArrayPtr()
|
||||
{
|
||||
return &m_overlappingPairArray[0];
|
||||
}
|
||||
|
||||
const btBroadphasePair* getOverlappingPairArrayPtr() const
|
||||
{
|
||||
return &m_overlappingPairArray[0];
|
||||
}
|
||||
|
||||
btBroadphasePairArray& getOverlappingPairArray()
|
||||
{
|
||||
return m_overlappingPairArray;
|
||||
}
|
||||
|
||||
const btBroadphasePairArray& getOverlappingPairArray() const
|
||||
{
|
||||
return m_overlappingPairArray;
|
||||
}
|
||||
|
||||
void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
|
||||
|
||||
|
||||
|
||||
btBroadphasePair* findPair(int proxy0, int proxy1);
|
||||
|
||||
int GetCount() const { return m_overlappingPairArray.size(); }
|
||||
// btBroadphasePair* GetPairs() { return m_pairs; }
|
||||
|
||||
btOverlapFilterCallback* getOverlapFilterCallback()
|
||||
{
|
||||
return m_overlapFilterCallback;
|
||||
}
|
||||
|
||||
void setOverlapFilterCallback(btOverlapFilterCallback* callback)
|
||||
{
|
||||
m_overlapFilterCallback = callback;
|
||||
}
|
||||
|
||||
int getNumOverlappingPairs() const
|
||||
{
|
||||
return m_overlappingPairArray.size();
|
||||
}
|
||||
private:
|
||||
|
||||
btBroadphasePair* internalAddPair(int proxy0,int proxy1);
|
||||
|
||||
void growTables();
|
||||
|
||||
SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2)
|
||||
{
|
||||
return pair.x == proxyId1 && pair.y == proxyId2;
|
||||
}
|
||||
|
||||
/*
|
||||
// Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||
// This assumes proxyId1 and proxyId2 are 16-bit.
|
||||
SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2)
|
||||
{
|
||||
int key = (proxyId2 << 16) | proxyId1;
|
||||
key = ~key + (key << 15);
|
||||
key = key ^ (key >> 12);
|
||||
key = key + (key << 2);
|
||||
key = key ^ (key >> 4);
|
||||
key = key * 2057;
|
||||
key = key ^ (key >> 16);
|
||||
return key;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
|
||||
{
|
||||
int key = static_cast<int>(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16));
|
||||
// Thomas Wang's hash
|
||||
|
||||
key += ~(key << 15);
|
||||
key ^= (key >> 10);
|
||||
key += (key << 3);
|
||||
key ^= (key >> 6);
|
||||
key += ~(key << 11);
|
||||
key ^= (key >> 16);
|
||||
return static_cast<unsigned int>(key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(int proxy0, int proxy1, int hash)
|
||||
{
|
||||
int proxyId1 = proxy0;
|
||||
int proxyId2 = proxy1;
|
||||
#if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
|
||||
if (proxyId1 > proxyId2)
|
||||
btSwap(proxyId1, proxyId2);
|
||||
#endif
|
||||
|
||||
int index = m_hashTable[hash];
|
||||
|
||||
while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
|
||||
{
|
||||
index = m_next[index];
|
||||
}
|
||||
|
||||
if ( index == BT_NULL_PAIR )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
btAssert(index < m_overlappingPairArray.size());
|
||||
|
||||
return &m_overlappingPairArray[index];
|
||||
}
|
||||
|
||||
virtual bool hasDeferredRemoval()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
|
||||
{
|
||||
m_ghostPairCallback = ghostPairCallback;
|
||||
}
|
||||
*/
|
||||
|
||||
virtual void sortOverlappingPairs(btDispatcher* dispatcher);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
b3AlignedObjectArray<int> m_hashTable;
|
||||
b3AlignedObjectArray<int> m_next;
|
||||
// btOverlappingPairCallback* m_ghostPairCallback;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
///btSortedOverlappingPairCache maintains the objects with overlapping AABB
|
||||
///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
|
||||
class btSortedOverlappingPairCache : public b3OverlappingPairCache
|
||||
{
|
||||
protected:
|
||||
//avoid brute-force finding all the time
|
||||
btBroadphasePairArray m_overlappingPairArray;
|
||||
|
||||
//during the dispatch, check that user doesn't destroy/create proxy
|
||||
bool m_blockedForChanges;
|
||||
|
||||
///by default, do the removal during the pair traversal
|
||||
bool m_hasDeferredRemoval;
|
||||
|
||||
//if set, use the callback instead of the built in filter in needBroadphaseCollision
|
||||
btOverlapFilterCallback* m_overlapFilterCallback;
|
||||
|
||||
// btOverlappingPairCallback* m_ghostPairCallback;
|
||||
|
||||
public:
|
||||
|
||||
btSortedOverlappingPairCache();
|
||||
virtual ~btSortedOverlappingPairCache();
|
||||
|
||||
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
|
||||
|
||||
void* removeOverlappingPair(int proxy0,int proxy1,btDispatcher* dispatcher);
|
||||
|
||||
void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
|
||||
|
||||
btBroadphasePair* addOverlappingPair(int proxy0,int proxy1);
|
||||
|
||||
btBroadphasePair* findPair(int proxy0,int proxy1);
|
||||
|
||||
|
||||
void cleanProxyFromPairs(int proxy,btDispatcher* dispatcher);
|
||||
|
||||
virtual void removeOverlappingPairsContainingProxy(int proxy,btDispatcher* dispatcher);
|
||||
|
||||
|
||||
inline bool needsBroadphaseCollision(int proxy0,int proxy1) const
|
||||
{
|
||||
if (m_overlapFilterCallback)
|
||||
return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
|
||||
|
||||
bool collides = true;//(proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
|
||||
//collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
|
||||
|
||||
return collides;
|
||||
}
|
||||
|
||||
btBroadphasePairArray& getOverlappingPairArray()
|
||||
{
|
||||
return m_overlappingPairArray;
|
||||
}
|
||||
|
||||
const btBroadphasePairArray& getOverlappingPairArray() const
|
||||
{
|
||||
return m_overlappingPairArray;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
btBroadphasePair* getOverlappingPairArrayPtr()
|
||||
{
|
||||
return &m_overlappingPairArray[0];
|
||||
}
|
||||
|
||||
const btBroadphasePair* getOverlappingPairArrayPtr() const
|
||||
{
|
||||
return &m_overlappingPairArray[0];
|
||||
}
|
||||
|
||||
int getNumOverlappingPairs() const
|
||||
{
|
||||
return m_overlappingPairArray.size();
|
||||
}
|
||||
|
||||
btOverlapFilterCallback* getOverlapFilterCallback()
|
||||
{
|
||||
return m_overlapFilterCallback;
|
||||
}
|
||||
|
||||
void setOverlapFilterCallback(btOverlapFilterCallback* callback)
|
||||
{
|
||||
m_overlapFilterCallback = callback;
|
||||
}
|
||||
|
||||
virtual bool hasDeferredRemoval()
|
||||
{
|
||||
return m_hasDeferredRemoval;
|
||||
}
|
||||
|
||||
/* virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
|
||||
{
|
||||
m_ghostPairCallback = ghostPairCallback;
|
||||
}
|
||||
*/
|
||||
virtual void sortOverlappingPairs(btDispatcher* dispatcher);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
|
||||
class btNullPairCache : public b3OverlappingPairCache
|
||||
{
|
||||
|
||||
btBroadphasePairArray m_overlappingPairArray;
|
||||
|
||||
public:
|
||||
|
||||
virtual btBroadphasePair* getOverlappingPairArrayPtr()
|
||||
{
|
||||
return &m_overlappingPairArray[0];
|
||||
}
|
||||
const btBroadphasePair* getOverlappingPairArrayPtr() const
|
||||
{
|
||||
return &m_overlappingPairArray[0];
|
||||
}
|
||||
btBroadphasePairArray& getOverlappingPairArray()
|
||||
{
|
||||
return m_overlappingPairArray;
|
||||
}
|
||||
|
||||
virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual int getNumOverlappingPairs() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void cleanProxyFromPairs(int /*proxy*/,btDispatcher* /*dispatcher*/)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/)
|
||||
{
|
||||
}
|
||||
|
||||
virtual btBroadphasePair* findPair(int /*proxy0*/, int /*proxy1*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual bool hasDeferredRemoval()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
|
||||
// {
|
||||
//
|
||||
// }
|
||||
|
||||
virtual btBroadphasePair* addOverlappingPair(int /*proxy0*/,int /*proxy1*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void* removeOverlappingPair(int /*proxy0*/,int /*proxy1*/,btDispatcher* /*dispatcher*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void removeOverlappingPairsContainingProxy(int /*proxy0*/,btDispatcher* /*dispatcher*/)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void sortOverlappingPairs(btDispatcher* dispatcher)
|
||||
{
|
||||
(void) dispatcher;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //BT_OVERLAPPING_PAIR_CACHE_H
|
||||
|
||||
|
||||
35
src/Bullet3Common/btInt2.h
Normal file
35
src/Bullet3Common/btInt2.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef BT_INT2_H
|
||||
#define BT_INT2_H
|
||||
|
||||
struct btUnsignedInt2
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned int x,y;
|
||||
};
|
||||
struct
|
||||
{
|
||||
unsigned int s[2];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct btInt2
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int x,y;
|
||||
};
|
||||
struct
|
||||
{
|
||||
int s[2];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
82
test/b3DynamicBvhBroadphase/main.cpp
Normal file
82
test/b3DynamicBvhBroadphase/main.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright (c) 2012 Advanced Micro Devices, Inc.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Bullet3Common/b3Vector3.h"
|
||||
#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h"
|
||||
#include "Bullet3Common/b3CommandLineArgs.h"
|
||||
#include "Bullet3Common/b3MinMax.h"
|
||||
#include "Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h"
|
||||
|
||||
int g_nPassed = 0;
|
||||
int g_nFailed = 0;
|
||||
bool g_testFailed = 0;
|
||||
|
||||
#define TEST_INIT g_testFailed = 0;
|
||||
#define TEST_ASSERT(x) if( !(x) ){g_testFailed = 1;}
|
||||
#define TEST_REPORT(testName) printf("[%s] %s\n",(g_testFailed)?"X":"O", testName); if(g_testFailed) g_nFailed++; else g_nPassed++;
|
||||
|
||||
|
||||
|
||||
inline void broadphaseTest()
|
||||
{
|
||||
TEST_INIT;
|
||||
|
||||
b3DynamicBvhBroadphase* bp = new b3DynamicBvhBroadphase(1);
|
||||
|
||||
int group=1;
|
||||
int mask=1;
|
||||
b3Vector3 aabbMin(0,0,0);
|
||||
b3Vector3 aabbMax(1,1,1);
|
||||
int userId = 0;
|
||||
bp->createProxy(aabbMin,aabbMax,userId++,0,group,mask);
|
||||
|
||||
aabbMin.setValue(1,1,1);
|
||||
aabbMax.setValue(2,2,2);
|
||||
|
||||
|
||||
bp->createProxy(aabbMin,aabbMax,userId++,0,group,mask);
|
||||
|
||||
|
||||
bp->calculateOverlappingPairs();
|
||||
|
||||
int numOverlap = bp->getOverlappingPairCache()->getNumOverlappingPairs();
|
||||
|
||||
|
||||
TEST_ASSERT(numOverlap==1);
|
||||
|
||||
delete bp;
|
||||
|
||||
TEST_REPORT( "broadphaseTest" );
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
||||
|
||||
broadphaseTest();
|
||||
|
||||
printf("%d tests passed\n",g_nPassed, g_nFailed);
|
||||
if (g_nFailed)
|
||||
{
|
||||
printf("%d tests failed\n",g_nFailed);
|
||||
}
|
||||
printf("End, press <enter>\n");
|
||||
|
||||
getchar();
|
||||
|
||||
}
|
||||
|
||||
16
test/b3DynamicBvhBroadphase/premake4.lua
Normal file
16
test/b3DynamicBvhBroadphase/premake4.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
|
||||
project ("b3DynamicBvhBroadphase_test")
|
||||
|
||||
language "C++"
|
||||
|
||||
kind "ConsoleApp"
|
||||
targetdir "../../bin"
|
||||
includedirs {"../../src"}
|
||||
|
||||
links {"Bullet3Common", "Bullet3Collision"}
|
||||
|
||||
files {
|
||||
"main.cpp",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user