Changeset View
Changeset View
Standalone View
Standalone View
extern/bullet2/src/BulletSoftBody/btSoftBody.h
| Show All 14 Lines | |||||
| ///btSoftBody implementation by Nathanael Presson | ///btSoftBody implementation by Nathanael Presson | ||||
| #ifndef _BT_SOFT_BODY_H | #ifndef _BT_SOFT_BODY_H | ||||
| #define _BT_SOFT_BODY_H | #define _BT_SOFT_BODY_H | ||||
| #include "LinearMath/btAlignedObjectArray.h" | #include "LinearMath/btAlignedObjectArray.h" | ||||
| #include "LinearMath/btTransform.h" | #include "LinearMath/btTransform.h" | ||||
| #include "LinearMath/btIDebugDraw.h" | #include "LinearMath/btIDebugDraw.h" | ||||
| #include "LinearMath/btVector3.h" | |||||
| #include "BulletDynamics/Dynamics/btRigidBody.h" | #include "BulletDynamics/Dynamics/btRigidBody.h" | ||||
| #include "BulletCollision/CollisionShapes/btConcaveShape.h" | #include "BulletCollision/CollisionShapes/btConcaveShape.h" | ||||
| #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" | #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" | ||||
| #include "btSparseSDF.h" | #include "btSparseSDF.h" | ||||
| #include "BulletCollision/BroadphaseCollision/btDbvt.h" | #include "BulletCollision/BroadphaseCollision/btDbvt.h" | ||||
| #include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h" | |||||
| #include "BulletDynamics/Featherstone/btMultiBodyConstraint.h" | |||||
| //#ifdef BT_USE_DOUBLE_PRECISION | //#ifdef BT_USE_DOUBLE_PRECISION | ||||
| //#define btRigidBodyData btRigidBodyDoubleData | //#define btRigidBodyData btRigidBodyDoubleData | ||||
| //#define btRigidBodyDataName "btRigidBodyDoubleData" | //#define btRigidBodyDataName "btRigidBodyDoubleData" | ||||
| //#else | //#else | ||||
| #define btSoftBodyData btSoftBodyFloatData | #define btSoftBodyData btSoftBodyFloatData | ||||
| #define btSoftBodyDataName "btSoftBodyFloatData" | #define btSoftBodyDataName "btSoftBodyFloatData" | ||||
| static const btScalar OVERLAP_REDUCTION_FACTOR = 0.1; | |||||
| static unsigned long seed = 243703; | |||||
| //#endif //BT_USE_DOUBLE_PRECISION | //#endif //BT_USE_DOUBLE_PRECISION | ||||
| class btBroadphaseInterface; | class btBroadphaseInterface; | ||||
| class btDispatcher; | class btDispatcher; | ||||
| class btSoftBodySolver; | class btSoftBodySolver; | ||||
| /* btSoftBodyWorldInfo */ | /* btSoftBodyWorldInfo */ | ||||
| struct btSoftBodyWorldInfo | struct btSoftBodyWorldInfo | ||||
| { | { | ||||
| btScalar air_density; | btScalar air_density; | ||||
| btScalar water_density; | btScalar water_density; | ||||
| btScalar water_offset; | btScalar water_offset; | ||||
| btScalar m_maxDisplacement; | btScalar m_maxDisplacement; | ||||
| btVector3 water_normal; | btVector3 water_normal; | ||||
| btBroadphaseInterface* m_broadphase; | btBroadphaseInterface* m_broadphase; | ||||
| btDispatcher* m_dispatcher; | btDispatcher* m_dispatcher; | ||||
| btVector3 m_gravity; | btVector3 m_gravity; | ||||
| btSparseSdf<3> m_sparsesdf; | btSparseSdf<3> m_sparsesdf; | ||||
| btSoftBodyWorldInfo() | btSoftBodyWorldInfo() | ||||
| :air_density((btScalar)1.2), | : air_density((btScalar)1.2), | ||||
| water_density(0), | water_density(0), | ||||
| water_offset(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 | 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), | water_normal(0, 0, 0), | ||||
| m_broadphase(0), | m_broadphase(0), | ||||
| m_dispatcher(0), | m_dispatcher(0), | ||||
| m_gravity(0,-10,0) | m_gravity(0, -10, 0) | ||||
| { | { | ||||
| } | } | ||||
| }; | }; | ||||
| ///The btSoftBody is an class to simulate cloth and volumetric soft bodies. | ///The btSoftBody is an class to simulate cloth and volumetric soft bodies. | ||||
| ///There is two-way interaction between btSoftBody and btRigidBody/btCollisionObject. | ///There is two-way interaction between btSoftBody and btRigidBody/btCollisionObject. | ||||
| class btSoftBody : public btCollisionObject | class btSoftBody : public btCollisionObject | ||||
| { | { | ||||
| public: | public: | ||||
| btAlignedObjectArray<const class btCollisionObject*> m_collisionDisabledObjects; | btAlignedObjectArray<const class btCollisionObject*> m_collisionDisabledObjects; | ||||
| // The solver object that handles this soft body | // The solver object that handles this soft body | ||||
| btSoftBodySolver *m_softBodySolver; | btSoftBodySolver* m_softBodySolver; | ||||
| // | // | ||||
| // Enumerations | // Enumerations | ||||
| // | // | ||||
| ///eAeroModel | ///eAeroModel | ||||
| struct eAeroModel { enum _ { | struct eAeroModel | ||||
| { | |||||
| enum _ | |||||
| { | |||||
| V_Point, ///Vertex normals are oriented toward velocity | V_Point, ///Vertex normals are oriented toward velocity | ||||
| V_TwoSided, ///Vertex normals are flipped to match 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_TwoSidedLiftDrag, ///Vertex normals are flipped to match velocity and lift and drag forces are applied | ||||
| V_OneSided, ///Vertex normals are taken as it is | V_OneSided, ///Vertex normals are taken as it is | ||||
| F_TwoSided, ///Face normals are flipped to match velocity | 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_TwoSidedLiftDrag, ///Face normals are flipped to match velocity and lift and drag forces are applied | ||||
| F_OneSided, ///Face normals are taken as it is | F_OneSided, ///Face normals are taken as it is | ||||
| END | END | ||||
| };}; | }; | ||||
| }; | |||||
| ///eVSolver : velocities solvers | ///eVSolver : velocities solvers | ||||
| struct eVSolver { enum _ { | struct eVSolver | ||||
| { | |||||
| enum _ | |||||
| { | |||||
| Linear, ///Linear solver | Linear, ///Linear solver | ||||
| END | END | ||||
| };}; | }; | ||||
| }; | |||||
| ///ePSolver : positions solvers | ///ePSolver : positions solvers | ||||
| struct ePSolver { enum _ { | struct ePSolver | ||||
| { | |||||
| enum _ | |||||
| { | |||||
| Linear, ///Linear solver | Linear, ///Linear solver | ||||
| Anchors, ///Anchor solver | Anchors, ///Anchor solver | ||||
| RContacts, ///Rigid contacts solver | RContacts, ///Rigid contacts solver | ||||
| SContacts, ///Soft contacts solver | SContacts, ///Soft contacts solver | ||||
| END | END | ||||
| };}; | }; | ||||
| }; | |||||
| ///eSolverPresets | ///eSolverPresets | ||||
| struct eSolverPresets { enum _ { | struct eSolverPresets | ||||
| { | |||||
| enum _ | |||||
| { | |||||
| Positions, | Positions, | ||||
| Velocities, | Velocities, | ||||
| Default = Positions, | Default = Positions, | ||||
| END | END | ||||
| };}; | }; | ||||
| }; | |||||
| ///eFeature | ///eFeature | ||||
| struct eFeature { enum _ { | struct eFeature | ||||
| { | |||||
| enum _ | |||||
| { | |||||
| None, | None, | ||||
| Node, | Node, | ||||
| Link, | Link, | ||||
| Face, | Face, | ||||
| Tetra, | Tetra, | ||||
| END | END | ||||
| };}; | }; | ||||
| }; | |||||
| typedef btAlignedObjectArray<eVSolver::_> tVSolverArray; | typedef btAlignedObjectArray<eVSolver::_> tVSolverArray; | ||||
| typedef btAlignedObjectArray<ePSolver::_> tPSolverArray; | typedef btAlignedObjectArray<ePSolver::_> tPSolverArray; | ||||
| // | // | ||||
| // Flags | // Flags | ||||
| // | // | ||||
| ///fCollision | ///fCollision | ||||
| struct fCollision { enum _ { | struct fCollision | ||||
| { | |||||
| enum _ | |||||
| { | |||||
| RVSmask = 0x000f, ///Rigid versus soft mask | RVSmask = 0x000f, ///Rigid versus soft mask | ||||
| SDF_RS = 0x0001, ///SDF based rigid vs soft | SDF_RS = 0x0001, ///SDF based rigid vs soft | ||||
| CL_RS = 0x0002, ///Cluster vs convex rigid vs soft | CL_RS = 0x0002, ///Cluster vs convex rigid vs soft | ||||
| SDF_RD = 0x0004, ///rigid vs deformable | |||||
| SVSmask = 0x0030, ///Rigid versus soft mask | SVSmask = 0x00f0, ///Rigid versus soft mask | ||||
| VF_SS = 0x0010, ///Vertex vs face soft vs soft handling | VF_SS = 0x0010, ///Vertex vs face soft vs soft handling | ||||
| CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling | CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling | ||||
| CL_SELF = 0x0040, ///Cluster soft body self collision | CL_SELF = 0x0040, ///Cluster soft body self collision | ||||
| VF_DD = 0x0080, ///Vertex vs face soft vs soft handling | |||||
| RVDFmask = 0x0f00, /// Rigid versus deformable face mask | |||||
| SDF_RDF = 0x0100, /// GJK based Rigid vs. deformable face | |||||
| SDF_MDF = 0x0200, /// GJK based Multibody vs. deformable face | |||||
| SDF_RDN = 0x0400, /// SDF based Rigid vs. deformable node | |||||
| /* presets */ | /* presets */ | ||||
| Default = SDF_RS, | Default = SDF_RS, | ||||
| END | END | ||||
| };}; | }; | ||||
| }; | |||||
| ///fMaterial | ///fMaterial | ||||
| struct fMaterial { enum _ { | struct fMaterial | ||||
| { | |||||
| enum _ | |||||
| { | |||||
| DebugDraw = 0x0001, /// Enable debug draw | DebugDraw = 0x0001, /// Enable debug draw | ||||
| /* presets */ | /* presets */ | ||||
| Default = DebugDraw, | Default = DebugDraw, | ||||
| END | END | ||||
| };}; | }; | ||||
| }; | |||||
| // | // | ||||
| // API Types | // API Types | ||||
| // | // | ||||
| /* sRayCast */ | /* sRayCast */ | ||||
| struct sRayCast | struct sRayCast | ||||
| { | { | ||||
| btSoftBody* body; /// soft body | btSoftBody* body; /// soft body | ||||
| eFeature::_ feature; /// feature type | eFeature::_ feature; /// feature type | ||||
| int index; /// feature index | int index; /// feature index | ||||
| btScalar fraction; /// time of impact fraction (rayorg+(rayto-rayfrom)*fraction) | btScalar fraction; /// time of impact fraction (rayorg+(rayto-rayfrom)*fraction) | ||||
| }; | }; | ||||
| /* ImplicitFn */ | /* ImplicitFn */ | ||||
| struct ImplicitFn | struct ImplicitFn | ||||
| { | { | ||||
| virtual ~ImplicitFn() {} | virtual ~ImplicitFn() {} | ||||
| virtual btScalar Eval(const btVector3& x)=0; | virtual btScalar Eval(const btVector3& x) = 0; | ||||
| }; | }; | ||||
| // | // | ||||
| // Internal types | // Internal types | ||||
| // | // | ||||
| typedef btAlignedObjectArray<btScalar> tScalarArray; | typedef btAlignedObjectArray<btScalar> tScalarArray; | ||||
| typedef btAlignedObjectArray<btVector3> tVector3Array; | typedef btAlignedObjectArray<btVector3> tVector3Array; | ||||
| /* sCti is Softbody contact info */ | /* sCti is Softbody contact info */ | ||||
| struct sCti | struct sCti | ||||
| { | { | ||||
| const btCollisionObject* m_colObj; /* Rigid body */ | const btCollisionObject* m_colObj; /* Rigid body */ | ||||
| btVector3 m_normal; /* Outward normal */ | btVector3 m_normal; /* Outward normal */ | ||||
| btScalar m_offset; /* Offset from origin */ | btScalar m_offset; /* Offset from origin */ | ||||
| btVector3 m_bary; /* Barycentric weights for faces */ | |||||
| }; | }; | ||||
| /* sMedium */ | /* sMedium */ | ||||
| struct sMedium | struct sMedium | ||||
| { | { | ||||
| btVector3 m_velocity; /* Velocity */ | btVector3 m_velocity; /* Velocity */ | ||||
| btScalar m_pressure; /* Pressure */ | btScalar m_pressure; /* Pressure */ | ||||
| btScalar m_density; /* Density */ | btScalar m_density; /* Density */ | ||||
| }; | }; | ||||
| /* Base type */ | /* Base type */ | ||||
| struct Element | struct Element | ||||
| { | { | ||||
| void* m_tag; // User data | void* m_tag; // User data | ||||
| Element() : m_tag(0) {} | Element() : m_tag(0) {} | ||||
| }; | }; | ||||
| /* Material */ | /* Material */ | ||||
| struct Material : Element | struct Material : Element | ||||
| { | { | ||||
| btScalar m_kLST; // Linear stiffness coefficient [0,1] | btScalar m_kLST; // Linear stiffness coefficient [0,1] | ||||
| btScalar m_kAST; // Area/Angular stiffness coefficient [0,1] | btScalar m_kAST; // Area/Angular stiffness coefficient [0,1] | ||||
| btScalar m_kVST; // Volume stiffness coefficient [0,1] | btScalar m_kVST; // Volume stiffness coefficient [0,1] | ||||
| int m_flags; // Flags | int m_flags; // Flags | ||||
| }; | }; | ||||
| /* Feature */ | /* Feature */ | ||||
| struct Feature : Element | struct Feature : Element | ||||
| { | { | ||||
| Material* m_material; // Material | Material* m_material; // Material | ||||
| }; | }; | ||||
| /* Node */ | /* Node */ | ||||
| struct Node : Feature | struct Node : Feature | ||||
| { | { | ||||
| btVector3 m_x; // Position | btVector3 m_x; // Position | ||||
| btVector3 m_q; // Previous step position | btVector3 m_q; // Previous step position/Test position | ||||
| btVector3 m_v; // Velocity | btVector3 m_v; // Velocity | ||||
| btVector3 m_vn; // Previous step velocity | |||||
| btVector3 m_f; // Force accumulator | btVector3 m_f; // Force accumulator | ||||
| btVector3 m_n; // Normal | btVector3 m_n; // Normal | ||||
| btScalar m_im; // 1/mass | btScalar m_im; // 1/mass | ||||
| btScalar m_area; // Area | btScalar m_area; // Area | ||||
| btDbvtNode* m_leaf; // Leaf data | btDbvtNode* m_leaf; // Leaf data | ||||
| int m_constrained; // depth of penetration | |||||
| int m_battach:1; // Attached | int m_battach : 1; // Attached | ||||
| int index; | |||||
| btVector3 m_splitv; // velocity associated with split impulse | |||||
| btMatrix3x3 m_effectiveMass; // effective mass in contact | |||||
| btMatrix3x3 m_effectiveMass_inv; // inverse of effective mass | |||||
| }; | }; | ||||
| /* Link */ | /* Link */ | ||||
| struct Link : Feature | ATTRIBUTE_ALIGNED16(struct) | ||||
| Link : Feature | |||||
| { | { | ||||
| btVector3 m_c3; // gradient | |||||
| Node* m_n[2]; // Node pointers | Node* m_n[2]; // Node pointers | ||||
| btScalar m_rl; // Rest length | btScalar m_rl; // Rest length | ||||
| int m_bbending:1; // Bending link | int m_bbending : 1; // Bending link | ||||
| btScalar m_c0; // (ima+imb)*kLST | btScalar m_c0; // (ima+imb)*kLST | ||||
| btScalar m_c1; // rl^2 | btScalar m_c1; // rl^2 | ||||
| btScalar m_c2; // |gradient|^2/c0 | btScalar m_c2; // |gradient|^2/c0 | ||||
| btVector3 m_c3; // gradient | |||||
| BT_DECLARE_ALIGNED_ALLOCATOR(); | |||||
| }; | }; | ||||
| /* Face */ | /* Face */ | ||||
| struct Face : Feature | struct Face : Feature | ||||
| { | { | ||||
| Node* m_n[3]; // Node pointers | Node* m_n[3]; // Node pointers | ||||
| btVector3 m_normal; // Normal | btVector3 m_normal; // Normal | ||||
| btScalar m_ra; // Rest area | btScalar m_ra; // Rest area | ||||
| btDbvtNode* m_leaf; // Leaf data | btDbvtNode* m_leaf; // Leaf data | ||||
| btVector4 m_pcontact; // barycentric weights of the persistent contact | |||||
| btVector3 m_n0, m_n1, m_vn; | |||||
| int m_index; | |||||
| }; | }; | ||||
| /* Tetra */ | /* Tetra */ | ||||
| struct Tetra : Feature | struct Tetra : Feature | ||||
| { | { | ||||
| Node* m_n[4]; // Node pointers | Node* m_n[4]; // Node pointers | ||||
| btScalar m_rv; // Rest volume | btScalar m_rv; // Rest volume | ||||
| btDbvtNode* m_leaf; // Leaf data | btDbvtNode* m_leaf; // Leaf data | ||||
| btVector3 m_c0[4]; // gradients | btVector3 m_c0[4]; // gradients | ||||
| btScalar m_c1; // (4*kVST)/(im0+im1+im2+im3) | btScalar m_c1; // (4*kVST)/(im0+im1+im2+im3) | ||||
| btScalar m_c2; // m_c1/sum(|g0..3|^2) | btScalar m_c2; // m_c1/sum(|g0..3|^2) | ||||
| btMatrix3x3 m_Dm_inverse; // rest Dm^-1 | |||||
| btMatrix3x3 m_F; | |||||
| btScalar m_element_measure; | |||||
| btVector4 m_P_inv[3]; // first three columns of P_inv matrix | |||||
| }; | }; | ||||
| /* TetraScratch */ | |||||
| struct TetraScratch | |||||
| { | |||||
| btMatrix3x3 m_F; // deformation gradient F | |||||
| btScalar m_trace; // trace of F^T * F | |||||
| btScalar m_J; // det(F) | |||||
| btMatrix3x3 m_cofF; // cofactor of F | |||||
| btMatrix3x3 m_corotation; // corotatio of the tetra | |||||
| }; | |||||
| /* RContact */ | /* RContact */ | ||||
| struct RContact | struct RContact | ||||
| { | { | ||||
| sCti m_cti; // Contact infos | sCti m_cti; // Contact infos | ||||
| Node* m_node; // Owner node | Node* m_node; // Owner node | ||||
| btMatrix3x3 m_c0; // Impulse matrix | btMatrix3x3 m_c0; // Impulse matrix | ||||
| btVector3 m_c1; // Relative anchor | btVector3 m_c1; // Relative anchor | ||||
| btScalar m_c2; // ima*dt | btScalar m_c2; // ima*dt | ||||
| btScalar m_c3; // Friction | btScalar m_c3; // Friction | ||||
| btScalar m_c4; // Hardness | btScalar m_c4; // Hardness | ||||
| // jacobians and unit impulse responses for multibody | |||||
| btMultiBodyJacobianData jacobianData_normal; | |||||
| btMultiBodyJacobianData jacobianData_t1; | |||||
| btMultiBodyJacobianData jacobianData_t2; | |||||
| btVector3 t1; | |||||
| btVector3 t2; | |||||
| }; | |||||
| class DeformableRigidContact | |||||
| { | |||||
| public: | |||||
| sCti m_cti; // Contact infos | |||||
| btMatrix3x3 m_c0; // Impulse matrix | |||||
| btVector3 m_c1; // Relative anchor | |||||
| btScalar m_c2; // inverse mass of node/face | |||||
| btScalar m_c3; // Friction | |||||
| btScalar m_c4; // Hardness | |||||
| btMatrix3x3 m_c5; // inverse effective mass | |||||
| // jacobians and unit impulse responses for multibody | |||||
| btMultiBodyJacobianData jacobianData_normal; | |||||
| btMultiBodyJacobianData jacobianData_t1; | |||||
| btMultiBodyJacobianData jacobianData_t2; | |||||
| btVector3 t1; | |||||
| btVector3 t2; | |||||
| }; | |||||
| class DeformableNodeRigidContact : public DeformableRigidContact | |||||
| { | |||||
| public: | |||||
| Node* m_node; // Owner node | |||||
| }; | |||||
| class DeformableNodeRigidAnchor : public DeformableNodeRigidContact | |||||
| { | |||||
| public: | |||||
| btVector3 m_local; // Anchor position in body space | |||||
| }; | |||||
| class DeformableFaceRigidContact : public DeformableRigidContact | |||||
| { | |||||
| public: | |||||
| Face* m_face; // Owner face | |||||
| btVector3 m_contactPoint; // Contact point | |||||
| btVector3 m_bary; // Barycentric weights | |||||
| btVector3 m_weights; // v_contactPoint * m_weights[i] = m_face->m_node[i]->m_v; | |||||
| }; | }; | ||||
| struct DeformableFaceNodeContact | |||||
| { | |||||
| Node* m_node; // Node | |||||
| Face* m_face; // Face | |||||
| btVector3 m_bary; // Barycentric weights | |||||
| btVector3 m_weights; // v_contactPoint * m_weights[i] = m_face->m_node[i]->m_v; | |||||
| btVector3 m_normal; // Normal | |||||
| btScalar m_margin; // Margin | |||||
| btScalar m_friction; // Friction | |||||
| btScalar m_imf; // inverse mass of the face at contact point | |||||
| btScalar m_c0; // scale of the impulse matrix; | |||||
| }; | |||||
| /* SContact */ | /* SContact */ | ||||
| struct SContact | struct SContact | ||||
| { | { | ||||
| Node* m_node; // Node | Node* m_node; // Node | ||||
| Face* m_face; // Face | Face* m_face; // Face | ||||
| btVector3 m_weights; // Weigths | btVector3 m_weights; // Weigths | ||||
| btVector3 m_normal; // Normal | btVector3 m_normal; // Normal | ||||
| btScalar m_margin; // Margin | btScalar m_margin; // Margin | ||||
| btScalar m_friction; // Friction | btScalar m_friction; // Friction | ||||
| btScalar m_cfm[2]; // Constraint force mixing | btScalar m_cfm[2]; // Constraint force mixing | ||||
| }; | }; | ||||
| /* Anchor */ | /* Anchor */ | ||||
| struct Anchor | struct Anchor | ||||
| { | { | ||||
| Node* m_node; // Node pointer | Node* m_node; // Node pointer | ||||
| btVector3 m_local; // Anchor position in body space | btVector3 m_local; // Anchor position in body space | ||||
| btRigidBody* m_body; // Body | btRigidBody* m_body; // Body | ||||
| btScalar m_influence; | btScalar m_influence; | ||||
| btMatrix3x3 m_c0; // Impulse matrix | btMatrix3x3 m_c0; // Impulse matrix | ||||
| btVector3 m_c1; // Relative anchor | btVector3 m_c1; // Relative anchor | ||||
| btScalar m_c2; // ima*dt | btScalar m_c2; // ima*dt | ||||
| }; | }; | ||||
| /* Note */ | /* Note */ | ||||
| struct Note : Element | struct Note : Element | ||||
| { | { | ||||
| const char* m_text; // Text | const char* m_text; // Text | ||||
| btVector3 m_offset; // Offset | btVector3 m_offset; // Offset | ||||
| int m_rank; // Rank | int m_rank; // Rank | ||||
| Node* m_nodes[4]; // Nodes | Node* m_nodes[4]; // Nodes | ||||
| btScalar m_coords[4]; // Coordinates | btScalar m_coords[4]; // Coordinates | ||||
| }; | }; | ||||
| /* Pose */ | /* Pose */ | ||||
| struct Pose | struct Pose | ||||
| { | { | ||||
| bool m_bvolume; // Is valid | bool m_bvolume; // Is valid | ||||
| bool m_bframe; // Is frame | bool m_bframe; // Is frame | ||||
| btScalar m_volume; // Rest volume | btScalar m_volume; // Rest volume | ||||
| tVector3Array m_pos; // Reference positions | tVector3Array m_pos; // Reference positions | ||||
| tScalarArray m_wgh; // Weights | tScalarArray m_wgh; // Weights | ||||
| btVector3 m_com; // COM | btVector3 m_com; // COM | ||||
| btMatrix3x3 m_rot; // Rotation | btMatrix3x3 m_rot; // Rotation | ||||
| btMatrix3x3 m_scl; // Scale | btMatrix3x3 m_scl; // Scale | ||||
| btMatrix3x3 m_aqq; // Base scaling | btMatrix3x3 m_aqq; // Base scaling | ||||
| }; | }; | ||||
| /* Cluster */ | /* Cluster */ | ||||
| struct Cluster | struct Cluster | ||||
| { | { | ||||
| tScalarArray m_masses; | tScalarArray m_masses; | ||||
| btAlignedObjectArray<Node*> m_nodes; | btAlignedObjectArray<Node*> m_nodes; | ||||
| tVector3Array m_framerefs; | tVector3Array m_framerefs; | ||||
| btTransform m_framexform; | btTransform m_framexform; | ||||
| btScalar m_idmass; | btScalar m_idmass; | ||||
| btScalar m_imass; | btScalar m_imass; | ||||
| btMatrix3x3 m_locii; | btMatrix3x3 m_locii; | ||||
| btMatrix3x3 m_invwi; | btMatrix3x3 m_invwi; | ||||
| btVector3 m_com; | btVector3 m_com; | ||||
| btVector3 m_vimpulses[2]; | btVector3 m_vimpulses[2]; | ||||
| btVector3 m_dimpulses[2]; | btVector3 m_dimpulses[2]; | ||||
| int m_nvimpulses; | int m_nvimpulses; | ||||
| int m_ndimpulses; | int m_ndimpulses; | ||||
| btVector3 m_lv; | btVector3 m_lv; | ||||
| btVector3 m_av; | btVector3 m_av; | ||||
| btDbvtNode* m_leaf; | btDbvtNode* m_leaf; | ||||
| btScalar m_ndamping; /* Node damping */ | btScalar m_ndamping; /* Node damping */ | ||||
| btScalar m_ldamping; /* Linear damping */ | btScalar m_ldamping; /* Linear damping */ | ||||
| btScalar m_adamping; /* Angular damping */ | btScalar m_adamping; /* Angular damping */ | ||||
| btScalar m_matching; | btScalar m_matching; | ||||
| btScalar m_maxSelfCollisionImpulse; | btScalar m_maxSelfCollisionImpulse; | ||||
| btScalar m_selfCollisionImpulseFactor; | btScalar m_selfCollisionImpulseFactor; | ||||
| bool m_containsAnchor; | bool m_containsAnchor; | ||||
| bool m_collide; | bool m_collide; | ||||
| int m_clusterIndex; | int m_clusterIndex; | ||||
| Cluster() : m_leaf(0),m_ndamping(0),m_ldamping(0),m_adamping(0),m_matching(0) | 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) | ||||
| ,m_maxSelfCollisionImpulse(100.f), | { | ||||
| m_selfCollisionImpulseFactor(0.01f), | } | ||||
| m_containsAnchor(false) | |||||
| {} | |||||
| }; | }; | ||||
| /* Impulse */ | /* Impulse */ | ||||
| struct Impulse | struct Impulse | ||||
| { | { | ||||
| btVector3 m_velocity; | btVector3 m_velocity; | ||||
| btVector3 m_drift; | btVector3 m_drift; | ||||
| int m_asVelocity:1; | int m_asVelocity : 1; | ||||
| int m_asDrift:1; | int m_asDrift : 1; | ||||
| Impulse() : m_velocity(0,0,0),m_drift(0,0,0),m_asVelocity(0),m_asDrift(0) {} | Impulse() : m_velocity(0, 0, 0), m_drift(0, 0, 0), m_asVelocity(0), m_asDrift(0) {} | ||||
| Impulse operator -() const | Impulse operator-() const | ||||
| { | { | ||||
| Impulse i=*this; | Impulse i = *this; | ||||
| i.m_velocity=-i.m_velocity; | i.m_velocity = -i.m_velocity; | ||||
| i.m_drift=-i.m_drift; | i.m_drift = -i.m_drift; | ||||
| return(i); | return (i); | ||||
| } | } | ||||
| Impulse operator*(btScalar x) const | Impulse operator*(btScalar x) const | ||||
| { | { | ||||
| Impulse i=*this; | Impulse i = *this; | ||||
| i.m_velocity*=x; | i.m_velocity *= x; | ||||
| i.m_drift*=x; | i.m_drift *= x; | ||||
| return(i); | return (i); | ||||
| } | } | ||||
| }; | }; | ||||
| /* Body */ | /* Body */ | ||||
| struct Body | struct Body | ||||
| { | { | ||||
| Cluster* m_soft; | Cluster* m_soft; | ||||
| btRigidBody* m_rigid; | btRigidBody* m_rigid; | ||||
| const btCollisionObject* m_collisionObject; | const btCollisionObject* m_collisionObject; | ||||
| Body() : m_soft(0),m_rigid(0),m_collisionObject(0) {} | Body() : m_soft(0), m_rigid(0), m_collisionObject(0) {} | ||||
| Body(Cluster* p) : m_soft(p),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) | Body(const btCollisionObject* colObj) : m_soft(0), m_collisionObject(colObj) | ||||
| { | { | ||||
| m_rigid = (btRigidBody*)btRigidBody::upcast(m_collisionObject); | m_rigid = (btRigidBody*)btRigidBody::upcast(m_collisionObject); | ||||
| } | } | ||||
| void activate() const | void activate() const | ||||
| { | { | ||||
| if(m_rigid) | if (m_rigid) | ||||
| m_rigid->activate(); | m_rigid->activate(); | ||||
| if (m_collisionObject) | if (m_collisionObject) | ||||
| m_collisionObject->activate(); | m_collisionObject->activate(); | ||||
| } | } | ||||
| const btMatrix3x3& invWorldInertia() const | const btMatrix3x3& invWorldInertia() const | ||||
| { | { | ||||
| static const btMatrix3x3 iwi(0,0,0,0,0,0,0,0,0); | static const btMatrix3x3 iwi(0, 0, 0, 0, 0, 0, 0, 0, 0); | ||||
| if(m_rigid) return(m_rigid->getInvInertiaTensorWorld()); | if (m_rigid) return (m_rigid->getInvInertiaTensorWorld()); | ||||
| if(m_soft) return(m_soft->m_invwi); | if (m_soft) return (m_soft->m_invwi); | ||||
| return(iwi); | return (iwi); | ||||
| } | } | ||||
| btScalar invMass() const | btScalar invMass() const | ||||
| { | { | ||||
| if(m_rigid) return(m_rigid->getInvMass()); | if (m_rigid) return (m_rigid->getInvMass()); | ||||
| if(m_soft) return(m_soft->m_imass); | if (m_soft) return (m_soft->m_imass); | ||||
| return(0); | return (0); | ||||
| } | } | ||||
| const btTransform& xform() const | const btTransform& xform() const | ||||
| { | { | ||||
| static const btTransform identity=btTransform::getIdentity(); | static const btTransform identity = btTransform::getIdentity(); | ||||
| if(m_collisionObject) return(m_collisionObject->getWorldTransform()); | if (m_collisionObject) return (m_collisionObject->getWorldTransform()); | ||||
| if(m_soft) return(m_soft->m_framexform); | if (m_soft) return (m_soft->m_framexform); | ||||
| return(identity); | return (identity); | ||||
| } | } | ||||
| btVector3 linearVelocity() const | btVector3 linearVelocity() const | ||||
| { | { | ||||
| if(m_rigid) return(m_rigid->getLinearVelocity()); | if (m_rigid) return (m_rigid->getLinearVelocity()); | ||||
| if(m_soft) return(m_soft->m_lv); | if (m_soft) return (m_soft->m_lv); | ||||
| return(btVector3(0,0,0)); | return (btVector3(0, 0, 0)); | ||||
| } | } | ||||
| btVector3 angularVelocity(const btVector3& rpos) const | btVector3 angularVelocity(const btVector3& rpos) const | ||||
| { | { | ||||
| if(m_rigid) return(btCross(m_rigid->getAngularVelocity(),rpos)); | if (m_rigid) return (btCross(m_rigid->getAngularVelocity(), rpos)); | ||||
| if(m_soft) return(btCross(m_soft->m_av,rpos)); | if (m_soft) return (btCross(m_soft->m_av, rpos)); | ||||
| return(btVector3(0,0,0)); | return (btVector3(0, 0, 0)); | ||||
| } | } | ||||
| btVector3 angularVelocity() const | btVector3 angularVelocity() const | ||||
| { | { | ||||
| if(m_rigid) return(m_rigid->getAngularVelocity()); | if (m_rigid) return (m_rigid->getAngularVelocity()); | ||||
| if(m_soft) return(m_soft->m_av); | if (m_soft) return (m_soft->m_av); | ||||
| return(btVector3(0,0,0)); | return (btVector3(0, 0, 0)); | ||||
| } | } | ||||
| btVector3 velocity(const btVector3& rpos) const | btVector3 velocity(const btVector3& rpos) const | ||||
| { | { | ||||
| return(linearVelocity()+angularVelocity(rpos)); | return (linearVelocity() + angularVelocity(rpos)); | ||||
| } | } | ||||
| void applyVImpulse(const btVector3& impulse,const btVector3& rpos) const | void applyVImpulse(const btVector3& impulse, const btVector3& rpos) const | ||||
| { | { | ||||
| if(m_rigid) m_rigid->applyImpulse(impulse,rpos); | if (m_rigid) m_rigid->applyImpulse(impulse, rpos); | ||||
| if(m_soft) btSoftBody::clusterVImpulse(m_soft,rpos,impulse); | if (m_soft) btSoftBody::clusterVImpulse(m_soft, rpos, impulse); | ||||
| } | } | ||||
| void applyDImpulse(const btVector3& impulse,const btVector3& rpos) const | void applyDImpulse(const btVector3& impulse, const btVector3& rpos) const | ||||
| { | { | ||||
| if(m_rigid) m_rigid->applyImpulse(impulse,rpos); | if (m_rigid) m_rigid->applyImpulse(impulse, rpos); | ||||
| if(m_soft) btSoftBody::clusterDImpulse(m_soft,rpos,impulse); | if (m_soft) btSoftBody::clusterDImpulse(m_soft, rpos, impulse); | ||||
| } | } | ||||
| void applyImpulse(const Impulse& impulse,const btVector3& rpos) const | void applyImpulse(const Impulse& impulse, const btVector3& rpos) const | ||||
| { | { | ||||
| if(impulse.m_asVelocity) | if (impulse.m_asVelocity) | ||||
| { | { | ||||
| // printf("impulse.m_velocity = %f,%f,%f\n",impulse.m_velocity.getX(),impulse.m_velocity.getY(),impulse.m_velocity.getZ()); | // 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); | applyVImpulse(impulse.m_velocity, rpos); | ||||
| } | } | ||||
| if(impulse.m_asDrift) | if (impulse.m_asDrift) | ||||
| { | { | ||||
| // printf("impulse.m_drift = %f,%f,%f\n",impulse.m_drift.getX(),impulse.m_drift.getY(),impulse.m_drift.getZ()); | // 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); | applyDImpulse(impulse.m_drift, rpos); | ||||
| } | } | ||||
| } | } | ||||
| void applyVAImpulse(const btVector3& impulse) const | void applyVAImpulse(const btVector3& impulse) const | ||||
| { | { | ||||
| if(m_rigid) m_rigid->applyTorqueImpulse(impulse); | if (m_rigid) m_rigid->applyTorqueImpulse(impulse); | ||||
| if(m_soft) btSoftBody::clusterVAImpulse(m_soft,impulse); | if (m_soft) btSoftBody::clusterVAImpulse(m_soft, impulse); | ||||
| } | } | ||||
| void applyDAImpulse(const btVector3& impulse) const | void applyDAImpulse(const btVector3& impulse) const | ||||
| { | { | ||||
| if(m_rigid) m_rigid->applyTorqueImpulse(impulse); | if (m_rigid) m_rigid->applyTorqueImpulse(impulse); | ||||
| if(m_soft) btSoftBody::clusterDAImpulse(m_soft,impulse); | if (m_soft) btSoftBody::clusterDAImpulse(m_soft, impulse); | ||||
| } | } | ||||
| void applyAImpulse(const Impulse& impulse) const | void applyAImpulse(const Impulse& impulse) const | ||||
| { | { | ||||
| if(impulse.m_asVelocity) applyVAImpulse(impulse.m_velocity); | if (impulse.m_asVelocity) applyVAImpulse(impulse.m_velocity); | ||||
| if(impulse.m_asDrift) applyDAImpulse(impulse.m_drift); | if (impulse.m_asDrift) applyDAImpulse(impulse.m_drift); | ||||
| } | } | ||||
| void applyDCImpulse(const btVector3& impulse) const | void applyDCImpulse(const btVector3& impulse) const | ||||
| { | { | ||||
| if(m_rigid) m_rigid->applyCentralImpulse(impulse); | if (m_rigid) m_rigid->applyCentralImpulse(impulse); | ||||
| if(m_soft) btSoftBody::clusterDCImpulse(m_soft,impulse); | if (m_soft) btSoftBody::clusterDCImpulse(m_soft, impulse); | ||||
| } | } | ||||
| }; | }; | ||||
| /* Joint */ | /* Joint */ | ||||
| struct Joint | struct Joint | ||||
| { | { | ||||
| struct eType { enum _ { | struct eType | ||||
| { | |||||
| enum _ | |||||
| { | |||||
| Linear=0, | Linear = 0, | ||||
| Angular, | Angular, | ||||
| Contact | Contact | ||||
| };}; | }; | ||||
| }; | |||||
| struct Specs | struct Specs | ||||
| { | { | ||||
| Specs() : erp(1),cfm(1),split(1) {} | Specs() : erp(1), cfm(1), split(1) {} | ||||
| btScalar erp; | btScalar erp; | ||||
| btScalar cfm; | btScalar cfm; | ||||
| btScalar split; | btScalar split; | ||||
| }; | }; | ||||
| Body m_bodies[2]; | Body m_bodies[2]; | ||||
| btVector3 m_refs[2]; | btVector3 m_refs[2]; | ||||
| btScalar m_cfm; | btScalar m_cfm; | ||||
| btScalar m_erp; | btScalar m_erp; | ||||
| btScalar m_split; | btScalar m_split; | ||||
| btVector3 m_drift; | btVector3 m_drift; | ||||
| btVector3 m_sdrift; | btVector3 m_sdrift; | ||||
| btMatrix3x3 m_massmatrix; | btMatrix3x3 m_massmatrix; | ||||
| bool m_delete; | bool m_delete; | ||||
| virtual ~Joint() {} | virtual ~Joint() {} | ||||
| Joint() : m_delete(false) {} | Joint() : m_delete(false) {} | ||||
| virtual void Prepare(btScalar dt,int iterations); | virtual void Prepare(btScalar dt, int iterations); | ||||
| virtual void Solve(btScalar dt,btScalar sor)=0; | virtual void Solve(btScalar dt, btScalar sor) = 0; | ||||
| virtual void Terminate(btScalar dt)=0; | virtual void Terminate(btScalar dt) = 0; | ||||
| virtual eType::_ Type() const=0; | virtual eType::_ Type() const = 0; | ||||
| }; | }; | ||||
| /* LJoint */ | /* LJoint */ | ||||
| struct LJoint : Joint | struct LJoint : Joint | ||||
| { | { | ||||
| struct Specs : Joint::Specs | struct Specs : Joint::Specs | ||||
| { | { | ||||
| btVector3 position; | btVector3 position; | ||||
| }; | }; | ||||
| btVector3 m_rpos[2]; | btVector3 m_rpos[2]; | ||||
| void Prepare(btScalar dt,int iterations); | void Prepare(btScalar dt, int iterations); | ||||
| void Solve(btScalar dt,btScalar sor); | void Solve(btScalar dt, btScalar sor); | ||||
| void Terminate(btScalar dt); | void Terminate(btScalar dt); | ||||
| eType::_ Type() const { return(eType::Linear); } | eType::_ Type() const { return (eType::Linear); } | ||||
| }; | }; | ||||
| /* AJoint */ | /* AJoint */ | ||||
| struct AJoint : Joint | struct AJoint : Joint | ||||
| { | { | ||||
| struct IControl | struct IControl | ||||
| { | { | ||||
| virtual ~IControl() {} | virtual ~IControl() {} | ||||
| virtual void Prepare(AJoint*) {} | virtual void Prepare(AJoint*) {} | ||||
| virtual btScalar Speed(AJoint*,btScalar current) { return(current); } | virtual btScalar Speed(AJoint*, btScalar current) { return (current); } | ||||
| static IControl* Default() { static IControl def;return(&def); } | static IControl* Default() | ||||
| { | |||||
| static IControl def; | |||||
| return (&def); | |||||
| } | |||||
| }; | }; | ||||
| struct Specs : Joint::Specs | struct Specs : Joint::Specs | ||||
| { | { | ||||
| Specs() : icontrol(IControl::Default()) {} | Specs() : icontrol(IControl::Default()) {} | ||||
| btVector3 axis; | btVector3 axis; | ||||
| IControl* icontrol; | IControl* icontrol; | ||||
| }; | }; | ||||
| btVector3 m_axis[2]; | btVector3 m_axis[2]; | ||||
| IControl* m_icontrol; | IControl* m_icontrol; | ||||
| void Prepare(btScalar dt,int iterations); | void Prepare(btScalar dt, int iterations); | ||||
| void Solve(btScalar dt,btScalar sor); | void Solve(btScalar dt, btScalar sor); | ||||
| void Terminate(btScalar dt); | void Terminate(btScalar dt); | ||||
| eType::_ Type() const { return(eType::Angular); } | eType::_ Type() const { return (eType::Angular); } | ||||
| }; | }; | ||||
| /* CJoint */ | /* CJoint */ | ||||
| struct CJoint : Joint | struct CJoint : Joint | ||||
| { | { | ||||
| int m_life; | int m_life; | ||||
| int m_maxlife; | int m_maxlife; | ||||
| btVector3 m_rpos[2]; | btVector3 m_rpos[2]; | ||||
| btVector3 m_normal; | btVector3 m_normal; | ||||
| btScalar m_friction; | btScalar m_friction; | ||||
| void Prepare(btScalar dt,int iterations); | void Prepare(btScalar dt, int iterations); | ||||
| void Solve(btScalar dt,btScalar sor); | void Solve(btScalar dt, btScalar sor); | ||||
| void Terminate(btScalar dt); | void Terminate(btScalar dt); | ||||
| eType::_ Type() const { return(eType::Contact); } | eType::_ Type() const { return (eType::Contact); } | ||||
| }; | }; | ||||
| /* Config */ | /* Config */ | ||||
| struct Config | struct Config | ||||
| { | { | ||||
| eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point) | eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point) | ||||
| btScalar kVCF; // Velocities correction factor (Baumgarte) | btScalar kVCF; // Velocities correction factor (Baumgarte) | ||||
| btScalar kDP; // Damping coefficient [0,1] | btScalar kDP; // Damping coefficient [0,1] | ||||
| btScalar kDG; // Drag coefficient [0,+inf] | btScalar kDG; // Drag coefficient [0,+inf] | ||||
| btScalar kLF; // Lift coefficient [0,+inf] | btScalar kLF; // Lift coefficient [0,+inf] | ||||
| btScalar kPR; // Pressure coefficient [-inf,+inf] | btScalar kPR; // Pressure coefficient [-inf,+inf] | ||||
| btScalar kVC; // Volume conversation coefficient [0,+inf] | btScalar kVC; // Volume conversation coefficient [0,+inf] | ||||
| btScalar kDF; // Dynamic friction coefficient [0,1] | btScalar kDF; // Dynamic friction coefficient [0,1] | ||||
| btScalar kMT; // Pose matching coefficient [0,1] | btScalar kMT; // Pose matching coefficient [0,1] | ||||
| btScalar kCHR; // Rigid contacts hardness [0,1] | btScalar kCHR; // Rigid contacts hardness [0,1] | ||||
| btScalar kKHR; // Kinetic contacts hardness [0,1] | btScalar kKHR; // Kinetic contacts hardness [0,1] | ||||
| btScalar kSHR; // Soft contacts hardness [0,1] | btScalar kSHR; // Soft contacts hardness [0,1] | ||||
| btScalar kAHR; // Anchors hardness [0,1] | btScalar kAHR; // Anchors hardness [0,1] | ||||
| btScalar kSRHR_CL; // Soft vs rigid hardness [0,1] (cluster only) | btScalar kSRHR_CL; // Soft vs rigid hardness [0,1] (cluster only) | ||||
| btScalar kSKHR_CL; // Soft vs kinetic 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 kSSHR_CL; // Soft vs soft hardness [0,1] (cluster only) | ||||
| btScalar kSR_SPLT_CL; // Soft vs rigid impulse split [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 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 kSS_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) | ||||
| btScalar maxvolume; // Maximum volume ratio for pose | btScalar maxvolume; // Maximum volume ratio for pose | ||||
| btScalar timescale; // Time scale | btScalar timescale; // Time scale | ||||
| int viterations; // Velocities solver iterations | int viterations; // Velocities solver iterations | ||||
| int piterations; // Positions solver iterations | int piterations; // Positions solver iterations | ||||
| int diterations; // Drift solver iterations | int diterations; // Drift solver iterations | ||||
| int citerations; // Cluster solver iterations | int citerations; // Cluster solver iterations | ||||
| int collisions; // Collisions flags | int collisions; // Collisions flags | ||||
| tVSolverArray m_vsequence; // Velocity solvers sequence | tVSolverArray m_vsequence; // Velocity solvers sequence | ||||
| tPSolverArray m_psequence; // Position solvers sequence | tPSolverArray m_psequence; // Position solvers sequence | ||||
| tPSolverArray m_dsequence; // Drift solvers sequence | tPSolverArray m_dsequence; // Drift solvers sequence | ||||
| btScalar drag; // deformable air drag | |||||
| btScalar m_maxStress; // Maximum principle first Piola stress | |||||
| }; | }; | ||||
| /* SolverState */ | /* SolverState */ | ||||
| struct SolverState | struct SolverState | ||||
| { | { | ||||
| //if you add new variables, always initialize them! | |||||
| SolverState() | |||||
| : sdt(0), | |||||
| isdt(0), | |||||
| velmrg(0), | |||||
| radmrg(0), | |||||
| updmrg(0) | |||||
| { | |||||
| } | |||||
| btScalar sdt; // dt*timescale | btScalar sdt; // dt*timescale | ||||
| btScalar isdt; // 1/sdt | btScalar isdt; // 1/sdt | ||||
| btScalar velmrg; // velocity margin | btScalar velmrg; // velocity margin | ||||
| btScalar radmrg; // radial margin | btScalar radmrg; // radial margin | ||||
| btScalar updmrg; // Update margin | btScalar updmrg; // Update margin | ||||
| }; | }; | ||||
| /// RayFromToCaster takes a ray from, ray to (instead of direction!) | /// RayFromToCaster takes a ray from, ray to (instead of direction!) | ||||
| struct RayFromToCaster : btDbvt::ICollide | struct RayFromToCaster : btDbvt::ICollide | ||||
| { | { | ||||
| btVector3 m_rayFrom; | btVector3 m_rayFrom; | ||||
| btVector3 m_rayTo; | btVector3 m_rayTo; | ||||
| btVector3 m_rayNormalizedDirection; | btVector3 m_rayNormalizedDirection; | ||||
| btScalar m_mint; | btScalar m_mint; | ||||
| Face* m_face; | Face* m_face; | ||||
| int m_tests; | int m_tests; | ||||
| RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt); | RayFromToCaster(const btVector3& rayFrom, const btVector3& rayTo, btScalar mxt); | ||||
| void Process(const btDbvtNode* leaf); | void Process(const btDbvtNode* leaf); | ||||
| static inline btScalar rayFromToTriangle(const btVector3& rayFrom, | static /*inline*/ btScalar rayFromToTriangle(const btVector3& rayFrom, | ||||
| const btVector3& rayTo, | const btVector3& rayTo, | ||||
| const btVector3& rayNormalizedDirection, | const btVector3& rayNormalizedDirection, | ||||
| const btVector3& a, | const btVector3& a, | ||||
| const btVector3& b, | const btVector3& b, | ||||
| const btVector3& c, | const btVector3& c, | ||||
| btScalar maxt=SIMD_INFINITY); | btScalar maxt = SIMD_INFINITY); | ||||
| }; | }; | ||||
| // | // | ||||
| // Typedefs | // Typedefs | ||||
| // | // | ||||
| typedef void (*psolver_t)(btSoftBody*,btScalar,btScalar); | typedef void (*psolver_t)(btSoftBody*, btScalar, btScalar); | ||||
| typedef void (*vsolver_t)(btSoftBody*,btScalar); | typedef void (*vsolver_t)(btSoftBody*, btScalar); | ||||
| typedef btAlignedObjectArray<Cluster*> tClusterArray; | typedef btAlignedObjectArray<Cluster*> tClusterArray; | ||||
| typedef btAlignedObjectArray<Note> tNoteArray; | typedef btAlignedObjectArray<Note> tNoteArray; | ||||
| typedef btAlignedObjectArray<Node> tNodeArray; | typedef btAlignedObjectArray<Node> tNodeArray; | ||||
| typedef btAlignedObjectArray<btDbvtNode*> tLeafArray; | typedef btAlignedObjectArray<btDbvtNode*> tLeafArray; | ||||
| typedef btAlignedObjectArray<Link> tLinkArray; | typedef btAlignedObjectArray<Link> tLinkArray; | ||||
| typedef btAlignedObjectArray<Face> tFaceArray; | typedef btAlignedObjectArray<Face> tFaceArray; | ||||
| typedef btAlignedObjectArray<Tetra> tTetraArray; | typedef btAlignedObjectArray<Tetra> tTetraArray; | ||||
| typedef btAlignedObjectArray<Anchor> tAnchorArray; | typedef btAlignedObjectArray<Anchor> tAnchorArray; | ||||
| typedef btAlignedObjectArray<RContact> tRContactArray; | typedef btAlignedObjectArray<RContact> tRContactArray; | ||||
| typedef btAlignedObjectArray<SContact> tSContactArray; | typedef btAlignedObjectArray<SContact> tSContactArray; | ||||
| typedef btAlignedObjectArray<Material*> tMaterialArray; | typedef btAlignedObjectArray<Material*> tMaterialArray; | ||||
| typedef btAlignedObjectArray<Joint*> tJointArray; | typedef btAlignedObjectArray<Joint*> tJointArray; | ||||
| typedef btAlignedObjectArray<btSoftBody*> tSoftBodyArray; | typedef btAlignedObjectArray<btSoftBody*> tSoftBodyArray; | ||||
| // | // | ||||
| // Fields | // Fields | ||||
| // | // | ||||
| Config m_cfg; // Configuration | Config m_cfg; // Configuration | ||||
| SolverState m_sst; // Solver state | SolverState m_sst; // Solver state | ||||
| Pose m_pose; // Pose | Pose m_pose; // Pose | ||||
| void* m_tag; // User data | void* m_tag; // User data | ||||
| btSoftBodyWorldInfo* m_worldInfo; // World info | btSoftBodyWorldInfo* m_worldInfo; // World info | ||||
| tNoteArray m_notes; // Notes | tNoteArray m_notes; // Notes | ||||
| tNodeArray m_nodes; // Nodes | tNodeArray m_nodes; // Nodes | ||||
| tNodeArray m_renderNodes; // Nodes | |||||
| tLinkArray m_links; // Links | tLinkArray m_links; // Links | ||||
| tFaceArray m_faces; // Faces | tFaceArray m_faces; // Faces | ||||
| tFaceArray m_renderFaces; // Faces | |||||
| tTetraArray m_tetras; // Tetras | tTetraArray m_tetras; // Tetras | ||||
| btAlignedObjectArray<TetraScratch> m_tetraScratches; | |||||
| btAlignedObjectArray<TetraScratch> m_tetraScratchesTn; | |||||
| tAnchorArray m_anchors; // Anchors | tAnchorArray m_anchors; // Anchors | ||||
| btAlignedObjectArray<DeformableNodeRigidAnchor> m_deformableAnchors; | |||||
| tRContactArray m_rcontacts; // Rigid contacts | tRContactArray m_rcontacts; // Rigid contacts | ||||
| btAlignedObjectArray<DeformableNodeRigidContact> m_nodeRigidContacts; | |||||
| btAlignedObjectArray<DeformableFaceNodeContact> m_faceNodeContacts; | |||||
| btAlignedObjectArray<DeformableFaceRigidContact> m_faceRigidContacts; | |||||
| tSContactArray m_scontacts; // Soft contacts | tSContactArray m_scontacts; // Soft contacts | ||||
| tJointArray m_joints; // Joints | tJointArray m_joints; // Joints | ||||
| tMaterialArray m_materials; // Materials | tMaterialArray m_materials; // Materials | ||||
| btScalar m_timeacc; // Time accumulator | btScalar m_timeacc; // Time accumulator | ||||
| btVector3 m_bounds[2]; // Spatial bounds | btVector3 m_bounds[2]; // Spatial bounds | ||||
| bool m_bUpdateRtCst; // Update runtime constants | bool m_bUpdateRtCst; // Update runtime constants | ||||
| btDbvt m_ndbvt; // Nodes tree | btDbvt m_ndbvt; // Nodes tree | ||||
| btDbvt m_fdbvt; // Faces tree | btDbvt m_fdbvt; // Faces tree | ||||
| btDbvntNode* m_fdbvnt; // Faces tree with normals | |||||
| btDbvt m_cdbvt; // Clusters tree | btDbvt m_cdbvt; // Clusters tree | ||||
| tClusterArray m_clusters; // Clusters | tClusterArray m_clusters; // Clusters | ||||
| btScalar m_dampingCoefficient; // Damping Coefficient | |||||
| btScalar m_sleepingThreshold; | |||||
| btScalar m_maxSpeedSquared; | |||||
| btAlignedObjectArray<btVector3> m_quads; // quadrature points for collision detection | |||||
| btScalar m_repulsionStiffness; | |||||
| btScalar m_gravityFactor; | |||||
| btAlignedObjectArray<btVector3> m_X; // initial positions | |||||
| btAlignedObjectArray<btVector4> m_renderNodesInterpolationWeights; | |||||
| btAlignedObjectArray<btAlignedObjectArray<const btSoftBody::Node*> > m_renderNodesParents; | |||||
| btAlignedObjectArray<btScalar> m_z; // vertical distance used in extrapolation | |||||
| bool m_useSelfCollision; | |||||
| bool m_softSoftCollision; | |||||
| btAlignedObjectArray<bool>m_clusterConnectivity;//cluster connectivity, for self-collision | btAlignedObjectArray<bool> m_clusterConnectivity; //cluster connectivity, for self-collision | ||||
| btTransform m_initialWorldTransform; | |||||
| btVector3 m_windVelocity; | btVector3 m_windVelocity; | ||||
| btScalar m_restLengthScale; | btScalar m_restLengthScale; | ||||
| // | // | ||||
| // Api | // Api | ||||
| // | // | ||||
| /* ctor */ | /* ctor */ | ||||
| btSoftBody( btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m); | btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m); | ||||
| /* ctor */ | /* ctor */ | ||||
| btSoftBody( btSoftBodyWorldInfo* worldInfo); | btSoftBody(btSoftBodyWorldInfo* worldInfo); | ||||
| void initDefaults(); | void initDefaults(); | ||||
| /* dtor */ | /* dtor */ | ||||
| virtual ~btSoftBody(); | virtual ~btSoftBody(); | ||||
| /* Check for existing link */ | /* Check for existing link */ | ||||
| btAlignedObjectArray<int> m_userIndexMapping; | btAlignedObjectArray<int> m_userIndexMapping; | ||||
| btSoftBodyWorldInfo* getWorldInfo() | btSoftBodyWorldInfo* getWorldInfo() | ||||
| { | { | ||||
| return m_worldInfo; | return m_worldInfo; | ||||
| } | } | ||||
| void setDampingCoefficient(btScalar damping_coeff) | |||||
| { | |||||
| m_dampingCoefficient = damping_coeff; | |||||
| } | |||||
| ///@todo: avoid internal softbody shape hack and move collision code to collision library | ///@todo: avoid internal softbody shape hack and move collision code to collision library | ||||
| virtual void setCollisionShape(btCollisionShape* collisionShape) | virtual void setCollisionShape(btCollisionShape* collisionShape) | ||||
| { | { | ||||
| } | } | ||||
| bool checkLink( int node0, | bool checkLink(int node0, | ||||
| int node1) const; | int node1) const; | ||||
| bool checkLink( const Node* node0, | bool checkLink(const Node* node0, | ||||
| const Node* node1) const; | const Node* node1) const; | ||||
| /* Check for existring face */ | /* Check for existring face */ | ||||
| bool checkFace( int node0, | bool checkFace(int node0, | ||||
| int node1, | int node1, | ||||
| int node2) const; | int node2) const; | ||||
| /* Append material */ | /* Append material */ | ||||
| Material* appendMaterial(); | Material* appendMaterial(); | ||||
| /* Append note */ | /* Append note */ | ||||
| void appendNote( const char* text, | void appendNote(const char* text, | ||||
| const btVector3& o, | const btVector3& o, | ||||
| const btVector4& c=btVector4(1,0,0,0), | const btVector4& c = btVector4(1, 0, 0, 0), | ||||
| Node* n0=0, | Node* n0 = 0, | ||||
| Node* n1=0, | Node* n1 = 0, | ||||
| Node* n2=0, | Node* n2 = 0, | ||||
| Node* n3=0); | Node* n3 = 0); | ||||
| void appendNote( const char* text, | void appendNote(const char* text, | ||||
| const btVector3& o, | const btVector3& o, | ||||
| Node* feature); | Node* feature); | ||||
| void appendNote( const char* text, | void appendNote(const char* text, | ||||
| const btVector3& o, | const btVector3& o, | ||||
| Link* feature); | Link* feature); | ||||
| void appendNote( const char* text, | void appendNote(const char* text, | ||||
| const btVector3& o, | const btVector3& o, | ||||
| Face* feature); | Face* feature); | ||||
| /* Append node */ | /* Append node */ | ||||
| void appendNode( const btVector3& x,btScalar m); | void appendNode(const btVector3& x, btScalar m); | ||||
| /* Append link */ | /* Append link */ | ||||
| void appendLink(int model=-1,Material* mat=0); | void appendLink(int model = -1, Material* mat = 0); | ||||
| void appendLink( int node0, | void appendLink(int node0, | ||||
| int node1, | int node1, | ||||
| Material* mat=0, | Material* mat = 0, | ||||
| bool bcheckexist=false); | bool bcheckexist = false); | ||||
| void appendLink( Node* node0, | void appendLink(Node* node0, | ||||
| Node* node1, | Node* node1, | ||||
| Material* mat=0, | Material* mat = 0, | ||||
| bool bcheckexist=false); | bool bcheckexist = false); | ||||
| /* Append face */ | /* Append face */ | ||||
| void appendFace(int model=-1,Material* mat=0); | void appendFace(int model = -1, Material* mat = 0); | ||||
| void appendFace( int node0, | void appendFace(int node0, | ||||
| int node1, | int node1, | ||||
| int node2, | int node2, | ||||
| Material* mat=0); | Material* mat = 0); | ||||
| void appendTetra(int model,Material* mat); | void appendTetra(int model, Material* mat); | ||||
| // | // | ||||
| void appendTetra(int node0, | void appendTetra(int node0, | ||||
| int node1, | int node1, | ||||
| int node2, | int node2, | ||||
| int node3, | int node3, | ||||
| Material* mat=0); | Material* mat = 0); | ||||
| /* Append anchor */ | /* Append anchor */ | ||||
| void appendDeformableAnchor(int node, btRigidBody* body); | |||||
| void appendDeformableAnchor(int node, btMultiBodyLinkCollider* link); | |||||
| void appendAnchor( int node, | void appendAnchor(int node, | ||||
| btRigidBody* body, bool disableCollisionBetweenLinkedBodies=false,btScalar influence = 1); | btRigidBody* body, bool disableCollisionBetweenLinkedBodies = false, btScalar influence = 1); | ||||
| void appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies=false,btScalar influence = 1); | void appendAnchor(int node, btRigidBody* body, const btVector3& localPivot, bool disableCollisionBetweenLinkedBodies = false, btScalar influence = 1); | ||||
| void removeAnchor(int node); | |||||
| /* Append linear joint */ | /* Append linear joint */ | ||||
| void appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1); | 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, Body body = Body()); | ||||
| void appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body); | void appendLinearJoint(const LJoint::Specs& specs, btSoftBody* body); | ||||
| /* Append linear joint */ | /* Append linear joint */ | ||||
| void appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1); | 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, Body body = Body()); | ||||
| void appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body); | void appendAngularJoint(const AJoint::Specs& specs, btSoftBody* body); | ||||
| /* Add force (or gravity) to the entire body */ | /* Add force (or gravity) to the entire body */ | ||||
| void addForce( const btVector3& force); | void addForce(const btVector3& force); | ||||
| /* Add force (or gravity) to a node of the body */ | /* Add force (or gravity) to a node of the body */ | ||||
| void addForce( const btVector3& force, | void addForce(const btVector3& force, | ||||
| int node); | int node); | ||||
| /* Add aero force to a node of the body */ | /* Add aero force to a node of the body */ | ||||
| void addAeroForceToNode(const btVector3& windVelocity,int nodeIndex); | void addAeroForceToNode(const btVector3& windVelocity, int nodeIndex); | ||||
| /* Add aero force to a face of the body */ | /* Add aero force to a face of the body */ | ||||
| void addAeroForceToFace(const btVector3& windVelocity,int faceIndex); | void addAeroForceToFace(const btVector3& windVelocity, int faceIndex); | ||||
| /* Add velocity to the entire body */ | /* Add velocity to the entire body */ | ||||
| void addVelocity( const btVector3& velocity); | void addVelocity(const btVector3& velocity); | ||||
| /* Set velocity for the entire body */ | /* Set velocity for the entire body */ | ||||
| void setVelocity( const btVector3& velocity); | void setVelocity(const btVector3& velocity); | ||||
| /* Add velocity to a node of the body */ | /* Add velocity to a node of the body */ | ||||
| void addVelocity( const btVector3& velocity, | void addVelocity(const btVector3& velocity, | ||||
| int node); | int node); | ||||
| /* Set mass */ | /* Set mass */ | ||||
| void setMass( int node, | void setMass(int node, | ||||
| btScalar mass); | btScalar mass); | ||||
| /* Get mass */ | /* Get mass */ | ||||
| btScalar getMass( int node) const; | btScalar getMass(int node) const; | ||||
| /* Get total mass */ | /* Get total mass */ | ||||
| btScalar getTotalMass() const; | btScalar getTotalMass() const; | ||||
| /* Set total mass (weighted by previous masses) */ | /* Set total mass (weighted by previous masses) */ | ||||
| void setTotalMass( btScalar mass, | void setTotalMass(btScalar mass, | ||||
| bool fromfaces=false); | bool fromfaces = false); | ||||
| /* Set total density */ | /* Set total density */ | ||||
| void setTotalDensity(btScalar density); | void setTotalDensity(btScalar density); | ||||
| /* Set volume mass (using tetrahedrons) */ | /* Set volume mass (using tetrahedrons) */ | ||||
| void setVolumeMass( btScalar mass); | void setVolumeMass(btScalar mass); | ||||
| /* Set volume density (using tetrahedrons) */ | /* Set volume density (using tetrahedrons) */ | ||||
| void setVolumeDensity( btScalar density); | void setVolumeDensity(btScalar density); | ||||
| /* Get the linear velocity of the center of mass */ | |||||
| btVector3 getLinearVelocity(); | |||||
| /* Set the linear velocity of the center of mass */ | |||||
| void setLinearVelocity(const btVector3& linVel); | |||||
| /* Set the angular velocity of the center of mass */ | |||||
| void setAngularVelocity(const btVector3& angVel); | |||||
| /* Get best fit rigid transform */ | |||||
| btTransform getRigidTransform(); | |||||
| /* Transform to given pose */ | |||||
| void transformTo(const btTransform& trs); | |||||
| /* Transform */ | /* Transform */ | ||||
| void transform( const btTransform& trs); | void transform(const btTransform& trs); | ||||
| /* Translate */ | /* Translate */ | ||||
| void translate( const btVector3& trs); | void translate(const btVector3& trs); | ||||
| /* Rotate */ | /* Rotate */ | ||||
| void rotate( const btQuaternion& rot); | void rotate(const btQuaternion& rot); | ||||
| /* Scale */ | /* Scale */ | ||||
| void scale( const btVector3& scl); | void scale(const btVector3& scl); | ||||
| /* Get link resting lengths scale */ | /* Get link resting lengths scale */ | ||||
| btScalar getRestLengthScale(); | btScalar getRestLengthScale(); | ||||
| /* Scale resting length of all springs */ | /* Scale resting length of all springs */ | ||||
| void setRestLengthScale(btScalar restLength); | void setRestLengthScale(btScalar restLength); | ||||
| /* Set current state as pose */ | /* Set current state as pose */ | ||||
| void setPose( bool bvolume, | void setPose(bool bvolume, | ||||
| bool bframe); | bool bframe); | ||||
| /* Set current link lengths as resting lengths */ | /* Set current link lengths as resting lengths */ | ||||
| void resetLinkRestLengths(); | void resetLinkRestLengths(); | ||||
| /* Return the volume */ | /* Return the volume */ | ||||
| btScalar getVolume() const; | btScalar getVolume() const; | ||||
| /* Cluster count */ | /* Cluster count */ | ||||
| btVector3 getCenterOfMass() const | |||||
| { | |||||
| btVector3 com(0, 0, 0); | |||||
| for (int i = 0; i < m_nodes.size(); i++) | |||||
| { | |||||
| com += (m_nodes[i].m_x * this->getMass(i)); | |||||
| } | |||||
| com /= this->getTotalMass(); | |||||
| return com; | |||||
| } | |||||
| int clusterCount() const; | int clusterCount() const; | ||||
| /* Cluster center of mass */ | /* Cluster center of mass */ | ||||
| static btVector3 clusterCom(const Cluster* cluster); | static btVector3 clusterCom(const Cluster* cluster); | ||||
| btVector3 clusterCom(int cluster) const; | btVector3 clusterCom(int cluster) const; | ||||
| /* Cluster velocity at rpos */ | /* Cluster velocity at rpos */ | ||||
| static btVector3 clusterVelocity(const Cluster* cluster,const btVector3& rpos); | static btVector3 clusterVelocity(const Cluster* cluster, const btVector3& rpos); | ||||
| /* Cluster impulse */ | /* Cluster impulse */ | ||||
| static void clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& 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 clusterDImpulse(Cluster* cluster, const btVector3& rpos, const btVector3& impulse); | ||||
| static void clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse); | static void clusterImpulse(Cluster* cluster, const btVector3& rpos, const Impulse& impulse); | ||||
| static void clusterVAImpulse(Cluster* cluster,const btVector3& impulse); | static void clusterVAImpulse(Cluster* cluster, const btVector3& impulse); | ||||
| static void clusterDAImpulse(Cluster* cluster,const btVector3& impulse); | static void clusterDAImpulse(Cluster* cluster, const btVector3& impulse); | ||||
| static void clusterAImpulse(Cluster* cluster,const Impulse& impulse); | static void clusterAImpulse(Cluster* cluster, const Impulse& impulse); | ||||
| static void clusterDCImpulse(Cluster* cluster,const btVector3& impulse); | static void clusterDCImpulse(Cluster* cluster, const btVector3& impulse); | ||||
| /* Generate bending constraints based on distance in the adjency graph */ | /* Generate bending constraints based on distance in the adjency graph */ | ||||
| int generateBendingConstraints( int distance, | int generateBendingConstraints(int distance, | ||||
| Material* mat=0); | Material* mat = 0); | ||||
| /* Randomize constraints to reduce solver bias */ | /* Randomize constraints to reduce solver bias */ | ||||
| void randomizeConstraints(); | void randomizeConstraints(); | ||||
| /* Release clusters */ | /* Release clusters */ | ||||
| void releaseCluster(int index); | void releaseCluster(int index); | ||||
| void releaseClusters(); | void releaseClusters(); | ||||
| /* Generate clusters (K-mean) */ | /* Generate clusters (K-mean) */ | ||||
| ///generateClusters with k=0 will create a convex cluster for each tetrahedron or triangle | ///generateClusters with k=0 will create a convex cluster for each tetrahedron or triangle | ||||
| ///otherwise an approximation will be used (better performance) | ///otherwise an approximation will be used (better performance) | ||||
| int generateClusters(int k,int maxiterations=8192); | int generateClusters(int k, int maxiterations = 8192); | ||||
| /* Refine */ | /* Refine */ | ||||
| void refine(ImplicitFn* ifn,btScalar accurary,bool cut); | void refine(ImplicitFn* ifn, btScalar accurary, bool cut); | ||||
| /* CutLink */ | /* CutLink */ | ||||
| bool cutLink(int node0,int node1,btScalar position); | bool cutLink(int node0, int node1, btScalar position); | ||||
| bool cutLink(const Node* node0,const Node* node1,btScalar position); | bool cutLink(const Node* node0, const Node* node1, btScalar position); | ||||
| ///Ray casting using rayFrom and rayTo in worldspace, (not direction!) | ///Ray casting using rayFrom and rayTo in worldspace, (not direction!) | ||||
| bool rayTest(const btVector3& rayFrom, | bool rayTest(const btVector3& rayFrom, | ||||
| const btVector3& rayTo, | const btVector3& rayTo, | ||||
| sRayCast& results); | sRayCast& results); | ||||
| bool rayFaceTest(const btVector3& rayFrom, | |||||
| const btVector3& rayTo, | |||||
| sRayCast& results); | |||||
| int rayFaceTest(const btVector3& rayFrom, const btVector3& rayTo, | |||||
| btScalar& mint, int& index) const; | |||||
| /* Solver presets */ | /* Solver presets */ | ||||
| void setSolver(eSolverPresets::_ preset); | void setSolver(eSolverPresets::_ preset); | ||||
| /* predictMotion */ | /* predictMotion */ | ||||
| void predictMotion(btScalar dt); | void predictMotion(btScalar dt); | ||||
| /* solveConstraints */ | /* solveConstraints */ | ||||
| void solveConstraints(); | void solveConstraints(); | ||||
| /* staticSolve */ | /* staticSolve */ | ||||
| void staticSolve(int iterations); | void staticSolve(int iterations); | ||||
| /* solveCommonConstraints */ | /* solveCommonConstraints */ | ||||
| static void solveCommonConstraints(btSoftBody** bodies,int count,int iterations); | static void solveCommonConstraints(btSoftBody** bodies, int count, int iterations); | ||||
| /* solveClusters */ | /* solveClusters */ | ||||
| static void solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies); | static void solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies); | ||||
| /* integrateMotion */ | /* integrateMotion */ | ||||
| void integrateMotion(); | void integrateMotion(); | ||||
| /* defaultCollisionHandlers */ | /* defaultCollisionHandlers */ | ||||
| void defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap); | void defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap); | ||||
| void defaultCollisionHandler(btSoftBody* psb); | void defaultCollisionHandler(btSoftBody* psb); | ||||
| void setSelfCollision(bool useSelfCollision); | |||||
| bool useSelfCollision(); | |||||
| void updateDeactivation(btScalar timeStep); | |||||
| void setZeroVelocity(); | |||||
| bool wantsSleeping(); | |||||
| // | // | ||||
| // Functionality to deal with new accelerated solvers. | // Functionality to deal with new accelerated solvers. | ||||
| // | // | ||||
| /** | /** | ||||
| * Set a wind velocity for interaction with the air. | * Set a wind velocity for interaction with the air. | ||||
| */ | */ | ||||
| void setWindVelocity( const btVector3 &velocity ); | void setWindVelocity(const btVector3& velocity); | ||||
| /** | /** | ||||
| * Return the wind velocity for interaction with the air. | * Return the wind velocity for interaction with the air. | ||||
| */ | */ | ||||
| const btVector3& getWindVelocity(); | const btVector3& getWindVelocity(); | ||||
| // | // | ||||
| // Set the solver that handles this soft body | // Set the solver that handles this soft body | ||||
| // Should not be allowed to get out of sync with reality | // Should not be allowed to get out of sync with reality | ||||
| // Currently called internally on addition to the world | // Currently called internally on addition to the world | ||||
| void setSoftBodySolver( btSoftBodySolver *softBodySolver ) | void setSoftBodySolver(btSoftBodySolver* softBodySolver) | ||||
| { | { | ||||
| m_softBodySolver = softBodySolver; | m_softBodySolver = softBodySolver; | ||||
| } | } | ||||
| // | // | ||||
| // Return the solver that handles this soft body | // Return the solver that handles this soft body | ||||
| // | // | ||||
| btSoftBodySolver *getSoftBodySolver() | btSoftBodySolver* getSoftBodySolver() | ||||
| { | { | ||||
| return m_softBodySolver; | return m_softBodySolver; | ||||
| } | } | ||||
| // | // | ||||
| // Return the solver that handles this soft body | // Return the solver that handles this soft body | ||||
| // | // | ||||
| btSoftBodySolver *getSoftBodySolver() const | btSoftBodySolver* getSoftBodySolver() const | ||||
| { | { | ||||
| return m_softBodySolver; | return m_softBodySolver; | ||||
| } | } | ||||
| // | // | ||||
| // Cast | // Cast | ||||
| // | // | ||||
| static const btSoftBody* upcast(const btCollisionObject* colObj) | static const btSoftBody* upcast(const btCollisionObject* colObj) | ||||
| { | { | ||||
| if (colObj->getInternalType()==CO_SOFT_BODY) | if (colObj->getInternalType() == CO_SOFT_BODY) | ||||
| return (const btSoftBody*)colObj; | return (const btSoftBody*)colObj; | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| static btSoftBody* upcast(btCollisionObject* colObj) | static btSoftBody* upcast(btCollisionObject* colObj) | ||||
| { | { | ||||
| if (colObj->getInternalType()==CO_SOFT_BODY) | if (colObj->getInternalType() == CO_SOFT_BODY) | ||||
| return (btSoftBody*)colObj; | return (btSoftBody*)colObj; | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| // | // | ||||
| // ::btCollisionObject | // ::btCollisionObject | ||||
| // | // | ||||
| virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const | virtual void getAabb(btVector3& aabbMin, btVector3& aabbMax) const | ||||
| { | { | ||||
| aabbMin = m_bounds[0]; | aabbMin = m_bounds[0]; | ||||
| aabbMax = m_bounds[1]; | aabbMax = m_bounds[1]; | ||||
| } | } | ||||
| // | // | ||||
| // Private | // Private | ||||
| // | // | ||||
| void pointersToIndices(); | void pointersToIndices(); | ||||
| void indicesToPointers(const int* map=0); | void indicesToPointers(const int* map = 0); | ||||
| int rayTest(const btVector3& rayFrom,const btVector3& rayTo, | int rayTest(const btVector3& rayFrom, const btVector3& rayTo, | ||||
| btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const; | btScalar& mint, eFeature::_& feature, int& index, bool bcountonly) const; | ||||
| void initializeFaceTree(); | void initializeFaceTree(); | ||||
| void rebuildNodeTree(); | |||||
| btVector3 evaluateCom() const; | btVector3 evaluateCom() const; | ||||
| bool checkDeformableContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti, bool predict = false) const; | |||||
| bool checkDeformableFaceContact(const btCollisionObjectWrapper* colObjWrap, Face& f, btVector3& contact_point, btVector3& bary, btScalar margin, btSoftBody::sCti& cti, bool predict = false) const; | |||||
| bool checkContact(const btCollisionObjectWrapper* colObjWrap,const btVector3& x,btScalar margin,btSoftBody::sCti& cti) const; | bool checkContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti) const; | ||||
| void updateNormals(); | void updateNormals(); | ||||
| void updateBounds(); | void updateBounds(); | ||||
| void updatePose(); | void updatePose(); | ||||
| void updateConstants(); | void updateConstants(); | ||||
| void updateLinkConstants(); | void updateLinkConstants(); | ||||
| void updateArea(bool averageArea = true); | void updateArea(bool averageArea = true); | ||||
| void initializeClusters(); | void initializeClusters(); | ||||
| void updateClusters(); | void updateClusters(); | ||||
| void cleanupClusters(); | void cleanupClusters(); | ||||
| void prepareClusters(int iterations); | void prepareClusters(int iterations); | ||||
| void solveClusters(btScalar sor); | void solveClusters(btScalar sor); | ||||
| void applyClusters(bool drift); | void applyClusters(bool drift); | ||||
| void dampClusters(); | void dampClusters(); | ||||
| void setSpringStiffness(btScalar k); | |||||
| void setGravityFactor(btScalar gravFactor); | |||||
| void initializeDmInverse(); | |||||
| void updateDeformation(); | |||||
| void advanceDeformation(); | |||||
| void applyForces(); | void applyForces(); | ||||
| void setMaxStress(btScalar maxStress); | |||||
| void interpolateRenderMesh(); | |||||
| void setCollisionQuadrature(int N); | |||||
| static void PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti); | static void PSolve_Anchors(btSoftBody* psb, btScalar kst, btScalar ti); | ||||
| static void PSolve_RContacts(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_SContacts(btSoftBody* psb, btScalar, btScalar ti); | ||||
| static void PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti); | static void PSolve_Links(btSoftBody* psb, btScalar kst, btScalar ti); | ||||
| static void VSolve_Links(btSoftBody* psb,btScalar kst); | static void VSolve_Links(btSoftBody* psb, btScalar kst); | ||||
| static psolver_t getSolver(ePSolver::_ solver); | static psolver_t getSolver(ePSolver::_ solver); | ||||
| static vsolver_t getSolver(eVSolver::_ solver); | static vsolver_t getSolver(eVSolver::_ solver); | ||||
| void geometricCollisionHandler(btSoftBody* psb); | |||||
| #define SAFE_EPSILON SIMD_EPSILON * 100.0 | |||||
| void updateNode(btDbvtNode* node, bool use_velocity, bool margin) | |||||
| { | |||||
| if (node->isleaf()) | |||||
| { | |||||
| btSoftBody::Node* n = (btSoftBody::Node*)(node->data); | |||||
| ATTRIBUTE_ALIGNED16(btDbvtVolume) | |||||
| vol; | |||||
| btScalar pad = margin ? m_sst.radmrg : SAFE_EPSILON; // use user defined margin or margin for floating point precision | |||||
| if (use_velocity) | |||||
| { | |||||
| btVector3 points[2] = {n->m_x, n->m_x + m_sst.sdt * n->m_v}; | |||||
| vol = btDbvtVolume::FromPoints(points, 2); | |||||
| vol.Expand(btVector3(pad, pad, pad)); | |||||
| } | |||||
| else | |||||
| { | |||||
| vol = btDbvtVolume::FromCR(n->m_x, pad); | |||||
| } | |||||
| node->volume = vol; | |||||
| return; | |||||
| } | |||||
| else | |||||
| { | |||||
| updateNode(node->childs[0], use_velocity, margin); | |||||
| updateNode(node->childs[1], use_velocity, margin); | |||||
| ATTRIBUTE_ALIGNED16(btDbvtVolume) | |||||
| vol; | |||||
| Merge(node->childs[0]->volume, node->childs[1]->volume, vol); | |||||
| node->volume = vol; | |||||
| } | |||||
| } | |||||
| void updateNodeTree(bool use_velocity, bool margin) | |||||
| { | |||||
| if (m_ndbvt.m_root) | |||||
| updateNode(m_ndbvt.m_root, use_velocity, margin); | |||||
| } | |||||
| virtual int calculateSerializeBufferSize() const; | template <class DBVTNODE> // btDbvtNode or btDbvntNode | ||||
| void updateFace(DBVTNODE* node, bool use_velocity, bool margin) | |||||
| { | |||||
| if (node->isleaf()) | |||||
| { | |||||
| btSoftBody::Face* f = (btSoftBody::Face*)(node->data); | |||||
| btScalar pad = margin ? m_sst.radmrg : SAFE_EPSILON; // use user defined margin or margin for floating point precision | |||||
| ATTRIBUTE_ALIGNED16(btDbvtVolume) | |||||
| vol; | |||||
| if (use_velocity) | |||||
| { | |||||
| btVector3 points[6] = {f->m_n[0]->m_x, f->m_n[0]->m_x + m_sst.sdt * f->m_n[0]->m_v, | |||||
| f->m_n[1]->m_x, f->m_n[1]->m_x + m_sst.sdt * f->m_n[1]->m_v, | |||||
| f->m_n[2]->m_x, f->m_n[2]->m_x + m_sst.sdt * f->m_n[2]->m_v}; | |||||
| vol = btDbvtVolume::FromPoints(points, 6); | |||||
| } | |||||
| else | |||||
| { | |||||
| btVector3 points[3] = {f->m_n[0]->m_x, | |||||
| f->m_n[1]->m_x, | |||||
| f->m_n[2]->m_x}; | |||||
| vol = btDbvtVolume::FromPoints(points, 3); | |||||
| } | |||||
| vol.Expand(btVector3(pad, pad, pad)); | |||||
| node->volume = vol; | |||||
| return; | |||||
| } | |||||
| else | |||||
| { | |||||
| updateFace(node->childs[0], use_velocity, margin); | |||||
| updateFace(node->childs[1], use_velocity, margin); | |||||
| ATTRIBUTE_ALIGNED16(btDbvtVolume) | |||||
| vol; | |||||
| Merge(node->childs[0]->volume, node->childs[1]->volume, vol); | |||||
| node->volume = vol; | |||||
| } | |||||
| } | |||||
| void updateFaceTree(bool use_velocity, bool margin) | |||||
| { | |||||
| if (m_fdbvt.m_root) | |||||
| updateFace(m_fdbvt.m_root, use_velocity, margin); | |||||
| if (m_fdbvnt) | |||||
| updateFace(m_fdbvnt, use_velocity, margin); | |||||
| } | |||||
| ///fills the dataBuffer and returns the struct name (and 0 on failure) | template <typename T> | ||||
| virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const; | static inline T BaryEval(const T& a, | ||||
| const T& b, | |||||
| const T& c, | |||||
| const btVector3& coord) | |||||
| { | |||||
| return (a * coord.x() + b * coord.y() + c * coord.z()); | |||||
| } | |||||
| //virtual void serializeSingleObject(class btSerializer* serializer) const; | void applyRepulsionForce(btScalar timeStep, bool applySpringForce) | ||||
| { | |||||
| btAlignedObjectArray<int> indices; | |||||
| { | |||||
| // randomize the order of repulsive force | |||||
| indices.resize(m_faceNodeContacts.size()); | |||||
| for (int i = 0; i < m_faceNodeContacts.size(); ++i) | |||||
| indices[i] = i; | |||||
| #define NEXTRAND (seed = (1664525L * seed + 1013904223L) & 0xffffffff) | |||||
| int i, ni; | |||||
| for (i = 0, ni = indices.size(); i < ni; ++i) | |||||
| { | |||||
| btSwap(indices[i], indices[NEXTRAND % ni]); | |||||
| } | |||||
| } | |||||
| for (int k = 0; k < m_faceNodeContacts.size(); ++k) | |||||
| { | |||||
| int i = indices[k]; | |||||
| btSoftBody::DeformableFaceNodeContact& c = m_faceNodeContacts[i]; | |||||
| btSoftBody::Node* node = c.m_node; | |||||
| btSoftBody::Face* face = c.m_face; | |||||
| const btVector3& w = c.m_bary; | |||||
| const btVector3& n = c.m_normal; | |||||
| btVector3 l = node->m_x - BaryEval(face->m_n[0]->m_x, face->m_n[1]->m_x, face->m_n[2]->m_x, w); | |||||
| btScalar d = c.m_margin - n.dot(l); | |||||
| d = btMax(btScalar(0), d); | |||||
| }; | const btVector3& va = node->m_v; | ||||
| btVector3 vb = BaryEval(face->m_n[0]->m_v, face->m_n[1]->m_v, face->m_n[2]->m_v, w); | |||||
| btVector3 vr = va - vb; | |||||
| const btScalar vn = btDot(vr, n); // dn < 0 <==> opposing | |||||
| if (vn > OVERLAP_REDUCTION_FACTOR * d / timeStep) | |||||
| continue; | |||||
| btVector3 vt = vr - vn * n; | |||||
| btScalar I = 0; | |||||
| btScalar mass = node->m_im == 0 ? 0 : btScalar(1) / node->m_im; | |||||
| if (applySpringForce) | |||||
| I = -btMin(m_repulsionStiffness * timeStep * d, mass * (OVERLAP_REDUCTION_FACTOR * d / timeStep - vn)); | |||||
| if (vn < 0) | |||||
| I += 0.5 * mass * vn; | |||||
| int face_penetration = 0, node_penetration = node->m_constrained; | |||||
| for (int i = 0; i < 3; ++i) | |||||
| face_penetration |= face->m_n[i]->m_constrained; | |||||
| btScalar I_tilde = 2.0 * I / (1.0 + w.length2()); | |||||
| // double the impulse if node or face is constrained. | |||||
| if (face_penetration > 0 || node_penetration > 0) | |||||
| { | |||||
| I_tilde *= 2.0; | |||||
| } | |||||
| if (face_penetration <= 0) | |||||
| { | |||||
| for (int j = 0; j < 3; ++j) | |||||
| face->m_n[j]->m_v += w[j] * n * I_tilde * node->m_im; | |||||
| } | |||||
| if (node_penetration <= 0) | |||||
| { | |||||
| node->m_v -= I_tilde * node->m_im * n; | |||||
| } | |||||
| // apply frictional impulse | |||||
| btScalar vt_norm = vt.safeNorm(); | |||||
| if (vt_norm > SIMD_EPSILON) | |||||
| { | |||||
| btScalar delta_vn = -2 * I * node->m_im; | |||||
| btScalar mu = c.m_friction; | |||||
| btScalar vt_new = btMax(btScalar(1) - mu * delta_vn / (vt_norm + SIMD_EPSILON), btScalar(0)) * vt_norm; | |||||
| I = 0.5 * mass * (vt_norm - vt_new); | |||||
| vt.safeNormalize(); | |||||
| I_tilde = 2.0 * I / (1.0 + w.length2()); | |||||
| // double the impulse if node or face is constrained. | |||||
| if (face_penetration > 0 || node_penetration > 0) | |||||
| I_tilde *= 2.0; | |||||
| if (face_penetration <= 0) | |||||
| { | |||||
| for (int j = 0; j < 3; ++j) | |||||
| face->m_n[j]->m_v += w[j] * vt * I_tilde * (face->m_n[j])->m_im; | |||||
| } | |||||
| if (node_penetration <= 0) | |||||
| { | |||||
| node->m_v -= I_tilde * node->m_im * vt; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| 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; | |||||
| }; | |||||
| #endif //_BT_SOFT_BODY_H | #endif //_BT_SOFT_BODY_H | ||||