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

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

File diff suppressed because it is too large Load Diff

View File

@@ -14,8 +14,8 @@ subject to the following restrictions:
*/
///btSoftBody implementation by Nathanael Presson
#ifndef _312AEEF3_52DA_4ff6_B804_FCF937182E46_
#define _312AEEF3_52DA_4ff6_B804_FCF937182E46_
#ifndef _BT_SOFT_BODY_H
#define _BT_SOFT_BODY_H
#include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btPoint3.h"
@@ -23,83 +23,116 @@ subject to the following restrictions:
#include "LinearMath/btIDebugDraw.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
//
// btSoftBody
//
struct btSoftBody
{
#include "BulletCollision/CollisionShapes/btConcaveShape.h"
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
#include "BulletDynamics/SoftBody/btSparseSDF.h"
class btBroadphaseInterface;
class btCollisionDispatcher;
/// btSoftBody is work-in-progress
struct btSoftBody : public btCollisionObject
{
//
// Enumerations
//
/* eLType */
///eLType
struct eLType { enum _ {
Structural, /* Master constraints */
Bending, /* Secondary constraints */
Structural, ///Master constraints
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 */
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 */
V_Point, ///Vertex normals are oriented toward velocity
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
};};
//
// Interfaces
//
/* ISoftBody */
struct ISoftBody
{
struct sCti
{
btRigidBody* m_body; /* Rigid body */
btVector3 m_normal; /* Outward normal */
btScalar m_offset; /* Offset from origin */
};
struct sMedium
{
btVector3 m_velocity; /* Velocity */
btScalar m_pressure; /* Pressure */
btScalar m_density; /* Density */
};
virtual void Attach(btSoftBody*)
{}
virtual void Detach(btSoftBody*)
{ delete this; }
virtual void StartCollide( const btVector3& /*minbounds*/,
const btVector3& /*maxbounds*/)
{}
virtual bool CheckContact (const btVector3& /*position*/,
sCti& /*contact*/)
{ return(false); }
virtual void EndCollide()
{}
virtual void EvaluateMedium( const btVector3& /*position*/,
sMedium& medium)
{ medium.m_velocity=btVector3(0,0,0);
medium.m_pressure=0;
medium.m_density=0; }
};
struct btSoftBodyWorldInfo
{
btScalar air_density;
btScalar water_density;
btScalar water_offset;
btVector3 water_normal;
btBroadphaseInterface* m_broadphase;
btCollisionDispatcher* m_dispatcher;
btSparseSdf<3> m_sparsesdf;
};
//reference or copy?
btSoftBodyWorldInfo& m_worldInfo;
///constructor
btSoftBody(btSoftBody::btSoftBodyWorldInfo& worldInfo,int node_count,
const btVector3* x,
const btScalar* m);
///sCti is Softbody contact info
struct sCti
{
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)
{
medium.m_velocity=btVector3(0,0,0);
medium.m_pressure=0;
medium.m_density=0;
}
//
// Internal types
//
typedef btAlignedObjectArray<btScalar> tScalarArray;
typedef btAlignedObjectArray<btVector3> tVector3Array;
/* 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
@@ -108,47 +141,47 @@ struct btSoftBody
btScalar m_im; // 1/mass
btScalar m_area; // Area
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
eLType::_ m_type; // Link type
};
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
};
};
/* Contact */
struct Contact
{
ISoftBody::sCti m_cti; // Contact infos
{
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
};
};
/* 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
};
};
/* Pose */
struct Pose
{
{
bool m_bvolume; // Is valid
bool m_bframe; // Is frame
btScalar m_volume; // Rest volume
@@ -156,11 +189,11 @@ struct btSoftBody
tScalarArray m_wgh; // Weights
btVector3 m_com; // COM
btMatrix3x3 m_trs; // Transform
};
};
/* Config */
struct Config
{
eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point)
{
btSoftBody::eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point)
btScalar kLST; // Linear stiffness coefficient [0,1]
btScalar kDP; // Damping coefficient [0,1]
btScalar kDG; // Drag coefficient [0,+inf]
@@ -178,93 +211,176 @@ struct btSoftBody
int iterations; // Solver iterations
bool becollide; // Enable external collisions
bool bscollide; // Enable self collisions
};
};
//
// Typedef's
//
typedef btAlignedObjectArray<Node> tNodeArray;
typedef btAlignedObjectArray<Link> tLinkArray;
typedef btAlignedObjectArray<Face> tFaceArray;
typedef btAlignedObjectArray<Anchor> tAnchorArray;
typedef btAlignedObjectArray<Contact> tContactArray;
//
// Fields
//
Config m_cfg; // Configuration
Pose m_pose; // Pose
ISoftBody* m_isb; // ISoftBody
void* m_tag; // User data
tNodeArray m_nodes; // Nodes
tLinkArray m_links; // Links
tFaceArray m_faces; // Faces
//////////////////////
///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
//
// Api
//
/* Create a soft body */
static btSoftBody* Create( ISoftBody* isoftbody,
int node_count,
const btVector3* x=0,
const btScalar* m=0);
/* Delete a body */
void Delete();
/* Check for existing link */
bool CheckLink( int node0,
int node1) const;
int node1) const;
bool CheckLink( const btSoftBody::Node* node0,
const btSoftBody::Node* node1) const;
const btSoftBody::Node* node1) const;
/* Check for existring face */
bool CheckFace( int node0,
int node1,
int node2) const;
int node1,
int node2) const;
/* Append link */
void AppendLink( int node0,
int node1,
btScalar kST,
btSoftBody::eLType::_ type,
bool bcheckexist=false);
int node1,
btScalar kST,
btSoftBody::eLType::_ type,
bool bcheckexist=false);
void AppendLink( btSoftBody::Node* node0,
btSoftBody::Node* node1,
btScalar kST,
btSoftBody::eLType::_ type,
bool bcheckexist=false);
btSoftBody::Node* node1,
btScalar kST,
btSoftBody::eLType::_ type,
bool bcheckexist=false);
/* Append face */
void AppendFace( int node0,
int node1,
int node2);
int node1,
int node2);
/* Append anchor */
void AppendAnchor( int node,
btRigidBody* body);
btRigidBody* body);
/* Add force (or gravity) to the entire body */
void AddForce( const btVector3& force);
/* Add force (or gravity) to a node of the body */
void AddForce( const btVector3& force,
int node);
int node);
/* Add velocity to the entire body */
void AddVelocity( const btVector3& velocity);
/* Add velocity to a node of the body */
void AddVelocity( const btVector3& velocity,
int node);
int node);
/* Set mass */
void SetMass( int node,
btScalar mass);
btScalar mass);
/* Get mass */
btScalar GetMass( int node) const;
/* Get total mass */
btScalar GetTotalMass() const;
/* Set total mass (weighted by previous masses) */
void SetTotalMass( btScalar mass,
bool fromfaces=false);
bool fromfaces=false);
/* Set total density */
void SetTotalDensity(btScalar density);
/* Transform */
@@ -273,84 +389,30 @@ struct btSoftBody
void Scale( const btVector3& scl);
/* Set current state as pose */
void SetPose( bool bvolume,
bool bframe);
bool bframe);
/* Return the volume */
btScalar GetVolume() const;
/* Generate bending constraints based on distance in the adjency graph */
int GenerateBendingConstraints( int distance,
btScalar stiffness);
btScalar stiffness);
/* Randomize constraints to reduce solver bias */
void RandomizeConstraints();
/* Ray casting */
btScalar Raycast( const btVector3& org,
const btVector3& dir) const;
const btVector3& dir) const;
/* Step */
void Step( btScalar dt);
};
//
// Helpers
//
/* fDrawFlags */
struct fDrawFlags { enum _ {
Nodes = 0x0001,
SLinks = 0x0002,
BLinks = 0x0004,
Faces = 0x0008,
Tetras = 0x0010,
Normals = 0x0020,
Contacts = 0x0040,
Anchors = 0x0080,
/* presets */
Links = SLinks+BLinks,
Std = SLinks+Faces+Anchors,
StdTetra = Std-Faces+Tetras,
};};
void updateBounds();
/* Draw body */
void Draw( btSoftBody* psb,
btIDebugDraw* idraw,
int drawflags=fDrawFlags::Std);
/* Draw body infos */
void DrawInfos( btSoftBody* psb,
btIDebugDraw* idraw,
bool masses,
bool areas,
bool stress);
/* Draw rigid frame */
void DrawFrame( btSoftBody* psb,
btIDebugDraw* idraw);
/* Create a rope */
btSoftBody* CreateRope( btSoftBody::ISoftBody* isoftbody,
const btVector3& from,
const btVector3& to,
int res,
int fixeds);
/* Create a patch */
btSoftBody* CreatePatch( btSoftBody::ISoftBody* isoftbody,
const btVector3& corner00,
const btVector3& corner10,
const btVector3& corner01,
const btVector3& corner11,
int resx,
int resy,
int fixeds,
bool gendiags);
/* Create an ellipsoid */
btSoftBody* CreateEllipsoid(btSoftBody::ISoftBody* isoftbody,
const btVector3& center,
const btVector3& radius,
int res);
/* Create from convex-hull */
btSoftBody* CreateFromConvexHull( btSoftBody::ISoftBody* isoftbody,
const btVector3* vertices,
int nvertices);
/* Create from trimesh */
btSoftBody* CreateFromTriMesh( btSoftBody::ISoftBody* isoftbody,
const btScalar* vertices,
const int* triangles,
int ntriangles);
void updateTransform()
{
updateBounds();
}
#endif
};
#endif //_BT_SOFT_BODY_H

View File

@@ -17,73 +17,69 @@ subject to the following restrictions:
#include "btSoftBody.h"
#include <stdio.h>
#include <string.h>
namespace btsoftbody_internals
{
#include "btSoftBodyHelpers.h"
//
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);
}
//
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);
}
}
using namespace btsoftbody_internals;
//
void Draw( btSoftBody* psb,
btIDebugDraw* idraw,
int drawflags)
{
const btScalar scl=(btScalar)0.1;
const btScalar nscl=scl*5;
const btScalar alpha=(btScalar)0.5;
const btVector3 scolor=btVector3(0,0,0);
const btVector3 bcolor=btVector3(1,1,0);
const btVector3 ncolor=btVector3(1,1,1);
const btVector3 ccolor=btVector3(1,0,0);
/* Nodes */
if(0!=(drawflags&fDrawFlags::Nodes))
void btSoftBodyHelpers::drawVertex( btIDebugDraw* idraw,
const btVector3& x,btScalar s,const btVector3& c)
{
for(int i=0;i<psb->m_nodes.size();++i)
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);
}
//
btVector3 btSoftBodyHelpers::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,
btIDebugDraw* idraw,
int drawflags)
{
const btScalar scl=(btScalar)0.1;
const btScalar nscl=scl*5;
const btScalar alpha=(btScalar)0.5;
const btVector3 scolor=btVector3(0,0,0);
const btVector3 bcolor=btVector3(1,1,0);
const btVector3 ncolor=btVector3(1,1,1);
const btVector3 ccolor=btVector3(1,0,0);
/* Nodes */
if(0!=(drawflags&fDrawFlags::Nodes))
{
for(int i=0;i<psb->getNodes().size();++i)
{
const btSoftBody::Node& n=psb->m_nodes[i];
idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0));
idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0));
idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1));
const btSoftBody::Node& n=psb->getNodes()[i];
idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0));
idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0));
idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1));
}
}
/* Links */
if(0!=(drawflags&fDrawFlags::Links))
/* Links */
if(0!=(drawflags&fDrawFlags::Links))
{
for(int i=0;i<psb->m_links.size();++i)
for(int i=0;i<psb->getLinks().size();++i)
{
const btSoftBody::Link& l=psb->m_links[i];
switch(l.m_type)
const btSoftBody::Link& l=psb->getLinks()[i];
switch(l.m_type)
{
case btSoftBody::eLType::Structural:
if(0!=(drawflags&fDrawFlags::SLinks)) idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,scolor);break;
@@ -92,308 +88,304 @@ if(0!=(drawflags&fDrawFlags::Links))
}
}
}
/* Normals */
if(0!=(drawflags&fDrawFlags::Normals))
/* Normals */
if(0!=(drawflags&fDrawFlags::Normals))
{
for(int i=0;i<psb->m_nodes.size();++i)
for(int i=0;i<psb->getNodes().size();++i)
{
const btSoftBody::Node& n=psb->m_nodes[i];
const btVector3 d=n.m_n*nscl;
idraw->drawLine(n.m_x,n.m_x+d,ncolor);
idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5);
const btSoftBody::Node& n=psb->getNodes()[i];
const btVector3 d=n.m_n*nscl;
idraw->drawLine(n.m_x,n.m_x+d,ncolor);
idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5);
}
}
/* Contacts */
if(0!=(drawflags&fDrawFlags::Contacts))
/* Contacts */
if(0!=(drawflags&fDrawFlags::Contacts))
{
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)
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)
{
const btSoftBody::Contact& c=psb->m_contacts[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();
const btVector3 y=cross(x,c.m_cti.m_normal).normalized();
idraw->drawLine(o-x*nscl,o+x*nscl,ccolor);
idraw->drawLine(o-y*nscl,o+y*nscl,ccolor);
idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0));
const btSoftBody::Contact& c=psb->m_contacts[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();
const btVector3 y=cross(x,c.m_cti.m_normal).normalized();
idraw->drawLine(o-x*nscl,o+x*nscl,ccolor);
idraw->drawLine(o-y*nscl,o+y*nscl,ccolor);
idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0));
}
}
/* Anchors */
if(0!=(drawflags&fDrawFlags::Anchors))
/* Anchors */
if(0!=(drawflags&fDrawFlags::Anchors))
{
for(int i=0;i<psb->m_anchors.size();++i)
for(int i=0;i<psb->m_anchors.size();++i)
{
const btSoftBody::Anchor& a=psb->m_anchors[i];
const btVector3 q=a.m_body->getWorldTransform()*a.m_local;
drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0));
drawVertex(idraw,q,0.25,btVector3(0,1,0));
idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1));
const btSoftBody::Anchor& a=psb->m_anchors[i];
const btVector3 q=a.m_body->getWorldTransform()*a.m_local;
drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0));
drawVertex(idraw,q,0.25,btVector3(0,1,0));
idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1));
}
for(int i=0;i<psb->m_nodes.size();++i)
for(int i=0;i<psb->getNodes().size();++i)
{
const btSoftBody::Node& n=psb->m_nodes[i];
if(n.m_im<=0)
const btSoftBody::Node& n=psb->getNodes()[i];
if(n.m_im<=0)
{
drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0));
drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0));
}
}
}
/* Faces */
if(0!=(drawflags&fDrawFlags::Faces))
/* Faces */
if(0!=(drawflags&fDrawFlags::Faces))
{
const btScalar scl=(btScalar)0.7;
const btScalar alp=(btScalar)1;
const btVector3 col(0,(btScalar)0.7,0);
for(int i=0;i<psb->m_faces.size();++i)
const btScalar scl=(btScalar)0.7;
const btScalar alp=(btScalar)1;
const btVector3 col(0,(btScalar)0.7,0);
for(int i=0;i<psb->getFaces().size();++i)
{
const btSoftBody::Face& f=psb->m_faces[i];
const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x};
const btVector3 c=(x[0]+x[1]+x[2])/3;
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);
const btSoftBody::Face& f=psb->getFaces()[i];
const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x};
const btVector3 c=(x[0]+x[1]+x[2])/3;
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);
}
}
}
//
void DrawInfos( btSoftBody* psb,
btIDebugDraw* idraw,
bool masses,
bool areas,
bool stress)
void btSoftBodyHelpers::DrawInfos( btSoftBody* psb,
btIDebugDraw* idraw,
bool masses,
bool areas,
bool stress)
{
for(int i=0;i<psb->m_nodes.size();++i)
for(int i=0;i<psb->getNodes().size();++i)
{
const btSoftBody::Node& n=psb->m_nodes[i];
char text[2048]={0};
char buff[1024];
if(masses)
const btSoftBody::Node& n=psb->getNodes()[i];
char text[2048]={0};
char buff[1024];
if(masses)
{
sprintf(buff," M(%.2f)",1/n.m_im);
strcat(text,buff);
sprintf(buff," M(%.2f)",1/n.m_im);
strcat(text,buff);
}
if(areas)
if(areas)
{
sprintf(buff," A(%.2f)",n.m_area);
strcat(text,buff);
sprintf(buff," A(%.2f)",n.m_area);
strcat(text,buff);
}
if(text[0]) idraw->draw3dText(n.m_x,text);
if(text[0]) idraw->draw3dText(n.m_x,text);
}
}
//
void DrawFrame( btSoftBody* psb,
btIDebugDraw* idraw)
void btSoftBodyHelpers::DrawFrame( btSoftBody* psb,
btIDebugDraw* idraw)
{
if(psb->m_pose.m_bframe)
if(psb->m_pose.m_bframe)
{
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 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();
idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0));
idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0));
idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1));
for(int i=0;i<psb->m_pose.m_pos.size();++i)
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 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();
idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0));
idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0));
idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1));
for(int i=0;i<psb->m_pose.m_pos.size();++i)
{
const btVector3 x=com+trs*psb->m_pose.m_pos[i];
idraw->drawLine(x-btVector3(1,0,0)*nscl,x+btVector3(1,0,0)*nscl,btVector3(1,0,1));
idraw->drawLine(x-btVector3(0,1,0)*nscl,x+btVector3(0,1,0)*nscl,btVector3(1,0,1));
idraw->drawLine(x-btVector3(0,0,1)*nscl,x+btVector3(0,0,1)*nscl,btVector3(1,0,1));
const btVector3 x=com+trs*psb->m_pose.m_pos[i];
idraw->drawLine(x-btVector3(1,0,0)*nscl,x+btVector3(1,0,0)*nscl,btVector3(1,0,1));
idraw->drawLine(x-btVector3(0,1,0)*nscl,x+btVector3(0,1,0)*nscl,btVector3(1,0,1));
idraw->drawLine(x-btVector3(0,0,1)*nscl,x+btVector3(0,0,1)*nscl,btVector3(1,0,1));
}
}
}
//
btSoftBody* CreateRope( btSoftBody::ISoftBody* isoftbody,
const btVector3& from,
const btVector3& to,
int res,
int fixeds)
btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBody::btSoftBodyWorldInfo& worldInfo, const btVector3& from,
const btVector3& to,
int res,
int fixeds)
{
/* Create nodes */
const int r=res+2;
btVector3* x=new btVector3[r];
btScalar* m=new btScalar[r];
for(int i=0;i<r;++i)
/* Create nodes */
const int r=res+2;
btVector3* x=new btVector3[r];
btScalar* m=new btScalar[r];
for(int i=0;i<r;++i)
{
const btScalar t=i/(btScalar)(r-1);
x[i]=lerp(from,to,t);
m[i]=1;
const btScalar t=i/(btScalar)(r-1);
x[i]=lerp(from,to,t);
m[i]=1;
}
btSoftBody* psb=btSoftBody::Create(isoftbody,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)
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);
/* Finished */
return(psb);
}
//
btSoftBody* CreatePatch( btSoftBody::ISoftBody* isoftbody,
const btVector3& corner00,
const btVector3& corner10,
const btVector3& corner01,
const btVector3& corner11,
int resx,
int resy,
int fixeds,
bool gendiags)
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)
{
#define IDX(_x_,_y_) ((_y_)*rx+(_x_))
/* Create nodes */
if((resx<2)||(resy<2)) return(0);
const int rx=resx;
const int ry=resy;
const int tot=rx*ry;
btVector3* x=new btVector3[tot];
btScalar* m=new btScalar[tot];
for(int iy=0;iy<ry;++iy)
/* Create nodes */
if((resx<2)||(resy<2)) return(0);
const int rx=resx;
const int ry=resy;
const int tot=rx*ry;
btVector3* x=new btVector3[tot];
btScalar* m=new btScalar[tot];
for(int iy=0;iy<ry;++iy)
{
const btScalar ty=iy/(btScalar)(ry-1);
const btVector3 py0=lerp(corner00,corner01,ty);
const btVector3 py1=lerp(corner10,corner11,ty);
for(int ix=0;ix<rx;++ix)
const btScalar ty=iy/(btScalar)(ry-1);
const btVector3 py0=lerp(corner00,corner01,ty);
const btVector3 py1=lerp(corner10,corner11,ty);
for(int ix=0;ix<rx;++ix)
{
const btScalar tx=ix/(btScalar)(rx-1);
x[IDX(ix,iy)]=lerp(py0,py1,tx);
m[IDX(ix,iy)]=1;
const btScalar tx=ix/(btScalar)(rx-1);
x[IDX(ix,iy)]=lerp(py0,py1,tx);
m[IDX(ix,iy)]=1;
}
}
btSoftBody* psb=btSoftBody::Create(isoftbody,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 */
for(int iy=0;iy<ry;++iy)
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 */
for(int iy=0;iy<ry;++iy)
{
for(int ix=0;ix<rx;++ix)
for(int ix=0;ix<rx;++ix)
{
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),
1,btSoftBody::eLType::Structural);
if(mdy) psb->AppendLink(idx,IDX(ix,iy+1),
1,btSoftBody::eLType::Structural);
if(mdx&&mdy)
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),
1,btSoftBody::eLType::Structural);
if(mdy) psb->AppendLink(idx,IDX(ix,iy+1),
1,btSoftBody::eLType::Structural);
if(mdx&&mdy)
{
if((ix+iy)&1)
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));
if(gendiags)
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),
1,btSoftBody::eLType::Structural);
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));
if(gendiags)
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),
1,btSoftBody::eLType::Structural);
psb->AppendLink(IDX(ix+1,iy),IDX(ix,iy+1),
1,btSoftBody::eLType::Structural);
}
}
}
}
}
/* Finished */
/* Finished */
#undef IDX
return(psb);
return(psb);
}
//
btSoftBody* CreateEllipsoid(btSoftBody::ISoftBody* isoftbody,
const btVector3& center,
btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& center,
const btVector3& radius,
int res)
{
struct Hammersley
struct Hammersley
{
static void Generate(btVector3* x,int n)
static void Generate(btVector3* x,int n)
{
for(int i=0;i<n;i++)
for(int i=0;i<n;i++)
{
btScalar p=0.5,t=0;
for(int j=i;j;p*=0.5,j>>=1) if(j&1) t+=p;
btScalar w=2*t-1;
btScalar a=(SIMD_PI+2*i*SIMD_PI)/n;
btScalar s=btSqrt(1-w*w);
*x++=btVector3(s*btCos(a),s*btSin(a),w);
btScalar p=0.5,t=0;
for(int j=i;j;p*=0.5,j>>=1) if(j&1) t+=p;
btScalar w=2*t-1;
btScalar a=(SIMD_PI+2*i*SIMD_PI)/n;
btScalar s=btSqrt(1-w*w);
*x++=btVector3(s*btCos(a),s*btSin(a),w);
}
}
};
btAlignedObjectArray<btVector3> vtx;
vtx.resize(3+res);
Hammersley::Generate(&vtx[0],vtx.size());
for(int i=0;i<vtx.size();++i)
btAlignedObjectArray<btVector3> vtx;
vtx.resize(3+res);
Hammersley::Generate(&vtx[0],vtx.size());
for(int i=0;i<vtx.size();++i)
{
vtx[i]=vtx[i]*radius+center;
vtx[i]=vtx[i]*radius+center;
}
return(CreateFromConvexHull(isoftbody,&vtx[0],vtx.size()));
return(CreateFromConvexHull(worldInfo,&vtx[0],vtx.size()));
}
//
btSoftBody* CreateFromTriMesh( btSoftBody::ISoftBody* isoftbody,
const btScalar* vertices,
const int* triangles,
int ntriangles)
btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btScalar* vertices,
const int* triangles,
int ntriangles)
{
int maxidx=0;
for(int i=0,ni=ntriangles*3;i<ni;++i)
int maxidx=0;
for(int i=0,ni=ntriangles*3;i<ni;++i)
{
maxidx=btMax(triangles[i],maxidx);
maxidx=btMax(triangles[i],maxidx);
}
++maxidx;
btAlignedObjectArray<bool> chks;
btAlignedObjectArray<btVector3> vtx;
chks.resize(maxidx*maxidx,false);
vtx.resize(maxidx);
for(int i=0,j=0,ni=maxidx*3;i<ni;++j,i+=3)
++maxidx;
btAlignedObjectArray<bool> chks;
btAlignedObjectArray<btVector3> vtx;
chks.resize(maxidx*maxidx,false);
vtx.resize(maxidx);
for(int i=0,j=0,ni=maxidx*3;i<ni;++j,i+=3)
{
vtx[j]=btVector3(vertices[i],vertices[i+1],vertices[i+2]);
vtx[j]=btVector3(vertices[i],vertices[i+1],vertices[i+2]);
}
btSoftBody* psb=btSoftBody::Create(isoftbody,vtx.size(),&vtx[0],0);
for(int i=0,ni=ntriangles*3;i<ni;i+=3)
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]};
#define IDX(_x_,_y_) ((_y_)*maxidx+(_x_))
for(int j=2,k=0;k<3;j=k++)
const int idx[]={triangles[i],triangles[i+1],triangles[i+2]};
#define IDX(_x_,_y_) ((_y_)*maxidx+(_x_))
for(int j=2,k=0;k<3;j=k++)
{
if(!chks[IDX(idx[j],idx[k])])
if(!chks[IDX(idx[j],idx[k])])
{
chks[IDX(idx[j],idx[k])]=true;
chks[IDX(idx[k],idx[k])]=true;
psb->AppendLink(idx[j],idx[k],1,btSoftBody::eLType::Structural);
chks[IDX(idx[j],idx[k])]=true;
chks[IDX(idx[k],idx[k])]=true;
psb->AppendLink(idx[j],idx[k],1,btSoftBody::eLType::Structural);
}
}
#undef IDX
psb->AppendFace(idx[0],idx[1],idx[2]);
#undef IDX
psb->AppendFace(idx[0],idx[1],idx[2]);
}
psb->RandomizeConstraints();
return(psb);
psb->RandomizeConstraints();
return(psb);
}

View File

@@ -0,0 +1,90 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SOFT_BODY_HELPERS_H
#define SOFT_BODY_HELPERS_H
#include "btSoftBody.h"
//
// Helpers
//
/* fDrawFlags */
struct fDrawFlags { enum _ {
Nodes = 0x0001,
SLinks = 0x0002,
BLinks = 0x0004,
Faces = 0x0008,
Tetras = 0x0010,
Normals = 0x0020,
Contacts = 0x0040,
Anchors = 0x0080,
/* presets */
Links = SLinks+BLinks,
Std = SLinks+Faces+Anchors,
StdTetra = Std-Faces+Tetras,
};};
struct btSoftBodyHelpers
{
static btVector3 stresscolor(btScalar stress);
static void drawVertex( btIDebugDraw* idraw,
const btVector3& x,btScalar s,const btVector3& c);
/* Draw body */
static void Draw( btSoftBody* psb,
btIDebugDraw* idraw,
int drawflags=fDrawFlags::Std);
/* Draw body infos */
static void DrawInfos( btSoftBody* psb,
btIDebugDraw* idraw,
bool masses,
bool areas,
bool stress);
/* Draw rigid frame */
static void DrawFrame( btSoftBody* psb,
btIDebugDraw* idraw);
/* Create a rope */
static btSoftBody* CreateRope( btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& from,
const btVector3& to,
int res,
int fixeds);
/* Create a patch */
static btSoftBody* CreatePatch( btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& corner00,
const btVector3& corner10,
const btVector3& corner01,
const btVector3& corner11,
int resx,
int resy,
int fixeds,
bool gendiags);
/* Create an ellipsoid */
static btSoftBody* CreateEllipsoid(btSoftBody::btSoftBodyWorldInfo& worldInfo,const btVector3& center,
const btVector3& radius,
int res);
/* Create from convex-hull */
static btSoftBody* CreateFromConvexHull( btSoftBody::btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
int nvertices);
/* Create from trimesh */
static btSoftBody* CreateFromTriMesh( btSoftBody::btSoftBodyWorldInfo& worldInfo, const btScalar* vertices,
const int* triangles,
int ntriangles);
};
#endif //SOFT_BODY_HELPERS_H