Softbody improvements, thanks to Nathanael

This commit is contained in:
erwin.coumans
2008-05-17 12:39:16 +00:00
parent 649709dc2d
commit d9e7058ff2
12 changed files with 2098 additions and 1828 deletions

View File

@@ -15,13 +15,7 @@ subject to the following restrictions:
///btSoftBody implementation by Nathanael Presson
#include "btSoftBody.h"
#if 1
#include <stdio.h>
#define DOTRACE
#endif
#include <string.h>
#include "LinearMath/btQuickprof.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
@@ -136,17 +130,6 @@ void btSoftBodyCollisionShape::processAllTriangles(btTriangleCallback* /*callbac
//
//
#ifdef DOTRACE
static inline void Trace(const btMatrix3x3& m,const char* name)
{
printf("%s[0]: %.2f,\t%.2f,\t%.2f\r\n",name,m[0].x(),m[0].y(),m[0].z());
printf("%s[1]: %.2f,\t%.2f,\t%.2f\r\n",name,m[1].x(),m[1].y(),m[1].z());
printf("%s[2]: %.2f,\t%.2f,\t%.2f\r\n",name,m[2].x(),m[2].y(),m[2].z());
printf("\r\n");
}
#else
static inline void Trace(const btMatrix3x3&,const char*) {}
#endif
//
template <typename T>
@@ -199,6 +182,10 @@ template <typename T>
static inline T Sign(const T& x)
{ return((T)(x<0?-1:+1)); }
//
template <typename T>
static inline bool SameSign(const T& x,const T& y)
{ return((x*y)>0); }
//
static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a,btScalar s)
{
const btScalar xx=a.x()*a.x();
@@ -456,17 +443,6 @@ static void PointersToIndices(btSoftBody* psb)
psb->m_faces[i].m_leaf->data=*(void**)&i;
}
}
for(int i=0,ni=psb->m_tetras.size();i<ni;++i)
{
psb->m_tetras[i].m_n[0]=PTR2IDX(psb->m_tetras[i].m_n[0],base);
psb->m_tetras[i].m_n[1]=PTR2IDX(psb->m_tetras[i].m_n[1],base);
psb->m_tetras[i].m_n[2]=PTR2IDX(psb->m_tetras[i].m_n[2],base);
psb->m_tetras[i].m_n[3]=PTR2IDX(psb->m_tetras[i].m_n[3],base);
if(psb->m_tetras[i].m_leaf)
{
psb->m_tetras[i].m_leaf->data=*(void**)&i;
}
}
for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
{
psb->m_anchors[i].m_node=PTR2IDX(psb->m_anchors[i].m_node,base);
@@ -509,17 +485,6 @@ static void IndicesToPointers(btSoftBody* psb,const int* map=0)
psb->m_faces[i].m_leaf->data=&psb->m_faces[i];
}
}
for(int i=0,ni=psb->m_tetras.size();i<ni;++i)
{
psb->m_tetras[i].m_n[0]=IDX2PTR(psb->m_tetras[i].m_n[0],base);
psb->m_tetras[i].m_n[1]=IDX2PTR(psb->m_tetras[i].m_n[1],base);
psb->m_tetras[i].m_n[2]=IDX2PTR(psb->m_tetras[i].m_n[2],base);
psb->m_tetras[i].m_n[3]=IDX2PTR(psb->m_tetras[i].m_n[3],base);
if(psb->m_tetras[i].m_leaf)
{
psb->m_tetras[i].m_leaf->data=&psb->m_tetras[i];
}
}
for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
{
psb->m_anchors[i].m_node=IDX2PTR(psb->m_anchors[i].m_node,base);
@@ -605,11 +570,10 @@ static inline btScalar RayTriangle(const btVector3& org,
// Private implementation
//
struct RayCaster : public btDbvt::ICollide
struct RayCaster : btDbvt::ICollide
{
btVector3 o;
btVector3 d;
btVector3 nd;
btScalar mint;
btSoftBody::Face* face;
int tests;
@@ -617,18 +581,11 @@ struct RayCaster : public btDbvt::ICollide
{
o = org;
d = dir;
nd = dir.normalized();
mint = mxt;
face = 0;
tests = 0;
}
virtual void Process(const btDbvt::Node* /*a*/,const btDbvt::Node* /*b*/)
{
}
virtual void Process(const btDbvt::Node* leaf)
void Process(const btDbvt::Node* leaf)
{
btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data;
const btScalar t=RayTriangle( o,d,
@@ -643,13 +600,6 @@ struct RayCaster : public btDbvt::ICollide
}
++tests;
}
virtual bool Descent(const btDbvt::Node* node)
{
const btVector3 ctr=node->volume.Center()-o;
const btScalar sqr=node->volume.Lengths().length2()/4;
const btScalar prj=dot(ctr,nd);
return((ctr-(nd*prj)).length2()<=sqr);
}
};
@@ -665,55 +615,22 @@ static int RaycastInternal(const btSoftBody* psb,
int cnt=0;
if(bcountonly||psb->m_fdbvt.empty())
{/* Full search */
if(!psb->m_faces.size())
{/* Tetras */
for(int i=0,ni=psb->m_tetras.size();i<ni;++i)
{
const btSoftBody::Tetra& t=psb->m_tetras[i];
const btSoftBody::Node* const* n=t.m_n;
const int f[]={ 0,1,2,
0,1,3,
1,2,3,
2,0,3};
for(int j=0;j<12;j+=3)
{
const btScalar t=RayTriangle( org,dir,
n[f[j+0]]->m_x,
n[f[j+1]]->m_x,
n[f[j+2]]->m_x,
for(int i=0,ni=psb->m_faces.size();i<ni;++i)
{
const btSoftBody::Face& f=psb->m_faces[i];
const btScalar t=RayTriangle( org,dir,
f.m_n[0]->m_x,
f.m_n[1]->m_x,
f.m_n[2]->m_x,
mint);
if(t>0)
{
++cnt;
if(!bcountonly)
{
feature=btSoftBody::eFeature::Tetra;
index=-1;
mint=t;
}
}
}
}
}
else
{/* Faces */
for(int i=0,ni=psb->m_faces.size();i<ni;++i)
if(t>0)
{
const btSoftBody::Face& f=psb->m_faces[i];
const btScalar t=RayTriangle( org,dir,
f.m_n[0]->m_x,
f.m_n[1]->m_x,
f.m_n[2]->m_x,
mint);
if(t>0)
++cnt;
if(!bcountonly)
{
++cnt;
if(!bcountonly)
{
feature=btSoftBody::eFeature::Face;
index=i;
mint=t;
}
feature=btSoftBody::eFeature::Face;
index=i;
mint=t;
}
}
}
@@ -721,7 +638,7 @@ static int RaycastInternal(const btSoftBody* psb,
else
{/* Use dbvt */
RayCaster collider(org,dir,mint);
psb->m_fdbvt.collideGeneric(&collider);
btDbvt::collideRAY(psb->m_fdbvt.m_root,org,dir,collider);
if(collider.face)
{
mint=collider.mint;
@@ -742,7 +659,6 @@ for(int i=0;i<psb->m_faces.size();++i)
btSoftBody::Face& f=psb->m_faces[i];
f.m_leaf=psb->m_fdbvt.insert(VolumeOf(f,0),&f);
}
psb->m_fdbvt.optimizeTopDown();
}
//
@@ -910,15 +826,6 @@ static void UpdateConstants(btSoftBody* psb)
btSoftBody::Face& f=psb->m_faces[i];
f.m_ra = AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
}
/* Tetras */
for(int i=0,ni=psb->m_tetras.size();i<ni;++i)
{
btSoftBody::Tetra& t=psb->m_tetras[i];
btSoftBody::Material& m=*t.m_material;
btSoftBody::Node** n=t.m_n;
t.m_rv = VolumeOf(n[0]->m_x,n[1]->m_x,n[2]->m_x,n[3]->m_x);
t.m_c1 = (4*m.m_kVST)/(n[0]->m_im+n[1]->m_im+n[2]->m_im+n[3]->m_im);
}
/* Area's */
btAlignedObjectArray<int> counts;
counts.resize(psb->m_nodes.size(),0);
@@ -1081,9 +988,9 @@ static void ApplyForces(btSoftBody* psb,btScalar dt)
}
//
static void PSolve_Anchors(btSoftBody* psb)
static void PSolve_Anchors(btSoftBody* psb,btScalar kst)
{
const btScalar kAHR=psb->m_cfg.kAHR;
const btScalar kAHR=psb->m_cfg.kAHR*kst;
const btScalar dt=psb->m_sst.sdt;
for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
{
@@ -1101,9 +1008,10 @@ static void PSolve_Anchors(btSoftBody* psb)
}
//
static void PSolve_RContacts(btSoftBody* psb)
static void PSolve_RContacts(btSoftBody* psb,btScalar kst)
{
const btScalar dt=psb->m_sst.sdt;
const btScalar mrg=psb->getCollisionShape()->getMargin();
for(int i=0,ni=psb->m_rcontacts.size();i<ni;++i)
{
const btSoftBody::RContact& c=psb->m_rcontacts[i];
@@ -1114,9 +1022,9 @@ static void PSolve_RContacts(btSoftBody* psb)
const btScalar dn=dot(vr,cti.m_normal);
if(dn<=SIMD_EPSILON)
{
const btScalar dp=dot(c.m_node->m_x,cti.m_normal)+cti.m_offset;
const btScalar dp=btMin(dot(c.m_node->m_x,cti.m_normal)+cti.m_offset,mrg);
const btVector3 fv=vr-cti.m_normal*dn;
const btVector3 impulse=c.m_c0*(vr-fv*c.m_c3+cti.m_normal*(dp*c.m_c4));
const btVector3 impulse=c.m_c0*((vr-fv*c.m_c3+cti.m_normal*(dp*c.m_c4))*kst);
c.m_node->m_x-=impulse*c.m_c2;
c.m_cti.m_body->applyImpulse(impulse,c.m_c1);
}
@@ -1124,7 +1032,7 @@ static void PSolve_RContacts(btSoftBody* psb)
}
//
static void PSolve_SContacts(btSoftBody* psb)
static void PSolve_SContacts(btSoftBody* psb,btScalar)
{
for(int i=0,ni=psb->m_scontacts.size();i<ni;++i)
{
@@ -1156,7 +1064,7 @@ for(int i=0,ni=psb->m_scontacts.size();i<ni;++i)
}
//
static void PSolve_Links(btSoftBody* psb)
static void PSolve_Links(btSoftBody* psb,btScalar kst)
{
for(int i=0,ni=psb->m_links.size();i<ni;++i)
{
@@ -1167,7 +1075,7 @@ static void PSolve_Links(btSoftBody* psb)
btSoftBody::Node& b=*l.m_n[1];
const btVector3 del=b.m_x-a.m_x;
const btScalar len=del.length2();
const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)));
const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst;
a.m_x-=del*(k*a.m_im);
b.m_x+=del*(k*b.m_im);
}
@@ -1175,72 +1083,30 @@ static void PSolve_Links(btSoftBody* psb)
}
//
static void PSolve_Tetras(btSoftBody* psb)
{
for(int i=0,ni=psb->m_tetras.size();i<ni;++i)
{
btSoftBody::Tetra& t=psb->m_tetras[i];
btSoftBody::Node** n=t.m_n;
const btVector3 g0=cross(n[3]->m_x-n[1]->m_x,n[2]->m_x-n[1]->m_x);
const btVector3 g1=cross(n[3]->m_x-n[2]->m_x,n[0]->m_x-n[2]->m_x);
const btVector3 g2=cross(n[3]->m_x-n[0]->m_x,n[1]->m_x-n[0]->m_x);
const btVector3 g3=cross(n[1]->m_x-n[0]->m_x,n[2]->m_x-n[0]->m_x);
const btScalar v1=VolumeOf(n[0]->m_x,n[1]->m_x,n[2]->m_x,n[3]->m_x);
const btScalar k=(t.m_rv-v1)/(g0.length2()+g1.length2()+g2.length2()+g3.length2());
const btScalar j=k*t.m_c1;
n[0]->m_x += g0*j*n[0]->m_im;
n[1]->m_x += g1*j*n[1]->m_im;
n[2]->m_x += g2*j*n[2]->m_im;
n[3]->m_x += g3*j*n[3]->m_im;
}
}
//
static void VSolve_Links(btSoftBody* psb)
static void VSolve_Links(btSoftBody* psb,btScalar kst)
{
for(int i=0,ni=psb->m_links.size();i<ni;++i)
{
btSoftBody::Link& l=psb->m_links[i];
btSoftBody::Node** n=l.m_n;
const btScalar j=-dot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2;
const btScalar j=-dot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst;
n[0]->m_v+= l.m_c3*(j*n[0]->m_im);
n[1]->m_v-= l.m_c3*(j*n[1]->m_im);
}
}
//
static void VSolve_Tetras(btSoftBody* psb)
{
for(int i=0,ni=psb->m_tetras.size();i<ni;++i)
{
btSoftBody::Tetra& t=psb->m_tetras[i];
btSoftBody::Node** n=t.m_n;
const btScalar r= dot(t.m_c0[0],n[0]->m_v)+
dot(t.m_c0[1],n[1]->m_v)+
dot(t.m_c0[2],n[2]->m_v)+
dot(t.m_c0[3],n[3]->m_v);
const btScalar j=r*t.m_c2;
n[0]->m_v += t.m_c0[0]*(j*n[0]->m_im);
n[1]->m_v += t.m_c0[1]*(j*n[1]->m_im);
n[2]->m_v += t.m_c0[2]*(j*n[2]->m_im);
n[3]->m_v += t.m_c0[3]*(j*n[3]->m_im);
}
}
//
static void (* const VSolvers[])(btSoftBody*)= {
VSolve_Links,
VSolve_Tetras,
};
static void (* const VSolvers[])(btSoftBody*,btScalar)= {
VSolve_Links,
};
//
static void (* const PSolvers[])(btSoftBody*)= {
PSolve_Links,
PSolve_Tetras,
PSolve_Anchors,
PSolve_RContacts,
PSolve_SContacts,
};
static void (* const PSolvers[])(btSoftBody*,btScalar)= {
PSolve_Links,
PSolve_Anchors,
PSolve_RContacts,
PSolve_SContacts,
};
//
// btSoftBody
@@ -1262,7 +1128,7 @@ btSoftBody::btSoftBody(btSoftBody::btSoftBodyWorldInfo* worldInfo,int node_count
m_cfg.kDF = (btScalar)0.2;
m_cfg.kMT = 0;
m_cfg.kCHR = (btScalar)1.0;
m_cfg.kKHR = (btScalar)0.5;
m_cfg.kKHR = (btScalar)0.1;
m_cfg.kSHR = (btScalar)1.0;
m_cfg.kAHR = (btScalar)0.7;
m_cfg.maxvolume = (btScalar)1;
@@ -1308,7 +1174,6 @@ btSoftBody::btSoftBody(btSoftBody::btSoftBodyWorldInfo* worldInfo,int node_count
n.m_leaf = m_ndbvt.insert(btDbvt::Volume::FromCR(n.m_x,margin),&n);
n.m_material= pm;
}
m_ndbvt.optimizeTopDown();
UpdateBounds(this);
@@ -1319,7 +1184,7 @@ btSoftBody::~btSoftBody()
{
//for now, delete the internal shape
delete m_collisionShape;
for(int i=0;i<m_materials.size();++i) delete m_materials[i];
for(int i=0;i<m_materials.size();++i) btAlignedFree(m_materials[i]);
}
//
@@ -1368,7 +1233,7 @@ bool btSoftBody::checkFace(int node0,int node1,int node2) const
//
btSoftBody::Material* btSoftBody::appendMaterial()
{
Material* pm=new Material();
Material* pm=new(btAlignedAlloc(sizeof(Material),16)) Material();
if(m_materials.size()>0)
*pm=*m_materials[0];
else
@@ -1430,18 +1295,6 @@ appendNote(text,o,btVector4(w,w,w,0), feature->m_n[0],
feature->m_n[1],
feature->m_n[2]);
}
//
void btSoftBody::appendNote( const char* text,
const btVector3& o,
Tetra* feature)
{
static const btScalar w=1/(btScalar)4;
appendNote(text,o,btVector4(w,w,w,w), feature->m_n[0],
feature->m_n[1],
feature->m_n[2],
feature->m_n[3]);
}
//
void btSoftBody::appendNode( const btVector3& x,btScalar m)
@@ -1525,34 +1378,6 @@ void btSoftBody::appendFace(int node0,int node1,int node2,Material* mat)
m_bUpdateRtCst=true;
}
//
void btSoftBody::appendTetra(int model,Material* mat)
{
Tetra t;
if(model>=0)
t=m_tetras[model];
else
{ ZeroInitialize(t);t.m_material=mat?mat:m_materials[0]; }
m_tetras.push_back(t);
}
//
void btSoftBody::appendTetra(int node0,
int node1,
int node2,
int node3,
Material* mat)
{
appendTetra(-1,mat);
Tetra& t=m_tetras[m_tetras.size()-1];
t.m_n[0] = &m_nodes[node0];
t.m_n[1] = &m_nodes[node1];
t.m_n[2] = &m_nodes[node2];
t.m_n[3] = &m_nodes[node3];
t.m_rv = VolumeOf(t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x);
m_bUpdateRtCst=true;
}
//
void btSoftBody::appendAnchor(int node,btRigidBody* body)
{
@@ -1660,49 +1485,6 @@ void btSoftBody::setTotalDensity(btScalar density)
setTotalMass(getVolume()*density,true);
}
//
void btSoftBody::setVolumeMass(btScalar mass)
{
btAlignedObjectArray<btScalar> ranks;
ranks.resize(m_nodes.size(),0);
for(int i=0;i<m_nodes.size();++i)
{
m_nodes[i].m_im=0;
}
for(int i=0;i<m_tetras.size();++i)
{
const Tetra& t=m_tetras[i];
for(int j=0;j<4;++j)
{
t.m_n[j]->m_im+=btFabs(t.m_rv);
ranks[int(t.m_n[j]-&m_nodes[0])]+=1;
}
}
for(int i=0;i<m_nodes.size();++i)
{
if(m_nodes[i].m_im>0)
{
m_nodes[i].m_im=ranks[i]/m_nodes[i].m_im;
}
}
setTotalMass(mass,false);
}
//
void btSoftBody::setVolumeDensity(btScalar density)
{
btScalar volume=0;
for(int i=0;i<m_tetras.size();++i)
{
const Tetra& t=m_tetras[i];
for(int j=0;j<4;++j)
{
volume+=btFabs(t.m_rv);
}
}
setVolumeMass(volume*density/6);
}
//
void btSoftBody::transform(const btTransform& trs)
{
@@ -1715,7 +1497,6 @@ void btSoftBody::transform(const btTransform& trs)
n.m_n=trs.getBasis()*n.m_n;
m_ndbvt.update(n.m_leaf,btDbvt::Volume::FromCR(n.m_x,margin));
}
m_ndbvt.optimizeTopDown();
UpdateNormals(this);
UpdateBounds(this);
UpdateConstants(this);
@@ -1750,7 +1531,6 @@ void btSoftBody::scale(const btVector3& scl)
n.m_q*=scl;
m_ndbvt.update(n.m_leaf,btDbvt::Volume::FromCR(n.m_x,margin));
}
m_ndbvt.optimizeTopDown();
UpdateNormals(this);
UpdateBounds(this);
UpdateConstants(this);
@@ -1870,34 +1650,31 @@ int btSoftBody::generateBendingConstraints(int distance,Material* mat)
if(adj[IDX(i,j)]==(unsigned)distance)
{
appendLink(i,j,mat);
m_links[m_links.size()-1].m_bbending=1;
++nlinks;
}
}
}
delete[] adj;
delete[] adj;
return(nlinks);
}
return(0);
}
//
int btSoftBody::generateTetrahedralConstraints()
{
/// not implemented
return(0);
}
//
void btSoftBody::randomizeConstraints()
{
unsigned long seed=243703;
#define NEXTRAND (seed=(1664525L*seed+1013904223L)&0xffffffff)
for(int i=0,ni=m_links.size();i<ni;++i)
{
btSwap(m_links[i],m_links[std::rand()%ni]);
btSwap(m_links[i],m_links[NEXTRAND%ni]);
}
for(int i=0,ni=m_faces.size();i<ni;++i)
{
btSwap(m_faces[i],m_faces[std::rand()%ni]);
btSwap(m_faces[i],m_faces[NEXTRAND%ni]);
}
#undef NEXTRAND
}
//
@@ -1907,6 +1684,19 @@ const Node* nbase(&m_nodes[0]);
int ncount(m_nodes.size());
btSymMatrix<int> edges(ncount,-2);
int newnodes=0;
/* Filter out */
for(int i=0;i<m_links.size();++i)
{
Link& l=m_links[i];
if(l.m_bbending)
{
if(!SameSign(ifn->Eval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x)))
{
btSwap(m_links[i],m_links[m_links.size()-1]);
m_links.pop_back();--i;
}
}
}
/* Fill edges */
for(int i=0;i<m_links.size();++i)
{
@@ -1920,16 +1710,6 @@ for(int i=0;i<m_faces.size();++i)
edges(int(f.m_n[1]-nbase),int(f.m_n[2]-nbase))=-1;
edges(int(f.m_n[2]-nbase),int(f.m_n[0]-nbase))=-1;
}
for(int i=0;i<m_tetras.size();++i)
{
Tetra& t=m_tetras[i];
edges(int(t.m_n[0]-nbase),int(t.m_n[1]-nbase))=-1;
edges(int(t.m_n[1]-nbase),int(t.m_n[2]-nbase))=-1;
edges(int(t.m_n[2]-nbase),int(t.m_n[0]-nbase))=-1;
edges(int(t.m_n[0]-nbase),int(t.m_n[3]-nbase))=-1;
edges(int(t.m_n[1]-nbase),int(t.m_n[3]-nbase))=-1;
edges(int(t.m_n[2]-nbase),int(t.m_n[3]-nbase))=-1;
}
/* Intersect */
for(int i=0;i<ncount;++i)
{
@@ -2027,60 +1807,6 @@ for(int i=0;i<m_faces.size();++i)
}
}
}
/* Refine tetras */
static const int edg[]={0,1,1,2,2,0,0,3,1,3,2,3};
static const int apx[]={2,3,0,3,1,3,1,2,2,0,0,1};
for(int i=0;i<m_tetras.size();++i)
{
const Tetra& feat=m_tetras[i];
const int idx[]={ int(feat.m_n[0]-nbase),
int(feat.m_n[1]-nbase),
int(feat.m_n[2]-nbase),
int(feat.m_n[3]-nbase)};
for(int j=0;j<(sizeof(edg)/sizeof(edg[0]));j+=2)
{
const int ia=idx[edg[j]];
const int ib=idx[edg[j+1]];
if((ia<ncount)&&(ib<ncount))
{
const int ni=edges(ia,ib);
const int xa=idx[apx[j]];
const int xb=idx[apx[j+1]];
if(ni!=-1)
{
appendTetra(i);
Tetra* pft[]={ &m_tetras[i],
&m_tetras[m_tetras.size()-1]};
const btScalar sig=Sign(pft[0]->m_rv);
pft[0]->m_n[0]=&m_nodes[ia];
pft[0]->m_n[1]=&m_nodes[xb];
pft[0]->m_n[2]=&m_nodes[xa];
pft[0]->m_n[3]=&m_nodes[ni];
if(Sign(VolumeOf( pft[0]->m_n[0]->m_x,
pft[0]->m_n[1]->m_x,
pft[0]->m_n[2]->m_x,
pft[0]->m_n[3]->m_x))!=sig)
{
btSwap(pft[0]->m_n[0],pft[0]->m_n[1]);
}
pft[1]->m_n[0]=&m_nodes[ib];
pft[1]->m_n[1]=&m_nodes[xa];
pft[1]->m_n[2]=&m_nodes[xb];
pft[1]->m_n[3]=&m_nodes[ni];
if(Sign(VolumeOf( pft[1]->m_n[0]->m_x,
pft[1]->m_n[1]->m_x,
pft[1]->m_n[2]->m_x,
pft[1]->m_n[3]->m_x))!=sig)
{
btSwap(pft[1]->m_n[0],pft[1]->m_n[1]);
}
appendLink(ni,xa,pft[0]->m_material,true);
appendLink(ni,xb,pft[0]->m_material,true);
--i;break;
}
}
}
}
/* Cut */
if(cut)
{
@@ -2145,22 +1871,6 @@ if(cut)
}
}
}
/* Tetras */
for(int i=0,ni=m_tetras.size();i<ni;++i)
{
Node** n= m_tetras[i].m_n;
if( (ifn->Eval(n[0]->m_x)<accurary)&&
(ifn->Eval(n[1]->m_x)<accurary)&&
(ifn->Eval(n[2]->m_x)<accurary)&&
(ifn->Eval(n[3]->m_x)<accurary))
{
for(int j=0;j<4;++j)
{
int cn=cnodes[int(n[j]-nbase)];
if(cn) n[j]=&m_nodes[cn];
}
}
}
/* Clean orphans */
int nnodes=m_nodes.size();
btAlignedObjectArray<int> ranks;
@@ -2174,10 +1884,6 @@ if(cut)
{
for(int j=0;j<3;++j) ranks[int(m_faces[i].m_n[j]-nbase)]++;
}
for(int i=0,ni=m_tetras.size();i<ni;++i)
{
for(int j=0;j<4;++j) ranks[int(m_tetras[i].m_n[j]-nbase)]++;
}
for(int i=0;i<m_links.size();++i)
{
const int id[]={ int(m_links[i].m_n[0]-nbase),
@@ -2318,18 +2024,15 @@ switch(preset)
m_cfg.m_psequence.push_back(ePSolver::Anchors);
m_cfg.m_psequence.push_back(ePSolver::RContacts);
m_cfg.m_psequence.push_back(ePSolver::SContacts);
m_cfg.m_psequence.push_back(ePSolver::Volume);
m_cfg.m_psequence.push_back(ePSolver::Linear);
break;
case eSolverPresets::Velocities:
m_cfg.m_vsequence.push_back(eVSolver::Volume);
m_cfg.m_vsequence.push_back(eVSolver::Linear);
m_cfg.m_psequence.push_back(ePSolver::Anchors);
m_cfg.m_psequence.push_back(ePSolver::RContacts);
m_cfg.m_psequence.push_back(ePSolver::SContacts);
m_cfg.m_dsequence.push_back(ePSolver::Volume);
m_cfg.m_dsequence.push_back(ePSolver::Linear);
break;
}
@@ -2389,65 +2092,36 @@ void btSoftBody::predictMotion(btScalar dt)
}
/* Pose */
UpdatePose(this);
/* Clear contacts */
/* Match */
if(m_pose.m_bframe&&(m_cfg.kMT>0))
{
for(int i=0,ni=m_nodes.size();i<ni;++i)
{
Node& n=m_nodes[i];
if(n.m_im>0)
{
const btVector3 x=m_pose.m_rot*m_pose.m_pos[i]+m_pose.m_com;
n.m_x=Lerp(n.m_x,x,m_cfg.kMT);
}
}
}
/* Clear contacts */
m_rcontacts.resize(0);
m_scontacts.resize(0);
/* Optimize dbvt's */
m_ndbvt.optimizeIncremental(1);
m_fdbvt.optimizeIncremental(1);
}
//
void btSoftBody::solveConstraints()
{
/* Solve velocities */
if(m_cfg.viterations>0)
/* Prepare links */
for(int i=0,ni=m_links.size();i<ni;++i)
{
/* Prepare */
for(int i=0,ni=m_links.size();i<ni;++i)
{
Link& l=m_links[i];
l.m_c3 = l.m_n[1]->m_x-l.m_n[0]->m_x;
l.m_c2 = 1/(l.m_c3.length2()*l.m_c0);
}
for(int i=0,ni=m_tetras.size();i<ni;++i)
{
Tetra& t=m_tetras[i];
Node** n=t.m_n;
t.m_c0[0] = cross(n[3]->m_x-n[1]->m_x,n[2]->m_x-n[1]->m_x);
t.m_c0[1] = cross(n[3]->m_x-n[2]->m_x,n[0]->m_x-n[2]->m_x);
t.m_c0[2] = cross(n[3]->m_x-n[0]->m_x,n[1]->m_x-n[0]->m_x);
t.m_c0[3] = cross(n[1]->m_x-n[0]->m_x,n[2]->m_x-n[0]->m_x);
const btScalar den=t.m_c0[0].length2()+
t.m_c0[1].length2()+
t.m_c0[2].length2()+
t.m_c0[3].length2();
t.m_c2 = -t.m_c1/den;
}
/* Solve */
for(int isolve=0;isolve<m_cfg.viterations;++isolve)
{
for(int iseq=0;iseq<m_cfg.m_vsequence.size();++iseq)
{
VSolvers[m_cfg.m_vsequence[iseq]](this);
}
}
/* Update */
for(int i=0,ni=m_nodes.size();i<ni;++i)
{
Node& n=m_nodes[i];
n.m_x = n.m_q+n.m_v*m_sst.sdt;
}
}
/* Match */
if(m_pose.m_bframe&&(m_cfg.kMT>0))
{
for(int i=0,ni=m_nodes.size();i<ni;++i)
{
Node& n=m_nodes[i];
if(n.m_im>0)
{
const btVector3 x=m_pose.m_rot*m_pose.m_pos[i]+m_pose.m_com;
n.m_x=Lerp(n.m_x,x,m_cfg.kMT);
}
}
Link& l=m_links[i];
l.m_c3 = l.m_n[1]->m_x-l.m_n[0]->m_x;
l.m_c2 = 1/(l.m_c3.length2()*l.m_c0);
}
/* Prepare anchors */
for(int i=0,ni=m_anchors.size();i<ni;++i)
@@ -2463,6 +2137,24 @@ for(int i=0,ni=m_anchors.size();i<ni;++i)
a.m_c2 = m_sst.sdt*a.m_node->m_im;
a.m_body->activate();
}
/* Solve velocities */
if(m_cfg.viterations>0)
{
/* Solve */
for(int isolve=0;isolve<m_cfg.viterations;++isolve)
{
for(int iseq=0;iseq<m_cfg.m_vsequence.size();++iseq)
{
VSolvers[m_cfg.m_vsequence[iseq]](this,1);
}
}
/* Update */
for(int i=0,ni=m_nodes.size();i<ni;++i)
{
Node& n=m_nodes[i];
n.m_x = n.m_q+n.m_v*m_sst.sdt;
}
}
/* Solve positions */
if(m_cfg.piterations>0)
{
@@ -2470,7 +2162,7 @@ if(m_cfg.piterations>0)
{
for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
{
PSolvers[m_cfg.m_psequence[iseq]](this);
PSolvers[m_cfg.m_psequence[iseq]](this,1);
}
}
const btScalar vc=m_sst.isdt*(1-m_cfg.kDP);
@@ -2494,7 +2186,7 @@ if(m_cfg.diterations>0)
{
for(int iseq=0;iseq<m_cfg.m_dsequence.size();++iseq)
{
PSolvers[m_cfg.m_dsequence[iseq]](this);
PSolvers[m_cfg.m_dsequence[iseq]](this,1);
}
}
for(int i=0,ni=m_nodes.size();i<ni;++i)
@@ -2502,7 +2194,7 @@ if(m_cfg.diterations>0)
Node& n=m_nodes[i];
n.m_v += (n.m_x-n.m_q)*vcf;
}
}
}
}
//
@@ -2512,7 +2204,7 @@ for(int isolve=0;isolve<iterations;++isolve)
{
for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
{
PSolvers[m_cfg.m_psequence[iseq]](this);
PSolvers[m_cfg.m_psequence[iseq]](this,1);
}
}
}
@@ -2539,17 +2231,7 @@ switch(m_cfg.collisions&fCollision::RVSmask)
{
struct DoCollide : btDbvt::ICollide
{
virtual void Process(const btDbvt::Node* /*a*/,const btDbvt::Node* /*b*/)
{
}
virtual bool Descent(const btDbvt::Node*)
{
return false;
}
virtual void Process(const btDbvt::Node* leaf)
void Process(const btDbvt::Node* leaf)
{
Node* node=(Node*)leaf->data;
DoNode(*node);
@@ -2608,7 +2290,7 @@ switch(m_cfg.collisions&fCollision::RVSmask)
docollide.prb = prb;
docollide.dynmargin = basemargin+timemargin;
docollide.stamargin = basemargin;
m_ndbvt.collide(volume,&docollide);
btDbvt::collideTV(m_ndbvt.m_root,volume,docollide);
}
break;
}
@@ -2624,15 +2306,6 @@ switch(cf&fCollision::SVSmask)
{
struct DoCollide : btDbvt::ICollide
{
virtual bool Descent(const btDbvt::Node*)
{
return false;
}
virtual void Process(const btDbvt::Node* /*leaf*/)
{
}
void Process(const btDbvt::Node* lnode,
const btDbvt::Node* lface)
{
@@ -2683,14 +2356,16 @@ switch(cf&fCollision::SVSmask)
/* psb0 nodes vs psb1 faces */
docollide.psb[0]=this;
docollide.psb[1]=psb;
docollide.psb[0]->m_ndbvt.collide( &docollide.psb[1]->m_fdbvt,
&docollide);
btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root,
docollide.psb[1]->m_fdbvt.m_root,
docollide);
/* psb1 nodes vs psb0 faces */
docollide.psb[0]=psb;
docollide.psb[1]=this;
docollide.psb[0]->m_ndbvt.collide( &docollide.psb[1]->m_fdbvt,
&docollide);
btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root,
docollide.psb[1]->m_fdbvt.m_root,
docollide);
}
break;
}
}
}

View File

@@ -45,29 +45,31 @@ public:
V_TwoSided, ///Vertex normals are fliped to match velocity
V_OneSided, ///Vertex normals are taken as it is
F_TwoSided, ///Face normals are fliped to match velocity
F_OneSided ///Face normals are taken as it is
F_OneSided, ///Face normals are taken as it is
END
};};
///eVSolver : velocities solvers
struct eVSolver { enum _ {
Linear, ///Linear solver
Volume ///Volume solver
END
};};
///ePSolver : positions solvers
struct ePSolver { enum _ {
Linear, ///Linear solver
Volume, ///Volume solver
Anchors, ///Anchor solver
RContacts, ///Rigid contacts solver
SContacts ///Soft contacts solver
SContacts, ///Soft contacts solver
END
};};
///eSolverPresets
struct eSolverPresets { enum _ {
Positions,
Velocities,
Default = Positions
Default = Positions,
END
};};
///eFeature
@@ -76,7 +78,7 @@ public:
Node,
Link,
Face,
Tetra
END
};};
typedef btAlignedObjectArray<eVSolver::_> tVSolverArray;
@@ -94,14 +96,16 @@ public:
SVSmask = 0x00f0, ///Rigid versus soft mask
VF_SS = 0x0010, ///Vertex vs face soft vs soft handling
/* presets */
Default = SDF_RS
Default = SDF_RS,
END
};};
///fMaterial
struct fMaterial { enum _ {
DebugDraw = 0x0001, /// Enable debug draw
/* presets */
Default = DebugDraw
Default = DebugDraw,
END
};};
//
@@ -120,7 +124,6 @@ public:
/* ImplicitFn */
struct ImplicitFn
{
virtual ~ImplicitFn() {}
virtual btScalar Eval(const btVector3& x)=0;
};
@@ -163,16 +166,13 @@ public:
struct Element
{
void* m_tag; // User data
Element()
{
m_tag=0;
}
Element() : m_tag(0) {}
};
/* Material */
struct Material : Element
{
btScalar m_kLST; // Linear stiffness coefficient [0,1]
btScalar m_kAST; // Area stiffness coefficient [0,1]
btScalar m_kAST; // Area/Angular stiffness coefficient [0,1]
btScalar m_kVST; // Volume stiffness coefficient [0,1]
int m_flags; // Flags
};
@@ -199,7 +199,8 @@ public:
struct Link : Feature
{
Node* m_n[2]; // Node pointers
btScalar m_rl; // Rest length
btScalar m_rl; // Rest length
int m_bbending:1; // Bending link
btScalar m_c0; // (ima+imb)*kLST
btScalar m_c1; // rl^2
btScalar m_c2; // |gradient|^2/c0
@@ -213,16 +214,6 @@ public:
btScalar m_ra; // Rest area
btDbvt::Node* m_leaf; // Leaf data
};
/* Tetra */
struct Tetra : Feature
{
Node* m_n[4]; // Node pointers
btScalar m_rv; // Rest volume
btDbvt::Node* m_leaf; // Leaf data
btVector3 m_c0[4]; // gradients
btScalar m_c1; // (4*kVST)/(im0+im1+im2+im3)
btScalar m_c2; // m_c1/sum(|g0..3|^2)
};
/* RContact */
struct RContact
{
@@ -322,7 +313,6 @@ public:
typedef btAlignedObjectArray<btDbvt::Node*> tLeafArray;
typedef btAlignedObjectArray<Link> tLinkArray;
typedef btAlignedObjectArray<Face> tFaceArray;
typedef btAlignedObjectArray<Tetra> tTetraArray;
typedef btAlignedObjectArray<Anchor> tAnchorArray;
typedef btAlignedObjectArray<RContact> tRContactArray;
typedef btAlignedObjectArray<SContact> tSContactArray;
@@ -342,7 +332,6 @@ public:
tNodeArray m_nodes; // Nodes
tLinkArray m_links; // Links
tFaceArray m_faces; // Faces
tTetraArray m_tetras; // Tetras
tAnchorArray m_anchors; // Anchors
tRContactArray m_rcontacts; // Rigid contacts
tSContactArray m_scontacts; // Soft contacts
@@ -365,12 +354,12 @@ public:
/* Check for existing link */
bool checkLink( int node0,
int node1) const;
bool checkLink( const btSoftBody::Node* node0,
const btSoftBody::Node* node1) const;
bool checkLink( const Node* node0,
const Node* node1) const;
/* Check for existring face */
bool checkFace( int node0,
int node1,
int node2) const;
int node1,
int node2) const;
/* Append material */
Material* appendMaterial();
/* Append note */
@@ -390,9 +379,6 @@ public:
void appendNote( const char* text,
const btVector3& o,
Face* feature);
void appendNote( const char* text,
const btVector3& o,
Tetra* feature);
/* Append node */
void appendNode( const btVector3& x,btScalar m);
/* Append link */
@@ -401,8 +387,8 @@ public:
int node1,
Material* mat=0,
bool bcheckexist=false);
void appendLink( btSoftBody::Node* node0,
btSoftBody::Node* node1,
void appendLink( Node* node0,
Node* node1,
Material* mat=0,
bool bcheckexist=false);
/* Append face */
@@ -411,13 +397,6 @@ public:
int node1,
int node2,
Material* mat=0);
/* Append tetrahedron */
void appendTetra(int model=-1,Material* mat=0);
void appendTetra(int node0,
int node1,
int node2,
int node3,
Material* mat=0);
/* Append anchor */
void appendAnchor( int node,
btRigidBody* body);
@@ -443,10 +422,6 @@ public:
bool fromfaces=false);
/* Set total density */
void setTotalDensity(btScalar density);
/* Set volume mass (using tetrahedrons) */
void setVolumeMass( btScalar mass);
/* Set volume density (using tetrahedrons) */
void setVolumeDensity( btScalar density);
/* Transform */
void transform( const btTransform& trs);
/* Translate */
@@ -463,8 +438,6 @@ public:
/* Generate bending constraints based on distance in the adjency graph */
int generateBendingConstraints( int distance,
Material* mat=0);
/* Generate tetrahedral constraints */
int generateTetrahedralConstraints();
/* Randomize constraints to reduce solver bias */
void randomizeConstraints();
/* Refine */

View File

@@ -15,7 +15,6 @@ subject to the following restrictions:
///btSoftBodyHelpers.cpp by Nathanael Presson
#include "btSoftBody.h"
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
#include <stdio.h>
#include <string.h>
#include "btSoftBodyHelpers.h"
@@ -23,97 +22,98 @@ subject to the following restrictions:
//
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);
idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c);
}
const btVector3& x,btScalar s,const btVector3& c)
{
idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c);
idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c);
idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c);
}
//
static void drawBox( btIDebugDraw* idraw,
const btVector3& mins,
const btVector3& maxs,
const btVector3& color)
const btVector3& mins,
const btVector3& maxs,
const btVector3& color)
{
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);
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)
const btDbvt::Node* node,
int depth,
const btVector3& ncolor,
const btVector3& lcolor,
int mindepth,
int maxdepth)
{
if(node)
if(node)
{
if(node->isinternal()&&((depth<maxdepth)||(maxdepth<0)))
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);
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)
if(depth>=mindepth)
{
const btScalar scl=(btScalar)(node->isinternal()?1:1);
const btVector3 mi=node->volume.Center()-node->volume.Extent()*scl;
const btVector3 mx=node->volume.Center()+node->volume.Extent()*scl;
drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor);
const btScalar scl=(btScalar)(node->isinternal()?1:1);
const btVector3 mi=node->volume.Center()-node->volume.Extent()*scl;
const btVector3 mx=node->volume.Center()+node->volume.Extent()*scl;
drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor);
}
}
}
//
//
static inline btScalar tetravolume(const btVector3& x0,
const btVector3& x1,
const btVector3& x2,
const btVector3& x3)
{
const btVector3 a=x1-x0;
const btVector3 b=x2-x0;
const btVector3 c=x3-x0;
return(dot(a,cross(b,c)));
//
static inline btScalar tetravolume(const btVector3& x0,
const btVector3& x1,
const btVector3& x2,
const btVector3& x3)
{
const btVector3 a=x1-x0;
const btVector3 b=x2-x0;
const btVector3 c=x3-x0;
return(dot(a,cross(b,c)));
}
//
/*
#if 0
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)};
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);
}
*/
}
#endif
//
void btSoftBodyHelpers::Draw( btSoftBody* psb,
btIDebugDraw* idraw,
int drawflags)
btIDebugDraw* idraw,
int drawflags)
{
const btScalar scl=(btScalar)0.1;
const btScalar nscl=scl*5;
@@ -209,32 +209,14 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb,
idraw->drawLine((x[1]-c)*scl+c,(x[2]-c)*scl+c,col);
idraw->drawLine((x[2]-c)*scl+c,(x[0]-c)*scl+c,col);*/
idraw->drawTriangle((x[0]-c)*scl+c,
(x[1]-c)*scl+c,
(x[2]-c)*scl+c,
col,alp);
/*idraw->drawTriangle((x[0]-c)*scl+c,
(x[1]-c)*scl+c,
(x[2]-c)*scl+c,
col,alp);
/*idraw->drawTriangle((x[0]-c)*scl+c,
(x[1]-c)*scl+c,
(x[2]-c)*scl+c,
f.m_n[0]->m_n,f.m_n[1]->m_n,f.m_n[2]->m_n,
col,alp);*/
}
}
/* Tetras */
if(0!=(drawflags&fDrawFlags::Tetras))
{
const btScalar scl=(btScalar)0.8;
const btScalar alp=(btScalar)1;
const btVector3 col((btScalar)0.7,(btScalar)0.7,(btScalar)0.7);
for(int i=0;i<psb->m_tetras.size();++i)
{
const btSoftBody::Tetra& t=psb->m_tetras[i];
if(0==(t.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
const btVector3 x[]={t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x};
const btVector3 c=(x[0]+x[1]+x[2]+x[3])/4;
idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[2]-c)*scl+c,col,alp);
idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
idraw->drawTriangle((x[1]-c)*scl+c,(x[2]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
idraw->drawTriangle((x[2]-c)*scl+c,(x[0]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
f.m_n[0]->m_n,f.m_n[1]->m_n,f.m_n[2]->m_n,
col,alp);*/
}
}
/* Notes */
@@ -245,21 +227,20 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb,
const btSoftBody::Note& n=psb->m_notes[i];
btVector3 p=n.m_offset;
for(int j=0;j<n.m_rank;++j)
{
{
p+=n.m_nodes[j]->m_x*n.m_coords[j];
}
}
idraw->draw3dText(p,n.m_text);
}
}
}
#if 0
//
void btSoftBodyHelpers::DrawInfos( btSoftBody* psb,
btIDebugDraw* idraw,
bool masses,
bool areas,
bool /*stress*/)
btIDebugDraw* idraw,
bool masses,
bool areas,
bool /*stress*/)
{
for(int i=0;i<psb->m_nodes.size();++i)
{
@@ -279,29 +260,28 @@ void btSoftBodyHelpers::DrawInfos( btSoftBody* psb,
if(text[0]) idraw->draw3dText(n.m_x,text);
}
}
#endif
//
void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb,
btIDebugDraw* idraw,
int mindepth,
int maxdepth)
btIDebugDraw* idraw,
int mindepth,
int maxdepth)
{
drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,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)
btIDebugDraw* idraw,
int mindepth,
int maxdepth)
{
drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,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)
btIDebugDraw* idraw)
{
if(psb->m_pose.m_bframe)
{
@@ -325,9 +305,9 @@ void btSoftBodyHelpers::DrawFrame( btSoftBody* psb,
//
btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBody::btSoftBodyWorldInfo& worldInfo, const btVector3& from,
const btVector3& to,
int res,
int fixeds)
const btVector3& to,
int res,
int fixeds)
{
/* Create nodes */
const int r=res+2;
@@ -355,13 +335,13 @@ btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBody::btSoftBodyWorldInfo& wor
//
btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& corner00,
const btVector3& corner10,
const btVector3& corner01,
const btVector3& corner11,
int resx,
int resy,
int fixeds,
bool gendiags)
const btVector3& corner10,
const btVector3& corner01,
const btVector3& corner11,
int resx,
int resy,
int fixeds,
bool gendiags)
{
#define IDX(_x_,_y_) ((_y_)*rx+(_x_))
/* Create nodes */
@@ -430,8 +410,8 @@ btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBody::btSoftBodyWorldInfo& wor
//
btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& center,
const btVector3& radius,
int res)
const btVector3& radius,
int res)
{
struct Hammersley
{
@@ -462,8 +442,8 @@ btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBody::btSoftBodyWorldInfo&
//
btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btScalar* vertices,
const int* triangles,
int ntriangles)
const int* triangles,
int ntriangles)
{
int maxidx=0;
for(int i=0,ni=ntriangles*3;i<ni;++i)
@@ -502,20 +482,20 @@ btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBody::btSoftBodyWorldInf
//
btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBody::btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
int nvertices)
int nvertices)
{
HullDesc hdsc(QF_TRIANGLES,static_cast<unsigned int>(nvertices),vertices);
HullDesc hdsc(QF_TRIANGLES,nvertices,vertices);
HullResult hres;
HullLibrary hlib;/*??*/
hdsc.mMaxVertices=static_cast<unsigned int>(nvertices);
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[]={ static_cast<int>(hres.m_Indices[i*3+0]),
static_cast<int>(hres.m_Indices[i*3+1]),
static_cast<int>(hres.m_Indices[i*3+2])};
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]);
if(idx[1]<idx[2]) psb->appendLink( idx[1],idx[2]);
if(idx[2]<idx[0]) psb->appendLink( idx[2],idx[0]);
@@ -524,156 +504,4 @@ btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBody::btSoftBodyWorld
hlib.ReleaseResult(hres);
psb->randomizeConstraints();
return(psb);
}
#if BT_SOFTBODY_USE_STL
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <stdio.h>
//
void btSoftBodyHelpers::ExportAsSMeshFile(btSoftBody* psb,
const char* filename)
{
std::ofstream output(filename);
output << psb->m_nodes.size() << " " << 3 << " " << 0 << " " << 0 << "\n";
for(int i=0;i<psb->m_nodes.size();++i)
{
const btSoftBody::Node& n=psb->m_nodes[i];
output << i << " "
<< n.m_x.x() << " "
<< n.m_x.y() << " "
<< n.m_x.z() << "\n";
}
output << psb->m_faces.size() << " " << 1 << "\n";
for(int i=0;i<psb->m_faces.size();++i)
{
const btSoftBody::Node* b=&psb->m_nodes[0];
const btSoftBody::Face& f=psb->m_faces[i];
output << 3 << " "
<< int(f.m_n[0]-b) << " "
<< int(f.m_n[1]-b) << " "
<< int(f.m_n[2]-b) << " "
<< 1 << "\n";
}
output << 0 << "\n";
output << 0 << "\n";
output.close();
}
/* Create from TetGen .ele, .face, .node files */
btSoftBody* btSoftBodyHelpers::CreateFromTetGenFile(btSoftBody::btSoftBodyWorldInfo& worldInfo,
const char* ele,
const char* face,
const char* node,
bool bfacelinks,
bool btetralinks,
bool bfacesfromtetras)
{
std::ifstream efile(ele?ele:"");
std::ifstream ffile(face?face:"");
std::ifstream nfile(node);
std::string edata;
std::string fdata;
std::string ndata;
if(efile.good()) while(!efile.eof()) edata+=efile.get();
if(ffile.good()) while(!ffile.eof()) fdata+=ffile.get();
if(nfile.good()) while(!nfile.eof()) ndata+=nfile.get();
efile.close();
ffile.close();
nfile.close();
return(CreateFromTetGenData(worldInfo,edata.c_str(),fdata.c_str(),ndata.c_str(),
bfacelinks,btetralinks,bfacesfromtetras));
}
/* Create from TetGen .ele, .face, .node data */
btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBody::btSoftBodyWorldInfo& worldInfo,
const char* ele,
const char* face,
const char* node,
bool bfacelinks,
bool btetralinks,
bool bfacesfromtetras)
{
std::istringstream se(ele?ele:"");
std::istringstream sf(face?face:"");
std::istringstream sn(node?node:"");
btAlignedObjectArray<btVector3> pos;
int nnode=0;
int ndims=0;
int nattrb=0;
int hasbounds=0;
sn>>nnode;sn>>ndims;sn>>nattrb;sn>>hasbounds;
pos.resize(nnode);
for(int i=0;i<pos.size();++i)
{
int index=0;
int bound=0;
btScalar x,y,z,a;
sn>>index;
sn>>x;sn>>y;sn>>z;
for(int j=0;j<nattrb;++j) sn>>a;
if(hasbounds) sn>>bound;
pos[index].setX(x);
pos[index].setY(y);
pos[index].setZ(z);
}
btSoftBody* psb=new btSoftBody(&worldInfo,nnode,&pos[0],0);
if(face&&face[0])
{
int nface=0;
sf>>nface;sf>>hasbounds;
for(int i=0;i<nface;++i)
{
int index=0;
int bound=0;
int ni[3];
sf>>index;
sf>>ni[0];sf>>ni[1];sf>>ni[2];
sf>>bound;
psb->appendFace(ni[0],ni[1],ni[2]);
if(btetralinks)
{
psb->appendLink(ni[0],ni[1],0,true);
psb->appendLink(ni[1],ni[2],0,true);
psb->appendLink(ni[2],ni[0],0,true);
}
}
}
if(ele&&ele[0])
{
int ntetra=0;
int ncorner=0;
int neattrb=0;
se>>ntetra;se>>ncorner;se>>neattrb;
for(int i=0;i<ntetra;++i)
{
int index=0;
int ni[4],a;
se>>index;
se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3];
for(int j=0;j<neattrb;++j) se>>a;
psb->appendTetra(ni[0],ni[1],ni[2],ni[3]);
if(btetralinks)
{
psb->appendLink(ni[0],ni[1],0,true);
psb->appendLink(ni[1],ni[2],0,true);
psb->appendLink(ni[2],ni[0],0,true);
psb->appendLink(ni[0],ni[3],0,true);
psb->appendLink(ni[1],ni[3],0,true);
psb->appendLink(ni[2],ni[3],0,true);
}
}
}
printf("Nodes: %u\r\n",psb->m_nodes.size());
printf("Links: %u\r\n",psb->m_links.size());
printf("Faces: %u\r\n",psb->m_faces.size());
printf("Tetras: %u\r\n",psb->m_tetras.size());
return(psb);
}
#endif
}

View File

@@ -18,9 +18,6 @@ subject to the following restrictions:
#include "btSoftBody.h"
//Can't enable this, Bullet doesn't use STL
//#define BT_SOFTBODY_USE_STL 1
//
// Helpers
//
@@ -37,7 +34,7 @@ struct fDrawFlags { enum _ {
Notes = 0x0080,
/* presets */
Std = Links+Faces+Tetras+Anchors+Notes,
StdTetra = Std-Faces+Tetras
StdTetra = Std-Faces+Tetras,
};};
struct btSoftBodyHelpers
@@ -46,14 +43,12 @@ struct btSoftBodyHelpers
static void Draw( btSoftBody* psb,
btIDebugDraw* idraw,
int drawflags=fDrawFlags::Std);
#if 0
/* Draw body infos */
static void DrawInfos( btSoftBody* psb,
btIDebugDraw* idraw,
bool masses,
bool areas,
bool stress);
#endif
/* Draw node tree */
static void DrawNodeTree( btSoftBody* psb,
btIDebugDraw* idraw,
@@ -97,27 +92,6 @@ struct btSoftBodyHelpers
static btSoftBody* CreateFromConvexHull( btSoftBody::btSoftBodyWorldInfo& worldInfo,
const btVector3* vertices,
int nvertices);
#if BT_SOFTBODY_USE_STL
/* Export TetGen compatible .smesh file */
static void ExportAsSMeshFile( btSoftBody* psb,
const char* filename);
/* Create from TetGen .ele, .face, .node files */
static btSoftBody* CreateFromTetGenFile( btSoftBody::btSoftBodyWorldInfo& worldInfo,
const char* ele,
const char* face,
const char* node,
bool bfacelinks,
bool btetralinks,
bool bfacesfromtetras);
/* Create from TetGen .ele, .face, .node data */
static btSoftBody* CreateFromTetGenData( btSoftBody::btSoftBodyWorldInfo& worldInfo,
const char* ele,
const char* face,
const char* node,
bool bfacelinks,
bool btetralinks,
bool bfacesfromtetras);
#endif
};
#endif //SOFT_BODY_HELPERS_H