2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans https://bulletphysics.org
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
15 ///btSoftBody implementation by Nathanael Presson
17 #include "btSoftBodyInternals.h"
18 #include "BulletSoftBody/btSoftBodySolvers.h"
19 #include "btSoftBodyData.h"
20 #include "LinearMath/btSerializer.h"
21 #include "LinearMath/btImplicitQRSVD.h"
22 #include "LinearMath/btAlignedAllocator.h"
23 #include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
24 #include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
25 #include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
26 #include "BulletCollision/CollisionShapes/btTriangleShape.h"
29 static inline btDbvtNode* buildTreeBottomUp(btAlignedObjectArray<btDbvtNode*>& leafNodes, btAlignedObjectArray<btAlignedObjectArray<int> >& adj)
31 int N = leafNodes.size();
38 btAlignedObjectArray<bool> marked;
39 btAlignedObjectArray<btDbvtNode*> newLeafNodes;
40 btAlignedObjectArray<std::pair<int, int> > childIds;
41 btAlignedObjectArray<btAlignedObjectArray<int> > newAdj;
43 for (int i = 0; i < N; ++i)
46 // pair adjacent nodes into new(parent) node
47 for (int i = 0; i < N; ++i)
52 for (int j = 0; j < adj[i].size(); ++j)
55 if (!marked[adj[i][j]])
57 btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
59 node->childs[0] = leafNodes[i];
60 node->childs[1] = leafNodes[n];
61 leafNodes[i]->parent = node;
62 leafNodes[n]->parent = node;
63 newLeafNodes.push_back(node);
64 childIds.push_back(std::make_pair(i, n));
72 newLeafNodes.push_back(leafNodes[i]);
73 childIds.push_back(std::make_pair(i, -1));
77 // update adjacency matrix
78 newAdj.resize(newLeafNodes.size());
79 for (int i = 0; i < newLeafNodes.size(); ++i)
81 for (int j = i + 1; j < newLeafNodes.size(); ++j)
83 bool neighbor = false;
84 const btAlignedObjectArray<int>& leftChildNeighbors = adj[childIds[i].first];
85 for (int k = 0; k < leftChildNeighbors.size(); ++k)
87 if (leftChildNeighbors[k] == childIds[j].first || leftChildNeighbors[k] == childIds[j].second)
93 if (!neighbor && childIds[i].second != -1)
95 const btAlignedObjectArray<int>& rightChildNeighbors = adj[childIds[i].second];
96 for (int k = 0; k < rightChildNeighbors.size(); ++k)
98 if (rightChildNeighbors[k] == childIds[j].first || rightChildNeighbors[k] == childIds[j].second)
107 newAdj[i].push_back(j);
108 newAdj[j].push_back(i);
112 leafNodes = newLeafNodes;
113 //this assignment leaks memory, the assignment doesn't do a deep copy, for now a manual copy
116 adj.resize(newAdj.size());
117 for (int i = 0; i < newAdj.size(); i++)
119 for (int j = 0; j < newAdj[i].size(); j++)
121 adj[i].push_back(newAdj[i][j]);
124 N = leafNodes.size();
130 btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m)
131 : m_softBodySolver(0), m_worldInfo(worldInfo)
136 /* Default material */
137 Material* pm = appendMaterial();
141 pm->m_flags = fMaterial::Default;
144 const btScalar margin = getCollisionShape()->getMargin();
145 m_nodes.resize(node_count);
146 m_X.resize(node_count);
147 for (int i = 0, ni = node_count; i < ni; ++i)
149 Node& n = m_nodes[i];
151 n.m_x = x ? *x++ : btVector3(0, 0, 0);
153 n.m_im = m ? *m++ : 1;
154 n.m_im = n.m_im > 0 ? 1 / n.m_im : 0;
155 n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x, margin), &n);
160 setCollisionQuadrature(3);
164 btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo)
165 : m_worldInfo(worldInfo)
170 void btSoftBody::initDefaults()
172 m_internalType = CO_SOFT_BODY;
173 m_cfg.aeromodel = eAeroModel::V_Point;
180 m_cfg.kDF = (btScalar)0.2;
182 m_cfg.kCHR = (btScalar)1.0;
183 m_cfg.kKHR = (btScalar)0.1;
184 m_cfg.kSHR = (btScalar)1.0;
185 m_cfg.kAHR = (btScalar)0.7;
186 m_cfg.kSRHR_CL = (btScalar)0.1;
187 m_cfg.kSKHR_CL = (btScalar)1;
188 m_cfg.kSSHR_CL = (btScalar)0.5;
189 m_cfg.kSR_SPLT_CL = (btScalar)0.5;
190 m_cfg.kSK_SPLT_CL = (btScalar)0.5;
191 m_cfg.kSS_SPLT_CL = (btScalar)0.5;
192 m_cfg.maxvolume = (btScalar)1;
194 m_cfg.viterations = 0;
195 m_cfg.piterations = 1;
196 m_cfg.diterations = 0;
197 m_cfg.citerations = 4;
199 m_cfg.m_maxStress = 0;
200 m_cfg.collisions = fCollision::Default;
201 m_pose.m_bvolume = false;
202 m_pose.m_bframe = false;
204 m_pose.m_com = btVector3(0, 0, 0);
205 m_pose.m_rot.setIdentity();
206 m_pose.m_scl.setIdentity();
209 m_bUpdateRtCst = true;
210 m_bounds[0] = btVector3(0, 0, 0);
211 m_bounds[1] = btVector3(0, 0, 0);
212 m_worldTransform.setIdentity();
213 setSolver(eSolverPresets::Positions);
215 /* Collision shape */
216 ///for now, create a collision shape internally
217 m_collisionShape = new btSoftBodyCollisionShape(this);
218 m_collisionShape->setMargin(0.25f);
220 m_worldTransform.setIdentity();
222 m_windVelocity = btVector3(0, 0, 0);
223 m_restLengthScale = btScalar(1.0);
224 m_dampingCoefficient = 1.0;
225 m_sleepingThreshold = .04;
226 m_useSelfCollision = false;
227 m_collisionFlags = 0;
228 m_softSoftCollision = false;
229 m_maxSpeedSquared = 0;
230 m_repulsionStiffness = 0.5;
232 m_cacheBarycenter = false;
236 m_reducedModel = false;
240 btSoftBody::~btSoftBody()
242 //for now, delete the internal shape
243 delete m_collisionShape;
247 for (i = 0; i < m_materials.size(); ++i)
248 btAlignedFree(m_materials[i]);
249 for (i = 0; i < m_joints.size(); ++i)
250 btAlignedFree(m_joints[i]);
256 bool btSoftBody::checkLink(int node0, int node1) const
258 return (checkLink(&m_nodes[node0], &m_nodes[node1]));
262 bool btSoftBody::checkLink(const Node* node0, const Node* node1) const
264 const Node* n[] = {node0, node1};
265 for (int i = 0, ni = m_links.size(); i < ni; ++i)
267 const Link& l = m_links[i];
268 if ((l.m_n[0] == n[0] && l.m_n[1] == n[1]) ||
269 (l.m_n[0] == n[1] && l.m_n[1] == n[0]))
278 bool btSoftBody::checkFace(int node0, int node1, int node2) const
280 const Node* n[] = {&m_nodes[node0],
283 for (int i = 0, ni = m_faces.size(); i < ni; ++i)
285 const Face& f = m_faces[i];
287 for (int j = 0; j < 3; ++j)
289 if ((f.m_n[j] == n[0]) ||
290 (f.m_n[j] == n[1]) ||
296 if (c == 7) return (true);
302 btSoftBody::Material* btSoftBody::appendMaterial()
304 Material* pm = new (btAlignedAlloc(sizeof(Material), 16)) Material();
305 if (m_materials.size() > 0)
306 *pm = *m_materials[0];
309 m_materials.push_back(pm);
314 void btSoftBody::appendNote(const char* text,
327 n.m_coords[0] = c.x();
328 n.m_coords[1] = c.y();
329 n.m_coords[2] = c.z();
330 n.m_coords[3] = c.w();
332 n.m_rank += n0 ? 1 : 0;
334 n.m_rank += n1 ? 1 : 0;
336 n.m_rank += n2 ? 1 : 0;
338 n.m_rank += n3 ? 1 : 0;
339 m_notes.push_back(n);
343 void btSoftBody::appendNote(const char* text,
347 appendNote(text, o, btVector4(1, 0, 0, 0), feature);
351 void btSoftBody::appendNote(const char* text,
355 static const btScalar w = 1 / (btScalar)2;
356 appendNote(text, o, btVector4(w, w, 0, 0), feature->m_n[0],
361 void btSoftBody::appendNote(const char* text,
365 static const btScalar w = 1 / (btScalar)3;
366 appendNote(text, o, btVector4(w, w, w, 0), feature->m_n[0],
372 void btSoftBody::appendNode(const btVector3& x, btScalar m)
374 if (m_nodes.capacity() == m_nodes.size())
377 m_nodes.reserve(m_nodes.size() * 2 + 1);
380 const btScalar margin = getCollisionShape()->getMargin();
381 m_nodes.push_back(Node());
382 Node& n = m_nodes[m_nodes.size() - 1];
386 n.m_im = m > 0 ? 1 / m : 0;
387 n.m_material = m_materials[0];
388 n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x, margin), &n);
392 void btSoftBody::appendLink(int model, Material* mat)
400 l.m_material = mat ? mat : m_materials[0];
402 m_links.push_back(l);
406 void btSoftBody::appendLink(int node0,
411 appendLink(&m_nodes[node0], &m_nodes[node1], mat, bcheckexist);
415 void btSoftBody::appendLink(Node* node0,
420 if ((!bcheckexist) || (!checkLink(node0, node1)))
423 Link& l = m_links[m_links.size() - 1];
426 l.m_rl = (l.m_n[0]->m_x - l.m_n[1]->m_x).length();
427 m_bUpdateRtCst = true;
432 void btSoftBody::appendFace(int model, Material* mat)
442 f.m_material = mat ? mat : m_materials[0];
444 m_faces.push_back(f);
448 void btSoftBody::appendFace(int node0, int node1, int node2, Material* mat)
458 Face& f = m_faces[m_faces.size() - 1];
459 btAssert(node0 != node1);
460 btAssert(node1 != node2);
461 btAssert(node2 != node0);
462 f.m_n[0] = &m_nodes[node0];
463 f.m_n[1] = &m_nodes[node1];
464 f.m_n[2] = &m_nodes[node2];
465 f.m_ra = AreaOf(f.m_n[0]->m_x,
468 m_bUpdateRtCst = true;
472 void btSoftBody::appendTetra(int model, Material* mat)
480 t.m_material = mat ? mat : m_materials[0];
482 m_tetras.push_back(t);
486 void btSoftBody::appendTetra(int node0,
492 appendTetra(-1, mat);
493 Tetra& t = m_tetras[m_tetras.size() - 1];
494 t.m_n[0] = &m_nodes[node0];
495 t.m_n[1] = &m_nodes[node1];
496 t.m_n[2] = &m_nodes[node2];
497 t.m_n[3] = &m_nodes[node3];
498 t.m_rv = VolumeOf(t.m_n[0]->m_x, t.m_n[1]->m_x, t.m_n[2]->m_x, t.m_n[3]->m_x);
499 m_bUpdateRtCst = true;
504 void btSoftBody::appendAnchor(int node, btRigidBody* body, bool disableCollisionBetweenLinkedBodies, btScalar influence)
506 btVector3 local = body->getWorldTransform().inverse() * m_nodes[node].m_x;
507 appendAnchor(node, body, local, disableCollisionBetweenLinkedBodies, influence);
511 void btSoftBody::appendAnchor(int node, btRigidBody* body, const btVector3& localPivot, bool disableCollisionBetweenLinkedBodies, btScalar influence)
513 if (disableCollisionBetweenLinkedBodies)
515 if (m_collisionDisabledObjects.findLinearSearch(body) == m_collisionDisabledObjects.size())
517 m_collisionDisabledObjects.push_back(body);
522 a.m_node = &m_nodes[node];
524 a.m_local = localPivot;
525 a.m_node->m_battach = 1;
526 a.m_influence = influence;
527 m_anchors.push_back(a);
531 void btSoftBody::appendDeformableAnchor(int node, btRigidBody* body)
533 DeformableNodeRigidAnchor c;
534 btSoftBody::Node& n = m_nodes[node];
535 const btScalar ima = n.m_im;
536 const btScalar imb = body->getInvMass();
538 const btCollisionShape* shp = body->getCollisionShape();
539 const btTransform& wtr = body->getWorldTransform();
541 m_worldInfo->m_sparsesdf.Evaluate(
542 wtr.invXform(m_nodes[node].m_x),
547 c.m_cti.m_colObj = body;
548 c.m_cti.m_normal = wtr.getBasis() * nrm;
549 c.m_cti.m_offset = dst;
550 c.m_node = &m_nodes[node];
551 const btScalar fc = m_cfg.kDF * body->getFriction();
554 c.m_c4 = body->isStaticOrKinematicObject() ? m_cfg.kKHR : m_cfg.kCHR;
555 static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
556 const btMatrix3x3& iwi = body->getInvInertiaTensorWorld();
557 const btVector3 ra = n.m_x - wtr.getOrigin();
559 c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
561 c.m_local = body->getWorldTransform().inverse() * m_nodes[node].m_x;
562 c.m_node->m_battach = 1;
563 m_deformableAnchors.push_back(c);
566 void btSoftBody::removeAnchor(int node)
568 const btSoftBody::Node& n = m_nodes[node];
569 for (int i = 0; i < m_deformableAnchors.size();)
571 const DeformableNodeRigidAnchor& c = m_deformableAnchors[i];
574 m_deformableAnchors.removeAtIndex(i);
584 void btSoftBody::appendDeformableAnchor(int node, btMultiBodyLinkCollider* link)
586 DeformableNodeRigidAnchor c;
587 btSoftBody::Node& n = m_nodes[node];
588 const btScalar ima = n.m_im;
590 const btCollisionShape* shp = link->getCollisionShape();
591 const btTransform& wtr = link->getWorldTransform();
593 m_worldInfo->m_sparsesdf.Evaluate(
594 wtr.invXform(m_nodes[node].m_x),
598 c.m_cti.m_colObj = link;
599 c.m_cti.m_normal = wtr.getBasis() * nrm;
600 c.m_cti.m_offset = dst;
601 c.m_node = &m_nodes[node];
602 const btScalar fc = m_cfg.kDF * link->getFriction();
605 c.m_c4 = link->isStaticOrKinematicObject() ? m_cfg.kKHR : m_cfg.kCHR;
606 btVector3 normal = c.m_cti.m_normal;
607 btVector3 t1 = generateUnitOrthogonalVector(normal);
608 btVector3 t2 = btCross(normal, t1);
609 btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
610 findJacobian(link, jacobianData_normal, c.m_node->m_x, normal);
611 findJacobian(link, jacobianData_t1, c.m_node->m_x, t1);
612 findJacobian(link, jacobianData_t2, c.m_node->m_x, t2);
614 btScalar* J_n = &jacobianData_normal.m_jacobians[0];
615 btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
616 btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
618 btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
619 btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
620 btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
622 btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
623 t1.getX(), t1.getY(), t1.getZ(),
624 t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
625 const int ndof = link->m_multiBody->getNumDofs() + 6;
626 btMatrix3x3 local_impulse_matrix = (Diagonal(n.m_im) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
627 c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
628 c.jacobianData_normal = jacobianData_normal;
629 c.jacobianData_t1 = jacobianData_t1;
630 c.jacobianData_t2 = jacobianData_t2;
633 const btVector3 ra = n.m_x - wtr.getOrigin();
635 c.m_local = link->getWorldTransform().inverse() * m_nodes[node].m_x;
636 c.m_node->m_battach = 1;
637 m_deformableAnchors.push_back(c);
640 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs, Cluster* body0, Body body1)
642 LJoint* pj = new (btAlignedAlloc(sizeof(LJoint), 16)) LJoint();
643 pj->m_bodies[0] = body0;
644 pj->m_bodies[1] = body1;
645 pj->m_refs[0] = pj->m_bodies[0].xform().inverse() * specs.position;
646 pj->m_refs[1] = pj->m_bodies[1].xform().inverse() * specs.position;
647 pj->m_cfm = specs.cfm;
648 pj->m_erp = specs.erp;
649 pj->m_split = specs.split;
650 m_joints.push_back(pj);
654 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs, Body body)
656 appendLinearJoint(specs, m_clusters[0], body);
660 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs, btSoftBody* body)
662 appendLinearJoint(specs, m_clusters[0], body->m_clusters[0]);
666 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs, Cluster* body0, Body body1)
668 AJoint* pj = new (btAlignedAlloc(sizeof(AJoint), 16)) AJoint();
669 pj->m_bodies[0] = body0;
670 pj->m_bodies[1] = body1;
671 pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis() * specs.axis;
672 pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis() * specs.axis;
673 pj->m_cfm = specs.cfm;
674 pj->m_erp = specs.erp;
675 pj->m_split = specs.split;
676 pj->m_icontrol = specs.icontrol;
677 m_joints.push_back(pj);
681 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs, Body body)
683 appendAngularJoint(specs, m_clusters[0], body);
687 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs, btSoftBody* body)
689 appendAngularJoint(specs, m_clusters[0], body->m_clusters[0]);
693 void btSoftBody::addForce(const btVector3& force)
695 for (int i = 0, ni = m_nodes.size(); i < ni; ++i) addForce(force, i);
699 void btSoftBody::addForce(const btVector3& force, int node)
701 Node& n = m_nodes[node];
708 void btSoftBody::addAeroForceToNode(const btVector3& windVelocity, int nodeIndex)
710 btAssert(nodeIndex >= 0 && nodeIndex < m_nodes.size());
712 const btScalar dt = m_sst.sdt;
713 const btScalar kLF = m_cfg.kLF;
714 const btScalar kDG = m_cfg.kDG;
715 //const btScalar kPR = m_cfg.kPR;
716 //const btScalar kVC = m_cfg.kVC;
717 const bool as_lift = kLF > 0;
718 const bool as_drag = kDG > 0;
719 const bool as_aero = as_lift || as_drag;
720 const bool as_vaero = as_aero && (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
722 Node& n = m_nodes[nodeIndex];
726 btSoftBody::sMedium medium;
728 EvaluateMedium(m_worldInfo, n.m_x, medium);
729 medium.m_velocity = windVelocity;
730 medium.m_density = m_worldInfo->air_density;
735 const btVector3 rel_v = n.m_v - medium.m_velocity;
736 const btScalar rel_v_len = rel_v.length();
737 const btScalar rel_v2 = rel_v.length2();
739 if (rel_v2 > SIMD_EPSILON)
741 const btVector3 rel_v_nrm = rel_v.normalized();
742 btVector3 nrm = n.m_n;
744 if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSidedLiftDrag)
746 nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
747 btVector3 fDrag(0, 0, 0);
748 btVector3 fLift(0, 0, 0);
750 btScalar n_dot_v = nrm.dot(rel_v_nrm);
751 btScalar tri_area = 0.5f * n.m_area;
753 fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
755 // Check angle of attack
756 // cos(10º) = 0.98480
757 if (0 < n_dot_v && n_dot_v < 0.98480f)
758 fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f - n_dot_v * n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
760 // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
761 btVector3 del_v_by_fDrag = fDrag * n.m_im * m_sst.sdt;
762 btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
763 btScalar v_len2 = n.m_v.length2();
765 if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
767 btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
768 btScalar v_len = n.m_v.length();
769 fDrag *= btScalar(0.8) * (v_len / del_v_by_fDrag_len);
775 else if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_Point || m_cfg.aeromodel == btSoftBody::eAeroModel::V_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided)
777 if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided)
778 nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
780 const btScalar dvn = btDot(rel_v, nrm);
784 btVector3 force(0, 0, 0);
785 const btScalar c0 = n.m_area * dvn * rel_v2 / 2;
786 const btScalar c1 = c0 * medium.m_density;
787 force += nrm * (-c1 * kLF);
788 force += rel_v.normalized() * (-c1 * kDG);
789 ApplyClampedForce(n, force, dt);
797 void btSoftBody::addAeroForceToFace(const btVector3& windVelocity, int faceIndex)
799 const btScalar dt = m_sst.sdt;
800 const btScalar kLF = m_cfg.kLF;
801 const btScalar kDG = m_cfg.kDG;
802 // const btScalar kPR = m_cfg.kPR;
803 // const btScalar kVC = m_cfg.kVC;
804 const bool as_lift = kLF > 0;
805 const bool as_drag = kDG > 0;
806 const bool as_aero = as_lift || as_drag;
807 const bool as_faero = as_aero && (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
811 btSoftBody::Face& f = m_faces[faceIndex];
813 btSoftBody::sMedium medium;
815 const btVector3 v = (f.m_n[0]->m_v + f.m_n[1]->m_v + f.m_n[2]->m_v) / 3;
816 const btVector3 x = (f.m_n[0]->m_x + f.m_n[1]->m_x + f.m_n[2]->m_x) / 3;
817 EvaluateMedium(m_worldInfo, x, medium);
818 medium.m_velocity = windVelocity;
819 medium.m_density = m_worldInfo->air_density;
820 const btVector3 rel_v = v - medium.m_velocity;
821 const btScalar rel_v_len = rel_v.length();
822 const btScalar rel_v2 = rel_v.length2();
824 if (rel_v2 > SIMD_EPSILON)
826 const btVector3 rel_v_nrm = rel_v.normalized();
827 btVector3 nrm = f.m_normal;
829 if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSidedLiftDrag)
831 nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
833 btVector3 fDrag(0, 0, 0);
834 btVector3 fLift(0, 0, 0);
836 btScalar n_dot_v = nrm.dot(rel_v_nrm);
837 btScalar tri_area = 0.5f * f.m_ra;
839 fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
841 // Check angle of attack
842 // cos(10º) = 0.98480
843 if (0 < n_dot_v && n_dot_v < 0.98480f)
844 fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f - n_dot_v * n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
849 for (int j = 0; j < 3; ++j)
851 if (f.m_n[j]->m_im > 0)
853 // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
854 btVector3 del_v_by_fDrag = fDrag * f.m_n[j]->m_im * m_sst.sdt;
855 btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
856 btScalar v_len2 = f.m_n[j]->m_v.length2();
858 if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
860 btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
861 btScalar v_len = f.m_n[j]->m_v.length();
862 fDrag *= btScalar(0.8) * (v_len / del_v_by_fDrag_len);
865 f.m_n[j]->m_f += fDrag;
866 f.m_n[j]->m_f += fLift;
870 else if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided)
872 if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided)
873 nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
875 const btScalar dvn = btDot(rel_v, nrm);
879 btVector3 force(0, 0, 0);
880 const btScalar c0 = f.m_ra * dvn * rel_v2;
881 const btScalar c1 = c0 * medium.m_density;
882 force += nrm * (-c1 * kLF);
883 force += rel_v.normalized() * (-c1 * kDG);
885 for (int j = 0; j < 3; ++j) ApplyClampedForce(*f.m_n[j], force, dt);
893 void btSoftBody::addVelocity(const btVector3& velocity)
895 for (int i = 0, ni = m_nodes.size(); i < ni; ++i) addVelocity(velocity, i);
898 /* Set velocity for the entire body */
899 void btSoftBody::setVelocity(const btVector3& velocity)
901 for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
903 Node& n = m_nodes[i];
913 void btSoftBody::addVelocity(const btVector3& velocity, int node)
915 Node& n = m_nodes[node];
923 void btSoftBody::setMass(int node, btScalar mass)
925 m_nodes[node].m_im = mass > 0 ? 1 / mass : 0;
926 m_bUpdateRtCst = true;
930 btScalar btSoftBody::getMass(int node) const
932 return (m_nodes[node].m_im > 0 ? 1 / m_nodes[node].m_im : 0);
936 btScalar btSoftBody::getTotalMass() const
939 for (int i = 0; i < m_nodes.size(); ++i)
947 void btSoftBody::setTotalMass(btScalar mass, bool fromfaces)
953 for (i = 0; i < m_nodes.size(); ++i)
957 for (i = 0; i < m_faces.size(); ++i)
959 const Face& f = m_faces[i];
960 const btScalar twicearea = AreaOf(f.m_n[0]->m_x,
963 for (int j = 0; j < 3; ++j)
965 f.m_n[j]->m_im += twicearea;
968 for (i = 0; i < m_nodes.size(); ++i)
970 m_nodes[i].m_im = 1 / m_nodes[i].m_im;
973 const btScalar tm = getTotalMass();
974 const btScalar itm = 1 / tm;
975 for (i = 0; i < m_nodes.size(); ++i)
977 m_nodes[i].m_im /= itm * mass;
979 m_bUpdateRtCst = true;
983 void btSoftBody::setTotalDensity(btScalar density)
985 setTotalMass(getVolume() * density, true);
989 void btSoftBody::setVolumeMass(btScalar mass)
991 btAlignedObjectArray<btScalar> ranks;
992 ranks.resize(m_nodes.size(), 0);
995 for (i = 0; i < m_nodes.size(); ++i)
999 for (i = 0; i < m_tetras.size(); ++i)
1001 const Tetra& t = m_tetras[i];
1002 for (int j = 0; j < 4; ++j)
1004 t.m_n[j]->m_im += btFabs(t.m_rv);
1005 ranks[int(t.m_n[j] - &m_nodes[0])] += 1;
1008 for (i = 0; i < m_nodes.size(); ++i)
1010 if (m_nodes[i].m_im > 0)
1012 m_nodes[i].m_im = ranks[i] / m_nodes[i].m_im;
1015 setTotalMass(mass, false);
1019 void btSoftBody::setVolumeDensity(btScalar density)
1021 btScalar volume = 0;
1022 for (int i = 0; i < m_tetras.size(); ++i)
1024 const Tetra& t = m_tetras[i];
1025 for (int j = 0; j < 4; ++j)
1027 volume += btFabs(t.m_rv);
1030 setVolumeMass(volume * density / 6);
1034 btVector3 btSoftBody::getLinearVelocity()
1036 btVector3 total_momentum = btVector3(0, 0, 0);
1037 for (int i = 0; i < m_nodes.size(); ++i)
1039 btScalar mass = m_nodes[i].m_im == 0 ? 0 : 1.0 / m_nodes[i].m_im;
1040 total_momentum += mass * m_nodes[i].m_v;
1042 btScalar total_mass = getTotalMass();
1043 return total_mass == 0 ? total_momentum : total_momentum / total_mass;
1047 void btSoftBody::setLinearVelocity(const btVector3& linVel)
1049 btVector3 old_vel = getLinearVelocity();
1050 btVector3 diff = linVel - old_vel;
1051 for (int i = 0; i < m_nodes.size(); ++i)
1052 m_nodes[i].m_v += diff;
1056 void btSoftBody::setAngularVelocity(const btVector3& angVel)
1058 btVector3 old_vel = getLinearVelocity();
1059 btVector3 com = getCenterOfMass();
1060 for (int i = 0; i < m_nodes.size(); ++i)
1062 m_nodes[i].m_v = angVel.cross(m_nodes[i].m_x - com) + old_vel;
1067 btTransform btSoftBody::getRigidTransform()
1069 btVector3 t = getCenterOfMass();
1072 // Get rotation that minimizes L2 difference: \sum_i || RX_i + t - x_i ||
1073 // It's important to make sure that S has the correct signs.
1074 // SVD is only unique up to the ordering of singular values.
1075 // SVD will manipulate U and V to ensure the ordering of singular values. If all three singular
1076 // vaues are negative, SVD will permute colums of U to make two of them positive.
1077 for (int i = 0; i < m_nodes.size(); ++i)
1079 S -= OuterProduct(m_X[i], t - m_nodes[i].m_x);
1083 singularValueDecomposition(S, U, sigma, V);
1084 btMatrix3x3 R = V * U.transpose();
1093 void btSoftBody::transformTo(const btTransform& trs)
1095 // get the current best rigid fit
1096 btTransform current_transform = getRigidTransform();
1097 // apply transform in material space
1098 btTransform new_transform = trs * current_transform.inverse();
1099 transform(new_transform);
1103 void btSoftBody::transform(const btTransform& trs)
1105 const btScalar margin = getCollisionShape()->getMargin();
1106 ATTRIBUTE_ALIGNED16(btDbvtVolume)
1109 for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
1111 Node& n = m_nodes[i];
1112 n.m_x = trs * n.m_x;
1113 n.m_q = trs * n.m_q;
1114 n.m_n = trs.getBasis() * n.m_n;
1115 vol = btDbvtVolume::FromCR(n.m_x, margin);
1117 m_ndbvt.update(n.m_leaf, vol);
1125 void btSoftBody::translate(const btVector3& trs)
1134 void btSoftBody::rotate(const btQuaternion& rot)
1143 void btSoftBody::scale(const btVector3& scl)
1145 const btScalar margin = getCollisionShape()->getMargin();
1146 ATTRIBUTE_ALIGNED16(btDbvtVolume)
1149 for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
1151 Node& n = m_nodes[i];
1154 vol = btDbvtVolume::FromCR(n.m_x, margin);
1155 m_ndbvt.update(n.m_leaf, vol);
1160 initializeDmInverse();
1164 btScalar btSoftBody::getRestLengthScale()
1166 return m_restLengthScale;
1170 void btSoftBody::setRestLengthScale(btScalar restLengthScale)
1172 for (int i = 0, ni = m_links.size(); i < ni; ++i)
1174 Link& l = m_links[i];
1175 l.m_rl = l.m_rl / m_restLengthScale * restLengthScale;
1176 l.m_c1 = l.m_rl * l.m_rl;
1178 m_restLengthScale = restLengthScale;
1180 if (getActivationState() == ISLAND_SLEEPING)
1185 void btSoftBody::setPose(bool bvolume, bool bframe)
1187 m_pose.m_bvolume = bvolume;
1188 m_pose.m_bframe = bframe;
1192 const btScalar omass = getTotalMass();
1193 const btScalar kmass = omass * m_nodes.size() * 1000;
1194 btScalar tmass = omass;
1195 m_pose.m_wgh.resize(m_nodes.size());
1196 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
1198 if (m_nodes[i].m_im <= 0) tmass += kmass;
1200 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
1202 Node& n = m_nodes[i];
1203 m_pose.m_wgh[i] = n.m_im > 0 ? 1 / (m_nodes[i].m_im * tmass) : kmass / tmass;
1206 const btVector3 com = evaluateCom();
1207 m_pose.m_pos.resize(m_nodes.size());
1208 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
1210 m_pose.m_pos[i] = m_nodes[i].m_x - com;
1212 m_pose.m_volume = bvolume ? getVolume() : 0;
1214 m_pose.m_rot.setIdentity();
1215 m_pose.m_scl.setIdentity();
1219 m_pose.m_aqq[2] = btVector3(0, 0, 0);
1220 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
1222 const btVector3& q = m_pose.m_pos[i];
1223 const btVector3 mq = m_pose.m_wgh[i] * q;
1224 m_pose.m_aqq[0] += mq.x() * q;
1225 m_pose.m_aqq[1] += mq.y() * q;
1226 m_pose.m_aqq[2] += mq.z() * q;
1228 m_pose.m_aqq = m_pose.m_aqq.inverse();
1233 void btSoftBody::resetLinkRestLengths()
1235 for (int i = 0, ni = m_links.size(); i < ni; ++i)
1237 Link& l = m_links[i];
1238 l.m_rl = (l.m_n[0]->m_x - l.m_n[1]->m_x).length();
1239 l.m_c1 = l.m_rl * l.m_rl;
1244 btScalar btSoftBody::getVolume() const
1247 if (m_nodes.size() > 0)
1251 const btVector3 org = m_nodes[0].m_x;
1252 for (i = 0, ni = m_faces.size(); i < ni; ++i)
1254 const Face& f = m_faces[i];
1255 vol += btDot(f.m_n[0]->m_x - org, btCross(f.m_n[1]->m_x - org, f.m_n[2]->m_x - org));
1263 int btSoftBody::clusterCount() const
1265 return (m_clusters.size());
1269 btVector3 btSoftBody::clusterCom(const Cluster* cluster)
1271 btVector3 com(0, 0, 0);
1272 for (int i = 0, ni = cluster->m_nodes.size(); i < ni; ++i)
1274 com += cluster->m_nodes[i]->m_x * cluster->m_masses[i];
1276 return (com * cluster->m_imass);
1280 btVector3 btSoftBody::clusterCom(int cluster) const
1282 return (clusterCom(m_clusters[cluster]));
1286 btVector3 btSoftBody::clusterVelocity(const Cluster* cluster, const btVector3& rpos)
1288 return (cluster->m_lv + btCross(cluster->m_av, rpos));
1292 void btSoftBody::clusterVImpulse(Cluster* cluster, const btVector3& rpos, const btVector3& impulse)
1294 const btVector3 li = cluster->m_imass * impulse;
1295 const btVector3 ai = cluster->m_invwi * btCross(rpos, impulse);
1296 cluster->m_vimpulses[0] += li;
1297 cluster->m_lv += li;
1298 cluster->m_vimpulses[1] += ai;
1299 cluster->m_av += ai;
1300 cluster->m_nvimpulses++;
1304 void btSoftBody::clusterDImpulse(Cluster* cluster, const btVector3& rpos, const btVector3& impulse)
1306 const btVector3 li = cluster->m_imass * impulse;
1307 const btVector3 ai = cluster->m_invwi * btCross(rpos, impulse);
1308 cluster->m_dimpulses[0] += li;
1309 cluster->m_dimpulses[1] += ai;
1310 cluster->m_ndimpulses++;
1314 void btSoftBody::clusterImpulse(Cluster* cluster, const btVector3& rpos, const Impulse& impulse)
1316 if (impulse.m_asVelocity) clusterVImpulse(cluster, rpos, impulse.m_velocity);
1317 if (impulse.m_asDrift) clusterDImpulse(cluster, rpos, impulse.m_drift);
1321 void btSoftBody::clusterVAImpulse(Cluster* cluster, const btVector3& impulse)
1323 const btVector3 ai = cluster->m_invwi * impulse;
1324 cluster->m_vimpulses[1] += ai;
1325 cluster->m_av += ai;
1326 cluster->m_nvimpulses++;
1330 void btSoftBody::clusterDAImpulse(Cluster* cluster, const btVector3& impulse)
1332 const btVector3 ai = cluster->m_invwi * impulse;
1333 cluster->m_dimpulses[1] += ai;
1334 cluster->m_ndimpulses++;
1338 void btSoftBody::clusterAImpulse(Cluster* cluster, const Impulse& impulse)
1340 if (impulse.m_asVelocity) clusterVAImpulse(cluster, impulse.m_velocity);
1341 if (impulse.m_asDrift) clusterDAImpulse(cluster, impulse.m_drift);
1345 void btSoftBody::clusterDCImpulse(Cluster* cluster, const btVector3& impulse)
1347 cluster->m_dimpulses[0] += impulse * cluster->m_imass;
1348 cluster->m_ndimpulses++;
1353 btAlignedObjectArray<int> m_links;
1357 int btSoftBody::generateBendingConstraints(int distance, Material* mat)
1364 const int n = m_nodes.size();
1365 const unsigned inf = (~(unsigned)0) >> 1;
1366 unsigned* adj = new unsigned[n * n];
1368 #define IDX(_x_, _y_) ((_y_)*n + (_x_))
1369 for (j = 0; j < n; ++j)
1371 for (i = 0; i < n; ++i)
1375 adj[IDX(i, j)] = adj[IDX(j, i)] = inf;
1379 adj[IDX(i, j)] = adj[IDX(j, i)] = 0;
1383 for (i = 0; i < m_links.size(); ++i)
1385 const int ia = (int)(m_links[i].m_n[0] - &m_nodes[0]);
1386 const int ib = (int)(m_links[i].m_n[1] - &m_nodes[0]);
1387 adj[IDX(ia, ib)] = 1;
1388 adj[IDX(ib, ia)] = 1;
1391 //special optimized case for distance == 2
1394 btAlignedObjectArray<NodeLinks> nodeLinks;
1396 /* Build node links */
1397 nodeLinks.resize(m_nodes.size());
1399 for (i = 0; i < m_links.size(); ++i)
1401 const int ia = (int)(m_links[i].m_n[0] - &m_nodes[0]);
1402 const int ib = (int)(m_links[i].m_n[1] - &m_nodes[0]);
1403 if (nodeLinks[ia].m_links.findLinearSearch(ib) == nodeLinks[ia].m_links.size())
1404 nodeLinks[ia].m_links.push_back(ib);
1406 if (nodeLinks[ib].m_links.findLinearSearch(ia) == nodeLinks[ib].m_links.size())
1407 nodeLinks[ib].m_links.push_back(ia);
1409 for (int ii = 0; ii < nodeLinks.size(); ii++)
1413 for (int jj = 0; jj < nodeLinks[ii].m_links.size(); jj++)
1415 int k = nodeLinks[ii].m_links[jj];
1416 for (int kk = 0; kk < nodeLinks[k].m_links.size(); kk++)
1418 int j = nodeLinks[k].m_links[kk];
1421 const unsigned sum = adj[IDX(i, k)] + adj[IDX(k, j)];
1423 if (adj[IDX(i, j)] > sum)
1425 adj[IDX(i, j)] = adj[IDX(j, i)] = sum;
1434 ///generic Floyd's algorithm
1435 for (int k = 0; k < n; ++k)
1437 for (j = 0; j < n; ++j)
1439 for (i = j + 1; i < n; ++i)
1441 const unsigned sum = adj[IDX(i, k)] + adj[IDX(k, j)];
1442 if (adj[IDX(i, j)] > sum)
1444 adj[IDX(i, j)] = adj[IDX(j, i)] = sum;
1453 for (j = 0; j < n; ++j)
1455 for (i = j + 1; i < n; ++i)
1457 if (adj[IDX(i, j)] == (unsigned)distance)
1459 appendLink(i, j, mat);
1460 m_links[m_links.size() - 1].m_bbending = 1;
1472 void btSoftBody::randomizeConstraints()
1474 unsigned long seed = 243703;
1475 #define NEXTRAND (seed = (1664525L * seed + 1013904223L) & 0xffffffff)
1478 for (i = 0, ni = m_links.size(); i < ni; ++i)
1480 btSwap(m_links[i], m_links[NEXTRAND % ni]);
1482 for (i = 0, ni = m_faces.size(); i < ni; ++i)
1484 btSwap(m_faces[i], m_faces[NEXTRAND % ni]);
1489 void btSoftBody::updateState(const btAlignedObjectArray<btVector3>& q, const btAlignedObjectArray<btVector3>& v)
1491 int node_count = m_nodes.size();
1492 btAssert(node_count == q.size());
1493 btAssert(node_count == v.size());
1494 for (int i = 0; i < node_count; i++)
1496 Node& n = m_nodes[i];
1505 void btSoftBody::releaseCluster(int index)
1507 Cluster* c = m_clusters[index];
1508 if (c->m_leaf) m_cdbvt.remove(c->m_leaf);
1511 m_clusters.remove(c);
1515 void btSoftBody::releaseClusters()
1517 while (m_clusters.size() > 0) releaseCluster(0);
1521 int btSoftBody::generateClusters(int k, int maxiterations)
1525 m_clusters.resize(btMin(k, m_nodes.size()));
1526 for (i = 0; i < m_clusters.size(); ++i)
1528 m_clusters[i] = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
1529 m_clusters[i]->m_collide = true;
1531 k = m_clusters.size();
1535 btAlignedObjectArray<btVector3> centers;
1536 btVector3 cog(0, 0, 0);
1538 for (i = 0; i < m_nodes.size(); ++i)
1540 cog += m_nodes[i].m_x;
1541 m_clusters[(i * 29873) % m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
1543 cog /= (btScalar)m_nodes.size();
1544 centers.resize(k, cog);
1546 const btScalar slope = 16;
1551 const btScalar w = 2 - btMin<btScalar>(1, iterations / slope);
1556 for (i = 0; i < k; ++i)
1558 btVector3 c(0, 0, 0);
1559 for (int j = 0; j < m_clusters[i]->m_nodes.size(); ++j)
1561 c += m_clusters[i]->m_nodes[j]->m_x;
1563 if (m_clusters[i]->m_nodes.size())
1565 c /= (btScalar)m_clusters[i]->m_nodes.size();
1566 c = centers[i] + (c - centers[i]) * w;
1567 changed |= ((c - centers[i]).length2() > SIMD_EPSILON);
1569 m_clusters[i]->m_nodes.resize(0);
1572 for (i = 0; i < m_nodes.size(); ++i)
1574 const btVector3 nx = m_nodes[i].m_x;
1576 btScalar kdist = ClusterMetric(centers[0], nx);
1577 for (int j = 1; j < k; ++j)
1579 const btScalar d = ClusterMetric(centers[j], nx);
1586 m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
1588 } while (changed && (iterations < maxiterations));
1590 btAlignedObjectArray<int> cids;
1591 cids.resize(m_nodes.size(), -1);
1592 for (i = 0; i < m_clusters.size(); ++i)
1594 for (int j = 0; j < m_clusters[i]->m_nodes.size(); ++j)
1596 cids[int(m_clusters[i]->m_nodes[j] - &m_nodes[0])] = i;
1599 for (i = 0; i < m_faces.size(); ++i)
1601 const int idx[] = {int(m_faces[i].m_n[0] - &m_nodes[0]),
1602 int(m_faces[i].m_n[1] - &m_nodes[0]),
1603 int(m_faces[i].m_n[2] - &m_nodes[0])};
1604 for (int j = 0; j < 3; ++j)
1606 const int cid = cids[idx[j]];
1607 for (int q = 1; q < 3; ++q)
1609 const int kid = idx[(j + q) % 3];
1610 if (cids[kid] != cid)
1612 if (m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid]) == m_clusters[cid]->m_nodes.size())
1614 m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
1621 if (m_clusters.size() > 1)
1623 Cluster* pmaster = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
1624 pmaster->m_collide = false;
1625 pmaster->m_nodes.reserve(m_nodes.size());
1626 for (int i = 0; i < m_nodes.size(); ++i) pmaster->m_nodes.push_back(&m_nodes[i]);
1627 m_clusters.push_back(pmaster);
1628 btSwap(m_clusters[0], m_clusters[m_clusters.size() - 1]);
1631 for (i = 0; i < m_clusters.size(); ++i)
1633 if (m_clusters[i]->m_nodes.size() == 0)
1635 releaseCluster(i--);
1641 //create a cluster for each tetrahedron (if tetrahedra exist) or each face
1642 if (m_tetras.size())
1644 m_clusters.resize(m_tetras.size());
1645 for (i = 0; i < m_clusters.size(); ++i)
1647 m_clusters[i] = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
1648 m_clusters[i]->m_collide = true;
1650 for (i = 0; i < m_tetras.size(); i++)
1652 for (int j = 0; j < 4; j++)
1654 m_clusters[i]->m_nodes.push_back(m_tetras[i].m_n[j]);
1660 m_clusters.resize(m_faces.size());
1661 for (i = 0; i < m_clusters.size(); ++i)
1663 m_clusters[i] = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
1664 m_clusters[i]->m_collide = true;
1667 for (i = 0; i < m_faces.size(); ++i)
1669 for (int j = 0; j < 3; ++j)
1671 m_clusters[i]->m_nodes.push_back(m_faces[i].m_n[j]);
1677 if (m_clusters.size())
1679 initializeClusters();
1682 //for self-collision
1683 m_clusterConnectivity.resize(m_clusters.size() * m_clusters.size());
1685 for (int c0 = 0; c0 < m_clusters.size(); c0++)
1687 m_clusters[c0]->m_clusterIndex = c0;
1688 for (int c1 = 0; c1 < m_clusters.size(); c1++)
1690 bool connected = false;
1691 Cluster* cla = m_clusters[c0];
1692 Cluster* clb = m_clusters[c1];
1693 for (int i = 0; !connected && i < cla->m_nodes.size(); i++)
1695 for (int j = 0; j < clb->m_nodes.size(); j++)
1697 if (cla->m_nodes[i] == clb->m_nodes[j])
1704 m_clusterConnectivity[c0 + c1 * m_clusters.size()] = connected;
1710 return (m_clusters.size());
1714 void btSoftBody::refine(ImplicitFn* ifn, btScalar accurary, bool cut)
1716 const Node* nbase = &m_nodes[0];
1717 int ncount = m_nodes.size();
1718 btSymMatrix<int> edges(ncount, -2);
1723 for (i = 0; i < m_links.size(); ++i)
1725 Link& l = m_links[i];
1728 if (!SameSign(ifn->Eval(l.m_n[0]->m_x), ifn->Eval(l.m_n[1]->m_x)))
1730 btSwap(m_links[i], m_links[m_links.size() - 1]);
1737 for (i = 0; i < m_links.size(); ++i)
1739 Link& l = m_links[i];
1740 edges(int(l.m_n[0] - nbase), int(l.m_n[1] - nbase)) = -1;
1742 for (i = 0; i < m_faces.size(); ++i)
1744 Face& f = m_faces[i];
1745 edges(int(f.m_n[0] - nbase), int(f.m_n[1] - nbase)) = -1;
1746 edges(int(f.m_n[1] - nbase), int(f.m_n[2] - nbase)) = -1;
1747 edges(int(f.m_n[2] - nbase), int(f.m_n[0] - nbase)) = -1;
1750 for (i = 0; i < ncount; ++i)
1752 for (j = i + 1; j < ncount; ++j)
1754 if (edges(i, j) == -1)
1756 Node& a = m_nodes[i];
1757 Node& b = m_nodes[j];
1758 const btScalar t = ImplicitSolve(ifn, a.m_x, b.m_x, accurary);
1761 const btVector3 x = Lerp(a.m_x, b.m_x, t);
1762 const btVector3 v = Lerp(a.m_v, b.m_v, t);
1768 const btScalar ma = 1 / a.m_im;
1769 const btScalar mb = 1 / b.m_im;
1770 const btScalar mc = Lerp(ma, mb, t);
1771 const btScalar f = (ma + mb) / (ma + mb + mc);
1772 a.m_im = 1 / (ma * f);
1773 b.m_im = 1 / (mb * f);
1793 edges(i, j) = m_nodes.size() - 1;
1794 m_nodes[edges(i, j)].m_v = v;
1800 nbase = &m_nodes[0];
1802 for (i = 0, ni = m_links.size(); i < ni; ++i)
1804 Link& feat = m_links[i];
1805 const int idx[] = {int(feat.m_n[0] - nbase),
1806 int(feat.m_n[1] - nbase)};
1807 if ((idx[0] < ncount) && (idx[1] < ncount))
1809 const int ni = edges(idx[0], idx[1]);
1813 Link* pft[] = {&m_links[i],
1814 &m_links[m_links.size() - 1]};
1815 pft[0]->m_n[0] = &m_nodes[idx[0]];
1816 pft[0]->m_n[1] = &m_nodes[ni];
1817 pft[1]->m_n[0] = &m_nodes[ni];
1818 pft[1]->m_n[1] = &m_nodes[idx[1]];
1823 for (i = 0; i < m_faces.size(); ++i)
1825 const Face& feat = m_faces[i];
1826 const int idx[] = {int(feat.m_n[0] - nbase),
1827 int(feat.m_n[1] - nbase),
1828 int(feat.m_n[2] - nbase)};
1829 for (j = 2, k = 0; k < 3; j = k++)
1831 if ((idx[j] < ncount) && (idx[k] < ncount))
1833 const int ni = edges(idx[j], idx[k]);
1837 const int l = (k + 1) % 3;
1838 Face* pft[] = {&m_faces[i],
1839 &m_faces[m_faces.size() - 1]};
1840 pft[0]->m_n[0] = &m_nodes[idx[l]];
1841 pft[0]->m_n[1] = &m_nodes[idx[j]];
1842 pft[0]->m_n[2] = &m_nodes[ni];
1843 pft[1]->m_n[0] = &m_nodes[ni];
1844 pft[1]->m_n[1] = &m_nodes[idx[k]];
1845 pft[1]->m_n[2] = &m_nodes[idx[l]];
1846 appendLink(ni, idx[l], pft[0]->m_material);
1856 btAlignedObjectArray<int> cnodes;
1857 const int pcount = ncount;
1859 ncount = m_nodes.size();
1860 cnodes.resize(ncount, 0);
1862 for (i = 0; i < ncount; ++i)
1864 const btVector3 x = m_nodes[i].m_x;
1865 if ((i >= pcount) || (btFabs(ifn->Eval(x)) < accurary))
1867 const btVector3 v = m_nodes[i].m_v;
1868 btScalar m = getMass(i);
1872 m_nodes[i].m_im /= 0.5f;
1875 cnodes[i] = m_nodes.size() - 1;
1876 m_nodes[cnodes[i]].m_v = v;
1879 nbase = &m_nodes[0];
1881 for (i = 0, ni = m_links.size(); i < ni; ++i)
1883 const int id[] = {int(m_links[i].m_n[0] - nbase),
1884 int(m_links[i].m_n[1] - nbase)};
1886 if (cnodes[id[0]] && cnodes[id[1]])
1889 todetach = m_links.size() - 1;
1893 if (((ifn->Eval(m_nodes[id[0]].m_x) < accurary) &&
1894 (ifn->Eval(m_nodes[id[1]].m_x) < accurary)))
1899 Link& l = m_links[todetach];
1900 for (int j = 0; j < 2; ++j)
1902 int cn = cnodes[int(l.m_n[j] - nbase)];
1903 if (cn) l.m_n[j] = &m_nodes[cn];
1908 for (i = 0, ni = m_faces.size(); i < ni; ++i)
1910 Node** n = m_faces[i].m_n;
1911 if ((ifn->Eval(n[0]->m_x) < accurary) &&
1912 (ifn->Eval(n[1]->m_x) < accurary) &&
1913 (ifn->Eval(n[2]->m_x) < accurary))
1915 for (int j = 0; j < 3; ++j)
1917 int cn = cnodes[int(n[j] - nbase)];
1918 if (cn) n[j] = &m_nodes[cn];
1923 int nnodes = m_nodes.size();
1924 btAlignedObjectArray<int> ranks;
1925 btAlignedObjectArray<int> todelete;
1926 ranks.resize(nnodes, 0);
1927 for (i = 0, ni = m_links.size(); i < ni; ++i)
1929 for (int j = 0; j < 2; ++j) ranks[int(m_links[i].m_n[j] - nbase)]++;
1931 for (i = 0, ni = m_faces.size(); i < ni; ++i)
1933 for (int j = 0; j < 3; ++j) ranks[int(m_faces[i].m_n[j] - nbase)]++;
1935 for (i = 0; i < m_links.size(); ++i)
1937 const int id[] = {int(m_links[i].m_n[0] - nbase),
1938 int(m_links[i].m_n[1] - nbase)};
1939 const bool sg[] = {ranks[id[0]] == 1,
1945 btSwap(m_links[i], m_links[m_links.size() - 1]);
1951 for(i=nnodes-1;i>=0;--i)
1953 if(!ranks[i]) todelete.push_back(i);
1957 btAlignedObjectArray<int>& map=ranks;
1958 for(int i=0;i<nnodes;++i) map[i]=i;
1959 PointersToIndices(this);
1960 for(int i=0,ni=todelete.size();i<ni;++i)
1964 int& b=map[--nnodes];
1965 m_ndbvt.remove(m_nodes[a].m_leaf);m_nodes[a].m_leaf=0;
1966 btSwap(m_nodes[a],m_nodes[b]);
1969 IndicesToPointers(this,&map[0]);
1970 m_nodes.resize(nnodes);
1974 m_bUpdateRtCst = true;
1978 bool btSoftBody::cutLink(const Node* node0, const Node* node1, btScalar position)
1980 return (cutLink(int(node0 - &m_nodes[0]), int(node1 - &m_nodes[0]), position));
1984 bool btSoftBody::cutLink(int node0, int node1, btScalar position)
1988 // const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
1989 const btVector3 x = Lerp(m_nodes[node0].m_x, m_nodes[node1].m_x, position);
1990 const btVector3 v = Lerp(m_nodes[node0].m_v, m_nodes[node1].m_v, position);
1991 const btScalar m = 1;
1994 Node* pa = &m_nodes[node0];
1995 Node* pb = &m_nodes[node1];
1996 Node* pn[2] = {&m_nodes[m_nodes.size() - 2],
1997 &m_nodes[m_nodes.size() - 1]};
2000 for (i = 0, ni = m_links.size(); i < ni; ++i)
2002 const int mtch = MatchEdge(m_links[i].m_n[0], m_links[i].m_n[1], pa, pb);
2006 Link* pft[] = {&m_links[i], &m_links[m_links.size() - 1]};
2007 pft[0]->m_n[1] = pn[mtch];
2008 pft[1]->m_n[0] = pn[1 - mtch];
2012 for (i = 0, ni = m_faces.size(); i < ni; ++i)
2014 for (int k = 2, l = 0; l < 3; k = l++)
2016 const int mtch = MatchEdge(m_faces[i].m_n[k], m_faces[i].m_n[l], pa, pb);
2020 Face* pft[] = {&m_faces[i], &m_faces[m_faces.size() - 1]};
2021 pft[0]->m_n[l] = pn[mtch];
2022 pft[1]->m_n[k] = pn[1 - mtch];
2023 appendLink(pn[0], pft[0]->m_n[(l + 1) % 3], pft[0]->m_material, true);
2024 appendLink(pn[1], pft[0]->m_n[(l + 1) % 3], pft[0]->m_material, true);
2030 m_ndbvt.remove(pn[0]->m_leaf);
2031 m_ndbvt.remove(pn[1]->m_leaf);
2039 bool btSoftBody::rayTest(const btVector3& rayFrom,
2040 const btVector3& rayTo,
2043 if (m_faces.size() && m_fdbvt.empty())
2044 initializeFaceTree();
2046 results.body = this;
2047 results.fraction = 1.f;
2048 results.feature = eFeature::None;
2051 return (rayTest(rayFrom, rayTo, results.fraction, results.feature, results.index, false) != 0);
2054 bool btSoftBody::rayFaceTest(const btVector3& rayFrom,
2055 const btVector3& rayTo,
2058 if (m_faces.size() == 0)
2062 if (m_fdbvt.empty())
2063 initializeFaceTree();
2066 results.body = this;
2067 results.fraction = 1.f;
2070 return (rayFaceTest(rayFrom, rayTo, results.fraction, results.index) != 0);
2074 void btSoftBody::setSolver(eSolverPresets::_ preset)
2076 m_cfg.m_vsequence.clear();
2077 m_cfg.m_psequence.clear();
2078 m_cfg.m_dsequence.clear();
2081 case eSolverPresets::Positions:
2082 m_cfg.m_psequence.push_back(ePSolver::Anchors);
2083 m_cfg.m_psequence.push_back(ePSolver::RContacts);
2084 m_cfg.m_psequence.push_back(ePSolver::SContacts);
2085 m_cfg.m_psequence.push_back(ePSolver::Linear);
2087 case eSolverPresets::Velocities:
2088 m_cfg.m_vsequence.push_back(eVSolver::Linear);
2090 m_cfg.m_psequence.push_back(ePSolver::Anchors);
2091 m_cfg.m_psequence.push_back(ePSolver::RContacts);
2092 m_cfg.m_psequence.push_back(ePSolver::SContacts);
2094 m_cfg.m_dsequence.push_back(ePSolver::Linear);
2099 void btSoftBody::predictMotion(btScalar dt)
2106 m_bUpdateRtCst = false;
2109 if (m_cfg.collisions & fCollision::VF_SS)
2111 initializeFaceTree();
2116 m_sst.sdt = dt * m_cfg.timescale;
2117 m_sst.isdt = 1 / m_sst.sdt;
2118 m_sst.velmrg = m_sst.sdt * 3;
2119 m_sst.radmrg = getCollisionShape()->getMargin();
2120 m_sst.updmrg = m_sst.radmrg * (btScalar)0.25;
2122 addVelocity(m_worldInfo->m_gravity * m_sst.sdt);
2125 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2127 Node& n = m_nodes[i];
2129 btVector3 deltaV = n.m_f * n.m_im * m_sst.sdt;
2131 btScalar maxDisplacement = m_worldInfo->m_maxDisplacement;
2132 btScalar clampDeltaV = maxDisplacement / m_sst.sdt;
2133 for (int c = 0; c < 3; c++)
2135 if (deltaV[c] > clampDeltaV)
2137 deltaV[c] = clampDeltaV;
2139 if (deltaV[c] < -clampDeltaV)
2141 deltaV[c] = -clampDeltaV;
2146 n.m_x += n.m_v * m_sst.sdt;
2147 n.m_f = btVector3(0, 0, 0);
2154 ATTRIBUTE_ALIGNED16(btDbvtVolume)
2156 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2158 Node& n = m_nodes[i];
2159 vol = btDbvtVolume::FromCR(n.m_x, m_sst.radmrg);
2160 m_ndbvt.update(n.m_leaf,
2162 n.m_v * m_sst.velmrg,
2166 if (!m_fdbvt.empty())
2168 for (int i = 0; i < m_faces.size(); ++i)
2170 Face& f = m_faces[i];
2171 const btVector3 v = (f.m_n[0]->m_v +
2175 vol = VolumeOf(f, m_sst.radmrg);
2176 m_fdbvt.update(f.m_leaf,
2185 if (m_pose.m_bframe && (m_cfg.kMT > 0))
2187 const btMatrix3x3 posetrs = m_pose.m_rot;
2188 for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
2190 Node& n = m_nodes[i];
2193 const btVector3 x = posetrs * m_pose.m_pos[i] + m_pose.m_com;
2194 n.m_x = Lerp(n.m_x, x, m_cfg.kMT);
2198 /* Clear contacts */
2199 m_rcontacts.resize(0);
2200 m_scontacts.resize(0);
2201 /* Optimize dbvt's */
2202 m_ndbvt.optimizeIncremental(1);
2203 m_fdbvt.optimizeIncremental(1);
2204 m_cdbvt.optimizeIncremental(1);
2208 void btSoftBody::solveConstraints()
2210 /* Apply clusters */
2211 applyClusters(false);
2216 for (i = 0, ni = m_links.size(); i < ni; ++i)
2218 Link& l = m_links[i];
2219 l.m_c3 = l.m_n[1]->m_q - l.m_n[0]->m_q;
2220 l.m_c2 = 1 / (l.m_c3.length2() * l.m_c0);
2222 /* Prepare anchors */
2223 for (i = 0, ni = m_anchors.size(); i < ni; ++i)
2225 Anchor& a = m_anchors[i];
2226 const btVector3 ra = a.m_body->getWorldTransform().getBasis() * a.m_local;
2227 a.m_c0 = ImpulseMatrix(m_sst.sdt,
2229 a.m_body->getInvMass(),
2230 a.m_body->getInvInertiaTensorWorld(),
2233 a.m_c2 = m_sst.sdt * a.m_node->m_im;
2234 a.m_body->activate();
2236 /* Solve velocities */
2237 if (m_cfg.viterations > 0)
2240 for (int isolve = 0; isolve < m_cfg.viterations; ++isolve)
2242 for (int iseq = 0; iseq < m_cfg.m_vsequence.size(); ++iseq)
2244 getSolver(m_cfg.m_vsequence[iseq])(this, 1);
2248 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2250 Node& n = m_nodes[i];
2251 n.m_x = n.m_q + n.m_v * m_sst.sdt;
2254 /* Solve positions */
2255 if (m_cfg.piterations > 0)
2257 for (int isolve = 0; isolve < m_cfg.piterations; ++isolve)
2259 const btScalar ti = isolve / (btScalar)m_cfg.piterations;
2260 for (int iseq = 0; iseq < m_cfg.m_psequence.size(); ++iseq)
2262 getSolver(m_cfg.m_psequence[iseq])(this, 1, ti);
2265 const btScalar vc = m_sst.isdt * (1 - m_cfg.kDP);
2266 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2268 Node& n = m_nodes[i];
2269 n.m_v = (n.m_x - n.m_q) * vc;
2270 n.m_f = btVector3(0, 0, 0);
2274 if (m_cfg.diterations > 0)
2276 const btScalar vcf = m_cfg.kVCF * m_sst.isdt;
2277 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2279 Node& n = m_nodes[i];
2282 for (int idrift = 0; idrift < m_cfg.diterations; ++idrift)
2284 for (int iseq = 0; iseq < m_cfg.m_dsequence.size(); ++iseq)
2286 getSolver(m_cfg.m_dsequence[iseq])(this, 1, 0);
2289 for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
2291 Node& n = m_nodes[i];
2292 n.m_v += (n.m_x - n.m_q) * vcf;
2295 /* Apply clusters */
2297 applyClusters(true);
2301 void btSoftBody::staticSolve(int iterations)
2303 for (int isolve = 0; isolve < iterations; ++isolve)
2305 for (int iseq = 0; iseq < m_cfg.m_psequence.size(); ++iseq)
2307 getSolver(m_cfg.m_psequence[iseq])(this, 1, 0);
2313 void btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/, int /*count*/, int /*iterations*/)
2319 void btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
2321 const int nb = bodies.size();
2325 for (i = 0; i < nb; ++i)
2327 iterations = btMax(iterations, bodies[i]->m_cfg.citerations);
2329 for (i = 0; i < nb; ++i)
2331 bodies[i]->prepareClusters(iterations);
2333 for (i = 0; i < iterations; ++i)
2335 const btScalar sor = 1;
2336 for (int j = 0; j < nb; ++j)
2338 bodies[j]->solveClusters(sor);
2341 for (i = 0; i < nb; ++i)
2343 bodies[i]->cleanupClusters();
2348 void btSoftBody::integrateMotion()
2355 btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom, const btVector3& rayTo, btScalar mxt)
2357 m_rayFrom = rayFrom;
2358 m_rayNormalizedDirection = (rayTo - rayFrom);
2366 void btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf)
2368 btSoftBody::Face& f = *(btSoftBody::Face*)leaf->data;
2369 const btScalar t = rayFromToTriangle(m_rayFrom, m_rayTo, m_rayNormalizedDirection,
2374 if ((t > 0) && (t < m_mint))
2383 btScalar btSoftBody::RayFromToCaster::rayFromToTriangle(const btVector3& rayFrom,
2384 const btVector3& rayTo,
2385 const btVector3& rayNormalizedDirection,
2391 static const btScalar ceps = -SIMD_EPSILON * 10;
2392 static const btScalar teps = SIMD_EPSILON * 10;
2394 const btVector3 n = btCross(b - a, c - a);
2395 const btScalar d = btDot(a, n);
2396 const btScalar den = btDot(rayNormalizedDirection, n);
2397 if (!btFuzzyZero(den))
2399 const btScalar num = btDot(rayFrom, n) - d;
2400 const btScalar t = -num / den;
2401 if ((t > teps) && (t < maxt))
2403 const btVector3 hit = rayFrom + rayNormalizedDirection * t;
2404 if ((btDot(n, btCross(a - hit, b - hit)) > ceps) &&
2405 (btDot(n, btCross(b - hit, c - hit)) > ceps) &&
2406 (btDot(n, btCross(c - hit, a - hit)) > ceps))
2416 void btSoftBody::pointersToIndices()
2418 #define PTR2IDX(_p_, _b_) reinterpret_cast<btSoftBody::Node*>((_p_) - (_b_))
2419 btSoftBody::Node* base = m_nodes.size() ? &m_nodes[0] : 0;
2422 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2424 if (m_nodes[i].m_leaf)
2426 m_nodes[i].m_leaf->data = *(void**)&i;
2429 for (i = 0, ni = m_links.size(); i < ni; ++i)
2431 m_links[i].m_n[0] = PTR2IDX(m_links[i].m_n[0], base);
2432 m_links[i].m_n[1] = PTR2IDX(m_links[i].m_n[1], base);
2434 for (i = 0, ni = m_faces.size(); i < ni; ++i)
2436 m_faces[i].m_n[0] = PTR2IDX(m_faces[i].m_n[0], base);
2437 m_faces[i].m_n[1] = PTR2IDX(m_faces[i].m_n[1], base);
2438 m_faces[i].m_n[2] = PTR2IDX(m_faces[i].m_n[2], base);
2439 if (m_faces[i].m_leaf)
2441 m_faces[i].m_leaf->data = *(void**)&i;
2444 for (i = 0, ni = m_anchors.size(); i < ni; ++i)
2446 m_anchors[i].m_node = PTR2IDX(m_anchors[i].m_node, base);
2448 for (i = 0, ni = m_notes.size(); i < ni; ++i)
2450 for (int j = 0; j < m_notes[i].m_rank; ++j)
2452 m_notes[i].m_nodes[j] = PTR2IDX(m_notes[i].m_nodes[j], base);
2459 void btSoftBody::indicesToPointers(const int* map)
2461 #define IDX2PTR(_p_, _b_) map ? (&(_b_)[map[(((char*)_p_) - (char*)0)]]) : (&(_b_)[(((char*)_p_) - (char*)0)])
2462 btSoftBody::Node* base = m_nodes.size() ? &m_nodes[0] : 0;
2465 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2467 if (m_nodes[i].m_leaf)
2469 m_nodes[i].m_leaf->data = &m_nodes[i];
2472 for (i = 0, ni = m_links.size(); i < ni; ++i)
2474 m_links[i].m_n[0] = IDX2PTR(m_links[i].m_n[0], base);
2475 m_links[i].m_n[1] = IDX2PTR(m_links[i].m_n[1], base);
2477 for (i = 0, ni = m_faces.size(); i < ni; ++i)
2479 m_faces[i].m_n[0] = IDX2PTR(m_faces[i].m_n[0], base);
2480 m_faces[i].m_n[1] = IDX2PTR(m_faces[i].m_n[1], base);
2481 m_faces[i].m_n[2] = IDX2PTR(m_faces[i].m_n[2], base);
2482 if (m_faces[i].m_leaf)
2484 m_faces[i].m_leaf->data = &m_faces[i];
2487 for (i = 0, ni = m_anchors.size(); i < ni; ++i)
2489 m_anchors[i].m_node = IDX2PTR(m_anchors[i].m_node, base);
2491 for (i = 0, ni = m_notes.size(); i < ni; ++i)
2493 for (int j = 0; j < m_notes[i].m_rank; ++j)
2495 m_notes[i].m_nodes[j] = IDX2PTR(m_notes[i].m_nodes[j], base);
2502 int btSoftBody::rayTest(const btVector3& rayFrom, const btVector3& rayTo,
2503 btScalar& mint, eFeature::_& feature, int& index, bool bcountonly) const
2506 btVector3 dir = rayTo - rayFrom;
2508 if (bcountonly || m_fdbvt.empty())
2511 for (int i = 0, ni = m_faces.size(); i < ni; ++i)
2513 const btSoftBody::Face& f = m_faces[i];
2515 const btScalar t = RayFromToCaster::rayFromToTriangle(rayFrom, rayTo, dir,
2525 feature = btSoftBody::eFeature::Face;
2534 RayFromToCaster collider(rayFrom, rayTo, mint);
2536 btDbvt::rayTest(m_fdbvt.m_root, rayFrom, rayTo, collider);
2537 if (collider.m_face)
2539 mint = collider.m_mint;
2540 feature = btSoftBody::eFeature::Face;
2541 index = (int)(collider.m_face - &m_faces[0]);
2546 for (int i = 0; i < m_tetras.size(); i++)
2548 const btSoftBody::Tetra& tet = m_tetras[i];
2549 int tetfaces[4][3] = {{0, 1, 2}, {0, 1, 3}, {1, 2, 3}, {0, 2, 3}};
2550 for (int f = 0; f < 4; f++)
2552 int index0 = tetfaces[f][0];
2553 int index1 = tetfaces[f][1];
2554 int index2 = tetfaces[f][2];
2555 btVector3 v0 = tet.m_n[index0]->m_x;
2556 btVector3 v1 = tet.m_n[index1]->m_x;
2557 btVector3 v2 = tet.m_n[index2]->m_x;
2559 const btScalar t = RayFromToCaster::rayFromToTriangle(rayFrom, rayTo, dir,
2567 feature = btSoftBody::eFeature::Tetra;
2577 int btSoftBody::rayFaceTest(const btVector3& rayFrom, const btVector3& rayTo,
2578 btScalar& mint, int& index) const
2582 RayFromToCaster collider(rayFrom, rayTo, mint);
2584 btDbvt::rayTest(m_fdbvt.m_root, rayFrom, rayTo, collider);
2585 if (collider.m_face)
2587 mint = collider.m_mint;
2588 index = (int)(collider.m_face - &m_faces[0]);
2596 static inline btDbvntNode* copyToDbvnt(const btDbvtNode* n)
2600 btDbvntNode* root = new btDbvntNode(n);
2601 if (n->isinternal())
2603 btDbvntNode* c0 = copyToDbvnt(n->childs[0]);
2604 root->childs[0] = c0;
2605 btDbvntNode* c1 = copyToDbvnt(n->childs[1]);
2606 root->childs[1] = c1;
2611 static inline void calculateNormalCone(btDbvntNode* root)
2617 const btSoftBody::Face* face = (btSoftBody::Face*)root->data;
2618 root->normal = face->m_normal;
2623 btVector3 n0(0, 0, 0), n1(0, 0, 0);
2624 btScalar a0 = 0, a1 = 0;
2625 if (root->childs[0])
2627 calculateNormalCone(root->childs[0]);
2628 n0 = root->childs[0]->normal;
2629 a0 = root->childs[0]->angle;
2631 if (root->childs[1])
2633 calculateNormalCone(root->childs[1]);
2634 n1 = root->childs[1]->normal;
2635 a1 = root->childs[1]->angle;
2637 root->normal = (n0 + n1).safeNormalize();
2638 root->angle = btMax(a0, a1) + btAngle(n0, n1) * 0.5;
2642 void btSoftBody::initializeFaceTree()
2644 BT_PROFILE("btSoftBody::initializeFaceTree");
2646 // create leaf nodes;
2647 btAlignedObjectArray<btDbvtNode*> leafNodes;
2648 leafNodes.resize(m_faces.size());
2649 for (int i = 0; i < m_faces.size(); ++i)
2651 Face& f = m_faces[i];
2652 ATTRIBUTE_ALIGNED16(btDbvtVolume)
2653 vol = VolumeOf(f, 0);
2654 btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
2655 node->parent = NULL;
2657 node->childs[1] = 0;
2659 leafNodes[i] = node;
2662 btAlignedObjectArray<btAlignedObjectArray<int> > adj;
2663 adj.resize(m_faces.size());
2664 // construct the adjacency list for triangles
2665 for (int i = 0; i < adj.size(); ++i)
2667 for (int j = i + 1; j < adj.size(); ++j)
2670 for (int k = 0; k < 3; ++k)
2672 for (int l = 0; l < 3; ++l)
2674 if (m_faces[i].m_n[k] == m_faces[j].m_n[l])
2682 adj[i].push_back(j);
2683 adj[j].push_back(i);
2688 m_fdbvt.m_root = buildTreeBottomUp(leafNodes, adj);
2691 m_fdbvnt = copyToDbvnt(m_fdbvt.m_root);
2692 updateFaceTree(false, false);
2697 void btSoftBody::rebuildNodeTree()
2700 btAlignedObjectArray<btDbvtNode*> leafNodes;
2701 leafNodes.resize(m_nodes.size());
2702 for (int i = 0; i < m_nodes.size(); ++i)
2704 Node& n = m_nodes[i];
2705 ATTRIBUTE_ALIGNED16(btDbvtVolume)
2706 vol = btDbvtVolume::FromCR(n.m_x, 0);
2707 btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
2708 node->parent = NULL;
2710 node->childs[1] = 0;
2712 leafNodes[i] = node;
2715 btAlignedObjectArray<btAlignedObjectArray<int> > adj;
2716 adj.resize(m_nodes.size());
2717 btAlignedObjectArray<int> old_id;
2718 old_id.resize(m_nodes.size());
2719 for (int i = 0; i < m_nodes.size(); ++i)
2720 old_id[i] = m_nodes[i].index;
2721 for (int i = 0; i < m_nodes.size(); ++i)
2722 m_nodes[i].index = i;
2723 for (int i = 0; i < m_links.size(); ++i)
2725 Link& l = m_links[i];
2726 adj[l.m_n[0]->index].push_back(l.m_n[1]->index);
2727 adj[l.m_n[1]->index].push_back(l.m_n[0]->index);
2729 m_ndbvt.m_root = buildTreeBottomUp(leafNodes, adj);
2730 for (int i = 0; i < m_nodes.size(); ++i)
2731 m_nodes[i].index = old_id[i];
2735 btVector3 btSoftBody::evaluateCom() const
2737 btVector3 com(0, 0, 0);
2738 if (m_pose.m_bframe)
2740 for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
2742 com += m_nodes[i].m_x * m_pose.m_wgh[i];
2748 bool btSoftBody::checkContact(const btCollisionObjectWrapper* colObjWrap,
2751 btSoftBody::sCti& cti) const
2754 const btCollisionShape* shp = colObjWrap->getCollisionShape();
2755 // const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject());
2756 //const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform();
2757 const btTransform& wtr = colObjWrap->getWorldTransform();
2758 //todo: check which transform is needed here
2761 m_worldInfo->m_sparsesdf.Evaluate(
2768 cti.m_colObj = colObjWrap->getCollisionObject();
2769 cti.m_normal = wtr.getBasis() * nrm;
2770 cti.m_offset = -btDot(cti.m_normal, x - cti.m_normal * dst);
2777 bool btSoftBody::checkDeformableContact(const btCollisionObjectWrapper* colObjWrap,
2780 btSoftBody::sCti& cti, bool predict) const
2783 const btCollisionShape* shp = colObjWrap->getCollisionShape();
2784 const btCollisionObject* tmpCollisionObj = colObjWrap->getCollisionObject();
2785 // use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
2786 // but resolve contact at x_n
2787 btTransform wtr = (predict) ? (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform() * (*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
2788 : colObjWrap->getWorldTransform();
2790 m_worldInfo->m_sparsesdf.Evaluate(
2798 cti.m_colObj = colObjWrap->getCollisionObject();
2799 cti.m_normal = wtr.getBasis() * nrm;
2808 // Compute barycentric coordinates (u, v, w) for
2809 // point p with respect to triangle (a, b, c)
2810 static void getBarycentric(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, btVector3& bary)
2812 btVector3 v0 = b - a, v1 = c - a, v2 = p - a;
2813 btScalar d00 = v0.dot(v0);
2814 btScalar d01 = v0.dot(v1);
2815 btScalar d11 = v1.dot(v1);
2816 btScalar d20 = v2.dot(v0);
2817 btScalar d21 = v2.dot(v1);
2818 btScalar denom = d00 * d11 - d01 * d01;
2819 // In the case of a degenerate triangle, pick a vertex.
2820 if (btFabs(denom) < SIMD_EPSILON)
2822 bary.setY(btScalar(0.0));
2823 bary.setZ(btScalar(0.0));
2827 bary.setY((d11 * d20 - d01 * d21) / denom);
2828 bary.setZ((d00 * d21 - d01 * d20) / denom);
2830 bary.setX(btScalar(1) - bary.getY() - bary.getZ());
2834 bool btSoftBody::checkDeformableFaceContact(const btCollisionObjectWrapper* colObjWrap,
2836 btVector3& contact_point,
2839 btSoftBody::sCti& cti, bool predict) const
2842 const btCollisionShape* shp = colObjWrap->getCollisionShape();
2843 const btCollisionObject* tmpCollisionObj = colObjWrap->getCollisionObject();
2844 // use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
2845 // but resolve contact at x_n
2846 btTransform wtr = (predict) ? (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform() * (*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
2847 : colObjWrap->getWorldTransform();
2849 btGjkEpaSolver2::sResults results;
2851 // #define USE_QUADRATURE 1
2853 // use collision quadrature point
2854 #ifdef USE_QUADRATURE
2856 dst = SIMD_INFINITY;
2857 btVector3 local_nrm;
2858 for (int q = 0; q < m_quads.size(); ++q)
2862 p = BaryEval(f.m_n[0]->m_q, f.m_n[1]->m_q, f.m_n[2]->m_q, m_quads[q]);
2864 p = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, m_quads[q]);
2865 btScalar local_dst = m_worldInfo->m_sparsesdf.Evaluate(
2870 if (local_dst < dst)
2872 if (local_dst < 0 && predict)
2881 cti.m_colObj = colObjWrap->getCollisionObject();
2882 cti.m_normal = wtr.getBasis() * nrm;
2890 // collision detection using x*
2891 btTransform triangle_transform;
2892 triangle_transform.setIdentity();
2893 triangle_transform.setOrigin(f.m_n[0]->m_q);
2894 btTriangleShape triangle(btVector3(0, 0, 0), f.m_n[1]->m_q - f.m_n[0]->m_q, f.m_n[2]->m_q - f.m_n[0]->m_q);
2895 btVector3 guess(0, 0, 0);
2896 const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
2897 btGjkEpaSolver2::SignedDistance(&triangle, triangle_transform, csh, wtr, guess, results);
2898 dst = results.distance - 2.0 * csh->getMargin() - margin; // margin padding so that the distance = the actual distance between face and rigid - margin of rigid - margin of deformable
2902 // Use consistent barycenter to recalculate distance.
2903 if (this->m_cacheBarycenter)
2905 if (f.m_pcontact[3] != 0)
2907 for (int i = 0; i < 3; ++i)
2908 bary[i] = f.m_pcontact[i];
2909 contact_point = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
2910 const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
2911 btGjkEpaSolver2::SignedDistance(contact_point, margin, csh, wtr, results);
2912 cti.m_colObj = colObjWrap->getCollisionObject();
2913 dst = results.distance;
2914 cti.m_normal = results.normal;
2918 wtr = colObjWrap->getWorldTransform();
2919 btTriangleShape triangle2(btVector3(0, 0, 0), f.m_n[1]->m_x - f.m_n[0]->m_x, f.m_n[2]->m_x - f.m_n[0]->m_x);
2920 triangle_transform.setOrigin(f.m_n[0]->m_x);
2921 btGjkEpaSolver2::SignedDistance(&triangle2, triangle_transform, csh, wtr, guess, results);
2923 dst = results.distance - csh->getMargin() - margin;
2928 // Use triangle-convex CD.
2929 wtr = colObjWrap->getWorldTransform();
2930 btTriangleShape triangle2(btVector3(0, 0, 0), f.m_n[1]->m_x - f.m_n[0]->m_x, f.m_n[2]->m_x - f.m_n[0]->m_x);
2931 triangle_transform.setOrigin(f.m_n[0]->m_x);
2932 btGjkEpaSolver2::SignedDistance(&triangle2, triangle_transform, csh, wtr, guess, results);
2933 contact_point = results.witnesses[0];
2934 getBarycentric(contact_point, f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
2936 for (int i = 0; i < 3; ++i)
2937 f.m_pcontact[i] = bary[i];
2939 dst = results.distance - csh->getMargin() - margin;
2940 cti.m_colObj = colObjWrap->getCollisionObject();
2941 cti.m_normal = results.normal;
2946 void btSoftBody::updateNormals()
2948 const btVector3 zv(0, 0, 0);
2951 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2953 m_nodes[i].m_n = zv;
2955 for (i = 0, ni = m_faces.size(); i < ni; ++i)
2957 btSoftBody::Face& f = m_faces[i];
2958 const btVector3 n = btCross(f.m_n[1]->m_x - f.m_n[0]->m_x,
2959 f.m_n[2]->m_x - f.m_n[0]->m_x);
2961 f.m_normal.safeNormalize();
2966 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
2968 btScalar len = m_nodes[i].m_n.length();
2969 if (len > SIMD_EPSILON)
2970 m_nodes[i].m_n /= len;
2975 void btSoftBody::updateBounds()
2977 /*if( m_acceleratedSoftBody )
2979 // If we have an accelerated softbody we need to obtain the bounds correctly
2980 // For now (slightly hackily) just have a very large AABB
2981 // TODO: Write get bounds kernel
2982 // If that is updating in place, atomic collisions might be low (when the cloth isn't perfectly aligned to an axis) and we could
2983 // probably do a test and exchange reasonably efficiently.
2985 m_bounds[0] = btVector3(-1000, -1000, -1000);
2986 m_bounds[1] = btVector3(1000, 1000, 1000);
2989 // if (m_ndbvt.m_root)
2991 // const btVector3& mins = m_ndbvt.m_root->volume.Mins();
2992 // const btVector3& maxs = m_ndbvt.m_root->volume.Maxs();
2993 // const btScalar csm = getCollisionShape()->getMargin();
2994 // const btVector3 mrg = btVector3(csm,
2997 // 1; // ??? to investigate...
2998 // m_bounds[0] = mins - mrg;
2999 // m_bounds[1] = maxs + mrg;
3000 // if (0 != getBroadphaseHandle())
3002 // m_worldInfo->m_broadphase->setAabb(getBroadphaseHandle(),
3005 // m_worldInfo->m_dispatcher);
3011 // m_bounds[1] = btVector3(0, 0, 0);
3015 btVector3 mins = m_nodes[0].m_x;
3016 btVector3 maxs = m_nodes[0].m_x;
3017 for (int i = 1; i < m_nodes.size(); ++i)
3019 for (int d = 0; d < 3; ++d)
3021 if (m_nodes[i].m_x[d] > maxs[d])
3022 maxs[d] = m_nodes[i].m_x[d];
3023 if (m_nodes[i].m_x[d] < mins[d])
3024 mins[d] = m_nodes[i].m_x[d];
3027 const btScalar csm = getCollisionShape()->getMargin();
3028 const btVector3 mrg = btVector3(csm,
3031 m_bounds[0] = mins - mrg;
3032 m_bounds[1] = maxs + mrg;
3033 if (0 != getBroadphaseHandle())
3035 m_worldInfo->m_broadphase->setAabb(getBroadphaseHandle(),
3038 m_worldInfo->m_dispatcher);
3044 m_bounds[1] = btVector3(0, 0, 0);
3049 void btSoftBody::updatePose()
3051 if (m_pose.m_bframe)
3053 btSoftBody::Pose& pose = m_pose;
3054 const btVector3 com = evaluateCom();
3059 const btScalar eps = SIMD_EPSILON;
3060 Apq[0] = Apq[1] = Apq[2] = btVector3(0, 0, 0);
3062 Apq[1].setY(eps * 2);
3063 Apq[2].setZ(eps * 3);
3064 for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
3066 const btVector3 a = pose.m_wgh[i] * (m_nodes[i].m_x - com);
3067 const btVector3& b = pose.m_pos[i];
3068 Apq[0] += a.x() * b;
3069 Apq[1] += a.y() * b;
3070 Apq[2] += a.z() * b;
3073 PolarDecompose(Apq, r, s);
3075 pose.m_scl = pose.m_aqq * r.transpose() * Apq;
3076 if (m_cfg.maxvolume > 1)
3078 const btScalar idet = Clamp<btScalar>(1 / pose.m_scl.determinant(),
3079 1, m_cfg.maxvolume);
3080 pose.m_scl = Mul(pose.m_scl, idet);
3086 void btSoftBody::updateArea(bool averageArea)
3091 for (i = 0, ni = m_faces.size(); i < ni; ++i)
3093 Face& f = m_faces[i];
3094 f.m_ra = AreaOf(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x);
3101 btAlignedObjectArray<int> counts;
3102 counts.resize(m_nodes.size(), 0);
3103 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
3105 m_nodes[i].m_area = 0;
3107 for (i = 0, ni = m_faces.size(); i < ni; ++i)
3109 btSoftBody::Face& f = m_faces[i];
3110 for (int j = 0; j < 3; ++j)
3112 const int index = (int)(f.m_n[j] - &m_nodes[0]);
3114 f.m_n[j]->m_area += btFabs(f.m_ra);
3117 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
3120 m_nodes[i].m_area /= (btScalar)counts[i];
3122 m_nodes[i].m_area = 0;
3127 // initialize node area as zero
3128 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
3130 m_nodes[i].m_area = 0;
3133 for (i = 0, ni = m_faces.size(); i < ni; ++i)
3135 btSoftBody::Face& f = m_faces[i];
3137 for (int j = 0; j < 3; ++j)
3139 f.m_n[j]->m_area += f.m_ra;
3143 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
3145 m_nodes[i].m_area *= 0.3333333f;
3150 void btSoftBody::updateLinkConstants()
3155 for (i = 0, ni = m_links.size(); i < ni; ++i)
3157 Link& l = m_links[i];
3158 Material& m = *l.m_material;
3159 l.m_c0 = (l.m_n[0]->m_im + l.m_n[1]->m_im) / m.m_kLST;
3163 void btSoftBody::updateConstants()
3165 resetLinkRestLengths();
3166 updateLinkConstants();
3171 void btSoftBody::initializeClusters()
3175 for (i = 0; i < m_clusters.size(); ++i)
3177 Cluster& c = *m_clusters[i];
3179 c.m_masses.resize(c.m_nodes.size());
3180 for (int j = 0; j < c.m_nodes.size(); ++j)
3182 if (c.m_nodes[j]->m_im == 0)
3184 c.m_containsAnchor = true;
3185 c.m_masses[j] = BT_LARGE_FLOAT;
3189 c.m_masses[j] = btScalar(1.) / c.m_nodes[j]->m_im;
3191 c.m_imass += c.m_masses[j];
3193 c.m_imass = btScalar(1.) / c.m_imass;
3194 c.m_com = btSoftBody::clusterCom(&c);
3195 c.m_lv = btVector3(0, 0, 0);
3196 c.m_av = btVector3(0, 0, 0);
3199 btMatrix3x3& ii = c.m_locii;
3200 ii[0] = ii[1] = ii[2] = btVector3(0, 0, 0);
3204 for (i = 0, ni = c.m_nodes.size(); i < ni; ++i)
3206 const btVector3 k = c.m_nodes[i]->m_x - c.m_com;
3207 const btVector3 q = k * k;
3208 const btScalar m = c.m_masses[i];
3209 ii[0][0] += m * (q[1] + q[2]);
3210 ii[1][1] += m * (q[0] + q[2]);
3211 ii[2][2] += m * (q[0] + q[1]);
3212 ii[0][1] -= m * k[0] * k[1];
3213 ii[0][2] -= m * k[0] * k[2];
3214 ii[1][2] -= m * k[1] * k[2];
3217 ii[1][0] = ii[0][1];
3218 ii[2][0] = ii[0][2];
3219 ii[2][1] = ii[1][2];
3224 c.m_framexform.setIdentity();
3225 c.m_framexform.setOrigin(c.m_com);
3226 c.m_framerefs.resize(c.m_nodes.size());
3229 for (i = 0; i < c.m_framerefs.size(); ++i)
3231 c.m_framerefs[i] = c.m_nodes[i]->m_x - c.m_com;
3238 void btSoftBody::updateClusters()
3240 BT_PROFILE("UpdateClusters");
3243 for (i = 0; i < m_clusters.size(); ++i)
3245 btSoftBody::Cluster& c = *m_clusters[i];
3246 const int n = c.m_nodes.size();
3247 //const btScalar invn=1/(btScalar)n;
3251 const btScalar eps = btScalar(0.0001);
3252 btMatrix3x3 m, r, s;
3253 m[0] = m[1] = m[2] = btVector3(0, 0, 0);
3257 c.m_com = clusterCom(&c);
3258 for (int i = 0; i < c.m_nodes.size(); ++i)
3260 const btVector3 a = c.m_nodes[i]->m_x - c.m_com;
3261 const btVector3& b = c.m_framerefs[i];
3266 PolarDecompose(m, r, s);
3267 c.m_framexform.setOrigin(c.m_com);
3268 c.m_framexform.setBasis(r);
3270 #if 1 /* Constant */
3271 c.m_invwi = c.m_framexform.getBasis() * c.m_locii * c.m_framexform.getBasis().transpose();
3274 const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass);
3275 const btVector3 inertia(rk,rk,rk);
3276 const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
3277 btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0,
3278 btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
3280 c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
3282 c.m_invwi[0] = c.m_invwi[1] = c.m_invwi[2] = btVector3(0, 0, 0);
3283 for (int i = 0; i < n; ++i)
3285 const btVector3 k = c.m_nodes[i]->m_x - c.m_com;
3286 const btVector3 q = k * k;
3287 const btScalar m = 1 / c.m_nodes[i]->m_im;
3288 c.m_invwi[0][0] += m * (q[1] + q[2]);
3289 c.m_invwi[1][1] += m * (q[0] + q[2]);
3290 c.m_invwi[2][2] += m * (q[0] + q[1]);
3291 c.m_invwi[0][1] -= m * k[0] * k[1];
3292 c.m_invwi[0][2] -= m * k[0] * k[2];
3293 c.m_invwi[1][2] -= m * k[1] * k[2];
3295 c.m_invwi[1][0] = c.m_invwi[0][1];
3296 c.m_invwi[2][0] = c.m_invwi[0][2];
3297 c.m_invwi[2][1] = c.m_invwi[1][2];
3298 c.m_invwi = c.m_invwi.inverse();
3302 c.m_lv = btVector3(0, 0, 0);
3303 c.m_av = btVector3(0, 0, 0);
3307 for (i = 0; i < n; ++i)
3309 const btVector3 v = c.m_nodes[i]->m_v * c.m_masses[i];
3311 c.m_av += btCross(c.m_nodes[i]->m_x - c.m_com, v);
3314 c.m_lv = c.m_imass * c.m_lv * (1 - c.m_ldamping);
3315 c.m_av = c.m_invwi * c.m_av * (1 - c.m_adamping);
3317 c.m_vimpulses[1] = btVector3(0, 0, 0);
3319 c.m_dimpulses[1] = btVector3(0, 0, 0);
3323 if (c.m_matching > 0)
3325 for (int j = 0; j < c.m_nodes.size(); ++j)
3327 Node& n = *c.m_nodes[j];
3328 const btVector3 x = c.m_framexform * c.m_framerefs[j];
3329 n.m_x = Lerp(n.m_x, x, c.m_matching);
3335 btVector3 mi = c.m_nodes[0]->m_x;
3337 for (int j = 1; j < n; ++j)
3339 mi.setMin(c.m_nodes[j]->m_x);
3340 mx.setMax(c.m_nodes[j]->m_x);
3342 ATTRIBUTE_ALIGNED16(btDbvtVolume)
3343 bounds = btDbvtVolume::FromMM(mi, mx);
3345 m_cdbvt.update(c.m_leaf, bounds, c.m_lv * m_sst.sdt * 3, m_sst.radmrg);
3347 c.m_leaf = m_cdbvt.insert(bounds, &c);
3354 void btSoftBody::cleanupClusters()
3356 for (int i = 0; i < m_joints.size(); ++i)
3358 m_joints[i]->Terminate(m_sst.sdt);
3359 if (m_joints[i]->m_delete)
3361 btAlignedFree(m_joints[i]);
3362 m_joints.remove(m_joints[i--]);
3368 void btSoftBody::prepareClusters(int iterations)
3370 for (int i = 0; i < m_joints.size(); ++i)
3372 m_joints[i]->Prepare(m_sst.sdt, iterations);
3377 void btSoftBody::solveClusters(btScalar sor)
3379 for (int i = 0, ni = m_joints.size(); i < ni; ++i)
3381 m_joints[i]->Solve(m_sst.sdt, sor);
3386 void btSoftBody::applyClusters(bool drift)
3388 BT_PROFILE("ApplyClusters");
3389 // const btScalar f0=m_sst.sdt;
3390 //const btScalar f1=f0/2;
3391 btAlignedObjectArray<btVector3> deltas;
3392 btAlignedObjectArray<btScalar> weights;
3393 deltas.resize(m_nodes.size(), btVector3(0, 0, 0));
3394 weights.resize(m_nodes.size(), 0);
3399 for (i = 0; i < m_clusters.size(); ++i)
3401 Cluster& c = *m_clusters[i];
3404 c.m_dimpulses[0] /= (btScalar)c.m_ndimpulses;
3405 c.m_dimpulses[1] /= (btScalar)c.m_ndimpulses;
3410 for (i = 0; i < m_clusters.size(); ++i)
3412 Cluster& c = *m_clusters[i];
3413 if (0 < (drift ? c.m_ndimpulses : c.m_nvimpulses))
3415 const btVector3 v = (drift ? c.m_dimpulses[0] : c.m_vimpulses[0]) * m_sst.sdt;
3416 const btVector3 w = (drift ? c.m_dimpulses[1] : c.m_vimpulses[1]) * m_sst.sdt;
3417 for (int j = 0; j < c.m_nodes.size(); ++j)
3419 const int idx = int(c.m_nodes[j] - &m_nodes[0]);
3420 const btVector3& x = c.m_nodes[j]->m_x;
3421 const btScalar q = c.m_masses[j];
3422 deltas[idx] += (v + btCross(w, x - c.m_com)) * q;
3427 for (i = 0; i < deltas.size(); ++i)
3431 m_nodes[i].m_x += deltas[i] / weights[i];
3437 void btSoftBody::dampClusters()
3441 for (i = 0; i < m_clusters.size(); ++i)
3443 Cluster& c = *m_clusters[i];
3444 if (c.m_ndamping > 0)
3446 for (int j = 0; j < c.m_nodes.size(); ++j)
3448 Node& n = *c.m_nodes[j];
3451 const btVector3 vx = c.m_lv + btCross(c.m_av, c.m_nodes[j]->m_q - c.m_com);
3452 if (vx.length2() <= n.m_v.length2())
3454 n.m_v += c.m_ndamping * (vx - n.m_v);
3462 void btSoftBody::setSpringStiffness(btScalar k)
3464 for (int i = 0; i < m_links.size(); ++i)
3466 m_links[i].Feature::m_material->m_kLST = k;
3468 m_repulsionStiffness = k;
3471 void btSoftBody::setGravityFactor(btScalar gravFactor)
3473 m_gravityFactor = gravFactor;
3476 void btSoftBody::setCacheBarycenter(bool cacheBarycenter)
3478 m_cacheBarycenter = cacheBarycenter;
3481 void btSoftBody::initializeDmInverse()
3483 btScalar unit_simplex_measure = 1. / 6.;
3485 for (int i = 0; i < m_tetras.size(); ++i)
3487 Tetra& t = m_tetras[i];
3488 btVector3 c1 = t.m_n[1]->m_x - t.m_n[0]->m_x;
3489 btVector3 c2 = t.m_n[2]->m_x - t.m_n[0]->m_x;
3490 btVector3 c3 = t.m_n[3]->m_x - t.m_n[0]->m_x;
3491 btMatrix3x3 Dm(c1.getX(), c2.getX(), c3.getX(),
3492 c1.getY(), c2.getY(), c3.getY(),
3493 c1.getZ(), c2.getZ(), c3.getZ());
3494 t.m_element_measure = Dm.determinant() * unit_simplex_measure;
3495 t.m_Dm_inverse = Dm.inverse();
3497 // calculate the first three columns of P^{-1}
3498 btVector3 a = t.m_n[0]->m_x;
3499 btVector3 b = t.m_n[1]->m_x;
3500 btVector3 c = t.m_n[2]->m_x;
3501 btVector3 d = t.m_n[3]->m_x;
3503 btScalar det = 1 / (a[0] * b[1] * c[2] - a[0] * b[1] * d[2] - a[0] * b[2] * c[1] + a[0] * b[2] * d[1] + a[0] * c[1] * d[2] - a[0] * c[2] * d[1] + a[1] * (-b[0] * c[2] + b[0] * d[2] + b[2] * c[0] - b[2] * d[0] - c[0] * d[2] + c[2] * d[0]) + a[2] * (b[0] * c[1] - b[0] * d[1] + b[1] * (d[0] - c[0]) + c[0] * d[1] - c[1] * d[0]) - b[0] * c[1] * d[2] + b[0] * c[2] * d[1] + b[1] * c[0] * d[2] - b[1] * c[2] * d[0] - b[2] * c[0] * d[1] + b[2] * c[1] * d[0]);
3505 btScalar P11 = -b[2] * c[1] + d[2] * c[1] + b[1] * c[2] + b[2] * d[1] - c[2] * d[1] - b[1] * d[2];
3506 btScalar P12 = b[2] * c[0] - d[2] * c[0] - b[0] * c[2] - b[2] * d[0] + c[2] * d[0] + b[0] * d[2];
3507 btScalar P13 = -b[1] * c[0] + d[1] * c[0] + b[0] * c[1] + b[1] * d[0] - c[1] * d[0] - b[0] * d[1];
3508 btScalar P21 = a[2] * c[1] - d[2] * c[1] - a[1] * c[2] - a[2] * d[1] + c[2] * d[1] + a[1] * d[2];
3509 btScalar P22 = -a[2] * c[0] + d[2] * c[0] + a[0] * c[2] + a[2] * d[0] - c[2] * d[0] - a[0] * d[2];
3510 btScalar P23 = a[1] * c[0] - d[1] * c[0] - a[0] * c[1] - a[1] * d[0] + c[1] * d[0] + a[0] * d[1];
3511 btScalar P31 = -a[2] * b[1] + d[2] * b[1] + a[1] * b[2] + a[2] * d[1] - b[2] * d[1] - a[1] * d[2];
3512 btScalar P32 = a[2] * b[0] - d[2] * b[0] - a[0] * b[2] - a[2] * d[0] + b[2] * d[0] + a[0] * d[2];
3513 btScalar P33 = -a[1] * b[0] + d[1] * b[0] + a[0] * b[1] + a[1] * d[0] - b[1] * d[0] - a[0] * d[1];
3514 btScalar P41 = a[2] * b[1] - c[2] * b[1] - a[1] * b[2] - a[2] * c[1] + b[2] * c[1] + a[1] * c[2];
3515 btScalar P42 = -a[2] * b[0] + c[2] * b[0] + a[0] * b[2] + a[2] * c[0] - b[2] * c[0] - a[0] * c[2];
3516 btScalar P43 = a[1] * b[0] - c[1] * b[0] - a[0] * b[1] - a[1] * c[0] + b[1] * c[0] + a[0] * c[1];
3518 btVector4 p1(P11 * det, P21 * det, P31 * det, P41 * det);
3519 btVector4 p2(P12 * det, P22 * det, P32 * det, P42 * det);
3520 btVector4 p3(P13 * det, P23 * det, P33 * det, P43 * det);
3528 static btScalar Dot4(const btVector4& a, const btVector4& b)
3530 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
3533 void btSoftBody::updateDeformation()
3536 for (int i = 0; i < m_tetras.size(); ++i)
3538 btSoftBody::Tetra& t = m_tetras[i];
3539 btVector3 c1 = t.m_n[1]->m_q - t.m_n[0]->m_q;
3540 btVector3 c2 = t.m_n[2]->m_q - t.m_n[0]->m_q;
3541 btVector3 c3 = t.m_n[3]->m_q - t.m_n[0]->m_q;
3542 btMatrix3x3 Ds(c1.getX(), c2.getX(), c3.getX(),
3543 c1.getY(), c2.getY(), c3.getY(),
3544 c1.getZ(), c2.getZ(), c3.getZ());
3545 t.m_F = Ds * t.m_Dm_inverse;
3547 btSoftBody::TetraScratch& s = m_tetraScratches[i];
3549 s.m_J = t.m_F.determinant();
3550 btMatrix3x3 C = t.m_F.transpose() * t.m_F;
3551 s.m_trace = C[0].getX() + C[1].getY() + C[2].getZ();
3552 s.m_cofF = t.m_F.adjoint().transpose();
3554 btVector3 a = t.m_n[0]->m_q;
3555 btVector3 b = t.m_n[1]->m_q;
3556 btVector3 c = t.m_n[2]->m_q;
3557 btVector3 d = t.m_n[3]->m_q;
3558 btVector4 q1(a[0], b[0], c[0], d[0]);
3559 btVector4 q2(a[1], b[1], c[1], d[1]);
3560 btVector4 q3(a[2], b[2], c[2], d[2]);
3561 btMatrix3x3 B(Dot4(q1, t.m_P_inv[0]), Dot4(q1, t.m_P_inv[1]), Dot4(q1, t.m_P_inv[2]),
3562 Dot4(q2, t.m_P_inv[0]), Dot4(q2, t.m_P_inv[1]), Dot4(q2, t.m_P_inv[2]),
3563 Dot4(q3, t.m_P_inv[0]), Dot4(q3, t.m_P_inv[1]), Dot4(q3, t.m_P_inv[2]));
3564 q.setRotation(btVector3(0, 0, 1), 0);
3565 B.extractRotation(q, 0.01); // precision of the rotation is not very important for visual correctness.
3571 void btSoftBody::advanceDeformation()
3573 updateDeformation();
3574 for (int i = 0; i < m_tetras.size(); ++i)
3576 m_tetraScratchesTn[i] = m_tetraScratches[i];
3580 void btSoftBody::Joint::Prepare(btScalar dt, int)
3582 m_bodies[0].activate();
3583 m_bodies[1].activate();
3587 void btSoftBody::LJoint::Prepare(btScalar dt, int iterations)
3589 static const btScalar maxdrift = 4;
3590 Joint::Prepare(dt, iterations);
3591 m_rpos[0] = m_bodies[0].xform() * m_refs[0];
3592 m_rpos[1] = m_bodies[1].xform() * m_refs[1];
3593 m_drift = Clamp(m_rpos[0] - m_rpos[1], maxdrift) * m_erp / dt;
3594 m_rpos[0] -= m_bodies[0].xform().getOrigin();
3595 m_rpos[1] -= m_bodies[1].xform().getOrigin();
3596 m_massmatrix = ImpulseMatrix(m_bodies[0].invMass(), m_bodies[0].invWorldInertia(), m_rpos[0],
3597 m_bodies[1].invMass(), m_bodies[1].invWorldInertia(), m_rpos[1]);
3600 m_sdrift = m_massmatrix * (m_drift * m_split);
3601 m_drift *= 1 - m_split;
3603 m_drift /= (btScalar)iterations;
3607 void btSoftBody::LJoint::Solve(btScalar dt, btScalar sor)
3609 const btVector3 va = m_bodies[0].velocity(m_rpos[0]);
3610 const btVector3 vb = m_bodies[1].velocity(m_rpos[1]);
3611 const btVector3 vr = va - vb;
3612 btSoftBody::Impulse impulse;
3613 impulse.m_asVelocity = 1;
3614 impulse.m_velocity = m_massmatrix * (m_drift + vr * m_cfm) * sor;
3615 m_bodies[0].applyImpulse(-impulse, m_rpos[0]);
3616 m_bodies[1].applyImpulse(impulse, m_rpos[1]);
3620 void btSoftBody::LJoint::Terminate(btScalar dt)
3624 m_bodies[0].applyDImpulse(-m_sdrift, m_rpos[0]);
3625 m_bodies[1].applyDImpulse(m_sdrift, m_rpos[1]);
3630 void btSoftBody::AJoint::Prepare(btScalar dt, int iterations)
3632 static const btScalar maxdrift = SIMD_PI / 16;
3633 m_icontrol->Prepare(this);
3634 Joint::Prepare(dt, iterations);
3635 m_axis[0] = m_bodies[0].xform().getBasis() * m_refs[0];
3636 m_axis[1] = m_bodies[1].xform().getBasis() * m_refs[1];
3637 m_drift = NormalizeAny(btCross(m_axis[1], m_axis[0]));
3638 m_drift *= btMin(maxdrift, btAcos(Clamp<btScalar>(btDot(m_axis[0], m_axis[1]), -1, +1)));
3639 m_drift *= m_erp / dt;
3640 m_massmatrix = AngularImpulseMatrix(m_bodies[0].invWorldInertia(), m_bodies[1].invWorldInertia());
3643 m_sdrift = m_massmatrix * (m_drift * m_split);
3644 m_drift *= 1 - m_split;
3646 m_drift /= (btScalar)iterations;
3650 void btSoftBody::AJoint::Solve(btScalar dt, btScalar sor)
3652 const btVector3 va = m_bodies[0].angularVelocity();
3653 const btVector3 vb = m_bodies[1].angularVelocity();
3654 const btVector3 vr = va - vb;
3655 const btScalar sp = btDot(vr, m_axis[0]);
3656 const btVector3 vc = vr - m_axis[0] * m_icontrol->Speed(this, sp);
3657 btSoftBody::Impulse impulse;
3658 impulse.m_asVelocity = 1;
3659 impulse.m_velocity = m_massmatrix * (m_drift + vc * m_cfm) * sor;
3660 m_bodies[0].applyAImpulse(-impulse);
3661 m_bodies[1].applyAImpulse(impulse);
3665 void btSoftBody::AJoint::Terminate(btScalar dt)
3669 m_bodies[0].applyDAImpulse(-m_sdrift);
3670 m_bodies[1].applyDAImpulse(m_sdrift);
3675 void btSoftBody::CJoint::Prepare(btScalar dt, int iterations)
3677 Joint::Prepare(dt, iterations);
3678 const bool dodrift = (m_life == 0);
3679 m_delete = (++m_life) > m_maxlife;
3682 m_drift = m_drift * m_erp / dt;
3685 m_sdrift = m_massmatrix * (m_drift * m_split);
3686 m_drift *= 1 - m_split;
3688 m_drift /= (btScalar)iterations;
3692 m_drift = m_sdrift = btVector3(0, 0, 0);
3697 void btSoftBody::CJoint::Solve(btScalar dt, btScalar sor)
3699 const btVector3 va = m_bodies[0].velocity(m_rpos[0]);
3700 const btVector3 vb = m_bodies[1].velocity(m_rpos[1]);
3701 const btVector3 vrel = va - vb;
3702 const btScalar rvac = btDot(vrel, m_normal);
3703 btSoftBody::Impulse impulse;
3704 impulse.m_asVelocity = 1;
3705 impulse.m_velocity = m_drift;
3708 const btVector3 iv = m_normal * rvac;
3709 const btVector3 fv = vrel - iv;
3710 impulse.m_velocity += iv + fv * m_friction;
3712 impulse.m_velocity = m_massmatrix * impulse.m_velocity * sor;
3714 if (m_bodies[0].m_soft == m_bodies[1].m_soft)
3716 if ((impulse.m_velocity.getX() == impulse.m_velocity.getX()) && (impulse.m_velocity.getY() == impulse.m_velocity.getY()) &&
3717 (impulse.m_velocity.getZ() == impulse.m_velocity.getZ()))
3719 if (impulse.m_asVelocity)
3721 if (impulse.m_velocity.length() < m_bodies[0].m_soft->m_maxSelfCollisionImpulse)
3726 m_bodies[0].applyImpulse(-impulse * m_bodies[0].m_soft->m_selfCollisionImpulseFactor, m_rpos[0]);
3727 m_bodies[1].applyImpulse(impulse * m_bodies[0].m_soft->m_selfCollisionImpulseFactor, m_rpos[1]);
3734 m_bodies[0].applyImpulse(-impulse, m_rpos[0]);
3735 m_bodies[1].applyImpulse(impulse, m_rpos[1]);
3740 void btSoftBody::CJoint::Terminate(btScalar dt)
3744 m_bodies[0].applyDImpulse(-m_sdrift, m_rpos[0]);
3745 m_bodies[1].applyDImpulse(m_sdrift, m_rpos[1]);
3750 void btSoftBody::applyForces()
3752 BT_PROFILE("SoftBody applyForces");
3753 // const btScalar dt = m_sst.sdt;
3754 const btScalar kLF = m_cfg.kLF;
3755 const btScalar kDG = m_cfg.kDG;
3756 const btScalar kPR = m_cfg.kPR;
3757 const btScalar kVC = m_cfg.kVC;
3758 const bool as_lift = kLF > 0;
3759 const bool as_drag = kDG > 0;
3760 const bool as_pressure = kPR != 0;
3761 const bool as_volume = kVC > 0;
3762 const bool as_aero = as_lift ||
3764 //const bool as_vaero = as_aero &&
3765 // (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
3766 //const bool as_faero = as_aero &&
3767 // (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
3768 const bool use_medium = as_aero;
3769 const bool use_volume = as_pressure ||
3771 btScalar volume = 0;
3772 btScalar ivolumetp = 0;
3773 btScalar dvolumetv = 0;
3774 btSoftBody::sMedium medium;
3777 volume = getVolume();
3778 ivolumetp = 1 / btFabs(volume) * kPR;
3779 dvolumetv = (m_pose.m_volume - volume) * kVC;
3781 /* Per vertex forces */
3784 for (i = 0, ni = m_nodes.size(); i < ni; ++i)
3786 btSoftBody::Node& n = m_nodes[i];
3792 addAeroForceToNode(m_windVelocity, i);
3797 n.m_f += n.m_n * (n.m_area * ivolumetp);
3802 n.m_f += n.m_n * (n.m_area * dvolumetv);
3807 /* Per face forces */
3808 for (i = 0, ni = m_faces.size(); i < ni; ++i)
3810 // btSoftBody::Face& f=m_faces[i];
3813 addAeroForceToFace(m_windVelocity, i);
3818 void btSoftBody::setMaxStress(btScalar maxStress)
3820 m_cfg.m_maxStress = maxStress;
3824 void btSoftBody::interpolateRenderMesh()
3828 for (int i = 0; i < m_renderNodes.size(); ++i)
3830 const Node* p0 = m_renderNodesParents[i][0];
3831 const Node* p1 = m_renderNodesParents[i][1];
3832 const Node* p2 = m_renderNodesParents[i][2];
3833 btVector3 normal = btCross(p1->m_x - p0->m_x, p2->m_x - p0->m_x);
3834 btVector3 unit_normal = normal.normalized();
3835 RenderNode& n = m_renderNodes[i];
3837 for (int j = 0; j < 3; ++j)
3839 n.m_x += m_renderNodesParents[i][j]->m_x * m_renderNodesInterpolationWeights[i][j];
3841 n.m_x += m_z[i] * unit_normal;
3846 for (int i = 0; i < m_renderNodes.size(); ++i)
3848 RenderNode& n = m_renderNodes[i];
3850 for (int j = 0; j < 4; ++j)
3852 if (m_renderNodesParents[i].size())
3854 n.m_x += m_renderNodesParents[i][j]->m_x * m_renderNodesInterpolationWeights[i][j];
3861 void btSoftBody::setCollisionQuadrature(int N)
3863 for (int i = 0; i <= N; ++i)
3865 for (int j = 0; i + j <= N; ++j)
3867 m_quads.push_back(btVector3(btScalar(i) / btScalar(N), btScalar(j) / btScalar(N), btScalar(N - i - j) / btScalar(N)));
3873 void btSoftBody::PSolve_Anchors(btSoftBody* psb, btScalar kst, btScalar ti)
3875 BT_PROFILE("PSolve_Anchors");
3876 const btScalar kAHR = psb->m_cfg.kAHR * kst;
3877 const btScalar dt = psb->m_sst.sdt;
3878 for (int i = 0, ni = psb->m_anchors.size(); i < ni; ++i)
3880 const Anchor& a = psb->m_anchors[i];
3881 const btTransform& t = a.m_body->getWorldTransform();
3882 Node& n = *a.m_node;
3883 const btVector3 wa = t * a.m_local;
3884 const btVector3 va = a.m_body->getVelocityInLocalPoint(a.m_c1) * dt;
3885 const btVector3 vb = n.m_x - n.m_q;
3886 const btVector3 vr = (va - vb) + (wa - n.m_x) * kAHR;
3887 const btVector3 impulse = a.m_c0 * vr * a.m_influence;
3888 n.m_x += impulse * a.m_c2;
3889 a.m_body->applyImpulse(-impulse, a.m_c1);
3894 void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti)
3896 BT_PROFILE("PSolve_RContacts");
3897 const btScalar dt = psb->m_sst.sdt;
3898 const btScalar mrg = psb->getCollisionShape()->getMargin();
3899 btMultiBodyJacobianData jacobianData;
3900 for (int i = 0, ni = psb->m_rcontacts.size(); i < ni; ++i)
3902 const RContact& c = psb->m_rcontacts[i];
3903 const sCti& cti = c.m_cti;
3904 if (cti.m_colObj->hasContactResponse())
3906 btVector3 va(0, 0, 0);
3907 btRigidBody* rigidCol = 0;
3908 btMultiBodyLinkCollider* multibodyLinkCol = 0;
3909 btScalar* deltaV = NULL;
3911 if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
3913 rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
3914 va = rigidCol ? rigidCol->getVelocityInLocalPoint(c.m_c1) * dt : btVector3(0, 0, 0);
3916 else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
3918 multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
3919 if (multibodyLinkCol)
3921 const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
3922 jacobianData.m_jacobians.resize(ndof);
3923 jacobianData.m_deltaVelocitiesUnitImpulse.resize(ndof);
3924 btScalar* jac = &jacobianData.m_jacobians[0];
3926 multibodyLinkCol->m_multiBody->fillContactJacobianMultiDof(multibodyLinkCol->m_link, c.m_node->m_x, cti.m_normal, jac, jacobianData.scratch_r, jacobianData.scratch_v, jacobianData.scratch_m);
3927 deltaV = &jacobianData.m_deltaVelocitiesUnitImpulse[0];
3928 multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0], deltaV, jacobianData.scratch_r, jacobianData.scratch_v);
3931 for (int j = 0; j < ndof; ++j)
3933 vel += multibodyLinkCol->m_multiBody->getVelocityVector()[j] * jac[j];
3935 va = cti.m_normal * vel * dt;
3939 const btVector3 vb = c.m_node->m_x - c.m_node->m_q;
3940 const btVector3 vr = vb - va;
3941 const btScalar dn = btDot(vr, cti.m_normal);
3942 if (dn <= SIMD_EPSILON)
3944 const btScalar dp = btMin((btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg);
3945 const btVector3 fv = vr - (cti.m_normal * dn);
3946 // c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient
3947 const btVector3 impulse = c.m_c0 * ((vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst);
3948 c.m_node->m_x -= impulse * c.m_c2;
3950 if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
3953 rigidCol->applyImpulse(impulse, c.m_c1);
3955 else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
3957 if (multibodyLinkCol)
3959 double multiplier = 0.5;
3960 multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof(deltaV, -impulse.length() * multiplier);
3969 void btSoftBody::PSolve_SContacts(btSoftBody* psb, btScalar, btScalar ti)
3971 BT_PROFILE("PSolve_SContacts");
3973 for (int i = 0, ni = psb->m_scontacts.size(); i < ni; ++i)
3975 const SContact& c = psb->m_scontacts[i];
3976 const btVector3& nr = c.m_normal;
3977 Node& n = *c.m_node;
3978 Face& f = *c.m_face;
3979 const btVector3 p = BaryEval(f.m_n[0]->m_x,
3983 const btVector3 q = BaryEval(f.m_n[0]->m_q,
3987 const btVector3 vr = (n.m_x - n.m_q) - (p - q);
3988 btVector3 corr(0, 0, 0);
3989 btScalar dot = btDot(vr, nr);
3992 const btScalar j = c.m_margin - (btDot(nr, n.m_x) - btDot(nr, p));
3993 corr += c.m_normal * j;
3995 corr -= ProjectOnPlane(vr, nr) * c.m_friction;
3996 n.m_x += corr * c.m_cfm[0];
3997 f.m_n[0]->m_x -= corr * (c.m_cfm[1] * c.m_weights.x());
3998 f.m_n[1]->m_x -= corr * (c.m_cfm[1] * c.m_weights.y());
3999 f.m_n[2]->m_x -= corr * (c.m_cfm[1] * c.m_weights.z());
4004 void btSoftBody::PSolve_Links(btSoftBody* psb, btScalar kst, btScalar ti)
4006 BT_PROFILE("PSolve_Links");
4007 for (int i = 0, ni = psb->m_links.size(); i < ni; ++i)
4009 Link& l = psb->m_links[i];
4012 Node& a = *l.m_n[0];
4013 Node& b = *l.m_n[1];
4014 const btVector3 del = b.m_x - a.m_x;
4015 const btScalar len = del.length2();
4016 if (l.m_c1 + len > SIMD_EPSILON)
4018 const btScalar k = ((l.m_c1 - len) / (l.m_c0 * (l.m_c1 + len))) * kst;
4019 a.m_x -= del * (k * a.m_im);
4020 b.m_x += del * (k * b.m_im);
4027 void btSoftBody::VSolve_Links(btSoftBody* psb, btScalar kst)
4029 BT_PROFILE("VSolve_Links");
4030 for (int i = 0, ni = psb->m_links.size(); i < ni; ++i)
4032 Link& l = psb->m_links[i];
4034 const btScalar j = -btDot(l.m_c3, n[0]->m_v - n[1]->m_v) * l.m_c2 * kst;
4035 n[0]->m_v += l.m_c3 * (j * n[0]->m_im);
4036 n[1]->m_v -= l.m_c3 * (j * n[1]->m_im);
4041 btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver)
4045 case ePSolver::Anchors:
4046 return (&btSoftBody::PSolve_Anchors);
4047 case ePSolver::Linear:
4048 return (&btSoftBody::PSolve_Links);
4049 case ePSolver::RContacts:
4050 return (&btSoftBody::PSolve_RContacts);
4051 case ePSolver::SContacts:
4052 return (&btSoftBody::PSolve_SContacts);
4061 btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
4065 case eVSolver::Linear:
4066 return (&btSoftBody::VSolve_Links);
4074 void btSoftBody::setSelfCollision(bool useSelfCollision)
4076 m_useSelfCollision = useSelfCollision;
4079 bool btSoftBody::useSelfCollision()
4081 return m_useSelfCollision;
4085 void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap)
4087 switch (m_cfg.collisions & fCollision::RVSmask)
4089 case fCollision::SDF_RS:
4091 btSoftColliders::CollideSDF_RS docollide;
4092 btRigidBody* prb1 = (btRigidBody*)btRigidBody::upcast(pcoWrap->getCollisionObject());
4093 btTransform wtr = pcoWrap->getWorldTransform();
4095 const btTransform ctr = pcoWrap->getWorldTransform();
4096 const btScalar timemargin = (wtr.getOrigin() - ctr.getOrigin()).length();
4097 const btScalar basemargin = getCollisionShape()->getMargin();
4100 ATTRIBUTE_ALIGNED16(btDbvtVolume)
4102 pcoWrap->getCollisionShape()->getAabb(pcoWrap->getWorldTransform(),
4105 volume = btDbvtVolume::FromMM(mins, maxs);
4106 volume.Expand(btVector3(basemargin, basemargin, basemargin));
4107 docollide.psb = this;
4108 docollide.m_colObj1Wrap = pcoWrap;
4109 docollide.m_rigidBody = prb1;
4111 docollide.dynmargin = basemargin + timemargin;
4112 docollide.stamargin = basemargin;
4113 m_ndbvt.collideTV(m_ndbvt.m_root, volume, docollide);
4116 case fCollision::CL_RS:
4118 btSoftColliders::CollideCL_RS collider;
4119 collider.ProcessColObj(this, pcoWrap);
4122 case fCollision::SDF_RD:
4124 btRigidBody* prb1 = (btRigidBody*)btRigidBody::upcast(pcoWrap->getCollisionObject());
4125 if (this->isActive())
4127 const btTransform wtr = pcoWrap->getWorldTransform();
4128 const btScalar timemargin = 0;
4129 const btScalar basemargin = getCollisionShape()->getMargin();
4132 ATTRIBUTE_ALIGNED16(btDbvtVolume)
4134 pcoWrap->getCollisionShape()->getAabb(wtr,
4137 volume = btDbvtVolume::FromMM(mins, maxs);
4138 volume.Expand(btVector3(basemargin, basemargin, basemargin));
4139 if (m_cfg.collisions & fCollision::SDF_RDN)
4141 btSoftColliders::CollideSDF_RD docollideNode;
4142 docollideNode.psb = this;
4143 docollideNode.m_colObj1Wrap = pcoWrap;
4144 docollideNode.m_rigidBody = prb1;
4145 docollideNode.dynmargin = basemargin + timemargin;
4146 docollideNode.stamargin = basemargin;
4147 m_ndbvt.collideTV(m_ndbvt.m_root, volume, docollideNode);
4150 if (((pcoWrap->getCollisionObject()->getInternalType() == CO_RIGID_BODY) && (m_cfg.collisions & fCollision::SDF_RDF)) || ((pcoWrap->getCollisionObject()->getInternalType() == CO_FEATHERSTONE_LINK) && (m_cfg.collisions & fCollision::SDF_MDF)))
4152 btSoftColliders::CollideSDF_RDF docollideFace;
4153 docollideFace.psb = this;
4154 docollideFace.m_colObj1Wrap = pcoWrap;
4155 docollideFace.m_rigidBody = prb1;
4156 docollideFace.dynmargin = basemargin + timemargin;
4157 docollideFace.stamargin = basemargin;
4158 m_fdbvt.collideTV(m_fdbvt.m_root, volume, docollideFace);
4167 void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
4169 BT_PROFILE("Deformable Collision");
4170 const int cf = m_cfg.collisions & psb->m_cfg.collisions;
4171 switch (cf & fCollision::SVSmask)
4173 case fCollision::CL_SS:
4175 //support self-collision if CL_SELF flag set
4176 if (this != psb || psb->m_cfg.collisions & fCollision::CL_SELF)
4178 btSoftColliders::CollideCL_SS docollide;
4179 docollide.ProcessSoftSoft(this, psb);
4183 case fCollision::VF_SS:
4185 //only self-collision for Cluster, not Vertex-Face yet
4188 btSoftColliders::CollideVF_SS docollide;
4190 docollide.mrg = getCollisionShape()->getMargin() +
4191 psb->getCollisionShape()->getMargin();
4192 /* psb0 nodes vs psb1 faces */
4193 docollide.psb[0] = this;
4194 docollide.psb[1] = psb;
4195 docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
4196 docollide.psb[1]->m_fdbvt.m_root,
4198 /* psb1 nodes vs psb0 faces */
4199 docollide.psb[0] = psb;
4200 docollide.psb[1] = this;
4201 docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
4202 docollide.psb[1]->m_fdbvt.m_root,
4207 case fCollision::VF_DD:
4209 if (!psb->m_softSoftCollision)
4211 if (psb->isActive() || this->isActive())
4215 btSoftColliders::CollideVF_DD docollide;
4217 docollide.mrg = getCollisionShape()->getMargin() +
4218 psb->getCollisionShape()->getMargin();
4219 /* psb0 nodes vs psb1 faces */
4220 if (psb->m_tetras.size() > 0)
4221 docollide.useFaceNormal = true;
4223 docollide.useFaceNormal = false;
4224 docollide.psb[0] = this;
4225 docollide.psb[1] = psb;
4226 docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
4227 docollide.psb[1]->m_fdbvt.m_root,
4230 /* psb1 nodes vs psb0 faces */
4231 if (this->m_tetras.size() > 0)
4232 docollide.useFaceNormal = true;
4234 docollide.useFaceNormal = false;
4235 docollide.psb[0] = psb;
4236 docollide.psb[1] = this;
4237 docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
4238 docollide.psb[1]->m_fdbvt.m_root,
4243 if (psb->useSelfCollision())
4245 btSoftColliders::CollideFF_DD docollide;
4246 docollide.mrg = 2 * getCollisionShape()->getMargin();
4247 docollide.psb[0] = this;
4248 docollide.psb[1] = psb;
4249 if (this->m_tetras.size() > 0)
4250 docollide.useFaceNormal = true;
4252 docollide.useFaceNormal = false;
4253 /* psb0 faces vs psb0 faces */
4254 calculateNormalCone(this->m_fdbvnt);
4255 this->m_fdbvt.selfCollideT(m_fdbvnt, docollide);
4267 void btSoftBody::geometricCollisionHandler(btSoftBody* psb)
4269 if (psb->isActive() || this->isActive())
4273 btSoftColliders::CollideCCD docollide;
4275 docollide.mrg = SAFE_EPSILON; // for rounding error instead of actual margin
4276 docollide.dt = psb->m_sst.sdt;
4277 /* psb0 nodes vs psb1 faces */
4278 if (psb->m_tetras.size() > 0)
4279 docollide.useFaceNormal = true;
4281 docollide.useFaceNormal = false;
4282 docollide.psb[0] = this;
4283 docollide.psb[1] = psb;
4284 docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
4285 docollide.psb[1]->m_fdbvt.m_root,
4287 /* psb1 nodes vs psb0 faces */
4288 if (this->m_tetras.size() > 0)
4289 docollide.useFaceNormal = true;
4291 docollide.useFaceNormal = false;
4292 docollide.psb[0] = psb;
4293 docollide.psb[1] = this;
4294 docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
4295 docollide.psb[1]->m_fdbvt.m_root,
4300 if (psb->useSelfCollision())
4302 btSoftColliders::CollideCCD docollide;
4303 docollide.mrg = SAFE_EPSILON;
4304 docollide.psb[0] = this;
4305 docollide.psb[1] = psb;
4306 docollide.dt = psb->m_sst.sdt;
4307 if (this->m_tetras.size() > 0)
4308 docollide.useFaceNormal = true;
4310 docollide.useFaceNormal = false;
4311 /* psb0 faces vs psb0 faces */
4312 calculateNormalCone(this->m_fdbvnt); // should compute this outside of this scope
4313 this->m_fdbvt.selfCollideT(m_fdbvnt, docollide);
4319 void btSoftBody::setWindVelocity(const btVector3& velocity)
4321 m_windVelocity = velocity;
4324 const btVector3& btSoftBody::getWindVelocity()
4326 return m_windVelocity;
4329 int btSoftBody::calculateSerializeBufferSize() const
4331 int sz = sizeof(btSoftBodyData);
4335 ///fills the dataBuffer and returns the struct name (and 0 on failure)
4336 const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializer) const
4338 btSoftBodyData* sbd = (btSoftBodyData*)dataBuffer;
4340 btCollisionObject::serialize(&sbd->m_collisionObjectData, serializer);
4342 btHashMap<btHashPtr, int> m_nodeIndexMap;
4344 sbd->m_numMaterials = m_materials.size();
4345 sbd->m_materials = sbd->m_numMaterials ? (SoftBodyMaterialData**)serializer->getUniquePointer((void*)&m_materials) : 0;
4347 if (sbd->m_materials)
4349 int sz = sizeof(SoftBodyMaterialData*);
4350 int numElem = sbd->m_numMaterials;
4351 btChunk* chunk = serializer->allocate(sz, numElem);
4352 //SoftBodyMaterialData** memPtr = chunk->m_oldPtr;
4353 SoftBodyMaterialData** memPtr = (SoftBodyMaterialData**)chunk->m_oldPtr;
4354 for (int i = 0; i < numElem; i++, memPtr++)
4356 btSoftBody::Material* mat = m_materials[i];
4357 *memPtr = mat ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)mat) : 0;
4358 if (!serializer->findPointer(mat))
4361 btChunk* chunk = serializer->allocate(sizeof(SoftBodyMaterialData), 1);
4362 SoftBodyMaterialData* memPtr = (SoftBodyMaterialData*)chunk->m_oldPtr;
4363 memPtr->m_flags = mat->m_flags;
4364 memPtr->m_angularStiffness = mat->m_kAST;
4365 memPtr->m_linearStiffness = mat->m_kLST;
4366 memPtr->m_volumeStiffness = mat->m_kVST;
4367 serializer->finalizeChunk(chunk, "SoftBodyMaterialData", BT_SBMATERIAL_CODE, mat);
4370 serializer->finalizeChunk(chunk, "SoftBodyMaterialData", BT_ARRAY_CODE, (void*)&m_materials);
4373 sbd->m_numNodes = m_nodes.size();
4374 sbd->m_nodes = sbd->m_numNodes ? (SoftBodyNodeData*)serializer->getUniquePointer((void*)&m_nodes) : 0;
4377 int sz = sizeof(SoftBodyNodeData);
4378 int numElem = sbd->m_numNodes;
4379 btChunk* chunk = serializer->allocate(sz, numElem);
4380 SoftBodyNodeData* memPtr = (SoftBodyNodeData*)chunk->m_oldPtr;
4381 for (int i = 0; i < numElem; i++, memPtr++)
4383 m_nodes[i].m_f.serializeFloat(memPtr->m_accumulatedForce);
4384 memPtr->m_area = m_nodes[i].m_area;
4385 memPtr->m_attach = m_nodes[i].m_battach;
4386 memPtr->m_inverseMass = m_nodes[i].m_im;
4387 memPtr->m_material = m_nodes[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_nodes[i].m_material) : 0;
4388 m_nodes[i].m_n.serializeFloat(memPtr->m_normal);
4389 m_nodes[i].m_x.serializeFloat(memPtr->m_position);
4390 m_nodes[i].m_q.serializeFloat(memPtr->m_previousPosition);
4391 m_nodes[i].m_v.serializeFloat(memPtr->m_velocity);
4392 m_nodeIndexMap.insert(&m_nodes[i], i);
4394 serializer->finalizeChunk(chunk, "SoftBodyNodeData", BT_SBNODE_CODE, (void*)&m_nodes);
4397 sbd->m_numLinks = m_links.size();
4398 sbd->m_links = sbd->m_numLinks ? (SoftBodyLinkData*)serializer->getUniquePointer((void*)&m_links[0]) : 0;
4401 int sz = sizeof(SoftBodyLinkData);
4402 int numElem = sbd->m_numLinks;
4403 btChunk* chunk = serializer->allocate(sz, numElem);
4404 SoftBodyLinkData* memPtr = (SoftBodyLinkData*)chunk->m_oldPtr;
4405 for (int i = 0; i < numElem; i++, memPtr++)
4407 memPtr->m_bbending = m_links[i].m_bbending;
4408 memPtr->m_material = m_links[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_links[i].m_material) : 0;
4409 memPtr->m_nodeIndices[0] = m_links[i].m_n[0] ? m_links[i].m_n[0] - &m_nodes[0] : -1;
4410 memPtr->m_nodeIndices[1] = m_links[i].m_n[1] ? m_links[i].m_n[1] - &m_nodes[0] : -1;
4411 btAssert(memPtr->m_nodeIndices[0] < m_nodes.size());
4412 btAssert(memPtr->m_nodeIndices[1] < m_nodes.size());
4413 memPtr->m_restLength = m_links[i].m_rl;
4415 serializer->finalizeChunk(chunk, "SoftBodyLinkData", BT_ARRAY_CODE, (void*)&m_links[0]);
4418 sbd->m_numFaces = m_faces.size();
4419 sbd->m_faces = sbd->m_numFaces ? (SoftBodyFaceData*)serializer->getUniquePointer((void*)&m_faces[0]) : 0;
4422 int sz = sizeof(SoftBodyFaceData);
4423 int numElem = sbd->m_numFaces;
4424 btChunk* chunk = serializer->allocate(sz, numElem);
4425 SoftBodyFaceData* memPtr = (SoftBodyFaceData*)chunk->m_oldPtr;
4426 for (int i = 0; i < numElem; i++, memPtr++)
4428 memPtr->m_material = m_faces[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_faces[i].m_material) : 0;
4429 m_faces[i].m_normal.serializeFloat(memPtr->m_normal);
4430 for (int j = 0; j < 3; j++)
4432 memPtr->m_nodeIndices[j] = m_faces[i].m_n[j] ? m_faces[i].m_n[j] - &m_nodes[0] : -1;
4434 memPtr->m_restArea = m_faces[i].m_ra;
4436 serializer->finalizeChunk(chunk, "SoftBodyFaceData", BT_ARRAY_CODE, (void*)&m_faces[0]);
4439 sbd->m_numTetrahedra = m_tetras.size();
4440 sbd->m_tetrahedra = sbd->m_numTetrahedra ? (SoftBodyTetraData*)serializer->getUniquePointer((void*)&m_tetras[0]) : 0;
4441 if (sbd->m_tetrahedra)
4443 int sz = sizeof(SoftBodyTetraData);
4444 int numElem = sbd->m_numTetrahedra;
4445 btChunk* chunk = serializer->allocate(sz, numElem);
4446 SoftBodyTetraData* memPtr = (SoftBodyTetraData*)chunk->m_oldPtr;
4447 for (int i = 0; i < numElem; i++, memPtr++)
4449 for (int j = 0; j < 4; j++)
4451 m_tetras[i].m_c0[j].serializeFloat(memPtr->m_c0[j]);
4452 memPtr->m_nodeIndices[j] = m_tetras[i].m_n[j] ? m_tetras[i].m_n[j] - &m_nodes[0] : -1;
4454 memPtr->m_c1 = m_tetras[i].m_c1;
4455 memPtr->m_c2 = m_tetras[i].m_c2;
4456 memPtr->m_material = m_tetras[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_tetras[i].m_material) : 0;
4457 memPtr->m_restVolume = m_tetras[i].m_rv;
4459 serializer->finalizeChunk(chunk, "SoftBodyTetraData", BT_ARRAY_CODE, (void*)&m_tetras[0]);
4462 sbd->m_numAnchors = m_anchors.size();
4463 sbd->m_anchors = sbd->m_numAnchors ? (SoftRigidAnchorData*)serializer->getUniquePointer((void*)&m_anchors[0]) : 0;
4466 int sz = sizeof(SoftRigidAnchorData);
4467 int numElem = sbd->m_numAnchors;
4468 btChunk* chunk = serializer->allocate(sz, numElem);
4469 SoftRigidAnchorData* memPtr = (SoftRigidAnchorData*)chunk->m_oldPtr;
4470 for (int i = 0; i < numElem; i++, memPtr++)
4472 m_anchors[i].m_c0.serializeFloat(memPtr->m_c0);
4473 m_anchors[i].m_c1.serializeFloat(memPtr->m_c1);
4474 memPtr->m_c2 = m_anchors[i].m_c2;
4475 m_anchors[i].m_local.serializeFloat(memPtr->m_localFrame);
4476 memPtr->m_nodeIndex = m_anchors[i].m_node ? m_anchors[i].m_node - &m_nodes[0] : -1;
4478 memPtr->m_rigidBody = m_anchors[i].m_body ? (btRigidBodyData*)serializer->getUniquePointer((void*)m_anchors[i].m_body) : 0;
4479 btAssert(memPtr->m_nodeIndex < m_nodes.size());
4481 serializer->finalizeChunk(chunk, "SoftRigidAnchorData", BT_ARRAY_CODE, (void*)&m_anchors[0]);
4484 sbd->m_config.m_dynamicFriction = m_cfg.kDF;
4485 sbd->m_config.m_baumgarte = m_cfg.kVCF;
4486 sbd->m_config.m_pressure = m_cfg.kPR;
4487 sbd->m_config.m_aeroModel = this->m_cfg.aeromodel;
4488 sbd->m_config.m_lift = m_cfg.kLF;
4489 sbd->m_config.m_drag = m_cfg.kDG;
4490 sbd->m_config.m_positionIterations = m_cfg.piterations;
4491 sbd->m_config.m_driftIterations = m_cfg.diterations;
4492 sbd->m_config.m_clusterIterations = m_cfg.citerations;
4493 sbd->m_config.m_velocityIterations = m_cfg.viterations;
4494 sbd->m_config.m_maxVolume = m_cfg.maxvolume;
4495 sbd->m_config.m_damping = m_cfg.kDP;
4496 sbd->m_config.m_poseMatch = m_cfg.kMT;
4497 sbd->m_config.m_collisionFlags = m_cfg.collisions;
4498 sbd->m_config.m_volume = m_cfg.kVC;
4499 sbd->m_config.m_rigidContactHardness = m_cfg.kCHR;
4500 sbd->m_config.m_kineticContactHardness = m_cfg.kKHR;
4501 sbd->m_config.m_softContactHardness = m_cfg.kSHR;
4502 sbd->m_config.m_anchorHardness = m_cfg.kAHR;
4503 sbd->m_config.m_timeScale = m_cfg.timescale;
4504 sbd->m_config.m_maxVolume = m_cfg.maxvolume;
4505 sbd->m_config.m_softRigidClusterHardness = m_cfg.kSRHR_CL;
4506 sbd->m_config.m_softKineticClusterHardness = m_cfg.kSKHR_CL;
4507 sbd->m_config.m_softSoftClusterHardness = m_cfg.kSSHR_CL;
4508 sbd->m_config.m_softRigidClusterImpulseSplit = m_cfg.kSR_SPLT_CL;
4509 sbd->m_config.m_softKineticClusterImpulseSplit = m_cfg.kSK_SPLT_CL;
4510 sbd->m_config.m_softSoftClusterImpulseSplit = m_cfg.kSS_SPLT_CL;
4512 //pose for shape matching
4514 sbd->m_pose = (SoftBodyPoseData*)serializer->getUniquePointer((void*)&m_pose);
4516 int sz = sizeof(SoftBodyPoseData);
4517 btChunk* chunk = serializer->allocate(sz, 1);
4518 SoftBodyPoseData* memPtr = (SoftBodyPoseData*)chunk->m_oldPtr;
4520 m_pose.m_aqq.serializeFloat(memPtr->m_aqq);
4521 memPtr->m_bframe = m_pose.m_bframe;
4522 memPtr->m_bvolume = m_pose.m_bvolume;
4523 m_pose.m_com.serializeFloat(memPtr->m_com);
4525 memPtr->m_numPositions = m_pose.m_pos.size();
4526 memPtr->m_positions = memPtr->m_numPositions ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_pose.m_pos[0]) : 0;
4527 if (memPtr->m_numPositions)
4529 int numElem = memPtr->m_numPositions;
4530 int sz = sizeof(btVector3Data);
4531 btChunk* chunk = serializer->allocate(sz, numElem);
4532 btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr;
4533 for (int i = 0; i < numElem; i++, memPtr++)
4535 m_pose.m_pos[i].serializeFloat(*memPtr);
4537 serializer->finalizeChunk(chunk, "btVector3FloatData", BT_ARRAY_CODE, (void*)&m_pose.m_pos[0]);
4539 memPtr->m_restVolume = m_pose.m_volume;
4540 m_pose.m_rot.serializeFloat(memPtr->m_rot);
4541 m_pose.m_scl.serializeFloat(memPtr->m_scale);
4543 memPtr->m_numWeigts = m_pose.m_wgh.size();
4544 memPtr->m_weights = memPtr->m_numWeigts ? (float*)serializer->getUniquePointer((void*)&m_pose.m_wgh[0]) : 0;
4545 if (memPtr->m_numWeigts)
4547 int numElem = memPtr->m_numWeigts;
4548 int sz = sizeof(float);
4549 btChunk* chunk = serializer->allocate(sz, numElem);
4550 float* memPtr = (float*)chunk->m_oldPtr;
4551 for (int i = 0; i < numElem; i++, memPtr++)
4553 *memPtr = m_pose.m_wgh[i];
4555 serializer->finalizeChunk(chunk, "float", BT_ARRAY_CODE, (void*)&m_pose.m_wgh[0]);
4558 serializer->finalizeChunk(chunk, "SoftBodyPoseData", BT_ARRAY_CODE, (void*)&m_pose);
4561 //clusters for convex-cluster collision detection
4563 sbd->m_numClusters = m_clusters.size();
4564 sbd->m_clusters = sbd->m_numClusters ? (SoftBodyClusterData*)serializer->getUniquePointer((void*)m_clusters[0]) : 0;
4565 if (sbd->m_numClusters)
4567 int numElem = sbd->m_numClusters;
4568 int sz = sizeof(SoftBodyClusterData);
4569 btChunk* chunk = serializer->allocate(sz, numElem);
4570 SoftBodyClusterData* memPtr = (SoftBodyClusterData*)chunk->m_oldPtr;
4571 for (int i = 0; i < numElem; i++, memPtr++)
4573 memPtr->m_adamping = m_clusters[i]->m_adamping;
4574 m_clusters[i]->m_av.serializeFloat(memPtr->m_av);
4575 memPtr->m_clusterIndex = m_clusters[i]->m_clusterIndex;
4576 memPtr->m_collide = m_clusters[i]->m_collide;
4577 m_clusters[i]->m_com.serializeFloat(memPtr->m_com);
4578 memPtr->m_containsAnchor = m_clusters[i]->m_containsAnchor;
4579 m_clusters[i]->m_dimpulses[0].serializeFloat(memPtr->m_dimpulses[0]);
4580 m_clusters[i]->m_dimpulses[1].serializeFloat(memPtr->m_dimpulses[1]);
4581 m_clusters[i]->m_framexform.serializeFloat(memPtr->m_framexform);
4582 memPtr->m_idmass = m_clusters[i]->m_idmass;
4583 memPtr->m_imass = m_clusters[i]->m_imass;
4584 m_clusters[i]->m_invwi.serializeFloat(memPtr->m_invwi);
4585 memPtr->m_ldamping = m_clusters[i]->m_ldamping;
4586 m_clusters[i]->m_locii.serializeFloat(memPtr->m_locii);
4587 m_clusters[i]->m_lv.serializeFloat(memPtr->m_lv);
4588 memPtr->m_matching = m_clusters[i]->m_matching;
4589 memPtr->m_maxSelfCollisionImpulse = m_clusters[i]->m_maxSelfCollisionImpulse;
4590 memPtr->m_ndamping = m_clusters[i]->m_ndamping;
4591 memPtr->m_ldamping = m_clusters[i]->m_ldamping;
4592 memPtr->m_adamping = m_clusters[i]->m_adamping;
4593 memPtr->m_selfCollisionImpulseFactor = m_clusters[i]->m_selfCollisionImpulseFactor;
4595 memPtr->m_numFrameRefs = m_clusters[i]->m_framerefs.size();
4596 memPtr->m_numMasses = m_clusters[i]->m_masses.size();
4597 memPtr->m_numNodes = m_clusters[i]->m_nodes.size();
4599 memPtr->m_nvimpulses = m_clusters[i]->m_nvimpulses;
4600 m_clusters[i]->m_vimpulses[0].serializeFloat(memPtr->m_vimpulses[0]);
4601 m_clusters[i]->m_vimpulses[1].serializeFloat(memPtr->m_vimpulses[1]);
4602 memPtr->m_ndimpulses = m_clusters[i]->m_ndimpulses;
4604 memPtr->m_framerefs = memPtr->m_numFrameRefs ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_clusters[i]->m_framerefs[0]) : 0;
4605 if (memPtr->m_framerefs)
4607 int numElem = memPtr->m_numFrameRefs;
4608 int sz = sizeof(btVector3FloatData);
4609 btChunk* chunk = serializer->allocate(sz, numElem);
4610 btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr;
4611 for (int j = 0; j < numElem; j++, memPtr++)
4613 m_clusters[i]->m_framerefs[j].serializeFloat(*memPtr);
4615 serializer->finalizeChunk(chunk, "btVector3FloatData", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_framerefs[0]);
4618 memPtr->m_masses = memPtr->m_numMasses ? (float*)serializer->getUniquePointer((void*)&m_clusters[i]->m_masses[0]) : 0;
4619 if (memPtr->m_masses)
4621 int numElem = memPtr->m_numMasses;
4622 int sz = sizeof(float);
4623 btChunk* chunk = serializer->allocate(sz, numElem);
4624 float* memPtr = (float*)chunk->m_oldPtr;
4625 for (int j = 0; j < numElem; j++, memPtr++)
4627 *memPtr = m_clusters[i]->m_masses[j];
4629 serializer->finalizeChunk(chunk, "float", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_masses[0]);
4632 memPtr->m_nodeIndices = memPtr->m_numNodes ? (int*)serializer->getUniquePointer((void*)&m_clusters[i]->m_nodes) : 0;
4633 if (memPtr->m_nodeIndices)
4635 int numElem = memPtr->m_numMasses;
4636 int sz = sizeof(int);
4637 btChunk* chunk = serializer->allocate(sz, numElem);
4638 int* memPtr = (int*)chunk->m_oldPtr;
4639 for (int j = 0; j < numElem; j++, memPtr++)
4641 int* indexPtr = m_nodeIndexMap.find(m_clusters[i]->m_nodes[j]);
4643 *memPtr = *indexPtr;
4645 serializer->finalizeChunk(chunk, "int", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_nodes);
4648 serializer->finalizeChunk(chunk, "SoftBodyClusterData", BT_ARRAY_CODE, (void*)m_clusters[0]);
4651 sbd->m_numJoints = m_joints.size();
4652 sbd->m_joints = m_joints.size() ? (btSoftBodyJointData*)serializer->getUniquePointer((void*)&m_joints[0]) : 0;
4656 int sz = sizeof(btSoftBodyJointData);
4657 int numElem = m_joints.size();
4658 btChunk* chunk = serializer->allocate(sz, numElem);
4659 btSoftBodyJointData* memPtr = (btSoftBodyJointData*)chunk->m_oldPtr;
4661 for (int i = 0; i < numElem; i++, memPtr++)
4663 memPtr->m_jointType = (int)m_joints[i]->Type();
4664 m_joints[i]->m_refs[0].serializeFloat(memPtr->m_refs[0]);
4665 m_joints[i]->m_refs[1].serializeFloat(memPtr->m_refs[1]);
4666 memPtr->m_cfm = m_joints[i]->m_cfm;
4667 memPtr->m_erp = float(m_joints[i]->m_erp);
4668 memPtr->m_split = float(m_joints[i]->m_split);
4669 memPtr->m_delete = m_joints[i]->m_delete;
4671 for (int j = 0; j < 4; j++)
4673 memPtr->m_relPosition[0].m_floats[j] = 0.f;
4674 memPtr->m_relPosition[1].m_floats[j] = 0.f;
4676 memPtr->m_bodyA = 0;
4677 memPtr->m_bodyB = 0;
4678 if (m_joints[i]->m_bodies[0].m_soft)
4680 memPtr->m_bodyAtype = BT_JOINT_SOFT_BODY_CLUSTER;
4681 memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_soft);
4683 if (m_joints[i]->m_bodies[0].m_collisionObject)
4685 memPtr->m_bodyAtype = BT_JOINT_COLLISION_OBJECT;
4686 memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_collisionObject);
4688 if (m_joints[i]->m_bodies[0].m_rigid)
4690 memPtr->m_bodyAtype = BT_JOINT_RIGID_BODY;
4691 memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_rigid);
4694 if (m_joints[i]->m_bodies[1].m_soft)
4696 memPtr->m_bodyBtype = BT_JOINT_SOFT_BODY_CLUSTER;
4697 memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_soft);
4699 if (m_joints[i]->m_bodies[1].m_collisionObject)
4701 memPtr->m_bodyBtype = BT_JOINT_COLLISION_OBJECT;
4702 memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_collisionObject);
4704 if (m_joints[i]->m_bodies[1].m_rigid)
4706 memPtr->m_bodyBtype = BT_JOINT_RIGID_BODY;
4707 memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_rigid);
4710 serializer->finalizeChunk(chunk, "btSoftBodyJointData", BT_ARRAY_CODE, (void*)&m_joints[0]);
4713 return btSoftBodyDataName;
4716 void btSoftBody::updateDeactivation(btScalar timeStep)
4718 if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
4721 if (m_maxSpeedSquared < m_sleepingThreshold * m_sleepingThreshold)
4723 m_deactivationTime += timeStep;
4727 m_deactivationTime = btScalar(0.);
4728 setActivationState(0);
4732 void btSoftBody::setZeroVelocity()
4734 for (int i = 0; i < m_nodes.size(); ++i)
4736 m_nodes[i].m_v.setZero();
4740 bool btSoftBody::wantsSleeping()
4742 if (getActivationState() == DISABLE_DEACTIVATION)
4745 //disable deactivation
4746 if (gDisableDeactivation || (gDeactivationTime == btScalar(0.)))
4749 if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION))
4752 if (m_deactivationTime > gDeactivationTime)