Added several updates for btSoftBody: convex cluster collision detection, new constraints, new demos (only enabled in SoftBodyDemo, todo for AllBulletDemos) etc.

Thanks a lot to Nathanael Presson for this update.
This commit is contained in:
erwin.coumans
2008-07-22 02:22:01 +00:00
parent fe5033119b
commit d71f8d6623
9 changed files with 3223 additions and 1347 deletions

View File

@@ -129,10 +129,16 @@ void SoftDemo::clientMoveAndDisplay()
m_goal=rayFrom+rayDir*hit;
}
}
m_node->m_v+=(m_goal-m_node->m_x)/dt;
btVector3 delta=m_goal-m_node->m_x;
static const btScalar maxdrag=10;
if(delta.length2()>(maxdrag*maxdrag))
{
delta=delta.normalized()*maxdrag;
}
m_node->m_v+=delta/dt;
}
//#define FIXED_STEP
#define FIXED_STEP
#ifdef FIXED_STEP
m_dynamicsWorld->stepSimulation(dt=1.0f/60.f,0);
@@ -296,7 +302,7 @@ static void Ctor_RbUpStack(SoftDemo* pdemo,int count)
{
btTransform startTransform;
startTransform.setIdentity();
startTransform.setOrigin(btVector3(0,1+6*i,0));
startTransform.setOrigin(btVector3(0,2+6*i,0));
pdemo->localCreateRigidBody(mass,startTransform,shape[i%nshapes]);
}
}
@@ -315,13 +321,14 @@ static void Ctor_BigBall(SoftDemo* pdemo,btScalar mass=10)
//
// Big plate
//
static void Ctor_BigPlate(SoftDemo* pdemo,btScalar mass=15)
static btRigidBody* Ctor_BigPlate(SoftDemo* pdemo,btScalar mass=15,btScalar height=4)
{
btTransform startTransform;
startTransform.setIdentity();
startTransform.setOrigin(btVector3(0,4,0.5));
startTransform.setOrigin(btVector3(0,height,0.5));
btRigidBody* body=pdemo->localCreateRigidBody(mass,startTransform,new btBoxShape(btVector3(5,1,5)));
body->setFriction(1);
return(body);
}
//
@@ -359,6 +366,7 @@ static btSoftBody* Ctor_SoftBox(SoftDemo* pdemo,const btVector3& p,const btVecto
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
return(psb);
}
//
@@ -598,7 +606,9 @@ static void Init_Aero(SoftDemo* pdemo)
btVector3(+s,h,+s),
segments,segments,
0,true);
psb->generateBendingConstraints(2);
btSoftBody::Material* pm=psb->appendMaterial();
pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
psb->generateBendingConstraints(2,pm);
psb->m_cfg.kLF = 0.004;
psb->m_cfg.kDG = 0.0003;
psb->m_cfg.aeromodel = btSoftBody::eAeroModel::V_TwoSided;
@@ -779,7 +789,7 @@ static void Init_Bunny(SoftDemo* pdemo)
psb->m_cfg.kDF = 0.5;
psb->randomizeConstraints();
psb->scale(btVector3(6,6,6));
psb->setTotalMass(100,true);
psb->setTotalMass(100,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
pdemo->m_cutting=true;
@@ -795,12 +805,12 @@ static void Init_BunnyMatch(SoftDemo* pdemo)
&gIndicesBunny[0][0],
BUNNY_NUM_TRIANGLES);
psb->m_cfg.kDF = 0.5;
psb->m_materials[0]->m_kLST = 0.1;
psb->m_cfg.kMT = 0.05;
psb->m_cfg.piterations = 5;
psb->randomizeConstraints();
psb->scale(btVector3(6,6,6));
psb->setTotalMass(100,true);
psb->setPose(true,true);
psb->setPose(false,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
@@ -844,7 +854,7 @@ static void Init_TorusMatch(SoftDemo* pdemo)
psb->transform(btTransform(m,btVector3(0,4,0)));
psb->scale(btVector3(2,2,2));
psb->setTotalMass(50,true);
psb->setPose(true,true);
psb->setPose(false,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
@@ -866,7 +876,371 @@ static void Init_Cutting1(SoftDemo* pdemo)
pdemo->m_cutting=true;
}
unsigned current_demo=0;
//
// Clusters
//
//
static void Ctor_Gear(SoftDemo* pdemo,const btVector3& pos,btScalar speed)
{
btTransform startTransform;
startTransform.setIdentity();
startTransform.setOrigin(pos);
btCompoundShape* shape=new btCompoundShape();
#if 1
shape->addChildShape(btTransform(btQuaternion(0,0,0)),new btBoxShape(btVector3(5,1,6)));
shape->addChildShape(btTransform(btQuaternion(0,0,SIMD_HALF_PI)),new btBoxShape(btVector3(5,1,6)));
#else
shape->addChildShape(btTransform(btQuaternion(0,0,0)),new btCylinderShapeZ(btVector3(5,1,7)));
shape->addChildShape(btTransform(btQuaternion(0,0,SIMD_HALF_PI)),new btBoxShape(btVector3(4,1,8)));
#endif
btRigidBody* body=pdemo->localCreateRigidBody(10,startTransform,shape);
body->setFriction(1);
btDynamicsWorld* world=pdemo->getDynamicsWorld();
btHingeConstraint* hinge=new btHingeConstraint(*body,btTransform::getIdentity());
if(speed!=0) hinge->enableAngularMotor(true,speed,3);
world->addConstraint(hinge);
}
//
static btSoftBody* Ctor_ClusterBunny(SoftDemo* pdemo,const btVector3& x,const btVector3& a)
{
btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVerticesBunny,&gIndicesBunny[0][0],BUNNY_NUM_TRIANGLES);
btSoftBody::Material* pm=psb->appendMaterial();
pm->m_kLST = 1;
pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
psb->generateBendingConstraints(2,pm);
psb->m_cfg.piterations = 2;
psb->m_cfg.kDF = 1;
psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS+
btSoftBody::fCollision::CL_RS;
psb->randomizeConstraints();
btMatrix3x3 m;
m.setEulerZYX(a.x(),a.y(),a.z());
psb->transform(btTransform(m,x));
psb->scale(btVector3(8,8,8));
psb->setTotalMass(150,true);
psb->generateClusters(1);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
return(psb);
}
//
static btSoftBody* Ctor_ClusterTorus(SoftDemo* pdemo,const btVector3& x,const btVector3& a,const btVector3& s=btVector3(2,2,2))
{
btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVertices,&gIndices[0][0],NUM_TRIANGLES);
btSoftBody::Material* pm=psb->appendMaterial();
pm->m_kLST = 1;
pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
psb->generateBendingConstraints(2,pm);
psb->m_cfg.piterations = 2;
psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS+
btSoftBody::fCollision::CL_RS;
psb->randomizeConstraints();
psb->scale(s);
psb->rotate(btQuaternion(a[0],a[1],a[2]));
psb->translate(x);
psb->setTotalMass(50,true);
psb->generateClusters(64);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
return(psb);
}
//
static struct MotorControl : btSoftBody::AJoint::IControl
{
MotorControl()
{
goal=0;
maxtorque=0;
}
btScalar Speed(btSoftBody::AJoint*,btScalar current)
{
return(current+btMin(maxtorque,btMax(-maxtorque,goal-current)));
}
btScalar goal;
btScalar maxtorque;
} motorcontrol;
//
struct SteerControl : btSoftBody::AJoint::IControl
{
SteerControl(btScalar s)
{
angle=0;
sign=s;
}
void Prepare(btSoftBody::AJoint* joint)
{
joint->m_refs[0][0]=btCos(angle*sign);
joint->m_refs[0][2]=btSin(angle*sign);
}
btScalar Speed(btSoftBody::AJoint* joint,btScalar current)
{
return(motorcontrol.Speed(joint,current));
}
btScalar angle;
btScalar sign;
};
static SteerControl steercontrol_f(+1);
static SteerControl steercontrol_r(-1);
//
static void Init_ClusterDeform(SoftDemo* pdemo)
{
btSoftBody* psb=Ctor_ClusterTorus(pdemo,btVector3(0,0,0),btVector3(SIMD_PI/2,0,SIMD_HALF_PI));
psb->generateClusters(8);
psb->m_cfg.kDF=1;
}
//
static void Init_ClusterCollide1(SoftDemo* pdemo)
{
const btScalar s=8;
btSoftBody* psb=btSoftBodyHelpers::CreatePatch( pdemo->m_softBodyWorldInfo,btVector3(-s,0,-s),
btVector3(+s,0,-s),
btVector3(-s,0,+s),
btVector3(+s,0,+s),
31,31,
1+2+4+8,true);
btSoftBody::Material* pm=psb->appendMaterial();
pm->m_kLST = 0.4;
pm->m_flags -= btSoftBody::fMaterial::DebugDraw;
psb->m_cfg.kDF = 1;
psb->m_cfg.kSRHR_CL = 1;
psb->m_cfg.kSR_SPLT_CL = 0;
psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS+
btSoftBody::fCollision::CL_RS;
psb->generateBendingConstraints(2,pm);
psb->setTotalMass(50);
psb->generateClusters(64);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
Ctor_RbUpStack(pdemo,10);
}
//
static void Init_ClusterCollide2(SoftDemo* pdemo)
{
struct Functor
{
static btSoftBody* Create(SoftDemo* pdemo,const btVector3& x,const btVector3& a)
{
btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVertices,
&gIndices[0][0],
NUM_TRIANGLES);
psb->generateBendingConstraints(2);
psb->m_cfg.piterations=2;
psb->m_cfg.kSSHR_CL =1;
psb->m_cfg.kSS_SPLT_CL =0;
psb->m_cfg.collisions= btSoftBody::fCollision::CL_SS+
btSoftBody::fCollision::CL_RS;
psb->randomizeConstraints();
btMatrix3x3 m;
m.setEulerZYX(a.x(),a.y(),a.z());
psb->transform(btTransform(m,x));
psb->scale(btVector3(2,2,2));
psb->setTotalMass(50,true);
psb->generateClusters(16);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
return(psb);
}
};
for(int i=0;i<3;++i)
{
Functor::Create(pdemo,btVector3(3*i,2,0),btVector3(SIMD_PI/2*(1-(i&1)),SIMD_PI/2*(i&1),0));
}
}
//
static void Init_ClusterSocket(SoftDemo* pdemo)
{
btSoftBody* psb=Ctor_ClusterTorus(pdemo,btVector3(0,0,0),btVector3(SIMD_PI/2,0,SIMD_HALF_PI));
btRigidBody* prb=Ctor_BigPlate(pdemo,50,8);
psb->m_cfg.kDF=1;
btSoftBody::LJoint::Specs lj;
lj.position = btVector3(0,5,0);
psb->appendLinearJoint(lj,prb);
}
//
static void Init_ClusterHinge(SoftDemo* pdemo)
{
btSoftBody* psb=Ctor_ClusterTorus(pdemo,btVector3(0,0,0),btVector3(SIMD_PI/2,0,SIMD_HALF_PI));
btRigidBody* prb=Ctor_BigPlate(pdemo,50,8);
psb->m_cfg.kDF=1;
btSoftBody::AJoint::Specs aj;
aj.axis = btVector3(0,0,1);
psb->appendAngularJoint(aj,prb);
}
//
static void Init_ClusterCombine(SoftDemo* pdemo)
{
const btVector3 sz(2,4,2);
btSoftBody* psb0=Ctor_ClusterTorus(pdemo,btVector3(0,8,0),btVector3(SIMD_PI/2,0,SIMD_HALF_PI),sz);
btSoftBody* psb1=Ctor_ClusterTorus(pdemo,btVector3(0,8,10),btVector3(SIMD_PI/2,0,SIMD_HALF_PI),sz);
btSoftBody* psbs[]={psb0,psb1};
for(int j=0;j<2;++j)
{
psbs[j]->m_cfg.kDF=1;
psbs[j]->m_cfg.kDP=0;
psbs[j]->m_cfg.piterations=1;
psbs[j]->m_clusters[0]->m_matching = 0.05;
psbs[j]->m_clusters[0]->m_ndamping = 0.05;
}
btSoftBody::AJoint::Specs aj;
aj.axis = btVector3(0,0,1);
aj.icontrol = &motorcontrol;
psb0->appendAngularJoint(aj,psb1);
btSoftBody::LJoint::Specs lj;
lj.position = btVector3(0,8,5);
psb0->appendLinearJoint(lj,psb1);
}
//
static void Init_ClusterCar(SoftDemo* pdemo)
{
const btVector3 origin(100,80,0);
const btQuaternion orientation(-SIMD_PI/2,0,0);
const btScalar widthf=8;
const btScalar widthr=9;
const btScalar length=8;
const btScalar height=4;
const btVector3 wheels[]= {
btVector3(+widthf,-height,+length), // Front left
btVector3(-widthf,-height,+length), // Front right
btVector3(+widthr,-height,-length), // Rear left
btVector3(-widthr,-height,-length), // Rear right
};
btSoftBody* pa=Ctor_ClusterBunny(pdemo,btVector3(0,0,0),btVector3(0,0,0));
btSoftBody* pfl=Ctor_ClusterTorus(pdemo,wheels[0],btVector3(0,0,SIMD_HALF_PI),btVector3(2,4,2));
btSoftBody* pfr=Ctor_ClusterTorus(pdemo,wheels[1],btVector3(0,0,SIMD_HALF_PI),btVector3(2,4,2));
btSoftBody* prl=Ctor_ClusterTorus(pdemo,wheels[2],btVector3(0,0,SIMD_HALF_PI),btVector3(2,5,2));
btSoftBody* prr=Ctor_ClusterTorus(pdemo,wheels[3],btVector3(0,0,SIMD_HALF_PI),btVector3(2,5,2));
pfl->m_cfg.kDF =
pfr->m_cfg.kDF =
prl->m_cfg.kDF =
prr->m_cfg.kDF = 1;
btSoftBody::LJoint::Specs lspecs;
lspecs.cfm = 1;
lspecs.erp = 1;
lspecs.position = btVector3(0,0,0);
lspecs.position=wheels[0];pa->appendLinearJoint(lspecs,pfl);
lspecs.position=wheels[1];pa->appendLinearJoint(lspecs,pfr);
lspecs.position=wheels[2];pa->appendLinearJoint(lspecs,prl);
lspecs.position=wheels[3];pa->appendLinearJoint(lspecs,prr);
btSoftBody::AJoint::Specs aspecs;
aspecs.cfm = 1;
aspecs.erp = 1;
aspecs.axis = btVector3(1,0,0);
aspecs.icontrol = &steercontrol_f;
pa->appendAngularJoint(aspecs,pfl);
pa->appendAngularJoint(aspecs,pfr);
aspecs.icontrol = &motorcontrol;
pa->appendAngularJoint(aspecs,prl);
pa->appendAngularJoint(aspecs,prr);
pa->rotate(orientation);
pfl->rotate(orientation);
pfr->rotate(orientation);
prl->rotate(orientation);
prr->rotate(orientation);
pa->translate(origin);
pfl->translate(origin);
pfr->translate(origin);
prl->translate(origin);
prr->translate(origin);
pfl->m_cfg.piterations =
pfr->m_cfg.piterations =
prl->m_cfg.piterations =
prr->m_cfg.piterations = 1;
pfl->m_clusters[0]->m_matching =
pfr->m_clusters[0]->m_matching =
prl->m_clusters[0]->m_matching =
prr->m_clusters[0]->m_matching = 0.05;
pfl->m_clusters[0]->m_ndamping =
pfr->m_clusters[0]->m_ndamping =
prl->m_clusters[0]->m_ndamping =
prr->m_clusters[0]->m_ndamping = 0.05;
Ctor_LinearStair(pdemo,btVector3(0,-8,0),btVector3(3,2,40),0,20);
Ctor_RbUpStack(pdemo,50);
pdemo->m_autocam=true;
}
//
static void Init_ClusterRobot(SoftDemo* pdemo)
{
struct Functor
{
static btSoftBody* CreateBall(SoftDemo* pdemo,const btVector3& pos)
{
btSoftBody* psb=btSoftBodyHelpers::CreateEllipsoid(pdemo->m_softBodyWorldInfo,pos,btVector3(1,1,1)*3,512);
psb->m_materials[0]->m_kLST = 0.45;
psb->m_cfg.kVC = 20;
psb->setTotalMass(50,true);
psb->setPose(true,false);
psb->generateClusters(1);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
return(psb);
}
};
const btVector3 base=btVector3(0,25,8);
btSoftBody* psb0=Functor::CreateBall(pdemo,base+btVector3(-8,0,0));
btSoftBody* psb1=Functor::CreateBall(pdemo,base+btVector3(+8,0,0));
btSoftBody* psb2=Functor::CreateBall(pdemo,base+btVector3(0,0,+8*btSqrt(2)));
const btVector3 ctr=(psb0->clusterCom(0)+psb1->clusterCom(0)+psb2->clusterCom(0))/3;
btCylinderShape* pshp=new btCylinderShape(btVector3(8,1,8));
btRigidBody* prb=pdemo->localCreateRigidBody(50,btTransform(btQuaternion(0,0,0),ctr+btVector3(0,5,0)),pshp);
btSoftBody::LJoint::Specs ls;
ls.erp=0.5f;
ls.position=psb0->clusterCom(0);psb0->appendLinearJoint(ls,prb);
ls.position=psb1->clusterCom(0);psb1->appendLinearJoint(ls,prb);
ls.position=psb2->clusterCom(0);psb2->appendLinearJoint(ls,prb);
btBoxShape* pbox=new btBoxShape(btVector3(20,1,40));
btRigidBody* pgrn=pdemo->localCreateRigidBody(0,btTransform(btQuaternion(0,-SIMD_HALF_PI/2,0),btVector3(0,0,0)),pbox);
pdemo->m_autocam=true;
}
//
static void Init_ClusterStackSoft(SoftDemo* pdemo)
{
for(int i=0;i<10;++i)
{
btSoftBody* psb=Ctor_ClusterTorus(pdemo,btVector3(0,-9+8.25*i,0),btVector3(0,0,0));
psb->m_cfg.kDF=1;
}
}
//
static void Init_ClusterStackMixed(SoftDemo* pdemo)
{
for(int i=0;i<10;++i)
{
if((i+1)&1)
{
Ctor_BigPlate(pdemo,50,-9+4.25*i);
}
else
{
btSoftBody* psb=Ctor_ClusterTorus(pdemo,btVector3(0,-9+4.25*i,0),btVector3(0,0,0));
psb->m_cfg.kDF=1;
}
}
}
unsigned current_demo=18;
void SoftDemo::clientResetScene()
{
@@ -880,6 +1254,12 @@ void SoftDemo::clientResetScene()
{
delete body->getMotionState();
}
while(m_dynamicsWorld->getNumConstraints())
{
btTypedConstraint* pc=m_dynamicsWorld->getConstraint(0);
m_dynamicsWorld->removeConstraint(pc);
delete pc;
}
btSoftBody* softBody = btSoftBody::upcast(obj);
if (softBody)
{
@@ -913,10 +1293,19 @@ void SoftDemo::clientResetScene()
Init_Bunny,
Init_BunnyMatch,
Init_Cutting1,
Init_ClusterDeform,
Init_ClusterCollide1,
Init_ClusterCollide2,
Init_ClusterSocket,
Init_ClusterHinge,
Init_ClusterCombine,
Init_ClusterCar,
Init_ClusterRobot,
Init_ClusterStackSoft,
Init_ClusterStackMixed,
};
current_demo=current_demo%(sizeof(demofncs)/sizeof(demofncs[0]));
m_softBodyWorldInfo.air_density = (btScalar)1.2;
m_softBodyWorldInfo.water_density = 0;
m_softBodyWorldInfo.water_offset = 0;
@@ -953,7 +1342,7 @@ void SoftDemo::renderme()
}
ps/=nps;
if(m_autocam)
m_cameraTargetPosition+=(ps-m_cameraTargetPosition)*0.01;
m_cameraTargetPosition+=(ps-m_cameraTargetPosition)*0.05;
else
m_cameraTargetPosition=btVector3(0,0,0);
/* Anm */
@@ -1047,6 +1436,7 @@ void SoftDemo::renderme()
idraw->drawTriangle(o-x*s-y*s,o+x*s-y*s,o+x*s+y*s,c,a);
idraw->drawTriangle(o-x*s-y*s,o+x*s+y*s,o-x*s+y*s,c,a);
}
//
DemoApplication::renderme();
}
@@ -1055,10 +1445,15 @@ void SoftDemo::keyboardCallback(unsigned char key, int x, int y)
{
switch(key)
{
case 'n': motorcontrol.maxtorque=10;motorcontrol.goal+=1;break;
case 'm': motorcontrol.maxtorque=10;motorcontrol.goal-=1;break;
case '4': steercontrol_f.angle+=0.1;steercontrol_r.angle+=0.1;break;
case '6': steercontrol_f.angle-=0.1;steercontrol_r.angle-=0.1;break;
case ']': ++current_demo;clientResetScene();break;
case '[': --current_demo;clientResetScene();break;
case ',': m_raycast=!m_raycast;break;
case ';': m_autocam=!m_autocam;break;
case 'c': getSoftDynamicsWorld()->setDrawFlags(getSoftDynamicsWorld()->getDrawFlags()^fDrawFlags::Clusters);break;
case '`':
{
btSoftBodyArray& sbs=getSoftDynamicsWorld()->getSoftBodyArray();
@@ -1367,3 +1762,4 @@ void SoftDemo::exitPhysics()