1006 lines
30 KiB
C++
1006 lines
30 KiB
C++
|
/*
|
||
|
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.
|
||
|
*/
|
||
|
///btSoftBody implementation by Nathanael Presson
|
||
|
|
||
|
#ifndef _BT_SOFT_BODY_H
|
||
|
#define _BT_SOFT_BODY_H
|
||
|
|
||
|
#include "LinearMath/btAlignedObjectArray.h"
|
||
|
#include "LinearMath/btTransform.h"
|
||
|
#include "LinearMath/btIDebugDraw.h"
|
||
|
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
||
|
|
||
|
#include "BulletCollision/CollisionShapes/btConcaveShape.h"
|
||
|
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
|
||
|
#include "btSparseSDF.h"
|
||
|
#include "BulletCollision/BroadphaseCollision/btDbvt.h"
|
||
|
|
||
|
//#ifdef BT_USE_DOUBLE_PRECISION
|
||
|
//#define btRigidBodyData btRigidBodyDoubleData
|
||
|
//#define btRigidBodyDataName "btRigidBodyDoubleData"
|
||
|
//#else
|
||
|
#define btSoftBodyData btSoftBodyFloatData
|
||
|
#define btSoftBodyDataName "btSoftBodyFloatData"
|
||
|
//#endif //BT_USE_DOUBLE_PRECISION
|
||
|
|
||
|
class btBroadphaseInterface;
|
||
|
class btDispatcher;
|
||
|
class btSoftBodySolver;
|
||
|
|
||
|
/* btSoftBodyWorldInfo */
|
||
|
struct btSoftBodyWorldInfo
|
||
|
{
|
||
|
btScalar air_density;
|
||
|
btScalar water_density;
|
||
|
btScalar water_offset;
|
||
|
btScalar m_maxDisplacement;
|
||
|
btVector3 water_normal;
|
||
|
btBroadphaseInterface* m_broadphase;
|
||
|
btDispatcher* m_dispatcher;
|
||
|
btVector3 m_gravity;
|
||
|
btSparseSdf<3> m_sparsesdf;
|
||
|
|
||
|
btSoftBodyWorldInfo()
|
||
|
:air_density((btScalar)1.2),
|
||
|
water_density(0),
|
||
|
water_offset(0),
|
||
|
m_maxDisplacement(1000.f),//avoid soft body from 'exploding' so use some upper threshold of maximum motion that a node can travel per frame
|
||
|
water_normal(0,0,0),
|
||
|
m_broadphase(0),
|
||
|
m_dispatcher(0),
|
||
|
m_gravity(0,-10,0)
|
||
|
{
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
///The btSoftBody is an class to simulate cloth and volumetric soft bodies.
|
||
|
///There is two-way interaction between btSoftBody and btRigidBody/btCollisionObject.
|
||
|
class btSoftBody : public btCollisionObject
|
||
|
{
|
||
|
public:
|
||
|
btAlignedObjectArray<const class btCollisionObject*> m_collisionDisabledObjects;
|
||
|
|
||
|
// The solver object that handles this soft body
|
||
|
btSoftBodySolver *m_softBodySolver;
|
||
|
|
||
|
//
|
||
|
// Enumerations
|
||
|
//
|
||
|
|
||
|
///eAeroModel
|
||
|
struct eAeroModel { enum _ {
|
||
|
V_Point, ///Vertex normals are oriented toward velocity
|
||
|
V_TwoSided, ///Vertex normals are flipped to match velocity
|
||
|
V_TwoSidedLiftDrag, ///Vertex normals are flipped to match velocity and lift and drag forces are applied
|
||
|
V_OneSided, ///Vertex normals are taken as it is
|
||
|
F_TwoSided, ///Face normals are flipped to match velocity
|
||
|
F_TwoSidedLiftDrag, ///Face normals are flipped to match velocity and lift and drag forces are applied
|
||
|
F_OneSided, ///Face normals are taken as it is
|
||
|
END
|
||
|
};};
|
||
|
|
||
|
///eVSolver : velocities solvers
|
||
|
struct eVSolver { enum _ {
|
||
|
Linear, ///Linear solver
|
||
|
END
|
||
|
};};
|
||
|
|
||
|
///ePSolver : positions solvers
|
||
|
struct ePSolver { enum _ {
|
||
|
Linear, ///Linear solver
|
||
|
Anchors, ///Anchor solver
|
||
|
RContacts, ///Rigid contacts solver
|
||
|
SContacts, ///Soft contacts solver
|
||
|
END
|
||
|
};};
|
||
|
|
||
|
///eSolverPresets
|
||
|
struct eSolverPresets { enum _ {
|
||
|
Positions,
|
||
|
Velocities,
|
||
|
Default = Positions,
|
||
|
END
|
||
|
};};
|
||
|
|
||
|
///eFeature
|
||
|
struct eFeature { enum _ {
|
||
|
None,
|
||
|
Node,
|
||
|
Link,
|
||
|
Face,
|
||
|
Tetra,
|
||
|
END
|
||
|
};};
|
||
|
|
||
|
typedef btAlignedObjectArray<eVSolver::_> tVSolverArray;
|
||
|
typedef btAlignedObjectArray<ePSolver::_> tPSolverArray;
|
||
|
|
||
|
//
|
||
|
// Flags
|
||
|
//
|
||
|
|
||
|
///fCollision
|
||
|
struct fCollision { enum _ {
|
||
|
RVSmask = 0x000f, ///Rigid versus soft mask
|
||
|
SDF_RS = 0x0001, ///SDF based rigid vs soft
|
||
|
CL_RS = 0x0002, ///Cluster vs convex rigid vs soft
|
||
|
|
||
|
SVSmask = 0x0030, ///Rigid versus soft mask
|
||
|
VF_SS = 0x0010, ///Vertex vs face soft vs soft handling
|
||
|
CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling
|
||
|
CL_SELF = 0x0040, ///Cluster soft body self collision
|
||
|
/* presets */
|
||
|
Default = SDF_RS,
|
||
|
END
|
||
|
};};
|
||
|
|
||
|
///fMaterial
|
||
|
struct fMaterial { enum _ {
|
||
|
DebugDraw = 0x0001, /// Enable debug draw
|
||
|
/* presets */
|
||
|
Default = DebugDraw,
|
||
|
END
|
||
|
};};
|
||
|
|
||
|
//
|
||
|
// API Types
|
||
|
//
|
||
|
|
||
|
/* sRayCast */
|
||
|
struct sRayCast
|
||
|
{
|
||
|
btSoftBody* body; /// soft body
|
||
|
eFeature::_ feature; /// feature type
|
||
|
int index; /// feature index
|
||
|
btScalar fraction; /// time of impact fraction (rayorg+(rayto-rayfrom)*fraction)
|
||
|
};
|
||
|
|
||
|
/* ImplicitFn */
|
||
|
struct ImplicitFn
|
||
|
{
|
||
|
virtual ~ImplicitFn() {}
|
||
|
virtual btScalar Eval(const btVector3& x)=0;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Internal types
|
||
|
//
|
||
|
|
||
|
typedef btAlignedObjectArray<btScalar> tScalarArray;
|
||
|
typedef btAlignedObjectArray<btVector3> tVector3Array;
|
||
|
|
||
|
/* sCti is Softbody contact info */
|
||
|
struct sCti
|
||
|
{
|
||
|
const btCollisionObject* m_colObj; /* 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
|
||
|
Element() : m_tag(0) {}
|
||
|
};
|
||
|
/* Material */
|
||
|
struct Material : Element
|
||
|
{
|
||
|
btScalar m_kLST; // Linear 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
|
||
|
};
|
||
|
|
||
|
/* Feature */
|
||
|
struct Feature : Element
|
||
|
{
|
||
|
Material* m_material; // Material
|
||
|
};
|
||
|
/* Node */
|
||
|
struct Node : Feature
|
||
|
{
|
||
|
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
|
||
|
btDbvtNode* m_leaf; // Leaf data
|
||
|
int m_battach:1; // Attached
|
||
|
};
|
||
|
/* Link */
|
||
|
ATTRIBUTE_ALIGNED16(struct) Link : Feature
|
||
|
{
|
||
|
btVector3 m_c3; // gradient
|
||
|
Node* m_n[2]; // Node pointers
|
||
|
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
|
||
|
|
||
|
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||
|
|
||
|
};
|
||
|
/* Face */
|
||
|
struct Face : Feature
|
||
|
{
|
||
|
Node* m_n[3]; // Node pointers
|
||
|
btVector3 m_normal; // Normal
|
||
|
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
|
||
|
{
|
||
|
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
|
||
|
btScalar m_c4; // Hardness
|
||
|
};
|
||
|
/* 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
|
||
|
btScalar m_influence;
|
||
|
btMatrix3x3 m_c0; // Impulse matrix
|
||
|
btVector3 m_c1; // Relative anchor
|
||
|
btScalar m_c2; // ima*dt
|
||
|
};
|
||
|
/* Note */
|
||
|
struct Note : Element
|
||
|
{
|
||
|
const char* m_text; // Text
|
||
|
btVector3 m_offset; // Offset
|
||
|
int m_rank; // Rank
|
||
|
Node* m_nodes[4]; // Nodes
|
||
|
btScalar m_coords[4]; // Coordinates
|
||
|
};
|
||
|
/* 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_rot; // Rotation
|
||
|
btMatrix3x3 m_scl; // Scale
|
||
|
btMatrix3x3 m_aqq; // Base scaling
|
||
|
};
|
||
|
/* Cluster */
|
||
|
struct Cluster
|
||
|
{
|
||
|
tScalarArray m_masses;
|
||
|
btAlignedObjectArray<Node*> m_nodes;
|
||
|
tVector3Array m_framerefs;
|
||
|
btTransform m_framexform;
|
||
|
btScalar m_idmass;
|
||
|
btScalar m_imass;
|
||
|
btMatrix3x3 m_locii;
|
||
|
btMatrix3x3 m_invwi;
|
||
|
btVector3 m_com;
|
||
|
btVector3 m_vimpulses[2];
|
||
|
btVector3 m_dimpulses[2];
|
||
|
int m_nvimpulses;
|
||
|
int m_ndimpulses;
|
||
|
btVector3 m_lv;
|
||
|
btVector3 m_av;
|
||
|
btDbvtNode* m_leaf;
|
||
|
btScalar m_ndamping; /* Node damping */
|
||
|
btScalar m_ldamping; /* Linear damping */
|
||
|
btScalar m_adamping; /* Angular damping */
|
||
|
btScalar m_matching;
|
||
|
btScalar m_maxSelfCollisionImpulse;
|
||
|
btScalar m_selfCollisionImpulseFactor;
|
||
|
bool m_containsAnchor;
|
||
|
bool m_collide;
|
||
|
int m_clusterIndex;
|
||
|
Cluster() : m_leaf(0),m_ndamping(0),m_ldamping(0),m_adamping(0),m_matching(0)
|
||
|
,m_maxSelfCollisionImpulse(100.f),
|
||
|
m_selfCollisionImpulseFactor(0.01f),
|
||
|
m_containsAnchor(false)
|
||
|
{}
|
||
|
};
|
||
|
/* Impulse */
|
||
|
struct Impulse
|
||
|
{
|
||
|
btVector3 m_velocity;
|
||
|
btVector3 m_drift;
|
||
|
int m_asVelocity:1;
|
||
|
int m_asDrift:1;
|
||
|
Impulse() : m_velocity(0,0,0),m_drift(0,0,0),m_asVelocity(0),m_asDrift(0) {}
|
||
|
Impulse operator -() const
|
||
|
{
|
||
|
Impulse i=*this;
|
||
|
i.m_velocity=-i.m_velocity;
|
||
|
i.m_drift=-i.m_drift;
|
||
|
return(i);
|
||
|
}
|
||
|
Impulse operator*(btScalar x) const
|
||
|
{
|
||
|
Impulse i=*this;
|
||
|
i.m_velocity*=x;
|
||
|
i.m_drift*=x;
|
||
|
return(i);
|
||
|
}
|
||
|
};
|
||
|
/* Body */
|
||
|
struct Body
|
||
|
{
|
||
|
Cluster* m_soft;
|
||
|
btRigidBody* m_rigid;
|
||
|
const btCollisionObject* m_collisionObject;
|
||
|
|
||
|
Body() : m_soft(0),m_rigid(0),m_collisionObject(0) {}
|
||
|
Body(Cluster* p) : m_soft(p),m_rigid(0),m_collisionObject(0) {}
|
||
|
Body(const btCollisionObject* colObj) : m_soft(0),m_collisionObject(colObj)
|
||
|
{
|
||
|
m_rigid = (btRigidBody*)btRigidBody::upcast(m_collisionObject);
|
||
|
}
|
||
|
|
||
|
void activate() const
|
||
|
{
|
||
|
if(m_rigid)
|
||
|
m_rigid->activate();
|
||
|
if (m_collisionObject)
|
||
|
m_collisionObject->activate();
|
||
|
|
||
|
}
|
||
|
const btMatrix3x3& invWorldInertia() const
|
||
|
{
|
||
|
static const btMatrix3x3 iwi(0,0,0,0,0,0,0,0,0);
|
||
|
if(m_rigid) return(m_rigid->getInvInertiaTensorWorld());
|
||
|
if(m_soft) return(m_soft->m_invwi);
|
||
|
return(iwi);
|
||
|
}
|
||
|
btScalar invMass() const
|
||
|
{
|
||
|
if(m_rigid) return(m_rigid->getInvMass());
|
||
|
if(m_soft) return(m_soft->m_imass);
|
||
|
return(0);
|
||
|
}
|
||
|
const btTransform& xform() const
|
||
|
{
|
||
|
static const btTransform identity=btTransform::getIdentity();
|
||
|
if(m_collisionObject) return(m_collisionObject->getWorldTransform());
|
||
|
if(m_soft) return(m_soft->m_framexform);
|
||
|
return(identity);
|
||
|
}
|
||
|
btVector3 linearVelocity() const
|
||
|
{
|
||
|
if(m_rigid) return(m_rigid->getLinearVelocity());
|
||
|
if(m_soft) return(m_soft->m_lv);
|
||
|
return(btVector3(0,0,0));
|
||
|
}
|
||
|
btVector3 angularVelocity(const btVector3& rpos) const
|
||
|
{
|
||
|
if(m_rigid) return(btCross(m_rigid->getAngularVelocity(),rpos));
|
||
|
if(m_soft) return(btCross(m_soft->m_av,rpos));
|
||
|
return(btVector3(0,0,0));
|
||
|
}
|
||
|
btVector3 angularVelocity() const
|
||
|
{
|
||
|
if(m_rigid) return(m_rigid->getAngularVelocity());
|
||
|
if(m_soft) return(m_soft->m_av);
|
||
|
return(btVector3(0,0,0));
|
||
|
}
|
||
|
btVector3 velocity(const btVector3& rpos) const
|
||
|
{
|
||
|
return(linearVelocity()+angularVelocity(rpos));
|
||
|
}
|
||
|
void applyVImpulse(const btVector3& impulse,const btVector3& rpos) const
|
||
|
{
|
||
|
if(m_rigid) m_rigid->applyImpulse(impulse,rpos);
|
||
|
if(m_soft) btSoftBody::clusterVImpulse(m_soft,rpos,impulse);
|
||
|
}
|
||
|
void applyDImpulse(const btVector3& impulse,const btVector3& rpos) const
|
||
|
{
|
||
|
if(m_rigid) m_rigid->applyImpulse(impulse,rpos);
|
||
|
if(m_soft) btSoftBody::clusterDImpulse(m_soft,rpos,impulse);
|
||
|
}
|
||
|
void applyImpulse(const Impulse& impulse,const btVector3& rpos) const
|
||
|
{
|
||
|
if(impulse.m_asVelocity)
|
||
|
{
|
||
|
// printf("impulse.m_velocity = %f,%f,%f\n",impulse.m_velocity.getX(),impulse.m_velocity.getY(),impulse.m_velocity.getZ());
|
||
|
applyVImpulse(impulse.m_velocity,rpos);
|
||
|
}
|
||
|
if(impulse.m_asDrift)
|
||
|
{
|
||
|
// printf("impulse.m_drift = %f,%f,%f\n",impulse.m_drift.getX(),impulse.m_drift.getY(),impulse.m_drift.getZ());
|
||
|
applyDImpulse(impulse.m_drift,rpos);
|
||
|
}
|
||
|
}
|
||
|
void applyVAImpulse(const btVector3& impulse) const
|
||
|
{
|
||
|
if(m_rigid) m_rigid->applyTorqueImpulse(impulse);
|
||
|
if(m_soft) btSoftBody::clusterVAImpulse(m_soft,impulse);
|
||
|
}
|
||
|
void applyDAImpulse(const btVector3& impulse) const
|
||
|
{
|
||
|
if(m_rigid) m_rigid->applyTorqueImpulse(impulse);
|
||
|
if(m_soft) btSoftBody::clusterDAImpulse(m_soft,impulse);
|
||
|
}
|
||
|
void applyAImpulse(const Impulse& impulse) const
|
||
|
{
|
||
|
if(impulse.m_asVelocity) applyVAImpulse(impulse.m_velocity);
|
||
|
if(impulse.m_asDrift) applyDAImpulse(impulse.m_drift);
|
||
|
}
|
||
|
void applyDCImpulse(const btVector3& impulse) const
|
||
|
{
|
||
|
if(m_rigid) m_rigid->applyCentralImpulse(impulse);
|
||
|
if(m_soft) btSoftBody::clusterDCImpulse(m_soft,impulse);
|
||
|
}
|
||
|
};
|
||
|
/* Joint */
|
||
|
struct Joint
|
||
|
{
|
||
|
struct eType { enum _ {
|
||
|
Linear=0,
|
||
|
Angular,
|
||
|
Contact
|
||
|
};};
|
||
|
struct Specs
|
||
|
{
|
||
|
Specs() : erp(1),cfm(1),split(1) {}
|
||
|
btScalar erp;
|
||
|
btScalar cfm;
|
||
|
btScalar split;
|
||
|
};
|
||
|
Body m_bodies[2];
|
||
|
btVector3 m_refs[2];
|
||
|
btScalar m_cfm;
|
||
|
btScalar m_erp;
|
||
|
btScalar m_split;
|
||
|
btVector3 m_drift;
|
||
|
btVector3 m_sdrift;
|
||
|
btMatrix3x3 m_massmatrix;
|
||
|
bool m_delete;
|
||
|
virtual ~Joint() {}
|
||
|
Joint() : m_delete(false) {}
|
||
|
virtual void Prepare(btScalar dt,int iterations);
|
||
|
virtual void Solve(btScalar dt,btScalar sor)=0;
|
||
|
virtual void Terminate(btScalar dt)=0;
|
||
|
virtual eType::_ Type() const=0;
|
||
|
};
|
||
|
/* LJoint */
|
||
|
struct LJoint : Joint
|
||
|
{
|
||
|
struct Specs : Joint::Specs
|
||
|
{
|
||
|
btVector3 position;
|
||
|
};
|
||
|
btVector3 m_rpos[2];
|
||
|
void Prepare(btScalar dt,int iterations);
|
||
|
void Solve(btScalar dt,btScalar sor);
|
||
|
void Terminate(btScalar dt);
|
||
|
eType::_ Type() const { return(eType::Linear); }
|
||
|
};
|
||
|
/* AJoint */
|
||
|
struct AJoint : Joint
|
||
|
{
|
||
|
struct IControl
|
||
|
{
|
||
|
virtual ~IControl() {}
|
||
|
virtual void Prepare(AJoint*) {}
|
||
|
virtual btScalar Speed(AJoint*,btScalar current) { return(current); }
|
||
|
static IControl* Default() { static IControl def;return(&def); }
|
||
|
};
|
||
|
struct Specs : Joint::Specs
|
||
|
{
|
||
|
Specs() : icontrol(IControl::Default()) {}
|
||
|
btVector3 axis;
|
||
|
IControl* icontrol;
|
||
|
};
|
||
|
btVector3 m_axis[2];
|
||
|
IControl* m_icontrol;
|
||
|
void Prepare(btScalar dt,int iterations);
|
||
|
void Solve(btScalar dt,btScalar sor);
|
||
|
void Terminate(btScalar dt);
|
||
|
eType::_ Type() const { return(eType::Angular); }
|
||
|
};
|
||
|
/* CJoint */
|
||
|
struct CJoint : Joint
|
||
|
{
|
||
|
int m_life;
|
||
|
int m_maxlife;
|
||
|
btVector3 m_rpos[2];
|
||
|
btVector3 m_normal;
|
||
|
btScalar m_friction;
|
||
|
void Prepare(btScalar dt,int iterations);
|
||
|
void Solve(btScalar dt,btScalar sor);
|
||
|
void Terminate(btScalar dt);
|
||
|
eType::_ Type() const { return(eType::Contact); }
|
||
|
};
|
||
|
/* Config */
|
||
|
struct Config
|
||
|
{
|
||
|
eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point)
|
||
|
btScalar kVCF; // Velocities correction factor (Baumgarte)
|
||
|
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 kCHR; // Rigid contacts hardness [0,1]
|
||
|
btScalar kKHR; // Kinetic contacts hardness [0,1]
|
||
|
btScalar kSHR; // Soft contacts hardness [0,1]
|
||
|
btScalar kAHR; // Anchors hardness [0,1]
|
||
|
btScalar kSRHR_CL; // Soft vs rigid hardness [0,1] (cluster only)
|
||
|
btScalar kSKHR_CL; // Soft vs kinetic hardness [0,1] (cluster only)
|
||
|
btScalar kSSHR_CL; // Soft vs soft hardness [0,1] (cluster only)
|
||
|
btScalar kSR_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
|
||
|
btScalar kSK_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
|
||
|
btScalar kSS_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
|
||
|
btScalar maxvolume; // Maximum volume ratio for pose
|
||
|
btScalar timescale; // Time scale
|
||
|
int viterations; // Velocities solver iterations
|
||
|
int piterations; // Positions solver iterations
|
||
|
int diterations; // Drift solver iterations
|
||
|
int citerations; // Cluster solver iterations
|
||
|
int collisions; // Collisions flags
|
||
|
tVSolverArray m_vsequence; // Velocity solvers sequence
|
||
|
tPSolverArray m_psequence; // Position solvers sequence
|
||
|
tPSolverArray m_dsequence; // Drift solvers sequence
|
||
|
};
|
||
|
/* SolverState */
|
||
|
struct SolverState
|
||
|
{
|
||
|
btScalar sdt; // dt*timescale
|
||
|
btScalar isdt; // 1/sdt
|
||
|
btScalar velmrg; // velocity margin
|
||
|
btScalar radmrg; // radial margin
|
||
|
btScalar updmrg; // Update margin
|
||
|
};
|
||
|
/// RayFromToCaster takes a ray from, ray to (instead of direction!)
|
||
|
struct RayFromToCaster : btDbvt::ICollide
|
||
|
{
|
||
|
btVector3 m_rayFrom;
|
||
|
btVector3 m_rayTo;
|
||
|
btVector3 m_rayNormalizedDirection;
|
||
|
btScalar m_mint;
|
||
|
Face* m_face;
|
||
|
int m_tests;
|
||
|
RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt);
|
||
|
void Process(const btDbvtNode* leaf);
|
||
|
|
||
|
static /*inline*/ btScalar rayFromToTriangle(const btVector3& rayFrom,
|
||
|
const btVector3& rayTo,
|
||
|
const btVector3& rayNormalizedDirection,
|
||
|
const btVector3& a,
|
||
|
const btVector3& b,
|
||
|
const btVector3& c,
|
||
|
btScalar maxt=SIMD_INFINITY);
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Typedefs
|
||
|
//
|
||
|
|
||
|
typedef void (*psolver_t)(btSoftBody*,btScalar,btScalar);
|
||
|
typedef void (*vsolver_t)(btSoftBody*,btScalar);
|
||
|
typedef btAlignedObjectArray<Cluster*> tClusterArray;
|
||
|
typedef btAlignedObjectArray<Note> tNoteArray;
|
||
|
typedef btAlignedObjectArray<Node> tNodeArray;
|
||
|
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;
|
||
|
typedef btAlignedObjectArray<Material*> tMaterialArray;
|
||
|
typedef btAlignedObjectArray<Joint*> tJointArray;
|
||
|
typedef btAlignedObjectArray<btSoftBody*> tSoftBodyArray;
|
||
|
|
||
|
//
|
||
|
// Fields
|
||
|
//
|
||
|
|
||
|
Config m_cfg; // Configuration
|
||
|
SolverState m_sst; // Solver state
|
||
|
Pose m_pose; // Pose
|
||
|
void* m_tag; // User data
|
||
|
btSoftBodyWorldInfo* m_worldInfo; // World info
|
||
|
tNoteArray m_notes; // Notes
|
||
|
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
|
||
|
tJointArray m_joints; // Joints
|
||
|
tMaterialArray m_materials; // Materials
|
||
|
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
|
||
|
btDbvt m_cdbvt; // Clusters tree
|
||
|
tClusterArray m_clusters; // Clusters
|
||
|
|
||
|
btAlignedObjectArray<bool>m_clusterConnectivity;//cluster connectivity, for self-collision
|
||
|
|
||
|
btTransform m_initialWorldTransform;
|
||
|
|
||
|
btVector3 m_windVelocity;
|
||
|
|
||
|
btScalar m_restLengthScale;
|
||
|
|
||
|
//
|
||
|
// Api
|
||
|
//
|
||
|
|
||
|
/* ctor */
|
||
|
btSoftBody( btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m);
|
||
|
|
||
|
/* ctor */
|
||
|
btSoftBody( btSoftBodyWorldInfo* worldInfo);
|
||
|
|
||
|
void initDefaults();
|
||
|
|
||
|
/* dtor */
|
||
|
virtual ~btSoftBody();
|
||
|
/* Check for existing link */
|
||
|
|
||
|
btAlignedObjectArray<int> m_userIndexMapping;
|
||
|
|
||
|
btSoftBodyWorldInfo* getWorldInfo()
|
||
|
{
|
||
|
return m_worldInfo;
|
||
|
}
|
||
|
|
||
|
///@todo: avoid internal softbody shape hack and move collision code to collision library
|
||
|
virtual void setCollisionShape(btCollisionShape* collisionShape)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
bool checkLink( int node0,
|
||
|
int node1) const;
|
||
|
bool checkLink( const Node* node0,
|
||
|
const Node* node1) const;
|
||
|
/* Check for existring face */
|
||
|
bool checkFace( int node0,
|
||
|
int node1,
|
||
|
int node2) const;
|
||
|
/* Append material */
|
||
|
Material* appendMaterial();
|
||
|
/* Append note */
|
||
|
void appendNote( const char* text,
|
||
|
const btVector3& o,
|
||
|
const btVector4& c=btVector4(1,0,0,0),
|
||
|
Node* n0=0,
|
||
|
Node* n1=0,
|
||
|
Node* n2=0,
|
||
|
Node* n3=0);
|
||
|
void appendNote( const char* text,
|
||
|
const btVector3& o,
|
||
|
Node* feature);
|
||
|
void appendNote( const char* text,
|
||
|
const btVector3& o,
|
||
|
Link* feature);
|
||
|
void appendNote( const char* text,
|
||
|
const btVector3& o,
|
||
|
Face* feature);
|
||
|
/* Append node */
|
||
|
void appendNode( const btVector3& x,btScalar m);
|
||
|
/* Append link */
|
||
|
void appendLink(int model=-1,Material* mat=0);
|
||
|
void appendLink( int node0,
|
||
|
int node1,
|
||
|
Material* mat=0,
|
||
|
bool bcheckexist=false);
|
||
|
void appendLink( Node* node0,
|
||
|
Node* node1,
|
||
|
Material* mat=0,
|
||
|
bool bcheckexist=false);
|
||
|
/* Append face */
|
||
|
void appendFace(int model=-1,Material* mat=0);
|
||
|
void appendFace( int node0,
|
||
|
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,btScalar influence = 1);
|
||
|
void appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies=false,btScalar influence = 1);
|
||
|
/* Append linear joint */
|
||
|
void appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1);
|
||
|
void appendLinearJoint(const LJoint::Specs& specs,Body body=Body());
|
||
|
void appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body);
|
||
|
/* Append linear joint */
|
||
|
void appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1);
|
||
|
void appendAngularJoint(const AJoint::Specs& specs,Body body=Body());
|
||
|
void appendAngularJoint(const AJoint::Specs& specs,btSoftBody* 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);
|
||
|
/* Add aero force to a node of the body */
|
||
|
void addAeroForceToNode(const btVector3& windVelocity,int nodeIndex);
|
||
|
|
||
|
/* Add aero force to a face of the body */
|
||
|
void addAeroForceToFace(const btVector3& windVelocity,int faceIndex);
|
||
|
|
||
|
/* Add velocity to the entire body */
|
||
|
void addVelocity( const btVector3& velocity);
|
||
|
|
||
|
/* Set velocity for the entire body */
|
||
|
void setVelocity( const btVector3& velocity);
|
||
|
|
||
|
/* Add velocity to a node of the body */
|
||
|
void addVelocity( const btVector3& velocity,
|
||
|
int node);
|
||
|
/* Set mass */
|
||
|
void setMass( int node,
|
||
|
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);
|
||
|
/* 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 */
|
||
|
void translate( const btVector3& trs);
|
||
|
/* Rotate */
|
||
|
void rotate( const btQuaternion& rot);
|
||
|
/* Scale */
|
||
|
void scale( const btVector3& scl);
|
||
|
/* Get link resting lengths scale */
|
||
|
btScalar getRestLengthScale();
|
||
|
/* Scale resting length of all springs */
|
||
|
void setRestLengthScale(btScalar restLength);
|
||
|
/* Set current state as pose */
|
||
|
void setPose( bool bvolume,
|
||
|
bool bframe);
|
||
|
/* Set current link lengths as resting lengths */
|
||
|
void resetLinkRestLengths();
|
||
|
/* Return the volume */
|
||
|
btScalar getVolume() const;
|
||
|
/* Cluster count */
|
||
|
int clusterCount() const;
|
||
|
/* Cluster center of mass */
|
||
|
static btVector3 clusterCom(const Cluster* cluster);
|
||
|
btVector3 clusterCom(int cluster) const;
|
||
|
/* Cluster velocity at rpos */
|
||
|
static btVector3 clusterVelocity(const Cluster* cluster,const btVector3& rpos);
|
||
|
/* Cluster impulse */
|
||
|
static void clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse);
|
||
|
static void clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse);
|
||
|
static void clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse);
|
||
|
static void clusterVAImpulse(Cluster* cluster,const btVector3& impulse);
|
||
|
static void clusterDAImpulse(Cluster* cluster,const btVector3& impulse);
|
||
|
static void clusterAImpulse(Cluster* cluster,const Impulse& impulse);
|
||
|
static void clusterDCImpulse(Cluster* cluster,const btVector3& impulse);
|
||
|
/* Generate bending constraints based on distance in the adjency graph */
|
||
|
int generateBendingConstraints( int distance,
|
||
|
Material* mat=0);
|
||
|
/* Randomize constraints to reduce solver bias */
|
||
|
void randomizeConstraints();
|
||
|
/* Release clusters */
|
||
|
void releaseCluster(int index);
|
||
|
void releaseClusters();
|
||
|
/* Generate clusters (K-mean) */
|
||
|
///generateClusters with k=0 will create a convex cluster for each tetrahedron or triangle
|
||
|
///otherwise an approximation will be used (better performance)
|
||
|
int generateClusters(int k,int maxiterations=8192);
|
||
|
/* Refine */
|
||
|
void refine(ImplicitFn* ifn,btScalar accurary,bool cut);
|
||
|
/* CutLink */
|
||
|
bool cutLink(int node0,int node1,btScalar position);
|
||
|
bool cutLink(const Node* node0,const Node* node1,btScalar position);
|
||
|
|
||
|
///Ray casting using rayFrom and rayTo in worldspace, (not direction!)
|
||
|
bool rayTest(const btVector3& rayFrom,
|
||
|
const btVector3& rayTo,
|
||
|
sRayCast& results);
|
||
|
/* Solver presets */
|
||
|
void setSolver(eSolverPresets::_ preset);
|
||
|
/* predictMotion */
|
||
|
void predictMotion(btScalar dt);
|
||
|
/* solveConstraints */
|
||
|
void solveConstraints();
|
||
|
/* staticSolve */
|
||
|
void staticSolve(int iterations);
|
||
|
/* solveCommonConstraints */
|
||
|
static void solveCommonConstraints(btSoftBody** bodies,int count,int iterations);
|
||
|
/* solveClusters */
|
||
|
static void solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies);
|
||
|
/* integrateMotion */
|
||
|
void integrateMotion();
|
||
|
/* defaultCollisionHandlers */
|
||
|
void defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap);
|
||
|
void defaultCollisionHandler(btSoftBody* psb);
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Functionality to deal with new accelerated solvers.
|
||
|
//
|
||
|
|
||
|
/**
|
||
|
* Set a wind velocity for interaction with the air.
|
||
|
*/
|
||
|
void setWindVelocity( const btVector3 &velocity );
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Return the wind velocity for interaction with the air.
|
||
|
*/
|
||
|
const btVector3& getWindVelocity();
|
||
|
|
||
|
//
|
||
|
// Set the solver that handles this soft body
|
||
|
// Should not be allowed to get out of sync with reality
|
||
|
// Currently called internally on addition to the world
|
||
|
void setSoftBodySolver( btSoftBodySolver *softBodySolver )
|
||
|
{
|
||
|
m_softBodySolver = softBodySolver;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Return the solver that handles this soft body
|
||
|
//
|
||
|
btSoftBodySolver *getSoftBodySolver()
|
||
|
{
|
||
|
return m_softBodySolver;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Return the solver that handles this soft body
|
||
|
//
|
||
|
btSoftBodySolver *getSoftBodySolver() const
|
||
|
{
|
||
|
return m_softBodySolver;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Cast
|
||
|
//
|
||
|
|
||
|
static const btSoftBody* upcast(const btCollisionObject* colObj)
|
||
|
{
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// ::btCollisionObject
|
||
|
//
|
||
|
|
||
|
virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const
|
||
|
{
|
||
|
aabbMin = m_bounds[0];
|
||
|
aabbMax = m_bounds[1];
|
||
|
}
|
||
|
//
|
||
|
// Private
|
||
|
//
|
||
|
void pointersToIndices();
|
||
|
void indicesToPointers(const int* map=0);
|
||
|
|
||
|
int rayTest(const btVector3& rayFrom,const btVector3& rayTo,
|
||
|
btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const;
|
||
|
void initializeFaceTree();
|
||
|
btVector3 evaluateCom() const;
|
||
|
bool checkContact(const btCollisionObjectWrapper* colObjWrap,const btVector3& x,btScalar margin,btSoftBody::sCti& cti) const;
|
||
|
void updateNormals();
|
||
|
void updateBounds();
|
||
|
void updatePose();
|
||
|
void updateConstants();
|
||
|
void updateLinkConstants();
|
||
|
void updateArea(bool averageArea = true);
|
||
|
void initializeClusters();
|
||
|
void updateClusters();
|
||
|
void cleanupClusters();
|
||
|
void prepareClusters(int iterations);
|
||
|
void solveClusters(btScalar sor);
|
||
|
void applyClusters(bool drift);
|
||
|
void dampClusters();
|
||
|
void applyForces();
|
||
|
static void PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti);
|
||
|
static void PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti);
|
||
|
static void PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti);
|
||
|
static void PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti);
|
||
|
static void VSolve_Links(btSoftBody* psb,btScalar kst);
|
||
|
static psolver_t getSolver(ePSolver::_ solver);
|
||
|
static vsolver_t getSolver(eVSolver::_ solver);
|
||
|
|
||
|
|
||
|
virtual int calculateSerializeBufferSize() const;
|
||
|
|
||
|
///fills the dataBuffer and returns the struct name (and 0 on failure)
|
||
|
virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
|
||
|
|
||
|
//virtual void serializeSingleObject(class btSerializer* serializer) const;
|
||
|
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#endif //_BT_SOFT_BODY_H
|