Added example of tetrahedral (volumetric) softbodies
Keep camera distance positive when using mouse zoom Updated autogenerated msvc projectfiles Added glut 64 bit support
This commit is contained in:
@@ -305,6 +305,34 @@ 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, bool disableCollisionBetweenLinkedBodies)
|
||||
{
|
||||
@@ -490,6 +518,49 @@ 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)
|
||||
{
|
||||
|
||||
@@ -220,6 +220,16 @@ public:
|
||||
btScalar m_ra; // Rest area
|
||||
btDbvtNode* m_leaf; // Leaf data
|
||||
};
|
||||
/* Tetra */
|
||||
struct Tetra : Feature
|
||||
{
|
||||
Node* m_n[4]; // Node pointers
|
||||
btScalar m_rv; // Rest volume
|
||||
btDbvtNode* 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
|
||||
{
|
||||
@@ -574,6 +584,7 @@ public:
|
||||
typedef btAlignedObjectArray<btDbvtNode*> 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;
|
||||
@@ -594,6 +605,7 @@ 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
|
||||
@@ -681,6 +693,15 @@ public:
|
||||
int node1,
|
||||
int node2,
|
||||
Material* mat=0);
|
||||
void appendTetra(int model,Material* mat);
|
||||
//
|
||||
void appendTetra(int node0,
|
||||
int node1,
|
||||
int node2,
|
||||
int node3,
|
||||
Material* mat=0);
|
||||
|
||||
|
||||
/* Append anchor */
|
||||
void appendAnchor( int node,
|
||||
btRigidBody* body, bool disableCollisionBetweenLinkedBodies=false);
|
||||
@@ -718,6 +739,10 @@ 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 */
|
||||
|
||||
@@ -310,6 +310,26 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb,
|
||||
idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1));
|
||||
}
|
||||
}
|
||||
|
||||
/* Tetras */
|
||||
if(0!=(drawflags&fDrawFlags::Tetras))
|
||||
{
|
||||
const btScalar scl=(btScalar)0.8;
|
||||
const btScalar alp=(btScalar)1;
|
||||
const btVector3 col((btScalar)0.7,(btScalar)0.7,(btScalar)0.7);
|
||||
for(int i=0;i<psb->m_tetras.size();++i)
|
||||
{
|
||||
const btSoftBody::Tetra& t=psb->m_tetras[i];
|
||||
if(0==(t.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
|
||||
const btVector3 x[]={t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x};
|
||||
const btVector3 c=(x[0]+x[1]+x[2]+x[3])/4;
|
||||
idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[2]-c)*scl+c,col,alp);
|
||||
idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
|
||||
idraw->drawTriangle((x[1]-c)*scl+c,(x[2]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
|
||||
idraw->drawTriangle((x[2]-c)*scl+c,(x[0]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Notes */
|
||||
if(0!=(drawflags&fDrawFlags::Notes))
|
||||
{
|
||||
@@ -857,3 +877,130 @@ btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldI
|
||||
psb->randomizeConstraints();
|
||||
return(psb);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int nextLine(const char* buffer)
|
||||
{
|
||||
int numBytesRead=0;
|
||||
|
||||
while (*buffer != '\n')
|
||||
{
|
||||
buffer++;
|
||||
numBytesRead++;
|
||||
}
|
||||
|
||||
|
||||
if (buffer[0]==0x0a)
|
||||
{
|
||||
buffer++;
|
||||
numBytesRead++;
|
||||
}
|
||||
return numBytesRead;
|
||||
}
|
||||
|
||||
/* Create from TetGen .ele, .face, .node data */
|
||||
btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo,
|
||||
const char* ele,
|
||||
const char* face,
|
||||
const char* node,
|
||||
bool bfacelinks,
|
||||
bool btetralinks,
|
||||
bool bfacesfromtetras)
|
||||
{
|
||||
btAlignedObjectArray<btVector3> pos;
|
||||
int nnode=0;
|
||||
int ndims=0;
|
||||
int nattrb=0;
|
||||
int hasbounds=0;
|
||||
int result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
|
||||
result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
|
||||
node += nextLine(node);
|
||||
|
||||
pos.resize(nnode);
|
||||
for(int i=0;i<pos.size();++i)
|
||||
{
|
||||
int index=0;
|
||||
//int bound=0;
|
||||
float x,y,z,a;
|
||||
sscanf(node,"%d %f %f %f",&index,&x,&y,&z);
|
||||
|
||||
// sn>>index;
|
||||
// sn>>x;sn>>y;sn>>z;
|
||||
node += nextLine(node);
|
||||
|
||||
//for(int j=0;j<nattrb;++j)
|
||||
// sn>>a;
|
||||
|
||||
//if(hasbounds)
|
||||
// sn>>bound;
|
||||
|
||||
pos[index].setX(btScalar(x));
|
||||
pos[index].setY(btScalar(y));
|
||||
pos[index].setZ(btScalar(z));
|
||||
}
|
||||
btSoftBody* psb=new btSoftBody(&worldInfo,nnode,&pos[0],0);
|
||||
#if 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(ele&&ele[0])
|
||||
{
|
||||
int ntetra=0;
|
||||
int ncorner=0;
|
||||
int neattrb=0;
|
||||
sscanf(ele,"%d %d %d",&ntetra,&ncorner,&neattrb);
|
||||
ele += nextLine(ele);
|
||||
|
||||
//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];
|
||||
sscanf(ele,"%d %d %d %d %d",&index,&ni[0],&ni[1],&ni[2],&ni[3]);
|
||||
ele+=nextLine(ele);
|
||||
//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);
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,28 @@ struct btSoftBodyHelpers
|
||||
static btSoftBody* CreateFromConvexHull( btSoftBodyWorldInfo& worldInfo,
|
||||
const btVector3* vertices,
|
||||
int nvertices);
|
||||
|
||||
|
||||
/* Export TetGen compatible .smesh file */
|
||||
static void ExportAsSMeshFile( btSoftBody* psb,
|
||||
const char* filename);
|
||||
/* Create from TetGen .ele, .face, .node files */
|
||||
static btSoftBody* CreateFromTetGenFile( 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( btSoftBodyWorldInfo& worldInfo,
|
||||
const char* ele,
|
||||
const char* face,
|
||||
const char* node,
|
||||
bool bfacelinks,
|
||||
bool btetralinks,
|
||||
bool bfacesfromtetras);
|
||||
|
||||
};
|
||||
|
||||
#endif //SOFT_BODY_HELPERS_H
|
||||
|
||||
Reference in New Issue
Block a user