+Added btDbvtBroadphase, this very fast/efficient broadphase is based on Dynamic AABB tree (btDbvt).

+SoftBody improvements by Nathanael Presson:
+Add tetrahedralization
+Add support for tearing/slicing cloth and deformable volumes. Uncomment the line in Bullet/src/BulletSoftBody/btSoftBodyHelpers.h: //#define	BT_SOFTBODY_USE_STL	1
This commit is contained in:
erwin.coumans 2008-05-05 23:19:21 +00:00
parent bce0047986
commit 25c5d0d57a
19 changed files with 2897 additions and 828 deletions

View File

@ -34,6 +34,21 @@ void GLDebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btV
}
}
void GLDebugDrawer::drawTriangle(const btVector3& a,const btVector3& b,const btVector3& c,const btVector3& color,btScalar alpha)
{
// if (m_debugMode > 0)
{
const btVector3 n=cross(b-a,c-a).normalized();
glBegin(GL_TRIANGLES);
glColor4f(color.getX(), color.getY(), color.getZ(),alpha);
glNormal3d(n.getX(),n.getY(),n.getZ());
glVertex3d(a.getX(),a.getY(),a.getZ());
glVertex3d(b.getX(),b.getY(),b.getZ());
glVertex3d(c.getX(),c.getY(),c.getZ());
glEnd();
}
}
void GLDebugDrawer::setDebugMode(int debugMode)
{
m_debugMode = debugMode;
@ -76,3 +91,4 @@ void GLDebugDrawer::drawContactPoint(const btVector3& pointOnB,const btVector3&

View File

@ -15,7 +15,9 @@ public:
virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color);
virtual void drawTriangle(const btVector3& a,const btVector3& b,const btVector3& c,const btVector3& color,btScalar alpha);
virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color);
virtual void reportErrorWarning(const char* warningString);

View File

@ -106,7 +106,7 @@ void SoftDemo::clientMoveAndDisplay()
if (m_dynamicsWorld)
{
//#define FIXED_STEP
#define FIXED_STEP
#ifdef FIXED_STEP
m_dynamicsWorld->stepSimulation(dt=1.0f/60.f,0);
@ -186,7 +186,36 @@ void SoftDemo::displayCallback(void) {
}
//
// ImplicitShape
//
//
struct ImplicitSphere : btSoftBody::ImplicitFn
{
btVector3 center;
btScalar sqradius;
ImplicitSphere() {}
ImplicitSphere(const btVector3& c,btScalar r) : center(c),sqradius(r*r) {}
btScalar Eval(const btVector3& x)
{
return((x-center).length2()-sqradius);
}
};
//
// Tetra meshes
//
struct TetraBunny
{
#include "bunny.inl"
};
struct TetraCube
{
#include "cube.inl"
};
//
@ -282,7 +311,7 @@ static btSoftBody* Ctor_SoftBox(SoftDemo* pdemo,const btVector3& p,const btVecto
p+h*btVector3(-1,+1,+1),
p+h*btVector3(+1,+1,+1)};
btSoftBody* psb=btSoftBodyHelpers::CreateFromConvexHull(pdemo->m_softBodyWorldInfo,c,8);
psb->generateBendingConstraints(2,1);
psb->generateBendingConstraints(2);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
return(psb);
@ -300,7 +329,7 @@ static btSoftBody* Ctor_SoftBoulder(SoftDemo* pdemo,const btVector3& p,const btV
pts.push_back(Vector3Rand()*s+p);
}
btSoftBody* psb=btSoftBodyHelpers::CreateFromConvexHull(pdemo->m_softBodyWorldInfo,&pts[0],pts.size());
psb->generateBendingConstraints(2,1);
psb->generateBendingConstraints(2);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
return(psb);
@ -321,8 +350,8 @@ static void Init_Ropes(SoftDemo* pdemo)
btVector3(10,0,i*0.25),
16,
1+2);
psb->m_cfg.iterations = 4;
psb->m_cfg.kLST = 0.1+(i/(btScalar)(n-1))*0.9;
psb->m_cfg.piterations = 4;
psb->m_materials[0]->m_kLST = 0.1+(i/(btScalar)(n-1))*0.9;
psb->setTotalMass(20);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
@ -335,6 +364,7 @@ static void Init_Ropes(SoftDemo* pdemo)
static void Init_RopeAttach(SoftDemo* pdemo)
{
//TRACEDEMO
pdemo->m_softBodyWorldInfo.m_sparsesdf.RemoveReferences(0);
struct Functors
{
static btSoftBody* CtorRope(SoftDemo* pdemo,const btVector3& p)
@ -351,8 +381,8 @@ static void Init_RopeAttach(SoftDemo* pdemo)
btRigidBody* body=pdemo->localCreateRigidBody(50,startTransform,new btBoxShape(btVector3(2,6,2)));
btSoftBody* psb0=Functors::CtorRope(pdemo,btVector3(0,8,-1));
btSoftBody* psb1=Functors::CtorRope(pdemo,btVector3(0,8,+1));
psb0->appendAnchor(psb0->getNodes().size()-1,body);
psb1->appendAnchor(psb1->getNodes().size()-1,body);
psb0->appendAnchor(psb0->m_nodes.size()-1,body);
psb1->appendAnchor(psb1->m_nodes.size()-1,body);
}
//
@ -376,6 +406,7 @@ static void Init_ClothAttach(SoftDemo* pdemo)
btRigidBody* body=pdemo->localCreateRigidBody(20,startTransform,new btBoxShape(btVector3(s,1,3)));
psb->appendAnchor(0,body);
psb->appendAnchor(r-1,body);
pdemo->m_cutting=true;
}
//
@ -409,8 +440,8 @@ static void Init_Collide(SoftDemo* pdemo)
btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVertices,
&gIndices[0][0],
NUM_TRIANGLES);
psb->generateBendingConstraints(2,1);
psb->m_cfg.iterations=2;
psb->generateBendingConstraints(2);
psb->m_cfg.piterations=2;
psb->m_cfg.collisions|=btSoftBody::fCollision::VF_SS;
psb->randomizeConstraints();
btMatrix3x3 m;
@ -426,6 +457,7 @@ static void Init_Collide(SoftDemo* pdemo)
{
Functor::Create(pdemo,btVector3(3*i,2,0),btVector3(SIMD_PI/2*(1-(i&1)),SIMD_PI/2*(i&1),0));
}
pdemo->m_cutting=true;
}
//
@ -441,8 +473,11 @@ static void Init_Collide2(SoftDemo* pdemo)
btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVerticesBunny,
&gIndicesBunny[0][0],
BUNNY_NUM_TRIANGLES);
psb->generateBendingConstraints(2,0.5);
psb->m_cfg.iterations = 2;
btSoftBody::Material* pm=psb->appendMaterial();
pm->m_kLST = 0.5;
pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
psb->generateBendingConstraints(2,pm);
psb->m_cfg.piterations = 2;
psb->m_cfg.kDF = 0.5;
psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS;
psb->randomizeConstraints();
@ -459,6 +494,7 @@ static void Init_Collide2(SoftDemo* pdemo)
{
Functor::Create(pdemo,btVector3(0,-1+5*i,0),btVector3(0,SIMD_PI/2*(i&1),0));
}
pdemo->m_cutting=true;
}
//
@ -474,25 +510,29 @@ static void Init_Collide3(SoftDemo* pdemo)
btVector3(-s,0,+s),
btVector3(+s,0,+s),
15,15,1+2+4+8,true);
psb->m_cfg.kLST = 0.4;
psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS;
psb->m_materials[0]->m_kLST = 0.4;
psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS;
psb->setTotalMass(150);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
{
const btScalar s=4;
const btVector3 o=btVector3(4,10,0);
const btVector3 o=btVector3(5,10,0);
btSoftBody* psb=btSoftBodyHelpers::CreatePatch( pdemo->m_softBodyWorldInfo,
btVector3(-s,0,-s)+o,
btVector3(+s,0,-s)+o,
btVector3(-s,0,+s)+o,
btVector3(+s,0,+s)+o,
7,7,0,true);
psb->generateBendingConstraints(2,0.5);
psb->m_cfg.kLST = 0.4;
psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS;
btSoftBody::Material* pm=psb->appendMaterial();
pm->m_kLST = 0.1;
pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
psb->generateBendingConstraints(2,pm);
psb->m_materials[0]->m_kLST = 0.5;
psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS;
psb->setTotalMass(150);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
pdemo->m_cutting=true;
}
}
@ -514,7 +554,7 @@ static void Init_Aero(SoftDemo* pdemo)
btVector3(+s,h,+s),
segments,segments,
0,true);
psb->generateBendingConstraints(2,1);
psb->generateBendingConstraints(2);
psb->m_cfg.kLF = 0.004;
psb->m_cfg.kDG = 0.0003;
psb->m_cfg.aeromodel = btSoftBody::eAeroModel::V_TwoSided;
@ -561,10 +601,10 @@ static void Init_Pressure(SoftDemo* pdemo)
btSoftBody* psb=btSoftBodyHelpers::CreateEllipsoid(pdemo->m_softBodyWorldInfo,btVector3(35,25,0),
btVector3(1,1,1)*3,
512);
psb->m_cfg.kLST = 0.1;
psb->m_cfg.kDF = 1;
psb->m_cfg.kDP = 0.001; // fun factor...
psb->m_cfg.kPR = 2500;
psb->m_materials[0]->m_kLST = 0.1;
psb->m_cfg.kDF = 1;
psb->m_cfg.kDP = 0.001; // fun factor...
psb->m_cfg.kPR = 2500;
psb->setTotalMass(30,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
@ -582,8 +622,8 @@ static void Init_Volume(SoftDemo* pdemo)
btSoftBody* psb=btSoftBodyHelpers::CreateEllipsoid(pdemo->m_softBodyWorldInfo,btVector3(35,25,0),
btVector3(1,1,1)*3,
512);
psb->m_cfg.kLST = 0.45;
psb->m_cfg.kVC = 20;
psb->m_materials[0]->m_kLST = 0.45;
psb->m_cfg.kVC = 20;
psb->setTotalMass(50,true);
psb->setPose(true,false);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
@ -615,12 +655,11 @@ static void Init_Sticks(SoftDemo* pdemo)
org+btVector3(hg*0.001,hg,0),
sg,
1);
psb->m_cfg.iterations = 1;
psb->m_cfg.kDP = 0.005;
psb->m_cfg.kCHR = 0.1;
for(int i=0;i<3;++i)
{
psb->generateBendingConstraints(2+i,1);
psb->generateBendingConstraints(2+i);
}
psb->setMass(1,0);
psb->setTotalMass(0.01);
@ -646,12 +685,15 @@ static void Init_Cloth(SoftDemo* pdemo)
// 31,31,
1+2+4+8,true);
psb->generateBendingConstraints(2,1);
psb->m_cfg.kLST = 0.4;
btSoftBody::Material* pm=psb->appendMaterial();
pm->m_kLST = 0.4;
pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
psb->generateBendingConstraints(2,pm);
psb->setTotalMass(150);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
Ctor_RbUpStack(pdemo,10);
pdemo->m_cutting=true;
}
//
@ -663,8 +705,11 @@ static void Init_Bunny(SoftDemo* pdemo)
btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVerticesBunny,
&gIndicesBunny[0][0],
BUNNY_NUM_TRIANGLES);
psb->generateBendingConstraints(2,0.5);
psb->m_cfg.iterations = 2;
btSoftBody::Material* pm=psb->appendMaterial();
pm->m_kLST = 0.5;
pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
psb->generateBendingConstraints(2,pm);
psb->m_cfg.piterations = 2;
psb->m_cfg.kDF = 0.5;
psb->randomizeConstraints();
psb->scale(btVector3(6,6,6));
@ -682,9 +727,9 @@ static void Init_BunnyMatch(SoftDemo* pdemo)
btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVerticesBunny,
&gIndicesBunny[0][0],
BUNNY_NUM_TRIANGLES);
psb->m_cfg.kDF = 0.5;
psb->m_cfg.kLST = 0.1;
psb->m_cfg.kMT = 0.05;
psb->m_cfg.kDF = 0.5;
psb->m_materials[0]->m_kLST = 0.1;
psb->m_cfg.kMT = 0.05;
psb->randomizeConstraints();
psb->scale(btVector3(6,6,6));
psb->setTotalMass(100,true);
@ -702,8 +747,8 @@ static void Init_Torus(SoftDemo* pdemo)
btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh( pdemo->m_softBodyWorldInfo, gVertices,
&gIndices[0][0],
NUM_TRIANGLES);
psb->generateBendingConstraints(2,1);
psb->m_cfg.iterations=2;
psb->generateBendingConstraints(2);
psb->m_cfg.piterations=2;
psb->randomizeConstraints();
btMatrix3x3 m;
m.setEulerZYX(SIMD_PI/2,0,0);
@ -723,8 +768,8 @@ static void Init_TorusMatch(SoftDemo* pdemo)
btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVertices,
&gIndices[0][0],
NUM_TRIANGLES);
psb->m_cfg.kLST=0.1;
psb->m_cfg.kMT=0.05;
psb->m_materials[0]->m_kLST = 0.1;
psb->m_cfg.kMT = 0.05;
psb->randomizeConstraints();
btMatrix3x3 m;
m.setEulerZYX(SIMD_PI/2,0,0);
@ -733,11 +778,176 @@ static void Init_TorusMatch(SoftDemo* pdemo)
psb->setTotalMass(50,true);
psb->setPose(true,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
unsigned current_demo=0;
//
// Cutting1
//
static void Init_Cutting1(SoftDemo* pdemo)
{
const btScalar s=6;
const btScalar h=2;
const int r=16;
const btVector3 p[]={ btVector3(+s,h,-s),
btVector3(-s,h,-s),
btVector3(+s,h,+s),
btVector3(-s,h,+s)};
btSoftBody* psb=btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo,p[0],p[1],p[2],p[3],r,r,1+2+4+8,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
psb->m_cfg.piterations=1;
pdemo->m_cutting=true;
}
#ifdef BT_SOFTBODY_USE_STL
//
// TetraBunny
//
static void Init_TetraBunny(SoftDemo* pdemo)
{
btSoftBody* psb=btSoftBodyHelpers::CreateFromTetGenData(pdemo->m_softBodyWorldInfo,
TetraBunny::getElements(),
0,
TetraBunny::getNodes(),
false,true,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
psb->rotate(btQuaternion(SIMD_PI/2,0,0));
psb->setVolumeMass(150);
psb->m_cfg.piterations=2;
pdemo->m_cutting=true;
}
//
// TetraCube
//
static void Init_TetraCube(SoftDemo* pdemo)
{
btSoftBody* psb=btSoftBodyHelpers::CreateFromTetGenData(pdemo->m_softBodyWorldInfo,
TetraCube::getElements(),
0,
TetraCube::getNodes(),
false,true,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
psb->scale(btVector3(4,4,4));
psb->translate(btVector3(0,5,0));
psb->setVolumeMass(300);
psb->setMass(0,0);
/*psb->setMass(10,0);
psb->setMass(20,0);*/
psb->m_cfg.piterations=1;
//psb->m_materials[0]->m_kLST=0.05;
pdemo->m_cutting=true;
}
#endif //BT_SOFTBODY_USE_STL
//
// Tetra
//
static void Init_Tetra(SoftDemo* pdemo)
{
//TRACEDEMO
#if 0
{
btVector3 pts[]={ btVector3(-1,-1,-1),
btVector3(+1,-1,-1),
btVector3(+1,+1,-1),
btVector3(-1,+1,-1),
btVector3(-1,-1,+1),
btVector3(+1,-1,+1),
btVector3(+1,+1,+1),
btVector3(-1,+1,+1)};
btSoftBody* psb=btSoftBodyHelpers::CreateFromConvexHull(pdemo->m_softBodyWorldInfo,pts,8);
btSoftBodyHelpers::ExportAsSMeshFile(psb,"C:/HomeH/Oss/tetgen/Release/cube.smesh");
delete psb;
/*btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh( pdemo->m_softBodyWorldInfo,gVerticesBunny,
&gIndicesBunny[0][0],
BUNNY_NUM_TRIANGLES);
psb->scale(btVector3(6,6,6));
btSoftBodyHelpers::ExportAsSMeshFile(psb,"C:/HomeH/Oss/tetgen/Release/bunny.smesh");
delete psb;*/
}
btSoftBody* psb=btSoftBodyHelpers::CreateFromTetGenFile(pdemo->m_softBodyWorldInfo,
/*"C:/HomeH/Oss/tetgen/Release/bunny.1.ele",
"C:/HomeH/Oss/tetgen/Release/bunny.1.face",
"C:/HomeH/Oss/tetgen/Release/bunny.1.node",*/
"C:/HomeH/Oss/tetgen/Release/cube.1.ele",
0/*"C:/HomeH/Oss/tetgen/Release/cube.1.face"*/,
"C:/HomeH/Oss/tetgen/Release/cube.1.node",
true,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
psb->scale(btVector3(4,4,4));
/*psb->rotate(btQuaternion(SIMD_PI/4,SIMD_PI/4,0));
psb->translate(btVector3(0,10,0));*/
psb->setVolumeMass(30);
psb->m_cfg.piterations=1;
psb->m_cfg.kKHR=1;
//psb->addVelocity(btVector3(0,50,0));
//psb->m_tetras.clear();
ImplicitSphere fnc;
fnc.center = btVector3(4,4,4);
fnc.radius = 4;
psb->refine(&fnc,0.001,true);
//psb->m_tetras.clear();
printf("Nodes: %u\r\n",psb->m_nodes.size());
printf("Links: %u\r\n",psb->m_links.size());
printf("Faces: %u\r\n",psb->m_faces.size());
printf("Tetras: %u\r\n",psb->m_tetras.size());
#else
#if 1
const btScalar s=4;
const int r=32;
const btVector3 p[]={ btVector3(+s,0,-s),
btVector3(-s,0,-s),
btVector3(+s,0,+s),
btVector3(-s,0,+s)};
btSoftBody* psb=btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo,p[0],p[1],p[2],p[3],r,r,1+2+4+8,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
psb->m_cfg.piterations=2;
/*ImplicitSphere fnc;
fnc.center = btVector3(0,0,0);
fnc.radius = 1.5;
psb->refine(&fnc,0.001,true);*/
//psb->m_faces.clear();
/*fnc.center = btVector3(4,0,4);
fnc.radius = 2;
psb->refine(&fnc,0.001,true);*/
#else
const btScalar s=4;
const btVector3 p[]={ btVector3(+s,-s,0),
btVector3(-s,0,0),
btVector3(0,0,+s),
btVector3(0,+s,0)};
btSoftBody* psb=new btSoftBody(&pdemo->m_softBodyWorldInfo,4,p,0);
psb->appendTetra(0,1,2,3);
psb->appendLink(0,1,1,btSoftBody::eLType::Structural);
psb->appendLink(1,2,1,btSoftBody::eLType::Structural);
psb->appendLink(2,0,1,btSoftBody::eLType::Structural);
psb->appendLink(0,3,1,btSoftBody::eLType::Structural);
psb->appendLink(1,3,1,btSoftBody::eLType::Structural);
psb->appendLink(2,3,1,btSoftBody::eLType::Structural);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
psb->setSolver(btSoftBody::eSolverPresets::Velocities);
psb->m_cfg.viterations=1;
psb->m_cfg.diterations=1;
psb->m_cfg.kDF=0;
psb->m_cfg.kLST=0.000001;
//psb1->m_cfg.diterations=1;
/*btSoftBody* psb0=btSoftBodyHelpers::CreateRope( pdemo->m_softBodyWorldInfo,
btVector3(0,0,0),btVector3(5,0,0),16,1);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb0);
btSoftBody* psb1=btSoftBodyHelpers::CreateRope( pdemo->m_softBodyWorldInfo,
btVector3(0,0,2),btVector3(5,0,2),16,1);
psb1->m_cfg.viterations=1;
psb1->m_cfg.diterations=1;
psb1->setSolver(btSoftBody::eSolverPresets::Velocities);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb1);*/
#endif
#endif
pdemo->toggleIdle();
}
unsigned current_demo=1;
void SoftDemo::clientResetScene()
{
@ -766,6 +976,11 @@ void SoftDemo::clientResetScene()
/* Init */
void (*demofncs[])(SoftDemo*)=
{
Init_Cutting1,
#ifdef BT_SOFTBODY_USE_STL
Init_TetraBunny,
Init_TetraCube,
#endif //BT_SOFTBODY_USE_STL
Init_Cloth,
Init_Pressure,
Init_Volume,
@ -796,6 +1011,7 @@ void SoftDemo::clientResetScene()
m_autocam = false;
m_raycast = false;
m_cutting = false;
demofncs[current_demo](this);
}
@ -813,10 +1029,10 @@ void SoftDemo::renderme()
for(int ib=0;ib<sbs.size();++ib)
{
btSoftBody* psb=sbs[ib];
nps+=psb->getNodes().size();
for(int i=0;i<psb->getNodes().size();++i)
nps+=psb->m_nodes.size();
for(int i=0;i<psb->m_nodes.size();++i)
{
ps+=psb->getNodes()[i].m_x;
ps+=psb->m_nodes[i].m_x;
}
}
ps/=nps;
@ -927,10 +1143,69 @@ void SoftDemo::keyboardCallback(unsigned char key, int x, int y)
case '[': --current_demo;clientResetScene();break;
case ',': m_raycast=!m_raycast;break;
case ';': m_autocam=!m_autocam;break;
case '`':
{
btSoftBodyArray& sbs=getSoftDynamicsWorld()->getSoftBodyArray();
for(int ib=0;ib<sbs.size();++ib)
{
btSoftBody* psb=sbs[ib];
psb->staticSolve(128);
}
}
break;
default: DemoApplication::keyboardCallback(key,x,y);
}
}
//
void SoftDemo::mouseFunc(int button, int state, int x, int y)
{
if(m_cutting&&(state==0)&&(button==0))
{
const btVector3 rayFrom=m_cameraPosition;
const btVector3 rayTo=getRayTo(x,y);
const btVector3 rayDir=(rayTo-rayFrom).normalized();
btSoftBodyArray& sbs=getSoftDynamicsWorld()->getSoftBodyArray();
btSoftBody::sRayCast results;
results.time=SIMD_INFINITY;
for(int ib=0;ib<sbs.size();++ib)
{
btSoftBody* psb=sbs[ib];
btSoftBody::sRayCast res;
if(psb->rayCast(rayFrom,rayDir,res,results.time))
{
results=res;
}
}
if(results.time<SIMD_INFINITY)
{
#if 0
const btVector3 x=rayFrom+rayDir*results.time;
const btSoftBody::Face& f=results.body->m_faces[results.index];
btScalar bestarea=SIMD_INFINITY;
const btSoftBody::Node* n[2]={0,0};
for(int i=2,j=0;j<3;i=j++)
{
const btScalar a2=cross(f.m_n[i]->m_x-x,f.m_n[j]->m_x-x).length2();
if(a2<bestarea)
{
bestarea=a2;
n[0]=f.m_n[i];
n[1]=f.m_n[j];
}
}
results.body->cutLink(n[0],n[1],0.5);
#endif
ImplicitSphere isphere(rayFrom+rayDir*results.time,1);
printf("Mass before: %f\r\n",results.body->getTotalMass());
results.body->refine(&isphere,0.0001,true);
printf("Mass after: %f\r\n",results.body->getTotalMass());
return;
}
}
DemoApplication::mouseFunc(button,state,x,y);
}
void SoftDemo::initPhysics()
{
@ -1051,3 +1326,4 @@ void SoftDemo::exitPhysics()

View File

@ -53,6 +53,7 @@ public:
bool m_autocam;
bool m_cutting;
bool m_raycast;
btScalar m_animtime;
btClock m_clock;
@ -116,6 +117,7 @@ public:
void clientResetScene();
void renderme();
void keyboardCallback(unsigned char key, int x, int y);
void mouseFunc(int button, int state, int x, int y);
};
@ -158,3 +160,4 @@ MACRO_SOFT_DEMO(16)//Init_BunnyMatch

View File

@ -22,6 +22,7 @@ subject to the following restrictions:
#include "RenderingHelpers.h"
#include "GLFontRenderer.h"
#include "btBulletCollisionCommon.h"
#include "BulletSoftBody/btDbvtBroadphase.h"
int numParts =2;
@ -99,7 +100,10 @@ BulletSAPCompleteBoxPruningTest::BulletSAPCompleteBoxPruningTest(int numBoxes,in
}
break;
case 7:
m_broadphase = new btDbvtBroadphase();
methodname = "btDbvtBroadphase";
break;
default:
{
m_broadphase = new btAxisSweep3(aabbMin,aabbMax,numBoxes,new btNullPairCache());
@ -179,7 +183,7 @@ bool BulletSAPCompleteBoxPruningTest::UpdateBoxes(int numBoxes)
{
static bool once=true;
for(udword i=0;i<numBoxes;i++)
for(udword i=0;i<(udword)numBoxes;i++)
{
mBoxTime[i] += mSpeed;
@ -195,18 +199,19 @@ bool BulletSAPCompleteBoxPruningTest::UpdateBoxes(int numBoxes)
return true;
}
extern int doTree;
extern int percentUpdate;
void BulletSAPCompleteBoxPruningTest::PerformTest()
{
int numUpdatedBoxes = (mNbBoxes*10)/100;
int numUpdatedBoxes = (mNbBoxes*percentUpdate)/100;
if (m_firstTime)
{
numUpdatedBoxes = mNbBoxes;
m_firstTime = false;
}
mProfiler.Start();
UpdateBoxes(numUpdatedBoxes);
mPairs.ResetPairs();
@ -240,7 +245,7 @@ void BulletSAPCompleteBoxPruningTest::PerformTest()
btOverlappingPairCache* pairCache = m_broadphase->getOverlappingPairCache();
const btBroadphasePair* pairPtr = pairCache->getOverlappingPairArrayPtr();
for(udword i=0;i<pairCache->getNumOverlappingPairs();i++)
for(udword i=0;i<(udword)pairCache->getNumOverlappingPairs();i++)
{
// Flags[pairPtr[i].m_pProxy0->getUid()-1] = true;
// Flags[pairPtr[i].m_pProxy1->getUid()-1] = true;

View File

@ -32,8 +32,9 @@ subject to the following restrictions:
//#define NUM_SAP_BOXES 8192
//#define NUM_SAP_BOXES 4096
#define NUM_SAP_BOXES 4096
#define NUM_SAP_BOXES 8192
int percentUpdate = 10;
//Broadphase comparison
//Static case (updating 10% of objects to same position ( -> no swaps)
@ -73,8 +74,8 @@ enum TestIndex
MAX_NB_TESTS
};
static int gTest = TEST_BULLET_MULTISAP_8192;
static int gSelectedTest = TEST_BULLET_MULTISAP_8192;
static int gTest = TEST_DBVT_8192;//TEST_BULLET_MULTISAP_8192;
static int gSelectedTest = TEST_DBVT_8192;//TEST_BULLET_MULTISAP_8192;
static CollisionTest* gCollisionTests[MAX_NB_TESTS];
static GLFontRenderer gFnt;
@ -300,6 +301,7 @@ int main(int argc, char** argv)
};
TwType testType = TwDefineEnum("CollisionTest", testEV, MAX_NB_TESTS);
TwAddVarRW(gMainBar, "CollisionTests", testType, &gSelectedTest, "");
TwAddVarRW(gMainBar, "% of updates",TW_TYPE_INT32,&percentUpdate,"min=0 max=100");
}
// Create tests
@ -315,7 +317,7 @@ int main(int argc, char** argv)
// gCollisionTests[TEST_BULLET_SAP_SORTEDPAIRS_8192] = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,3);
gCollisionTests[TEST_BULLET_MULTISAP_8192] = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,6);
// gCollisionTests[TEST_BIPARTITE_BOX_PRUNING] = new BipartiteBoxPruningTest;
gCollisionTests[TEST_DBVT_8192] = new DbvtTest(NUM_SAP_BOXES);
gCollisionTests[TEST_DBVT_8192] = new BulletSAPCompleteBoxPruningTest(NUM_SAP_BOXES,7);
for(int i=0;i<MAX_NB_TESTS;i++)
gCollisionTests[i]->Init();
@ -418,4 +420,4 @@ void BuildBulletTree()
}
#endif
#endif

View File

@ -20,6 +20,8 @@ subject to the following restrictions:
#include "btDispatcher.h"
#include "btCollisionAlgorithm.h"
#include <stdio.h>
int gOverlappingPairs = 0;
int gRemovePairs =0;
@ -133,12 +135,12 @@ void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroad
btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
gFindPairs++;
if(proxy0>proxy1) btSwap(proxy0,proxy1);
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);
/*if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);*/
int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1);
@ -196,8 +198,8 @@ void btHashedOverlappingPairCache::growTables()
const btBroadphasePair& pair = m_overlappingPairArray[i];
int proxyId1 = pair.m_pProxy0->getUid();
int proxyId2 = pair.m_pProxy1->getUid();
if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);
/*if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);*/
int hashValue = getHash(proxyId1,proxyId2) & (m_overlappingPairArray.capacity()-1); // New hash value with new mask
m_next[i] = m_hashTable[hashValue];
m_hashTable[hashValue] = i;
@ -209,11 +211,12 @@ void btHashedOverlappingPairCache::growTables()
btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
{
if(proxy0>proxy1) btSwap(proxy0,proxy1);
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);
/*if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);*/
int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1);
@ -224,7 +227,15 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
{
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.expand();
@ -255,12 +266,12 @@ btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProx
void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
{
gRemovePairs++;
if(proxy0>proxy1) btSwap(proxy0,proxy1);
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);
/*if (proxyId1 > proxyId2)
btSwap(proxyId1, proxyId2);*/
int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1);
@ -316,6 +327,7 @@ void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* pro
// Remove the last pair from the hash table.
const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
/* missing swap here too, Nat. */
int lastHash = getHash(last->m_pProxy0->getUid(), last->m_pProxy1->getUid()) & (m_overlappingPairArray.capacity()-1);
index = m_hashTable[lastHash];
@ -416,6 +428,7 @@ btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseP
void* mem = &m_overlappingPairArray.expand();
btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
gOverlappingPairs++;
gAddedPairs++;
return pair;
}
@ -500,6 +513,7 @@ void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,b
pair.m_algorithm->~btCollisionAlgorithm();
dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
pair.m_algorithm=0;
gRemovePairs--;
}
}
}

View File

@ -225,8 +225,10 @@ private:
{
int proxyId1 = proxy0->getUid();
int proxyId2 = proxy1->getUid();
#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];
@ -432,3 +434,4 @@ public:
#endif //OVERLAPPING_PAIR_CACHE_H

View File

@ -8,6 +8,8 @@ ADD_LIBRARY(LibBulletSoftBody
btSoftBody.h
btSoftBodyHelpers.cpp
btSparseSDF.h
btDbvtBroadphase.cpp
btDbvtBroadphase.h
btDbvt.cpp
btDbvt.h
btSoftBodyHelpers.h
@ -16,6 +18,8 @@ ADD_LIBRARY(LibBulletSoftBody
btSoftRigidCollisionAlgorithm.h
btSoftSoftCollisionAlgorithm.cpp
btSoftSoftCollisionAlgorithm.h
btSoftBodyConcaveCollisionAlgorithm.cpp
btSoftBodyConcaveCollisionAlgorithm.h
btSoftRigidDynamicsWorld.h
btSoftRigidDynamicsWorld.cpp
)

View File

@ -1,3 +1,19 @@
/*
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.
*/
///btDbvt implementation by Nathanael Presson
#include "btDbvt.h"
//
@ -10,16 +26,16 @@ return(node->parent->childs[1]==node);
}
//
static inline btDbvt::Aabb merge( const btDbvt::Aabb& a,
const btDbvt::Aabb& b)
static inline btDbvt::Volume merge( const btDbvt::Volume& a,
const btDbvt::Volume& b)
{
btDbvt::Aabb res;
btDbvt::Volume res;
Merge(a,b,res);
return(res);
}
// volume+edge lengths
static inline btScalar size(const btDbvt::Aabb& a)
static inline btScalar size(const btDbvt::Volume& a)
{
const btVector3 edges=a.Lengths();
return( edges.x()*edges.y()*edges.z()+
@ -50,7 +66,7 @@ deletenode(pdbvt,node);
//
static inline btDbvt::Node* createnode( btDbvt* pdbvt,
btDbvt::Node* parent,
const btDbvt::Aabb& box,
const btDbvt::Volume& volume,
void* data)
{
btDbvt::Node* node;
@ -59,7 +75,7 @@ if(pdbvt->m_free)
else
{ node=new btDbvt::Node(); }
node->parent = parent;
node->box = box;
node->volume = volume;
node->data = data;
node->childs[1] = 0;
return(node);
@ -80,25 +96,25 @@ if(!pdbvt->m_root)
if(!root->isleaf())
{
do {
if( Proximity(root->childs[0]->box,leaf->box)<
Proximity(root->childs[1]->box,leaf->box))
if( Proximity(root->childs[0]->volume,leaf->volume)<
Proximity(root->childs[1]->volume,leaf->volume))
root=root->childs[0];
else
root=root->childs[1];
} while(!root->isleaf());
}
btDbvt::Node* prev=root->parent;
btDbvt::Node* node=createnode(pdbvt,prev,merge(leaf->box,root->box),0);
btDbvt::Node* node=createnode(pdbvt,prev,merge(leaf->volume,root->volume),0);
if(prev)
{
prev->childs[indexof(root)] = node;
node->childs[0] = root;root->parent=node;
node->childs[1] = leaf;leaf->parent=node;
do {
if(prev->box.Contain(node->box))
if(prev->volume.Contain(node->volume))
break;
else
Merge(prev->childs[0]->box,prev->childs[1]->box,prev->box);
Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
node=prev;
} while(0!=(prev=node->parent));
}
@ -132,9 +148,9 @@ if(leaf==pdbvt->m_root)
deletenode(pdbvt,parent);
while(prev)
{
const btDbvt::Aabb pb=prev->box;
Merge(prev->childs[0]->box,prev->childs[1]->box,prev->box);
if(NotEqual(pb,prev->box))
const btDbvt::Volume pb=prev->volume;
Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
if(NotEqual(pb,prev->volume))
{
sibling = prev;
prev = prev->parent;
@ -170,17 +186,6 @@ if(root->isinternal()&&depth)
}
}
//
static int leafcount(btDbvt::Node* root)
{
if(root->isinternal())
{
return( leafcount(root->childs[0])+
leafcount(root->childs[1]));
}
return(1);
}
//
static void split( const tNodeArray& leafs,
tNodeArray& left,
@ -192,7 +197,7 @@ left.resize(0);
right.resize(0);
for(int i=0,ni=leafs.size();i<ni;++i)
{
if(dot(axis,leafs[i]->box.Center()-org)<0)
if(dot(axis,leafs[i]->volume.Center()-org)<0)
left.push_back(leafs[i]);
else
right.push_back(leafs[i]);
@ -200,14 +205,14 @@ for(int i=0,ni=leafs.size();i<ni;++i)
}
//
static btDbvt::Aabb bounds( const tNodeArray& leafs)
static btDbvt::Volume bounds( const tNodeArray& leafs)
{
btDbvt::Aabb box=leafs[0]->box;
btDbvt::Volume volume=leafs[0]->volume;
for(int i=1,ni=leafs.size();i<ni;++i)
{
box=merge(box,leafs[i]->box);
volume=merge(volume,leafs[i]->volume);
}
return(box);
return(volume);
}
//
@ -222,7 +227,7 @@ while(leafs.size()>1)
{
for(int j=i+1;j<leafs.size();++j)
{
const btScalar sz=size(merge(leafs[i]->box,leafs[j]->box));
const btScalar sz=size(merge(leafs[i]->volume,leafs[j]->volume));
if(sz<minsize)
{
minsize = sz;
@ -232,7 +237,7 @@ while(leafs.size()>1)
}
}
btDbvt::Node* n[] = {leafs[minidx[0]],leafs[minidx[1]]};
btDbvt::Node* p = createnode(pdbvt,0,merge(n[0]->box,n[1]->box),0);
btDbvt::Node* p = createnode(pdbvt,0,merge(n[0]->volume,n[1]->volume),0);
p->childs[0] = n[0];
p->childs[1] = n[1];
n[0]->parent = p;
@ -255,15 +260,15 @@ if(leafs.size()>1)
{
if(leafs.size()>bu_treshold)
{
const btDbvt::Aabb box=bounds(leafs);
const btVector3 org=box.Center();
tNodeArray sets[2];
int bestaxis=-1;
int bestmidp=leafs.size();
int splitcount[3][2]={0,0,0,0,0,0};
const btDbvt::Volume vol=bounds(leafs);
const btVector3 org=vol.Center();
tNodeArray sets[2];
int bestaxis=-1;
int bestmidp=leafs.size();
int splitcount[3][2]={0,0,0,0,0,0};
for(int i=0;i<leafs.size();++i)
{
const btVector3 x=leafs[i]->box.Center()-org;
const btVector3 x=leafs[i]->volume.Center()-org;
for(int j=0;j<3;++j)
{
++splitcount[j][dot(x,axis[j])>0?1:0];
@ -296,7 +301,7 @@ if(leafs.size()>1)
sets[i&1].push_back(leafs[i]);
}
}
btDbvt::Node* node=createnode(pdbvt,0,box,0);
btDbvt::Node* node=createnode(pdbvt,0,vol,0);
node->childs[0]=topdown(pdbvt,sets[0],bu_treshold);
node->childs[1]=topdown(pdbvt,sets[1],bu_treshold);
node->childs[0]->parent=node;
@ -344,6 +349,7 @@ return(node);
m_root = 0;
m_free = 0;
m_lkhd = 2;
m_leafs = 0;
}
//
@ -360,21 +366,13 @@ delete m_free;
m_free=0;
}
//
int btDbvt::leafCount() const
{
if(m_root) return(leafcount(m_root));
else
return(0);
}
//
void btDbvt::optimizeBottomUp()
{
if(m_root)
{
tNodeArray leafs;
leafs.reserve(leafCount());
leafs.reserve(m_leafs);
fetchleafs(this,m_root,leafs);
bottomup(this,leafs);
m_root=leafs[0];
@ -387,22 +385,37 @@ void btDbvt::optimizeTopDown(int bu_treshold)
if(m_root)
{
tNodeArray leafs;
leafs.reserve(leafCount());
leafs.reserve(m_leafs);
fetchleafs(this,m_root,leafs);
m_root=topdown(this,leafs,bu_treshold);
}
}
//
btDbvt::Node* btDbvt::insert(const Aabb& box,void* data)
btDbvt::Node* btDbvt::insert(const Volume& volume,void* data)
{
Node* leaf=createnode(this,0,box,data);
Node* leaf=createnode(this,0,volume,data);
insertleaf(this,m_root,leaf);
++m_leafs;
return(leaf);
}
//
void btDbvt::update(Node* leaf,const Aabb& box)
void btDbvt::update(Node* leaf,int lookahead)
{
Node* root=removeleaf(this,leaf);
if(root)
{
for(int i=0;(i<lookahead)&&root->parent;++i)
{
root=root->parent;
}
}
insertleaf(this,root,leaf);
}
//
void btDbvt::update(Node* leaf,const Volume& volume)
{
Node* root=removeleaf(this,leaf);
if(root)
@ -412,19 +425,35 @@ if(root)
root=root->parent;
}
}
leaf->box=box;
leaf->volume=volume;
insertleaf(this,root,leaf);
}
//
bool btDbvt::update(Node* leaf,Aabb box,const btVector3& velocity,btScalar margin)
bool btDbvt::update(Node* leaf,Volume volume,const btVector3& velocity,btScalar margin)
{
if(leaf->box.Contain(box)) return(false);
if(margin>0)
box.Expand(btVector3(margin,margin,margin));
if(velocity.length2()>0)
box.SignedExpand(velocity);
update(leaf,box);
if(leaf->volume.Contain(volume)) return(false);
volume.Expand(btVector3(margin,margin,margin));
volume.SignedExpand(velocity);
update(leaf,volume);
return(true);
}
//
bool btDbvt::update(Node* leaf,Volume volume,const btVector3& velocity)
{
if(leaf->volume.Contain(volume)) return(false);
volume.SignedExpand(velocity);
update(leaf,volume);
return(true);
}
//
bool btDbvt::update(Node* leaf,Volume volume,btScalar margin)
{
if(leaf->volume.Contain(volume)) return(false);
volume.Expand(btVector3(margin,margin,margin));
update(leaf,volume);
return(true);
}
@ -433,109 +462,32 @@ void btDbvt::remove(Node* leaf)
{
removeleaf(this,leaf);
deletenode(this,leaf);
--m_leafs;
}
//
void btDbvt::collide(btDbvt* tree,
ICollide* icollide) const
{
if(tree->m_root&&m_root)
{
btAlignedObjectArray<sStkElm> stack;
stack.reserve(128);
stack.push_back(sStkElm(m_root,tree->m_root));
do {
sStkElm p=stack[stack.size()-1];
stack.pop_back();
if(p.a==p.b)
{
if(p.a->isinternal())
{
stack.push_back(sStkElm(p.a->childs[0],p.a->childs[0]));
stack.push_back(sStkElm(p.a->childs[1],p.a->childs[1]));
stack.push_back(sStkElm(p.a->childs[0],p.a->childs[1]));
}
}
else if(Intersect(p.a->box,p.b->box))
{
if(p.a->isinternal())
{
if(p.b->isinternal())
{
stack.push_back(sStkElm(p.a->childs[0],p.b->childs[0]));
stack.push_back(sStkElm(p.a->childs[1],p.b->childs[0]));
stack.push_back(sStkElm(p.a->childs[0],p.b->childs[1]));
stack.push_back(sStkElm(p.a->childs[1],p.b->childs[1]));
}
else
{
stack.push_back(sStkElm(p.a->childs[0],p.b));
stack.push_back(sStkElm(p.a->childs[1],p.b));
}
}
else
{
if(p.b->isinternal())
{
stack.push_back(sStkElm(p.a,p.b->childs[0]));
stack.push_back(sStkElm(p.a,p.b->childs[1]));
}
else
{
icollide->Process(p.a,p.b);
}
}
}
} while(stack.size()>0);
}
collideGeneric(tree,GCollide(icollide));
}
//
void btDbvt::collide(btDbvt::Node* node,
ICollide* icollide) const
{
collideGeneric(node,GCollide(icollide));
}
//
void btDbvt::collide(const Aabb& box,
void btDbvt::collide(const Volume& volume,
ICollide* icollide) const
{
if(m_root)
{
btAlignedObjectArray<const Node*> stack;
stack.reserve(64);
stack.push_back(m_root);
do {
const Node* n=stack[stack.size()-1];
stack.pop_back();
if(Intersect(n->box,box))
{
if(n->isinternal())
{
stack.push_back(n->childs[0]);
stack.push_back(n->childs[1]);
}
else
{
icollide->Process(n);
}
}
} while(stack.size()>0);
}
collideGeneric(volume,GCollide(icollide));
}
//
void btDbvt::collide(ICollide* icollide) const
{
if(m_root)
{
btAlignedObjectArray<const Node*> stack;
stack.reserve(64);
stack.push_back(m_root);
do {
const Node* n=stack[stack.size()-1];
stack.pop_back();
if(icollide->Descent(n))
{
if(n->isinternal())
{ stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); }
else
{ icollide->Process(n); }
}
} while(stack.size()>0);
}
collideGeneric(GCollide(icollide));
}

View File

@ -12,7 +12,7 @@ subject to the following restrictions:
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.
*/
///btSoftBody implementation by Nathanael Presson
///btDbvt implementation by Nathanael Presson
#ifndef BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
#define BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
@ -20,46 +20,52 @@ subject to the following restrictions:
#include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btVector3.h"
//
// Defaults volumes
//
/* btDbvtAabbMm */
struct btDbvtAabbMm
{
inline btVector3 Center() const { return((mi+mx)/2); }
inline btVector3 Extent() const { return((mx-mi)/2); }
inline const btVector3& Mins() const { return(mi); }
inline const btVector3& Maxs() const { return(mx); }
inline btVector3 Lengths() const { return(mx-mi); }
static inline btDbvtAabbMm FromCE(const btVector3& c,const btVector3& e);
static inline btDbvtAabbMm FromCR(const btVector3& c,btScalar r);
static inline btDbvtAabbMm FromMM(const btVector3& mi,const btVector3& mx);
static inline btDbvtAabbMm FromPoints(const btVector3* pts,int n);
static inline btDbvtAabbMm FromPoints(const btVector3** ppts,int n);
inline void Expand(const btVector3 e);
inline void SignedExpand(const btVector3 e);
inline bool Contain(const btDbvtAabbMm& a) const;
inline friend bool Intersect( const btDbvtAabbMm& a,
const btDbvtAabbMm& b);
inline friend bool Intersect( const btDbvtAabbMm& a,
const btVector3& b);
inline friend btScalar Proximity( const btDbvtAabbMm& a,
const btDbvtAabbMm& b);
inline friend void Merge( const btDbvtAabbMm& a,
const btDbvtAabbMm& b,
btDbvtAabbMm& r);
inline friend bool NotEqual( const btDbvtAabbMm& a,
const btDbvtAabbMm& b);
private:
btVector3 mi,mx;
};
//
// Dynamic bounding volume tree
//
struct btDbvt
{
// Types
/* Aabb */
struct Aabb
{
inline btVector3 Center() const { return((mi+mx)/2); }
inline btVector3 Extent() const { return((mx-mi)/2); }
inline const btVector3& Mins() const { return(mi); }
inline const btVector3& Maxs() const { return(mx); }
inline btVector3 Lengths() const { return(mx-mi); }
static inline Aabb FromCE(const btVector3& c,const btVector3& e);
static inline Aabb FromCR(const btVector3& c,btScalar r);
static inline Aabb FromMM(const btVector3& mi,const btVector3& mx);
static inline Aabb FromPoints(const btVector3* pts,int n);
static inline Aabb FromPoints(const btVector3** ppts,int n);
inline void Expand(const btVector3 e);
inline void SignedExpand(const btVector3 e);
inline bool Contain(const Aabb& a) const;
inline friend bool Intersect( const Aabb& a,
const Aabb& b);
inline friend bool Intersect( const Aabb& a,
const btVector3& b);
inline friend btScalar Proximity( const Aabb& a,
const Aabb& b);
inline friend void Merge( const Aabb& a,
const Aabb& b,
Aabb& r);
inline friend bool NotEqual( const Aabb& a,
const Aabb& b);
btVector3 mi,mx;
};
// Types
typedef btDbvtAabbMm Volume;
/* Node */
struct Node
{
Aabb box;
Volume volume;
Node* parent;
bool isleaf() const { return(childs[1]==0); }
bool isinternal() const { return(!isleaf()); }
@ -83,55 +89,62 @@ struct btDbvt
{
virtual void Process(const Node*,const Node*) {}
virtual void Process(const Node*) {}
virtual bool Descent(const Node*) { return(false); }
virtual bool Descent(const Node*) { return(false); }
};
/* GCollide */
struct GCollide
{
ICollide* icollide;
GCollide(ICollide* ic) : icollide(ic) {}
void Process(const Node* a,const Node* b) { icollide->Process(a,b); }
void Process(const Node* a) { icollide->Process(a); }
bool Descent(const Node* a) { return(icollide->Descent(a)); }
};
// Constants
enum {
TREETREE_STACKSIZE = 128,
VOLUMETREE_STACKSIZE = 64,
};
// Fields
Node* m_root;
Node* m_free;
int m_lkhd;
int m_leafs;
// Methods
btDbvt();
~btDbvt();
void clear();
bool empty() const { return(0==m_root); }
int leafCount() const;
void optimizeBottomUp();
void optimizeTopDown(int bu_treshold=128);
Node* insert(const Aabb& box,void* data);
void update(Node* leaf,const Aabb& box);
bool update(Node* leaf,Aabb box,const btVector3& velocity,btScalar margin);
Node* insert(const Volume& box,void* data);
void update(Node* leaf,int lookahead=1);
void update(Node* leaf,const Volume& volume);
bool update(Node* leaf,Volume volume,const btVector3& velocity,btScalar margin);
bool update(Node* leaf,Volume volume,const btVector3& velocity);
bool update(Node* leaf,Volume volume,btScalar margin);
void remove(Node* leaf);
void collide(btDbvt* tree,
ICollide* icollide) const;
void collide(const Aabb& box,
void collide(btDbvt::Node* node,
ICollide* icollide) const;
void collide(const Volume& volume,
ICollide* icollide) const;
void collide(const btVector3& org,
const btVector3& dir,
ICollide* icollide) const;
void collide(ICollide* icollide) const;
// Generics
template <typename T/* must implement ICollide*/>
void collideGeneric(T& policy) const
{
if(m_root)
{
btAlignedObjectArray<const Node*> stack;
stack.reserve(64);
stack.push_back(m_root);
do {
const Node* n=stack[stack.size()-1];
stack.pop_back();
if(policy.Descent(n))
{
if(n->isinternal())
{ stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); }
else
{ policy.Process(n); }
}
} while(stack.size()>0);
}
}
// Generics : T must implement ICollide
template <typename T>
void collideGeneric( btDbvt* tree,T& policy) const;
template <typename T>
void collideGeneric( btDbvt::Node* node,T& policy) const;
template <typename T>
void collideGeneric(const Volume& volume,T& policy) const;
template <typename T>
void collideGeneric(T& policy) const;
//
private:
btDbvt(const btDbvt&) {}
@ -142,31 +155,31 @@ struct btDbvt
//
//
inline btDbvt::Aabb btDbvt::Aabb::FromCE(const btVector3& c,const btVector3& e)
inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e)
{
Aabb box;
btDbvtAabbMm box;
box.mi=c-e;box.mx=c+e;
return(box);
}
//
inline btDbvt::Aabb btDbvt::Aabb::FromCR(const btVector3& c,btScalar r)
inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c,btScalar r)
{
return(FromCE(c,btVector3(r,r,r)));
}
//
inline btDbvt::Aabb btDbvt::Aabb::FromMM(const btVector3& mi,const btVector3& mx)
inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx)
{
Aabb box;
btDbvtAabbMm box;
box.mi=mi;box.mx=mx;
return(box);
}
//
inline btDbvt::Aabb btDbvt::Aabb::FromPoints(const btVector3* pts,int n)
inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts,int n)
{
Aabb box;
btDbvtAabbMm box;
box.mi=box.mx=pts[0];
for(int i=1;i<n;++i)
{
@ -177,9 +190,9 @@ return(box);
}
//
inline btDbvt::Aabb btDbvt::Aabb::FromPoints(const btVector3** ppts,int n)
inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3** ppts,int n)
{
Aabb box;
btDbvtAabbMm box;
box.mi=box.mx=*ppts[0];
for(int i=1;i<n;++i)
{
@ -190,13 +203,13 @@ return(box);
}
//
inline void btDbvt::Aabb::Expand(const btVector3 e)
inline void btDbvtAabbMm::Expand(const btVector3 e)
{
mi-=e;mx+=e;
}
//
inline void btDbvt::Aabb::SignedExpand(const btVector3 e)
inline void btDbvtAabbMm::SignedExpand(const btVector3 e)
{
if(e.x()>0) mx.setX(mx.x()+e.x()); else mi.setX(mi.x()+e.x());
if(e.y()>0) mx.setY(mx.y()+e.y()); else mi.setY(mi.y()+e.y());
@ -204,7 +217,7 @@ if(e.z()>0) mx.setZ(mx.z()+e.z()); else mi.setZ(mi.z()+e.z());
}
//
inline bool btDbvt::Aabb::Contain(const Aabb& a) const
inline bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const
{
return( (mi.x()<=a.mi.x())&&
(mi.y()<=a.mi.y())&&
@ -215,19 +228,33 @@ return( (mi.x()<=a.mi.x())&&
}
//
inline bool Intersect( const btDbvt::Aabb& a,
const btDbvt::Aabb& b)
inline bool Intersect( const btDbvtAabbMm& a,
const btDbvtAabbMm& b)
{
#if 0
const btScalar mi[]={ b.mx.x()-a.mi.x(),
b.mx.y()-a.mi.y(),
b.mx.z()-a.mi.z()};
const unsigned* imi=(const unsigned*)mi;
if((imi[0]|imi[1]|imi[2])&0x80000000) return(false);
const btScalar mx[]={ a.mx.x()-b.mi.x(),
a.mx.y()-b.mi.y(),
a.mx.z()-b.mi.z()};
const unsigned* imx=(const unsigned*)mx;
if((imx[0]|imx[1]|imx[2])&0x80000000) return(false);
return(true);
#else
return( (a.mi.x()<=b.mx.x())&&
(a.mi.y()<=b.mx.y())&&
(a.mi.z()<=b.mx.z())&&
(a.mx.x()>=b.mi.x())&&
(a.mx.y()>=b.mi.y())&&
(a.mx.z()>=b.mi.z()));
#endif
}
//
inline bool Intersect( const btDbvt::Aabb& a,
inline bool Intersect( const btDbvtAabbMm& a,
const btVector3& b)
{
return( (b.x()>=a.mi.x())&&
@ -239,17 +266,17 @@ return( (b.x()>=a.mi.x())&&
}
//
inline btScalar Proximity( const btDbvt::Aabb& a,
const btDbvt::Aabb& b)
inline btScalar Proximity( const btDbvtAabbMm& a,
const btDbvtAabbMm& b)
{
const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx);
return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z()));
}
//
inline void Merge( const btDbvt::Aabb& a,
const btDbvt::Aabb& b,
btDbvt::Aabb& r)
inline void Merge( const btDbvtAabbMm& a,
const btDbvtAabbMm& b,
btDbvtAabbMm& r)
{
r=a;
r.mi.setMin(b.mi);
@ -257,8 +284,8 @@ r.mx.setMax(b.mx);
}
//
inline bool NotEqual( const btDbvt::Aabb& a,
const btDbvt::Aabb& b)
inline bool NotEqual( const btDbvtAabbMm& a,
const btDbvtAabbMm& b)
{
return( (a.mi.x()!=b.mi.x())||
(a.mi.y()!=b.mi.y())||
@ -268,4 +295,121 @@ return( (a.mi.x()!=b.mi.x())||
(a.mx.z()!=b.mx.z()));
}
//
// Generic's
//
//
template <typename T>
inline void btDbvt::collideGeneric( btDbvt::Node* node,T& policy) const
{
if(m_root&&node)
{
btAlignedObjectArray<sStkElm> stack;
stack.reserve(TREETREE_STACKSIZE);
stack.push_back(sStkElm(m_root,node));
do {
sStkElm p=stack[stack.size()-1];
stack.pop_back();
if(p.a==p.b)
{
if(p.a->isinternal())
{
stack.push_back(sStkElm(p.a->childs[0],p.a->childs[0]));
stack.push_back(sStkElm(p.a->childs[1],p.a->childs[1]));
stack.push_back(sStkElm(p.a->childs[0],p.a->childs[1]));
}
}
else if(Intersect(p.a->volume,p.b->volume))
{
if(p.a->isinternal())
{
if(p.b->isinternal())
{
stack.push_back(sStkElm(p.a->childs[0],p.b->childs[0]));
stack.push_back(sStkElm(p.a->childs[1],p.b->childs[0]));
stack.push_back(sStkElm(p.a->childs[0],p.b->childs[1]));
stack.push_back(sStkElm(p.a->childs[1],p.b->childs[1]));
}
else
{
stack.push_back(sStkElm(p.a->childs[0],p.b));
stack.push_back(sStkElm(p.a->childs[1],p.b));
}
}
else
{
if(p.b->isinternal())
{
stack.push_back(sStkElm(p.a,p.b->childs[0]));
stack.push_back(sStkElm(p.a,p.b->childs[1]));
}
else
{
policy.Process(p.a,p.b);
}
}
}
} while(stack.size()>0);
}
}
//
template <typename T>
inline void btDbvt::collideGeneric( btDbvt* tree,T& policy) const
{
collideGeneric<T>(tree->m_root,policy);
}
//
template <typename T>
inline void btDbvt::collideGeneric(const Volume& volume,T& policy) const
{
if(m_root)
{
btAlignedObjectArray<const Node*> stack;
stack.reserve(VOLUMETREE_STACKSIZE);
stack.push_back(m_root);
do {
const Node* n=stack[stack.size()-1];
stack.pop_back();
if(Intersect(n->volume,volume))
{
if(n->isinternal())
{
stack.push_back(n->childs[0]);
stack.push_back(n->childs[1]);
}
else
{
policy.Process(n);
}
}
} while(stack.size()>0);
}
}
//
template <typename T>
inline void btDbvt::collideGeneric(T& policy) const
{
if(m_root)
{
btAlignedObjectArray<const Node*> stack;
stack.reserve(VOLUMETREE_STACKSIZE);
stack.push_back(m_root);
do {
const Node* n=stack[stack.size()-1];
stack.pop_back();
if(policy.Descent(n))
{
if(n->isinternal())
{ stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); }
else
{ policy.Process(n); }
}
} while(stack.size()>0);
}
}
#endif

View File

@ -0,0 +1,342 @@
/*
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.
*/
///btDbvtBroadphase implementation by Nathanael Presson
#include "btDbvtBroadphase.h"
//
// Profiling
//
#if DBVT_BP_PROFILE
#include <stdio.h>
struct ProfileScope
{
ProfileScope(btClock& clock,unsigned long& value)
{
m_clock=&clock;
m_value=&value;
m_base=clock.getTimeMicroseconds();
}
~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
//
//
static inline int hash(unsigned int i,unsigned int j)
{
int key=((unsigned int)i)|(((unsigned int)j)<<16);
key+=~(key<<15);
key^= (key>>10);
key+= (key<<3);
key^= (key>>6);
key+=~(key<<11);
key^= (key>>16);
return(key);
}
//
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 T zerodummy;
value=zerodummy;
}
//
// Collider
//
struct btDbvtBroadphaseCollider : btDbvt::ICollide
{
btDbvtBroadphase* pbp;
int pid;
btDbvtBroadphaseCollider(btDbvtBroadphase* p,int id) : pbp(p),pid(id) {}
void Process(const btDbvt::Node* na,const btDbvt::Node* nb)
{
btDbvtProxy* pa=(btDbvtProxy*)na->data;
btDbvtProxy* pb=(btDbvtProxy*)nb->data;
#if DBVT_BP_DISCRETPAIRS
if(Intersect(pa->aabb,pb->aabb))
#endif
{
btBroadphasePair* pp=pbp->m_paircache->addOverlappingPair(pa,pb);
if(pp) pp->m_userInfo=*(void**)&pid;
}
}
};
//
// btDbvtBroadphase
//
//
btDbvtBroadphase::btDbvtBroadphase()
{
m_fcursor = 0;
m_dcursor = 0;
m_stageCurrent = 0;
m_fupdates = 1;
m_dupdates = 0;
m_paircache = new btHashedOverlappingPairCache();
m_gid = 0;
m_pid = 0;
for(int i=0;i<=STAGECOUNT;++i)
{
m_stageRoots[i]=0;
}
#if DBVT_BP_PROFILE
clear(m_profiling);
#endif
}
//
btDbvtBroadphase::~btDbvtBroadphase()
{
delete m_paircache;
}
//
btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin,
const btVector3& aabbMax,
int shapeType,
void* userPtr,
short int collisionFilterGroup,
short int collisionFilterMask,
btDispatcher* dispatcher,
void* multiSapProxy)
{
btDbvtProxy* proxy=new btDbvtProxy(userPtr,collisionFilterGroup,collisionFilterMask);
proxy->aabb = btDbvtAabbMm::FromMM(aabbMin,aabbMax);
proxy->leaf = m_sets[0].insert(proxy->aabb,proxy);
proxy->stage = m_stageCurrent;
proxy->m_uniqueId = ++m_gid;
listappend(proxy,m_stageRoots[m_stageCurrent]);
return(proxy);
}
//
void btDbvtBroadphase::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,dispatcher);
delete proxy;
}
//
void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy,
const btVector3& aabbMin,
const btVector3& aabbMax,
btDispatcher* dispatcher)
{
btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
btDbvtAabbMm aabb=btDbvtAabbMm::FromMM(aabbMin,aabbMax);
if(proxy->stage==STAGECOUNT)
{/* fixed -> dynamic set */
m_sets[1].remove(proxy->leaf);
proxy->leaf=m_sets[0].insert(aabb,proxy);
m_fcursor=0;
}
else
{/* dynamic set */
const btVector3 delta=(aabbMin+aabbMax)/2-proxy->aabb.Center();
m_sets[0].update(proxy->leaf,aabb,delta*PREDICTED_FRAMES,DBVT_BP_MARGIN);
}
listremove(proxy,m_stageRoots[proxy->stage]);
proxy->aabb = aabb;
proxy->stage = m_stageCurrent;
listappend(proxy,m_stageRoots[m_stageCurrent]);
}
//
void btDbvtBroadphase::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_leafs,m_sets[0].m_leafs,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);
clear(m_profiling);
m_clock.reset();
}
#endif
}
//
void btDbvtBroadphase::collide(btDispatcher* dispatcher)
{
SPC(m_profiling.m_total);
/* refine dynamic */
if(m_stageRoots[m_stageCurrent]&&(m_dupdates>0))
{
const int count=1+(m_sets[0].m_leafs*m_dupdates)/100;
for(int i=0;i<count;++i)
{
if(!m_dcursor) m_dcursor=m_stageRoots[m_stageCurrent];
m_sets[0].update(m_dcursor->leaf);
m_dcursor=m_dcursor->links[1];
}
}
/* dynamic -> fixed set */
m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
btDbvtProxy* current=m_stageRoots[m_stageCurrent];
if(current)
{
btDbvtBroadphaseCollider collider(this,m_pid);
do {
btDbvtProxy* next=current->links[1];
if(m_dcursor==current) m_dcursor=0;
listremove(current,m_stageRoots[current->stage]);
listappend(current,m_stageRoots[STAGECOUNT]);
m_sets[1].collideGeneric(current->leaf,collider);
m_sets[0].remove(current->leaf);
current->leaf = m_sets[1].insert(current->aabb,current);
current->stage = STAGECOUNT;
current = next;
} while(current);
}
/* refine fixed */
if(m_stageRoots[STAGECOUNT]&&(m_fupdates>0))
{
const int count=1+(m_sets[1].m_leafs*m_fupdates)/100;
for(int i=0;i<count;++i)
{
if(!m_fcursor) m_fcursor=m_stageRoots[STAGECOUNT];
m_sets[1].update(m_fcursor->leaf);
m_fcursor=m_fcursor->links[1];
}
}
/* collide dynamics */
btDbvtBroadphaseCollider collider(this,m_pid);
{
SPC(m_profiling.m_fdcollide);
m_sets[0].collideGeneric(&m_sets[1],collider);
}
{
SPC(m_profiling.m_ddcollide);
m_sets[0].collideGeneric(&m_sets[0],collider);
}
/* clean up */
{
SPC(m_profiling.m_cleanup);
btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray();
for(int i=0,ni=pairs.size();i<ni;++i)
{
btBroadphasePair& p=pairs[i];
if(m_pid!=(*(int*)&p.m_userInfo))
{
btDbvtProxy* pa=(btDbvtProxy*)p.m_pProxy0;
btDbvtProxy* pb=(btDbvtProxy*)p.m_pProxy1;
if(!Intersect(pa->aabb,pb->aabb))
{
m_paircache->removeOverlappingPair(pa,pb,dispatcher);
--ni;--i;
}
}
}
}
++m_pid;
}
//
btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache()
{
return(m_paircache);
}
//
const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const
{
return(m_paircache);
}
//
void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
{
btDbvtAabbMm 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=btDbvtAabbMm::FromCR(btVector3(0,0,0),0);
aabbMin=bounds.Mins();
aabbMax=bounds.Maxs();
}
//
void btDbvtBroadphase::printStats()
{}
#if DBVT_BP_PROFILE
#undef SPC
#endif

View File

@ -0,0 +1,108 @@
/*
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.
*/
///btDbvtBroadphase implementation by Nathanael Presson
#ifndef BT_DBVT_BROADPHASE_H
#define BT_DBVT_BROADPHASE_H
#include "btDbvt.h"
#include "LinearMath/btPoint3.h"
#include "LinearMath/btVector3.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
//
// Compile time config
//
#define DBVT_BP_PROFILE 1
#define DBVT_BP_DISCRETPAIRS 0
#define DBVT_BP_MARGIN (btScalar)0.05
#if DBVT_BP_PROFILE
#define DBVT_BP_PROFILING_RATE 50
#include "LinearMath/btQuickprof.h"
#endif
//
// btDbvtProxy
//
struct btDbvtProxy : btBroadphaseProxy
{
/* Fields */
btDbvtAabbMm aabb;
btDbvt::Node* leaf;
btDbvtProxy* links[2];
int stage;
/* ctor */
btDbvtProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask)
{
links[0]=links[1]=0;
}
};
//
// btDbvtBroadphase
//
struct btDbvtBroadphase : btBroadphaseInterface
{
/* Config */
enum {
DYNAMIC_SET = 0, /* Dynamic set index */
FIXED_SET = 1, /* Fixed set index */
STAGECOUNT = 2, /* Number of stages */
PREDICTED_FRAMES = 2, /* Frames prediction */
};
/* Fields */
btDbvt m_sets[2]; // Dbvt sets
btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list
int m_stageCurrent; // Current stage
btOverlappingPairCache* m_paircache; // Pair cache
btDbvtProxy* m_fcursor; // Current fixed cursor
btDbvtProxy* m_dcursor; // Current dynamic cursor
int m_fupdates; // % of fixed updates per frame
int m_dupdates; // % of dynamic updates per frame
int m_pid; // Parse id
int m_gid; // Gen id
#if DBVT_BP_PROFILE
btClock m_clock;
struct {
unsigned long m_total;
unsigned long m_ddcollide;
unsigned long m_fdcollide;
unsigned long m_cleanup;
} m_profiling;
#endif
/* Methods */
btDbvtBroadphase();
~btDbvtBroadphase();
void collide(btDispatcher* dispatcher);
/* btBroadphaseInterface Implementation */
btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
void calculateOverlappingPairs(btDispatcher* dispatcher);
btOverlappingPairCache* getOverlappingPairCache();
const btOverlappingPairCache* getOverlappingPairCache() const;
void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
void printStats();
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -39,12 +39,6 @@ public:
// Enumerations
//
///eLType
struct eLType { enum _ {
Structural, ///Master constraints
Bending, ///Secondary constraints
};};
///eAeroModel
struct eAeroModel { enum _ {
V_Point, ///Vertex normals are oriented toward velocity
@ -54,6 +48,40 @@ public:
F_OneSided, ///Face normals are taken as it is
};};
///eVSolver : velocities solvers
struct eVSolver { enum _ {
Linear, ///Linear solver
Volume, ///Volume solver
};};
///ePSolver : positions solvers
struct ePSolver { enum _ {
Linear, ///Linear solver
Volume, ///Volume solver
Anchors, ///Anchor solver
RContacts, ///Rigid contacts solver
SContacts, ///Soft contacts solver
};};
///eSolverPresets
struct eSolverPresets { enum _ {
Positions,
Velocities,
Default = Positions,
};};
///eFeature
struct eFeature { enum _ {
None,
Node,
Link,
Face,
Tetra,
};};
typedef btAlignedObjectArray<eVSolver::_> tVSolverArray;
typedef btAlignedObjectArray<ePSolver::_> tPSolverArray;
//
// Flags
//
@ -69,6 +97,13 @@ public:
Default = SDF_RS,
};};
///fMaterial
struct fMaterial { enum _ {
DebugDraw = 0x0001, /// Enable debug draw
/* presets */
Default = DebugDraw,
};};
//
// API Types
//
@ -76,8 +111,16 @@ public:
/* sRayCast */
struct sRayCast
{
int face; /// face
btScalar time; /// time of impact (rayorg+raydir*time)
btSoftBody* body; /// soft body
eFeature::_ feature; /// feature type
int index; /// feature index
btScalar time; /// time of impact (rayorg+raydir*time)
};
/* ImplicitFn */
struct ImplicitFn
{
virtual btScalar Eval(const btVector3& x)=0;
};
//
@ -86,7 +129,6 @@ public:
typedef btAlignedObjectArray<btScalar> tScalarArray;
typedef btAlignedObjectArray<btVector3> tVector3Array;
/* btSoftBodyWorldInfo */
struct btSoftBodyWorldInfo
{
@ -121,8 +163,22 @@ public:
{
void* m_tag; // User data
};
/* Material */
struct Material : Element
{
btScalar m_kLST; // Linear stiffness coefficient [0,1]
btScalar m_kAST; // Area stiffness coefficient [0,1]
btScalar m_kVST; // Volume stiffness coefficient [0,1]
int m_flags; // Flags
};
/* Feature */
struct Feature : Element
{
Material* m_material; // Material
};
/* Node */
struct Node : Element
struct Node : Feature
{
btVector3 m_x; // Position
btVector3 m_q; // Previous step position
@ -135,23 +191,33 @@ public:
int m_battach:1; // Attached
};
/* Link */
struct Link : Element
struct Link : Feature
{
Node* m_n[2]; // Node pointers
btScalar m_rl; // Rest length
btScalar m_kST; // Stiffness coefficient
btScalar m_c0; // (ima+imb)*kLST
btScalar m_c1; // rl^2
btSoftBody::eLType::_ m_type; // Link type
btScalar m_c2; // |gradient|^2/c0
btVector3 m_c3; // gradient
};
/* Face */
struct Face : Element
struct Face : Feature
{
Node* m_n[3]; // Node pointers
btVector3 m_normal; // Normal
btScalar m_ra; // Rest area
btDbvt::Node* m_leaf; // Leaf data
};
/* Tetra */
struct Tetra : Feature
{
Node* m_n[4]; // Node pointers
btScalar m_rv; // Rest volume
btDbvt::Node* m_leaf; // Leaf data
btVector3 m_c0[4]; // gradients
btScalar m_c1; // (4*kVST)/(im0+im1+im2+im3)
btScalar m_c2; // m_c1/sum(|g0..3|^2)
};
/* RContact */
struct RContact
{
@ -184,6 +250,15 @@ public:
btVector3 m_c1; // Relative anchor
btScalar m_c2; // ima*dt
};
/* Note */
struct Note : Element
{
const char* m_text; // Text
btVector3 m_offset; // Offset
int m_rank; // Rank
Node* m_nodes[4]; // Nodes
btScalar m_coords[4]; // Coordinates
};
/* Pose */
struct Pose
{
@ -197,16 +272,11 @@ public:
btMatrix3x3 m_scl; // Scale
btMatrix3x3 m_aqq; // Base scaling
};
/* DFld */
struct DFld
{
btAlignedObjectArray<btVector3> pts;
};
/* Config */
struct Config
{
btSoftBody::eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point)
btScalar kLST; // Linear stiffness coefficient [0,1]
eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point)
btScalar kVCF; // Velocities correction factor (Baumgarte)
btScalar kDP; // Damping coefficient [0,1]
btScalar kDG; // Drag coefficient [0,+inf]
btScalar kLF; // Lift coefficient [0,+inf]
@ -214,19 +284,23 @@ public:
btScalar kVC; // Volume conversation coefficient [0,+inf]
btScalar kDF; // Dynamic friction coefficient [0,1]
btScalar kMT; // Pose matching coefficient [0,1]
btScalar kSOR; // SOR(w) [1,2] default 1, never use with solver!=Accurate
btScalar kCHR; // Rigid contacts hardness [0,1]
btScalar kKHR; // Kinetic contacts hardness [0,1]
btScalar kSHR; // Soft contacts hardness [0,1]
btScalar kAHR; // Anchors hardness [0,1]
btScalar maxvolume; // Maximum volume ratio for pose
btScalar timescale; // Time scale
int iterations; // Solver iterations
int viterations; // Velocities solver iterations
int piterations; // Positions solver iterations
int diterations; // Drift solver iterations
int collisions; // Collisions flags
tVSolverArray m_vsequence; // Velocity solvers sequence
tPSolverArray m_psequence; // Position solvers sequence
tPSolverArray m_dsequence; // Drift solvers sequence
};
/* SolverState */
struct SolverState
{
btScalar iit; // 1/iterations
btScalar sdt; // dt*timescale
btScalar isdt; // 1/sdt
btScalar velmrg; // velocity margin
@ -238,14 +312,17 @@ public:
// Typedef's
//
typedef btAlignedObjectArray<Note> tNoteArray;
typedef btAlignedObjectArray<Node> tNodeArray;
typedef btAlignedObjectArray<btDbvt::Node*> tLeafArray;
typedef btAlignedObjectArray<Link> tLinkArray;
typedef btAlignedObjectArray<Face> tFaceArray;
typedef btAlignedObjectArray<Tetra> tTetraArray;
typedef btAlignedObjectArray<Anchor> tAnchorArray;
typedef btAlignedObjectArray<RContact> tRContactArray;
typedef btAlignedObjectArray<SContact> tSContactArray;
typedef btAlignedObjectArray<btSoftBody*> tSoftBodyArray;
typedef btAlignedObjectArray<Material*> tMaterialArray;
typedef btAlignedObjectArray<btSoftBody*> tSoftBodyArray;
//
// Fields
@ -254,18 +331,22 @@ public:
Config m_cfg; // Configuration
SolverState m_sst; // Solver state
Pose m_pose; // Pose
DFld m_dfld; // Distance field
void* m_tag; // User data
btSoftBodyWorldInfo* m_worldInfo; //
tNoteArray m_notes; // Notes
tNodeArray m_nodes; // Nodes
tLinkArray m_links; // Links
tFaceArray m_faces; // Faces
tTetraArray m_tetras; // Tetras
tAnchorArray m_anchors; // Anchors
tRContactArray m_rcontacts; // Rigid contacts
tSContactArray m_scontacts; // Soft contacts
tMaterialArray m_materials; // Materials
btScalar m_timeacc; // Time accumulator
btVector3 m_bounds[2]; // Spatial bounds
bool m_bUpdateRtCst; // Update runtime constants
btDbvt m_ndbvt; // Nodes tree
btDbvt m_fdbvt; // Faces tree
//
// Api
//
@ -285,71 +366,120 @@ public:
bool checkFace( int node0,
int node1,
int node2) const;
/* Append material */
Material* appendMaterial();
/* Append note */
void appendNote( const char* text,
const btVector3& o,
const btVector4& c=btVector4(1,0,0,0),
Node* n0=0,
Node* n1=0,
Node* n2=0,
Node* n3=0);
void appendNote( const char* text,
const btVector3& o,
Node* feature);
void appendNote( const char* text,
const btVector3& o,
Link* feature);
void appendNote( const char* text,
const btVector3& o,
Face* feature);
void appendNote( const char* text,
const btVector3& o,
Tetra* feature);
/* Append node */
void appendNode( const btVector3& x,btScalar m);
/* Append link */
void appendLink( int node0,
int node1,
btScalar kST,
btSoftBody::eLType::_ type,
bool bcheckexist=false);
void appendLink( btSoftBody::Node* node0,
btSoftBody::Node* node1,
btScalar kST,
btSoftBody::eLType::_ type,
bool bcheckexist=false);
void appendLink(int model=-1,Material* mat=0);
void appendLink( int node0,
int node1,
Material* mat=0,
bool bcheckexist=false);
void appendLink( btSoftBody::Node* node0,
btSoftBody::Node* node1,
Material* mat=0,
bool bcheckexist=false);
/* Append face */
void appendFace( int node0,
int node1,
int node2);
void appendFace(int model=-1,Material* mat=0);
void appendFace( int node0,
int node1,
int node2,
Material* mat=0);
/* Append tetrahedron */
void appendTetra(int model=-1,Material* mat=0);
void appendTetra(int node0,
int node1,
int node2,
int node3,
Material* mat=0);
/* Append anchor */
void appendAnchor( int node,
btRigidBody* body);
btRigidBody* body);
/* Add force (or gravity) to the entire body */
void addForce( const btVector3& force);
/* Add force (or gravity) to a node of the body */
void addForce( const btVector3& force,
int node);
int node);
/* Add velocity to the entire body */
void addVelocity( const btVector3& velocity);
/* Add velocity to a node of the body */
void addVelocity( const btVector3& velocity,
int node);
int node);
/* Set mass */
void setMass( int node,
btScalar mass);
btScalar mass);
/* Get mass */
btScalar getMass( int node) const;
/* Get total mass */
btScalar getTotalMass() const;
/* Set total mass (weighted by previous masses) */
void setTotalMass( btScalar mass,
bool fromfaces=false);
bool fromfaces=false);
/* Set total density */
void setTotalDensity(btScalar density);
/* Set volume mass (using tetrahedrons) */
void setVolumeMass( btScalar mass);
/* Set volume density (using tetrahedrons) */
void setVolumeDensity( btScalar density);
/* Transform */
void transform( const btTransform& trs);
/* Translate */
void translate( const btVector3& trs);
/* Rotate */
void rotate( const btQuaternion& rot);
/* Scale */
void scale( const btVector3& scl);
void scale( const btVector3& scl);
/* Set current state as pose */
void setPose( bool bvolume,
bool bframe);
/* Set current state as distance field */
void setDistanceField(int nominalresolution);
/* Return the volume */
btScalar getVolume() const;
/* Generate bending constraints based on distance in the adjency graph */
int generateBendingConstraints( int distance,
btScalar stiffness);
Material* mat=0);
/* Generate tetrahedral constraints */
int generateTetrahedralConstraints();
/* Randomize constraints to reduce solver bias */
void randomizeConstraints();
/* Refine */
void refine(ImplicitFn* ifn,btScalar accurary,bool cut);
/* CutLink */
bool cutLink(int node0,int node1,btScalar position);
bool cutLink(const Node* node0,const Node* node1,btScalar position);
/* Ray casting */
bool rayCast(const btVector3& org,
const btVector3& dir,
sRayCast& results,
btScalar maxtime=SIMD_INFINITY);
/* Solver presets */
void setSolver(eSolverPresets::_ preset);
/* predictMotion */
void predictMotion(btScalar dt);
/* solveConstraints */
void solveConstraints();
/* staticSolve */
void staticSolve(int iterations);
/* solveCommonConstraints */
static void solveCommonConstraints(btSoftBody** bodies,int count,int iterations);
/* integrateMotion */
@ -357,24 +487,7 @@ public:
/* defaultCollisionHandlers */
void defaultCollisionHandler(btCollisionObject* pco);
void defaultCollisionHandler(btSoftBody* psb);
//
// Accessor's and cast.
//
tNodeArray& getNodes();
const tNodeArray& getNodes() const;
tLinkArray& getLinks();
const tLinkArray& getLinks() const;
tFaceArray& getFaces();
const tFaceArray& getFaces() const;
virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const
{
aabbMin = m_bounds[0];
aabbMax = m_bounds[1];
}
//
// Cast
//
@ -391,6 +504,13 @@ public:
return (btSoftBody*)colObj;
return 0;
}
virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const
{
aabbMin = m_bounds[0];
aabbMax = m_bounds[1];
}
};

View File

@ -71,15 +71,27 @@ if(node)
if(depth>=mindepth)
{
const btScalar scl=(btScalar)(node->isinternal()?1:1);
const btVector3 mi=node->box.Center()-node->box.Extent()*scl;
const btVector3 mx=node->box.Center()+node->box.Extent()*scl;
const btVector3 mi=node->volume.Center()-node->volume.Extent()*scl;
const btVector3 mx=node->volume.Center()+node->volume.Extent()*scl;
drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor);
}
}
}
//
#if 0
//
static inline btScalar tetravolume(const btVector3& x0,
const btVector3& x1,
const btVector3& x2,
const btVector3& x3)
{
const btVector3 a=x1-x0;
const btVector3 b=x2-x0;
const btVector3 c=x3-x0;
return(dot(a,cross(b,c)));
}
//
static btVector3 stresscolor(btScalar stress)
{
static const btVector3 spectrum[]= { btVector3(1,0,1),
@ -96,7 +108,6 @@ static btVector3 stresscolor(btScalar stress)
const btScalar frc=stress-sel;
return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc);
}
#endif
//
void btSoftBodyHelpers::Draw( btSoftBody* psb,
@ -105,16 +116,16 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb,
{
const btScalar scl=(btScalar)0.1;
const btScalar nscl=scl*5;
const btVector3 scolor=btVector3(0,0,0);
const btVector3 bcolor=btVector3(1,1,0);
const btVector3 lcolor=btVector3(0,0,0);
const btVector3 ncolor=btVector3(1,1,1);
const btVector3 ccolor=btVector3(1,0,0);
/* Nodes */
if(0!=(drawflags&fDrawFlags::Nodes))
{
for(int i=0;i<psb->getNodes().size();++i)
for(int i=0;i<psb->m_nodes.size();++i)
{
const btSoftBody::Node& n=psb->getNodes()[i];
const btSoftBody::Node& n=psb->m_nodes[i];
if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0));
idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0));
idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1));
@ -123,24 +134,20 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb,
/* Links */
if(0!=(drawflags&fDrawFlags::Links))
{
for(int i=0;i<psb->getLinks().size();++i)
for(int i=0;i<psb->m_links.size();++i)
{
const btSoftBody::Link& l=psb->getLinks()[i];
switch(l.m_type)
{
case btSoftBody::eLType::Structural:
if(0!=(drawflags&fDrawFlags::SLinks)) idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,scolor);break;
case btSoftBody::eLType::Bending:
if(0!=(drawflags&fDrawFlags::BLinks)) idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,bcolor);break;
}
const btSoftBody::Link& l=psb->m_links[i];
if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor);
}
}
/* Normals */
if(0!=(drawflags&fDrawFlags::Normals))
{
for(int i=0;i<psb->getNodes().size();++i)
for(int i=0;i<psb->m_nodes.size();++i)
{
const btSoftBody::Node& n=psb->getNodes()[i];
const btSoftBody::Node& n=psb->m_nodes[i];
if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
const btVector3 d=n.m_n*nscl;
idraw->drawLine(n.m_x,n.m_x+d,ncolor);
idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5);
@ -175,9 +182,10 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb,
drawVertex(idraw,q,0.25,btVector3(0,1,0));
idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1));
}
for(int i=0;i<psb->getNodes().size();++i)
for(int i=0;i<psb->m_nodes.size();++i)
{
const btSoftBody::Node& n=psb->getNodes()[i];
const btSoftBody::Node& n=psb->m_nodes[i];
if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
if(n.m_im<=0)
{
drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0));
@ -187,21 +195,61 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb,
/* Faces */
if(0!=(drawflags&fDrawFlags::Faces))
{
const btScalar scl=(btScalar)0.7;
const btScalar scl=(btScalar)0.8;
const btScalar alp=(btScalar)1;
const btVector3 col(0,(btScalar)0.7,0);
for(int i=0;i<psb->getFaces().size();++i)
for(int i=0;i<psb->m_faces.size();++i)
{
const btSoftBody::Face& f=psb->getFaces()[i];
const btSoftBody::Face& f=psb->m_faces[i];
if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x};
const btVector3 c=(x[0]+x[1]+x[2])/3;
/*idraw->drawLine((x[0]-c)*scl+c,(x[1]-c)*scl+c,col);
idraw->drawLine((x[1]-c)*scl+c,(x[2]-c)*scl+c,col);
idraw->drawLine((x[2]-c)*scl+c,(x[0]-c)*scl+c,col);*/
idraw->drawTriangle((x[0]-c)*scl+c,
(x[1]-c)*scl+c,
(x[2]-c)*scl+c,
col,alp);
/*idraw->drawTriangle((x[0]-c)*scl+c,
(x[1]-c)*scl+c,
(x[2]-c)*scl+c,
f.m_n[0]->m_n,f.m_n[1]->m_n,f.m_n[2]->m_n,
col,alp);
col,alp);*/
}
}
/* Tetras */
if(0!=(drawflags&fDrawFlags::Tetras))
{
const btScalar scl=(btScalar)0.8;
const btScalar alp=(btScalar)1;
const btVector3 col((btScalar)0.7,(btScalar)0.7,(btScalar)0.7);
for(int i=0;i<psb->m_tetras.size();++i)
{
const btSoftBody::Tetra& t=psb->m_tetras[i];
if(0==(t.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
const btVector3 x[]={t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x};
const btVector3 c=(x[0]+x[1]+x[2]+x[3])/4;
idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[2]-c)*scl+c,col,alp);
idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
idraw->drawTriangle((x[1]-c)*scl+c,(x[2]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
idraw->drawTriangle((x[2]-c)*scl+c,(x[0]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
}
}
/* Notes */
if(0!=(drawflags&fDrawFlags::Notes))
{
for(int i=0;i<psb->m_notes.size();++i)
{
const btSoftBody::Note& n=psb->m_notes[i];
btVector3 p=n.m_offset;
for(int j=0;j<n.m_rank;++j)
{
p+=n.m_nodes[j]->m_x*n.m_coords[j];
}
idraw->draw3dText(p,n.m_text);
}
}
}
//
@ -211,9 +259,9 @@ void btSoftBodyHelpers::DrawInfos( btSoftBody* psb,
bool areas,
bool /*stress*/)
{
for(int i=0;i<psb->getNodes().size();++i)
for(int i=0;i<psb->m_nodes.size();++i)
{
const btSoftBody::Node& n=psb->getNodes()[i];
const btSoftBody::Node& n=psb->m_nodes[i];
char text[2048]={0};
char buff[1024];
if(masses)
@ -269,11 +317,6 @@ void btSoftBodyHelpers::DrawFrame( btSoftBody* psb,
const btVector3 x=com+trs*psb->m_pose.m_pos[i];
drawVertex(idraw,x,nscl,btVector3(1,0,1));
}
for(int i=0;i<psb->m_dfld.pts.size();++i)
{
const btVector3 x=com+trs*psb->m_dfld.pts[i];
drawVertex(idraw,x,nscl*(btScalar)0.5,btVector3(0,0,1));
}
}
}
@ -301,7 +344,7 @@ btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBody::btSoftBodyWorldInfo& wor
/* Create links */
for(int i=1;i<r;++i)
{
psb->appendLink(i-1,i,1,btSoftBody::eLType::Structural);
psb->appendLink(i-1,i);
}
/* Finished */
return(psb);
@ -352,10 +395,8 @@ btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBody::btSoftBodyWorldInfo& wor
const int idx=IDX(ix,iy);
const bool mdx=(ix+1)<rx;
const bool mdy=(iy+1)<ry;
if(mdx) psb->appendLink(idx,IDX(ix+1,iy),
1,btSoftBody::eLType::Structural);
if(mdy) psb->appendLink(idx,IDX(ix,iy+1),
1,btSoftBody::eLType::Structural);
if(mdx) psb->appendLink(idx,IDX(ix+1,iy));
if(mdy) psb->appendLink(idx,IDX(ix,iy+1));
if(mdx&&mdy)
{
if((ix+iy)&1)
@ -364,8 +405,7 @@ btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBody::btSoftBodyWorldInfo& wor
psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1));
if(gendiags)
{
psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1),
1,btSoftBody::eLType::Structural);
psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1));
}
}
else
@ -374,8 +414,7 @@ btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBody::btSoftBodyWorldInfo& wor
psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1));
if(gendiags)
{
psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1),
1,btSoftBody::eLType::Structural);
psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1));
}
}
}
@ -448,7 +487,7 @@ btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBody::btSoftBodyWorldInf
{
chks[IDX(idx[j],idx[k])]=true;
chks[IDX(idx[k],idx[k])]=true;
psb->appendLink(idx[j],idx[k],1,btSoftBody::eLType::Structural);
psb->appendLink(idx[j],idx[k]);
}
}
#undef IDX
@ -474,12 +513,9 @@ btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBody::btSoftBodyWorld
const int idx[]={ hres.m_Indices[i*3+0],
hres.m_Indices[i*3+1],
hres.m_Indices[i*3+2]};
if(idx[0]<idx[1]) psb->appendLink( idx[0],idx[1],
1,btSoftBody::eLType::Structural);
if(idx[1]<idx[2]) psb->appendLink( idx[1],idx[2],
1,btSoftBody::eLType::Structural);
if(idx[2]<idx[0]) psb->appendLink( idx[2],idx[0],
1,btSoftBody::eLType::Structural);
if(idx[0]<idx[1]) psb->appendLink( idx[0],idx[1]);
if(idx[1]<idx[2]) psb->appendLink( idx[1],idx[2]);
if(idx[2]<idx[0]) psb->appendLink( idx[2],idx[0]);
psb->appendFace(idx[0],idx[1],idx[2]);
}
hlib.ReleaseResult(hres);
@ -487,4 +523,154 @@ btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBody::btSoftBodyWorld
return(psb);
}
#if BT_SOFTBODY_USE_STL
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <stdio.h>
//
void btSoftBodyHelpers::ExportAsSMeshFile(btSoftBody* psb,
const char* filename)
{
std::ofstream output(filename);
output << psb->m_nodes.size() << " " << 3 << " " << 0 << " " << 0 << "\n";
for(int i=0;i<psb->m_nodes.size();++i)
{
const btSoftBody::Node& n=psb->m_nodes[i];
output << i << " "
<< n.m_x.x() << " "
<< n.m_x.y() << " "
<< n.m_x.z() << "\n";
}
output << psb->m_faces.size() << " " << 1 << "\n";
for(int i=0;i<psb->m_faces.size();++i)
{
const btSoftBody::Node* b=&psb->m_nodes[0];
const btSoftBody::Face& f=psb->m_faces[i];
output << 3 << " "
<< int(f.m_n[0]-b) << " "
<< int(f.m_n[1]-b) << " "
<< int(f.m_n[2]-b) << " "
<< 1 << "\n";
}
output << 0 << "\n";
output << 0 << "\n";
output.close();
}
/* Create from TetGen .ele, .face, .node files */
btSoftBody* btSoftBodyHelpers::CreateFromTetGenFile(btSoftBody::btSoftBodyWorldInfo& worldInfo,
const char* ele,
const char* face,
const char* node,
bool bfacelinks,
bool btetralinks,
bool bfacesfromtetras)
{
std::ifstream efile(ele?ele:"");
std::ifstream ffile(face?face:"");
std::ifstream nfile(node);
std::string edata;
std::string fdata;
std::string ndata;
if(efile.good()) while(!efile.eof()) edata+=efile.get();
if(ffile.good()) while(!ffile.eof()) fdata+=ffile.get();
if(nfile.good()) while(!nfile.eof()) ndata+=nfile.get();
efile.close();
ffile.close();
nfile.close();
return(CreateFromTetGenData(worldInfo,edata.c_str(),fdata.c_str(),ndata.c_str(),
bfacelinks,btetralinks,bfacesfromtetras));
}
/* Create from TetGen .ele, .face, .node data */
btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBody::btSoftBodyWorldInfo& worldInfo,
const char* ele,
const char* face,
const char* node,
bool bfacelinks,
bool btetralinks,
bool bfacesfromtetras)
{
std::istringstream se(ele?ele:"");
std::istringstream sf(face?face:"");
std::istringstream sn(node?node:"");
btAlignedObjectArray<btVector3> pos;
int nnode=0;
int ndims=0;
int nattrb=0;
int hasbounds=0;
sn>>nnode;sn>>ndims;sn>>nattrb;sn>>hasbounds;
pos.resize(nnode);
for(int i=0;i<pos.size();++i)
{
int index=0;
int bound=0;
btScalar x,y,z,a;
sn>>index;
sn>>x;sn>>y;sn>>z;
for(int j=0;j<nattrb;++j) sn>>a;
if(hasbounds) sn>>bound;
pos[index].setX(x);
pos[index].setY(y);
pos[index].setZ(z);
}
btSoftBody* psb=new btSoftBody(&worldInfo,nnode,&pos[0],0);
if(face&&face[0])
{
int nface=0;
sf>>nface;sf>>hasbounds;
for(int i=0;i<nface;++i)
{
int index=0;
int bound=0;
int ni[3];
sf>>index;
sf>>ni[0];sf>>ni[1];sf>>ni[2];
sf>>bound;
psb->appendFace(ni[0],ni[1],ni[2]);
if(btetralinks)
{
psb->appendLink(ni[0],ni[1],0,true);
psb->appendLink(ni[1],ni[2],0,true);
psb->appendLink(ni[2],ni[0],0,true);
}
}
}
if(ele&&ele[0])
{
int ntetra=0;
int ncorner=0;
int neattrb=0;
se>>ntetra;se>>ncorner;se>>neattrb;
for(int i=0;i<ntetra;++i)
{
int index=0;
int ni[4],a;
se>>index;
se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3];
for(int j=0;j<neattrb;++j) se>>a;
psb->appendTetra(ni[0],ni[1],ni[2],ni[3]);
if(btetralinks)
{
psb->appendLink(ni[0],ni[1],0,true);
psb->appendLink(ni[1],ni[2],0,true);
psb->appendLink(ni[2],ni[0],0,true);
psb->appendLink(ni[0],ni[3],0,true);
psb->appendLink(ni[1],ni[3],0,true);
psb->appendLink(ni[2],ni[3],0,true);
}
}
}
printf("Nodes: %u\r\n",psb->m_nodes.size());
printf("Links: %u\r\n",psb->m_links.size());
printf("Faces: %u\r\n",psb->m_faces.size());
printf("Tetras: %u\r\n",psb->m_tetras.size());
return(psb);
}
#endif

View File

@ -18,6 +18,9 @@ subject to the following restrictions:
#include "btSoftBody.h"
//Can't enable this, Bullet doesn't use STL
//#define BT_SOFTBODY_USE_STL 1
//
// Helpers
//
@ -25,16 +28,15 @@ subject to the following restrictions:
/* fDrawFlags */
struct fDrawFlags { enum _ {
Nodes = 0x0001,
SLinks = 0x0002,
BLinks = 0x0004,
Faces = 0x0008,
Tetras = 0x0010,
Normals = 0x0020,
Contacts = 0x0040,
Anchors = 0x0080,
Links = 0x0002,
Faces = 0x0004,
Tetras = 0x0008,
Normals = 0x0010,
Contacts = 0x0020,
Anchors = 0x0040,
Notes = 0x0080,
/* presets */
Links = SLinks+BLinks,
Std = SLinks+Faces+Anchors,
Std = Links+Faces+Tetras+Anchors+Notes,
StdTetra = Std-Faces+Tetras,
};};
@ -64,30 +66,56 @@ struct btSoftBodyHelpers
static void DrawFrame( btSoftBody* psb,
btIDebugDraw* idraw);
/* Create a rope */
static btSoftBody* CreateRope( btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& from,
const btVector3& to,
int res,
int fixeds);
static btSoftBody* CreateRope( btSoftBody::btSoftBodyWorldInfo& worldInfo,
const btVector3& from,
const btVector3& to,
int res,
int fixeds);
/* Create a patch */
static btSoftBody* CreatePatch( btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& corner00,
const btVector3& corner10,
const btVector3& corner01,
const btVector3& corner11,
int resx,
int resy,
int fixeds,
bool gendiags);
static btSoftBody* CreatePatch(btSoftBody::btSoftBodyWorldInfo& worldInfo,
const btVector3& corner00,
const btVector3& corner10,
const btVector3& corner01,
const btVector3& corner11,
int resx,
int resy,
int fixeds,
bool gendiags);
/* Create an ellipsoid */
static btSoftBody* CreateEllipsoid(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& center,
const btVector3& radius,
int res);
/* Create from convex-hull */
static btSoftBody* CreateFromConvexHull( btSoftBody::btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
int nvertices);
static btSoftBody* CreateEllipsoid(btSoftBody::btSoftBodyWorldInfo& worldInfo,
const btVector3& center,
const btVector3& radius,
int res);
/* Create from trimesh */
static btSoftBody* CreateFromTriMesh( btSoftBody::btSoftBodyWorldInfo& worldInfo, const btScalar* vertices,
const int* triangles,
int ntriangles);
static btSoftBody* CreateFromTriMesh( btSoftBody::btSoftBodyWorldInfo& worldInfo,
const btScalar* vertices,
const int* triangles,
int ntriangles);
/* Create from convex-hull */
static btSoftBody* CreateFromConvexHull( btSoftBody::btSoftBodyWorldInfo& worldInfo,
const btVector3* vertices,
int nvertices);
#if BT_SOFTBODY_USE_STL
/* Export TetGen compatible .smesh file */
static void ExportAsSMeshFile( btSoftBody* psb,
const char* filename);
/* Create from TetGen .ele, .face, .node files */
static btSoftBody* CreateFromTetGenFile( btSoftBody::btSoftBodyWorldInfo& worldInfo,
const char* ele,
const char* face,
const char* node,
bool bfacelinks,
bool btetralinks,
bool bfacesfromtetras);
/* Create from TetGen .ele, .face, .node data */
static btSoftBody* CreateFromTetGenData( btSoftBody::btSoftBodyWorldInfo& worldInfo,
const char* ele,
const char* face,
const char* node,
bool bfacelinks,
bool btetralinks,
bool bfacesfromtetras);
#endif
};
#endif //SOFT_BODY_HELPERS_H

View File

@ -106,7 +106,7 @@ void btSoftRigidDynamicsWorld::debugDrawWorld()
{
btSoftBody* psb=(btSoftBody*)this->m_softBodies[i];
btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer);
btSoftBodyHelpers::Draw(psb,m_debugDrawer,fDrawFlags::Std);
btSoftBodyHelpers::Draw(psb,m_debugDrawer,fDrawFlags::Nodes+fDrawFlags::Std);
if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
{
btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer);

View File

@ -109,6 +109,28 @@ struct btSparseSdf
/* else setup a priority list... */
}
//
int RemoveReferences(btCollisionShape* pcs)
{
int refcount=0;
for(int i=0;i<cells.size();++i)
{
Cell*& root=cells[i];
Cell* pp=0;
Cell* pc=root;
while(pc)
{
Cell* pn=pc->next;
if(pc->pclient==pcs)
{
if(pp) pp->next=pn; else root=pn;
delete pc;pc=pp;++refcount;
}
pp=pc;pc=pn;
}
}
return(refcount);
}
//
btScalar Evaluate( const btVector3& x,
btCollisionShape* shape,
btVector3& normal,