12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394 |
- /*
- 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 "LinearMath/btVector3.h"
- #include "BulletDynamics/Dynamics/btRigidBody.h"
- #include "BulletCollision/CollisionShapes/btConcaveShape.h"
- #include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
- #include "btSparseSDF.h"
- #include "BulletCollision/BroadphaseCollision/btDbvt.h"
- #include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
- #include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
- //#ifdef BT_USE_DOUBLE_PRECISION
- //#define btRigidBodyData btRigidBodyDoubleData
- //#define btRigidBodyDataName "btRigidBodyDoubleData"
- //#else
- #define btSoftBodyData btSoftBodyFloatData
- #define btSoftBodyDataName "btSoftBodyFloatData"
- static const btScalar OVERLAP_REDUCTION_FACTOR = 0.1;
- static unsigned long seed = 243703;
- //#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
- SDF_RD = 0x0004, ///rigid vs deformable
- SVSmask = 0x00f0, ///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
- 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 */
- 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 */
- btVector3 m_bary; /* Barycentric weights for faces */
- };
- /* 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 RenderNode
- {
- btVector3 m_x;
- btVector3 m_uv1;
- btVector3 m_normal;
- };
- struct Node : Feature
- {
- btVector3 m_x; // Position
- btVector3 m_q; // Previous step position/Test position
- btVector3 m_v; // Velocity
- btVector3 m_vn; // Previous step 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_constrained; // depth of penetration
- 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 */
- 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();
- };
- struct RenderFace
- {
- RenderNode* m_n[3]; // Node pointers
- };
- /* Face */
- struct Face : Feature
- {
- Node* m_n[3]; // Node pointers
- btVector3 m_normal; // Normal
- btScalar m_ra; // Rest area
- 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 */
- 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)
- 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 */
- 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
- // 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 */
- 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
- btScalar drag; // deformable air drag
- btScalar m_maxStress; // Maximum principle first Piola stress
- };
- /* 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 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< RenderNode> tRenderNodeArray;
- typedef btAlignedObjectArray<btDbvtNode*> tLeafArray;
- typedef btAlignedObjectArray<Link> tLinkArray;
- typedef btAlignedObjectArray<Face> tFaceArray;
- typedef btAlignedObjectArray<RenderFace> tRenderFaceArray;
- 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
- tRenderNodeArray m_renderNodes; // Render Nodes
- tLinkArray m_links; // Links
- tFaceArray m_faces; // Faces
- tRenderFaceArray m_renderFaces; // Faces
- tTetraArray m_tetras; // Tetras
- btAlignedObjectArray<TetraScratch> m_tetraScratches;
- btAlignedObjectArray<TetraScratch> m_tetraScratchesTn;
- tAnchorArray m_anchors; // Anchors
- btAlignedObjectArray<DeformableNodeRigidAnchor> m_deformableAnchors;
- tRContactArray m_rcontacts; // Rigid contacts
- btAlignedObjectArray<DeformableNodeRigidContact> m_nodeRigidContacts;
- btAlignedObjectArray<DeformableFaceNodeContact> m_faceNodeContacts;
- btAlignedObjectArray<DeformableFaceRigidContact> m_faceRigidContacts;
- 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
- btDbvntNode* m_fdbvnt; // Faces tree with normals
- btDbvt m_cdbvt; // Clusters tree
- 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;
- bool m_cacheBarycenter;
- 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
- 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;
- }
- void setDampingCoefficient(btScalar damping_coeff)
- {
- m_dampingCoefficient = damping_coeff;
- }
- ///@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 appendDeformableAnchor(int node, btRigidBody* body);
- void appendDeformableAnchor(int node, btMultiBodyLinkCollider* link);
- 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);
- void removeAnchor(int node);
- /* 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);
- /* 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 */
- 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 */
- 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;
- /* 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);
- 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 */
- 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);
- void setSelfCollision(bool useSelfCollision);
- bool useSelfCollision();
- void updateDeactivation(btScalar timeStep);
- void setZeroVelocity();
- bool wantsSleeping();
- //
- // 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();
- void rebuildNodeTree();
- 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;
- 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 setSpringStiffness(btScalar k);
- void setGravityFactor(btScalar gravFactor);
- void setCacheBarycenter(bool cacheBarycenter);
- void initializeDmInverse();
- void updateDeformation();
- void advanceDeformation();
- 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_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);
- 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);
- }
- 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);
- }
- template <typename T>
- 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());
- }
- 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 idx = indices[k];
- btSoftBody::DeformableFaceNodeContact& c = m_faceNodeContacts[idx];
- 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
|