Added initial broadphase support for softbody versus softbody and softbody versus rigidbody (see btSoftSoftCollisionAlgorithm and btSoftRididCollisionAlgorithm)

Added 	SOFTBODY_SHAPE_PROXYTYPE.
Some refactoring for btSoftBody, needs more work.
This commit is contained in:
erwin.coumans
2008-04-06 06:53:00 +00:00
parent 39d929cbb0
commit b37a37a28e
14 changed files with 2512 additions and 1859 deletions

View File

@@ -26,7 +26,8 @@ subject to the following restrictions:
#include "../GimpactTestDemo/TorusMesh.h" #include "../GimpactTestDemo/TorusMesh.h"
#include <stdio.h> //printf debugging #include <stdio.h> //printf debugging
#include "../../Extras/ConvexHull/btConvexHull.h" #include "../../Extras/ConvexHull/btConvexHull.h"
#include "btSoftBodyRigidBodyCollisionConfiguration.h"
#include "BulletDynamics/SoftBody/btSoftBodyHelpers.h"
static float gCollisionMargin = 0.05f/*0.05f*/; static float gCollisionMargin = 0.05f/*0.05f*/;
#include "SoftDemo.h" #include "SoftDemo.h"
@@ -42,8 +43,7 @@ const int maxProxies = 32766;
const int maxOverlap = 65535; const int maxOverlap = 65535;
// //
btSoftBody* CreateFromConvexHull( btSoftBody::ISoftBody* isoftbody, btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBody::btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
const btVector3* vertices,
int nvertices) int nvertices)
{ {
HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); HullDesc hdsc(QF_TRIANGLES,nvertices,vertices);
@@ -51,8 +51,7 @@ HullResult hres;
HullLibrary hlib;/*??*/ HullLibrary hlib;/*??*/
hdsc.mMaxVertices=nvertices; hdsc.mMaxVertices=nvertices;
hlib.CreateConvexHull(hdsc,hres); hlib.CreateConvexHull(hdsc,hres);
btSoftBody* psb=btSoftBody::Create( isoftbody, btSoftBody* psb=new btSoftBody(worldInfo,(int)hres.mNumOutputVertices,
(int)hres.mNumOutputVertices,
hres.mOutputVertices,0); hres.mOutputVertices,0);
for(int i=0;i<(int)hres.mNumFaces;++i) for(int i=0;i<(int)hres.mNumFaces;++i)
{ {
@@ -117,30 +116,15 @@ void SoftDemo::createStack( btCollisionShape* boxShape, float halfCubeSize, int
#ifdef DHSJHDSAKJDHSJKADHSAKJDHSA
//
// ISoftBody implementation
//
//
void SoftDemo::SoftBodyImpl::Attach(btSoftBody*)
{}
//
void SoftDemo::SoftBodyImpl::Detach(btSoftBody*)
{}
//
void SoftDemo::SoftBodyImpl::StartCollide(const btVector3&,const btVector3&)
{}
// //
bool SoftDemo::SoftBodyImpl::CheckContactPrecise(const btVector3& x, bool SoftDemo::SoftBodyImpl::CheckContactPrecise(const btVector3& x,
btSoftBody::ISoftBody::sCti& cti) btSoftBody::ISoftBody::sCti& cti)
{ {
btScalar maxdepth=0; btScalar maxdepth=0;
btGjkEpaSolver2::sResults res; btGjkEpaSolver2::sResults res;
btDynamicsWorld* pdw=pdemo->m_dynamicsWorld; // btDynamicsWorld* pdw=pdemo->m_dynamicsWorld;
btCollisionObjectArray& coa=pdw->getCollisionObjectArray(); btCollisionObjectArray& coa=pdw->getCollisionObjectArray();
for(int i=0,ni=coa.size();i<ni;++i) for(int i=0,ni=coa.size();i<ni;++i)
{ {
@@ -165,7 +149,7 @@ return(maxdepth<0);
// //
bool SoftDemo::SoftBodyImpl::CheckContact( const btVector3& x, bool SoftDemo::SoftBodyImpl::CheckContact( const btVector3& x,
btSoftBody::ISoftBody::sCti& cti) btSoftBody::sCti& cti)
{ {
btScalar maxdepth=0; btScalar maxdepth=0;
btGjkEpaSolver2::sResults res; btGjkEpaSolver2::sResults res;
@@ -216,6 +200,7 @@ if(water_density>0)
} }
} }
#endif
extern int gNumManifold; extern int gNumManifold;
@@ -267,14 +252,22 @@ void SoftDemo::clientMoveAndDisplay()
#endif #endif
/* soft bodies */ /* soft bodies collision detection */
for(int ib=0;ib<m_softbodies.size();++ib)
{
btSoftBody* psb=m_softbodies[ib];
// psb->updateAabb(dt);
}
/* soft bodies simulation */
for(int ib=0;ib<m_softbodies.size();++ib) for(int ib=0;ib<m_softbodies.size();++ib)
{ {
btSoftBody* psb=m_softbodies[ib]; btSoftBody* psb=m_softbodies[ib];
psb->AddVelocity(m_dynamicsWorld->getGravity()*dt); psb->AddVelocity(m_dynamicsWorld->getGravity()*dt);
psb->Step(dt); psb->Step(dt);
} }
m_sparsesdf.GarbageCollect();
m_softBodyWorldInfo.m_sparsesdf.GarbageCollect();
//optional but useful: debug drawing //optional but useful: debug drawing
@@ -418,9 +411,10 @@ const btVector3 c[]={ p+h*btVector3(-1,-1,-1),
p+h*btVector3(+1,-1,+1), p+h*btVector3(+1,-1,+1),
p+h*btVector3(-1,+1,+1), p+h*btVector3(-1,+1,+1),
p+h*btVector3(+1,+1,+1)}; p+h*btVector3(+1,+1,+1)};
btSoftBody* psb=CreateFromConvexHull(&pdemo->m_softbodyimpl,c,8); btSoftBody* psb=btSoftBodyHelpers::CreateFromConvexHull(pdemo->m_softBodyWorldInfo,c,8);
psb->GenerateBendingConstraints(2,1); psb->GenerateBendingConstraints(2,1);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
return(psb); return(psb);
} }
@@ -435,9 +429,10 @@ for(int i=0;i<np;++i)
{ {
pts.push_back(Vector3Rand()*s+p); pts.push_back(Vector3Rand()*s+p);
} }
btSoftBody* psb=CreateFromConvexHull(&pdemo->m_softbodyimpl,&pts[0],pts.size()); btSoftBody* psb=btSoftBodyHelpers::CreateFromConvexHull(pdemo->m_softBodyWorldInfo,&pts[0],pts.size());
psb->GenerateBendingConstraints(2,1); psb->GenerateBendingConstraints(2,1);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
return(psb); return(psb);
} }
@@ -452,8 +447,7 @@ static void Init_Ropes(SoftDemo* pdemo)
const int n=15; const int n=15;
for(int i=0;i<n;++i) for(int i=0;i<n;++i)
{ {
btSoftBody* psb=CreateRope( &pdemo->m_softbodyimpl, btSoftBody* psb=btSoftBodyHelpers::CreateRope(pdemo->m_softBodyWorldInfo, btVector3(-10,0,i*0.25),
btVector3(-10,0,i*0.25),
btVector3(10,0,i*0.25), btVector3(10,0,i*0.25),
16, 16,
1+2); 1+2);
@@ -461,6 +455,7 @@ for(int i=0;i<n;++i)
psb->m_cfg.kLST = 0.1+(i/(btScalar)(n-1))*0.9; psb->m_cfg.kLST = 0.1+(i/(btScalar)(n-1))*0.9;
psb->SetTotalMass(20); psb->SetTotalMass(20);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
} }
} }
@@ -474,8 +469,7 @@ struct Functors
{ {
static btSoftBody* CtorRope(SoftDemo* pdemo,const btVector3& p) static btSoftBody* CtorRope(SoftDemo* pdemo,const btVector3& p)
{ {
btSoftBody* psb=CreateRope(&pdemo->m_softbodyimpl, btSoftBody* psb=btSoftBodyHelpers::CreateRope(pdemo->m_softBodyWorldInfo,p,p+btVector3(10,0,0),8,1);
p,p+btVector3(10,0,0),8,1);
psb->m_cfg.kDF = 0; psb->m_cfg.kDF = 0;
psb->SetTotalMass(50); psb->SetTotalMass(50);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
@@ -488,8 +482,8 @@ startTransform.setOrigin(btVector3(12,8,0));
btRigidBody* body=pdemo->localCreateRigidBody(50,startTransform,new btBoxShape(btVector3(2,6,2))); btRigidBody* body=pdemo->localCreateRigidBody(50,startTransform,new btBoxShape(btVector3(2,6,2)));
btSoftBody* psb0=Functors::CtorRope(pdemo,btVector3(0,8,-1)); btSoftBody* psb0=Functors::CtorRope(pdemo,btVector3(0,8,-1));
btSoftBody* psb1=Functors::CtorRope(pdemo,btVector3(0,8,+1)); btSoftBody* psb1=Functors::CtorRope(pdemo,btVector3(0,8,+1));
psb0->AppendAnchor(psb0->m_nodes.size()-1,body); psb0->AppendAnchor(psb0->getNodes().size()-1,body);
psb1->AppendAnchor(psb1->m_nodes.size()-1,body); psb1->AppendAnchor(psb1->getNodes().size()-1,body);
} }
// //
@@ -501,12 +495,12 @@ static void Init_ClothAttach(SoftDemo* pdemo)
const btScalar s=4; const btScalar s=4;
const btScalar h=6; const btScalar h=6;
const int r=9; const int r=9;
btSoftBody* psb=CreatePatch(&pdemo->m_softbodyimpl, btSoftBody* psb=btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo,btVector3(-s,h,-s),
btVector3(-s,h,-s),
btVector3(+s,h,-s), btVector3(+s,h,-s),
btVector3(-s,h,+s), btVector3(-s,h,+s),
btVector3(+s,h,+s),r,r,4+8,true); btVector3(+s,h,+s),r,r,4+8,true);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
btTransform startTransform; btTransform startTransform;
startTransform.setIdentity(); startTransform.setIdentity();
startTransform.setOrigin(btVector3(0,h,-(s+3.5))); startTransform.setOrigin(btVector3(0,h,-(s+3.5)));
@@ -521,12 +515,12 @@ psb->AppendAnchor(r-1,body);
static void Init_Impact(SoftDemo* pdemo) static void Init_Impact(SoftDemo* pdemo)
{ {
//TRACEDEMO //TRACEDEMO
btSoftBody* psb=CreateRope( &pdemo->m_softbodyimpl, btSoftBody* psb=btSoftBodyHelpers::CreateRope(pdemo->m_softBodyWorldInfo, btVector3(0,0,0),
btVector3(0,0,0),
btVector3(0,-1,0), btVector3(0,-1,0),
0, 0,
1); 1);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
btTransform startTransform; btTransform startTransform;
startTransform.setIdentity(); startTransform.setIdentity();
startTransform.setOrigin(btVector3(0,20,0)); startTransform.setOrigin(btVector3(0,20,0));
@@ -545,8 +539,7 @@ const int segments=6;
const int count=50; const int count=50;
for(int i=0;i<count;++i) for(int i=0;i<count;++i)
{ {
btSoftBody* psb=CreatePatch(&pdemo->m_softbodyimpl, btSoftBody* psb=btSoftBodyHelpers::CreatePatch(pdemo->m_softBodyWorldInfo,btVector3(-s,h,-s),
btVector3(-s,h,-s),
btVector3(+s,h,-s), btVector3(+s,h,-s),
btVector3(-s,h,+s), btVector3(-s,h,+s),
btVector3(+s,h,+s), btVector3(+s,h,+s),
@@ -568,6 +561,7 @@ for(int i=0;i<count;++i)
psb->SetTotalMass(0.1); psb->SetTotalMass(0.1);
psb->AddForce(btVector3(0,2,0),0); psb->AddForce(btVector3(0,2,0),0);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
} }
pdemo->m_autocam=true; pdemo->m_autocam=true;
} }
@@ -595,8 +589,7 @@ for(int i=0,ni=20;i<ni;++i)
static void Init_Pressure(SoftDemo* pdemo) static void Init_Pressure(SoftDemo* pdemo)
{ {
//TRACEDEMO //TRACEDEMO
btSoftBody* psb=CreateEllipsoid(&pdemo->m_softbodyimpl, btSoftBody* psb=btSoftBodyHelpers::CreateEllipsoid(pdemo->m_softBodyWorldInfo,btVector3(35,25,0),
btVector3(35,25,0),
btVector3(1,1,1)*3, btVector3(1,1,1)*3,
512); 512);
psb->m_cfg.kLST = 0.1; psb->m_cfg.kLST = 0.1;
@@ -604,6 +597,7 @@ psb->m_cfg.kDF = 1;
psb->m_cfg.kPR = 2500; psb->m_cfg.kPR = 2500;
psb->SetTotalMass(30,true); psb->SetTotalMass(30,true);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
Ctor_BigPlate(pdemo); Ctor_BigPlate(pdemo);
Ctor_LinearStair(pdemo,btVector3(0,0,0),btVector3(2,1,5),0,10); Ctor_LinearStair(pdemo,btVector3(0,0,0),btVector3(2,1,5),0,10);
pdemo->m_autocam=true; pdemo->m_autocam=true;
@@ -615,8 +609,7 @@ pdemo->m_autocam=true;
static void Init_Volume(SoftDemo* pdemo) static void Init_Volume(SoftDemo* pdemo)
{ {
//TRACEDEMO //TRACEDEMO
btSoftBody* psb=CreateEllipsoid(&pdemo->m_softbodyimpl, btSoftBody* psb=btSoftBodyHelpers::CreateEllipsoid(pdemo->m_softBodyWorldInfo,btVector3(35,25,0),
btVector3(35,25,0),
btVector3(1,1,1)*3, btVector3(1,1,1)*3,
512); 512);
psb->m_cfg.kLST = 0.45; psb->m_cfg.kLST = 0.45;
@@ -624,6 +617,7 @@ psb->m_cfg.kVC = 20;
psb->SetTotalMass(50,true); psb->SetTotalMass(50,true);
psb->SetPose(true,false); psb->SetPose(true,false);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
Ctor_BigPlate(pdemo); Ctor_BigPlate(pdemo);
Ctor_LinearStair(pdemo,btVector3(0,0,0),btVector3(2,1,5),0,10); Ctor_LinearStair(pdemo,btVector3(0,0,0),btVector3(2,1,5),0,10);
pdemo->m_autocam=true; pdemo->m_autocam=true;
@@ -647,8 +641,7 @@ for(int y=0;y<n;++y)
const btVector3 org(-sz+sz*2*x*in, const btVector3 org(-sz+sz*2*x*in,
-10, -10,
-sz+sz*2*y*in); -sz+sz*2*y*in);
btSoftBody* psb=CreateRope( &pdemo->m_softbodyimpl, btSoftBody* psb=btSoftBodyHelpers::CreateRope( pdemo->m_softBodyWorldInfo, org,
org,
org+btVector3(hg*0.001,hg,0), org+btVector3(hg*0.001,hg,0),
sg, sg,
1); 1);
@@ -662,6 +655,7 @@ for(int y=0;y<n;++y)
psb->SetMass(1,0); psb->SetMass(1,0);
psb->SetTotalMass(0.01); psb->SetTotalMass(0.01);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
} }
} }
Ctor_BigBall(pdemo); Ctor_BigBall(pdemo);
@@ -674,17 +668,19 @@ static void Init_Cloth(SoftDemo* pdemo)
{ {
//TRACEDEMO //TRACEDEMO
const btScalar s=8; const btScalar s=8;
btSoftBody* psb=CreatePatch(&pdemo->m_softbodyimpl, btSoftBody* psb=btSoftBodyHelpers::CreatePatch( pdemo->m_softBodyWorldInfo,btVector3(-s,0,-s),
btVector3(-s,0,-s),
btVector3(+s,0,-s), btVector3(+s,0,-s),
btVector3(-s,0,+s), btVector3(-s,0,+s),
btVector3(+s,0,+s), btVector3(+s,0,+s),
31,31, 31,31,
// 31,31,
1+2+4+8,true); 1+2+4+8,true);
psb->GenerateBendingConstraints(2,1); psb->GenerateBendingConstraints(2,1);
psb->m_cfg.kLST = 0.4; psb->m_cfg.kLST = 0.4;
psb->SetTotalMass(150); psb->SetTotalMass(150);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
Ctor_RbUpStack(pdemo,10); Ctor_RbUpStack(pdemo,10);
} }
@@ -694,8 +690,7 @@ Ctor_RbUpStack(pdemo,10);
static void Init_Bunny(SoftDemo* pdemo) static void Init_Bunny(SoftDemo* pdemo)
{ {
//TRACEDEMO //TRACEDEMO
btSoftBody* psb=CreateFromTriMesh( &pdemo->m_softbodyimpl, btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVerticesBunny,
gVerticesBunny,
&gIndicesBunny[0][0], &gIndicesBunny[0][0],
BUNNY_NUM_TRIANGLES); BUNNY_NUM_TRIANGLES);
psb->GenerateBendingConstraints(2,0.5); psb->GenerateBendingConstraints(2,0.5);
@@ -705,6 +700,7 @@ psb->RandomizeConstraints();
psb->Scale(btVector3(6,6,6)); psb->Scale(btVector3(6,6,6));
psb->SetTotalMass(100,true); psb->SetTotalMass(100,true);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
} }
// //
@@ -713,8 +709,7 @@ pdemo->m_softbodies.push_back(psb);
static void Init_BunnyMatch(SoftDemo* pdemo) static void Init_BunnyMatch(SoftDemo* pdemo)
{ {
//TRACEDEMO //TRACEDEMO
btSoftBody* psb=CreateFromTriMesh( &pdemo->m_softbodyimpl, btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVerticesBunny,
gVerticesBunny,
&gIndicesBunny[0][0], &gIndicesBunny[0][0],
BUNNY_NUM_TRIANGLES); BUNNY_NUM_TRIANGLES);
psb->GenerateBendingConstraints(2,0.5); psb->GenerateBendingConstraints(2,0.5);
@@ -726,6 +721,7 @@ psb->Scale(btVector3(6,6,6));
psb->SetTotalMass(100,true); psb->SetTotalMass(100,true);
psb->SetPose(true,true); psb->SetPose(true,true);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
} }
// //
@@ -734,8 +730,7 @@ pdemo->m_softbodies.push_back(psb);
static void Init_Torus(SoftDemo* pdemo) static void Init_Torus(SoftDemo* pdemo)
{ {
//TRACEDEMO //TRACEDEMO
btSoftBody* psb=CreateFromTriMesh( &pdemo->m_softbodyimpl, btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh( pdemo->m_softBodyWorldInfo, gVertices,
gVertices,
&gIndices[0][0], &gIndices[0][0],
NUM_TRIANGLES); NUM_TRIANGLES);
psb->GenerateBendingConstraints(2,1); psb->GenerateBendingConstraints(2,1);
@@ -747,6 +742,7 @@ psb->Transform(btTransform(m,btVector3(0,4,0)));
psb->Scale(btVector3(2,2,2)); psb->Scale(btVector3(2,2,2));
psb->SetTotalMass(50,true); psb->SetTotalMass(50,true);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
} }
// //
@@ -755,8 +751,7 @@ pdemo->m_softbodies.push_back(psb);
static void Init_TorusMatch(SoftDemo* pdemo) static void Init_TorusMatch(SoftDemo* pdemo)
{ {
//TRACEDEMO //TRACEDEMO
btSoftBody* psb=CreateFromTriMesh( &pdemo->m_softbodyimpl, btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVertices,
gVertices,
&gIndices[0][0], &gIndices[0][0],
NUM_TRIANGLES); NUM_TRIANGLES);
psb->GenerateBendingConstraints(2,1); psb->GenerateBendingConstraints(2,1);
@@ -770,6 +765,8 @@ psb->Scale(btVector3(2,2,2));
psb->SetTotalMass(50,true); psb->SetTotalMass(50,true);
psb->SetPose(true,true); psb->SetPose(true,true);
pdemo->m_softbodies.push_back(psb); pdemo->m_softbodies.push_back(psb);
} }
static unsigned current_demo=0; static unsigned current_demo=0;
@@ -791,10 +788,11 @@ for(int i=m_dynamicsWorld->getNumCollisionObjects()-1;i>0;i--)
} }
for(int i=0;i<m_softbodies.size();++i) for(int i=0;i<m_softbodies.size();++i)
{ {
delete m_softbodies[i]; btSoftBody* softbody = m_softbodies[i];
delete softbody;
} }
m_softbodies.clear(); m_softbodies.clear();
m_sparsesdf.Reset(); m_softBodyWorldInfo.m_sparsesdf.Reset();
/* Init */ /* Init */
void (*demofncs[])(SoftDemo*)= void (*demofncs[])(SoftDemo*)=
{ {
@@ -814,10 +812,14 @@ void (*demofncs[])(SoftDemo*)=
Init_BunnyMatch, Init_BunnyMatch,
}; };
current_demo=current_demo%(sizeof(demofncs)/sizeof(demofncs[0])); current_demo=current_demo%(sizeof(demofncs)/sizeof(demofncs[0]));
m_softbodyimpl.air_density = (btScalar)1.2;
m_softbodyimpl.water_density = 0;
m_softbodyimpl.water_offset = 0; m_softBodyWorldInfo.air_density = (btScalar)1.2;
m_softbodyimpl.water_normal = btVector3(0,0,0); m_softBodyWorldInfo.water_density = 0;
m_softBodyWorldInfo.water_offset = 0;
m_softBodyWorldInfo.water_normal = btVector3(0,0,0);
m_autocam = false; m_autocam = false;
demofncs[current_demo](this); demofncs[current_demo](this);
} }
@@ -832,13 +834,13 @@ int nps=0;
for(int ib=0;ib<m_softbodies.size();++ib) for(int ib=0;ib<m_softbodies.size();++ib)
{ {
btSoftBody* psb=m_softbodies[ib]; btSoftBody* psb=m_softbodies[ib];
nps+=psb->m_nodes.size(); nps+=psb->getNodes().size();
for(int i=0;i<psb->m_nodes.size();++i) for(int i=0;i<psb->getNodes().size();++i)
{ {
ps+=psb->m_nodes[i].m_x; ps+=psb->getNodes()[i].m_x;
} }
DrawFrame(psb,idraw); btSoftBodyHelpers::DrawFrame(psb,idraw);
Draw(psb,idraw,fDrawFlags::Std); btSoftBodyHelpers::Draw(psb,idraw,fDrawFlags::Std);
} }
ps/=nps; ps/=nps;
if(m_autocam) if(m_autocam)
@@ -849,12 +851,12 @@ if(m_autocam)
static const btVector3 axis[]={btVector3(1,0,0), static const btVector3 axis[]={btVector3(1,0,0),
btVector3(0,1,0), btVector3(0,1,0),
btVector3(0,0,1)}; btVector3(0,0,1)};
if(m_softbodyimpl.water_density>0) if(m_softBodyWorldInfo.water_density>0)
{ {
const btVector3 c= btVector3((btScalar)0.25,(btScalar)0.25,1); const btVector3 c= btVector3((btScalar)0.25,(btScalar)0.25,1);
const btScalar a= (btScalar)0.5; const btScalar a= (btScalar)0.5;
const btVector3 n= m_softbodyimpl.water_normal; const btVector3 n= m_softBodyWorldInfo.water_normal;
const btVector3 o= -n*m_softbodyimpl.water_offset; const btVector3 o= -n*m_softBodyWorldInfo.water_offset;
const btVector3 x= cross(n,axis[n.minAxis()]).normalized(); const btVector3 x= cross(n,axis[n.minAxis()]).normalized();
const btVector3 y= cross(x,n).normalized(); const btVector3 y= cross(x,n).normalized();
const btScalar s= 25; const btScalar s= 25;
@@ -878,44 +880,40 @@ switch(key)
void SoftDemo::initPhysics() void SoftDemo::initPhysics()
{ {
//#define USE_GROUND_PLANE 1
#ifdef USE_GROUND_PLANE
m_collisionShapes.push_back(new btStaticPlaneShape(btVector3(0,1,0),0.5));
#else
///Please don't make the box sizes larger then 1000: the collision detection will be inaccurate.
///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=346
m_collisionShapes.push_back(new btBoxShape (btVector3(200,CUBE_HALF_EXTENTS,200))); m_collisionShapes.push_back(new btBoxShape (btVector3(200,CUBE_HALF_EXTENTS,200)));
//m_collisionShapes.push_back(new btCylinderShapeZ (btVector3(5,5,5)));
//m_collisionShapes.push_back(new btSphereShape(5));
#endif
m_collisionShapes.push_back(new btCylinderShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS))); m_collisionShapes.push_back(new btCylinderShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS)));
m_dispatcher=0; m_dispatcher=0;
m_collisionConfiguration = new btDefaultCollisionConfiguration();
///register some softbody collision algorithms on top of the default btDefaultCollisionConfiguration
m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
m_softBodyWorldInfo.m_dispatcher = m_dispatcher;
////////////////////////////
///Register softbody versus softbody collision algorithm
///Register softbody versus rigidbody collision algorithm
////////////////////////////
btVector3 worldAabbMin(-1000,-1000,-1000); btVector3 worldAabbMin(-1000,-1000,-1000);
btVector3 worldAabbMax(1000,1000,1000); btVector3 worldAabbMax(1000,1000,1000);
m_broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies); m_broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);
/// For large worlds or over 16384 objects, use the bt32BitAxisSweep3 broadphase
// m_broadphase = new bt32BitAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);
/// When trying to debug broadphase issues, try to use the btSimpleBroadphase
// m_broadphase = new btSimpleBroadphase;
//box-box is in Extras/AlternativeCollisionAlgorithms:it requires inclusion of those files
m_softBodyWorldInfo.m_broadphase = m_broadphase;
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver(); btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver();
m_solver = solver; m_solver = solver;
//default solverMode is SOLVER_RANDMIZE_ORDER. Warmstarting seems not to improve convergence, see
//solver->setSolverMode(0);//btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER);
btDiscreteDynamicsWorld* world = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); btDiscreteDynamicsWorld* world = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
m_dynamicsWorld = world; m_dynamicsWorld = world;
@@ -940,8 +938,7 @@ void SoftDemo::initPhysics()
// clientResetScene(); // clientResetScene();
m_softbodyimpl.pdemo=this; m_softBodyWorldInfo.m_sparsesdf.Initialize();
m_sparsesdf.Initialize();
clientResetScene(); clientResetScene();
} }

View File

@@ -21,7 +21,7 @@ subject to the following restrictions:
#include "DemoApplication.h" #include "DemoApplication.h"
#include "LinearMath/btAlignedObjectArray.h" #include "LinearMath/btAlignedObjectArray.h"
#include "BulletDynamics/SoftBody/btSoftBody.h" #include "BulletDynamics/SoftBody/btSoftBody.h"
#include "BulletDynamics/SoftBody/btSparseSDF.h"
class btBroadphaseInterface; class btBroadphaseInterface;
class btCollisionShape; class btCollisionShape;
@@ -31,31 +31,27 @@ class btConstraintSolver;
struct btCollisionAlgorithmCreateFunc; struct btCollisionAlgorithmCreateFunc;
class btDefaultCollisionConfiguration; class btDefaultCollisionConfiguration;
///collisions between two btSoftBody's
class btSoftSoftCollisionAlgorithm;
///collisions between a btSoftBody and a btRigidBody
class btSoftRididCollisionAlgorithm;
///CcdPhysicsDemo shows basic stacking using Bullet physics, and allows toggle of Ccd (using key '1') ///CcdPhysicsDemo shows basic stacking using Bullet physics, and allows toggle of Ccd (using key '1')
class SoftDemo : public DemoApplication class SoftDemo : public DemoApplication
{ {
public: public:
struct SoftBodyImpl : btSoftBody::ISoftBody
{ btAlignedObjectArray<btSoftSoftCollisionAlgorithm*> m_SoftSoftCollisionAlgorithms;
void Attach(btSoftBody*);
void Detach(btSoftBody*); btAlignedObjectArray<btSoftRididCollisionAlgorithm*> m_SoftRigidCollisionAlgorithms;
void StartCollide(const btVector3&,const btVector3&);
bool CheckContactPrecise(const btVector3&, btSoftBody::btSoftBodyWorldInfo m_softBodyWorldInfo;
btSoftBody::ISoftBody::sCti&);
bool CheckContact( const btVector3&,
btSoftBody::ISoftBody::sCti&);
void EndCollide();
void EvaluateMedium( const btVector3&,
btSoftBody::ISoftBody::sMedium&);
SoftDemo* pdemo;
btScalar air_density;
btScalar water_density;
btScalar water_offset;
btVector3 water_normal;
} m_softbodyimpl;
btAlignedObjectArray<btSoftBody*> m_softbodies; btAlignedObjectArray<btSoftBody*> m_softbodies;
btSparseSdf<3> m_sparsesdf;
bool m_autocam; bool m_autocam;
@@ -66,12 +62,6 @@ struct SoftBodyImpl : btSoftBody::ISoftBody
btCollisionDispatcher* m_dispatcher; btCollisionDispatcher* m_dispatcher;
#ifdef USE_PARALLEL_DISPATCHER
#ifdef WIN32
class Win32ThreadSupport* m_threadSupportCollision;
class Win32ThreadSupport* m_threadSupportSolver;
#endif
#endif
btConstraintSolver* m_solver; btConstraintSolver* m_solver;

View File

@@ -0,0 +1,77 @@
/*
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 "btSoftBodyRigidBodyCollisionConfiguration.h"
#include "btSoftRigidCollisionAlgorithm.h"
#include "btSoftSoftCollisionAlgorithm.h"
btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool)
:btDefaultCollisionConfiguration(stackAlloc,persistentManifoldPool,collisionAlgorithmPool)
{
void* mem;
mem = btAlignedAlloc(sizeof(btSoftSoftCollisionAlgorithm::CreateFunc),16);
m_softSoftCreateFunc = new(mem) btSoftSoftCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16);
m_softRigidCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc;
mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16);
m_swappedSoftRigidCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc;
m_swappedSoftRigidCreateFunc->m_swapped=true;
}
btSoftBodyRigidBodyCollisionConfiguration::~btSoftBodyRigidBodyCollisionConfiguration()
{
m_softSoftCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_softSoftCreateFunc);
m_softRigidCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_softRigidCreateFunc);
m_swappedSoftRigidCreateFunc->~btCollisionAlgorithmCreateFunc();
btAlignedFree( m_swappedSoftRigidCreateFunc);
}
///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation
btCollisionAlgorithmCreateFunc* btSoftBodyRigidBodyCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
{
///try to handle the softbody interactions first
if ((proxyType0 == SOFTBODY_SHAPE_PROXYTYPE ) && (proxyType1==SOFTBODY_SHAPE_PROXYTYPE))
{
return m_softSoftCreateFunc;
}
///other can't be also softbody, so assume rigid for now
if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE )
{
return m_softRigidCreateFunc;
}
///other can't be also softbody, so assume rigid for now
if (proxyType1 == SOFTBODY_SHAPE_PROXYTYPE )
{
return m_swappedSoftRigidCreateFunc;
}
///fallback to the regular rigid collision shape
return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0,proxyType1);
}

View File

@@ -0,0 +1,46 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION
#define BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION
#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
class btVoronoiSimplexSolver;
class btGjkEpaPenetrationDepthSolver;
///btSoftBodyRigidBodyCollisionConfiguration add softbody interaction on top of btDefaultCollisionConfiguration
class btSoftBodyRigidBodyCollisionConfiguration : public btDefaultCollisionConfiguration
{
//default CreationFunctions, filling the m_doubleDispatch table
btCollisionAlgorithmCreateFunc* m_softSoftCreateFunc;
btCollisionAlgorithmCreateFunc* m_softRigidCreateFunc;
btCollisionAlgorithmCreateFunc* m_swappedSoftRigidCreateFunc;
public:
btSoftBodyRigidBodyCollisionConfiguration(btStackAlloc* stackAlloc=0,btPoolAllocator* persistentManifoldPool=0,btPoolAllocator* collisionAlgorithmPool=0);
virtual ~btSoftBodyRigidBodyCollisionConfiguration();
///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
};
#endif //BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION

View File

@@ -0,0 +1,94 @@
/*
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 "btSoftRigidCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletDynamics/SoftBody/btSoftBody.h"
///TODO: include all the shapes that the softbody can collide with
///alternatively, implement special case collision algorithms (just like for rigid collision shapes)
//#include <stdio.h>
btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped)
: btCollisionAlgorithm(ci),
//m_ownManifold(false),
//m_manifoldPtr(mf),
m_isSwapped(isSwapped)
{
m_softBody = m_isSwapped? (btSoftBody*)col1 : (btSoftBody*)col0;
m_rigidCollisionObject = m_isSwapped? col0 : col1;
//quick fix, add overlapping rigidbody to softbody, so it can be handled within btSoftBody::Step method
m_softBody->m_overlappingRigidBodies.push_back(m_rigidCollisionObject);
///store the contacts straight into the btSoftBody for now?
/*if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObj,boxObj))
{
m_manifoldPtr = m_dispatcher->getNewManifold(sphereObj,boxObj);
m_ownManifold = true;
}
*/
}
btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm()
{
m_softBody->m_overlappingRigidBodies.remove(m_rigidCollisionObject);
/*if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
*/
}
#include <stdio.h>
void btSoftRigidCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)dispatchInfo;
(void)resultOut;
//printf("btSoftRigidCollisionAlgorithm\n");
btSoftBody* softBody = m_isSwapped? (btSoftBody*)body1 : (btSoftBody*)body0;
btCollisionObject* rigidCollisionObject = m_isSwapped? body0 : body1;
///do your stuff here
}
btScalar btSoftRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
(void)resultOut;
(void)dispatchInfo;
(void)col0;
(void)col1;
//not yet
return btScalar(1.);
}

View File

@@ -0,0 +1,69 @@
/*
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 SOFT_RIGID_COLLISION_ALGORITHM_H
#define SOFT_RIGID_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "LinearMath/btVector3.h"
struct btSoftBody;
/// btSoftRigidCollisionAlgorithm provides collision detection between btSoftBody and btRigidBody
class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm
{
// bool m_ownManifold;
// btPersistentManifold* m_manifoldPtr;
btSoftBody* m_softBody;
btCollisionObject* m_rigidCollisionObject;
///for rigid versus soft (instead of soft versus rigid), we use this swapped boolean
bool m_isSwapped;
public:
btSoftRigidCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
virtual ~btSoftRigidCollisionAlgorithm();
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftRigidCollisionAlgorithm));
if (!m_swapped)
{
return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0,body1,false);
} else
{
return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0,body1,true);
}
}
};
};
#endif //SOFT_RIGID_COLLISION_ALGORITHM_H

View File

@@ -0,0 +1,104 @@
/*
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 "btSoftSoftCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletDynamics/SoftBody/btSoftBody.h"
#define USE_PERSISTENT_CONTACTS 1
btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1)
: btCollisionAlgorithm(ci)
//m_ownManifold(false),
//m_manifoldPtr(mf)
{
m_softBody0 = (btSoftBody*) obj0;
m_softBody1 = (btSoftBody*) obj1;
m_softBody0->m_overlappingSoftBodies.push_back(m_softBody1);
m_softBody1->m_overlappingSoftBodies.push_back(m_softBody0);
/*if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
{
m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1);
m_ownManifold = true;
}
*/
}
btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm()
{
m_softBody0->m_overlappingSoftBodies.remove(m_softBody1);
m_softBody1->m_overlappingSoftBodies.remove(m_softBody0);
//this gets called when the overlap stops.
//here is where contacts (manifolds) should be removed
/*
if (m_ownManifold)
{
if (m_manifoldPtr)
m_dispatcher->releaseManifold(m_manifoldPtr);
}
*/
}
void btSoftSoftCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btCollisionObject* col0 = body0;
btCollisionObject* col1 = body1;
/*
btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape();
btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape();
/// report a contact. internally this will be kept persistent, and contact reduction is done
resultOut->setPersistentManifold(m_manifoldPtr);
#ifndef USE_PERSISTENT_CONTACTS
m_manifoldPtr->clearManifold();
#endif //USE_PERSISTENT_CONTACTS
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = 1e30f;
input.m_transformA = body0->getWorldTransform();
input.m_transformB = body1->getWorldTransform();
btBoxBoxDetector detector(box0,box1);
detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
#ifdef USE_PERSISTENT_CONTACTS
// refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
if (m_ownManifold)
{
resultOut->refreshContactPoints();
}
#endif //USE_PERSISTENT_CONTACTS
*/
}
btScalar btSoftSoftCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
//not yet
return 1.f;
}

View File

@@ -0,0 +1,62 @@
/*
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 SOFT_SOFT_COLLISION_ALGORITHM_H
#define SOFT_SOFT_COLLISION_ALGORITHM_H
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
struct btSoftBody;
///collision detection between two btSoftBody shapes
class btSoftSoftCollisionAlgorithm : public btCollisionAlgorithm
{
bool m_ownManifold;
btPersistentManifold* m_manifoldPtr;
btSoftBody* m_softBody0;
btSoftBody* m_softBody1;
public:
btSoftSoftCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
: btCollisionAlgorithm(ci) {}
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
btSoftSoftCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
virtual ~btSoftSoftCollisionAlgorithm();
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
int bbsize = sizeof(btSoftSoftCollisionAlgorithm);
void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
return new(ptr) btSoftSoftCollisionAlgorithm(0,ci,body0,body1);
}
};
};
#endif //SOFT_SOFT_COLLISION_ALGORITHM_H

View File

@@ -59,6 +59,8 @@ CONCAVE_SHAPES_END_HERE,
COMPOUND_SHAPE_PROXYTYPE, COMPOUND_SHAPE_PROXYTYPE,
SOFTBODY_SHAPE_PROXYTYPE,
MAX_BROADPHASE_COLLISION_TYPES MAX_BROADPHASE_COLLISION_TYPES
}; };

View File

@@ -81,7 +81,7 @@ public:
} }
btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
}; };

View File

@@ -17,6 +17,123 @@ subject to the following restrictions:
#include "btSoftBody.h" #include "btSoftBody.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
btSoftBody::btSoftBody(btSoftBody::btSoftBodyWorldInfo& worldInfo,int node_count, const btVector3* x, const btScalar* m)
:m_worldInfo(worldInfo)
{
///for now, create a collision shape internally
m_softBodyCollisionShape = new btSoftBodyCollisionShape();
setCollisionShape(m_softBodyCollisionShape);
/* Init */
m_cfg.aeromodel = eAeroModel::V_Point;
m_cfg.kDG = 0;
m_cfg.kLF = 0;
m_cfg.kDP = 0;
m_cfg.kPR = 0;
m_cfg.kVC = 0;
m_cfg.kDF = (btScalar)0.2;
m_cfg.kLST = 1;
m_cfg.kMT = 0;
m_cfg.kSOR = 1;
m_cfg.kCHR = (btScalar)1.0;
m_cfg.kAHR = (btScalar)0.5;
m_cfg.timescale = 1;
m_cfg.timestep = (btScalar)(1/60.);
m_cfg.maxsteps = 60;
m_cfg.iterations = 1;
m_cfg.becollide = true;
m_cfg.bscollide = false;
m_pose.m_bvolume = false;
m_pose.m_bframe = false;
m_pose.m_volume = 0;
m_pose.m_com = btVector3(0,0,0);
m_pose.m_trs.setIdentity();
m_tag = 0;
m_timeacc = 0;
m_bUpdateRtCst = true;
m_bounds[0] = btVector3(0,0,0);
m_bounds[1] = btVector3(0,0,0);
/* Nodes */
getNodes().resize(node_count);
for(int i=0,ni=node_count;i<ni;++i)
{
Node& n=getNodes()[i];
memset(&n,0,sizeof(n));
n.m_x = x?*x++:btVector3(0,0,0);
n.m_q = n.m_x;
n.m_im = m?*m++:1;
n.m_im = n.m_im>0?1/n.m_im:0;
}
updateTransform();
///register to the broadphase
setBroadphaseHandle( m_worldInfo.m_broadphase->createProxy(m_bounds[0],m_bounds[1],SOFTBODY_SHAPE_PROXYTYPE,this,1,1,m_worldInfo.m_dispatcher,0));
}
///destructor
btSoftBody::~btSoftBody()
{
//remove from broadphase
m_worldInfo.m_broadphase->destroyProxy(getBroadphaseHandle(),m_worldInfo.m_dispatcher);
///for now, delete the internal shape
delete m_softBodyCollisionShape;
}
btVector3 btSoftBody::btSoftBodyCollisionShape::m_sScaling(0,0,0);
btSoftBody::btSoftBodyCollisionShape::btSoftBodyCollisionShape()
{
}
btSoftBody::btSoftBodyCollisionShape::~btSoftBodyCollisionShape()
{
}
void btSoftBody::btSoftBodyCollisionShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
{
//not yet
btAssert(0);
}
//
void btSoftBody::updateBounds()
{
if(getNodes().size()>0)
{
m_bounds[0]=
m_bounds[1]=getNodes()[0].m_x;
for(int i=1,ni=getNodes().size();i<ni;++i)
{
const btSoftBody::Node& n=getNodes()[i];
m_bounds[0].setMin(n.m_x);
m_bounds[1].setMax(n.m_x);
m_bounds[0].setMin(n.m_q);
m_bounds[1].setMax(n.m_q);
}
if (getBroadphaseHandle())
{
m_worldInfo.m_broadphase->setAabb(getBroadphaseHandle(),m_bounds[0],m_bounds[1],m_worldInfo.m_dispatcher);
}
}
else
{
m_bounds[0]=
m_bounds[1]=btVector3(0,0,0);
}
}
namespace btsoftbody_internals namespace btsoftbody_internals
{ {
@@ -184,17 +301,17 @@ if(l>SIMD_EPSILON)
static void PointersToIndices(btSoftBody* psb) static void PointersToIndices(btSoftBody* psb)
{ {
#define PTR2IDX(_p_,_b_) reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_)) #define PTR2IDX(_p_,_b_) reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_))
btSoftBody::Node* base=&psb->m_nodes[0]; btSoftBody::Node* base=&psb->getNodes()[0];
for(int i=0,ni=psb->m_links.size();i<ni;++i) for(int i=0,ni=psb->getLinks().size();i<ni;++i)
{ {
psb->m_links[i].m_n[0]=PTR2IDX(psb->m_links[i].m_n[0],base); psb->getLinks()[i].m_n[0]=PTR2IDX(psb->getLinks()[i].m_n[0],base);
psb->m_links[i].m_n[1]=PTR2IDX(psb->m_links[i].m_n[1],base); psb->getLinks()[i].m_n[1]=PTR2IDX(psb->getLinks()[i].m_n[1],base);
} }
for(int i=0,ni=psb->m_faces.size();i<ni;++i) for(int i=0,ni=psb->getFaces().size();i<ni;++i)
{ {
psb->m_faces[i].m_n[0]=PTR2IDX(psb->m_faces[i].m_n[0],base); psb->getFaces()[i].m_n[0]=PTR2IDX(psb->getFaces()[i].m_n[0],base);
psb->m_faces[i].m_n[1]=PTR2IDX(psb->m_faces[i].m_n[1],base); psb->getFaces()[i].m_n[1]=PTR2IDX(psb->getFaces()[i].m_n[1],base);
psb->m_faces[i].m_n[2]=PTR2IDX(psb->m_faces[i].m_n[2],base); psb->getFaces()[i].m_n[2]=PTR2IDX(psb->getFaces()[i].m_n[2],base);
} }
#undef PTR2IDX #undef PTR2IDX
} }
@@ -203,17 +320,17 @@ for(int i=0,ni=psb->m_faces.size();i<ni;++i)
static void IndicesToPointers(btSoftBody* psb) static void IndicesToPointers(btSoftBody* psb)
{ {
#define IDX2PTR(_p_,_b_) ((_b_)+(((char*)_p_)-(char*)0)) #define IDX2PTR(_p_,_b_) ((_b_)+(((char*)_p_)-(char*)0))
btSoftBody::Node* base=&psb->m_nodes[0]; btSoftBody::Node* base=&psb->getNodes()[0];
for(int i=0,ni=psb->m_links.size();i<ni;++i) for(int i=0,ni=psb->getLinks().size();i<ni;++i)
{ {
psb->m_links[i].m_n[0]=IDX2PTR(psb->m_links[i].m_n[0],base); psb->getLinks()[i].m_n[0]=IDX2PTR(psb->getLinks()[i].m_n[0],base);
psb->m_links[i].m_n[1]=IDX2PTR(psb->m_links[i].m_n[1],base); psb->getLinks()[i].m_n[1]=IDX2PTR(psb->getLinks()[i].m_n[1],base);
} }
for(int i=0,ni=psb->m_faces.size();i<ni;++i) for(int i=0,ni=psb->getFaces().size();i<ni;++i)
{ {
psb->m_faces[i].m_n[0]=IDX2PTR(psb->m_faces[i].m_n[0],base); psb->getFaces()[i].m_n[0]=IDX2PTR(psb->getFaces()[i].m_n[0],base);
psb->m_faces[i].m_n[1]=IDX2PTR(psb->m_faces[i].m_n[1],base); psb->getFaces()[i].m_n[1]=IDX2PTR(psb->getFaces()[i].m_n[1],base);
psb->m_faces[i].m_n[2]=IDX2PTR(psb->m_faces[i].m_n[2],base); psb->getFaces()[i].m_n[2]=IDX2PTR(psb->getFaces()[i].m_n[2],base);
} }
#undef IDX2PTR #undef IDX2PTR
} }
@@ -286,9 +403,9 @@ static int RaycastInternal(const btSoftBody* psb,
{ {
int cnt=0; int cnt=0;
mint=SIMD_INFINITY; mint=SIMD_INFINITY;
for(int i=0,ni=psb->m_faces.size();i<ni;++i) for(int i=0,ni=psb->getFaces().size();i<ni;++i)
{ {
const btSoftBody::Face& f=psb->m_faces[i]; const btSoftBody::Face& f=psb->getFaces()[i];
const btScalar t=RayTriangle( org,dir, const btScalar t=RayTriangle( org,dir,
f.m_n[0]->m_x, f.m_n[0]->m_x,
f.m_n[1]->m_x, f.m_n[1]->m_x,
@@ -309,9 +426,9 @@ static btVector3 EvaluateCom(btSoftBody* psb)
btVector3 com(0,0,0); btVector3 com(0,0,0);
if(psb->m_pose.m_bframe) if(psb->m_pose.m_bframe)
{ {
for(int i=0,ni=psb->m_nodes.size();i<ni;++i) for(int i=0,ni=psb->getNodes().size();i<ni;++i)
{ {
com+=psb->m_nodes[i].m_x*psb->m_pose.m_wgh[i]; com+=psb->getNodes()[i].m_x*psb->m_pose.m_wgh[i];
} }
} }
return(com); return(com);
@@ -321,13 +438,13 @@ return(com);
static void UpdateNormals(btSoftBody* psb) static void UpdateNormals(btSoftBody* psb)
{ {
const btVector3 zv(0,0,0); const btVector3 zv(0,0,0);
for(int i=0,ni=psb->m_nodes.size();i<ni;++i) for(int i=0,ni=psb->getNodes().size();i<ni;++i)
{ {
psb->m_nodes[i].m_n=zv; psb->getNodes()[i].m_n=zv;
} }
for(int i=0,ni=psb->m_faces.size();i<ni;++i) for(int i=0,ni=psb->getFaces().size();i<ni;++i)
{ {
btSoftBody::Face& f=psb->m_faces[i]; btSoftBody::Face& f=psb->getFaces()[i];
const btVector3 n=cross(f.m_n[1]->m_x-f.m_n[0]->m_x, const btVector3 n=cross(f.m_n[1]->m_x-f.m_n[0]->m_x,
f.m_n[2]->m_x-f.m_n[0]->m_x); f.m_n[2]->m_x-f.m_n[0]->m_x);
f.m_normal=n.normalized(); f.m_normal=n.normalized();
@@ -335,40 +452,13 @@ for(int i=0,ni=psb->m_faces.size();i<ni;++i)
f.m_n[1]->m_n+=n; f.m_n[1]->m_n+=n;
f.m_n[2]->m_n+=n; f.m_n[2]->m_n+=n;
} }
for(int i=0,ni=psb->m_nodes.size();i<ni;++i) for(int i=0,ni=psb->getNodes().size();i<ni;++i)
{ {
psb->m_nodes[i].m_n.normalize(); psb->getNodes()[i].m_n.normalize();
} }
} }
//
static void UpdateBounds(btSoftBody* psb)
{
if(psb->m_nodes.size()>0)
{
psb->m_bounds[0]=
psb->m_bounds[1]=psb->m_nodes[0].m_x;
for(int i=1,ni=psb->m_nodes.size();i<ni;++i)
{
const btSoftBody::Node& n=psb->m_nodes[i];
psb->m_bounds[0].setMin(n.m_x);
psb->m_bounds[1].setMax(n.m_x);
psb->m_bounds[0].setMin(n.m_q);
psb->m_bounds[1].setMax(n.m_q);
}
}
else
{
psb->m_bounds[0]=
psb->m_bounds[1]=btVector3(0,0,0);
}
}
//
static void UpdateTransform(btSoftBody* psb)
{
UpdateBounds(psb);
}
// //
static void UpdatePose(btSoftBody* psb) static void UpdatePose(btSoftBody* psb)
@@ -381,12 +471,12 @@ if(psb->m_pose.m_bframe)
pose.m_com = com; pose.m_com = com;
/* Rotation */ /* Rotation */
btMatrix3x3 Apq; btMatrix3x3 Apq;
const btScalar eps=1/(btScalar)(100*psb->m_nodes.size()); const btScalar eps=1/(btScalar)(100*psb->getNodes().size());
Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0); Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0);
Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3); Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3);
for(int i=0,ni=psb->m_nodes.size();i<ni;++i) for(int i=0,ni=psb->getNodes().size();i<ni;++i)
{ {
const btVector3 a=pose.m_wgh[i]*(psb->m_nodes[i].m_x-com); const btVector3 a=pose.m_wgh[i]*(psb->getNodes()[i].m_x-com);
const btVector3& b=pose.m_pos[i]; const btVector3& b=pose.m_pos[i];
Apq[0]+=a.x()*b; Apq[0]+=a.x()*b;
Apq[1]+=a.y()*b; Apq[1]+=a.y()*b;
@@ -402,42 +492,42 @@ if(psb->m_pose.m_bframe)
static void UpdateConstants(btSoftBody* psb) static void UpdateConstants(btSoftBody* psb)
{ {
/* Links */ /* Links */
for(int i=0,ni=psb->m_links.size();i<ni;++i) for(int i=0,ni=psb->getLinks().size();i<ni;++i)
{ {
btSoftBody::Link& l=psb->m_links[i]; btSoftBody::Link& l=psb->getLinks()[i];
l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length(); l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
l.m_c0 = l.m_n[0]->m_im+l.m_n[1]->m_im; l.m_c0 = l.m_n[0]->m_im+l.m_n[1]->m_im;
l.m_c1 = l.m_rl*l.m_rl; l.m_c1 = l.m_rl*l.m_rl;
} }
/* Faces */ /* Faces */
for(int i=0,ni=psb->m_faces.size();i<ni;++i) for(int i=0,ni=psb->getFaces().size();i<ni;++i)
{ {
btSoftBody::Face& f=psb->m_faces[i]; btSoftBody::Face& f=psb->getFaces()[i];
f.m_ra = AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x); f.m_ra = AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
} }
/* Area's */ /* Area's */
btAlignedObjectArray<int> counts; btAlignedObjectArray<int> counts;
counts.resize(psb->m_nodes.size(),0); counts.resize(psb->getNodes().size(),0);
for(int i=0,ni=psb->m_nodes.size();i<ni;++i) for(int i=0,ni=psb->getNodes().size();i<ni;++i)
{ {
psb->m_nodes[i].m_area = 0; psb->getNodes()[i].m_area = 0;
} }
for(int i=0,ni=psb->m_faces.size();i<ni;++i) for(int i=0,ni=psb->getFaces().size();i<ni;++i)
{ {
btSoftBody::Face& f=psb->m_faces[i]; btSoftBody::Face& f=psb->getFaces()[i];
for(int j=0;j<3;++j) for(int j=0;j<3;++j)
{ {
const int index=(int)(f.m_n[j]-&psb->m_nodes[0]); const int index=(int)(f.m_n[j]-&psb->getNodes()[0]);
counts[index]++; counts[index]++;
f.m_n[j]->m_area+=btFabs(f.m_ra); f.m_n[j]->m_area+=btFabs(f.m_ra);
} }
} }
for(int i=0,ni=psb->m_nodes.size();i<ni;++i) for(int i=0,ni=psb->getNodes().size();i<ni;++i)
{ {
if(counts[i]>0) if(counts[i]>0)
psb->m_nodes[i].m_area/=(btScalar)counts[i]; psb->getNodes()[i].m_area/=(btScalar)counts[i];
else else
psb->m_nodes[i].m_area=0; psb->getNodes()[i].m_area=0;
} }
} }
@@ -482,7 +572,7 @@ const bool use_volume= as_pressure ||
btScalar volume=0; btScalar volume=0;
btScalar ivolumetp=0; btScalar ivolumetp=0;
btScalar dvolumetv=0; btScalar dvolumetv=0;
btSoftBody::ISoftBody::sMedium medium; btSoftBody::sMedium medium;
if(use_volume) if(use_volume)
{ {
volume = psb->GetVolume(); volume = psb->GetVolume();
@@ -490,14 +580,14 @@ if(use_volume)
dvolumetv = (psb->m_pose.m_volume-volume)*kVC; dvolumetv = (psb->m_pose.m_volume-volume)*kVC;
} }
/* Per vertex forces */ /* Per vertex forces */
for(int i=0,ni=psb->m_nodes.size();i<ni;++i) for(int i=0,ni=psb->getNodes().size();i<ni;++i)
{ {
btSoftBody::Node& n=psb->m_nodes[i]; btSoftBody::Node& n=psb->getNodes()[i];
if(n.m_im>0) if(n.m_im>0)
{ {
if(use_medium) if(use_medium)
{ {
psb->m_isb->EvaluateMedium(n.m_x,medium); psb->EvaluateMedium(n.m_x,medium);
/* Aerodynamics */ /* Aerodynamics */
if(as_vaero) if(as_vaero)
{ {
@@ -541,14 +631,14 @@ for(int i=0,ni=psb->m_nodes.size();i<ni;++i)
} }
} }
/* Per face forces */ /* Per face forces */
for(int i=0,ni=psb->m_faces.size();i<ni;++i) for(int i=0,ni=psb->getFaces().size();i<ni;++i)
{ {
btSoftBody::Face& f=psb->m_faces[i]; btSoftBody::Face& f=psb->getFaces()[i];
if(as_faero) if(as_faero)
{ {
const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3; const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3;
const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3; const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3;
psb->m_isb->EvaluateMedium(x,medium); psb->EvaluateMedium(x,medium);
const btVector3 rel_v=v-medium.m_velocity; const btVector3 rel_v=v-medium.m_velocity;
const btScalar rel_v2=rel_v.length2(); const btScalar rel_v2=rel_v.length2();
if(rel_v2>SIMD_EPSILON) if(rel_v2>SIMD_EPSILON)
@@ -603,7 +693,7 @@ const btScalar kCHR=psb->m_cfg.kCHR;
for(int i=0,ni=psb->m_contacts.size();i<ni;++i) for(int i=0,ni=psb->m_contacts.size();i<ni;++i)
{ {
const btSoftBody::Contact& c=psb->m_contacts[i]; const btSoftBody::Contact& c=psb->m_contacts[i];
const btSoftBody::ISoftBody::sCti& cti=c.m_cti; const btSoftBody::sCti& cti=c.m_cti;
const btVector3 va=cti.m_body->getVelocityInLocalPoint(c.m_c1)*sdt; const btVector3 va=cti.m_body->getVelocityInLocalPoint(c.m_c1)*sdt;
const btVector3 vb=c.m_node->m_x-c.m_node->m_q; const btVector3 vb=c.m_node->m_x-c.m_node->m_q;
const btVector3 vr=vb-va; const btVector3 vr=vb-va;
@@ -622,9 +712,9 @@ for(int i=0,ni=psb->m_contacts.size();i<ni;++i)
// //
static void PSolve_Links(btSoftBody* psb,btScalar w) static void PSolve_Links(btSoftBody* psb,btScalar w)
{ {
for(int i=0,ni=psb->m_links.size();i<ni;++i) for(int i=0,ni=psb->getLinks().size();i<ni;++i)
{ {
btSoftBody::Link& l=psb->m_links[i]; btSoftBody::Link& l=psb->getLinks()[i];
if(l.m_c0>0) if(l.m_c0>0)
{ {
btSoftBody::Node& a=*l.m_n[0]; btSoftBody::Node& a=*l.m_n[0];
@@ -647,79 +737,26 @@ using namespace btsoftbody_internals;
// Api // Api
// //
//
btSoftBody* btSoftBody::Create( ISoftBody* isoftbody,
int node_count,
const btVector3* x,
const btScalar* m)
{
btSoftBody* sb=new btSoftBody();
/* Init */
sb->m_cfg.aeromodel = eAeroModel::V_Point;
sb->m_cfg.kDG = 0;
sb->m_cfg.kLF = 0;
sb->m_cfg.kDP = 0;
sb->m_cfg.kPR = 0;
sb->m_cfg.kVC = 0;
sb->m_cfg.kDF = (btScalar)0.2;
sb->m_cfg.kLST = 1;
sb->m_cfg.kMT = 0;
sb->m_cfg.kSOR = 1;
sb->m_cfg.kCHR = (btScalar)1.0;
sb->m_cfg.kAHR = (btScalar)0.5;
sb->m_cfg.timescale = 1;
sb->m_cfg.timestep = (btScalar)(1/60.);
sb->m_cfg.maxsteps = 60;
sb->m_cfg.iterations = 1;
sb->m_cfg.becollide = true;
sb->m_cfg.bscollide = false;
sb->m_pose.m_bvolume = false;
sb->m_pose.m_bframe = false;
sb->m_pose.m_volume = 0;
sb->m_pose.m_com = btVector3(0,0,0);
sb->m_pose.m_trs.setIdentity();
sb->m_isb = isoftbody?isoftbody:new ISoftBody();
sb->m_tag = 0;
sb->m_timeacc = 0;
sb->m_bUpdateRtCst = true;
sb->m_bounds[0] = btVector3(0,0,0);
sb->m_bounds[1] = btVector3(0,0,0);
/* Nodes */
sb->m_nodes.resize(node_count);
for(int i=0,ni=node_count;i<ni;++i)
{
Node& n=sb->m_nodes[i];
memset(&n,0,sizeof(n));
n.m_x = x?*x++:btVector3(0,0,0);
n.m_q = n.m_x;
n.m_im = m?*m++:1;
n.m_im = n.m_im>0?1/n.m_im:0;
}
UpdateTransform(sb);
sb->m_isb->Attach(sb);
return(sb);
}
// //
void btSoftBody::Delete() void btSoftBody::Delete()
{ {
m_isb->Detach(this);
delete this; delete this;
} }
// //
bool btSoftBody::CheckLink(int node0,int node1) const bool btSoftBody::CheckLink(int node0,int node1) const
{ {
return(CheckLink(&m_nodes[node0],&m_nodes[node1])); return(CheckLink(&getNodes()[node0],&getNodes()[node1]));
} }
// //
bool btSoftBody::CheckLink(const Node* node0,const Node* node1) const bool btSoftBody::CheckLink(const Node* node0,const Node* node1) const
{ {
const Node* n[]={node0,node1}; const Node* n[]={node0,node1};
for(int i=0,ni=m_links.size();i<ni;++i) for(int i=0,ni=getLinks().size();i<ni;++i)
{ {
const Link& l=m_links[i]; const Link& l=getLinks()[i];
if( (l.m_n[0]==n[0]&&l.m_n[1]==n[1])|| if( (l.m_n[0]==n[0]&&l.m_n[1]==n[1])||
(l.m_n[0]==n[1]&&l.m_n[1]==n[0])) (l.m_n[0]==n[1]&&l.m_n[1]==n[0]))
{ {
@@ -732,12 +769,12 @@ return(false);
// //
bool btSoftBody::CheckFace(int node0,int node1,int node2) const bool btSoftBody::CheckFace(int node0,int node1,int node2) const
{ {
const Node* n[]={ &m_nodes[node0], const Node* n[]={ &getNodes()[node0],
&m_nodes[node1], &getNodes()[node1],
&m_nodes[node2]}; &getNodes()[node2]};
for(int i=0,ni=m_faces.size();i<ni;++i) for(int i=0,ni=getFaces().size();i<ni;++i)
{ {
const Face& f=m_faces[i]; const Face& f=getFaces()[i];
int c=0; int c=0;
for(int j=0;j<3;++j) for(int j=0;j<3;++j)
{ {
@@ -757,7 +794,7 @@ void btSoftBody::AppendLink( int node0,
eLType::_ type, eLType::_ type,
bool bcheckexist) bool bcheckexist)
{ {
AppendLink(&m_nodes[node0],&m_nodes[node1],kST,type,bcheckexist); AppendLink(&getNodes()[node0],&getNodes()[node1],kST,type,bcheckexist);
} }
// //
@@ -778,7 +815,7 @@ if((!bcheckexist)||(!CheckLink(node0,node1)))
l.m_c1 = 0; l.m_c1 = 0;
l.m_type = type; l.m_type = type;
l.m_tag = 0; l.m_tag = 0;
m_links.push_back(l); getLinks().push_back(l);
m_bUpdateRtCst=true; m_bUpdateRtCst=true;
} }
} }
@@ -787,14 +824,14 @@ if((!bcheckexist)||(!CheckLink(node0,node1)))
void btSoftBody::AppendFace(int node0,int node1,int node2) void btSoftBody::AppendFace(int node0,int node1,int node2)
{ {
Face f; Face f;
f.m_n[0] = &m_nodes[node0]; f.m_n[0] = &getNodes()[node0];
f.m_n[1] = &m_nodes[node1]; f.m_n[1] = &getNodes()[node1];
f.m_n[2] = &m_nodes[node2]; f.m_n[2] = &getNodes()[node2];
f.m_ra = AreaOf( f.m_n[0]->m_x, f.m_ra = AreaOf( f.m_n[0]->m_x,
f.m_n[1]->m_x, f.m_n[1]->m_x,
f.m_n[2]->m_x); f.m_n[2]->m_x);
f.m_tag = 0; f.m_tag = 0;
m_faces.push_back(f); getFaces().push_back(f);
m_bUpdateRtCst=true; m_bUpdateRtCst=true;
} }
@@ -802,7 +839,7 @@ m_bUpdateRtCst=true;
void btSoftBody::AppendAnchor(int node,btRigidBody* body) void btSoftBody::AppendAnchor(int node,btRigidBody* body)
{ {
Anchor a; Anchor a;
a.m_node = &m_nodes[node]; a.m_node = &getNodes()[node];
a.m_body = body; a.m_body = body;
a.m_local = body->getWorldTransform().inverse()*a.m_node->m_x; a.m_local = body->getWorldTransform().inverse()*a.m_node->m_x;
a.m_node->m_battach = 1; a.m_node->m_battach = 1;
@@ -812,13 +849,13 @@ m_anchors.push_back(a);
// //
void btSoftBody::AddForce(const btVector3& force) void btSoftBody::AddForce(const btVector3& force)
{ {
for(int i=0,ni=m_nodes.size();i<ni;++i) AddForce(force,i); for(int i=0,ni=getNodes().size();i<ni;++i) AddForce(force,i);
} }
// //
void btSoftBody::AddForce(const btVector3& force,int node) void btSoftBody::AddForce(const btVector3& force,int node)
{ {
Node& n=m_nodes[node]; Node& n=getNodes()[node];
if(n.m_im>0) if(n.m_im>0)
{ {
n.m_f += force; n.m_f += force;
@@ -828,13 +865,13 @@ if(n.m_im>0)
// //
void btSoftBody::AddVelocity(const btVector3& velocity) void btSoftBody::AddVelocity(const btVector3& velocity)
{ {
for(int i=0,ni=m_nodes.size();i<ni;++i) AddVelocity(velocity,i); for(int i=0,ni=getNodes().size();i<ni;++i) AddVelocity(velocity,i);
} }
// //
void btSoftBody::AddVelocity(const btVector3& velocity,int node) void btSoftBody::AddVelocity(const btVector3& velocity,int node)
{ {
Node& n=m_nodes[node]; Node& n=getNodes()[node];
if(n.m_im>0) if(n.m_im>0)
{ {
n.m_v += velocity; n.m_v += velocity;
@@ -844,21 +881,21 @@ if(n.m_im>0)
// //
void btSoftBody::SetMass(int node,btScalar mass) void btSoftBody::SetMass(int node,btScalar mass)
{ {
m_nodes[node].m_im=mass>0?1/mass:0; getNodes()[node].m_im=mass>0?1/mass:0;
m_bUpdateRtCst=true; m_bUpdateRtCst=true;
} }
// //
btScalar btSoftBody::GetMass(int node) const btScalar btSoftBody::GetMass(int node) const
{ {
return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0); return(getNodes()[node].m_im>0?1/getNodes()[node].m_im:0);
} }
// //
btScalar btSoftBody::GetTotalMass() const btScalar btSoftBody::GetTotalMass() const
{ {
btScalar mass=0; btScalar mass=0;
for(int i=0;i<m_nodes.size();++i) for(int i=0;i<getNodes().size();++i)
{ {
mass+=GetMass(i); mass+=GetMass(i);
} }
@@ -870,13 +907,13 @@ void btSoftBody::SetTotalMass(btScalar mass,bool fromfaces)
{ {
if(fromfaces) if(fromfaces)
{ {
for(int i=0;i<m_nodes.size();++i) for(int i=0;i<getNodes().size();++i)
{ {
m_nodes[i].m_im=0; getNodes()[i].m_im=0;
} }
for(int i=0;i<m_faces.size();++i) for(int i=0;i<getFaces().size();++i)
{ {
const Face& f=m_faces[i]; const Face& f=getFaces()[i];
const btScalar twicearea=AreaOf( f.m_n[0]->m_x, const btScalar twicearea=AreaOf( f.m_n[0]->m_x,
f.m_n[1]->m_x, f.m_n[1]->m_x,
f.m_n[2]->m_x); f.m_n[2]->m_x);
@@ -885,16 +922,16 @@ if(fromfaces)
f.m_n[j]->m_im+=twicearea; f.m_n[j]->m_im+=twicearea;
} }
} }
for(int i=0;i<m_nodes.size();++i) for(int i=0;i<getNodes().size();++i)
{ {
m_nodes[i].m_im=1/m_nodes[i].m_im; getNodes()[i].m_im=1/getNodes()[i].m_im;
} }
} }
const btScalar tm=GetTotalMass(); const btScalar tm=GetTotalMass();
const btScalar itm=1/tm; const btScalar itm=1/tm;
for(int i=0;i<m_nodes.size();++i) for(int i=0;i<getNodes().size();++i)
{ {
m_nodes[i].m_im/=itm*mass; getNodes()[i].m_im/=itm*mass;
} }
m_bUpdateRtCst=true; m_bUpdateRtCst=true;
} }
@@ -908,29 +945,29 @@ SetTotalMass(GetVolume()*density,true);
// //
void btSoftBody::Transform(const btTransform& trs) void btSoftBody::Transform(const btTransform& trs)
{ {
for(int i=0,ni=m_nodes.size();i<ni;++i) for(int i=0,ni=getNodes().size();i<ni;++i)
{ {
Node& n=m_nodes[i]; Node& n=getNodes()[i];
n.m_x=trs*n.m_x; n.m_x=trs*n.m_x;
n.m_q=trs*n.m_q; n.m_q=trs*n.m_q;
n.m_n=trs.getBasis()*n.m_n; n.m_n=trs.getBasis()*n.m_n;
} }
UpdateNormals(this); UpdateNormals(this);
UpdateTransform(this); updateTransform();
UpdateConstants(this); UpdateConstants(this);
} }
// //
void btSoftBody::Scale(const btVector3& scl) void btSoftBody::Scale(const btVector3& scl)
{ {
for(int i=0,ni=m_nodes.size();i<ni;++i) for(int i=0,ni=getNodes().size();i<ni;++i)
{ {
Node& n=m_nodes[i]; Node& n=getNodes()[i];
n.m_x*=scl; n.m_x*=scl;
n.m_q*=scl; n.m_q*=scl;
} }
UpdateNormals(this); UpdateNormals(this);
UpdateTransform(this); updateTransform();
UpdateConstants(this); UpdateConstants(this);
} }
@@ -941,26 +978,26 @@ m_pose.m_bvolume = bvolume;
m_pose.m_bframe = bframe; m_pose.m_bframe = bframe;
/* Weights */ /* Weights */
const btScalar omass=GetTotalMass(); const btScalar omass=GetTotalMass();
const btScalar kmass=omass*m_nodes.size()*1000; const btScalar kmass=omass*getNodes().size()*1000;
btScalar tmass=omass; btScalar tmass=omass;
m_pose.m_wgh.resize(m_nodes.size()); m_pose.m_wgh.resize(getNodes().size());
for(int i=0,ni=m_nodes.size();i<ni;++i) for(int i=0,ni=getNodes().size();i<ni;++i)
{ {
if(m_nodes[i].m_im<=0) tmass+=kmass; if(getNodes()[i].m_im<=0) tmass+=kmass;
} }
for(int i=0,ni=m_nodes.size();i<ni;++i) for(int i=0,ni=getNodes().size();i<ni;++i)
{ {
Node& n=m_nodes[i]; Node& n=getNodes()[i];
m_pose.m_wgh[i]= n.m_im>0 ? m_pose.m_wgh[i]= n.m_im>0 ?
1/(m_nodes[i].m_im*tmass) : 1/(getNodes()[i].m_im*tmass) :
kmass/tmass; kmass/tmass;
} }
/* Pos */ /* Pos */
const btVector3 com=EvaluateCom(this); const btVector3 com=EvaluateCom(this);
m_pose.m_pos.resize(m_nodes.size()); m_pose.m_pos.resize(getNodes().size());
for(int i=0,ni=m_nodes.size();i<ni;++i) for(int i=0,ni=getNodes().size();i<ni;++i)
{ {
m_pose.m_pos[i]=m_nodes[i].m_x-com; m_pose.m_pos[i]=getNodes()[i].m_x-com;
} }
m_pose.m_volume = bvolume?GetVolume():0; m_pose.m_volume = bvolume?GetVolume():0;
m_pose.m_com = com; m_pose.m_com = com;
@@ -972,12 +1009,12 @@ UpdateConstants(this);
btScalar btSoftBody::GetVolume() const btScalar btSoftBody::GetVolume() const
{ {
btScalar vol=0; btScalar vol=0;
if(m_nodes.size()>0) if(getNodes().size()>0)
{ {
const btVector3 org=m_nodes[0].m_x; const btVector3 org=getNodes()[0].m_x;
for(int i=0,ni=m_faces.size();i<ni;++i) for(int i=0,ni=getFaces().size();i<ni;++i)
{ {
const Face& f=m_faces[i]; const Face& f=getFaces()[i];
vol+=dot(f.m_n[0]->m_x-org,cross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org)); vol+=dot(f.m_n[0]->m_x-org,cross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org));
} }
vol/=(btScalar)6; vol/=(btScalar)6;
@@ -992,7 +1029,7 @@ int btSoftBody::GenerateBendingConstraints( int distance,
if(distance>1) if(distance>1)
{ {
/* Build graph */ /* Build graph */
const int n=m_nodes.size(); const int n=getNodes().size();
const unsigned inf=(~(unsigned)0)>>1; const unsigned inf=(~(unsigned)0)>>1;
unsigned* adj=new unsigned[n*n]; unsigned* adj=new unsigned[n*n];
#define IDX(_x_,_y_) ((_y_)*n+(_x_)) #define IDX(_x_,_y_) ((_y_)*n+(_x_))
@@ -1005,12 +1042,12 @@ if(distance>1)
adj[IDX(i,j)]=adj[IDX(j,i)]=0; adj[IDX(i,j)]=adj[IDX(j,i)]=0;
} }
} }
for(int i=0;i<m_links.size();++i) for(int i=0;i<getLinks().size();++i)
{ {
if(m_links[i].m_type==eLType::Structural) if(getLinks()[i].m_type==eLType::Structural)
{ {
const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]); const int ia=(int)(getLinks()[i].m_n[0]-&getNodes()[0]);
const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]); const int ib=(int)(getLinks()[i].m_n[1]-&getNodes()[0]);
adj[IDX(ia,ib)]=1; adj[IDX(ia,ib)]=1;
adj[IDX(ib,ia)]=1; adj[IDX(ib,ia)]=1;
} }
@@ -1051,13 +1088,13 @@ return(0);
// //
void btSoftBody::RandomizeConstraints() void btSoftBody::RandomizeConstraints()
{ {
for(int i=0,ni=m_links.size();i<ni;++i) for(int i=0,ni=getLinks().size();i<ni;++i)
{ {
btSwap(m_links[i],m_links[rand()%ni]); btSwap(getLinks()[i],getLinks()[rand()%ni]);
} }
for(int i=0,ni=m_faces.size();i<ni;++i) for(int i=0,ni=getFaces().size();i<ni;++i)
{ {
btSwap(m_faces[i],m_faces[rand()%ni]); btSwap(getFaces()[i],getFaces()[rand()%ni]);
} }
} }
@@ -1090,11 +1127,11 @@ while(m_timeacc>=m_cfg.timestep)
const btScalar iit = 1/(btScalar)m_cfg.iterations; const btScalar iit = 1/(btScalar)m_cfg.iterations;
const btScalar sdt = m_cfg.timestep*m_cfg.timescale; const btScalar sdt = m_cfg.timestep*m_cfg.timescale;
const btScalar isdt = 1/sdt; const btScalar isdt = 1/sdt;
Node* pnodes = m_nodes.size()>0?&m_nodes[0]:0; Node* pnodes = getNodes().size()>0?&getNodes()[0]:0;
/* Forces */ /* Forces */
ApplyForces(this,sdt); ApplyForces(this,sdt);
/* Integrate */ /* Integrate */
for(int i=0,ni=m_nodes.size();i<ni;++i) for(int i=0,ni=getNodes().size();i<ni;++i)
{ {
Node& n=pnodes[i]; Node& n=pnodes[i];
n.m_q = n.m_x; n.m_q = n.m_x;
@@ -1106,7 +1143,7 @@ while(m_timeacc>=m_cfg.timestep)
/* Match */ /* Match */
if(m_pose.m_bframe&&(m_cfg.kMT>0)) if(m_pose.m_bframe&&(m_cfg.kMT>0))
{ {
for(int i=0,ni=m_nodes.size();i<ni;++i) for(int i=0,ni=getNodes().size();i<ni;++i)
{ {
Node& n=pnodes[i]; Node& n=pnodes[i];
if(n.m_im>0) if(n.m_im>0)
@@ -1119,14 +1156,16 @@ while(m_timeacc>=m_cfg.timestep)
} }
/* External collide */ /* External collide */
m_contacts.resize(0); m_contacts.resize(0);
if(m_cfg.becollide) if(m_cfg.becollide)
{ {
m_isb->StartCollide(m_bounds[0],m_bounds[1]); StartCollide(m_bounds[0],m_bounds[1]);
for(int i=0,ni=m_nodes.size();i<ni;++i)
for(int i=0,ni=getNodes().size();i<ni;++i)
{ {
Node& n=pnodes[i]; Node& n=pnodes[i];
Contact c; Contact c;
if((!n.m_battach)&&m_isb->CheckContact(n.m_x,c.m_cti)) if((!n.m_battach)&&CheckContact(n.m_x,c.m_cti))
{ {
const btRigidBody* prb=c.m_cti.m_body; const btRigidBody* prb=c.m_cti.m_body;
const btScalar ima=n.m_im; const btScalar ima=n.m_im;
@@ -1152,7 +1191,7 @@ while(m_timeacc>=m_cfg.timestep)
} }
} }
} }
m_isb->EndCollide(); EndCollide();
} }
/* Prepare anchors */ /* Prepare anchors */
for(int i=0,ni=m_anchors.size();i<ni;++i) for(int i=0,ni=m_anchors.size();i<ni;++i)
@@ -1177,13 +1216,42 @@ while(m_timeacc>=m_cfg.timestep)
} }
/* Velocities */ /* Velocities */
const btScalar vc=isdt*(1-m_cfg.kDP); const btScalar vc=isdt*(1-m_cfg.kDP);
for(int i=0,ni=m_nodes.size();i<ni;++i) for(int i=0,ni=getNodes().size();i<ni;++i)
{ {
pnodes[i].m_v = (pnodes[i].m_x-pnodes[i].m_q)*vc; pnodes[i].m_v = (pnodes[i].m_x-pnodes[i].m_q)*vc;
pnodes[i].m_f = btVector3(0,0,0); pnodes[i].m_f = btVector3(0,0,0);
} }
/* Update */ /* Update */
UpdateTransform(this); updateTransform();
UpdateNormals(this); UpdateNormals(this);
} }
} }
//
bool btSoftBody::CheckContact( const btVector3& x,
btSoftBody::sCti& cti)
{
btScalar maxdepth=0;
btGjkEpaSolver2::sResults res;
for(int i=0,ni=m_overlappingRigidBodies.size();i<ni;++i)
{
btVector3 nrm;
btRigidBody* prb=btRigidBody::upcast(m_overlappingRigidBodies[i]);
btCollisionShape* shp=prb->getCollisionShape();
btConvexShape* csh=static_cast<btConvexShape*>(shp);
const btTransform& wtr=prb->getWorldTransform();
btScalar dst=m_worldInfo.m_sparsesdf.Evaluate(wtr.invXform(x),csh,nrm);
nrm=wtr.getBasis()*nrm;
btVector3 wit=x-nrm*dst;
if(dst<maxdepth)
{
maxdepth = dst;
cti.m_body = prb;
cti.m_normal = nrm;
cti.m_offset = -dot(cti.m_normal,wit);
}
}
return(maxdepth<0);
}

View File

@@ -14,8 +14,8 @@ subject to the following restrictions:
*/ */
///btSoftBody implementation by Nathanael Presson ///btSoftBody implementation by Nathanael Presson
#ifndef _312AEEF3_52DA_4ff6_B804_FCF937182E46_ #ifndef _BT_SOFT_BODY_H
#define _312AEEF3_52DA_4ff6_B804_FCF937182E46_ #define _BT_SOFT_BODY_H
#include "LinearMath/btAlignedObjectArray.h" #include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btPoint3.h" #include "LinearMath/btPoint3.h"
@@ -23,67 +23,100 @@ subject to the following restrictions:
#include "LinearMath/btIDebugDraw.h" #include "LinearMath/btIDebugDraw.h"
#include "BulletDynamics/Dynamics/btRigidBody.h" #include "BulletDynamics/Dynamics/btRigidBody.h"
// #include "BulletCollision/CollisionShapes/btConcaveShape.h"
// btSoftBody #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
// #include "BulletDynamics/SoftBody/btSparseSDF.h"
struct btSoftBody
class btBroadphaseInterface;
class btCollisionDispatcher;
/// btSoftBody is work-in-progress
struct btSoftBody : public btCollisionObject
{ {
// //
// Enumerations // Enumerations
// //
/* eLType */ ///eLType
struct eLType { enum _ { struct eLType { enum _ {
Structural, /* Master constraints */ Structural, ///Master constraints
Bending, /* Secondary constraints */ Bending, ///Secondary constraints
};}; };};
/* eAeroModel */ ////eAeroModel
struct eAeroModel { enum _ { struct eAeroModel { enum _ {
V_Point, /* Vertex normals are oriented toward velocity */ V_Point, ///Vertex normals are oriented toward velocity
V_TwoSided, /* Vertex normals are fliped to match velocity */ V_TwoSided, ///Vertex normals are fliped to match velocity
V_OneSided, /* Vertex normals are taken as it is */ V_OneSided, ///Vertex normals are taken as it is
F_TwoSided, /* Face normals are fliped to match velocity */ F_TwoSided, ///Face normals are fliped to match velocity
F_OneSided, /* Face normals are taken as it is */ F_OneSided, ///Face normals are taken as it is
};}; };};
// struct btSoftBodyWorldInfo
// Interfaces
//
/* ISoftBody */
struct ISoftBody
{ {
btScalar air_density;
btScalar water_density;
btScalar water_offset;
btVector3 water_normal;
btBroadphaseInterface* m_broadphase;
btCollisionDispatcher* m_dispatcher;
btSparseSdf<3> m_sparsesdf;
};
//reference or copy?
btSoftBodyWorldInfo& m_worldInfo;
///constructor
btSoftBody(btSoftBody::btSoftBodyWorldInfo& worldInfo,int node_count,
const btVector3* x,
const btScalar* m);
///sCti is Softbody contact info
struct sCti struct sCti
{ {
btRigidBody* m_body; /* Rigid body */ btRigidBody* m_body; /* Rigid body */
btVector3 m_normal; /* Outward normal */ btVector3 m_normal; /* Outward normal */
btScalar m_offset; /* Offset from origin */ btScalar m_offset; /* Offset from origin */
}; };
void StartCollide(const btVector3& aabbMin,const btVector3& aabbMax)
{
//??
}
void EndCollide()
{
//??
}
//
bool CheckContact( const btVector3& x, btSoftBody::sCti& cti);
////
///destructor
virtual ~btSoftBody();
struct sMedium struct sMedium
{ {
btVector3 m_velocity; /* Velocity */ btVector3 m_velocity; /* Velocity */
btScalar m_pressure; /* Pressure */ btScalar m_pressure; /* Pressure */
btScalar m_density; /* Density */ btScalar m_density; /* Density */
}; };
virtual void Attach(btSoftBody*)
{} virtual void EvaluateMedium( const btVector3& /*position*/, sMedium& medium)
virtual void Detach(btSoftBody*) {
{ delete this; } medium.m_velocity=btVector3(0,0,0);
virtual void StartCollide( const btVector3& /*minbounds*/,
const btVector3& /*maxbounds*/)
{}
virtual bool CheckContact (const btVector3& /*position*/,
sCti& /*contact*/)
{ return(false); }
virtual void EndCollide()
{}
virtual void EvaluateMedium( const btVector3& /*position*/,
sMedium& medium)
{ medium.m_velocity=btVector3(0,0,0);
medium.m_pressure=0; medium.m_pressure=0;
medium.m_density=0; } medium.m_density=0;
}; }
// //
// Internal types // Internal types
@@ -97,7 +130,7 @@ struct btSoftBody
{ {
void* m_tag; // User data void* m_tag; // User data
}; };
/* Node */ ///Node
struct Node : Element struct Node : Element
{ {
btVector3 m_x; // Position btVector3 m_x; // Position
@@ -117,7 +150,7 @@ struct btSoftBody
btScalar m_kST; // Stiffness coefficient btScalar m_kST; // Stiffness coefficient
btScalar m_c0; // (ima+imb)*kLST btScalar m_c0; // (ima+imb)*kLST
btScalar m_c1; // rl^2 btScalar m_c1; // rl^2
eLType::_ m_type; // Link type btSoftBody::eLType::_ m_type; // Link type
}; };
/* Face */ /* Face */
struct Face : Element struct Face : Element
@@ -129,7 +162,7 @@ struct btSoftBody
/* Contact */ /* Contact */
struct Contact struct Contact
{ {
ISoftBody::sCti m_cti; // Contact infos btSoftBody::sCti m_cti; // Contact infos
Node* m_node; // Owner node Node* m_node; // Owner node
btMatrix3x3 m_c0; // Impulse matrix btMatrix3x3 m_c0; // Impulse matrix
btVector3 m_c1; // Relative anchor btVector3 m_c1; // Relative anchor
@@ -160,7 +193,7 @@ struct btSoftBody
/* Config */ /* Config */
struct Config struct Config
{ {
eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point) btSoftBody::eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point)
btScalar kLST; // Linear stiffness coefficient [0,1] btScalar kLST; // Linear stiffness coefficient [0,1]
btScalar kDP; // Damping coefficient [0,1] btScalar kDP; // Damping coefficient [0,1]
btScalar kDG; // Drag coefficient [0,+inf] btScalar kDG; // Drag coefficient [0,+inf]
@@ -196,11 +229,99 @@ struct btSoftBody
Config m_cfg; // Configuration Config m_cfg; // Configuration
Pose m_pose; // Pose Pose m_pose; // Pose
ISoftBody* m_isb; // ISoftBody
void* m_tag; // User data void* m_tag; // User data
//////////////////////
///btSoftBodyCollisionShape is work-in-progress collision shape for softbodies
class btSoftBodyCollisionShape : public btConcaveShape
{
static btVector3 m_sScaling;
public:
tNodeArray m_nodes; // Nodes tNodeArray m_nodes; // Nodes
tLinkArray m_links; // Links tLinkArray m_links; // Links
tFaceArray m_faces; // Faces tFaceArray m_faces; // Faces
btSoftBodyCollisionShape();
virtual ~btSoftBodyCollisionShape();
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
{
///not yet
btAssert(0);
}
virtual int getShapeType() const
{
return SOFTBODY_SHAPE_PROXYTYPE;
}
virtual void setLocalScaling(const btVector3& scaling)
{
///not yet
btAssert(0);
}
virtual const btVector3& getLocalScaling() const
{
///not yet
btAssert(0);
return m_sScaling;
}
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
///not yet
btAssert(0);
}
virtual const char* getName()const
{
return "SoftBody";
}
};
btSoftBodyCollisionShape* m_softBodyCollisionShape;
btCollisionObjectArray m_overlappingRigidBodies;
btAlignedObjectArray<btSoftBody*> m_overlappingSoftBodies;
//////////////////////
inline tNodeArray& getNodes()
{
return m_softBodyCollisionShape->m_nodes;
}
inline const tNodeArray& getNodes() const
{
return m_softBodyCollisionShape->m_nodes;
}
inline tLinkArray& getLinks()
{
return m_softBodyCollisionShape->m_links;
}
inline const tLinkArray& getLinks() const
{
return m_softBodyCollisionShape->m_links;
}
inline tFaceArray& getFaces()
{
return m_softBodyCollisionShape->m_faces;
}
inline const tFaceArray& getFaces() const
{
return m_softBodyCollisionShape->m_faces;
}
tAnchorArray m_anchors; // Anchors tAnchorArray m_anchors; // Anchors
tContactArray m_contacts; // Contacts tContactArray m_contacts; // Contacts
btScalar m_timeacc; // Time accumulator btScalar m_timeacc; // Time accumulator
@@ -211,11 +332,6 @@ struct btSoftBody
// Api // Api
// //
/* Create a soft body */
static btSoftBody* Create( ISoftBody* isoftbody,
int node_count,
const btVector3* x=0,
const btScalar* m=0);
/* Delete a body */ /* Delete a body */
void Delete(); void Delete();
/* Check for existing link */ /* Check for existing link */
@@ -287,70 +403,16 @@ struct btSoftBody
/* Step */ /* Step */
void Step( btScalar dt); void Step( btScalar dt);
void updateBounds();
void updateTransform()
{
updateBounds();
}
}; };
//
// Helpers
//
/* fDrawFlags */
struct fDrawFlags { enum _ {
Nodes = 0x0001,
SLinks = 0x0002,
BLinks = 0x0004,
Faces = 0x0008,
Tetras = 0x0010,
Normals = 0x0020,
Contacts = 0x0040,
Anchors = 0x0080,
/* presets */
Links = SLinks+BLinks,
Std = SLinks+Faces+Anchors,
StdTetra = Std-Faces+Tetras,
};};
/* Draw body */ #endif //_BT_SOFT_BODY_H
void Draw( btSoftBody* psb,
btIDebugDraw* idraw,
int drawflags=fDrawFlags::Std);
/* Draw body infos */
void DrawInfos( btSoftBody* psb,
btIDebugDraw* idraw,
bool masses,
bool areas,
bool stress);
/* Draw rigid frame */
void DrawFrame( btSoftBody* psb,
btIDebugDraw* idraw);
/* Create a rope */
btSoftBody* CreateRope( btSoftBody::ISoftBody* isoftbody,
const btVector3& from,
const btVector3& to,
int res,
int fixeds);
/* Create a patch */
btSoftBody* CreatePatch( btSoftBody::ISoftBody* isoftbody,
const btVector3& corner00,
const btVector3& corner10,
const btVector3& corner01,
const btVector3& corner11,
int resx,
int resy,
int fixeds,
bool gendiags);
/* Create an ellipsoid */
btSoftBody* CreateEllipsoid(btSoftBody::ISoftBody* isoftbody,
const btVector3& center,
const btVector3& radius,
int res);
/* Create from convex-hull */
btSoftBody* CreateFromConvexHull( btSoftBody::ISoftBody* isoftbody,
const btVector3* vertices,
int nvertices);
/* Create from trimesh */
btSoftBody* CreateFromTriMesh( btSoftBody::ISoftBody* isoftbody,
const btScalar* vertices,
const int* triangles,
int ntriangles);
#endif

View File

@@ -17,12 +17,10 @@ subject to the following restrictions:
#include "btSoftBody.h" #include "btSoftBody.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "btSoftBodyHelpers.h"
namespace btsoftbody_internals
{
// //
static void drawVertex( btIDebugDraw* idraw, void btSoftBodyHelpers::drawVertex( btIDebugDraw* idraw,
const btVector3& x,btScalar s,const btVector3& c) const btVector3& x,btScalar s,const btVector3& c)
{ {
idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c); idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c);
@@ -31,7 +29,7 @@ idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c);
} }
// //
static btVector3 stresscolor(btScalar stress) btVector3 btSoftBodyHelpers::stresscolor(btScalar stress)
{ {
static const btVector3 spectrum[]= { static const btVector3 spectrum[]= {
btVector3(1,0,1), btVector3(1,0,1),
@@ -50,12 +48,10 @@ const btScalar frc=stress-sel;
return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc); return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc);
} }
}
using namespace btsoftbody_internals;
// //
void Draw( btSoftBody* psb, void btSoftBodyHelpers::Draw( btSoftBody* psb,
btIDebugDraw* idraw, btIDebugDraw* idraw,
int drawflags) int drawflags)
{ {
@@ -69,9 +65,9 @@ const btVector3 ccolor=btVector3(1,0,0);
/* Nodes */ /* Nodes */
if(0!=(drawflags&fDrawFlags::Nodes)) if(0!=(drawflags&fDrawFlags::Nodes))
{ {
for(int i=0;i<psb->m_nodes.size();++i) for(int i=0;i<psb->getNodes().size();++i)
{ {
const btSoftBody::Node& n=psb->m_nodes[i]; const btSoftBody::Node& n=psb->getNodes()[i];
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(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,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)); idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1));
@@ -80,9 +76,9 @@ if(0!=(drawflags&fDrawFlags::Nodes))
/* Links */ /* Links */
if(0!=(drawflags&fDrawFlags::Links)) if(0!=(drawflags&fDrawFlags::Links))
{ {
for(int i=0;i<psb->m_links.size();++i) for(int i=0;i<psb->getLinks().size();++i)
{ {
const btSoftBody::Link& l=psb->m_links[i]; const btSoftBody::Link& l=psb->getLinks()[i];
switch(l.m_type) switch(l.m_type)
{ {
case btSoftBody::eLType::Structural: case btSoftBody::eLType::Structural:
@@ -95,9 +91,9 @@ if(0!=(drawflags&fDrawFlags::Links))
/* Normals */ /* Normals */
if(0!=(drawflags&fDrawFlags::Normals)) if(0!=(drawflags&fDrawFlags::Normals))
{ {
for(int i=0;i<psb->m_nodes.size();++i) for(int i=0;i<psb->getNodes().size();++i)
{ {
const btSoftBody::Node& n=psb->m_nodes[i]; const btSoftBody::Node& n=psb->getNodes()[i];
const btVector3 d=n.m_n*nscl; 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);
idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5); idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5);
@@ -132,9 +128,9 @@ if(0!=(drawflags&fDrawFlags::Anchors))
drawVertex(idraw,q,0.25,btVector3(0,1,0)); drawVertex(idraw,q,0.25,btVector3(0,1,0));
idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1)); idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1));
} }
for(int i=0;i<psb->m_nodes.size();++i) for(int i=0;i<psb->getNodes().size();++i)
{ {
const btSoftBody::Node& n=psb->m_nodes[i]; const btSoftBody::Node& n=psb->getNodes()[i];
if(n.m_im<=0) if(n.m_im<=0)
{ {
drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0)); drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0));
@@ -147,9 +143,9 @@ if(0!=(drawflags&fDrawFlags::Faces))
const btScalar scl=(btScalar)0.7; const btScalar scl=(btScalar)0.7;
const btScalar alp=(btScalar)1; const btScalar alp=(btScalar)1;
const btVector3 col(0,(btScalar)0.7,0); const btVector3 col(0,(btScalar)0.7,0);
for(int i=0;i<psb->m_faces.size();++i) for(int i=0;i<psb->getFaces().size();++i)
{ {
const btSoftBody::Face& f=psb->m_faces[i]; const btSoftBody::Face& f=psb->getFaces()[i];
const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x}; 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; const btVector3 c=(x[0]+x[1]+x[2])/3;
idraw->drawTriangle((x[0]-c)*scl+c, idraw->drawTriangle((x[0]-c)*scl+c,
@@ -162,15 +158,15 @@ if(0!=(drawflags&fDrawFlags::Faces))
} }
// //
void DrawInfos( btSoftBody* psb, void btSoftBodyHelpers::DrawInfos( btSoftBody* psb,
btIDebugDraw* idraw, btIDebugDraw* idraw,
bool masses, bool masses,
bool areas, bool areas,
bool stress) bool stress)
{ {
for(int i=0;i<psb->m_nodes.size();++i) for(int i=0;i<psb->getNodes().size();++i)
{ {
const btSoftBody::Node& n=psb->m_nodes[i]; const btSoftBody::Node& n=psb->getNodes()[i];
char text[2048]={0}; char text[2048]={0};
char buff[1024]; char buff[1024];
if(masses) if(masses)
@@ -188,7 +184,7 @@ for(int i=0;i<psb->m_nodes.size();++i)
} }
// //
void DrawFrame( btSoftBody* psb, void btSoftBodyHelpers::DrawFrame( btSoftBody* psb,
btIDebugDraw* idraw) btIDebugDraw* idraw)
{ {
if(psb->m_pose.m_bframe) if(psb->m_pose.m_bframe)
@@ -214,8 +210,7 @@ if(psb->m_pose.m_bframe)
} }
// //
btSoftBody* CreateRope( btSoftBody::ISoftBody* isoftbody, btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBody::btSoftBodyWorldInfo& worldInfo, const btVector3& from,
const btVector3& from,
const btVector3& to, const btVector3& to,
int res, int res,
int fixeds) int fixeds)
@@ -230,7 +225,7 @@ for(int i=0;i<r;++i)
x[i]=lerp(from,to,t); x[i]=lerp(from,to,t);
m[i]=1; m[i]=1;
} }
btSoftBody* psb=btSoftBody::Create(isoftbody,r,x,m); btSoftBody* psb= new btSoftBody(worldInfo,r,x,m);
if(fixeds&1) psb->SetMass(0,0); if(fixeds&1) psb->SetMass(0,0);
if(fixeds&2) psb->SetMass(r-1,0); if(fixeds&2) psb->SetMass(r-1,0);
delete[] x; delete[] x;
@@ -245,8 +240,7 @@ return(psb);
} }
// //
btSoftBody* CreatePatch( btSoftBody::ISoftBody* isoftbody, btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& corner00,
const btVector3& corner00,
const btVector3& corner10, const btVector3& corner10,
const btVector3& corner01, const btVector3& corner01,
const btVector3& corner11, const btVector3& corner11,
@@ -275,7 +269,7 @@ for(int iy=0;iy<ry;++iy)
m[IDX(ix,iy)]=1; m[IDX(ix,iy)]=1;
} }
} }
btSoftBody* psb=btSoftBody::Create(isoftbody,tot,x,m); btSoftBody* psb=new btSoftBody(worldInfo,tot,x,m);
if(fixeds&1) psb->SetMass(IDX(0,0),0); if(fixeds&1) psb->SetMass(IDX(0,0),0);
if(fixeds&2) psb->SetMass(IDX(rx-1,0),0); if(fixeds&2) psb->SetMass(IDX(rx-1,0),0);
if(fixeds&4) psb->SetMass(IDX(0,ry-1),0); if(fixeds&4) psb->SetMass(IDX(0,ry-1),0);
@@ -325,8 +319,7 @@ return(psb);
} }
// //
btSoftBody* CreateEllipsoid(btSoftBody::ISoftBody* isoftbody, btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& center,
const btVector3& center,
const btVector3& radius, const btVector3& radius,
int res) int res)
{ {
@@ -352,14 +345,13 @@ for(int i=0;i<vtx.size();++i)
{ {
vtx[i]=vtx[i]*radius+center; vtx[i]=vtx[i]*radius+center;
} }
return(CreateFromConvexHull(isoftbody,&vtx[0],vtx.size())); return(CreateFromConvexHull(worldInfo,&vtx[0],vtx.size()));
} }
// //
btSoftBody* CreateFromTriMesh( btSoftBody::ISoftBody* isoftbody, btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btScalar* vertices,
const btScalar* vertices,
const int* triangles, const int* triangles,
int ntriangles) int ntriangles)
{ {
@@ -377,7 +369,7 @@ for(int i=0,j=0,ni=maxidx*3;i<ni;++j,i+=3)
{ {
vtx[j]=btVector3(vertices[i],vertices[i+1],vertices[i+2]); vtx[j]=btVector3(vertices[i],vertices[i+1],vertices[i+2]);
} }
btSoftBody* psb=btSoftBody::Create(isoftbody,vtx.size(),&vtx[0],0); btSoftBody* psb=new btSoftBody(worldInfo,vtx.size(),&vtx[0],0);
for(int i=0,ni=ntriangles*3;i<ni;i+=3) for(int i=0,ni=ntriangles*3;i<ni;i+=3)
{ {
const int idx[]={triangles[i],triangles[i+1],triangles[i+2]}; const int idx[]={triangles[i],triangles[i+1],triangles[i+2]};

View File

@@ -0,0 +1,90 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 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 SOFT_BODY_HELPERS_H
#define SOFT_BODY_HELPERS_H
#include "btSoftBody.h"
//
// Helpers
//
/* fDrawFlags */
struct fDrawFlags { enum _ {
Nodes = 0x0001,
SLinks = 0x0002,
BLinks = 0x0004,
Faces = 0x0008,
Tetras = 0x0010,
Normals = 0x0020,
Contacts = 0x0040,
Anchors = 0x0080,
/* presets */
Links = SLinks+BLinks,
Std = SLinks+Faces+Anchors,
StdTetra = Std-Faces+Tetras,
};};
struct btSoftBodyHelpers
{
static btVector3 stresscolor(btScalar stress);
static void drawVertex( btIDebugDraw* idraw,
const btVector3& x,btScalar s,const btVector3& c);
/* Draw body */
static void Draw( btSoftBody* psb,
btIDebugDraw* idraw,
int drawflags=fDrawFlags::Std);
/* Draw body infos */
static void DrawInfos( btSoftBody* psb,
btIDebugDraw* idraw,
bool masses,
bool areas,
bool stress);
/* Draw rigid frame */
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);
/* 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);
/* 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);
/* Create from trimesh */
static btSoftBody* CreateFromTriMesh( btSoftBody::btSoftBodyWorldInfo& worldInfo, const btScalar* vertices,
const int* triangles,
int ntriangles);
};
#endif //SOFT_BODY_HELPERS_H