more soft body preparations, moved some parts from Demo/SoftBody to src/BulletDynamics/SoftBody

moved Extras/ConvexHull/btConvexHull.* to src/LinearMath/btConvexHull.*
removed btCollisionObject::m_internalOwner, replaced it by m_internalType. This should not affect external API (it was clearly marked as internal)
This commit is contained in:
erwin.coumans
2008-04-10 20:00:41 +00:00
parent 03d846add0
commit 1139c06a4d
36 changed files with 3316 additions and 1543 deletions

View File

@@ -21,7 +21,7 @@ subject to the following restrictions:
#include "LinearMath/btQuickprof.h"
#include "LinearMath/btIDebugDraw.h"
#include "LinearMath/btGeometryUtil.h"
#include "btShapeHull.h"
#include "BulletCollision/CollisionShapes/btShapeHull.h"
//#define USE_PARALLEL_DISPATCHER 1
#ifdef USE_PARALLEL_DISPATCHER

View File

@@ -17,6 +17,8 @@ subject to the following restrictions:
#include "btBulletDynamicsCommon.h"
#include "BulletDynamics/SoftBody/btSoftRigidDynamicsWorld.h"
#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
#include "LinearMath/btQuickprof.h"
@@ -25,7 +27,7 @@ subject to the following restrictions:
#include "../GimpactTestDemo/BunnyMesh.h"
#include "../GimpactTestDemo/TorusMesh.h"
#include <stdio.h> //printf debugging
#include "../../Extras/ConvexHull/btConvexHull.h"
#include "LinearMath/btConvexHull.h"
#include "btSoftBodyRigidBodyCollisionConfiguration.h"
#include "BulletDynamics/SoftBody/btSoftBodyHelpers.h"
@@ -42,34 +44,6 @@ extern int glutScreenHeight;
const int maxProxies = 32766;
const int maxOverlap = 65535;
//
btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBody::btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
int nvertices)
{
HullDesc hdsc(QF_TRIANGLES,nvertices,vertices);
HullResult hres;
HullLibrary hlib;/*??*/
hdsc.mMaxVertices=nvertices;
hlib.CreateConvexHull(hdsc,hres);
btSoftBody* psb=new btSoftBody(worldInfo,(int)hres.mNumOutputVertices,
hres.mOutputVertices,0);
for(int i=0;i<(int)hres.mNumFaces;++i)
{
const int idx[]={ hres.mIndices[i*3+0],
hres.mIndices[i*3+1],
hres.mIndices[i*3+2]};
if(idx[0]<idx[1]) psb->AppendLink( idx[0],idx[1],
1,btSoftBody::eLType::Structural);
if(idx[1]<idx[2]) psb->AppendLink( idx[1],idx[2],
1,btSoftBody::eLType::Structural);
if(idx[2]<idx[0]) psb->AppendLink( idx[2],idx[0],
1,btSoftBody::eLType::Structural);
psb->AppendFace(idx[0],idx[1],idx[2]);
}
hlib.ReleaseResult(hres);
psb->RandomizeConstraints();
return(psb);
}
#ifdef _DEBUG
@@ -114,95 +88,6 @@ void SoftDemo::createStack( btCollisionShape* boxShape, float halfCubeSize, int
////////////////////////////////////
#ifdef DHSJHDSAKJDHSJKADHSAKJDHSA
//
bool SoftDemo::SoftBodyImpl::CheckContactPrecise(const btVector3& x,
btSoftBody::ISoftBody::sCti& cti)
{
btScalar maxdepth=0;
btGjkEpaSolver2::sResults res;
// btDynamicsWorld* pdw=pdemo->m_dynamicsWorld;
btCollisionObjectArray& coa=pdw->getCollisionObjectArray();
for(int i=0,ni=coa.size();i<ni;++i)
{
btRigidBody* prb=(btRigidBody*)(coa[i]);
btCollisionShape* shp=prb->getCollisionShape();
if(shp->isConvex())
{
btConvexShape* csh=static_cast<btConvexShape*>(shp);
const btTransform& wtr=prb->getWorldTransform();
const btScalar dst=btGjkEpaSolver2::SignedDistance(x,0.1,csh,wtr,res);
if(dst<maxdepth)
{
maxdepth = dst;
cti.m_body = prb;
cti.m_normal = res.normal;
cti.m_offset = -dot(cti.m_normal,res.witnesses[0]);
}
}
}
return(maxdepth<0);
}
//
bool SoftDemo::SoftBodyImpl::CheckContact( const btVector3& x,
btSoftBody::sCti& cti)
{
btScalar maxdepth=0;
btGjkEpaSolver2::sResults res;
btDynamicsWorld* pdw=pdemo->m_dynamicsWorld;
btCollisionObjectArray& coa=pdw->getCollisionObjectArray();
for(int i=0,ni=coa.size();i<ni;++i)
{
btVector3 nrm;
btRigidBody* prb=(btRigidBody*)(coa[i]);
btCollisionShape* shp=prb->getCollisionShape();
btConvexShape* csh=static_cast<btConvexShape*>(shp);
const btTransform& wtr=prb->getWorldTransform();
btScalar dst=pdemo->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);
}
//
void SoftDemo::SoftBodyImpl::EndCollide()
{}
//
void SoftDemo::SoftBodyImpl::EvaluateMedium( const btVector3& x,
btSoftBody::ISoftBody::sMedium& medium)
{
medium.m_velocity = btVector3(0,0,0);
medium.m_pressure = 0;
medium.m_density = air_density;
if(water_density>0)
{
const btScalar depth=-(dot(x,water_normal)+water_offset);
if(depth>0)
{
medium.m_density = water_density;
medium.m_pressure = depth *
water_density *
pdemo->m_dynamicsWorld->getGravity().length();
}
}
}
#endif
extern int gNumManifold;
extern int gOverlappingPairs;
extern int gTotalContactPoints;
@@ -253,19 +138,10 @@ void SoftDemo::clientMoveAndDisplay()
#endif
/* soft bodies simulation */
for(int ib=0;ib<m_softbodies.size();++ib)
{
btSoftBody* psb=m_softbodies[ib];
psb->AddVelocity(m_dynamicsWorld->getGravity()*dt);
psb->Step(dt);
}
m_softBodyWorldInfo.m_sparsesdf.GarbageCollect();
//optional but useful: debug drawing
m_dynamicsWorld->debugDrawWorld();
}
#ifdef USE_QUICKPROF
@@ -406,8 +282,8 @@ static btSoftBody* Ctor_SoftBox(SoftDemo* pdemo,const btVector3& p,const btVecto
p+h*btVector3(-1,+1,+1),
p+h*btVector3(+1,+1,+1)};
btSoftBody* psb=btSoftBodyHelpers::CreateFromConvexHull(pdemo->m_softBodyWorldInfo,c,8);
psb->GenerateBendingConstraints(2,1);
pdemo->m_softbodies.push_back(psb);
psb->generateBendingConstraints(2,1);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
return(psb);
}
@@ -424,8 +300,8 @@ static btSoftBody* Ctor_SoftBoulder(SoftDemo* pdemo,const btVector3& p,const btV
pts.push_back(Vector3Rand()*s+p);
}
btSoftBody* psb=btSoftBodyHelpers::CreateFromConvexHull(pdemo->m_softBodyWorldInfo,&pts[0],pts.size());
psb->GenerateBendingConstraints(2,1);
pdemo->m_softbodies.push_back(psb);
psb->generateBendingConstraints(2,1);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
return(psb);
}
@@ -447,8 +323,8 @@ static void Init_Ropes(SoftDemo* pdemo)
1+2);
psb->m_cfg.iterations = 4;
psb->m_cfg.kLST = 0.1+(i/(btScalar)(n-1))*0.9;
psb->SetTotalMass(20);
pdemo->m_softbodies.push_back(psb);
psb->setTotalMass(20);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
}
@@ -465,8 +341,9 @@ static void Init_RopeAttach(SoftDemo* pdemo)
{
btSoftBody* psb=btSoftBodyHelpers::CreateRope(pdemo->m_softBodyWorldInfo,p,p+btVector3(10,0,0),8,1);
psb->m_cfg.kDF = 0;
psb->SetTotalMass(50);
pdemo->m_softbodies.push_back(psb);
psb->m_cfg.kDP = 0.001;
psb->setTotalMass(50);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
return(psb);
}
};
@@ -476,8 +353,8 @@ static void Init_RopeAttach(SoftDemo* pdemo)
btRigidBody* body=pdemo->localCreateRigidBody(50,startTransform,new btBoxShape(btVector3(2,6,2)));
btSoftBody* psb0=Functors::CtorRope(pdemo,btVector3(0,8,-1));
btSoftBody* psb1=Functors::CtorRope(pdemo,btVector3(0,8,+1));
psb0->AppendAnchor(psb0->getNodes().size()-1,body);
psb1->AppendAnchor(psb1->getNodes().size()-1,body);
psb0->appendAnchor(psb0->getNodes().size()-1,body);
psb1->appendAnchor(psb1->getNodes().size()-1,body);
}
//
@@ -493,14 +370,14 @@ static void Init_ClothAttach(SoftDemo* pdemo)
btVector3(+s,h,-s),
btVector3(-s,h,+s),
btVector3(+s,h,+s),r,r,4+8,true);
pdemo->m_softbodies.push_back(psb);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
btTransform startTransform;
startTransform.setIdentity();
startTransform.setOrigin(btVector3(0,h,-(s+3.5)));
btRigidBody* body=pdemo->localCreateRigidBody(20,startTransform,new btBoxShape(btVector3(s,1,3)));
psb->AppendAnchor(0,body);
psb->AppendAnchor(r-1,body);
psb->appendAnchor(0,body);
psb->appendAnchor(r-1,body);
}
//
@@ -513,7 +390,7 @@ static void Init_Impact(SoftDemo* pdemo)
btVector3(0,-1,0),
0,
1);
pdemo->m_softbodies.push_back(psb);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
btTransform startTransform;
startTransform.setIdentity();
@@ -521,6 +398,136 @@ static void Init_Impact(SoftDemo* pdemo)
btRigidBody* body=pdemo->localCreateRigidBody(10,startTransform,new btBoxShape(btVector3(2,2,2)));
}
//
// Collide
//
static void Init_Collide(SoftDemo* pdemo)
{
//TRACEDEMO
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,1);
psb->m_cfg.iterations=2;
psb->m_cfg.collisions|=btSoftBody::fCollision::VF_SS;
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);
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));
}
#if 0
const btScalar s=2;
const btScalar s2=s*1.01;
{
const btScalar h=0;
const btVector3 p[]={ btVector3(-s,h,-s),btVector3(+s,h,-s),
btVector3(+s,h,+s),btVector3(-s,h,+s)};
btSoftBody* psb=new btSoftBody(&pdemo->m_softBodyWorldInfo,4,p,0);
psb->appendLink(0,1,1,btSoftBody::eLType::Structural);
psb->appendLink(1,2,1,btSoftBody::eLType::Structural);
psb->appendLink(2,3,1,btSoftBody::eLType::Structural);
psb->appendLink(3,0,1,btSoftBody::eLType::Structural);
psb->appendLink(0,2,1,btSoftBody::eLType::Structural);
psb->appendFace(0,1,2);
psb->appendFace(2,3,0);
/*psb->setMass(0,0);
psb->setMass(1,0);
psb->setMass(2,0);
psb->setMass(3,0);*/
psb->m_cfg.collisions|=btSoftBody::fCollision::VF_SS;
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
{
btVector3 p[]={btVector3(0.5,5,-0.5)};
btSoftBody* psb=new btSoftBody(&pdemo->m_softBodyWorldInfo,1,p,0);
//psb->setMass(0,0);
psb->m_cfg.collisions|=btSoftBody::fCollision::VF_SS;
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
#endif
}
//
// Collide2
//
static void Init_Collide2(SoftDemo* pdemo)
{
//TRACEDEMO
struct Functor
{
static btSoftBody* Create(SoftDemo* pdemo,const btVector3& x,const btVector3& a)
{
btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVerticesBunny,
&gIndicesBunny[0][0],
BUNNY_NUM_TRIANGLES);
psb->generateBendingConstraints(2,0.5);
psb->m_cfg.iterations = 2;
psb->m_cfg.kDF = 0.5;
psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS;
psb->randomizeConstraints();
btMatrix3x3 m;
m.setEulerZYX(a.x(),a.y(),a.z());
psb->transform(btTransform(m,x));
psb->scale(btVector3(6,6,6));
psb->setTotalMass(100,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
return(psb);
}
};
for(int i=0;i<3;++i)
{
Functor::Create(pdemo,btVector3(0,-1+4*i,0),btVector3(0,SIMD_PI/2*(i&1),0));
}
}
//
// Collide3
//
static void Init_Collide3(SoftDemo* pdemo)
{
//TRACEDEMO
{
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),
15,15,1+2+4+8,true);
psb->m_cfg.kLST = 0.4;
psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS;
psb->setTotalMass(150);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
{
const btScalar s=4;
const btVector3 o=btVector3(4,10,0);
btSoftBody* psb=btSoftBodyHelpers::CreatePatch( pdemo->m_softBodyWorldInfo,
btVector3(-s,0,-s)+o,
btVector3(+s,0,-s)+o,
btVector3(-s,0,+s)+o,
btVector3(+s,0,+s)+o,
15,15,0,true);
psb->generateBendingConstraints(2,0.5);
psb->m_cfg.kLST = 0.4;
psb->m_cfg.collisions |= btSoftBody::fCollision::VF_SS;
psb->setTotalMass(150);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
}
//
// Aerodynamic forces, 50x1g flyers
//
@@ -539,7 +546,7 @@ static void Init_Aero(SoftDemo* pdemo)
btVector3(+s,h,+s),
segments,segments,
0,true);
psb->GenerateBendingConstraints(2,1);
psb->generateBendingConstraints(2,1);
psb->m_cfg.kLF = 0.004;
psb->m_cfg.kDG = 0.0003;
psb->m_cfg.aeromodel = btSoftBody::eAeroModel::V_TwoSided;
@@ -551,10 +558,10 @@ static void Init_Aero(SoftDemo* pdemo)
trs.setIdentity();
trs.setOrigin(rp);
trs.setRotation(rot);
psb->Transform(trs);
psb->SetTotalMass(0.1);
psb->AddForce(btVector3(0,2,0),0);
pdemo->m_softbodies.push_back(psb);
psb->transform(trs);
psb->setTotalMass(0.1);
psb->addForce(btVector3(0,2,0),0);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
pdemo->m_autocam=true;
@@ -573,7 +580,7 @@ static void Init_Friction(SoftDemo* pdemo)
const btVector3 p(-ni*ts/2+i*ts,-10+bs,40);
btSoftBody* psb=Ctor_SoftBox(pdemo,p,btVector3(bs,bs,bs));
psb->m_cfg.kDF = 0.1 * ((i+1)/(btScalar)ni);
psb->AddVelocity(btVector3(0,0,-10));
psb->addVelocity(btVector3(0,0,-10));
}
}
@@ -588,9 +595,10 @@ static void Init_Pressure(SoftDemo* pdemo)
512);
psb->m_cfg.kLST = 0.1;
psb->m_cfg.kDF = 1;
psb->m_cfg.kDP = 0.008; // fun factor...
psb->m_cfg.kPR = 2500;
psb->SetTotalMass(30,true);
pdemo->m_softbodies.push_back(psb);
psb->setTotalMass(30,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
Ctor_BigPlate(pdemo);
Ctor_LinearStair(pdemo,btVector3(0,0,0),btVector3(2,1,5),0,10);
@@ -608,9 +616,9 @@ static void Init_Volume(SoftDemo* pdemo)
512);
psb->m_cfg.kLST = 0.45;
psb->m_cfg.kVC = 20;
psb->SetTotalMass(50,true);
psb->SetPose(true,false);
pdemo->m_softbodies.push_back(psb);
psb->setTotalMass(50,true);
psb->setPose(true,false);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
Ctor_BigPlate(pdemo);
Ctor_LinearStair(pdemo,btVector3(0,0,0),btVector3(2,1,5),0,10);
@@ -644,11 +652,11 @@ static void Init_Sticks(SoftDemo* pdemo)
psb->m_cfg.kCHR = 0.1;
for(int i=0;i<3;++i)
{
psb->GenerateBendingConstraints(2+i,1);
psb->generateBendingConstraints(2+i,1);
}
psb->SetMass(1,0);
psb->SetTotalMass(0.01);
pdemo->m_softbodies.push_back(psb);
psb->setMass(1,0);
psb->setTotalMass(0.01);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
}
@@ -670,10 +678,10 @@ static void Init_Cloth(SoftDemo* pdemo)
// 31,31,
1+2+4+8,true);
psb->GenerateBendingConstraints(2,1);
psb->generateBendingConstraints(2,1);
psb->m_cfg.kLST = 0.4;
psb->SetTotalMass(150);
pdemo->m_softbodies.push_back(psb);
psb->setTotalMass(150);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
Ctor_RbUpStack(pdemo,10);
}
@@ -687,13 +695,13 @@ static void Init_Bunny(SoftDemo* pdemo)
btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo,gVerticesBunny,
&gIndicesBunny[0][0],
BUNNY_NUM_TRIANGLES);
psb->GenerateBendingConstraints(2,0.5);
psb->generateBendingConstraints(2,0.5);
psb->m_cfg.iterations = 2;
psb->m_cfg.kDF = 0.5;
psb->RandomizeConstraints();
psb->Scale(btVector3(6,6,6));
psb->SetTotalMass(100,true);
pdemo->m_softbodies.push_back(psb);
psb->randomizeConstraints();
psb->scale(btVector3(6,6,6));
psb->setTotalMass(100,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
@@ -706,15 +714,14 @@ static void Init_BunnyMatch(SoftDemo* pdemo)
btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVerticesBunny,
&gIndicesBunny[0][0],
BUNNY_NUM_TRIANGLES);
psb->GenerateBendingConstraints(2,0.5);
psb->m_cfg.kDF = 0.5;
psb->m_cfg.kLST = 0.1;
psb->m_cfg.kMT = 0.01;
psb->RandomizeConstraints();
psb->Scale(btVector3(6,6,6));
psb->SetTotalMass(100,true);
psb->SetPose(true,true);
pdemo->m_softbodies.push_back(psb);
psb->m_cfg.kMT = 0.05;
psb->randomizeConstraints();
psb->scale(btVector3(6,6,6));
psb->setTotalMass(100,true);
psb->setPose(true,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
@@ -727,15 +734,15 @@ static void Init_Torus(SoftDemo* pdemo)
btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh( pdemo->m_softBodyWorldInfo, gVertices,
&gIndices[0][0],
NUM_TRIANGLES);
psb->GenerateBendingConstraints(2,1);
psb->generateBendingConstraints(2,1);
psb->m_cfg.iterations=2;
psb->RandomizeConstraints();
psb->randomizeConstraints();
btMatrix3x3 m;
m.setEulerZYX(SIMD_PI/2,0,0);
psb->Transform(btTransform(m,btVector3(0,4,0)));
psb->Scale(btVector3(2,2,2));
psb->SetTotalMass(50,true);
pdemo->m_softbodies.push_back(psb);
psb->transform(btTransform(m,btVector3(0,4,0)));
psb->scale(btVector3(2,2,2));
psb->setTotalMass(50,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
@@ -748,22 +755,21 @@ static void Init_TorusMatch(SoftDemo* pdemo)
btSoftBody* psb=btSoftBodyHelpers::CreateFromTriMesh(pdemo->m_softBodyWorldInfo, gVertices,
&gIndices[0][0],
NUM_TRIANGLES);
psb->GenerateBendingConstraints(2,1);
psb->m_cfg.kLST=0.1;
psb->m_cfg.kMT=0.05;
psb->RandomizeConstraints();
psb->randomizeConstraints();
btMatrix3x3 m;
m.setEulerZYX(SIMD_PI/2,0,0);
psb->Transform(btTransform(m,btVector3(0,4,0)));
psb->Scale(btVector3(2,2,2));
psb->SetTotalMass(50,true);
psb->SetPose(true,true);
pdemo->m_softbodies.push_back(psb);
psb->transform(btTransform(m,btVector3(0,4,0)));
psb->scale(btVector3(2,2,2));
psb->setTotalMass(50,true);
psb->setPose(true,true);
pdemo->getSoftDynamicsWorld()->addSoftBody(psb);
}
static unsigned current_demo=1;
static unsigned current_demo=14;
void SoftDemo::clientResetScene()
{
@@ -777,15 +783,17 @@ void SoftDemo::clientResetScene()
{
delete body->getMotionState();
}
m_dynamicsWorld->removeCollisionObject(obj);
btSoftBody* softBody = btSoftBody::upcast(obj);
if (softBody)
{
getSoftDynamicsWorld()->removeSoftBody(softBody);
} else
{
m_dynamicsWorld->removeCollisionObject(obj);
}
delete obj;
}
for(int i=0;i<m_softbodies.size();++i)
{
btSoftBody* softbody = m_softbodies[i];
delete softbody;
}
m_softbodies.clear();
m_softBodyWorldInfo.m_sparsesdf.Reset();
/* Init */
void (*demofncs[])(SoftDemo*)=
@@ -797,6 +805,9 @@ void SoftDemo::clientResetScene()
Init_RopeAttach,
Init_ClothAttach,
Init_Sticks,
Init_Collide,
Init_Collide2,
Init_Collide3,
Init_Impact,
Init_Aero,
Init_Friction,
@@ -816,6 +827,7 @@ void SoftDemo::clientResetScene()
m_autocam = false;
m_showtrees = 0;
demofncs[current_demo](this);
}
@@ -823,12 +835,17 @@ void SoftDemo::renderme()
{
DemoApplication::renderme();
btIDebugDraw* idraw=m_dynamicsWorld->getDebugDrawer();
m_dynamicsWorld->debugDrawWorld();
/* Bodies */
btVector3 ps(0,0,0);
int nps=0;
for(int ib=0;ib<m_softbodies.size();++ib)
btSoftBodyArray& sbs=getSoftDynamicsWorld()->getSoftBodyArray();
for(int ib=0;ib<sbs.size();++ib)
{
btSoftBody* psb=m_softbodies[ib];
btSoftBody* psb=sbs[ib];
nps+=psb->getNodes().size();
for(int i=0;i<psb->getNodes().size();++i)
{
@@ -836,6 +853,8 @@ void SoftDemo::renderme()
}
btSoftBodyHelpers::DrawFrame(psb,idraw);
btSoftBodyHelpers::Draw(psb,idraw,fDrawFlags::Std);
if(m_showtrees&1)
btSoftBodyHelpers::DrawNodeTree(psb,idraw);
}
ps/=nps;
if(m_autocam)
@@ -867,6 +886,7 @@ void SoftDemo::keyboardCallback(unsigned char key, int x, int y)
case ']': ++current_demo;clientResetScene();break;
case '[': --current_demo;clientResetScene();break;
case ';': m_autocam=!m_autocam;break;
case ',': m_showtrees+=1;break;
default: DemoApplication::keyboardCallback(key,x,y);
}
}
@@ -910,7 +930,7 @@ void SoftDemo::initPhysics()
m_solver = solver;
btDiscreteDynamicsWorld* world = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
btDiscreteDynamicsWorld* world = new btSoftRigidDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
m_dynamicsWorld = world;
@@ -922,8 +942,6 @@ void SoftDemo::initPhysics()
int i;
btTransform tr;
tr.setIdentity();
tr.setOrigin(btVector3(0,-12,0));
@@ -991,3 +1009,4 @@ void SoftDemo::exitPhysics()
}

View File

@@ -36,6 +36,7 @@ class btSoftSoftCollisionAlgorithm;
///collisions between a btSoftBody and a btRigidBody
class btSoftRididCollisionAlgorithm;
class btSoftRigidDynamicsWorld;
///CcdPhysicsDemo shows basic stacking using Bullet physics, and allows toggle of Ccd (using key '1')
@@ -49,10 +50,9 @@ public:
btSoftBody::btSoftBodyWorldInfo m_softBodyWorldInfo;
btAlignedObjectArray<btSoftBody*> m_softbodies;
bool m_autocam;
int m_showtrees;
//keep the collision shapes, for deletion/cleanup
@@ -95,6 +95,20 @@ public:
return demo;
}
const btSoftRigidDynamicsWorld* getSoftDynamicsWorld() const
{
///just make it a btSoftRigidDynamicsWorld please
///or we will add type checking
return (btSoftRigidDynamicsWorld*) m_dynamicsWorld;
}
btSoftRigidDynamicsWorld* getSoftDynamicsWorld()
{
///just make it a btSoftRigidDynamicsWorld please
///or we will add type checking
return (btSoftRigidDynamicsWorld*) m_dynamicsWorld;
}
//
void clientResetScene();
void renderme();
@@ -104,3 +118,4 @@ public:
#endif //CCD_PHYSICS_DEMO_H

View File

@@ -31,11 +31,11 @@ btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifol
m_isSwapped(isSwapped)
{
m_softBody = m_isSwapped? (btSoftBody*)col1 : (btSoftBody*)col0;
m_rigidCollisionObject = m_isSwapped? col0 : col1;
//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);
//m_softBody->m_overlappingRigidBodies.push_back(m_rigidCollisionObject);
///store the contacts straight into the btSoftBody for now?
@@ -54,7 +54,7 @@ m_isSwapped(isSwapped)
btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm()
{
m_softBody->m_overlappingRigidBodies.remove(m_rigidCollisionObject);
//m_softBody->m_overlappingRigidBodies.remove(m_rigidCollisionObject);
/*if (m_ownManifold)
{
@@ -76,7 +76,8 @@ void btSoftRigidCollisionAlgorithm::processCollision (btCollisionObject* body0,b
btSoftBody* softBody = m_isSwapped? (btSoftBody*)body1 : (btSoftBody*)body0;
btCollisionObject* rigidCollisionObject = m_isSwapped? body0 : body1;
///do your stuff here
softBody->defaultCollisionHandler(rigidCollisionObject);
}
@@ -92,3 +93,4 @@ btScalar btSoftRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject*
return btScalar(1.);
}

View File

@@ -23,7 +23,7 @@ class btPersistentManifold;
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
#include "LinearMath/btVector3.h"
struct btSoftBody;
class btSoftBody;
/// btSoftRigidCollisionAlgorithm provides collision detection between btSoftBody and btRigidBody
class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm
@@ -67,3 +67,4 @@ public:
#endif //SOFT_RIGID_COLLISION_ALGORITHM_H

View File

@@ -26,11 +26,11 @@ btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold*
//m_ownManifold(false),
//m_manifoldPtr(mf)
{
m_softBody0 = (btSoftBody*) obj0;
/*m_softBody0 = (btSoftBody*) obj0;
m_softBody1 = (btSoftBody*) obj1;
m_softBody0->m_overlappingSoftBodies.push_back(m_softBody1);
m_softBody1->m_overlappingSoftBodies.push_back(m_softBody0);
m_softBody1->m_overlappingSoftBodies.push_back(m_softBody0);*/
/*if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
{
@@ -43,8 +43,8 @@ btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold*
btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm()
{
m_softBody0->m_overlappingSoftBodies.remove(m_softBody1);
m_softBody1->m_overlappingSoftBodies.remove(m_softBody0);
//m_softBody0->m_overlappingSoftBodies.remove(m_softBody1);
//m_softBody1->m_overlappingSoftBodies.remove(m_softBody0);
//this gets called when the overlap stops.
@@ -63,9 +63,10 @@ btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm()
void btSoftSoftCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
{
btCollisionObject* col0 = body0;
btCollisionObject* col1 = body1;
btSoftBody* soft0 = (btSoftBody*)body0;
btSoftBody* soft1 = (btSoftBody*)body1;
soft0->defaultCollisionHandler(soft1);
/*
btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape();
btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape();

View File

@@ -22,7 +22,7 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
class btPersistentManifold;
struct btSoftBody;
class btSoftBody;
///collision detection between two btSoftBody shapes
class btSoftSoftCollisionAlgorithm : public btCollisionAlgorithm
@@ -60,3 +60,4 @@ public:
#endif //SOFT_SOFT_COLLISION_ALGORITHM_H

View File

@@ -26,7 +26,7 @@ subject to the following restrictions:
#include "dom/domCOLLADA.h"
#include "dae/domAny.h"
#include "dom/domConstants.h"
#include "btShapeHull.h"
#include "BulletCollision/CollisionShapes/btShapeHull.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"

View File

@@ -1 +1 @@
SUBDIRS( glui ConvexDecomposition ConvexHull BulletMultiThreaded BulletColladaConverter LibXML COLLADA_DOM GIMPACTUtils GIMPACT )
SUBDIRS( glui ConvexDecomposition BulletMultiThreaded BulletColladaConverter LibXML COLLADA_DOM GIMPACTUtils GIMPACT )

View File

@@ -1,10 +0,0 @@
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Extras/ConvexHull
)
ADD_LIBRARY(LibConvexHull
btConvexHull.h
btConvexHull.cpp
btShapeHull.cpp
btShapeHull.h
)

View File

@@ -1,17 +0,0 @@
SubDir TOP Extras ConvexHull ;
Library convexhull : [ Wildcard *.h *.cpp ] : noinstall ;
#internal header path to compile convexhull
CFlags convexhull : [ FIncludes $(TOP)/Extras/ConvexHull ] ;
#expose header include path for apps that depend on ConvexHull
convexhull.CFLAGS = [ FIncludes $(TOP)/Extras/ConvexHull ] ;
#same for msvcgen
MsvcGenConfig convexhull.INCDIRS : $(TOP)/Extras/ConvexHull ;
#for the include paths
LibDepends convexhull : bulletcollision ;
#InstallHeader [ Wildcard *.h ] : ConvexHull ;

View File

@@ -1,38 +0,0 @@
#### Source code Dirs
VPATH = ../
ROOT = ../../..
HOST = /usr/include
#### Library
LIBRARY_ppu = bulletconvexhull.a
#### Compiler flags
CPPFLAGS = -DUSE_LIBSPE2 \
-I$(ROOT)/Extras/ \
-I$(ROOT)/src/ \
-I$(SDKINC) \
-I$(HOST)
#### Optimization level flags
#CC_OPT_LEVEL = $(CC_OPT_LEVEL_DEBUG)
CC_OPT_LEVEL = -O3
##### Objects to be archived in lib
OBJS = \
btConvexHull.o \
btShapeHull.o
#### Install directories
INSTALL_DIR = $(ROOT)/lib/ibmsdk/
INSTALL_FILES = $(LIBRARY)
IBM_CELLSDK_VERSION := $(shell if [ -d /opt/cell ]; then echo "3.0"; fi)
ifeq ("$(IBM_CELLSDK_VERSION)","3.0")
CELL_TOP ?= /opt/cell/sdk
include $(CELL_TOP)/buildutils/make.footer
else
CELL_TOP ?= /opt/ibm/cell-sdk/prototype
include $(CELL_TOP)/make.footer
endif

View File

@@ -3,7 +3,6 @@ SubDir TOP Extras ;
SubInclude TOP Extras ConvexDecomposition ;
SubInclude TOP Extras COLLADA_DOM ;
SubInclude TOP Extras glui ;
SubInclude TOP Extras ConvexHull ;
SubInclude TOP Extras LibXML ;
SubInclude TOP Extras BulletColladaConverter ;
SubInclude TOP Extras BulletMultiThreaded ;

View File

@@ -27,7 +27,7 @@ btCollisionObject::btCollisionObject()
m_friction(btScalar(0.5)),
m_restitution(btScalar(0.)),
m_userObjectPointer(0),
m_internalOwner(0),
m_internalType(CO_COLLISION_OBJECT),
m_hitFraction(btScalar(1.)),
m_ccdSweptSphereRadius(btScalar(0.)),
m_ccdSquareMotionThreshold(btScalar(0.)),

View File

@@ -66,8 +66,9 @@ protected:
///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer
void* m_userObjectPointer;
///m_internalOwner is reserved to point to Bullet's btRigidBody. Don't use this, use m_userObjectPointer instead.
void* m_internalOwner;
///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody etc.
///do not assign your own m_internalType unless you write a new dynamics object class.
int m_internalType;
///time of impact calculation
btScalar m_hitFraction;
@@ -100,6 +101,12 @@ public:
CF_CUSTOM_MATERIAL_CALLBACK = 8//this allows per-triangle material (friction/restitution)
};
enum CollisionObjectTypes
{
CO_COLLISION_OBJECT =1,
CO_RIGID_BODY,
CO_SOFT_BODY
};
SIMD_FORCE_INLINE bool mergesSimulationIslands() const
{
@@ -189,14 +196,9 @@ public:
}
///reserved for Bullet internal usage
void* getInternalOwner()
int getInternalType() const
{
return m_internalOwner;
}
const void* getInternalOwner() const
{
return m_internalOwner;
return m_internalType;
}
btTransform& getWorldTransform()

View File

@@ -40,6 +40,8 @@ btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionS
void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
{
m_internalType=CO_RIGID_BODY;
m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
m_angularFactor = btScalar(1.);
@@ -78,9 +80,6 @@ void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo&
m_collisionShape = constructionInfo.m_collisionShape;
m_debugBodyId = uniqueId++;
//m_internalOwner is to allow upcasting from collision object to rigid body
m_internalOwner = this;
setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia);
setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping);
updateInertiaTensor();

View File

@@ -160,11 +160,15 @@ public:
///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast
static const btRigidBody* upcast(const btCollisionObject* colObj)
{
return (const btRigidBody*)colObj->getInternalOwner();
if (colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY)
return (const btRigidBody*)colObj;
return 0;
}
static btRigidBody* upcast(btCollisionObject* colObj)
{
return (btRigidBody*)colObj->getInternalOwner();
if (colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY)
return (btRigidBody*)colObj;
return 0;
}
/// continuous collision detection needs prediction

View File

@@ -0,0 +1,536 @@
#include "btDbvt.h"
#include <stdio.h>
namespace btdbvt_internals
{
//
typedef btAlignedObjectArray<btDbvt::Node*> tNodeArray;
//
static inline int indexof(const btDbvt::Node* node)
{
return(node->parent->childs[1]==node);
}
//
static inline btDbvt::Aabb merge( const btDbvt::Aabb& a,
const btDbvt::Aabb& b)
{
btDbvt::Aabb res;
Merge(a,b,res);
return(res);
}
// volume+edge lengths
static inline btScalar size(const btDbvt::Aabb& a)
{
const btVector3 edges=a.Lengths();
return( edges.x()*edges.y()*edges.z()+
edges.x()+edges.y()+edges.z());
}
//
static inline void deletenode( btDbvt* pdbvt,
btDbvt::Node* node)
{
delete pdbvt->m_free;
pdbvt->m_free=node;
}
//
static inline void recursedeletenode( btDbvt* pdbvt,
btDbvt::Node* node)
{
if(!node->isleaf())
{
recursedeletenode(pdbvt,node->childs[0]);
recursedeletenode(pdbvt,node->childs[1]);
}
if(node==pdbvt->m_root) pdbvt->m_root=0;
deletenode(pdbvt,node);
}
//
static inline btDbvt::Node* createnode( btDbvt* pdbvt,
btDbvt::Node* parent,
const btDbvt::Aabb& box,
void* data)
{
btDbvt::Node* node;
if(pdbvt->m_free)
{ node=pdbvt->m_free;pdbvt->m_free=0; }
else
{ node=new btDbvt::Node(); }
node->parent = parent;
node->box = box;
node->data = data;
node->childs[1] = 0;
return(node);
}
//
static inline void insertleaf( btDbvt* pdbvt,
btDbvt::Node* root,
btDbvt::Node* leaf)
{
if(!pdbvt->m_root)
{
pdbvt->m_root = leaf;
leaf->parent = 0;
}
else
{
if(!root->isleaf())
{
do {
if( Proximity(root->childs[0]->box,leaf->box)<
Proximity(root->childs[1]->box,leaf->box))
root=root->childs[0];
else
root=root->childs[1];
} while(!root->isleaf());
}
btDbvt::Node* prev=root->parent;
btDbvt::Node* node=createnode(pdbvt,prev,merge(leaf->box,root->box),0);
if(prev)
{
prev->childs[indexof(root)] = node;
node->childs[0] = root;root->parent=node;
node->childs[1] = leaf;leaf->parent=node;
do {
if(prev->box.Contain(node->box))
break;
else
Merge(prev->childs[0]->box,prev->childs[1]->box,prev->box);
node=prev;
} while(0!=(prev=node->parent));
}
else
{
node->childs[0] = root;root->parent=node;
node->childs[1] = leaf;leaf->parent=node;
pdbvt->m_root = node;
}
}
}
//
static inline btDbvt::Node* removeleaf( btDbvt* pdbvt,
btDbvt::Node* leaf)
{
if(leaf==pdbvt->m_root)
{
pdbvt->m_root=0;
return(0);
}
else
{
btDbvt::Node* parent=leaf->parent;
btDbvt::Node* prev=parent->parent;
btDbvt::Node* sibling=parent->childs[1-indexof(leaf)];
if(prev)
{
prev->childs[indexof(parent)]=sibling;
sibling->parent=prev;
deletenode(pdbvt,parent);
while(prev)
{
const btDbvt::Aabb pb=prev->box;
Merge(prev->childs[0]->box,prev->childs[1]->box,prev->box);
if(NotEqual(pb,prev->box))
{
sibling = prev;
prev = prev->parent;
} else break;
}
return(prev?prev:pdbvt->m_root);
}
else
{
pdbvt->m_root=sibling;
sibling->parent=0;
deletenode(pdbvt,parent);
return(pdbvt->m_root);
}
}
}
//
static void fetchleafs( btDbvt* pdbvt,
btDbvt::Node* root,
tNodeArray& leafs,
int depth=-1)
{
if(root->isinternal()&&depth)
{
fetchleafs(pdbvt,root->childs[0],leafs,depth-1);
fetchleafs(pdbvt,root->childs[1],leafs,depth-1);
deletenode(pdbvt,root);
}
else
{
leafs.push_back(root);
}
}
//
static int leafcount(btDbvt::Node* root)
{
if(root->isinternal())
{
return( leafcount(root->childs[0])+
leafcount(root->childs[1]));
}
return(1);
}
//
static void split( const tNodeArray& leafs,
tNodeArray& left,
tNodeArray& right,
const btVector3& org,
const btVector3& axis)
{
left.resize(0);
right.resize(0);
for(int i=0,ni=leafs.size();i<ni;++i)
{
if(dot(axis,leafs[i]->box.Center()-org)<0)
left.push_back(leafs[i]);
else
right.push_back(leafs[i]);
}
}
//
static btDbvt::Aabb bounds( const tNodeArray& leafs)
{
btDbvt::Aabb box=leafs[0]->box;
for(int i=1,ni=leafs.size();i<ni;++i)
{
box=merge(box,leafs[i]->box);
}
return(box);
}
//
static void bottomup( btDbvt* pdbvt,
tNodeArray& leafs)
{
while(leafs.size()>1)
{
btScalar minsize=SIMD_INFINITY;
int minidx[2]={-1,-1};
for(int i=0;i<leafs.size();++i)
{
for(int j=i+1;j<leafs.size();++j)
{
const btScalar sz=size(merge(leafs[i]->box,leafs[j]->box));
if(sz<minsize)
{
minsize = sz;
minidx[0] = i;
minidx[1] = j;
}
}
}
btDbvt::Node* n[] = {leafs[minidx[0]],leafs[minidx[1]]};
btDbvt::Node* p = createnode(pdbvt,0,merge(n[0]->box,n[1]->box),0);
p->childs[0] = n[0];
p->childs[1] = n[1];
n[0]->parent = p;
n[1]->parent = p;
leafs[minidx[0]] = p;
leafs.swap(minidx[1],leafs.size()-1);
leafs.pop_back();
}
}
//
static btDbvt::Node* topdown(btDbvt* pdbvt,
tNodeArray& leafs,
int bu_treshold)
{
static const btVector3 axis[]={btVector3(1,0,0),
btVector3(0,1,0),
btVector3(0,0,1)};
if(leafs.size()>1)
{
if(leafs.size()>bu_treshold)
{
const btDbvt::Aabb box=bounds(leafs);
const btVector3 org=box.Center();
tNodeArray sets[2];
int bestaxis=-1;
int bestmidp=leafs.size();
sets[0].reserve(leafs.size());
sets[1].reserve(leafs.size());
for(int i=0;i<3;++i)
{
split(leafs,sets[0],sets[1],org,axis[i]);
if((sets[0].size()>0)&&(sets[1].size()>0))
{
const int midp=abs(sets[0].size()-sets[1].size());
if(midp<bestmidp)
{
bestaxis=i;
bestmidp=midp;
}
}
}
if(bestaxis>=0)
{
split(leafs,sets[0],sets[1],org,axis[bestaxis]);
}
else
{
sets[0].resize(0);
sets[1].resize(0);
for(int i=0,ni=leafs.size();i<ni;++i)
{
sets[i&1].push_back(leafs[i]);
}
}
btDbvt::Node* node=createnode(pdbvt,0,box,0);
node->childs[0]=topdown(pdbvt,sets[0],bu_treshold);
node->childs[1]=topdown(pdbvt,sets[1],bu_treshold);
node->childs[0]->parent=node;
node->childs[1]->parent=node;
return(node);
}
else
{
bottomup(pdbvt,leafs);
return(leafs[0]);
}
}
return(leafs[0]);
}
//
static inline btDbvt::Node* refit( btDbvt* pdbvt,
btDbvt::Node* node)
{
btDbvt::Node* parent=node->parent;
if(parent)
{
const int idx=indexof(node);
tNodeArray leafs;
leafs.reserve(64);
fetchleafs(pdbvt,node,leafs,3);
if(leafs.size()>=2)
{
bottomup(pdbvt,leafs);
node=leafs[0];
node->parent=parent;
parent->childs[idx]=node;
}
}
return(node);
}
}
using namespace btdbvt_internals;
//
// Api
//
//
btDbvt::btDbvt()
{
m_root = 0;
m_free = 0;
m_lkhd = 2;
}
//
btDbvt::~btDbvt()
{
clear();
}
//
void btDbvt::clear()
{
if(m_root) recursedeletenode(this,m_root);
delete m_free;
m_free=0;
}
//
int btDbvt::leafCount() const
{
if(m_root) return(leafcount(m_root));
else
return(0);
}
//
void btDbvt::optimizeBottomUp()
{
if(m_root)
{
tNodeArray leafs;
leafs.reserve(leafCount());
fetchleafs(this,m_root,leafs);
bottomup(this,leafs);
m_root=leafs[0];
}
}
//
void btDbvt::optimizeTopDown(int bu_treshold)
{
if(m_root)
{
tNodeArray leafs;
leafs.reserve(leafCount());
fetchleafs(this,m_root,leafs);
m_root=topdown(this,leafs,bu_treshold);
}
}
//
btDbvt::Node* btDbvt::insert(const Aabb& box,void* data)
{
Node* leaf=createnode(this,0,box,data);
insertleaf(this,m_root,leaf);
return(leaf);
}
//
void btDbvt::update(Node* leaf,const Aabb& box)
{
Node* root=removeleaf(this,leaf);
if(root)
{
for(int i=0;(i<m_lkhd)&&root->parent;++i)
{
root=root->parent;
}
}
leaf->box=box;
insertleaf(this,root,leaf);
}
//
bool btDbvt::update(Node* leaf,Aabb box,const btVector3& velocity,btScalar margin)
{
if(leaf->box.Contain(box)) return(false);
if(margin>0)
box.Expand(btVector3(margin,margin,margin));
if(velocity.length2()>0)
box.SignedExpand(velocity);
update(leaf,box);
return(true);
}
//
void btDbvt::remove(Node* leaf)
{
removeleaf(this,leaf);
deletenode(this,leaf);
}
//
void btDbvt::collide(btDbvt* tree,
ICollide* icollide) const
{
if(tree->m_root&&m_root)
{
struct sStkElm
{
const Node* a;
const Node* b;
sStkElm(const Node* na,const Node* nb) : a(na),b(nb) {}
};
btAlignedObjectArray<sStkElm> stack;
stack.reserve(128);
stack.push_back(sStkElm(m_root,tree->m_root));
do {
sStkElm p=stack[stack.size()-1];
stack.pop_back();
if(p.a==p.b)
{
if(p.a->isinternal())
{
stack.push_back(sStkElm(p.a->childs[0],p.a->childs[0]));
stack.push_back(sStkElm(p.a->childs[1],p.a->childs[1]));
stack.push_back(sStkElm(p.a->childs[0],p.a->childs[1]));
}
}
else if(Intersect(p.a->box,p.b->box))
{
if(p.a->isinternal())
{
if(p.b->isinternal())
{
stack.push_back(sStkElm(p.a->childs[0],p.b->childs[0]));
stack.push_back(sStkElm(p.a->childs[1],p.b->childs[0]));
stack.push_back(sStkElm(p.a->childs[0],p.b->childs[1]));
stack.push_back(sStkElm(p.a->childs[1],p.b->childs[1]));
}
else
{
stack.push_back(sStkElm(p.a->childs[0],p.b));
stack.push_back(sStkElm(p.a->childs[1],p.b));
}
}
else
{
if(p.b->isinternal())
{
stack.push_back(sStkElm(p.a,p.b->childs[0]));
stack.push_back(sStkElm(p.a,p.b->childs[1]));
}
else
{
icollide->Process(p.a,p.b);
}
}
}
} while(stack.size()>0);
}
}
//
void btDbvt::collide(const Aabb& box,
ICollide* icollide) const
{
if(m_root)
{
btAlignedObjectArray<const Node*> stack;
stack.reserve(64);
stack.push_back(m_root);
do {
const Node* n=stack[stack.size()-1];
stack.pop_back();
if(Intersect(n->box,box))
{
if(n->isinternal())
{
stack.push_back(n->childs[0]);
stack.push_back(n->childs[1]);
}
else
{
icollide->Process(n);
}
}
} while(stack.size()>0);
}
}
//
void btDbvt::collide(const btVector3& org,
const btVector3& dir,
ICollide* icollide) const
{
/* not implemented */
}

View File

@@ -0,0 +1,224 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
///btSoftBody implementation by Nathanael Presson
#ifndef BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
#define BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
#include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btVector3.h"
//
// Dynamic bounding volume tree
//
struct btDbvt
{
// Types
/* Aabb */
struct Aabb
{
inline btVector3 Center() const { return((mi+mx)/2); }
inline btVector3 Extent() const { return((mx-mi)/2); }
inline const btVector3& Mins() const { return(mi); }
inline const btVector3& Maxs() const { return(mx); }
inline btVector3 Lengths() const { return(mx-mi); }
static inline Aabb FromCE(const btVector3& c,const btVector3& e);
static inline Aabb FromCR(const btVector3& c,btScalar r);
static inline Aabb FromMM(const btVector3& mi,const btVector3& mx);
static inline Aabb FromPoints(const btVector3* pts,int n);
static inline Aabb FromPoints(const btVector3** ppts,int n);
inline void Expand(const btVector3 e);
inline void SignedExpand(const btVector3 e);
inline bool Contain(const Aabb& a) const;
inline friend bool Intersect( const Aabb& a,
const Aabb& b);
inline friend btScalar Proximity( const Aabb& a,
const Aabb& b);
inline friend void Merge( const Aabb& a,
const Aabb& b,
Aabb& r);
inline friend bool NotEqual( const Aabb& a,
const Aabb& b);
btVector3 mi,mx;
};
/* Node */
struct Node
{
Aabb box;
Node* parent;
bool isleaf() const { return(childs[1]==0); }
bool isinternal() const { return(!isleaf()); }
union {
Node* childs[2];
void* data;
};
};
// Interfaces
/* ICollide */
struct ICollide
{
virtual void Process(const Node* leaf0,const Node* leaf1) {};
virtual void Process(const Node* leaf) {};
};
// Fields
Node* m_root;
Node* m_free;
int m_lkhd;
// Methods
btDbvt();
~btDbvt();
void clear();
int leafCount() const;
void optimizeBottomUp();
void optimizeTopDown(int bu_treshold=128);
Node* insert(const Aabb& box,void* data);
void update(Node* leaf,const Aabb& box);
bool update(Node* leaf,Aabb box,const btVector3& velocity,btScalar margin);
void remove(Node* leaf);
void collide(btDbvt* tree,
ICollide* icollide) const;
void collide(const Aabb& box,
ICollide* icollide) const;
void collide(const btVector3& org,
const btVector3& dir,
ICollide* icollide) const;
//
private:
btDbvt(const btDbvt&) {}
};
//
// Inline's
//
//
inline btDbvt::Aabb btDbvt::Aabb::FromCE(const btVector3& c,const btVector3& e)
{
Aabb box;
box.mi=c-e;box.mx=c+e;
return(box);
}
//
inline btDbvt::Aabb btDbvt::Aabb::FromCR(const btVector3& c,btScalar r)
{
return(FromCE(c,btVector3(r,r,r)));
}
//
inline btDbvt::Aabb btDbvt::Aabb::FromMM(const btVector3& mi,const btVector3& mx)
{
Aabb box;
box.mi=mi;box.mx=mx;
return(box);
}
//
inline btDbvt::Aabb btDbvt::Aabb::FromPoints(const btVector3* pts,int n)
{
Aabb box;
box.mi=box.mx=pts[0];
for(int i=1;i<n;++i)
{
box.mi.setMin(pts[i]);
box.mx.setMax(pts[i]);
}
return(box);
}
//
inline btDbvt::Aabb btDbvt::Aabb::FromPoints(const btVector3** ppts,int n)
{
Aabb box;
box.mi=box.mx=*ppts[0];
for(int i=1;i<n;++i)
{
box.mi.setMin(*ppts[i]);
box.mx.setMax(*ppts[i]);
}
return(box);
}
//
inline void btDbvt::Aabb::Expand(const btVector3 e)
{
mi-=e;mx+=e;
}
//
inline void btDbvt::Aabb::SignedExpand(const btVector3 e)
{
if(e.x()>0) mx.setX(mx.x()+e.x()); else mi.setX(mi.x()+e.x());
if(e.y()>0) mx.setY(mx.y()+e.y()); else mi.setY(mi.y()+e.y());
if(e.z()>0) mx.setZ(mx.z()+e.z()); else mi.setZ(mi.z()+e.z());
}
//
inline bool btDbvt::Aabb::Contain(const Aabb& a) const
{
return( (mi.x()<=a.mi.x())&&
(mi.y()<=a.mi.y())&&
(mi.z()<=a.mi.z())&&
(mx.x()>=a.mx.x())&&
(mx.y()>=a.mx.y())&&
(mx.z()>=a.mx.z()));
}
//
inline bool Intersect( const btDbvt::Aabb& a,
const btDbvt::Aabb& b)
{
return( (a.mi.x()<=b.mx.x())&&
(a.mi.y()<=b.mx.y())&&
(a.mi.z()<=b.mx.z())&&
(a.mx.x()>=b.mi.x())&&
(a.mx.y()>=b.mi.y())&&
(a.mx.z()>=b.mi.z()));
}
//
inline btScalar Proximity( const btDbvt::Aabb& a,
const btDbvt::Aabb& b)
{
const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx);
return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z()));
}
//
inline void Merge( const btDbvt::Aabb& a,
const btDbvt::Aabb& b,
btDbvt::Aabb& r)
{
r=a;
r.mi.setMin(b.mi);
r.mx.setMax(b.mx);
}
//
inline bool NotEqual( const btDbvt::Aabb& a,
const btDbvt::Aabb& b)
{
return( (a.mi.x()!=b.mi.x())||
(a.mi.y()!=b.mi.y())||
(a.mi.z()!=b.mi.z())||
(a.mx.x()!=b.mx.x())||
(a.mx.y()!=b.mx.y())||
(a.mx.z()!=b.mx.z()));
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -26,14 +26,15 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btConcaveShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "BulletDynamics/SoftBody/btSparseSDF.h"
#include "BulletDynamics/SoftBody/btDbvt.h"
class btBroadphaseInterface;
class btCollisionDispatcher;
/// btSoftBody is work-in-progress
struct btSoftBody : public btCollisionObject
class btSoftBody : public btCollisionObject
{
public:
//
// Enumerations
//
@@ -44,7 +45,7 @@ struct btSoftBody : public btCollisionObject
Bending, ///Secondary constraints
};};
////eAeroModel
///eAeroModel
struct eAeroModel { enum _ {
V_Point, ///Vertex normals are oriented toward velocity
V_TwoSided, ///Vertex normals are fliped to match velocity
@@ -53,66 +54,20 @@ struct btSoftBody : public btCollisionObject
F_OneSided, ///Face normals are taken as it is
};};
struct btSoftBodyWorldInfo
{
btScalar air_density;
btScalar water_density;
btScalar water_offset;
btVector3 water_normal;
btBroadphaseInterface* m_broadphase;
btCollisionDispatcher* m_dispatcher;
btVector3 m_gravity;
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
{
btRigidBody* m_body; /* Rigid body */
btVector3 m_normal; /* Outward normal */
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
{
btVector3 m_velocity; /* Velocity */
btScalar m_pressure; /* Pressure */
btScalar m_density; /* Density */
};
virtual void EvaluateMedium( const btVector3& /*position*/, sMedium& medium);
// Flags
//
///fCollision
struct fCollision { enum _ {
RVSmask = 0x000f, ///Rigid versus soft mask
SDF_RS = 0x0001, ///SDF base rigid vs soft
SVSmask = 0x00f0, ///Rigid versus soft mask
VF_SS = 0x0010, ///Vertex vs face soft vs soft handling
/* presets */
Default = SDF_RS,
};};
//
// Internal types
@@ -121,291 +76,288 @@ struct btSoftBody : public btCollisionObject
typedef btAlignedObjectArray<btScalar> tScalarArray;
typedef btAlignedObjectArray<btVector3> tVector3Array;
/* btSoftBodyWorldInfo */
struct btSoftBodyWorldInfo
{
btScalar air_density;
btScalar water_density;
btScalar water_offset;
btVector3 water_normal;
btBroadphaseInterface* m_broadphase;
btCollisionDispatcher* m_dispatcher;
btVector3 m_gravity;
btSparseSdf<3> m_sparsesdf;
};
/* sCti is Softbody contact info */
struct sCti
{
btRigidBody* m_body; /* Rigid body */
btVector3 m_normal; /* Outward normal */
btScalar m_offset; /* Offset from origin */
};
/* sMedium */
struct sMedium
{
btVector3 m_velocity; /* Velocity */
btScalar m_pressure; /* Pressure */
btScalar m_density; /* Density */
};
/* Base type */
struct Element
{
void* m_tag; // User data
};
///Node
/* Node */
struct Node : Element
{
btVector3 m_x; // Position
btVector3 m_q; // Previous step position
btVector3 m_v; // Velocity
btVector3 m_f; // Force accumulator
btVector3 m_n; // Normal
btScalar m_im; // 1/mass
btScalar m_area; // Area
int m_battach:1; // Attached
btVector3 m_x; // Position
btVector3 m_q; // Previous step position
btVector3 m_v; // Velocity
btVector3 m_f; // Force accumulator
btVector3 m_n; // Normal
btScalar m_im; // 1/mass
btScalar m_area; // Area
btDbvt::Node* m_leaf; // Leaf data
int m_battach:1; // Attached
};
/* Link */
struct Link : Element
{
Node* m_n[2]; // Node pointers
btScalar m_rl; // Rest length
btScalar m_kST; // Stiffness coefficient
btScalar m_c0; // (ima+imb)*kLST
btScalar m_c1; // rl^2
btSoftBody::eLType::_ m_type; // Link type
Node* m_n[2]; // Node pointers
btScalar m_rl; // Rest length
btScalar m_kST; // Stiffness coefficient
btScalar m_c0; // (ima+imb)*kLST
btScalar m_c1; // rl^2
btSoftBody::eLType::_ m_type; // Link type
};
/* Face */
struct Face : Element
{
Node* m_n[3]; // Node pointers
btVector3 m_normal; // Normal
btScalar m_ra; // Rest area
Node* m_n[3]; // Node pointers
btVector3 m_normal; // Normal
btScalar m_ra; // Rest area
btDbvt::Node* m_leaf; // Leaf data
};
/* Contact */
struct Contact
/* RContact */
struct RContact
{
btSoftBody::sCti m_cti; // Contact infos
Node* m_node; // Owner node
btMatrix3x3 m_c0; // Impulse matrix
btVector3 m_c1; // Relative anchor
btScalar m_c2; // ima*dt
btScalar m_c3; // Friction
btSoftBody::sCti m_cti; // Contact infos
Node* m_node; // Owner node
btMatrix3x3 m_c0; // Impulse matrix
btVector3 m_c1; // Relative anchor
btScalar m_c2; // ima*dt
btScalar m_c3; // Friction
};
/* SContact */
struct SContact
{
Node* m_node; // Node
Face* m_face; // Face
btVector3 m_weights; // Weigths
btVector3 m_normal; // Normal
btScalar m_margin; // Margin
btScalar m_friction; // Friction
btScalar m_cfm[2]; // Constraint force mixing
};
/* Anchor */
struct Anchor
{
Node* m_node; // Node pointer
btVector3 m_local; // Anchor position in body space
btRigidBody* m_body; // Body
btMatrix3x3 m_c0; // Impulse matrix
btVector3 m_c1; // Relative anchor
btScalar m_c2; // ima*dt
Node* m_node; // Node pointer
btVector3 m_local; // Anchor position in body space
btRigidBody* m_body; // Body
btMatrix3x3 m_c0; // Impulse matrix
btVector3 m_c1; // Relative anchor
btScalar m_c2; // ima*dt
};
/* Pose */
struct Pose
{
bool m_bvolume; // Is valid
bool m_bframe; // Is frame
btScalar m_volume; // Rest volume
tVector3Array m_pos; // Reference positions
tScalarArray m_wgh; // Weights
btVector3 m_com; // COM
btMatrix3x3 m_trs; // Transform
bool m_bvolume; // Is valid
bool m_bframe; // Is frame
btScalar m_volume; // Rest volume
tVector3Array m_pos; // Reference positions
tScalarArray m_wgh; // Weights
btVector3 m_com; // COM
btMatrix3x3 m_rot; // Rotation
btMatrix3x3 m_scl; // Scale
btMatrix3x3 m_aqq; // Base scaling
};
/* Config */
struct Config
{
btSoftBody::eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point)
btScalar kLST; // Linear stiffness coefficient [0,1]
btScalar kDP; // Damping coefficient [0,1]
btScalar kDG; // Drag coefficient [0,+inf]
btScalar kLF; // Lift coefficient [0,+inf]
btScalar kPR; // Pressure coefficient [-inf,+inf]
btScalar kVC; // Volume conversation coefficient [0,+inf]
btScalar kDF; // Dynamic friction coefficient [0,1]
btScalar kMT; // Pose matching coefficient [0,1]
btScalar kSOR; // SOR(w) [1,2] default 1, never use with solver!=Accurate
btScalar kCHR; // Contacts hardness [0,1]
btScalar kAHR; // Anchors hardness [0,1]
btScalar timescale; // Time scale
btScalar timestep; // Time step
int maxsteps; // Maximum time steps
int iterations; // Solver iterations
bool becollide; // Enable external collisions
bool bscollide; // Enable self collisions
btScalar kLST; // Linear stiffness coefficient [0,1]
btScalar kDP; // Damping coefficient [0,1]
btScalar kDG; // Drag coefficient [0,+inf]
btScalar kLF; // Lift coefficient [0,+inf]
btScalar kPR; // Pressure coefficient [-inf,+inf]
btScalar kVC; // Volume conversation coefficient [0,+inf]
btScalar kDF; // Dynamic friction coefficient [0,1]
btScalar kMT; // Pose matching coefficient [0,1]
btScalar kSOR; // SOR(w) [1,2] default 1, never use with solver!=Accurate
btScalar kCHR; // Rigid contacts hardness [0,1]
btScalar kSHR; // Soft contacts hardness [0,1]
btScalar kAHR; // Anchors hardness [0,1]
btScalar maxvolume; // Maximum volume ratio for pose
btScalar timescale; // Time scale
int iterations; // Solver iterations
int collisions; // Collisions flags
};
/* SolverState */
struct SolverState
{
btScalar iit; // 1/iterations
btScalar sdt; // dt*timescale
btScalar isdt; // 1/sdt
btScalar velmrg; // velocity margin
};
//
// Typedef's
//
typedef btAlignedObjectArray<Node> tNodeArray;
typedef btAlignedObjectArray<Link> tLinkArray;
typedef btAlignedObjectArray<Face> tFaceArray;
typedef btAlignedObjectArray<Anchor> tAnchorArray;
typedef btAlignedObjectArray<Contact> tContactArray;
typedef btAlignedObjectArray<Node> tNodeArray;
typedef btAlignedObjectArray<Link> tLinkArray;
typedef btAlignedObjectArray<Face> tFaceArray;
typedef btAlignedObjectArray<Anchor> tAnchorArray;
typedef btAlignedObjectArray<RContact> tRContactArray;
typedef btAlignedObjectArray<SContact> tSContactArray;
typedef btAlignedObjectArray<btSoftBody*> tSoftBodyArray;
//
// Fields
//
Config m_cfg; // Configuration
Pose m_pose; // Pose
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
tLinkArray m_links; // Links
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
tContactArray m_contacts; // Contacts
btScalar m_timeacc; // Time accumulator
btVector3 m_bounds[2]; // Spatial bounds
bool m_bUpdateRtCst; // Update runtime constants
Config m_cfg; // Configuration
SolverState m_sst; // Solver state
Pose m_pose; // Pose
void* m_tag; // User data
btSoftBodyWorldInfo* m_worldInfo; //
tAnchorArray m_anchors; // Anchors
tRContactArray m_rcontacts; // Rigid contacts
tSContactArray m_scontacts; // Soft contacts
btScalar m_timeacc; // Time accumulator
btVector3 m_bounds[2]; // Spatial bounds
bool m_bUpdateRtCst; // Update runtime constants
btDbvt m_ndbvt; // Nodes tree
btDbvt m_fdbvt; // Faces tree
//
// Api
//
/* Delete a body */
void Delete();
/* ctor */
btSoftBody( btSoftBody::btSoftBodyWorldInfo* worldInfo,int node_count,
const btVector3* x,
const btScalar* m);
/* dtor */
virtual ~btSoftBody();
/* Check for existing link */
bool CheckLink( int node0,
bool checkLink( int node0,
int node1) const;
bool CheckLink( const btSoftBody::Node* node0,
bool checkLink( const btSoftBody::Node* node0,
const btSoftBody::Node* node1) const;
/* Check for existring face */
bool CheckFace( int node0,
bool checkFace( int node0,
int node1,
int node2) const;
/* Append link */
void AppendLink( int node0,
void appendLink( int node0,
int node1,
btScalar kST,
btSoftBody::eLType::_ type,
bool bcheckexist=false);
void AppendLink( btSoftBody::Node* node0,
void appendLink( btSoftBody::Node* node0,
btSoftBody::Node* node1,
btScalar kST,
btSoftBody::eLType::_ type,
bool bcheckexist=false);
/* Append face */
void AppendFace( int node0,
void appendFace( int node0,
int node1,
int node2);
/* Append anchor */
void AppendAnchor( int node,
void appendAnchor( int node,
btRigidBody* body);
/* Add force (or gravity) to the entire body */
void AddForce( const btVector3& force);
void addForce( const btVector3& force);
/* Add force (or gravity) to a node of the body */
void AddForce( const btVector3& force,
void addForce( const btVector3& force,
int node);
/* Add velocity to the entire body */
void AddVelocity( const btVector3& velocity);
void addVelocity( const btVector3& velocity);
/* Add velocity to a node of the body */
void AddVelocity( const btVector3& velocity,
void addVelocity( const btVector3& velocity,
int node);
/* Set mass */
void SetMass( int node,
void setMass( int node,
btScalar mass);
/* Get mass */
btScalar GetMass( int node) const;
btScalar getMass( int node) const;
/* Get total mass */
btScalar GetTotalMass() const;
btScalar getTotalMass() const;
/* Set total mass (weighted by previous masses) */
void SetTotalMass( btScalar mass,
void setTotalMass( btScalar mass,
bool fromfaces=false);
/* Set total density */
void SetTotalDensity(btScalar density);
void setTotalDensity(btScalar density);
/* Transform */
void Transform( const btTransform& trs);
void transform( const btTransform& trs);
/* Scale */
void Scale( const btVector3& scl);
void scale( const btVector3& scl);
/* Set current state as pose */
void SetPose( bool bvolume,
void setPose( bool bvolume,
bool bframe);
/* Return the volume */
btScalar GetVolume() const;
btScalar getVolume() const;
/* Generate bending constraints based on distance in the adjency graph */
int GenerateBendingConstraints( int distance,
int generateBendingConstraints( int distance,
btScalar stiffness);
/* Randomize constraints to reduce solver bias */
void RandomizeConstraints();
void randomizeConstraints();
/* Ray casting */
btScalar Raycast( const btVector3& org,
const btVector3& dir) const;
/* Step */
void Step( btScalar dt);
btScalar raycast(const btVector3& org,
const btVector3& dir) const;
/* predictMotion */
void predictMotion(btScalar dt);
/* solveConstraints */
void solveConstraints();
/* solveCommonConstraints */
static void solveCommonConstraints(btSoftBody** bodies,int count,int iterations);
/* integrateMotion */
void integrateMotion();
/* defaultCollisionHandlers */
void defaultCollisionHandler(btCollisionObject* pco);
void defaultCollisionHandler(btSoftBody* psb);
void updateBounds();
void updateTransform()
///to keep collision detection and dynamics separate we don't store a rigidbody pointer
///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast
static const btSoftBody* upcast(const btCollisionObject* colObj)
{
updateBounds();
if (colObj->getInternalType()==CO_SOFT_BODY)
return (const btSoftBody*)colObj;
return 0;
}
static btSoftBody* upcast(btCollisionObject* colObj)
{
if (colObj->getInternalType()==CO_SOFT_BODY)
return (btSoftBody*)colObj;
return 0;
}
//
// ...
//
tNodeArray& getNodes();
const tNodeArray& getNodes() const;
tLinkArray& getLinks();
const tLinkArray& getLinks() const;
tFaceArray& getFaces();
const tFaceArray& getFaces() const;
};

View File

@@ -15,13 +15,15 @@ subject to the following restrictions:
///btSoftBodyHelpers.cpp by Nathanael Presson
#include "btSoftBody.h"
#include "btDbvt.h"
#include <stdio.h>
#include <string.h>
#include "btSoftBodyHelpers.h"
#include "LinearMath/btConvexHull.h"
//
void btSoftBodyHelpers::drawVertex( btIDebugDraw* idraw,
const btVector3& x,btScalar s,const btVector3& c)
static void drawVertex( btIDebugDraw* idraw,
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(0,s,0),x+btVector3(0,s,0),c);
@@ -29,26 +31,70 @@ void btSoftBodyHelpers::drawVertex( btIDebugDraw* idraw,
}
//
btVector3 btSoftBodyHelpers::stresscolor(btScalar stress)
static void drawBox( btIDebugDraw* idraw,
const btVector3& mins,
const btVector3& maxs,
const btVector3& color)
{
static const btVector3 spectrum[]= {
btVector3(1,0,1),
btVector3(0,0,1),
btVector3(0,1,1),
btVector3(0,1,0),
btVector3(1,1,0),
btVector3(1,0,0),
btVector3(1,0,0),
};
const btVector3 c[]={ btVector3(mins.x(),mins.y(),mins.z()),
btVector3(maxs.x(),mins.y(),mins.z()),
btVector3(maxs.x(),maxs.y(),mins.z()),
btVector3(mins.x(),maxs.y(),mins.z()),
btVector3(mins.x(),mins.y(),maxs.z()),
btVector3(maxs.x(),mins.y(),maxs.z()),
btVector3(maxs.x(),maxs.y(),maxs.z()),
btVector3(mins.x(),maxs.y(),maxs.z())};
idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color);
idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color);
idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color);
idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color);
idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color);
idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color);
}
//
static void drawTree( btIDebugDraw* idraw,
const btDbvt::Node* node,
int depth,
const btVector3& ncolor,
const btVector3& lcolor,
int mindepth,
int maxdepth)
{
if(node)
{
if(node->isinternal()&&((depth<maxdepth)||(maxdepth<0)))
{
drawTree(idraw,node->childs[0],depth+1,ncolor,lcolor,mindepth,maxdepth);
drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth);
}
if(depth>=mindepth)
{
const btScalar scl=(btScalar)(node->isinternal()?1:1);
const btVector3 mi=node->box.Center()-node->box.Extent()*scl;
const btVector3 mx=node->box.Center()+node->box.Extent()*scl;
drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor);
}
}
}
//
static btVector3 stresscolor(btScalar stress)
{
static const btVector3 spectrum[]= { btVector3(1,0,1),
btVector3(0,0,1),
btVector3(0,1,1),
btVector3(0,1,0),
btVector3(1,1,0),
btVector3(1,0,0),
btVector3(1,0,0)};
static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1;
static const btScalar one=1;
stress=btMax<btScalar>(0,btMin<btScalar>(1,stress))*ncolors;
const int sel=(int)stress;
const btScalar frc=stress-sel;
return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc);
}
}
//
void btSoftBodyHelpers::Draw( btSoftBody* psb,
@@ -105,9 +151,9 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb,
static const btVector3 axis[]={btVector3(1,0,0),
btVector3(0,1,0),
btVector3(0,0,1)};
for(int i=0;i<psb->m_contacts.size();++i)
for(int i=0;i<psb->m_rcontacts.size();++i)
{
const btSoftBody::Contact& c=psb->m_contacts[i];
const btSoftBody::RContact& c=psb->m_rcontacts[i];
const btVector3 o= c.m_node->m_x-c.m_cti.m_normal*
(dot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset);
const btVector3 x=cross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized();
@@ -183,6 +229,24 @@ void btSoftBodyHelpers::DrawInfos( btSoftBody* psb,
}
}
//
void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb,
btIDebugDraw* idraw,
int mindepth,
int maxdepth)
{
drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth);
}
//
void btSoftBodyHelpers::DrawFaceTree( btSoftBody* psb,
btIDebugDraw* idraw,
int mindepth,
int maxdepth)
{
drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth);
}
//
void btSoftBodyHelpers::DrawFrame( btSoftBody* psb,
btIDebugDraw* idraw)
@@ -192,7 +256,7 @@ void btSoftBodyHelpers::DrawFrame( btSoftBody* psb,
static const btScalar ascl=10;
static const btScalar nscl=(btScalar)0.1;
const btVector3 com=psb->m_pose.m_com;
const btMatrix3x3& trs=psb->m_pose.m_trs;
const btMatrix3x3 trs=psb->m_pose.m_rot*psb->m_pose.m_scl;
const btVector3 Xaxis=(trs*btVector3(1,0,0)).normalized();
const btVector3 Yaxis=(trs*btVector3(0,1,0)).normalized();
const btVector3 Zaxis=(trs*btVector3(0,0,1)).normalized();
@@ -225,15 +289,15 @@ btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBody::btSoftBodyWorldInfo& wor
x[i]=lerp(from,to,t);
m[i]=1;
}
btSoftBody* psb= new btSoftBody(worldInfo,r,x,m);
if(fixeds&1) psb->SetMass(0,0);
if(fixeds&2) psb->SetMass(r-1,0);
btSoftBody* psb= new btSoftBody(&worldInfo,r,x,m);
if(fixeds&1) psb->setMass(0,0);
if(fixeds&2) psb->setMass(r-1,0);
delete[] x;
delete[] m;
/* Create links */
for(int i=1;i<r;++i)
{
psb->AppendLink(i-1,i,1,btSoftBody::eLType::Structural);
psb->appendLink(i-1,i,1,btSoftBody::eLType::Structural);
}
/* Finished */
return(psb);
@@ -269,11 +333,11 @@ btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBody::btSoftBodyWorldInfo& wor
m[IDX(ix,iy)]=1;
}
}
btSoftBody* psb=new btSoftBody(worldInfo,tot,x,m);
if(fixeds&1) psb->SetMass(IDX(0,0),0);
if(fixeds&2) psb->SetMass(IDX(rx-1,0),0);
if(fixeds&4) psb->SetMass(IDX(0,ry-1),0);
if(fixeds&8) psb->SetMass(IDX(rx-1,ry-1),0);
btSoftBody* psb=new btSoftBody(&worldInfo,tot,x,m);
if(fixeds&1) psb->setMass(IDX(0,0),0);
if(fixeds&2) psb->setMass(IDX(rx-1,0),0);
if(fixeds&4) psb->setMass(IDX(0,ry-1),0);
if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0);
delete[] x;
delete[] m;
/* Create links and faces */
@@ -284,29 +348,29 @@ btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBody::btSoftBodyWorldInfo& wor
const int idx=IDX(ix,iy);
const bool mdx=(ix+1)<rx;
const bool mdy=(iy+1)<ry;
if(mdx) psb->AppendLink(idx,IDX(ix+1,iy),
if(mdx) psb->appendLink(idx,IDX(ix+1,iy),
1,btSoftBody::eLType::Structural);
if(mdy) psb->AppendLink(idx,IDX(ix,iy+1),
if(mdy) psb->appendLink(idx,IDX(ix,iy+1),
1,btSoftBody::eLType::Structural);
if(mdx&&mdy)
{
if((ix+iy)&1)
{
psb->AppendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1));
psb->AppendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1));
psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1));
psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1));
if(gendiags)
{
psb->AppendLink(IDX(ix,iy),IDX(ix+1,iy+1),
psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1),
1,btSoftBody::eLType::Structural);
}
}
else
{
psb->AppendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy));
psb->AppendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1));
psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy));
psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1));
if(gendiags)
{
psb->AppendLink(IDX(ix+1,iy),IDX(ix,iy+1),
psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1),
1,btSoftBody::eLType::Structural);
}
}
@@ -369,7 +433,7 @@ btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBody::btSoftBodyWorldInf
{
vtx[j]=btVector3(vertices[i],vertices[i+1],vertices[i+2]);
}
btSoftBody* psb=new btSoftBody(worldInfo,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)
{
const int idx[]={triangles[i],triangles[i+1],triangles[i+2]};
@@ -380,12 +444,42 @@ btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBody::btSoftBodyWorldInf
{
chks[IDX(idx[j],idx[k])]=true;
chks[IDX(idx[k],idx[k])]=true;
psb->AppendLink(idx[j],idx[k],1,btSoftBody::eLType::Structural);
psb->appendLink(idx[j],idx[k],1,btSoftBody::eLType::Structural);
}
}
#undef IDX
psb->AppendFace(idx[0],idx[1],idx[2]);
psb->appendFace(idx[0],idx[1],idx[2]);
}
psb->RandomizeConstraints();
psb->randomizeConstraints();
return(psb);
}
//
btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBody::btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
int nvertices)
{
HullDesc hdsc(QF_TRIANGLES,nvertices,vertices);
HullResult hres;
HullLibrary hlib;/*??*/
hdsc.mMaxVertices=nvertices;
hlib.CreateConvexHull(hdsc,hres);
btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices,
&hres.m_OutputVertices[0],0);
for(int i=0;i<(int)hres.mNumFaces;++i)
{
const int idx[]={ hres.m_Indices[i*3+0],
hres.m_Indices[i*3+1],
hres.m_Indices[i*3+2]};
if(idx[0]<idx[1]) psb->appendLink( idx[0],idx[1],
1,btSoftBody::eLType::Structural);
if(idx[1]<idx[2]) psb->appendLink( idx[1],idx[2],
1,btSoftBody::eLType::Structural);
if(idx[2]<idx[0]) psb->appendLink( idx[2],idx[0],
1,btSoftBody::eLType::Structural);
psb->appendFace(idx[0],idx[1],idx[2]);
}
hlib.ReleaseResult(hres);
psb->randomizeConstraints();
return(psb);
}

View File

@@ -40,26 +40,29 @@ struct fDrawFlags { enum _ {
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);
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);
static void DrawInfos( btSoftBody* psb,
btIDebugDraw* idraw,
bool masses,
bool areas,
bool stress);
/* Draw node tree */
static void DrawNodeTree( btSoftBody* psb,
btIDebugDraw* idraw,
int mindepth=0,
int maxdepth=-1);
/* Draw face tree */
static void DrawFaceTree( btSoftBody* psb,
btIDebugDraw* idraw,
int mindepth=0,
int maxdepth=-1);
/* Draw rigid frame */
static void DrawFrame( btSoftBody* psb,
btIDebugDraw* idraw);
btIDebugDraw* idraw);
/* Create a rope */
static btSoftBody* CreateRope( btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& from,
const btVector3& to,

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,96 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#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;
softBody->defaultCollisionHandler(rigidCollisionObject);
}
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,70 @@
/*
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"
class 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,132 @@
/*
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 "btSoftRigidDynamicsWorld.h"
#include "LinearMath/btQuickprof.h"
//softbody & helpers
#include "BulletDynamics/SoftBody/btSoftBody.h"
#include "BulletDynamics/SoftBody/btSoftBodyHelpers.h"
btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration)
{
}
btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld()
{
}
void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
{
btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep);
for ( int i=0;i<m_softBodies.size();++i)
{
btSoftBody* psb= m_softBodies[i];
psb->predictMotion(timeStep);
}
}
void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep)
{
btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep );
///solve soft bodies constraints
solveSoftBodiesConstraints();
///update soft bodies
updateSoftBodies();
}
void btSoftRigidDynamicsWorld::updateSoftBodies()
{
BT_PROFILE("updateSoftBodies");
for ( int i=0;i<m_softBodies.size();i++)
{
btSoftBody* psb=(btSoftBody*)m_softBodies[i];
psb->integrateMotion();
}
}
void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints()
{
BT_PROFILE("solveSoftConstraints");
for(int i=0;i<m_softBodies.size();++i)
{
btSoftBody* psb=(btSoftBody*)m_softBodies[i];
psb->solveConstraints();
}
}
void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body)
{
m_softBodies.push_back(body);
btCollisionWorld::addCollisionObject(body,
btBroadphaseProxy::DefaultFilter,
btBroadphaseProxy::AllFilter);
}
void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body)
{
m_softBodies.remove(body);
btCollisionWorld::removeCollisionObject(body);
}
void btSoftRigidDynamicsWorld::debugDrawWorld()
{
btDiscreteDynamicsWorld::debugDrawWorld();
if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb))
{
int i;
for ( i=0;i<this->m_softBodies.size();i++)
{
btSoftBody* psb=(btSoftBody*)this->m_softBodies[i];
btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer);
btSoftBodyHelpers::Draw(psb,m_debugDrawer,fDrawFlags::Std+fDrawFlags::Nodes);
if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
{
btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer);
//btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer);
}
}
if (getDebugDrawer())
{
for (int i=0;i<this->m_softBodies.size();i++)
{
btSoftBody* psb=(btSoftBody*)this->m_softBodies[i];
btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer);
btSoftBodyHelpers::Draw(psb,m_debugDrawer,fDrawFlags::Std);
if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
{
btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer);
}
}
}
}
}

View File

@@ -0,0 +1,65 @@
/*
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 "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H
#define BT_SOFT_RIGID_DYNAMICS_WORLD_H
class btSoftBody;
typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld
{
btSoftBodyArray m_softBodies;
protected:
virtual void predictUnconstraintMotion(btScalar timeStep);
virtual void internalSingleStepSimulation( btScalar timeStep);
void updateSoftBodies();
void solveSoftBodiesConstraints();
virtual void debugDrawWorld();
public:
btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
virtual ~btSoftRigidDynamicsWorld();
void addSoftBody(btSoftBody* body);
void removeSoftBody(btSoftBody* body);
btSoftBodyArray& getSoftBodyArray()
{
return m_softBodies;
}
const btSoftBodyArray& getSoftBodyArray() const
{
return m_softBodies;
}
};
#endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H

View File

@@ -0,0 +1,105 @@
/*
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)
{
btSoftBody* soft0 = (btSoftBody*)body0;
btSoftBody* soft1 = (btSoftBody*)body1;
soft0->defaultCollisionHandler(soft1);
/*
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,63 @@
/*
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;
class 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

@@ -32,21 +32,13 @@ struct btSparseSdf
int i;
btScalar f;
};
struct Client
{
btCollisionShape* shape;
btVector3 center;
btVector3 extent;
btScalar vsize;
int id;
};
struct Cell
{
btScalar d[CELLSIZE+1][CELLSIZE+1][CELLSIZE+1];
int c[3];
int puid;
unsigned hash;
const Client* pclient;
btCollisionShape* pclient;
Cell* next;
};
//
@@ -54,7 +46,7 @@ struct btSparseSdf
//
btAlignedObjectArray<Cell*> cells;
btAlignedObjectArray<Client*> clients;
btScalar voxelsz;
int puid;
int ncells;
int nprobes;
@@ -84,13 +76,14 @@ struct btSparseSdf
pc=pn;
}
}
voxelsz =0.25;
puid =0;
ncells =0;
nprobes =1;
nqueries =1;
}
//
void GarbageCollect(int lifetime=64)
void GarbageCollect(int lifetime=256)
{
const int life=puid-lifetime;
for(int i=0;i<cells.size();++i)
@@ -116,39 +109,17 @@ struct btSparseSdf
/* else setup a priority list... */
}
//
Client* GetClient( btCollisionShape* shape)
{
Client* pc=(Client*)shape->getUserPointer();
if(!pc)
{
pc=new Client();
clients.push_back(pc);
shape->setUserPointer(pc);
pc->shape = shape;
pc->id = clients.size();
pc->vsize = 0.25;
SetShapeBounds(*pc);
}
return(pc);
}
//
btScalar Evaluate( const btVector3& x,
btCollisionShape* shape,
btVector3& normal)
btVector3& normal,
btScalar margin)
{
const Client* pclient=GetClient(shape);
/* Bounds check */
const btVector3 offset=x-pclient->center;
const btVector3 sqoffset=offset*offset;
if( (sqoffset.x()>pclient->extent.x()) ||
(sqoffset.y()>pclient->extent.y()) ||
(sqoffset.z()>pclient->extent.z())) return(SIMD_INFINITY);
/* Lookup cell */
const btVector3 scx=x/pclient->vsize;
const btVector3 scx=x/voxelsz;
const IntFrac ix=Decompose(scx.x());
const IntFrac iy=Decompose(scx.y());
const IntFrac iz=Decompose(scx.z());
const unsigned h=Hash(ix.b,iy.b,iz.b,pclient->id);
const unsigned h=Hash(ix.b,iy.b,iz.b,shape);
Cell*& root=cells[h%cells.size()];
Cell* c=root;
++nqueries;
@@ -159,7 +130,7 @@ struct btSparseSdf
(c->c[0]==ix.b) &&
(c->c[1]==iy.b) &&
(c->c[2]==iz.b) &&
(c->pclient==pclient))
(c->pclient==shape))
{ break; }
else
{ c=c->next; }
@@ -170,7 +141,8 @@ struct btSparseSdf
++ncells;
c=new Cell();
c->next=root;root=c;
c->pclient=pclient;c->hash=h;
c->pclient=shape;
c->hash=h;
c->c[0]=ix.b;c->c[1]=iy.b;c->c[2]=iz.b;
BuildCell(*c);
}
@@ -208,33 +180,33 @@ struct btSparseSdf
Lerp(d[3],d[2],ix.f),iy.f);
const btScalar d1=Lerp(Lerp(d[4],d[5],ix.f),
Lerp(d[7],d[6],ix.f),iy.f);
return(Lerp(d0,d1,iz.f));
return(Lerp(d0,d1,iz.f)-margin);
}
//
void BuildCell(Cell& c)
{
const Client* client=c.pclient;
const btVector3 org=btVector3(c.c[0],c.c[1],c.c[2])*CELLSIZE*client->vsize;
const btVector3 org=btVector3( (btScalar)c.c[0],
(btScalar)c.c[1],
(btScalar)c.c[2]) *
CELLSIZE*voxelsz;
for(int k=0;k<=CELLSIZE;++k)
{
const btScalar z=client->vsize*k+org.z();
const btScalar z=voxelsz*k+org.z();
for(int j=0;j<=CELLSIZE;++j)
{
const btScalar y=client->vsize*j+org.y();
const btScalar y=voxelsz*j+org.y();
for(int i=0;i<=CELLSIZE;++i)
{
const btScalar x=client->vsize*i+org.x();
const btScalar x=voxelsz*i+org.x();
c.d[i][j][k]=DistanceToShape( btVector3(x,y,z),
client->shape,
client->vsize);
c.pclient);
}
}
}
}
//
static inline btScalar DistanceToShape(const btVector3& x,
btCollisionShape* shape,
btScalar margin)
btCollisionShape* shape)
{
btTransform unit;
unit.setIdentity();
@@ -242,33 +214,11 @@ struct btSparseSdf
{
btGjkEpaSolver2::sResults res;
btConvexShape* csh=static_cast<btConvexShape*>(shape);
return(btGjkEpaSolver2::SignedDistance(x,margin,csh,unit,res));
return(btGjkEpaSolver2::SignedDistance(x,0,csh,unit,res));
}
return(0);
}
//
static inline void SetShapeBounds(Client& c)
{
if(c.shape->isConvex())
{
btConvexShape* csh=static_cast<btConvexShape*>(c.shape);
const btVector3 x[]={ csh->localGetSupportingVertex(btVector3(+1,0,0)),
csh->localGetSupportingVertex(btVector3(-1,0,0))};
const btVector3 y[]={ csh->localGetSupportingVertex(btVector3(0,+1,0)),
csh->localGetSupportingVertex(btVector3(0,-1,0))};
const btVector3 z[]={ csh->localGetSupportingVertex(btVector3(0,0,+1)),
csh->localGetSupportingVertex(btVector3(0,0,-1))};
c.center = btVector3( x[0].x()+x[1].x(),
y[0].y()+y[1].y(),
z[0].z()+z[1].z())*0.5;
c.extent = btVector3( x[0].x()-x[1].x(),
y[0].y()-y[1].y(),
z[0].z()-z[1].z())*0.5;
c.extent += btVector3(c.vsize,c.vsize,c.vsize);
c.extent *= c.extent;
}
}
//
static inline IntFrac Decompose(btScalar x)
{
/* That one need a lot of improvements... */
@@ -287,10 +237,11 @@ struct btSparseSdf
return(a+(b-a)*t);
}
//
static inline unsigned Hash(int x,int y,int z,int i)
static inline unsigned Hash(int x,int y,int z,btCollisionShape* shape)
{
const int data[]={x,y,z,i};
return(HsiehHash<sizeof(data)/4>(data));
struct { int x,y,z;void* p; } set;
set.x=x;set.y=y;set.z=z;set.p=shape;
return(HsiehHash<sizeof(set)/4>(&set));
}
// Modified Paul Hsieh hash
template <const int DWORDLEN>