updated demos -> ALT + mouse uses Maya-style controls, replaced BMF_Fonts by GLDebugFont

fix debug drawing of btMultiSphereShape
added box2d demo
added experimental gpu 2d demo
This commit is contained in:
erwin.coumans
2009-05-09 19:27:14 +00:00
parent 7a210546cf
commit 33029ad996
129 changed files with 8576 additions and 2184 deletions

View File

@@ -0,0 +1,759 @@
/*
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 "BulletMultiThreaded/btGpuDefines.h"
#include "BulletMultiThreaded/btGpuUtilsSharedDefs.h"
#include "BulletMultiThreaded/btGpuUtilsSharedCode.h"
//----------------------------------------------------------------------------------------
#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
#include "btGpuDemoPairCache.h"
#include "btGpuDemoDynamicsWorld.h"
#include "GLDebugFont.h"
#define USE_CUDA_DEMO_PAIR_CASHE 0
#define SPEC_TEST 0
#define OECAKE_LOADER 1
#ifdef _DEBUG
#define LARGE_DEMO 0
// #define LARGE_DEMO 1
#else
#define LARGE_DEMO 1
#endif
#if LARGE_DEMO
///create 512 (8x8x8) dynamic object
// #define ARRAY_SIZE_X 116
// #define ARRAY_SIZE_Y 116
// #define ARRAY_SIZE_X 228
// #define ARRAY_SIZE_Y 228
// #define ARRAY_SIZE_X 256
// #define ARRAY_SIZE_Y 156
#define ARRAY_SIZE_X 50
#define ARRAY_SIZE_Y 100
#define ARRAY_SIZE_Z 1
#else
///create 125 (5x5x5) dynamic object
#define ARRAY_SIZE_X 5
#define ARRAY_SIZE_Y 5
// #define ARRAY_SIZE_Z 5
#define ARRAY_SIZE_Z 1
#endif
//maximum number of objects (and allow user to shoot additional boxes)
#define NUM_SMALL_PROXIES (ARRAY_SIZE_X*ARRAY_SIZE_Y*ARRAY_SIZE_Z)
#define MAX_PROXIES (NUM_SMALL_PROXIES + 1024)
#define MAX_LARGE_PROXIES 0
#define MAX_SMALL_PROXIES (MAX_PROXIES - MAX_LARGE_PROXIES)
///scaling of the objects (0.1 = 20 centimeter boxes )
//#define SCALING 0.1
#define SCALING 1
#define START_POS_X 0
#define START_POS_Y 0
#define START_POS_Z 0
#include "BasicDemo.h"
#include "GlutStuff.h"
///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files.
#include "btBulletDynamicsCommon.h"
#include <stdio.h> //printf debugging
#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
#ifdef BT_USE_CUDA
#include "../Extras/CUDA/btCudaBroadphase.h"
#else
#include "BulletMultiThreaded/btGpu3DGridBroadphase.h"
#endif
btScalar gTimeStep = btScalar(1./60.);
bool gbDrawBatches = false;
int gSelectedBatch = CUDA_DEMO_DYNAMICS_WORLD_MAX_BATCHES;
#ifdef BT_USE_CUDA
bool gUseCPUSolver = false;
#else
bool gUseCPUSolver = true;
#endif //BT_USE_CUDA
#include "oecakeLoader.h"
class BasicDemoOecakeLoader : public BasicOECakeReader
{
BasicDemo* m_demo;
public:
BasicDemoOecakeLoader(BasicDemo* demo)
:m_demo(demo)
{
}
virtual void createBodyForCompoundShape(btCompoundShape* compoundTmpShape,bool addConstraint, const btTransform& worldTransform, btScalar mass)
{
btDefaultMotionState* myMotionState= 0;
btVector3 inertiaHalfExtents;
btVector3 aabbMin,aabbMax;
compoundTmpShape->getAabb(btTransform::getIdentity(),aabbMin,aabbMax);
inertiaHalfExtents = (aabbMax-aabbMin)*0.5;
int numSpheres = compoundTmpShape->getNumChildShapes();
btAssert(numSpheres>0);
if (numSpheres>8)
{
printf("error: exceeded 8 spheres\n");
return;
}
btVector3* positions = new btVector3[numSpheres];
btScalar* radii = new btScalar[numSpheres];
for (int i=0;i<numSpheres;i++)
{
btAssert(compoundTmpShape->getChildShape(i)->getShapeType()== SPHERE_SHAPE_PROXYTYPE);
btSphereShape* sphereShape = (btSphereShape*)compoundTmpShape->getChildShape(i);
radii[i]=sphereShape->getRadius();
positions[i] = compoundTmpShape->getChildTransform(i).getOrigin();
}
btMultiSphereShape* multiSphere = new btMultiSphereShape(inertiaHalfExtents,positions,radii,numSpheres);
btVector3 localInertia(0,0,0);
if (mass)
{
myMotionState = new btDefaultMotionState(worldTransform);
multiSphere->calculateLocalInertia(mass,localInertia);
}
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btRigidBody* body = new btRigidBody(mass,myMotionState,multiSphere,localInertia);
body->setLinearFactor(btVector3(1,1,0));
body->setAngularFactor(btVector3(0,0,1));
body->setWorldTransform(worldTransform);
m_demo->getDynamicsWorld()->addRigidBody(body);
if (addConstraint)
{
btVector3 pivotInA(0,0,0);
btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*body,pivotInA);
m_demo->getDynamicsWorld()->addConstraint(p2p);
}
}
};
void BasicDemo::clientMoveAndDisplay()
{
updateCamera();
glDisable(GL_LIGHTING);
glColor3f(1.f, 1.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_TEXTURE_2D); // we always draw wireframe in this demo
//simple dynamics world doesn't handle fixed-time-stepping
float ms = getDeltaTimeMicroseconds();
///step the simulation
if (m_dynamicsWorld)
{
#if USE_CUDA_DEMO_PAIR_CASHE
btCudaDemoPairCache* pc = (btCudaDemoPairCache*)m_dynamicsWorld->getPairCache();
pc->m_numSmallProxies = m_dynamicsWorld->getNumCollisionObjects(); // - 1; // exclude floor
#endif
m_dynamicsWorld->stepSimulation(gTimeStep,0);//ms / 1000000.f);
//optional but useful: debug drawing
m_dynamicsWorld->debugDrawWorld();
}
renderme();
ms = getDeltaTimeMicroseconds();
glFlush();
glutSwapBuffers();
}
void BasicDemo::displayCallback(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderme();
//optional but useful: debug drawing to detect problems
if (m_dynamicsWorld)
m_dynamicsWorld->debugDrawWorld();
glFlush();
glutSwapBuffers();
}
#define POS_OFFS_X (ARRAY_SIZE_X * SCALING + 20)
#define POS_OFFS_Y (ARRAY_SIZE_Y * SCALING + 10)
#define POS_OFFS_Z (ARRAY_SIZE_Z * SCALING)
#if OECAKE_LOADER
btVector3 gWorldMin(-200, 0, 0);
btVector3 gWorldMax( 200, 200, 0);
#else
btVector3 gWorldMin(-POS_OFFS_X, -POS_OFFS_Y, -POS_OFFS_Z);
btVector3 gWorldMax( POS_OFFS_X, POS_OFFS_Y, POS_OFFS_Z);
#endif
//btCudaDemoPairCache* gPairCache;
btOverlappingPairCache* gPairCache;
void BasicDemo::initPhysics()
{
setTexturing(false);
setShadows(false);
#if OECAKE_LOADER
setCameraDistance(80.);
m_cameraTargetPosition.setValue(50, 10, 0);
#else
#if LARGE_DEMO
setCameraDistance(btScalar(SCALING*100.));
#else
setCameraDistance(btScalar(SCALING*20.));
#endif
m_cameraTargetPosition.setValue(START_POS_X, -START_POS_Y-20, START_POS_Z);
#endif
m_azi = btScalar(0.f);
m_ele = btScalar(0.f);
///collision configuration contains default setup for memory, collision setup
btDefaultCollisionConstructionInfo dci;
dci.m_defaultMaxPersistentManifoldPoolSize=50000;
dci.m_defaultMaxCollisionAlgorithmPoolSize=50000;
m_collisionConfiguration = new btDefaultCollisionConfiguration(dci);
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
m_dispatcher->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE,BOX_SHAPE_PROXYTYPE,new btEmptyAlgorithm::CreateFunc);
m_dispatcher->setNearCallback(cudaDemoNearCallback);
#if USE_CUDA_DEMO_PAIR_CASHE
gPairCache = new (btAlignedAlloc(sizeof(btCudaDemoPairCache),16)) btCudaDemoPairCache(MAX_PROXIES, 24, MAX_SMALL_PROXIES);
#else
gPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16))btHashedOverlappingPairCache();
#endif
btVector3 numOfCells = (gWorldMax - gWorldMin) / (2. * SCALING);
int numOfCellsX = (int)numOfCells[0];
int numOfCellsY = (int)numOfCells[1];
int numOfCellsZ = (int)numOfCells[2];
// m_broadphase = new btAxisSweep3(gWorldMin, gWorldMax, MAX_PROXIES,gPairCache);
m_broadphase = new btDbvtBroadphase(gPairCache);
// m_broadphase = new btGpu3DGridBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,24,24);
// m_broadphase = new btCudaBroadphase(gPairCache, gWorldMin, gWorldMax,numOfCellsX, numOfCellsY, numOfCellsZ,MAX_SMALL_PROXIES,10,24,24);
///the default constraint solver
m_solver = new btSequentialImpulseConstraintSolver();
btGpuDemoDynamicsWorld* pDdw = new btGpuDemoDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration, MAX_PROXIES);
m_dynamicsWorld = pDdw;
pDdw->getSimulationIslandManager()->setSplitIslands(true);
pDdw->setObjRad(SCALING);
pDdw->setWorldMin(gWorldMin);
pDdw->setWorldMax(gWorldMax);
// gUseCPUSolver = true;
pDdw->setUseCPUSolver(gUseCPUSolver);
// m_dynamicsWorld->setGravity(btVector3(0,0,0));
m_dynamicsWorld->setGravity(btVector3(0,-10.,0));
m_dynamicsWorld->getSolverInfo().m_numIterations = 4;
{
//create a few dynamic rigidbodies
// Re-using the same collision is better for memory usage and performance
//btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,0.1));//SCALING*1));
// btCollisionShape* colShape = new btBox2dShape(btVector3(SCALING*.7,SCALING*.7,0.1));//SCALING*1));
#define SPRADIUS btScalar(SCALING*0.1f)
#define SPRPOS btScalar(SCALING*0.05f)
static btVector3 sSphPos[8];
for (int k=0;k<8;k++)
{
sSphPos[k].setValue((k-4)*0.25*SCALING,0,0);
}
btVector3 inertiaHalfExtents(SPRADIUS, SPRADIUS, SPRADIUS);
static btScalar sSphRad[8] =
{
// SPRADIUS, SPRADIUS, SPRADIUS, SPRADIUS,SPRADIUS, SPRADIUS, SPRADIUS, 0.3
SPRADIUS, SPRADIUS, SPRADIUS, SPRADIUS,SPRADIUS, SPRADIUS, SPRADIUS, SPRADIUS
};
// sSphPos[0].setX(sSphPos[0].getX()-0.15);
#undef SPR
btMultiSphereShape* colShape[2];
colShape[0] = new btMultiSphereShape(inertiaHalfExtents, sSphPos, sSphRad, 8);
colShape[1] = new btMultiSphereShape(inertiaHalfExtents, sSphPos, sSphRad, 2);
//btCollisionShape* colShape = new btSphereShape(btScalar(1.));
m_collisionShapes.push_back(colShape[0]);
m_collisionShapes.push_back(colShape[1]);
/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();
btScalar mass(1.f);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
#if OECAKE_LOADER
BasicDemoOecakeLoader loader(this);
if (!loader.processFile("test1.oec"))
{
loader.processFile("../../test1.oec");
}
#else
#if (!SPEC_TEST)
float start_x = START_POS_X - ARRAY_SIZE_X * SCALING;
float start_y = START_POS_Y - ARRAY_SIZE_Y * SCALING;
float start_z = START_POS_Z - ARRAY_SIZE_Z * SCALING;
int collisionShapeIndex = 0;
for (int k=0;k<ARRAY_SIZE_Y;k++)
{
for (int i=0;i<ARRAY_SIZE_X;i++)
{
for(int j = 0;j<ARRAY_SIZE_Z;j++)
{
float offs = (2. * (float)rand() / (float)RAND_MAX - 1.f) * 0.05f;
startTransform.setOrigin(SCALING*btVector3(
2.0*SCALING*i + start_x + offs,
2.0*SCALING*k + start_y + offs,
2.0*SCALING*j + start_z));
if (isDynamic)
colShape[collisionShapeIndex]->calculateLocalInertia(mass,localInertia);
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
//btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape[collisionShapeIndex],localInertia);
collisionShapeIndex = 1 - collisionShapeIndex;
rbInfo.m_startWorldTransform=startTransform;
btRigidBody* body = new btRigidBody(rbInfo);
m_dynamicsWorld->addRigidBody(body);
}
}
}
#else//SPEC_TEST
// narrowphase test - 2 bodies at the same position
float start_x = START_POS_X;
// float start_y = START_POS_Y;
float start_y = gWorldMin[1] + SCALING * 0.7f + 5.f;
float start_z = START_POS_Z;
startTransform.setOrigin(SCALING*btVector3(start_x,start_y,start_z));
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,0,colShape[0],localInertia);
rbInfo.m_startWorldTransform=startTransform;
btRigidBody* body = new btRigidBody(rbInfo);
m_dynamicsWorld->addRigidBody(body);
btPoint2PointConstraint * p2pConstr = new btPoint2PointConstraint(*body, btVector3(1., 0., 0.));
m_dynamicsWorld->addConstraint(p2pConstr);
startTransform.setOrigin(SCALING*btVector3(start_x-2.f, start_y,start_z));
rbInfo.m_startWorldTransform=startTransform;
btRigidBody* body1 = new btRigidBody(rbInfo);
m_dynamicsWorld->addRigidBody(body1);
p2pConstr = new btPoint2PointConstraint(*body, *body1, btVector3(-1., 0., 0.), btVector3(1., 0., 0.));
m_dynamicsWorld->addConstraint(p2pConstr);
#endif//SPEC_TEST
#endif //OE_CAKE_LOADER
}
// now set Ids used by collision detector and constraint solver
int numObjects = m_dynamicsWorld->getNumCollisionObjects();
btCollisionObjectArray& collisionObjects = m_dynamicsWorld->getCollisionObjectArray();
for(int i = 0; i < numObjects; i++)
{
btCollisionObject* colObj = collisionObjects[i];
colObj->setCompanionId(i+1); // 0 reserved for the "world" object
btCollisionShape* pShape = colObj->getCollisionShape();
int shapeType = pShape->getShapeType();
if(shapeType == MULTI_SPHERE_SHAPE_PROXYTYPE)
{
btMultiSphereShape* pMs = (btMultiSphereShape*)pShape;
int numSpheres = pMs->getSphereCount();
pDdw->addMultiShereObject(numSpheres, i + 1);
for(int j = 0; j < numSpheres; j++)
{
btVector3 sphPos = pMs->getSpherePosition(j);
float sphRad = pMs->getSphereRadius(j);
pDdw->addSphere(sphPos, sphRad);
}
}
else
{
btAssert(0);
}
}
#if OECAKE_LOADER
clientResetScene();
#endif
}
void BasicDemo::clientResetScene()
{
DemoApplication::clientResetScene();
#if OECAKE_LOADER
return;
#endif
#if SPEC_TEST
{
float start_x = START_POS_X;
// float start_y = START_POS_Y;
float start_y = gWorldMin[1] + SCALING * 0.7f + 5.f;
float start_z = START_POS_Z;
int numObjects = m_dynamicsWorld->getNumCollisionObjects();
btCollisionObjectArray& collisionObjects = m_dynamicsWorld->getCollisionObjectArray();
btTransform startTransform;
startTransform.setIdentity();
for(int n = 0; n < numObjects; n++)
{
btCollisionObject* colObj = collisionObjects[n];
btRigidBody* rb = btRigidBody::upcast(colObj);
if(!n)
{
startTransform.setOrigin(SCALING*btVector3(start_x,start_y,start_z));
}
else
{
// startTransform.setOrigin(SCALING*btVector3(start_x+0.1f,start_y+SCALING * 0.7f * 2.f, start_z));
startTransform.setOrigin(SCALING*btVector3(start_x-2.f,start_y, start_z));
}
rb->setCenterOfMassTransform(startTransform);
}
return;
}
#endif
// we don't use motionState, so reset transforms here
int numObjects = m_dynamicsWorld->getNumCollisionObjects();
btCollisionObjectArray& collisionObjects = m_dynamicsWorld->getCollisionObjectArray();
float start_x = START_POS_X - ARRAY_SIZE_X * SCALING;
float start_y = START_POS_Y - ARRAY_SIZE_Y * SCALING;
float start_z = START_POS_Z - ARRAY_SIZE_Z * SCALING;
btTransform startTransform;
startTransform.setIdentity();
for(int n = 0; n < numObjects; n++)
{
btCollisionObject* colObj = collisionObjects[n];
colObj->setCompanionId(n);
btRigidBody* rb = btRigidBody::upcast(colObj);
int offs = ARRAY_SIZE_X * ARRAY_SIZE_Z;
int indx = n;
int ky = indx / offs;
indx -= ky * offs;
int kx = indx / ARRAY_SIZE_Z;
indx -= kx * ARRAY_SIZE_Z;
int kz = indx;
startTransform.setOrigin(SCALING*btVector3(
2.0*SCALING*kx + start_x,
2.0*SCALING*ky + start_y,
2.0*SCALING*kz + start_z));
rb->setCenterOfMassTransform(startTransform);
}
}
void BasicDemo::exitPhysics()
{
//cleanup in the reverse order of creation/initialization
//remove the rigidbodies from the dynamics world and delete them
int i;
for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
{
btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
delete body->getMotionState();
}
m_dynamicsWorld->removeCollisionObject( obj );
delete obj;
}
//delete collision shapes
for (int j=0;j<m_collisionShapes.size();j++)
{
btCollisionShape* shape = m_collisionShapes[j];
delete shape;
}
delete m_dynamicsWorld;
delete m_solver;
delete m_broadphase;
delete m_dispatcher;
delete m_collisionConfiguration;
}
void BasicDemo::keyboardCallback(unsigned char key, int x, int y)
{
(void)x;
(void)y;
switch (key)
{
case 'q' :
exitPhysics();
exit(0);
break;
case 'c' :
{
gbDrawBatches = !gbDrawBatches;
break;
}
case 'b' :
{
gSelectedBatch++;
gSelectedBatch %= (CUDA_DEMO_DYNAMICS_WORLD_MAX_BATCHES + 1);
break;
}
case 'u' :
{
btGpuDemoDynamicsWorld* pDdw = (btGpuDemoDynamicsWorld*)m_dynamicsWorld;
gUseCPUSolver = !gUseCPUSolver;
pDdw->setUseCPUSolver(gUseCPUSolver);
break;
}
default :
{
DemoApplication::keyboardCallback(key, x, y);
}
break;
}
if(key == ' ')
{
#if USE_CUDA_DEMO_PAIR_CASHE
((btCudaDemoPairCache*)gPairCache)->reset();
#endif
}
}
#define BATCH_NUM_COLORS 12
const float cBatchColorTab[BATCH_NUM_COLORS * 3] =
{
1.f, 0.f, 0.f,
0.f, 1.f, 0.f,
0.f, 0.f, 1.f,
1.f, 1.f, 0.f,
0.f, 1.f, 1.f,
1.f, 0.f, 1.f,
1.f, .5f, 0.f,
.5f, 1.f, 0.f,
0.f, 1.f, .5f,
0.f, .5f, 1.f,
.5f, 0.f, 1.f,
1.f, 0.f, .5f
};
void BasicDemo::DrawConstraintInfo()
{
int fontW = 10; // hack, could be changed
int fontH = 14; // hack, could be changed
char buf[32];
float xOffs;
float yOffs = fontH * 2;
glDisable(GL_LIGHTING);
glColor3f(1, 1, 1);
sprintf(buf,"solver on %s", gUseCPUSolver ? "CPU" : "CUDA");
xOffs = m_glutScreenWidth - (strlen(buf) + 1) * fontW;
GLDebugDrawString(xOffs, yOffs,buf);
yOffs += fontH;
btGpuDemoDynamicsWorld* cddw = (btGpuDemoDynamicsWorld*)m_dynamicsWorld;
for(int i = 0; i < CUDA_DEMO_DYNAMICS_WORLD_MAX_BATCHES; i++)
{
const float* pCol = cBatchColorTab + i * 3;
glColor3f(pCol[0], pCol[1], pCol[2]);
sprintf(buf,"%2d : %5d", i, cddw->m_numInBatches[i]);
xOffs = m_glutScreenWidth - (strlen(buf) + 1) * fontW;
GLDebugDrawString(xOffs, yOffs,buf);
yOffs += fontH;
}
}
void BasicDemo::renderme()
{
renderscene(0);
if(gbDrawBatches)
{
((btGpuDemoDynamicsWorld*)m_dynamicsWorld)->debugDrawConstraints(gSelectedBatch, cBatchColorTab);
}
// if (0)
if ((m_debugMode & btIDebugDraw::DBG_NoHelpText)==0)
{
setOrthographicProjection();
int xOffset = 10.f;
int yStart = 20.f;
int yIncr = 20.f;
showProfileInfo(xOffset, yStart, yIncr);
DrawConstraintInfo();
outputDebugInfo(xOffset, yStart, yIncr);
resetPerspectiveProjection();
}
}
extern int gNumClampedCcdMotions;
#define SHOW_NUM_DEEP_PENETRATIONS 1
#ifdef SHOW_NUM_DEEP_PENETRATIONS
extern int gNumDeepPenetrationChecks;
extern int gNumSplitImpulseRecoveries;
extern int gNumGjkChecks;
extern int gNumAlignedAllocs;
extern int gNumAlignedFree;
extern int gTotalBytesAlignedAllocs;
#endif //
void BasicDemo::outputDebugInfo(int & xOffset,int & yStart, int yIncr)
{
char buf[124];
glDisable(GL_LIGHTING);
glColor3f(0, 0, 0);
sprintf(buf,"mouse move+buttons to interact");
GLDebugDrawString(xOffset,yStart,buf);
yStart += yIncr;
sprintf(buf,"space to reset");
GLDebugDrawString(xOffset,yStart,buf);
yStart += yIncr;
sprintf(buf,"cursor keys and z,x to navigate");
GLDebugDrawString(xOffset,yStart,buf);
yStart += yIncr;
sprintf(buf,"i to toggle simulation, s single step");
GLDebugDrawString(xOffset,yStart,buf);
yStart += yIncr;
sprintf(buf,"q to quit");
GLDebugDrawString(xOffset,yStart,buf);
yStart += yIncr;
sprintf(buf,"h to toggle help text");
GLDebugDrawString(xOffset,yStart,buf);
yStart += yIncr;
sprintf(buf,"p to toggle profiling (+results to file)");
GLDebugDrawString(xOffset,yStart,buf);
yStart += yIncr;
sprintf(buf,"c to toggle constraint drawing");
GLDebugDrawString(xOffset,yStart,buf);
yStart += yIncr;
sprintf(buf,"b to draw single constraint batch");
GLDebugDrawString(xOffset,yStart,buf);
yStart += yIncr;
sprintf(buf,"u to toggle between CPU and CUDA solvers");
GLDebugDrawString(xOffset,yStart,buf);
yStart += yIncr;
sprintf(buf,"d to toggle between different batch builders");
GLDebugDrawString(xOffset,yStart,buf);
yStart += yIncr;
if (getDynamicsWorld())
{
sprintf(buf,"# objects = %d",getDynamicsWorld()->getNumCollisionObjects());
GLDebugDrawString(xOffset,yStart,buf);
yStart += yIncr;
sprintf(buf,"# pairs = %d",getDynamicsWorld()->getBroadphase()->getOverlappingPairCache()->getNumOverlappingPairs());
GLDebugDrawString(xOffset,yStart,buf);
yStart += yIncr;
}
} // BasicDemo::outputDebugInfo()

View File

@@ -0,0 +1,96 @@
/*
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 BASIC_DEMO_H
#define BASIC_DEMO_H
#include "DemoApplication.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
#ifdef BT_USE_CUDA
#include "btCudaDemoPairCache.h"
#include <vector_types.h>
#endif //BT_USE_CUDA
class btBroadphaseInterface;
class btCollisionShape;
class btOverlappingPairCache;
class btCollisionDispatcher;
class btConstraintSolver;
struct btCollisionAlgorithmCreateFunc;
class btDefaultCollisionConfiguration;
#include "GlutDemoApplication.h"
///BasicDemo is good starting point for learning the code base and porting.
class BasicDemo : public GlutDemoApplication
{
//keep the collision shapes, for deletion/cleanup
btAlignedObjectArray<btCollisionShape*> m_collisionShapes;
btBroadphaseInterface* m_broadphase;
btCollisionDispatcher* m_dispatcher;
btConstraintSolver* m_solver;
btDefaultCollisionConfiguration* m_collisionConfiguration;
int m_mouseButtons;
int m_mouseOldX;
int m_mouseOldY;
public:
BasicDemo()
{
}
virtual ~BasicDemo()
{
exitPhysics();
}
void initPhysics();
void exitPhysics();
virtual void clientMoveAndDisplay();
virtual void displayCallback();
virtual void keyboardCallback(unsigned char key, int x, int y);
virtual void clientResetScene();
static DemoApplication* Create()
{
BasicDemo* demo = new BasicDemo;
demo->myinit();
demo->initPhysics();
demo->m_mouseButtons = 0;
demo->m_mouseOldX = 0;
demo->m_mouseOldY = 0;
return demo;
}
void DrawConstraintInfo();
void outputDebugInfo(int & xOffset,int & yStart, int yIncr);
virtual void renderme();
};
#endif //BASIC_DEMO_H

View File

@@ -0,0 +1,26 @@
# This is basically the overall name of the project in Visual Studio this is the name of the Solution File
# For every executable you have with a main method you should have an add_executable line below.
# For every add executable line you should list every .cpp and .h file you have associated with that executable.
# This is the variable for Windows. I use this to define the root of my directory structure.
SET(GLUT_ROOT ${BULLET_PHYSICS_SOURCE_DIR}/Glut)
# You shouldn't have to modify anything below this line
########################################################
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL }
)
LINK_LIBRARIES(
OpenGLSupport BulletDynamics BulletCollision LinearMath ${GLUT_glut_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}
)
ADD_EXECUTABLE(AppBasicDemo
main.cpp
BasicDemo.cpp
)

3
Demos/Gpu2dDemo/Jamfile Normal file
View File

@@ -0,0 +1,3 @@
SubDir TOP Demos BasicDemo ;
BulletDemo BasicDemo : [ Wildcard *.h *.cpp ] ;

View File

@@ -0,0 +1,5 @@
noinst_PROGRAMS=BasicDemo
BasicDemo_SOURCES=BasicDemo.cpp BasicDemo.h main.cpp
BasicDemo_CXXFLAGS=-I@top_builddir@/src -I@top_builddir@/Demos/OpenGL $(CXXFLAGS)
BasicDemo_LDADD=-L../OpenGL -lbulletopenglsupport -L../../src -lbulletdynamics -lbulletcollision -lbulletmath @opengl_LIBS@

View File

@@ -0,0 +1,33 @@
/*
Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
Copyright (C) 2006, 2007 Sony Computer Entertainment 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 "LinearMath/btQuickprof.h"
//----------------------------------------------------------------------------------------
#include "LinearMath/btScalar.h"
#include "btGpuDemo2dSharedTypes.h"
//----------------------------------------------------------------------------------------
#include "BulletMultiThreaded/btGpuDefines.h"
#include "BulletMultiThreaded/btGpuUtilsSharedDefs.h"
#include "btGpuDemo2dSharedCode.h"
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

View File

@@ -0,0 +1,46 @@
/*
Impulse based Rigid body simulation using CUDA
Copyright (c) 2007 Takahiro Harada http://www.iii.u-tokyo.ac.jp/~takahiroharada/projects/impulseCUDA.html
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 <cstdlib>
#include <cstdio>
#include <string.h>
#include "../../Extras/CUDA/cutil_math.h"
#include "math_constants.h"
#include <vector_types.h>
//----------------------------------------------------------------------------------------
#include "../../Extras/CUDA/btCudaDefines.h"
//----------------------------------------------------------------------------------------
#include "../../src/BulletMultiThreaded/btGpuUtilsSharedDefs.h"
#include "btGpuDemo2dSharedTypes.h"
#include "btGpuDemo2dSharedDefs.h"
//----------------------------------------------------------------------------------------
texture<float4, 1, cudaReadModeElementType> posTex;
//----------------------------------------------------------------------------------------
#include "btGpuDemo2dSharedCode.h"
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------

View File

@@ -0,0 +1,472 @@
/*
Impulse based Rigid body simulation using CUDA
Copyright (c) 2007 Takahiro Harada http://www.iii.u-tokyo.ac.jp/~takahiroharada/projects/impulseCUDA.html
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.
*/
//----------------------------------------------------------------------------------------
#define USE_FRICTION 1
#define FRICTION_BOX_GROUND_FACT 0.05f
#define FRICTION_BOX_BOX_FACT 0.05f
#define USE_CENTERS 1
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//---------- C o n s t r a i n t s o l v e r d e m o ----------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
#define MAX_VTX_PER_OBJ 8
/*
BT_GPU___device__ void kill_me()
{
char* badPtr = (char*)0xFFFFFFFF;
*badPtr = 10;
}
*/
BT_GPU___global__ void clearAccumulationOfLambdaDtD(float* lambdaDtBox, int numConstraints, int numContPoints)
{
int index = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x;
if(index < numConstraints)
{
for(int i=0; i < numContPoints; i++)
lambdaDtBox[numContPoints * index + i] = 0;
}
}
#define SPHERE_FACT 1.0f
BT_GPU___device__ void testSphSph(float3 aPos, float3 bPos, float radA, float radB, float4* pOut)
{
float3 del = bPos - aPos;
float dist = BT_GPU_dot(del, del);
dist = sqrtf(dist);
float maxD = radA + radB;
if(dist > maxD)
{
return;
}
float penetration = (radA + radB - dist) * SPHERE_FACT;
// float penetration = (dist - radA - radB) * SPHERE_FACT;
float3 normal;
if(dist > 0.f)
{
float fact = -1.0f/dist;
// float fact = 1.0f/dist;
normal = del * fact;
}
else
{
normal = BT_GPU_make_float3(1.f, 0.f, 0.f);
}
// float3 contact = (bPos + aPos + normal * (radB - radA)) * 0.5f;
float3 contact = aPos - normal * radA;
// now add point
int numPoints = 0;
for(int i = 0; i < MAX_VTX_PER_OBJ; i++)
{
if(pOut[i*2].w >= 0.f)
{
numPoints++;
}
}
if(numPoints < MAX_VTX_PER_OBJ)
{
pOut[numPoints * 2] = BT_GPU_make_float42(contact, penetration);
pOut[numPoints * 2 + 1] = BT_GPU_make_float42(normal, 0.f);
}
} // testSphSph()
BT_GPU___global__ void setConstraintDataD(int2 *constraints,
int numConstraints,
float4 *pos,
float *rotation,
char* shapes,
int2* shapeIds,
btCudaPartProps pProp,
float4 *contact)
{
int idx = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x;
int aId,bId;
float3 aPos,bPos;
// float positionConstraint;
// float3 normal;
float aRot,bRot;
float sideLength2 = pProp.m_diameter*0.5f/sqrt(2.0f);
if(idx < numConstraints)
{
aId=constraints[idx].x;
bId=constraints[idx].y;
aPos=BT_GPU_make_float34(BT_GPU_FETCH4(pos,aId));
bPos=BT_GPU_make_float34(BT_GPU_FETCH4(pos,bId));
aRot= rotation[aId];
bRot= rotation[bId];
float cosA = cosf(aRot);
float sinA = sinf(aRot);
float cosB = cosf(bRot);
float sinB = sinf(bRot);
float4* shapeA = (float4*)(shapes + shapeIds[aId].x);
int numSphA = shapeIds[aId].y;
float4* shapeB = (float4*)(shapes + shapeIds[bId].x);
int numSphB = shapeIds[bId].y;
int i, j;
float3 ai = BT_GPU_make_float3(cosA, sinA, 0.f);
float3 aj = BT_GPU_make_float3(-sinA, cosA, 0.f);
float3 bi = BT_GPU_make_float3(cosB, sinB, 0.f);
float3 bj = BT_GPU_make_float3(-sinB, cosB, 0.f);
float4* pOut = contact + idx * MAX_VTX_PER_OBJ * 2;
for(i = 0; i < MAX_VTX_PER_OBJ; i++)
{
pOut[i * 2].w = -1.f;
pOut[i * 2 + 1].w = 0.f;
}
for(i = 0; i < numSphA; i++)
{
float3 va = aPos;
va += ai * shapeA[i].x;
va += aj * shapeA[i].y;
float radA = shapeA[i].w;
for(j = 0; j < numSphB; j++)
{
float3 vb = bPos;
vb += bi * shapeB[j].x;
vb += bj * shapeB[j].y;
float radB = shapeB[j].w;
testSphSph(va, vb, radA, radB, pOut);
}
}
}
}
BT_GPU___device__ float computeImpulse1(float3 rVel,
float positionConstraint,
float3 cNormal,
float dt)
{
const float collisionConstant = 0.1f;
const float baumgarteConstant = 0.5f;
const float penetrationError = 0.02f;
float lambdaDt=0;
float3 impulse=BT_GPU_make_float3(0.f,0.f,0.f);
if(positionConstraint > 0)
return lambdaDt;
positionConstraint = min(0.0f,positionConstraint+penetrationError);
lambdaDt = -(BT_GPU_dot(cNormal,rVel)*(1+collisionConstant));
lambdaDt -= (baumgarteConstant/dt*positionConstraint);
return lambdaDt;
}
BT_GPU___global__ void collisionWithWallBoxD(float4 *pos,
float4 *vel,
float *rotation,
float *angVel,
char* shapes,
int2* shapeIds,
btCudaPartProps pProp,
btCudaBoxProps gProp,
int nParticles,
float dt)
{
int idx = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x;
float3 aPos;
float aRot;
float positionConstraint;
float3 impulse;
if((idx > 0) && idx < nParticles)
{
aPos=BT_GPU_make_float34(BT_GPU_FETCH4(pos,idx));
aRot=rotation[idx];
float4* shape = (float4*)(shapes + shapeIds[idx].x);
int numSph = shapeIds[idx].y;
float cosA = cosf(aRot);
float sinA = sinf(aRot);
float3 ai = BT_GPU_make_float3(cosA, sinA, 0.f);
float3 aj = BT_GPU_make_float3(-sinA, cosA, 0.f);
for(int iVtx=0;iVtx < numSph; iVtx++){
float3 aVel = BT_GPU_make_float3(vel[idx].x, vel[idx].y, vel[idx].z);
float aAngVel = angVel[idx];
float3 rerVertex = ai * shape[iVtx].x;
rerVertex += aj * shape[iVtx].y;
float3 vPos = aPos + rerVertex;
float rad = shape[iVtx].w;
float3 vVel =aVel+BT_GPU_cross(BT_GPU_make_float3(0.0f,0.0f,aAngVel),rerVertex);
float restitution=1.0;
{
positionConstraint =vPos.y - rad - gProp.minY;
impulse =BT_GPU_make_float31(0.0f);
if(positionConstraint < 0){
float3 groundNormal;
groundNormal = BT_GPU_make_float3(0.0f,1.0f,0.0f);
impulse =groundNormal*
restitution * computeImpulse1(vVel,positionConstraint,
groundNormal,
dt);
#if USE_FRICTION // only with ground for now
float3 lat_vel = vVel - groundNormal * BT_GPU_dot(groundNormal,vVel);
float lat_vel_len = BT_GPU_dot(lat_vel, lat_vel);
if (lat_vel_len > 0)
{
lat_vel_len = sqrtf(lat_vel_len);
lat_vel *= 1.f/lat_vel_len;
impulse -= lat_vel * BT_GPU_dot(lat_vel, vVel) * FRICTION_BOX_GROUND_FACT;
}
#endif //USE_FRICTION
vel[idx] += BT_GPU_make_float42(impulse,0.0f);
angVel[idx] += BT_GPU_cross(rerVertex,impulse).z;
}
}
{
positionConstraint =vPos.x - rad - gProp.minX;
impulse =BT_GPU_make_float31(0.0f);
if(positionConstraint < 0){
impulse =BT_GPU_make_float3(1.0f,0.0f,0.0f)*
computeImpulse1(vVel,positionConstraint,
BT_GPU_make_float3(1.0f,0.0f,0.0f),
dt);
vel[idx] += BT_GPU_make_float42(impulse,0.0f);
angVel[idx] += BT_GPU_cross(rerVertex,impulse).z;
}
}
{
positionConstraint = gProp.maxX - vPos.x - rad;
impulse =BT_GPU_make_float31(0.0f);
if(positionConstraint < 0){
impulse =BT_GPU_make_float3(-1.0f,0.0f,0.0f)*
computeImpulse1(vVel,positionConstraint,
BT_GPU_make_float3(-1.0f,0.0f,0.0f),
dt);
vel[idx] += BT_GPU_make_float42(impulse,0.0f);
angVel[idx] += BT_GPU_cross(rerVertex,impulse).z;
}
}
}
}
}
BT_GPU___device__ void collisionResolutionBox( int constrId,
int2* constraints,
float4 *pos,
float4 *vel,
float *rotation,
float *angularVel,
float *lambdaDtBox,
float4* contact,
btCudaPartProps pProp,
float dt)
{
#if 1
float3 relVel;
float3 impulse;
float lambdaDt;
float positionConstraint;
int aId=constraints[constrId].x;
int bId=constraints[constrId].y;
float3 aPos=BT_GPU_make_float34(BT_GPU_FETCH4(pos,aId));
float3 bPos=BT_GPU_make_float34(BT_GPU_FETCH4(pos,bId));
float aRot=rotation[aId];
float bRot=rotation[bId];
float3 aVel=BT_GPU_make_float34(vel[aId]);
float3 bVel=BT_GPU_make_float34(vel[bId]);
float aAngVel=angularVel[aId];
float bAngVel=angularVel[bId];
float4* pCont = contact + constrId * MAX_VTX_PER_OBJ * 2;
// test Vertices in A to Box B
for(int iVtx=0;iVtx<MAX_VTX_PER_OBJ;iVtx++){
float3 contactPoint = BT_GPU_make_float34(pCont[iVtx * 2]);
contactPoint = contactPoint - aPos;
positionConstraint = pCont[iVtx * 2].w;
if(positionConstraint >= 0)
{
float3 contactNormal = BT_GPU_make_float34(pCont[iVtx * 2 + 1]);
relVel=(aVel+BT_GPU_cross(BT_GPU_make_float3(0.0f,0.0f,aAngVel),
contactPoint))
-(bVel+BT_GPU_cross(BT_GPU_make_float3(0.0f,0.0f,bAngVel),
contactPoint+aPos-bPos));
lambdaDt= computeImpulse1(relVel,-positionConstraint,
contactNormal,dt);
{
float rLambdaDt=lambdaDtBox[(MAX_VTX_PER_OBJ)*(2*constrId)+iVtx];
float pLambdaDt=rLambdaDt;
rLambdaDt=max(pLambdaDt+lambdaDt,0.0f);
lambdaDt=rLambdaDt-pLambdaDt;
lambdaDtBox[(MAX_VTX_PER_OBJ)*(2*constrId)+iVtx]=rLambdaDt;
}
impulse= contactNormal*lambdaDt*0.5;
#if USE_FRICTION
if(pCont[iVtx * 2 + 1].w <= 0)
{
float3 lat_vel = relVel - contactNormal * BT_GPU_dot(contactNormal, relVel);
float lat_vel_len = BT_GPU_dot(lat_vel, lat_vel);
if (lat_vel_len > 0)
{
lat_vel_len = sqrtf(lat_vel_len);
lat_vel *= 1.f/lat_vel_len;
impulse -= lat_vel * BT_GPU_dot(lat_vel , relVel) * FRICTION_BOX_BOX_FACT;
}
}
#endif //USE_FRICTION
if(aId)
{
aVel+= impulse;
aAngVel+= BT_GPU_cross(contactPoint, impulse).z;
}
if(bId)
{
bVel-= impulse;
bAngVel-= BT_GPU_cross(contactPoint+aPos-bPos, impulse).z;
}
}
}
vel[aId]=BT_GPU_make_float42(aVel,0.0f);
vel[bId]=BT_GPU_make_float42(bVel,0.0f);
angularVel[aId]=aAngVel;
angularVel[bId]=bAngVel;
#endif
}
BT_GPU___global__ void collisionBatchResolutionBoxD(int2 *constraints,
int *batch,
int nConstraints,
float4 *pos,
float4 *vel,
float *rotation,
float *angularVel,
float *lambdaDtBox,
float4* contact,
btCudaPartProps pProp,
int iBatch,
float dt)
{
int k_idx = BT_GPU___mul24(BT_GPU_blockIdx.x, BT_GPU_blockDim.x) + BT_GPU_threadIdx.x;
if(k_idx < nConstraints)
{
int idx = batch[k_idx];
collisionResolutionBox( idx, constraints, pos, vel, rotation, angularVel, lambdaDtBox,
contact, pProp, dt);
}
}
extern "C"
{
void BT_GPU_PREF(clearAccumulationOfLambdaDt(float* lambdaDtBox, int numConstraints, int numContPoints))
{
if(!numConstraints)
{
return;
}
int numThreads, numBlocks;
BT_GPU_PREF(computeGridSize)(numConstraints, 256, numBlocks, numThreads);
// execute the kernel
BT_GPU_EXECKERNEL(numBlocks, numThreads, clearAccumulationOfLambdaDtD, (lambdaDtBox, numConstraints, numContPoints));
// check if kernel invocation generated an error
BT_GPU_CHECK_ERROR("clearAccumulationOfLambdaDtD kernel execution failed");
}
void BT_GPU_PREF(setConstraintData(void* constraints,int numConstraints,int numObjs,void* pos,float *rotation,char* shapes,void* shapeIds,btCudaPartProps pProp,void* contact))
{
if(!numConstraints)
{
return;
}
int2* pConst = (int2*)constraints;
float4* pPos = (float4*)pos;
float4* pCont = (float4*)contact;
int2* pShapeIds = (int2*)shapeIds;
BT_GPU_SAFE_CALL(BT_GPU_BindTexture(0, posTex, pPos, numObjs * sizeof(float4)));
int numThreads, numBlocks;
BT_GPU_PREF(computeGridSize)(numConstraints, 256, numBlocks, numThreads);
// execute the kernel
BT_GPU_EXECKERNEL(numBlocks, numThreads, setConstraintDataD, (pConst,numConstraints,pPos,rotation,shapes,pShapeIds,pProp,pCont));
BT_GPU_SAFE_CALL(BT_GPU_UnbindTexture(posTex));
// check if kernel invocation generated an error
BT_GPU_CHECK_ERROR("setConstraintDataD kernel execution failed");
}
void BT_GPU_PREF(collisionWithWallBox(void* pos,void* vel,float *rotation,float *angVel,char* shapes,void* shapeIds,btCudaPartProps pProp, btCudaBoxProps gProp,int numObjs,float dt))
{
if(!numObjs)
{
return;
}
float4* pPos = (float4*)pos;
float4* pVel = (float4*)vel;
int2* pShapeIds = (int2*)shapeIds;
BT_GPU_SAFE_CALL(BT_GPU_BindTexture(0, posTex, pPos, numObjs * sizeof(float4)));
int numThreads, numBlocks;
BT_GPU_PREF(computeGridSize)(numObjs, 256, numBlocks, numThreads);
// execute the kernel
BT_GPU_EXECKERNEL(numBlocks, numThreads, collisionWithWallBoxD, (pPos,pVel,rotation,angVel,shapes, pShapeIds,pProp,gProp,numObjs,dt));
BT_GPU_SAFE_CALL(BT_GPU_UnbindTexture(posTex));
// check if kernel invocation generated an error
BT_GPU_CHECK_ERROR("collisionWithWallBoxD kernel execution failed");
}
void BT_GPU_PREF(collisionBatchResolutionBox(void* constraints,int *batch,int numConstraints,int numObjs,void *pos,void *vel,float *rotation,float *angularVel,float *lambdaDtBox,void* contact,btCudaPartProps pProp,int iBatch,float dt))
{
if(!numConstraints)
{
return;
}
int2* pConstr = (int2*)constraints;
float4* pPos = (float4*)pos;
float4* pVel = (float4*)vel;
float4* pCont = (float4*)contact;
int numThreads, numBlocks;
BT_GPU_PREF(computeGridSize)(numConstraints, 128, numBlocks, numThreads);
BT_GPU_SAFE_CALL(BT_GPU_BindTexture(0, posTex, pPos, numObjs * sizeof(float4)));
// execute the kernel
BT_GPU_EXECKERNEL(numBlocks, numThreads, collisionBatchResolutionBoxD, (pConstr,batch,numConstraints,pPos,pVel,rotation,angularVel,lambdaDtBox,pCont,pProp,iBatch,dt));
// check if kernel invocation generated an error
BT_GPU_CHECK_ERROR("collisionBatchResolutionBox2D kernel execution failed");
BT_GPU_SAFE_CALL(BT_GPU_UnbindTexture(posTex));
}
} // extern "C"

View File

@@ -0,0 +1,33 @@
/*
Impulse based Rigid body simulation using CUDA
Copyright (c) 2007 Takahiro Harada http://www.iii.u-tokyo.ac.jp/~takahiroharada/projects/impulseCUDA.html
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.
*/
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//---------- C o n s t r a i n t s o l v e r d e m o ----------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
extern "C"
{
void BT_GPU_PREF(clearAccumulationOfLambdaDt(float* lambdaDtBox, int numConstraints, int numContPoints));
void BT_GPU_PREF(setConstraintData(void* constraints,int numConstraints,int numObjs,void* pos,float *rotation,char* shapes,void* shapeIds,btCudaPartProps pProp,void* oContact));
void BT_GPU_PREF(collisionWithWallBox(void* pos,void* vel,float *rotation,float *angVel,char* shapes,void* shapeIds,btCudaPartProps pProp, btCudaBoxProps gProp,int numObjs,float dt));
void BT_GPU_PREF(collisionBatchResolutionBox(void* constraints,int *batch,int numConstraints,int numObjs,void *pos,void *vel,float *rotation,float *angularVel,float *lambdaDtBox,void* contact,btCudaPartProps pProp,int iBatch,float dt));
} // extern "C"
//----------------------------------------------------------------------------------------

View File

@@ -0,0 +1,39 @@
/*
Impulse based Rigid body simulation using CUDA
Copyright (c) 2007 Takahiro Harada http://www.iii.u-tokyo.ac.jp/~takahiroharada/projects/impulseCUDA.html
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.
*/
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//---------- C o n s t r a i n t s o l v e r d e m o ----------------------------
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
struct btCudaPartProps
{
float m_mass;
float m_diameter;
float m_restCoeff;
};
struct btCudaBoxProps
{
float minX;
float maxX;
float minY;
float maxY;
float minZ;
float maxZ;
};
//----------------------------------------------------------------------------------------

View File

@@ -0,0 +1,503 @@
/*
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 "btGpuDemoDynamicsWorld.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
#include "LinearMath/btQuickprof.h"
#include "GlutStuff.h"
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
//--------------------------------------------------------------------------
#define BT_GPU_PREF(func) btCuda_##func
#include "../../src/BulletMultiThreaded/btGpuUtilsSharedDefs.h"
#include "btGpuDemo2dSharedDefs.h"
#undef BT_GPU_PREF
#define BT_GPU_PREF(func) btGpu_##func
#include "btGpuDemo2dSharedDefs.h"
#undef BT_GPU_PREF
//--------------------------------------------------------------------------
btGpuDemoDynamicsWorld* gpCudaDemoDynamicsWorld = NULL;
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::grabNonContactConstraintData()
{
m_numNonContactConstraints = 0;
int numNonContactConstraints = getNumConstraints();
for(int i = 0; i < numNonContactConstraints; i++)
{
btTypedConstraint* ct = m_constraints[i];
int ctype = ct->getConstraintType();
switch(ctype)
{
case POINT2POINT_CONSTRAINT_TYPE :
grabP2PConstraintData((btPoint2PointConstraint*)ct);
break;
default :
// warning (not supported) here?
break;
}
}
} // btGpuDemoDynamicsWorld::grabNonContactConstraintData()
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::grabP2PConstraintData(btPoint2PointConstraint* ct)
{
btRigidBody& bodyA = ct->getRigidBodyA();
btTransform trA = bodyA.getCenterOfMassTransform();
btVector3 pivotA = trA.getBasis() * ct->getPivotInA();
btRigidBody& bodyB = ct->getRigidBodyB();
btTransform trB = bodyB.getCenterOfMassTransform();
btVector3 pivotB = trB.getBasis() * ct->getPivotInB();
btVector3 pivotA_W = pivotA + trA.getOrigin();
btVector3 pivotB_W = pivotB + trB.getOrigin();
btVector3 delta = pivotB_W - pivotA_W;
int idA = bodyA.getCompanionId();
int idB = bodyB.getCompanionId();
m_hIds[m_totalNumConstraints].x = idA;
m_hIds[m_totalNumConstraints].y = (idB > 0) ? idB : 0;
btVector3* pConstrData = (btVector3*)(m_hContact + m_totalNumConstraints * 2 * m_maxVtxPerObj);
for(int k = 0; k < 2; k++)
{
btScalar penetration = delta[k];
btScalar sign = (penetration < 0) ? btScalar(-1.f) : btScalar(1.f);
btVector3 normal = btVector3(0., 0., 0.);
normal[k] = sign;
penetration *= sign;
pConstrData[0] = pivotA_W;
pConstrData[0][3] = penetration;
pConstrData[1] = normal;
pConstrData[1][3] = btScalar(1.f);
pConstrData += 2;
}
for(int n = 2; n < m_maxVtxPerObj; n++)
{
pConstrData[0][3] = -1.f;
pConstrData += 2;
}
m_totalNumConstraints++;
m_numNonContactConstraints++;
} // btGpuDemoDynamicsWorld::grabP2PConstraintData()
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::grabData()
{
BT_PROFILE("grab data");
m_numObj = getNumCollisionObjects();
m_hPos[0].x = m_hPos[0].y = m_hPos[0].z = m_hPos[0].w = 0.f;
m_hRot[0] = 0.f;
m_hVel[0].x = m_hVel[0].y = m_hVel[0].z = m_hVel[0].w = 0.f;
m_hAngVel[0] = 0.f;
for(int i = 0; i < m_numObj; i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* rb = btRigidBody::upcast(colObj);
btVector3 v;
v = rb->getCenterOfMassPosition();
m_hPos[i+1] = *((float4*)&v);
const btTransform& tr = rb->getCenterOfMassTransform();
v = tr.getBasis().getColumn(0);
float rot = btAtan2(v[1], v[0]);
m_hRot[i+1] = rot;
v = rb->getLinearVelocity();
m_hVel[i+1] = *((float4*)&v);
v = rb->getAngularVelocity();
m_hAngVel[i+1] = v[2];
}
grabNonContactConstraintData();
} // btGpuDemoDynamicsWorld::grabGata()
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::createBatches2()
{
BT_PROFILE("create batches");
int sz = m_maxObjs * m_maxNeighbors;
for(int idx = 0; idx < sz; idx++)
{
m_hBatchIds[idx] = -1;
}
for(int i = 0; i < m_totalNumConstraints; i++)
{
m_hConstraintUsed[i] = 0;
}
int curBatchId=0;
int* pBatchIds = m_hBatchIds;
for(int stage = 0; stage < m_maxBatches; stage++)
{
bool isLast = (stage == m_maxBatches-1);
for(int j = 0; j < m_numObj + 1; j++)
{
m_hConstraintCounter[j] = 0;
}
int numInBatch = 0;
for(int i = 0; i < m_totalNumConstraints; i++)
{
if(m_hConstraintUsed[i])
{
continue;
}
int2 ids = m_hIds[i];
if(!isLast)
{
if((m_hConstraintCounter[ids.x] == 0) && (m_hConstraintCounter[ids.y] == 0))
{
m_hConstraintCounter[ids.x]=1;
m_hConstraintCounter[ids.y]=1;
pBatchIds[numInBatch]=i;
numInBatch++;
m_hConstraintUsed[i] = 1;
}
}
else
{
pBatchIds[numInBatch]=i;
numInBatch++;
m_hConstraintUsed[i] = 1;
}
}
m_numInBatches[stage] = numInBatch;
pBatchIds += numInBatch;
}
} // btGpuDemoDynamicsWorld::createBatches2()
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::writebackData()
{
BT_PROFILE("copy velocity into btRigidBody");
for(int i = 0; i < m_numObj; i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* rb = btRigidBody::upcast(colObj);
btVector3 v;
v = *((btVector3*)(m_hVel + i + 1));
v[2] = 0.f;
rb->setLinearVelocity(v);
v[0] = btScalar(0.f);
v[1] = btScalar(0.f);
v[2] = m_hAngVel[i + 1];
rb->setAngularVelocity(v);
}
} // btGpuDemoDynamicsWorld::writebackData()
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::copyDataToGPU()
{
BT_PROFILE("copyDataToGPU");
#ifdef BT_USE_CUDA
btCuda_copyArrayToDevice(m_dIds, m_hIds, sizeof(int2) * m_totalNumConstraints);
btCuda_copyArrayToDevice(m_dBatchIds, m_hBatchIds, sizeof(int) * m_totalNumConstraints);
if(m_numNonContactConstraints)
{ // non-contact constraints are set up by CPU, so copy data to GPU
int nonContConstrOffs = (m_totalNumConstraints - m_numNonContactConstraints) * 2 * m_maxVtxPerObj;
int nonContConstrSize = 2 * m_numNonContactConstraints * m_maxVtxPerObj;
btCuda_copyArrayToDevice(m_dContact + nonContConstrOffs, m_hContact + nonContConstrOffs, sizeof(float4) * nonContConstrSize);
}
if(m_numSimStep & 1)
{
m_dcPos = m_dpPos;
m_dcVel = m_dpVel;
m_dcRot = m_dpRot;
m_dcAngVel = m_dpAngVel;
}
else
{
m_dcPos = m_dPos;
m_dcVel = m_dVel;
m_dcRot = m_dRot;
m_dcAngVel = m_dAngVel;
}
btCuda_copyArrayToDevice(m_dcPos, m_hPos, (m_numObj + 1) * sizeof(float4));
btCuda_copyArrayToDevice(m_dcVel, m_hVel, (m_numObj + 1) * sizeof(float4));
btCuda_copyArrayToDevice(m_dcRot, m_hRot, (m_numObj + 1) * sizeof(float));
btCuda_copyArrayToDevice(m_dcAngVel, m_hAngVel, (m_numObj + 1) * sizeof(float));
if(m_copyShapeDataToGPU)
{
btCuda_copyArrayToDevice(m_dShapeBuffer, m_hShapeBuffer, m_firstFreeShapeBufferOffset);
btCuda_copyArrayToDevice(m_dShapeIds, m_hShapeIds, (m_numObj + 1) * sizeof(int2));
m_copyShapeDataToGPU = false;
}
#endif //BT_USE_CUDA
} // btGpuDemoDynamicsWorld::copyDataToGPU()
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::setConstraintData(btCudaPartProps& partProps)
{
BT_PROFILE("set constraint data");
partProps.m_mass = 1.0f;
partProps.m_diameter = m_objRad * 2.0f;
partProps.m_restCoeff = 1.0f;
#ifdef BT_USE_CUDA
btCuda_clearAccumulationOfLambdaDt(m_dLambdaDtBox, m_totalNumConstraints, m_maxVtxPerObj * 2);
btCuda_setConstraintData(m_dIds, m_totalNumConstraints - m_numNonContactConstraints, m_numObj + 1, m_dcPos, m_dcRot, m_dShapeBuffer, m_dShapeIds,
partProps, m_dContact);
#endif //BT_USE_CUDA
} // btGpuDemoDynamicsWorld::setConstraintData()
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::copyDataFromGPU()
{
BT_PROFILE("copy velocity data from device");
#ifdef BT_USE_CUDA
btCuda_copyArrayFromDevice(m_hVel, m_dcVel, (m_numObj + 1) * sizeof(float4));
btCuda_copyArrayFromDevice(m_hAngVel, m_dcAngVel, (m_numObj + 1) * sizeof(float));
#endif //BT_USE_CUDA
} // btGpuDemoDynamicsWorld::copyDataFromGPU()
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
{
if(m_useCPUSolver)
{
solveConstraintsCPU2(solverInfo);
}
else
{
solveConstraints2(solverInfo);
}
m_totalNumConstraints = 0;
} // btGpuDemoDynamicsWorld::solveConstraints()
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::solveConstraints2(btContactSolverInfo& solverInfo)
{
#ifdef BT_USE_CUDA
BT_PROFILE("solveConstraints");
grabData();
createBatches2();
copyDataToGPU();
btCudaPartProps partProps;
setConstraintData(partProps);
btCudaBoxProps boxProps;
boxProps.minX = m_worldMin[0];
boxProps.maxX = m_worldMax[0];
boxProps.minY = m_worldMin[1];
boxProps.maxY = m_worldMax[1];
{
BT_PROFILE("btCuda_collisionBatchResolutionBox");
int nIter=getSolverInfo().m_numIterations;
btDispatcherInfo& dispatchInfo = getDispatchInfo();
btScalar timeStep = dispatchInfo.m_timeStep;
for(int i=0;i<nIter;i++)
{
btCuda_collisionWithWallBox(m_dcPos, m_dcVel, m_dcRot, m_dcAngVel,m_dShapeBuffer, m_dShapeIds,
partProps, boxProps, m_numObj + 1, timeStep);
int* pBatchIds = m_dBatchIds;
for(int iBatch=0;iBatch < m_maxBatches;iBatch++)
{
int numConstraints = m_numInBatches[iBatch];
btCuda_collisionBatchResolutionBox( m_dIds, pBatchIds, numConstraints, m_numObj + 1,
m_dcPos, m_dcVel,
m_dcRot, m_dcAngVel,
m_dLambdaDtBox,
m_dContact,
partProps, iBatch, timeStep);
pBatchIds += numConstraints;
}
}
}
copyDataFromGPU();
writebackData();
m_numSimStep++;
#endif //BT_USE_CUDA
} // btGpuDemoDynamicsWorld::solveConstraints2()
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::solveConstraintsCPU2(btContactSolverInfo& solverInfo)
{
BT_PROFILE("solveConstraints");
grabData();
createBatches2();
btCudaPartProps partProps;
{
BT_PROFILE("set constraint data CPU");
partProps.m_mass = 1.0f;
partProps.m_diameter = m_objRad * 2.0f;
partProps.m_restCoeff = 1.0f;
btGpu_clearAccumulationOfLambdaDt(m_hLambdaDtBox, m_totalNumConstraints, m_maxVtxPerObj * 2);
btGpu_setConstraintData(m_hIds, m_totalNumConstraints - m_numNonContactConstraints, m_numObj + 1, m_hPos, m_hRot,m_hShapeBuffer, m_hShapeIds,
partProps, m_hContact);
}
btCudaBoxProps boxProps;
boxProps.minX = m_worldMin[0];
boxProps.maxX = m_worldMax[0];
boxProps.minY = m_worldMin[1];
boxProps.maxY = m_worldMax[1];
{
BT_PROFILE("btCuda_collisionBatchResolutionBox CPU");
int nIter=getSolverInfo().m_numIterations;
btDispatcherInfo& dispatchInfo = getDispatchInfo();
btScalar timeStep = dispatchInfo.m_timeStep;
for(int i=0;i<nIter;i++){
btGpu_collisionWithWallBox(m_hPos, m_hVel, m_hRot, m_hAngVel,m_hShapeBuffer, m_hShapeIds,
partProps, boxProps, m_numObj + 1, timeStep);
int* pBatchIds = m_hBatchIds;
for(int iBatch=0;iBatch < m_maxBatches;iBatch++)
{
int numContConstraints = m_numInBatches[iBatch];
if(!numContConstraints)
{
break;
}
btGpu_collisionBatchResolutionBox( m_hIds, pBatchIds, numContConstraints, m_numObj + 1,
m_hPos, m_hVel,
m_hRot, m_hAngVel,
m_hLambdaDtBox,
m_hContact,
partProps, iBatch, timeStep);
pBatchIds += numContConstraints;
}
}
}
writebackData();
m_numSimStep++;
} // btGpuDemoDynamicsWorld::solveConstraintsCPU2()
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::debugDrawConstraints(int selectedBatch, const float* pColorTab)
{
int* pBatchIds = m_hBatchIds;
for(int stage = 0; stage < m_maxBatches; stage++)
{
int numConstraints = m_numInBatches[stage];
if(!numConstraints)
{
break;
}
const float* pCol = pColorTab + stage * 3;
if(selectedBatch < CUDA_DEMO_DYNAMICS_WORLD_MAX_BATCHES)
{
if(stage != selectedBatch)
{
pBatchIds += numConstraints;
continue;
}
}
glColor3f(pCol[0], pCol[1], pCol[2]);
glBegin(GL_LINES);
for(int i = 0; i < numConstraints; i++)
{
int indx = pBatchIds[i];
int idA = m_hIds[indx].x;
int idB = m_hIds[indx].y;
if((idA > 0) && (idB > 0))
{
btCollisionObject* colObjA = m_collisionObjects[idA];
btCollisionObject* colObjB = m_collisionObjects[idB];
btVector3 vA = colObjA->getWorldTransform().getOrigin();
btVector3 vB = colObjB->getWorldTransform().getOrigin();
glVertex3f(vA[0], vA[1], vA[2]);
glVertex3f(vB[0], vB[1], vB[2]);
}
}
pBatchIds += numConstraints;
glEnd();
}
} // btGpuDemoDynamicsWorld::debugDrawConstraints()
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::initShapeBuffer(int maxShapeBufferSize)
{
m_maxShapeBufferSize = maxShapeBufferSize;
m_firstFreeShapeBufferOffset = 0;
m_hShapeBuffer = new char[m_maxShapeBufferSize];
m_hShapeIds = new int2[m_maxObjs];
#ifdef BT_USE_CUDA
btCuda_allocateArray((void**)&m_dShapeBuffer, m_maxShapeBufferSize);
btCuda_allocateArray((void**)&m_dShapeIds, sizeof(int) * 2 * m_maxObjs);
#endif //BT_USE_CUDA
m_copyShapeDataToGPU = true;
} // btGpuDemoDynamicsWorld::initShapeBuffer()
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::freeShapeBuffer()
{
delete [] m_hShapeBuffer;
delete [] m_hShapeIds;
#ifdef BT_USE_CUDA
btCuda_freeArray(m_dShapeBuffer);
btCuda_freeArray(m_dShapeIds);
#endif //BT_USE_CUDA
} // btGpuDemoDynamicsWorld::freeShapeBuffer()
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::addSphere(btVector3& pos, btScalar rad)
{
btVector3* pBuf = (btVector3*)(m_hShapeBuffer + m_firstFreeShapeBufferOffset);
*pBuf = pos;
pBuf->setW(rad);
m_firstFreeShapeBufferOffset += sizeof(btVector3);
} // btGpuDemoDynamicsWorld::addSphere()
//--------------------------------------------------------------------------
void btGpuDemoDynamicsWorld::addMultiShereObject(int numSpheres, int objIndex)
{
m_hShapeIds[objIndex].x = m_firstFreeShapeBufferOffset;
m_hShapeIds[objIndex].y = numSpheres;
return;
} // btGpuDemoDynamicsWorld::addMultiShereObject()
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

View File

@@ -0,0 +1,272 @@
/*
Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
Copyright (C) 2006, 2007 Sony Computer Entertainment 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.
*/
//----------------------------------------------------------------------------------------
#ifndef BT_CUDA_DEMO_DYNAMICS_WORLD_H
#define BT_CUDA_DEMO_DYNAMICS_WORLD_H
//----------------------------------------------------------------------------------------
#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
#ifdef BT_USE_CUDA
#include "btCudaDemoPairCache.h"
#include <vector_types.h>
#define BT_GPU_PREF(func) btCuda_##func
#include "../../src/BulletMultiThreaded/btGpuUtilsSharedDefs.h"
#else
#include "BulletMultiThreaded/btGpuDefines.h"
#include "../../src/BulletMultiThreaded/btGpuUtilsSharedDefs.h"
#endif
#undef BT_GPU_PREF
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
#include "btGpuDemo2DSharedTypes.h"
//----------------------------------------------------------------------------------------
#define CUDA_DEMO_DYNAMICS_WORLD_MAX_BATCHES 20
#define CUDA_DEMO_DYNAMICS_WORLD_MAX_OBJS 1024
#define CUDA_DEMO_DYNAMICS_WORLD_MAX_NEIGHBORS 24
#define CUDA_DEMO_DYNAMICS_WORLD_MAX_SPHERES_PER_OBJ 8
class btGpuDemoDynamicsWorld;
extern btGpuDemoDynamicsWorld* gpCudaDemoDynamicsWorld; // to access world members from pair cache
class btGpuDemoDynamicsWorld : public btDiscreteDynamicsWorld
{
protected:
int m_maxObjs;
int m_maxNeighbors;
int m_numObj;
int m_numSimStep;
bool m_useCPUSolver;
float4* m_hPos;
float* m_hRot;
float4* m_hVel;
float* m_hAngVel;
#ifdef BT_USE_CUDA
float4* m_dPos;
float* m_dRot;
float4* m_dVel;
float* m_dAngVel;
float4* m_dpPos;
float* m_dpRot;
float4* m_dpVel;
float* m_dpAngVel;
float4* m_dcPos;
float* m_dcRot;
float4* m_dcVel;
float* m_dcAngVel;
#endif //BT_USE_CUDA
btOverlappingPairCache* m_pairCache;
int* m_hConstraintBuffer;
int* m_hConstraintCounter;
int m_maxBatches;
int m_numBatches;
int m_totalNumConstraints;
int2* m_hIds;
int* m_hBatchIds;
int m_maxVtxPerObj;
int2* m_dIds;
int* m_dBatchIds;
float* m_dLambdaDtBox;
float4* m_dContact; // 8 floats : pos.x, pos.y, pos.z, penetration, norm.x, norm.y, norm.z, reserved
// ------------- these are only needed for CPU version and for debugging
float* m_hLambdaDtBox;
float4* m_hContact; // 8 floats : pos.x, pos.y, pos.z, penetration, norm.x, norm.y, norm.z, reserved
// -------------
btScalar m_objRad;
btVector3 m_worldMin;
btVector3 m_worldMax;
//-------------------------------
int* m_hConstraintUsed;
//-------------------------------
// shape buffer
int m_maxShapeBufferSize;
int m_firstFreeShapeBufferOffset;
char* m_hShapeBuffer; // (pos.x, pos.y, pos.z, radius)
char* m_dShapeBuffer;//pointer in device memory
int2* m_hShapeIds;
int2* m_dShapeIds;
bool m_copyShapeDataToGPU;
void initShapeBuffer(int maxShapeBufferSize);
void freeShapeBuffer();
void sendShapeDataToGpu();
//-------------------------------
int m_numNonContactConstraints;
void grabNonContactConstraintData();
void grabP2PConstraintData(btPoint2PointConstraint* ct);
public:
int m_numInBatches[CUDA_DEMO_DYNAMICS_WORLD_MAX_BATCHES];
void addSphere(btVector3& pos, btScalar rad);
void addMultiShereObject(int numSpheres, int objIndex);
btGpuDemoDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration,
int maxObjs = CUDA_DEMO_DYNAMICS_WORLD_MAX_OBJS, int maxNeighbors = CUDA_DEMO_DYNAMICS_WORLD_MAX_NEIGHBORS)
: btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration)
{
m_maxObjs = maxObjs;
m_maxNeighbors = maxNeighbors;
m_useCPUSolver = false;
m_pairCache = pairCache->getOverlappingPairCache();
int sz = m_maxObjs * m_maxNeighbors;
m_hConstraintBuffer = new int[sz];
m_hConstraintCounter = new int[m_maxObjs];
m_maxBatches = CUDA_DEMO_DYNAMICS_WORLD_MAX_BATCHES;
m_hIds = new int2[sz];
m_hBatchIds = new int[sz];
for(int i = 0; i < sz; i++)
{
m_hBatchIds[i] = -1;
}
m_hPos = new float4[m_maxObjs];
m_hVel = new float4[m_maxObjs];
m_hRot = new float[m_maxObjs];
m_hAngVel = new float[m_maxObjs];
m_maxVtxPerObj = 8;
#ifdef BT_USE_CUDA
btCuda_allocateArray((void**)&m_dPos, sizeof(float4) * m_maxObjs);
btCuda_allocateArray((void**)&m_dRot, sizeof(float) * m_maxObjs);
btCuda_allocateArray((void**)&m_dVel, sizeof(float4) * m_maxObjs);
btCuda_allocateArray((void**)&m_dAngVel, sizeof(float) * m_maxObjs);
btCuda_allocateArray((void**)&m_dpPos, sizeof(float4) * m_maxObjs);
btCuda_allocateArray((void**)&m_dpRot, sizeof(float) * m_maxObjs);
btCuda_allocateArray((void**)&m_dpVel, sizeof(float4) * m_maxObjs);
btCuda_allocateArray((void**)&m_dpAngVel, sizeof(float) * m_maxObjs);
btCuda_allocateArray((void**)&m_dIds, sizeof(int2) * sz);
btCuda_allocateArray((void**)&m_dBatchIds, sizeof(int) * sz);
btCuda_allocateArray((void**)&m_dLambdaDtBox, sizeof(float) * sz * m_maxVtxPerObj);
btCuda_allocateArray((void**)&m_dContact, sizeof(float) * sz * m_maxVtxPerObj * 8);
// btCuda_allocateArray((void**)&m_dPositionConstraint, sizeof(float) * sz * m_maxVtxPerObj * 2);
// btCuda_allocateArray((void**)&m_dNormal, sizeof(float3) * sz * m_maxVtxPerObj * 2);
#endif //BT_USE_CUDA
m_hLambdaDtBox = new float[sz * m_maxVtxPerObj];
m_hContact = new float4[sz * m_maxVtxPerObj * 2];
// m_hPositionConstraint = new float[sz * m_maxVtxPerObj * 2];
// m_hNormal = new float3[sz * m_maxVtxPerObj * 2];
m_numSimStep = 0;
m_objRad = 1.0f;
m_hConstraintUsed = new int[sz];
gpCudaDemoDynamicsWorld = this;
m_totalNumConstraints = 0;
initShapeBuffer(m_maxObjs * CUDA_DEMO_DYNAMICS_WORLD_MAX_SPHERES_PER_OBJ * sizeof(float) * 4);
}
virtual ~btGpuDemoDynamicsWorld()
{
delete [] m_hConstraintBuffer;
delete [] m_hConstraintCounter;
delete [] m_hIds;
delete [] m_hBatchIds;
delete [] m_hPos;
delete [] m_hRot;
delete [] m_hVel;
delete [] m_hAngVel;
#ifdef BT_USE_CUDA
btCuda_freeArray(m_dPos);
btCuda_freeArray(m_dRot);
btCuda_freeArray(m_dVel);
btCuda_freeArray(m_dAngVel);
btCuda_freeArray(m_dpPos);
btCuda_freeArray(m_dpRot);
btCuda_freeArray(m_dpVel);
btCuda_freeArray(m_dpAngVel);
btCuda_freeArray(m_dIds);
btCuda_freeArray(m_dBatchIds);
btCuda_freeArray(m_dLambdaDtBox);
btCuda_freeArray(m_dContact);
#endif //BT_USE_CUDA
delete [] m_hLambdaDtBox;
delete [] m_hContact;
delete [] m_hConstraintUsed;
gpCudaDemoDynamicsWorld = NULL;
freeShapeBuffer();
}
virtual void calculateSimulationIslands()
{
}
virtual void solveConstraints(btContactSolverInfo& solverInfo);
void solveConstraints2(btContactSolverInfo& solverInfo);
void solveConstraintsCPU2(btContactSolverInfo& solverInfo);
void debugDrawConstraints(int selectedBatch, const float* pColorTab);
void setObjRad(btScalar rad) { m_objRad = rad; }
void setWorldMin(const btVector3& worldMin) { m_worldMin = worldMin; }
void setWorldMax(const btVector3& worldMax) { m_worldMax = worldMax; }
void grabData();
void copyDataToGPU();
void setConstraintData(btCudaPartProps& partProps);
void copyDataFromGPU();
void writebackData();
void setUseCPUSolver(bool useCPU) { m_useCPUSolver = useCPU; }
void createBatches2();
int2* getIdsPtr() { return m_hIds; }
void setTotalNumConstraints(int totalNumConstraints) { m_totalNumConstraints = totalNumConstraints; }
int getTotalNumConstraints() { return m_totalNumConstraints; }
};
#endif //BT_CUDA_DEMO_DYNAMICS_WORLD_H

View File

@@ -0,0 +1,79 @@
/*
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 "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "btGpuDemoPairCache.h"
#include "btGpuDemoDynamicsWorld.h"
//--------------------------------------------------------------------------
void btGpuDemoPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher)
{
int sz = m_maxProxies * m_maxNeighbors;
int numContConstraints = 0;
int2* pIds = gpCudaDemoDynamicsWorld->getIdsPtr();
for(int idx = 0; idx < sz; idx++)
{
int neigh = m_hNeighbors[idx];
if(neigh >= 0)
{
int i=idx / m_maxNeighbors;
int j=idx % m_maxNeighbors;
pIds[numContConstraints].x = i;
pIds[numContConstraints].y = m_hNeighbors[i * m_maxNeighbors + j];
numContConstraints++;
}
}
gpCudaDemoDynamicsWorld->setTotalNumConstraints(numContConstraints);
} // btGpuDemoPairCache::processAllOverlappingPairs()
//--------------------------------------------------------------------------
// this will be called for each overlapping pair if collision detection uses pairCache other than btGpuDemoPairCache
// IMPORTANT : m_numConstraints in gpCudaDemoDynamicsWorld is set to 0 at start of simulation step
// IMPORTANT : companionIds for all objects should be properly set at start of simulation step
void cudaDemoNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
{
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
if (dispatcher.needsCollision(colObj0,colObj1))
{
// int id0 = collisionPair.m_pProxy0->m_uniqueId - 2;
// int id1 = collisionPair.m_pProxy1->m_uniqueId - 2;
// cannot use m_uniqueId : it may be altered by broadphase code
// so we'll use companionIds set on the initialization stage
unsigned int id0 = colObj0->getCompanionId();
unsigned int id1 = colObj1->getCompanionId();
if(id0 > id1)
{
int tmp = id0; id0 = id1; id1 = tmp;
}
int totalNumConstraints = gpCudaDemoDynamicsWorld->getTotalNumConstraints();
int2* pIds = gpCudaDemoDynamicsWorld->getIdsPtr();
pIds += totalNumConstraints;
pIds->x = id0;
pIds->y = id1;
totalNumConstraints++;
gpCudaDemoDynamicsWorld->setTotalNumConstraints(totalNumConstraints);
}
} // cudaDemoNearCallback()
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

View File

@@ -0,0 +1,136 @@
/*
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 CUDA_DEMO_PAIR_CACHE_H
#define CUDA_DEMO_PAIR_CACHE_H
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
#include "LinearMath/btAlignedObjectArray.h"
class btGpuDemoPairCache : public btNullPairCache
{
public:
int m_maxProxies;
int m_maxNeighbors;
int* m_hNeighbors;
int m_numPairs;
int m_numSmallProxies;
int m_maxSmallProxies;
btGpuDemoPairCache(int maxProxies, int maxNeighbors, int maxSmallProxies)
{
m_maxProxies = maxProxies;
m_maxNeighbors = maxNeighbors;
m_maxSmallProxies = maxSmallProxies;
int sz = maxProxies * maxNeighbors;
m_hNeighbors = new int [sz];
reset();
}
~btGpuDemoPairCache()
{
delete [] m_hNeighbors;
}
void reset(void)
{
int sz = m_maxProxies * m_maxNeighbors;
for(int i = 0; i < sz; i++)
{
m_hNeighbors[i] = -1;
}
m_numPairs = 0;
}
virtual int getNumOverlappingPairs() const
{
return m_numPairs;
//return 0; // to skip btSimulationIslandManager::findUnions()
}
virtual void processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher);
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
int id0 = proxy0->m_uniqueId - 2;
int id1 = proxy1->m_uniqueId - 2;
if(id0 >= m_maxSmallProxies)
{
id0 -= m_maxSmallProxies - m_numSmallProxies;
}
if(id1 >= m_maxSmallProxies)
{
id1 -= m_maxSmallProxies - m_numSmallProxies;
}
if(id0 > id1)
{
int tmp = id0; id0 = id1; id1 = tmp;
}
int offs = id0 * m_maxNeighbors;
int i;
for(i = 0; i < m_maxNeighbors; i++)
{
if(m_hNeighbors[offs + i] < 0)
{
m_hNeighbors[offs + i] = id1;
m_numPairs++;
break;
}
}
// btAssert(i < m_maxNeighbors);
return 0;
}
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* /*dispatcher*/)
{
int id0 = proxy0->m_uniqueId - 2;
int id1 = proxy1->m_uniqueId - 2;
if(id0 >= m_maxSmallProxies)
{
id0 -= m_maxSmallProxies - m_numSmallProxies;
}
if(id1 >= m_maxSmallProxies)
{
id1 -= m_maxSmallProxies - m_numSmallProxies;
}
if(id0 > id1)
{
int tmp = id0; id0 = id1; id1 = tmp;
}
int offs = id0 * m_maxNeighbors;
int i;
for(i = 0; i < m_maxNeighbors; i++)
{
if(m_hNeighbors[offs + i] == id1)
{
m_hNeighbors[offs + i] = -1;
m_numPairs--;
break;
}
}
// btAssert(i < m_maxNeighbors);
return 0;
}
};
extern void cudaDemoNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
#endif //CUDA_DEMO_PAIR_CACHE_H

62
Demos/Gpu2dDemo/main.cpp Normal file
View File

@@ -0,0 +1,62 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 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 "BasicDemo.h"
#include "GlutStuff.h"
#include "GLDebugDrawer.h"
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btHashMap.h"
class OurValue
{
int m_uid;
public:
OurValue(const btVector3& initialPos)
:m_position(initialPos)
{
static int gUid=0;
m_uid=gUid;
gUid++;
}
btVector3 m_position;
int getUid() const
{
return m_uid;
}
};
GLDebugDrawer gDebugDrawer;
int main(int argc,char** argv)
{
BasicDemo ccdDemo;
ccdDemo.initPhysics();
ccdDemo.getDynamicsWorld()->setDebugDrawer(&gDebugDrawer);
#ifdef CHECK_MEMORY_LEAKS
ccdDemo.exitPhysics();
#else
return glutmain(argc, argv,640,480,"Bullet Physics Demo. http://bulletphysics.com",&ccdDemo);
#endif
//default glut doesn't return from mainloop
return 0;
}

View File

@@ -0,0 +1,252 @@
#include "oecakeLoader.h"
#include <stdio.h> //printf debugging
#include <stdlib.h>
btCompoundShape* shiftTransform(btCompoundShape* boxCompound,btScalar mass,btTransform& shift)
{
btTransform principal;
btVector3 principalInertia;
btScalar* masses = new btScalar[boxCompound->getNumChildShapes()];
for (int j=0;j<boxCompound->getNumChildShapes();j++)
{
//evenly distribute mass
masses[j]=mass/boxCompound->getNumChildShapes();
}
boxCompound->calculatePrincipalAxisTransform(masses,principal,principalInertia);
///create a new compound with world transform/center of mass properly aligned with the principal axis
///non-recursive compound shapes perform better
//#define USE_RECURSIVE_COMPOUND 1
#ifdef USE_RECURSIVE_COMPOUND
btCompoundShape* newCompound = new btCompoundShape();
newCompound->addChildShape(principal.inverse(),boxCompound);
m_collisionShapes.push_back(newCompound);
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,newCompound,principalInertia);
#else
#ifdef CHANGE_COMPOUND_INPLACE
for (int i=0;i<boxCompound->getNumChildShapes();i++)
{
btTransform newChildTransform = principal.inverse()*boxCompound->getChildTransform(i);
///updateChildTransform is really slow, because it re-calculates the AABB each time. todo: add option to disable this update
boxCompound->updateChildTransform(i,newChildTransform);
}
if (isDynamic)
boxCompound->calculateLocalInertia(mass,localInertia);
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,boxCompound,localInertia);
#else
///creation is faster using a new compound to store the shifted children
btCompoundShape* newBoxCompound = new btCompoundShape();
for (int i=0;i<boxCompound->getNumChildShapes();i++)
{
btTransform newChildTransform = principal.inverse()*boxCompound->getChildTransform(i);
///updateChildTransform is really slow, because it re-calculates the AABB each time. todo: add option to disable this update
newBoxCompound->addChildShape(newChildTransform,boxCompound->getChildShape(i));
}
#endif
#endif//USE_RECURSIVE_COMPOUND
shift = principal;
return newBoxCompound;
}
void BasicOECakeReader::addParticle(int materialType, int pIndex, int pColor, float pPosX, float pPosY,float radius)
{
//determine that we have a new shape?
if (m_particlePositions.size())
{
if (
(materialType != m_materialType)
||
(pIndex != m_particleObjectIndex)
)
{
convertParticleGroup();
}
}
//add to array
m_materialType = materialType;
m_particleObjectIndex = pIndex;
m_particleColor = pColor;
m_particlePositions.push_back(btVector3(pPosX,pPosY,0.));
m_particleRadii.push_back(radius);
}
void BasicOECakeReader::convertParticleGroup()
{
printf("found a particle group of %d particles\n",m_particlePositions.size());
if (m_particlePositions.size()>0)
{
addNewCollisionShape(m_particlePositions.size(),&m_particlePositions[0],&m_particleRadii[0],m_materialType,m_particleObjectIndex,m_particleColor);
m_particlePositions.clear();
m_particleRadii.clear();
}
}
void BasicOECakeReader::addNewCollisionShape(int numParticles, btVector3* particlePositions, btScalar* radii, int materialType, int objectIndex,int color )
{
//create Bullet stuff
btCompoundShape* colShape = 0;
btScalar mass;
bool addConstraint = false;
if (materialType&0x800000)
{
addConstraint = true;
}
if ((materialType & 0x20000) ||(materialType & 0x12))
{
mass = 1.f;
}
btTransform startTransform;
startTransform.setIdentity();
{
btTransform localTrans;
localTrans.setIdentity();
//static
btCompoundShape* compound = new btCompoundShape();
for (int i=0;i<numParticles;i++)
{
localTrans.setOrigin(particlePositions[i]);
btSphereShape* particle = new btSphereShape(radii[i]);
compound->addChildShape(localTrans,particle);
}
if (mass)
{
//shift the center of mass, based on all spheres
btCompoundShape* newCompound = shiftTransform(compound,mass,startTransform);
colShape = newCompound;
} else
{
//use unmodified
colShape = compound;
}
}
btDefaultMotionState* myMotionState = 0;
if (colShape)
{
createBodyForCompoundShape(colShape,addConstraint,startTransform,mass);
}
}
int BasicOECakeReader::processLine(char * buffer, int size)
{
int numBytesRead = 0;
if (buffer[0] == 'p')
{
int materialType;
int particleObjectIndex;
int particleColor;
int dummy1;
float particlePosX;
float particlePosY;
if (sscanf (buffer, "p %x %x %x %x %f %f", &materialType,&particleObjectIndex,&dummy1, &particleColor, &particlePosX, &particlePosY) == 6)
{
addParticle(materialType,particleObjectIndex,particleColor,particlePosX,particlePosY);
}
else
{
printf("ERROR: invalid line (%s)\n", buffer);
}
}
while (*buffer != '\n' && size != 0)
{
buffer++;
numBytesRead++;
}
if (buffer[0]==0x0a)
{
buffer++;
numBytesRead++;
}
return numBytesRead;
}
bool BasicOECakeReader::processFile(char * fileName)
{
FILE * fp = fopen(fileName, "rb");
if (fp == NULL)
{
printf("ERROR: file(%s) not found", fileName);
return false;
}
int size;
if (fseek(fp, 0, SEEK_END) || (size = ftell(fp)) == EOF || fseek(fp, 0, SEEK_SET))
{
printf("ERROR: problem reading file(%s)", fileName);
fclose(fp);
return false;
}
else
{
rewind (fp);
char * buffer = (char *) malloc(size+1);
memset(buffer,0,size);
if (fread(buffer,1,size,fp) != size)
{
printf("Error reading file %s!\n",fileName);
fclose(fp);
return false;
}
int totalBytesRead = 0;
while(totalBytesRead<size)
{
int remainingSize = size-totalBytesRead;
if (remainingSize<1229)
{
printf("..");
}
totalBytesRead +=processLine(&buffer[totalBytesRead],remainingSize);
}
}
convertParticleGroup();
fclose(fp);
return false;
}

View File

@@ -0,0 +1,35 @@
#ifndef OE_CAKE_LOADER_H
#define OE_CAKE_LOADER_H
#include "btBulletDynamicsCommon.h"
class BasicOECakeReader
{
int m_materialType;
int m_particleObjectIndex;
int m_particleColor;
btAlignedObjectArray<btVector3> m_particlePositions;
btAlignedObjectArray<btScalar> m_particleRadii;
void addParticle(int materialType, int pIndex, int pColor, float pPosX, float pPosY, float radius=1);
virtual void addNewCollisionShape(int numParticles, btVector3* particlePositions, btScalar* radii, int materialType, int objectIndex,int color );
int processLine(char * buffer, int size);
void convertParticleGroup();
public:
BasicOECakeReader()
{
}
bool processFile(char * fileName);
virtual void createBodyForCompoundShape(btCompoundShape* compound,bool addConstraint,const btTransform& worldTransform, btScalar mass) = 0;
};
#endif //OE_CAKE_LOADER_H