2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
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"
24 btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m)
25 :m_softBodySolver(0),m_worldInfo(worldInfo)
30 /* Default material */
31 Material* pm=appendMaterial();
35 pm->m_flags = fMaterial::Default;
38 const btScalar margin=getCollisionShape()->getMargin();
39 m_nodes.resize(node_count);
40 for(int i=0,ni=node_count;i<ni;++i)
44 n.m_x = x?*x++:btVector3(0,0,0);
47 n.m_im = n.m_im>0?1/n.m_im:0;
48 n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
55 btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo)
56 :m_worldInfo(worldInfo)
62 void btSoftBody::initDefaults()
64 m_internalType = CO_SOFT_BODY;
65 m_cfg.aeromodel = eAeroModel::V_Point;
72 m_cfg.kDF = (btScalar)0.2;
74 m_cfg.kCHR = (btScalar)1.0;
75 m_cfg.kKHR = (btScalar)0.1;
76 m_cfg.kSHR = (btScalar)1.0;
77 m_cfg.kAHR = (btScalar)0.7;
78 m_cfg.kSRHR_CL = (btScalar)0.1;
79 m_cfg.kSKHR_CL = (btScalar)1;
80 m_cfg.kSSHR_CL = (btScalar)0.5;
81 m_cfg.kSR_SPLT_CL = (btScalar)0.5;
82 m_cfg.kSK_SPLT_CL = (btScalar)0.5;
83 m_cfg.kSS_SPLT_CL = (btScalar)0.5;
84 m_cfg.maxvolume = (btScalar)1;
86 m_cfg.viterations = 0;
87 m_cfg.piterations = 1;
88 m_cfg.diterations = 0;
89 m_cfg.citerations = 4;
90 m_cfg.collisions = fCollision::Default;
91 m_pose.m_bvolume = false;
92 m_pose.m_bframe = false;
94 m_pose.m_com = btVector3(0,0,0);
95 m_pose.m_rot.setIdentity();
96 m_pose.m_scl.setIdentity();
99 m_bUpdateRtCst = true;
100 m_bounds[0] = btVector3(0,0,0);
101 m_bounds[1] = btVector3(0,0,0);
102 m_worldTransform.setIdentity();
103 setSolver(eSolverPresets::Positions);
105 /* Collision shape */
106 ///for now, create a collision shape internally
107 m_collisionShape = new btSoftBodyCollisionShape(this);
108 m_collisionShape->setMargin(0.25f);
110 m_initialWorldTransform.setIdentity();
112 m_windVelocity = btVector3(0,0,0);
113 m_restLengthScale = btScalar(1.0);
117 btSoftBody::~btSoftBody()
119 //for now, delete the internal shape
120 delete m_collisionShape;
124 for(i=0;i<m_materials.size();++i)
125 btAlignedFree(m_materials[i]);
126 for(i=0;i<m_joints.size();++i)
127 btAlignedFree(m_joints[i]);
131 bool btSoftBody::checkLink(int node0,int node1) const
133 return(checkLink(&m_nodes[node0],&m_nodes[node1]));
137 bool btSoftBody::checkLink(const Node* node0,const Node* node1) const
139 const Node* n[]={node0,node1};
140 for(int i=0,ni=m_links.size();i<ni;++i)
142 const Link& l=m_links[i];
143 if( (l.m_n[0]==n[0]&&l.m_n[1]==n[1])||
144 (l.m_n[0]==n[1]&&l.m_n[1]==n[0]))
153 bool btSoftBody::checkFace(int node0,int node1,int node2) const
155 const Node* n[]={ &m_nodes[node0],
158 for(int i=0,ni=m_faces.size();i<ni;++i)
160 const Face& f=m_faces[i];
164 if( (f.m_n[j]==n[0])||
166 (f.m_n[j]==n[2])) c|=1<<j; else break;
168 if(c==7) return(true);
174 btSoftBody::Material* btSoftBody::appendMaterial()
176 Material* pm=new(btAlignedAlloc(sizeof(Material),16)) Material();
177 if(m_materials.size()>0)
181 m_materials.push_back(pm);
186 void btSoftBody::appendNote( const char* text,
199 n.m_coords[0] = c.x();
200 n.m_coords[1] = c.y();
201 n.m_coords[2] = c.z();
202 n.m_coords[3] = c.w();
203 n.m_nodes[0] = n0;n.m_rank+=n0?1:0;
204 n.m_nodes[1] = n1;n.m_rank+=n1?1:0;
205 n.m_nodes[2] = n2;n.m_rank+=n2?1:0;
206 n.m_nodes[3] = n3;n.m_rank+=n3?1:0;
207 m_notes.push_back(n);
211 void btSoftBody::appendNote( const char* text,
215 appendNote(text,o,btVector4(1,0,0,0),feature);
219 void btSoftBody::appendNote( const char* text,
223 static const btScalar w=1/(btScalar)2;
224 appendNote(text,o,btVector4(w,w,0,0), feature->m_n[0],
229 void btSoftBody::appendNote( const char* text,
233 static const btScalar w=1/(btScalar)3;
234 appendNote(text,o,btVector4(w,w,w,0), feature->m_n[0],
240 void btSoftBody::appendNode( const btVector3& x,btScalar m)
242 if(m_nodes.capacity()==m_nodes.size())
245 m_nodes.reserve(m_nodes.size()*2+1);
248 const btScalar margin=getCollisionShape()->getMargin();
249 m_nodes.push_back(Node());
250 Node& n=m_nodes[m_nodes.size()-1];
255 n.m_material = m_materials[0];
256 n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
260 void btSoftBody::appendLink(int model,Material* mat)
266 { ZeroInitialize(l);l.m_material=mat?mat:m_materials[0]; }
267 m_links.push_back(l);
271 void btSoftBody::appendLink( int node0,
276 appendLink(&m_nodes[node0],&m_nodes[node1],mat,bcheckexist);
280 void btSoftBody::appendLink( Node* node0,
285 if((!bcheckexist)||(!checkLink(node0,node1)))
288 Link& l=m_links[m_links.size()-1];
291 l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
297 void btSoftBody::appendFace(int model,Material* mat)
301 { f=m_faces[model]; }
303 { ZeroInitialize(f);f.m_material=mat?mat:m_materials[0]; }
304 m_faces.push_back(f);
308 void btSoftBody::appendFace(int node0,int node1,int node2,Material* mat)
318 Face& f=m_faces[m_faces.size()-1];
319 btAssert(node0!=node1);
320 btAssert(node1!=node2);
321 btAssert(node2!=node0);
322 f.m_n[0] = &m_nodes[node0];
323 f.m_n[1] = &m_nodes[node1];
324 f.m_n[2] = &m_nodes[node2];
325 f.m_ra = AreaOf( f.m_n[0]->m_x,
332 void btSoftBody::appendTetra(int model,Material* mat)
338 { ZeroInitialize(t);t.m_material=mat?mat:m_materials[0]; }
339 m_tetras.push_back(t);
343 void btSoftBody::appendTetra(int node0,
350 Tetra& t=m_tetras[m_tetras.size()-1];
351 t.m_n[0] = &m_nodes[node0];
352 t.m_n[1] = &m_nodes[node1];
353 t.m_n[2] = &m_nodes[node2];
354 t.m_n[3] = &m_nodes[node3];
355 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);
361 void btSoftBody::appendAnchor(int node,btRigidBody* body, bool disableCollisionBetweenLinkedBodies,btScalar influence)
363 btVector3 local = body->getWorldTransform().inverse()*m_nodes[node].m_x;
364 appendAnchor(node,body,local,disableCollisionBetweenLinkedBodies,influence);
368 void btSoftBody::appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies,btScalar influence)
370 if (disableCollisionBetweenLinkedBodies)
372 if (m_collisionDisabledObjects.findLinearSearch(body)==m_collisionDisabledObjects.size())
374 m_collisionDisabledObjects.push_back(body);
379 a.m_node = &m_nodes[node];
381 a.m_local = localPivot;
382 a.m_node->m_battach = 1;
383 a.m_influence = influence;
384 m_anchors.push_back(a);
388 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1)
390 LJoint* pj = new(btAlignedAlloc(sizeof(LJoint),16)) LJoint();
391 pj->m_bodies[0] = body0;
392 pj->m_bodies[1] = body1;
393 pj->m_refs[0] = pj->m_bodies[0].xform().inverse()*specs.position;
394 pj->m_refs[1] = pj->m_bodies[1].xform().inverse()*specs.position;
395 pj->m_cfm = specs.cfm;
396 pj->m_erp = specs.erp;
397 pj->m_split = specs.split;
398 m_joints.push_back(pj);
402 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body)
404 appendLinearJoint(specs,m_clusters[0],body);
408 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body)
410 appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]);
414 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1)
416 AJoint* pj = new(btAlignedAlloc(sizeof(AJoint),16)) AJoint();
417 pj->m_bodies[0] = body0;
418 pj->m_bodies[1] = body1;
419 pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis()*specs.axis;
420 pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis()*specs.axis;
421 pj->m_cfm = specs.cfm;
422 pj->m_erp = specs.erp;
423 pj->m_split = specs.split;
424 pj->m_icontrol = specs.icontrol;
425 m_joints.push_back(pj);
429 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body)
431 appendAngularJoint(specs,m_clusters[0],body);
435 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body)
437 appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]);
441 void btSoftBody::addForce(const btVector3& force)
443 for(int i=0,ni=m_nodes.size();i<ni;++i) addForce(force,i);
447 void btSoftBody::addForce(const btVector3& force,int node)
449 Node& n=m_nodes[node];
456 void btSoftBody::addAeroForceToNode(const btVector3& windVelocity,int nodeIndex)
458 btAssert(nodeIndex >= 0 && nodeIndex < m_nodes.size());
460 const btScalar dt = m_sst.sdt;
461 const btScalar kLF = m_cfg.kLF;
462 const btScalar kDG = m_cfg.kDG;
463 //const btScalar kPR = m_cfg.kPR;
464 //const btScalar kVC = m_cfg.kVC;
465 const bool as_lift = kLF>0;
466 const bool as_drag = kDG>0;
467 const bool as_aero = as_lift || as_drag;
468 const bool as_vaero = as_aero && (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
470 Node& n = m_nodes[nodeIndex];
474 btSoftBody::sMedium medium;
476 EvaluateMedium(m_worldInfo, n.m_x, medium);
477 medium.m_velocity = windVelocity;
478 medium.m_density = m_worldInfo->air_density;
483 const btVector3 rel_v = n.m_v - medium.m_velocity;
484 const btScalar rel_v_len = rel_v.length();
485 const btScalar rel_v2 = rel_v.length2();
487 if(rel_v2>SIMD_EPSILON)
489 const btVector3 rel_v_nrm = rel_v.normalized();
490 btVector3 nrm = n.m_n;
492 if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSidedLiftDrag)
494 nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
495 btVector3 fDrag(0, 0, 0);
496 btVector3 fLift(0, 0, 0);
498 btScalar n_dot_v = nrm.dot(rel_v_nrm);
499 btScalar tri_area = 0.5f * n.m_area;
501 fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
503 // Check angle of attack
504 // cos(10º) = 0.98480
505 if ( 0 < n_dot_v && n_dot_v < 0.98480f)
506 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));
508 // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
509 btVector3 del_v_by_fDrag = fDrag*n.m_im*m_sst.sdt;
510 btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
511 btScalar v_len2 = n.m_v.length2();
513 if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
515 btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
516 btScalar v_len = n.m_v.length();
517 fDrag *= btScalar(0.8)*(v_len / del_v_by_fDrag_len);
523 else if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_Point || m_cfg.aeromodel == btSoftBody::eAeroModel::V_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided)
525 if (btSoftBody::eAeroModel::V_TwoSided)
526 nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
528 const btScalar dvn = btDot(rel_v,nrm);
532 btVector3 force(0,0,0);
533 const btScalar c0 = n.m_area * dvn * rel_v2/2;
534 const btScalar c1 = c0 * medium.m_density;
535 force += nrm*(-c1*kLF);
536 force += rel_v.normalized() * (-c1 * kDG);
537 ApplyClampedForce(n, force, dt);
545 void btSoftBody::addAeroForceToFace(const btVector3& windVelocity,int faceIndex)
547 const btScalar dt = m_sst.sdt;
548 const btScalar kLF = m_cfg.kLF;
549 const btScalar kDG = m_cfg.kDG;
550 // const btScalar kPR = m_cfg.kPR;
551 // const btScalar kVC = m_cfg.kVC;
552 const bool as_lift = kLF>0;
553 const bool as_drag = kDG>0;
554 const bool as_aero = as_lift || as_drag;
555 const bool as_faero = as_aero && (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
559 btSoftBody::Face& f=m_faces[faceIndex];
561 btSoftBody::sMedium medium;
563 const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3;
564 const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3;
565 EvaluateMedium(m_worldInfo,x,medium);
566 medium.m_velocity = windVelocity;
567 medium.m_density = m_worldInfo->air_density;
568 const btVector3 rel_v=v-medium.m_velocity;
569 const btScalar rel_v_len = rel_v.length();
570 const btScalar rel_v2=rel_v.length2();
572 if(rel_v2>SIMD_EPSILON)
574 const btVector3 rel_v_nrm = rel_v.normalized();
575 btVector3 nrm = f.m_normal;
577 if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSidedLiftDrag)
579 nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
581 btVector3 fDrag(0, 0, 0);
582 btVector3 fLift(0, 0, 0);
584 btScalar n_dot_v = nrm.dot(rel_v_nrm);
585 btScalar tri_area = 0.5f * f.m_ra;
587 fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
589 // Check angle of attack
590 // cos(10º) = 0.98480
591 if ( 0 < n_dot_v && n_dot_v < 0.98480f)
592 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));
599 if (f.m_n[j]->m_im>0)
601 // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
602 btVector3 del_v_by_fDrag = fDrag*f.m_n[j]->m_im*m_sst.sdt;
603 btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
604 btScalar v_len2 = f.m_n[j]->m_v.length2();
606 if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
608 btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
609 btScalar v_len = f.m_n[j]->m_v.length();
610 fDrag *= btScalar(0.8)*(v_len / del_v_by_fDrag_len);
613 f.m_n[j]->m_f += fDrag;
614 f.m_n[j]->m_f += fLift;
618 else if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided)
620 if (btSoftBody::eAeroModel::F_TwoSided)
621 nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
623 const btScalar dvn=btDot(rel_v,nrm);
627 btVector3 force(0,0,0);
628 const btScalar c0 = f.m_ra*dvn*rel_v2;
629 const btScalar c1 = c0*medium.m_density;
630 force += nrm*(-c1*kLF);
631 force += rel_v.normalized()*(-c1*kDG);
633 for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt);
642 void btSoftBody::addVelocity(const btVector3& velocity)
644 for(int i=0,ni=m_nodes.size();i<ni;++i) addVelocity(velocity,i);
647 /* Set velocity for the entire body */
648 void btSoftBody::setVelocity( const btVector3& velocity)
650 for(int i=0,ni=m_nodes.size();i<ni;++i)
662 void btSoftBody::addVelocity(const btVector3& velocity,int node)
664 Node& n=m_nodes[node];
672 void btSoftBody::setMass(int node,btScalar mass)
674 m_nodes[node].m_im=mass>0?1/mass:0;
679 btScalar btSoftBody::getMass(int node) const
681 return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0);
685 btScalar btSoftBody::getTotalMass() const
688 for(int i=0;i<m_nodes.size();++i)
696 void btSoftBody::setTotalMass(btScalar mass,bool fromfaces)
703 for(i=0;i<m_nodes.size();++i)
707 for(i=0;i<m_faces.size();++i)
709 const Face& f=m_faces[i];
710 const btScalar twicearea=AreaOf( f.m_n[0]->m_x,
715 f.m_n[j]->m_im+=twicearea;
718 for( i=0;i<m_nodes.size();++i)
720 m_nodes[i].m_im=1/m_nodes[i].m_im;
723 const btScalar tm=getTotalMass();
724 const btScalar itm=1/tm;
725 for( i=0;i<m_nodes.size();++i)
727 m_nodes[i].m_im/=itm*mass;
733 void btSoftBody::setTotalDensity(btScalar density)
735 setTotalMass(getVolume()*density,true);
739 void btSoftBody::setVolumeMass(btScalar mass)
741 btAlignedObjectArray<btScalar> ranks;
742 ranks.resize(m_nodes.size(),0);
745 for(i=0;i<m_nodes.size();++i)
749 for(i=0;i<m_tetras.size();++i)
751 const Tetra& t=m_tetras[i];
754 t.m_n[j]->m_im+=btFabs(t.m_rv);
755 ranks[int(t.m_n[j]-&m_nodes[0])]+=1;
758 for( i=0;i<m_nodes.size();++i)
760 if(m_nodes[i].m_im>0)
762 m_nodes[i].m_im=ranks[i]/m_nodes[i].m_im;
765 setTotalMass(mass,false);
769 void btSoftBody::setVolumeDensity(btScalar density)
772 for(int i=0;i<m_tetras.size();++i)
774 const Tetra& t=m_tetras[i];
777 volume+=btFabs(t.m_rv);
780 setVolumeMass(volume*density/6);
784 void btSoftBody::transform(const btTransform& trs)
786 const btScalar margin=getCollisionShape()->getMargin();
787 ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
789 for(int i=0,ni=m_nodes.size();i<ni;++i)
794 n.m_n=trs.getBasis()*n.m_n;
795 vol = btDbvtVolume::FromCR(n.m_x,margin);
797 m_ndbvt.update(n.m_leaf,vol);
802 m_initialWorldTransform = trs;
806 void btSoftBody::translate(const btVector3& trs)
815 void btSoftBody::rotate( const btQuaternion& rot)
824 void btSoftBody::scale(const btVector3& scl)
827 const btScalar margin=getCollisionShape()->getMargin();
828 ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
830 for(int i=0,ni=m_nodes.size();i<ni;++i)
835 vol = btDbvtVolume::FromCR(n.m_x,margin);
836 m_ndbvt.update(n.m_leaf,vol);
844 btScalar btSoftBody::getRestLengthScale()
846 return m_restLengthScale;
850 void btSoftBody::setRestLengthScale(btScalar restLengthScale)
852 for(int i=0, ni=m_links.size(); i<ni; ++i)
855 l.m_rl = l.m_rl / m_restLengthScale * restLengthScale;
856 l.m_c1 = l.m_rl*l.m_rl;
858 m_restLengthScale = restLengthScale;
860 if (getActivationState() == ISLAND_SLEEPING)
865 void btSoftBody::setPose(bool bvolume,bool bframe)
867 m_pose.m_bvolume = bvolume;
868 m_pose.m_bframe = bframe;
872 const btScalar omass=getTotalMass();
873 const btScalar kmass=omass*m_nodes.size()*1000;
874 btScalar tmass=omass;
875 m_pose.m_wgh.resize(m_nodes.size());
876 for(i=0,ni=m_nodes.size();i<ni;++i)
878 if(m_nodes[i].m_im<=0) tmass+=kmass;
880 for( i=0,ni=m_nodes.size();i<ni;++i)
883 m_pose.m_wgh[i]= n.m_im>0 ?
884 1/(m_nodes[i].m_im*tmass) :
888 const btVector3 com=evaluateCom();
889 m_pose.m_pos.resize(m_nodes.size());
890 for( i=0,ni=m_nodes.size();i<ni;++i)
892 m_pose.m_pos[i]=m_nodes[i].m_x-com;
894 m_pose.m_volume = bvolume?getVolume():0;
896 m_pose.m_rot.setIdentity();
897 m_pose.m_scl.setIdentity();
901 m_pose.m_aqq[2] = btVector3(0,0,0);
902 for( i=0,ni=m_nodes.size();i<ni;++i)
904 const btVector3& q=m_pose.m_pos[i];
905 const btVector3 mq=m_pose.m_wgh[i]*q;
906 m_pose.m_aqq[0]+=mq.x()*q;
907 m_pose.m_aqq[1]+=mq.y()*q;
908 m_pose.m_aqq[2]+=mq.z()*q;
910 m_pose.m_aqq=m_pose.m_aqq.inverse();
915 void btSoftBody::resetLinkRestLengths()
917 for(int i=0, ni=m_links.size();i<ni;++i)
919 Link& l = m_links[i];
920 l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
921 l.m_c1 = l.m_rl*l.m_rl;
926 btScalar btSoftBody::getVolume() const
933 const btVector3 org=m_nodes[0].m_x;
934 for(i=0,ni=m_faces.size();i<ni;++i)
936 const Face& f=m_faces[i];
937 vol+=btDot(f.m_n[0]->m_x-org,btCross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org));
945 int btSoftBody::clusterCount() const
947 return(m_clusters.size());
951 btVector3 btSoftBody::clusterCom(const Cluster* cluster)
953 btVector3 com(0,0,0);
954 for(int i=0,ni=cluster->m_nodes.size();i<ni;++i)
956 com+=cluster->m_nodes[i]->m_x*cluster->m_masses[i];
958 return(com*cluster->m_imass);
962 btVector3 btSoftBody::clusterCom(int cluster) const
964 return(clusterCom(m_clusters[cluster]));
968 btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos)
970 return(cluster->m_lv+btCross(cluster->m_av,rpos));
974 void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
976 const btVector3 li=cluster->m_imass*impulse;
977 const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse);
978 cluster->m_vimpulses[0]+=li;cluster->m_lv+=li;
979 cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
980 cluster->m_nvimpulses++;
984 void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
986 const btVector3 li=cluster->m_imass*impulse;
987 const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse);
988 cluster->m_dimpulses[0]+=li;
989 cluster->m_dimpulses[1]+=ai;
990 cluster->m_ndimpulses++;
994 void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse)
996 if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity);
997 if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift);
1001 void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse)
1003 const btVector3 ai=cluster->m_invwi*impulse;
1004 cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
1005 cluster->m_nvimpulses++;
1009 void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse)
1011 const btVector3 ai=cluster->m_invwi*impulse;
1012 cluster->m_dimpulses[1]+=ai;
1013 cluster->m_ndimpulses++;
1017 void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse)
1019 if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity);
1020 if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift);
1024 void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse)
1026 cluster->m_dimpulses[0]+=impulse*cluster->m_imass;
1027 cluster->m_ndimpulses++;
1032 btAlignedObjectArray<int> m_links;
1038 int btSoftBody::generateBendingConstraints(int distance,Material* mat)
1045 const int n=m_nodes.size();
1046 const unsigned inf=(~(unsigned)0)>>1;
1047 unsigned* adj=new unsigned[n*n];
1050 #define IDX(_x_,_y_) ((_y_)*n+(_x_))
1057 adj[IDX(i,j)]=adj[IDX(j,i)]=inf;
1061 adj[IDX(i,j)]=adj[IDX(j,i)]=0;
1065 for( i=0;i<m_links.size();++i)
1067 const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
1068 const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
1074 //special optimized case for distance == 2
1078 btAlignedObjectArray<NodeLinks> nodeLinks;
1081 /* Build node links */
1082 nodeLinks.resize(m_nodes.size());
1084 for( i=0;i<m_links.size();++i)
1086 const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
1087 const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
1088 if (nodeLinks[ia].m_links.findLinearSearch(ib)==nodeLinks[ia].m_links.size())
1089 nodeLinks[ia].m_links.push_back(ib);
1091 if (nodeLinks[ib].m_links.findLinearSearch(ia)==nodeLinks[ib].m_links.size())
1092 nodeLinks[ib].m_links.push_back(ia);
1094 for (int ii=0;ii<nodeLinks.size();ii++)
1098 for (int jj=0;jj<nodeLinks[ii].m_links.size();jj++)
1100 int k = nodeLinks[ii].m_links[jj];
1101 for (int kk=0;kk<nodeLinks[k].m_links.size();kk++)
1103 int j = nodeLinks[k].m_links[kk];
1106 const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
1108 if(adj[IDX(i,j)]>sum)
1110 adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
1119 ///generic Floyd's algorithm
1120 for(int k=0;k<n;++k)
1126 const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
1127 if(adj[IDX(i,j)]>sum)
1129 adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
1143 if(adj[IDX(i,j)]==(unsigned)distance)
1145 appendLink(i,j,mat);
1146 m_links[m_links.size()-1].m_bbending=1;
1158 void btSoftBody::randomizeConstraints()
1160 unsigned long seed=243703;
1161 #define NEXTRAND (seed=(1664525L*seed+1013904223L)&0xffffffff)
1164 for(i=0,ni=m_links.size();i<ni;++i)
1166 btSwap(m_links[i],m_links[NEXTRAND%ni]);
1168 for(i=0,ni=m_faces.size();i<ni;++i)
1170 btSwap(m_faces[i],m_faces[NEXTRAND%ni]);
1176 void btSoftBody::releaseCluster(int index)
1178 Cluster* c=m_clusters[index];
1179 if(c->m_leaf) m_cdbvt.remove(c->m_leaf);
1182 m_clusters.remove(c);
1186 void btSoftBody::releaseClusters()
1188 while(m_clusters.size()>0) releaseCluster(0);
1192 int btSoftBody::generateClusters(int k,int maxiterations)
1196 m_clusters.resize(btMin(k,m_nodes.size()));
1197 for(i=0;i<m_clusters.size();++i)
1199 m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
1200 m_clusters[i]->m_collide= true;
1202 k=m_clusters.size();
1206 btAlignedObjectArray<btVector3> centers;
1207 btVector3 cog(0,0,0);
1209 for(i=0;i<m_nodes.size();++i)
1211 cog+=m_nodes[i].m_x;
1212 m_clusters[(i*29873)%m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
1214 cog/=(btScalar)m_nodes.size();
1215 centers.resize(k,cog);
1217 const btScalar slope=16;
1221 const btScalar w=2-btMin<btScalar>(1,iterations/slope);
1229 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
1231 c+=m_clusters[i]->m_nodes[j]->m_x;
1233 if(m_clusters[i]->m_nodes.size())
1235 c /= (btScalar)m_clusters[i]->m_nodes.size();
1236 c = centers[i]+(c-centers[i])*w;
1237 changed |= ((c-centers[i]).length2()>SIMD_EPSILON);
1239 m_clusters[i]->m_nodes.resize(0);
1242 for(i=0;i<m_nodes.size();++i)
1244 const btVector3 nx=m_nodes[i].m_x;
1246 btScalar kdist=ClusterMetric(centers[0],nx);
1247 for(int j=1;j<k;++j)
1249 const btScalar d=ClusterMetric(centers[j],nx);
1256 m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
1258 } while(changed&&(iterations<maxiterations));
1260 btAlignedObjectArray<int> cids;
1261 cids.resize(m_nodes.size(),-1);
1262 for(i=0;i<m_clusters.size();++i)
1264 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
1266 cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i;
1269 for(i=0;i<m_faces.size();++i)
1271 const int idx[]={ int(m_faces[i].m_n[0]-&m_nodes[0]),
1272 int(m_faces[i].m_n[1]-&m_nodes[0]),
1273 int(m_faces[i].m_n[2]-&m_nodes[0])};
1274 for(int j=0;j<3;++j)
1276 const int cid=cids[idx[j]];
1277 for(int q=1;q<3;++q)
1279 const int kid=idx[(j+q)%3];
1282 if(m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size())
1284 m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
1291 if(m_clusters.size()>1)
1293 Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
1294 pmaster->m_collide = false;
1295 pmaster->m_nodes.reserve(m_nodes.size());
1296 for(int i=0;i<m_nodes.size();++i) pmaster->m_nodes.push_back(&m_nodes[i]);
1297 m_clusters.push_back(pmaster);
1298 btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]);
1301 for(i=0;i<m_clusters.size();++i)
1303 if(m_clusters[i]->m_nodes.size()==0)
1305 releaseCluster(i--);
1310 //create a cluster for each tetrahedron (if tetrahedra exist) or each face
1311 if (m_tetras.size())
1313 m_clusters.resize(m_tetras.size());
1314 for(i=0;i<m_clusters.size();++i)
1316 m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
1317 m_clusters[i]->m_collide= true;
1319 for (i=0;i<m_tetras.size();i++)
1321 for (int j=0;j<4;j++)
1323 m_clusters[i]->m_nodes.push_back(m_tetras[i].m_n[j]);
1329 m_clusters.resize(m_faces.size());
1330 for(i=0;i<m_clusters.size();++i)
1332 m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
1333 m_clusters[i]->m_collide= true;
1336 for(i=0;i<m_faces.size();++i)
1338 for(int j=0;j<3;++j)
1340 m_clusters[i]->m_nodes.push_back(m_faces[i].m_n[j]);
1346 if (m_clusters.size())
1348 initializeClusters();
1352 //for self-collision
1353 m_clusterConnectivity.resize(m_clusters.size()*m_clusters.size());
1355 for (int c0=0;c0<m_clusters.size();c0++)
1357 m_clusters[c0]->m_clusterIndex=c0;
1358 for (int c1=0;c1<m_clusters.size();c1++)
1361 bool connected=false;
1362 Cluster* cla = m_clusters[c0];
1363 Cluster* clb = m_clusters[c1];
1364 for (int i=0;!connected&&i<cla->m_nodes.size();i++)
1366 for (int j=0;j<clb->m_nodes.size();j++)
1368 if (cla->m_nodes[i] == clb->m_nodes[j])
1375 m_clusterConnectivity[c0+c1*m_clusters.size()]=connected;
1381 return(m_clusters.size());
1385 void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
1387 const Node* nbase = &m_nodes[0];
1388 int ncount = m_nodes.size();
1389 btSymMatrix<int> edges(ncount,-2);
1394 for(i=0;i<m_links.size();++i)
1399 if(!SameSign(ifn->Eval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x)))
1401 btSwap(m_links[i],m_links[m_links.size()-1]);
1402 m_links.pop_back();--i;
1407 for(i=0;i<m_links.size();++i)
1410 edges(int(l.m_n[0]-nbase),int(l.m_n[1]-nbase))=-1;
1412 for(i=0;i<m_faces.size();++i)
1415 edges(int(f.m_n[0]-nbase),int(f.m_n[1]-nbase))=-1;
1416 edges(int(f.m_n[1]-nbase),int(f.m_n[2]-nbase))=-1;
1417 edges(int(f.m_n[2]-nbase),int(f.m_n[0]-nbase))=-1;
1420 for(i=0;i<ncount;++i)
1422 for(j=i+1;j<ncount;++j)
1428 const btScalar t=ImplicitSolve(ifn,a.m_x,b.m_x,accurary);
1431 const btVector3 x=Lerp(a.m_x,b.m_x,t);
1432 const btVector3 v=Lerp(a.m_v,b.m_v,t);
1438 const btScalar ma=1/a.m_im;
1439 const btScalar mb=1/b.m_im;
1440 const btScalar mc=Lerp(ma,mb,t);
1441 const btScalar f=(ma+mb)/(ma+mb+mc);
1447 { a.m_im/=0.5f;m=1/a.m_im; }
1452 { b.m_im/=0.5f;m=1/b.m_im; }
1457 edges(i,j)=m_nodes.size()-1;
1458 m_nodes[edges(i,j)].m_v=v;
1466 for(i=0,ni=m_links.size();i<ni;++i)
1468 Link& feat=m_links[i];
1469 const int idx[]={ int(feat.m_n[0]-nbase),
1470 int(feat.m_n[1]-nbase)};
1471 if((idx[0]<ncount)&&(idx[1]<ncount))
1473 const int ni=edges(idx[0],idx[1]);
1477 Link* pft[]={ &m_links[i],
1478 &m_links[m_links.size()-1]};
1479 pft[0]->m_n[0]=&m_nodes[idx[0]];
1480 pft[0]->m_n[1]=&m_nodes[ni];
1481 pft[1]->m_n[0]=&m_nodes[ni];
1482 pft[1]->m_n[1]=&m_nodes[idx[1]];
1487 for(i=0;i<m_faces.size();++i)
1489 const Face& feat=m_faces[i];
1490 const int idx[]={ int(feat.m_n[0]-nbase),
1491 int(feat.m_n[1]-nbase),
1492 int(feat.m_n[2]-nbase)};
1493 for(j=2,k=0;k<3;j=k++)
1495 if((idx[j]<ncount)&&(idx[k]<ncount))
1497 const int ni=edges(idx[j],idx[k]);
1501 const int l=(k+1)%3;
1502 Face* pft[]={ &m_faces[i],
1503 &m_faces[m_faces.size()-1]};
1504 pft[0]->m_n[0]=&m_nodes[idx[l]];
1505 pft[0]->m_n[1]=&m_nodes[idx[j]];
1506 pft[0]->m_n[2]=&m_nodes[ni];
1507 pft[1]->m_n[0]=&m_nodes[ni];
1508 pft[1]->m_n[1]=&m_nodes[idx[k]];
1509 pft[1]->m_n[2]=&m_nodes[idx[l]];
1510 appendLink(ni,idx[l],pft[0]->m_material);
1519 btAlignedObjectArray<int> cnodes;
1520 const int pcount=ncount;
1522 ncount=m_nodes.size();
1523 cnodes.resize(ncount,0);
1525 for(i=0;i<ncount;++i)
1527 const btVector3 x=m_nodes[i].m_x;
1528 if((i>=pcount)||(btFabs(ifn->Eval(x))<accurary))
1530 const btVector3 v=m_nodes[i].m_v;
1531 btScalar m=getMass(i);
1532 if(m>0) { m*=0.5f;m_nodes[i].m_im/=0.5f; }
1534 cnodes[i]=m_nodes.size()-1;
1535 m_nodes[cnodes[i]].m_v=v;
1540 for(i=0,ni=m_links.size();i<ni;++i)
1542 const int id[]={ int(m_links[i].m_n[0]-nbase),
1543 int(m_links[i].m_n[1]-nbase)};
1545 if(cnodes[id[0]]&&cnodes[id[1]])
1548 todetach=m_links.size()-1;
1552 if(( (ifn->Eval(m_nodes[id[0]].m_x)<accurary)&&
1553 (ifn->Eval(m_nodes[id[1]].m_x)<accurary)))
1558 Link& l=m_links[todetach];
1559 for(int j=0;j<2;++j)
1561 int cn=cnodes[int(l.m_n[j]-nbase)];
1562 if(cn) l.m_n[j]=&m_nodes[cn];
1567 for(i=0,ni=m_faces.size();i<ni;++i)
1569 Node** n= m_faces[i].m_n;
1570 if( (ifn->Eval(n[0]->m_x)<accurary)&&
1571 (ifn->Eval(n[1]->m_x)<accurary)&&
1572 (ifn->Eval(n[2]->m_x)<accurary))
1574 for(int j=0;j<3;++j)
1576 int cn=cnodes[int(n[j]-nbase)];
1577 if(cn) n[j]=&m_nodes[cn];
1582 int nnodes=m_nodes.size();
1583 btAlignedObjectArray<int> ranks;
1584 btAlignedObjectArray<int> todelete;
1585 ranks.resize(nnodes,0);
1586 for(i=0,ni=m_links.size();i<ni;++i)
1588 for(int j=0;j<2;++j) ranks[int(m_links[i].m_n[j]-nbase)]++;
1590 for(i=0,ni=m_faces.size();i<ni;++i)
1592 for(int j=0;j<3;++j) ranks[int(m_faces[i].m_n[j]-nbase)]++;
1594 for(i=0;i<m_links.size();++i)
1596 const int id[]={ int(m_links[i].m_n[0]-nbase),
1597 int(m_links[i].m_n[1]-nbase)};
1598 const bool sg[]={ ranks[id[0]]==1,
1604 btSwap(m_links[i],m_links[m_links.size()-1]);
1605 m_links.pop_back();--i;
1609 for(i=nnodes-1;i>=0;--i)
1611 if(!ranks[i]) todelete.push_back(i);
1615 btAlignedObjectArray<int>& map=ranks;
1616 for(int i=0;i<nnodes;++i) map[i]=i;
1617 PointersToIndices(this);
1618 for(int i=0,ni=todelete.size();i<ni;++i)
1622 int& b=map[--nnodes];
1623 m_ndbvt.remove(m_nodes[a].m_leaf);m_nodes[a].m_leaf=0;
1624 btSwap(m_nodes[a],m_nodes[b]);
1627 IndicesToPointers(this,&map[0]);
1628 m_nodes.resize(nnodes);
1632 m_bUpdateRtCst=true;
1636 bool btSoftBody::cutLink(const Node* node0,const Node* node1,btScalar position)
1638 return(cutLink(int(node0-&m_nodes[0]),int(node1-&m_nodes[0]),position));
1642 bool btSoftBody::cutLink(int node0,int node1,btScalar position)
1646 // const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
1647 const btVector3 x=Lerp(m_nodes[node0].m_x,m_nodes[node1].m_x,position);
1648 const btVector3 v=Lerp(m_nodes[node0].m_v,m_nodes[node1].m_v,position);
1652 Node* pa=&m_nodes[node0];
1653 Node* pb=&m_nodes[node1];
1654 Node* pn[2]={ &m_nodes[m_nodes.size()-2],
1655 &m_nodes[m_nodes.size()-1]};
1658 for(i=0,ni=m_links.size();i<ni;++i)
1660 const int mtch=MatchEdge(m_links[i].m_n[0],m_links[i].m_n[1],pa,pb);
1664 Link* pft[]={&m_links[i],&m_links[m_links.size()-1]};
1665 pft[0]->m_n[1]=pn[mtch];
1666 pft[1]->m_n[0]=pn[1-mtch];
1670 for(i=0,ni=m_faces.size();i<ni;++i)
1672 for(int k=2,l=0;l<3;k=l++)
1674 const int mtch=MatchEdge(m_faces[i].m_n[k],m_faces[i].m_n[l],pa,pb);
1678 Face* pft[]={&m_faces[i],&m_faces[m_faces.size()-1]};
1679 pft[0]->m_n[l]=pn[mtch];
1680 pft[1]->m_n[k]=pn[1-mtch];
1681 appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1682 appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1688 m_ndbvt.remove(pn[0]->m_leaf);
1689 m_ndbvt.remove(pn[1]->m_leaf);
1697 bool btSoftBody::rayTest(const btVector3& rayFrom,
1698 const btVector3& rayTo,
1701 if(m_faces.size()&&m_fdbvt.empty())
1702 initializeFaceTree();
1704 results.body = this;
1705 results.fraction = 1.f;
1706 results.feature = eFeature::None;
1709 return(rayTest(rayFrom,rayTo,results.fraction,results.feature,results.index,false)!=0);
1713 void btSoftBody::setSolver(eSolverPresets::_ preset)
1715 m_cfg.m_vsequence.clear();
1716 m_cfg.m_psequence.clear();
1717 m_cfg.m_dsequence.clear();
1720 case eSolverPresets::Positions:
1721 m_cfg.m_psequence.push_back(ePSolver::Anchors);
1722 m_cfg.m_psequence.push_back(ePSolver::RContacts);
1723 m_cfg.m_psequence.push_back(ePSolver::SContacts);
1724 m_cfg.m_psequence.push_back(ePSolver::Linear);
1726 case eSolverPresets::Velocities:
1727 m_cfg.m_vsequence.push_back(eVSolver::Linear);
1729 m_cfg.m_psequence.push_back(ePSolver::Anchors);
1730 m_cfg.m_psequence.push_back(ePSolver::RContacts);
1731 m_cfg.m_psequence.push_back(ePSolver::SContacts);
1733 m_cfg.m_dsequence.push_back(ePSolver::Linear);
1739 void btSoftBody::predictMotion(btScalar dt)
1747 m_bUpdateRtCst=false;
1750 if(m_cfg.collisions&fCollision::VF_SS)
1752 initializeFaceTree();
1757 m_sst.sdt = dt*m_cfg.timescale;
1758 m_sst.isdt = 1/m_sst.sdt;
1759 m_sst.velmrg = m_sst.sdt*3;
1760 m_sst.radmrg = getCollisionShape()->getMargin();
1761 m_sst.updmrg = m_sst.radmrg*(btScalar)0.25;
1763 addVelocity(m_worldInfo->m_gravity*m_sst.sdt);
1766 for(i=0,ni=m_nodes.size();i<ni;++i)
1770 n.m_v += n.m_f*n.m_im*m_sst.sdt;
1771 n.m_x += n.m_v*m_sst.sdt;
1772 n.m_f = btVector3(0,0,0);
1779 ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
1780 for(i=0,ni=m_nodes.size();i<ni;++i)
1783 vol = btDbvtVolume::FromCR(n.m_x,m_sst.radmrg);
1784 m_ndbvt.update( n.m_leaf,
1790 if(!m_fdbvt.empty())
1792 for(int i=0;i<m_faces.size();++i)
1795 const btVector3 v=( f.m_n[0]->m_v+
1798 vol = VolumeOf(f,m_sst.radmrg);
1799 m_fdbvt.update( f.m_leaf,
1808 if(m_pose.m_bframe&&(m_cfg.kMT>0))
1810 const btMatrix3x3 posetrs=m_pose.m_rot;
1811 for(int i=0,ni=m_nodes.size();i<ni;++i)
1816 const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com;
1817 n.m_x=Lerp(n.m_x,x,m_cfg.kMT);
1821 /* Clear contacts */
1822 m_rcontacts.resize(0);
1823 m_scontacts.resize(0);
1824 /* Optimize dbvt's */
1825 m_ndbvt.optimizeIncremental(1);
1826 m_fdbvt.optimizeIncremental(1);
1827 m_cdbvt.optimizeIncremental(1);
1831 void btSoftBody::solveConstraints()
1834 /* Apply clusters */
1835 applyClusters(false);
1840 for(i=0,ni=m_links.size();i<ni;++i)
1843 l.m_c3 = l.m_n[1]->m_q-l.m_n[0]->m_q;
1844 l.m_c2 = 1/(l.m_c3.length2()*l.m_c0);
1846 /* Prepare anchors */
1847 for(i=0,ni=m_anchors.size();i<ni;++i)
1849 Anchor& a=m_anchors[i];
1850 const btVector3 ra=a.m_body->getWorldTransform().getBasis()*a.m_local;
1851 a.m_c0 = ImpulseMatrix( m_sst.sdt,
1853 a.m_body->getInvMass(),
1854 a.m_body->getInvInertiaTensorWorld(),
1857 a.m_c2 = m_sst.sdt*a.m_node->m_im;
1858 a.m_body->activate();
1860 /* Solve velocities */
1861 if(m_cfg.viterations>0)
1864 for(int isolve=0;isolve<m_cfg.viterations;++isolve)
1866 for(int iseq=0;iseq<m_cfg.m_vsequence.size();++iseq)
1868 getSolver(m_cfg.m_vsequence[iseq])(this,1);
1872 for(i=0,ni=m_nodes.size();i<ni;++i)
1875 n.m_x = n.m_q+n.m_v*m_sst.sdt;
1878 /* Solve positions */
1879 if(m_cfg.piterations>0)
1881 for(int isolve=0;isolve<m_cfg.piterations;++isolve)
1883 const btScalar ti=isolve/(btScalar)m_cfg.piterations;
1884 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1886 getSolver(m_cfg.m_psequence[iseq])(this,1,ti);
1889 const btScalar vc=m_sst.isdt*(1-m_cfg.kDP);
1890 for(i=0,ni=m_nodes.size();i<ni;++i)
1893 n.m_v = (n.m_x-n.m_q)*vc;
1894 n.m_f = btVector3(0,0,0);
1898 if(m_cfg.diterations>0)
1900 const btScalar vcf=m_cfg.kVCF*m_sst.isdt;
1901 for(i=0,ni=m_nodes.size();i<ni;++i)
1906 for(int idrift=0;idrift<m_cfg.diterations;++idrift)
1908 for(int iseq=0;iseq<m_cfg.m_dsequence.size();++iseq)
1910 getSolver(m_cfg.m_dsequence[iseq])(this,1,0);
1913 for(int i=0,ni=m_nodes.size();i<ni;++i)
1916 n.m_v += (n.m_x-n.m_q)*vcf;
1919 /* Apply clusters */
1921 applyClusters(true);
1925 void btSoftBody::staticSolve(int iterations)
1927 for(int isolve=0;isolve<iterations;++isolve)
1929 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1931 getSolver(m_cfg.m_psequence[iseq])(this,1,0);
1937 void btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/,int /*count*/,int /*iterations*/)
1943 void btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
1945 const int nb=bodies.size();
1951 iterations=btMax(iterations,bodies[i]->m_cfg.citerations);
1955 bodies[i]->prepareClusters(iterations);
1957 for(i=0;i<iterations;++i)
1959 const btScalar sor=1;
1960 for(int j=0;j<nb;++j)
1962 bodies[j]->solveClusters(sor);
1967 bodies[i]->cleanupClusters();
1972 void btSoftBody::integrateMotion()
1979 btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt)
1981 m_rayFrom = rayFrom;
1982 m_rayNormalizedDirection = (rayTo-rayFrom);
1990 void btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf)
1992 btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data;
1993 const btScalar t=rayFromToTriangle( m_rayFrom,m_rayTo,m_rayNormalizedDirection,
1998 if((t>0)&&(t<m_mint))
2006 btScalar btSoftBody::RayFromToCaster::rayFromToTriangle( const btVector3& rayFrom,
2007 const btVector3& rayTo,
2008 const btVector3& rayNormalizedDirection,
2014 static const btScalar ceps=-SIMD_EPSILON*10;
2015 static const btScalar teps=SIMD_EPSILON*10;
2017 const btVector3 n=btCross(b-a,c-a);
2018 const btScalar d=btDot(a,n);
2019 const btScalar den=btDot(rayNormalizedDirection,n);
2020 if(!btFuzzyZero(den))
2022 const btScalar num=btDot(rayFrom,n)-d;
2023 const btScalar t=-num/den;
2024 if((t>teps)&&(t<maxt))
2026 const btVector3 hit=rayFrom+rayNormalizedDirection*t;
2027 if( (btDot(n,btCross(a-hit,b-hit))>ceps) &&
2028 (btDot(n,btCross(b-hit,c-hit))>ceps) &&
2029 (btDot(n,btCross(c-hit,a-hit))>ceps))
2039 void btSoftBody::pointersToIndices()
2041 #define PTR2IDX(_p_,_b_) reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_))
2042 btSoftBody::Node* base=m_nodes.size() ? &m_nodes[0] : 0;
2045 for(i=0,ni=m_nodes.size();i<ni;++i)
2047 if(m_nodes[i].m_leaf)
2049 m_nodes[i].m_leaf->data=*(void**)&i;
2052 for(i=0,ni=m_links.size();i<ni;++i)
2054 m_links[i].m_n[0]=PTR2IDX(m_links[i].m_n[0],base);
2055 m_links[i].m_n[1]=PTR2IDX(m_links[i].m_n[1],base);
2057 for(i=0,ni=m_faces.size();i<ni;++i)
2059 m_faces[i].m_n[0]=PTR2IDX(m_faces[i].m_n[0],base);
2060 m_faces[i].m_n[1]=PTR2IDX(m_faces[i].m_n[1],base);
2061 m_faces[i].m_n[2]=PTR2IDX(m_faces[i].m_n[2],base);
2062 if(m_faces[i].m_leaf)
2064 m_faces[i].m_leaf->data=*(void**)&i;
2067 for(i=0,ni=m_anchors.size();i<ni;++i)
2069 m_anchors[i].m_node=PTR2IDX(m_anchors[i].m_node,base);
2071 for(i=0,ni=m_notes.size();i<ni;++i)
2073 for(int j=0;j<m_notes[i].m_rank;++j)
2075 m_notes[i].m_nodes[j]=PTR2IDX(m_notes[i].m_nodes[j],base);
2082 void btSoftBody::indicesToPointers(const int* map)
2084 #define IDX2PTR(_p_,_b_) map?(&(_b_)[map[(((char*)_p_)-(char*)0)]]): \
2085 (&(_b_)[(((char*)_p_)-(char*)0)])
2086 btSoftBody::Node* base=m_nodes.size() ? &m_nodes[0]:0;
2089 for(i=0,ni=m_nodes.size();i<ni;++i)
2091 if(m_nodes[i].m_leaf)
2093 m_nodes[i].m_leaf->data=&m_nodes[i];
2096 for(i=0,ni=m_links.size();i<ni;++i)
2098 m_links[i].m_n[0]=IDX2PTR(m_links[i].m_n[0],base);
2099 m_links[i].m_n[1]=IDX2PTR(m_links[i].m_n[1],base);
2101 for(i=0,ni=m_faces.size();i<ni;++i)
2103 m_faces[i].m_n[0]=IDX2PTR(m_faces[i].m_n[0],base);
2104 m_faces[i].m_n[1]=IDX2PTR(m_faces[i].m_n[1],base);
2105 m_faces[i].m_n[2]=IDX2PTR(m_faces[i].m_n[2],base);
2106 if(m_faces[i].m_leaf)
2108 m_faces[i].m_leaf->data=&m_faces[i];
2111 for(i=0,ni=m_anchors.size();i<ni;++i)
2113 m_anchors[i].m_node=IDX2PTR(m_anchors[i].m_node,base);
2115 for(i=0,ni=m_notes.size();i<ni;++i)
2117 for(int j=0;j<m_notes[i].m_rank;++j)
2119 m_notes[i].m_nodes[j]=IDX2PTR(m_notes[i].m_nodes[j],base);
2126 int btSoftBody::rayTest(const btVector3& rayFrom,const btVector3& rayTo,
2127 btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const
2130 btVector3 dir = rayTo-rayFrom;
2133 if(bcountonly||m_fdbvt.empty())
2136 for(int i=0,ni=m_faces.size();i<ni;++i)
2138 const btSoftBody::Face& f=m_faces[i];
2140 const btScalar t=RayFromToCaster::rayFromToTriangle( rayFrom,rayTo,dir,
2150 feature=btSoftBody::eFeature::Face;
2159 RayFromToCaster collider(rayFrom,rayTo,mint);
2161 btDbvt::rayTest(m_fdbvt.m_root,rayFrom,rayTo,collider);
2164 mint=collider.m_mint;
2165 feature=btSoftBody::eFeature::Face;
2166 index=(int)(collider.m_face-&m_faces[0]);
2171 for (int i=0;i<m_tetras.size();i++)
2173 const btSoftBody::Tetra& tet = m_tetras[i];
2174 int tetfaces[4][3] = {{0,1,2},{0,1,3},{1,2,3},{0,2,3}};
2175 for (int f=0;f<4;f++)
2178 int index0=tetfaces[f][0];
2179 int index1=tetfaces[f][1];
2180 int index2=tetfaces[f][2];
2181 btVector3 v0=tet.m_n[index0]->m_x;
2182 btVector3 v1=tet.m_n[index1]->m_x;
2183 btVector3 v2=tet.m_n[index2]->m_x;
2186 const btScalar t=RayFromToCaster::rayFromToTriangle( rayFrom,rayTo,dir,
2194 feature=btSoftBody::eFeature::Tetra;
2205 void btSoftBody::initializeFaceTree()
2208 for(int i=0;i<m_faces.size();++i)
2211 f.m_leaf=m_fdbvt.insert(VolumeOf(f,0),&f);
2216 btVector3 btSoftBody::evaluateCom() const
2218 btVector3 com(0,0,0);
2221 for(int i=0,ni=m_nodes.size();i<ni;++i)
2223 com+=m_nodes[i].m_x*m_pose.m_wgh[i];
2230 bool btSoftBody::checkContact( const btCollisionObjectWrapper* colObjWrap,
2233 btSoftBody::sCti& cti) const
2236 const btCollisionShape *shp = colObjWrap->getCollisionShape();
2237 // const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject());
2238 //const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform();
2239 const btTransform &wtr = colObjWrap->getWorldTransform();
2240 //todo: check which transform is needed here
2243 m_worldInfo->m_sparsesdf.Evaluate(
2250 cti.m_colObj = colObjWrap->getCollisionObject();
2251 cti.m_normal = wtr.getBasis()*nrm;
2252 cti.m_offset = -btDot( cti.m_normal, x - cti.m_normal * dst );
2259 void btSoftBody::updateNormals()
2262 const btVector3 zv(0,0,0);
2265 for(i=0,ni=m_nodes.size();i<ni;++i)
2269 for(i=0,ni=m_faces.size();i<ni;++i)
2271 btSoftBody::Face& f=m_faces[i];
2272 const btVector3 n=btCross(f.m_n[1]->m_x-f.m_n[0]->m_x,
2273 f.m_n[2]->m_x-f.m_n[0]->m_x);
2274 f.m_normal=n.normalized();
2279 for(i=0,ni=m_nodes.size();i<ni;++i)
2281 btScalar len = m_nodes[i].m_n.length();
2282 if (len>SIMD_EPSILON)
2283 m_nodes[i].m_n /= len;
2288 void btSoftBody::updateBounds()
2290 /*if( m_acceleratedSoftBody )
2292 // If we have an accelerated softbody we need to obtain the bounds correctly
2293 // For now (slightly hackily) just have a very large AABB
2294 // TODO: Write get bounds kernel
2295 // If that is updating in place, atomic collisions might be low (when the cloth isn't perfectly aligned to an axis) and we could
2296 // probably do a test and exchange reasonably efficiently.
2298 m_bounds[0] = btVector3(-1000, -1000, -1000);
2299 m_bounds[1] = btVector3(1000, 1000, 1000);
2304 const btVector3& mins=m_ndbvt.m_root->volume.Mins();
2305 const btVector3& maxs=m_ndbvt.m_root->volume.Maxs();
2306 const btScalar csm=getCollisionShape()->getMargin();
2307 const btVector3 mrg=btVector3( csm,
2309 csm)*1; // ??? to investigate...
2310 m_bounds[0]=mins-mrg;
2311 m_bounds[1]=maxs+mrg;
2312 if(0!=getBroadphaseHandle())
2314 m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(),
2317 m_worldInfo->m_dispatcher);
2323 m_bounds[1]=btVector3(0,0,0);
2330 void btSoftBody::updatePose()
2334 btSoftBody::Pose& pose=m_pose;
2335 const btVector3 com=evaluateCom();
2340 const btScalar eps=SIMD_EPSILON;
2341 Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0);
2342 Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3);
2343 for(int i=0,ni=m_nodes.size();i<ni;++i)
2345 const btVector3 a=pose.m_wgh[i]*(m_nodes[i].m_x-com);
2346 const btVector3& b=pose.m_pos[i];
2352 PolarDecompose(Apq,r,s);
2354 pose.m_scl=pose.m_aqq*r.transpose()*Apq;
2355 if(m_cfg.maxvolume>1)
2357 const btScalar idet=Clamp<btScalar>( 1/pose.m_scl.determinant(),
2359 pose.m_scl=Mul(pose.m_scl,idet);
2366 void btSoftBody::updateArea(bool averageArea)
2371 for(i=0,ni=m_faces.size();i<ni;++i)
2374 f.m_ra = AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
2381 btAlignedObjectArray<int> counts;
2382 counts.resize(m_nodes.size(),0);
2383 for(i=0,ni=m_nodes.size();i<ni;++i)
2385 m_nodes[i].m_area = 0;
2387 for(i=0,ni=m_faces.size();i<ni;++i)
2389 btSoftBody::Face& f=m_faces[i];
2390 for(int j=0;j<3;++j)
2392 const int index=(int)(f.m_n[j]-&m_nodes[0]);
2394 f.m_n[j]->m_area+=btFabs(f.m_ra);
2397 for(i=0,ni=m_nodes.size();i<ni;++i)
2400 m_nodes[i].m_area/=(btScalar)counts[i];
2402 m_nodes[i].m_area=0;
2407 // initialize node area as zero
2408 for(i=0,ni=m_nodes.size();i<ni;++i)
2410 m_nodes[i].m_area=0;
2413 for(i=0,ni=m_faces.size();i<ni;++i)
2415 btSoftBody::Face& f=m_faces[i];
2417 for(int j=0;j<3;++j)
2419 f.m_n[j]->m_area += f.m_ra;
2423 for(i=0,ni=m_nodes.size();i<ni;++i)
2425 m_nodes[i].m_area *= 0.3333333f;
2431 void btSoftBody::updateLinkConstants()
2436 for(i=0,ni=m_links.size();i<ni;++i)
2439 Material& m=*l.m_material;
2440 l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST;
2444 void btSoftBody::updateConstants()
2446 resetLinkRestLengths();
2447 updateLinkConstants();
2454 void btSoftBody::initializeClusters()
2458 for( i=0;i<m_clusters.size();++i)
2460 Cluster& c=*m_clusters[i];
2462 c.m_masses.resize(c.m_nodes.size());
2463 for(int j=0;j<c.m_nodes.size();++j)
2465 if (c.m_nodes[j]->m_im==0)
2467 c.m_containsAnchor = true;
2468 c.m_masses[j] = BT_LARGE_FLOAT;
2471 c.m_masses[j] = btScalar(1.)/c.m_nodes[j]->m_im;
2473 c.m_imass += c.m_masses[j];
2475 c.m_imass = btScalar(1.)/c.m_imass;
2476 c.m_com = btSoftBody::clusterCom(&c);
2477 c.m_lv = btVector3(0,0,0);
2478 c.m_av = btVector3(0,0,0);
2481 btMatrix3x3& ii=c.m_locii;
2482 ii[0]=ii[1]=ii[2]=btVector3(0,0,0);
2486 for(i=0,ni=c.m_nodes.size();i<ni;++i)
2488 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
2489 const btVector3 q=k*k;
2490 const btScalar m=c.m_masses[i];
2491 ii[0][0] += m*(q[1]+q[2]);
2492 ii[1][1] += m*(q[0]+q[2]);
2493 ii[2][2] += m*(q[0]+q[1]);
2494 ii[0][1] -= m*k[0]*k[1];
2495 ii[0][2] -= m*k[0]*k[2];
2496 ii[1][2] -= m*k[1]*k[2];
2506 c.m_framexform.setIdentity();
2507 c.m_framexform.setOrigin(c.m_com);
2508 c.m_framerefs.resize(c.m_nodes.size());
2511 for(i=0;i<c.m_framerefs.size();++i)
2513 c.m_framerefs[i]=c.m_nodes[i]->m_x-c.m_com;
2520 void btSoftBody::updateClusters()
2522 BT_PROFILE("UpdateClusters");
2525 for(i=0;i<m_clusters.size();++i)
2527 btSoftBody::Cluster& c=*m_clusters[i];
2528 const int n=c.m_nodes.size();
2529 //const btScalar invn=1/(btScalar)n;
2533 const btScalar eps=btScalar(0.0001);
2535 m[0]=m[1]=m[2]=btVector3(0,0,0);
2539 c.m_com=clusterCom(&c);
2540 for(int i=0;i<c.m_nodes.size();++i)
2542 const btVector3 a=c.m_nodes[i]->m_x-c.m_com;
2543 const btVector3& b=c.m_framerefs[i];
2544 m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b;
2546 PolarDecompose(m,r,s);
2547 c.m_framexform.setOrigin(c.m_com);
2548 c.m_framexform.setBasis(r);
2551 c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose();
2554 const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass);
2555 const btVector3 inertia(rk,rk,rk);
2556 const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
2557 btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0,
2558 btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
2560 c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
2562 c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0);
2563 for(int i=0;i<n;++i)
2565 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
2566 const btVector3 q=k*k;
2567 const btScalar m=1/c.m_nodes[i]->m_im;
2568 c.m_invwi[0][0] += m*(q[1]+q[2]);
2569 c.m_invwi[1][1] += m*(q[0]+q[2]);
2570 c.m_invwi[2][2] += m*(q[0]+q[1]);
2571 c.m_invwi[0][1] -= m*k[0]*k[1];
2572 c.m_invwi[0][2] -= m*k[0]*k[2];
2573 c.m_invwi[1][2] -= m*k[1]*k[2];
2575 c.m_invwi[1][0]=c.m_invwi[0][1];
2576 c.m_invwi[2][0]=c.m_invwi[0][2];
2577 c.m_invwi[2][1]=c.m_invwi[1][2];
2578 c.m_invwi=c.m_invwi.inverse();
2582 c.m_lv=btVector3(0,0,0);
2583 c.m_av=btVector3(0,0,0);
2589 const btVector3 v=c.m_nodes[i]->m_v*c.m_masses[i];
2591 c.m_av += btCross(c.m_nodes[i]->m_x-c.m_com,v);
2594 c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping);
2595 c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping);
2597 c.m_vimpulses[1] = btVector3(0,0,0);
2599 c.m_dimpulses[1] = btVector3(0,0,0);
2605 for(int j=0;j<c.m_nodes.size();++j)
2607 Node& n=*c.m_nodes[j];
2608 const btVector3 x=c.m_framexform*c.m_framerefs[j];
2609 n.m_x=Lerp(n.m_x,x,c.m_matching);
2615 btVector3 mi=c.m_nodes[0]->m_x;
2617 for(int j=1;j<n;++j)
2619 mi.setMin(c.m_nodes[j]->m_x);
2620 mx.setMax(c.m_nodes[j]->m_x);
2622 ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx);
2624 m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg);
2626 c.m_leaf=m_cdbvt.insert(bounds,&c);
2638 void btSoftBody::cleanupClusters()
2640 for(int i=0;i<m_joints.size();++i)
2642 m_joints[i]->Terminate(m_sst.sdt);
2643 if(m_joints[i]->m_delete)
2645 btAlignedFree(m_joints[i]);
2646 m_joints.remove(m_joints[i--]);
2652 void btSoftBody::prepareClusters(int iterations)
2654 for(int i=0;i<m_joints.size();++i)
2656 m_joints[i]->Prepare(m_sst.sdt,iterations);
2662 void btSoftBody::solveClusters(btScalar sor)
2664 for(int i=0,ni=m_joints.size();i<ni;++i)
2666 m_joints[i]->Solve(m_sst.sdt,sor);
2671 void btSoftBody::applyClusters(bool drift)
2673 BT_PROFILE("ApplyClusters");
2674 // const btScalar f0=m_sst.sdt;
2675 //const btScalar f1=f0/2;
2676 btAlignedObjectArray<btVector3> deltas;
2677 btAlignedObjectArray<btScalar> weights;
2678 deltas.resize(m_nodes.size(),btVector3(0,0,0));
2679 weights.resize(m_nodes.size(),0);
2684 for(i=0;i<m_clusters.size();++i)
2686 Cluster& c=*m_clusters[i];
2689 c.m_dimpulses[0]/=(btScalar)c.m_ndimpulses;
2690 c.m_dimpulses[1]/=(btScalar)c.m_ndimpulses;
2695 for(i=0;i<m_clusters.size();++i)
2697 Cluster& c=*m_clusters[i];
2698 if(0<(drift?c.m_ndimpulses:c.m_nvimpulses))
2700 const btVector3 v=(drift?c.m_dimpulses[0]:c.m_vimpulses[0])*m_sst.sdt;
2701 const btVector3 w=(drift?c.m_dimpulses[1]:c.m_vimpulses[1])*m_sst.sdt;
2702 for(int j=0;j<c.m_nodes.size();++j)
2704 const int idx=int(c.m_nodes[j]-&m_nodes[0]);
2705 const btVector3& x=c.m_nodes[j]->m_x;
2706 const btScalar q=c.m_masses[j];
2707 deltas[idx] += (v+btCross(w,x-c.m_com))*q;
2712 for(i=0;i<deltas.size();++i)
2716 m_nodes[i].m_x+=deltas[i]/weights[i];
2722 void btSoftBody::dampClusters()
2726 for(i=0;i<m_clusters.size();++i)
2728 Cluster& c=*m_clusters[i];
2731 for(int j=0;j<c.m_nodes.size();++j)
2733 Node& n=*c.m_nodes[j];
2736 const btVector3 vx=c.m_lv+btCross(c.m_av,c.m_nodes[j]->m_q-c.m_com);
2737 if(vx.length2()<=n.m_v.length2())
2739 n.m_v += c.m_ndamping*(vx-n.m_v);
2748 void btSoftBody::Joint::Prepare(btScalar dt,int)
2750 m_bodies[0].activate();
2751 m_bodies[1].activate();
2755 void btSoftBody::LJoint::Prepare(btScalar dt,int iterations)
2757 static const btScalar maxdrift=4;
2758 Joint::Prepare(dt,iterations);
2759 m_rpos[0] = m_bodies[0].xform()*m_refs[0];
2760 m_rpos[1] = m_bodies[1].xform()*m_refs[1];
2761 m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt;
2762 m_rpos[0] -= m_bodies[0].xform().getOrigin();
2763 m_rpos[1] -= m_bodies[1].xform().getOrigin();
2764 m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0],
2765 m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]);
2768 m_sdrift = m_massmatrix*(m_drift*m_split);
2769 m_drift *= 1-m_split;
2771 m_drift /=(btScalar)iterations;
2775 void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor)
2777 const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
2778 const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
2779 const btVector3 vr=va-vb;
2780 btSoftBody::Impulse impulse;
2781 impulse.m_asVelocity = 1;
2782 impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor;
2783 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2784 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2788 void btSoftBody::LJoint::Terminate(btScalar dt)
2792 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2793 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2798 void btSoftBody::AJoint::Prepare(btScalar dt,int iterations)
2800 static const btScalar maxdrift=SIMD_PI/16;
2801 m_icontrol->Prepare(this);
2802 Joint::Prepare(dt,iterations);
2803 m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0];
2804 m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1];
2805 m_drift = NormalizeAny(btCross(m_axis[1],m_axis[0]));
2806 m_drift *= btMin(maxdrift,btAcos(Clamp<btScalar>(btDot(m_axis[0],m_axis[1]),-1,+1)));
2807 m_drift *= m_erp/dt;
2808 m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia());
2811 m_sdrift = m_massmatrix*(m_drift*m_split);
2812 m_drift *= 1-m_split;
2814 m_drift /=(btScalar)iterations;
2818 void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor)
2820 const btVector3 va=m_bodies[0].angularVelocity();
2821 const btVector3 vb=m_bodies[1].angularVelocity();
2822 const btVector3 vr=va-vb;
2823 const btScalar sp=btDot(vr,m_axis[0]);
2824 const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp);
2825 btSoftBody::Impulse impulse;
2826 impulse.m_asVelocity = 1;
2827 impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor;
2828 m_bodies[0].applyAImpulse(-impulse);
2829 m_bodies[1].applyAImpulse( impulse);
2833 void btSoftBody::AJoint::Terminate(btScalar dt)
2837 m_bodies[0].applyDAImpulse(-m_sdrift);
2838 m_bodies[1].applyDAImpulse( m_sdrift);
2843 void btSoftBody::CJoint::Prepare(btScalar dt,int iterations)
2845 Joint::Prepare(dt,iterations);
2846 const bool dodrift=(m_life==0);
2847 m_delete=(++m_life)>m_maxlife;
2850 m_drift=m_drift*m_erp/dt;
2853 m_sdrift = m_massmatrix*(m_drift*m_split);
2854 m_drift *= 1-m_split;
2856 m_drift/=(btScalar)iterations;
2860 m_drift=m_sdrift=btVector3(0,0,0);
2865 void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor)
2867 const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
2868 const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
2869 const btVector3 vrel=va-vb;
2870 const btScalar rvac=btDot(vrel,m_normal);
2871 btSoftBody::Impulse impulse;
2872 impulse.m_asVelocity = 1;
2873 impulse.m_velocity = m_drift;
2876 const btVector3 iv=m_normal*rvac;
2877 const btVector3 fv=vrel-iv;
2878 impulse.m_velocity += iv+fv*m_friction;
2880 impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor;
2882 if (m_bodies[0].m_soft==m_bodies[1].m_soft)
2884 if ((impulse.m_velocity.getX() ==impulse.m_velocity.getX())&&(impulse.m_velocity.getY() ==impulse.m_velocity.getY())&&
2885 (impulse.m_velocity.getZ() ==impulse.m_velocity.getZ()))
2887 if (impulse.m_asVelocity)
2889 if (impulse.m_velocity.length() <m_bodies[0].m_soft->m_maxSelfCollisionImpulse)
2894 m_bodies[0].applyImpulse(-impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[0]);
2895 m_bodies[1].applyImpulse( impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[1]);
2901 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2902 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2907 void btSoftBody::CJoint::Terminate(btScalar dt)
2911 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2912 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2917 void btSoftBody::applyForces()
2920 BT_PROFILE("SoftBody applyForces");
2921 // const btScalar dt = m_sst.sdt;
2922 const btScalar kLF = m_cfg.kLF;
2923 const btScalar kDG = m_cfg.kDG;
2924 const btScalar kPR = m_cfg.kPR;
2925 const btScalar kVC = m_cfg.kVC;
2926 const bool as_lift = kLF>0;
2927 const bool as_drag = kDG>0;
2928 const bool as_pressure = kPR!=0;
2929 const bool as_volume = kVC>0;
2930 const bool as_aero = as_lift ||
2932 //const bool as_vaero = as_aero &&
2933 // (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
2934 //const bool as_faero = as_aero &&
2935 // (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
2936 const bool use_medium = as_aero;
2937 const bool use_volume = as_pressure ||
2939 btScalar volume = 0;
2940 btScalar ivolumetp = 0;
2941 btScalar dvolumetv = 0;
2942 btSoftBody::sMedium medium;
2945 volume = getVolume();
2946 ivolumetp = 1/btFabs(volume)*kPR;
2947 dvolumetv = (m_pose.m_volume-volume)*kVC;
2949 /* Per vertex forces */
2952 for(i=0,ni=m_nodes.size();i<ni;++i)
2954 btSoftBody::Node& n=m_nodes[i];
2960 addAeroForceToNode(m_windVelocity, i);
2965 n.m_f += n.m_n*(n.m_area*ivolumetp);
2970 n.m_f += n.m_n*(n.m_area*dvolumetv);
2975 /* Per face forces */
2976 for(i=0,ni=m_faces.size();i<ni;++i)
2978 // btSoftBody::Face& f=m_faces[i];
2981 addAeroForceToFace(m_windVelocity, i);
2986 void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti)
2988 const btScalar kAHR=psb->m_cfg.kAHR*kst;
2989 const btScalar dt=psb->m_sst.sdt;
2990 for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
2992 const Anchor& a=psb->m_anchors[i];
2993 const btTransform& t=a.m_body->getWorldTransform();
2995 const btVector3 wa=t*a.m_local;
2996 const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt;
2997 const btVector3 vb=n.m_x-n.m_q;
2998 const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR;
2999 const btVector3 impulse=a.m_c0*vr*a.m_influence;
3000 n.m_x+=impulse*a.m_c2;
3001 a.m_body->applyImpulse(-impulse,a.m_c1);
3006 void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti)
3008 const btScalar dt = psb->m_sst.sdt;
3009 const btScalar mrg = psb->getCollisionShape()->getMargin();
3010 for(int i=0,ni=psb->m_rcontacts.size();i<ni;++i)
3012 const RContact& c = psb->m_rcontacts[i];
3013 const sCti& cti = c.m_cti;
3014 btRigidBody* tmpRigid = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
3016 const btVector3 va = tmpRigid ? tmpRigid->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0);
3017 const btVector3 vb = c.m_node->m_x-c.m_node->m_q;
3018 const btVector3 vr = vb-va;
3019 const btScalar dn = btDot(vr, cti.m_normal);
3020 if(dn<=SIMD_EPSILON)
3022 const btScalar dp = btMin( (btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg );
3023 const btVector3 fv = vr - (cti.m_normal * dn);
3024 // c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient
3025 const btVector3 impulse = c.m_c0 * ( (vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst );
3026 c.m_node->m_x -= impulse * c.m_c2;
3028 tmpRigid->applyImpulse(impulse,c.m_c1);
3034 void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti)
3036 for(int i=0,ni=psb->m_scontacts.size();i<ni;++i)
3038 const SContact& c=psb->m_scontacts[i];
3039 const btVector3& nr=c.m_normal;
3042 const btVector3 p=BaryEval( f.m_n[0]->m_x,
3046 const btVector3 q=BaryEval( f.m_n[0]->m_q,
3050 const btVector3 vr=(n.m_x-n.m_q)-(p-q);
3051 btVector3 corr(0,0,0);
3052 btScalar dot = btDot(vr,nr);
3055 const btScalar j=c.m_margin-(btDot(nr,n.m_x)-btDot(nr,p));
3058 corr -= ProjectOnPlane(vr,nr)*c.m_friction;
3059 n.m_x += corr*c.m_cfm[0];
3060 f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x());
3061 f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y());
3062 f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z());
3067 void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti)
3069 for(int i=0,ni=psb->m_links.size();i<ni;++i)
3071 Link& l=psb->m_links[i];
3076 const btVector3 del=b.m_x-a.m_x;
3077 const btScalar len=del.length2();
3078 if (l.m_c1+len > SIMD_EPSILON)
3080 const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst;
3081 a.m_x-=del*(k*a.m_im);
3082 b.m_x+=del*(k*b.m_im);
3089 void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst)
3091 for(int i=0,ni=psb->m_links.size();i<ni;++i)
3093 Link& l=psb->m_links[i];
3095 const btScalar j=-btDot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst;
3096 n[0]->m_v+= l.m_c3*(j*n[0]->m_im);
3097 n[1]->m_v-= l.m_c3*(j*n[1]->m_im);
3102 btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver)
3106 case ePSolver::Anchors:
3107 return(&btSoftBody::PSolve_Anchors);
3108 case ePSolver::Linear:
3109 return(&btSoftBody::PSolve_Links);
3110 case ePSolver::RContacts:
3111 return(&btSoftBody::PSolve_RContacts);
3112 case ePSolver::SContacts:
3113 return(&btSoftBody::PSolve_SContacts);
3122 btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
3126 case eVSolver::Linear: return(&btSoftBody::VSolve_Links);
3135 void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap)
3138 switch(m_cfg.collisions&fCollision::RVSmask)
3140 case fCollision::SDF_RS:
3142 btSoftColliders::CollideSDF_RS docollide;
3143 btRigidBody* prb1=(btRigidBody*) btRigidBody::upcast(pcoWrap->getCollisionObject());
3144 btTransform wtr=pcoWrap->getWorldTransform();
3146 const btTransform ctr=pcoWrap->getWorldTransform();
3147 const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length();
3148 const btScalar basemargin=getCollisionShape()->getMargin();
3151 ATTRIBUTE_ALIGNED16(btDbvtVolume) volume;
3152 pcoWrap->getCollisionShape()->getAabb( pcoWrap->getWorldTransform(),
3155 volume=btDbvtVolume::FromMM(mins,maxs);
3156 volume.Expand(btVector3(basemargin,basemargin,basemargin));
3157 docollide.psb = this;
3158 docollide.m_colObj1Wrap = pcoWrap;
3159 docollide.m_rigidBody = prb1;
3161 docollide.dynmargin = basemargin+timemargin;
3162 docollide.stamargin = basemargin;
3163 m_ndbvt.collideTV(m_ndbvt.m_root,volume,docollide);
3166 case fCollision::CL_RS:
3168 btSoftColliders::CollideCL_RS collider;
3169 collider.ProcessColObj(this,pcoWrap);
3176 void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
3178 const int cf=m_cfg.collisions&psb->m_cfg.collisions;
3179 switch(cf&fCollision::SVSmask)
3181 case fCollision::CL_SS:
3184 //support self-collision if CL_SELF flag set
3185 if (this!=psb || psb->m_cfg.collisions&fCollision::CL_SELF)
3187 btSoftColliders::CollideCL_SS docollide;
3188 docollide.ProcessSoftSoft(this,psb);
3193 case fCollision::VF_SS:
3195 //only self-collision for Cluster, not Vertex-Face yet
3198 btSoftColliders::CollideVF_SS docollide;
3200 docollide.mrg= getCollisionShape()->getMargin()+
3201 psb->getCollisionShape()->getMargin();
3202 /* psb0 nodes vs psb1 faces */
3203 docollide.psb[0]=this;
3204 docollide.psb[1]=psb;
3205 docollide.psb[0]->m_ndbvt.collideTT( docollide.psb[0]->m_ndbvt.m_root,
3206 docollide.psb[1]->m_fdbvt.m_root,
3208 /* psb1 nodes vs psb0 faces */
3209 docollide.psb[0]=psb;
3210 docollide.psb[1]=this;
3211 docollide.psb[0]->m_ndbvt.collideTT( docollide.psb[0]->m_ndbvt.m_root,
3212 docollide.psb[1]->m_fdbvt.m_root,
3226 void btSoftBody::setWindVelocity( const btVector3 &velocity )
3228 m_windVelocity = velocity;
3232 const btVector3& btSoftBody::getWindVelocity()
3234 return m_windVelocity;
3239 int btSoftBody::calculateSerializeBufferSize() const
3241 int sz = sizeof(btSoftBodyData);
3245 ///fills the dataBuffer and returns the struct name (and 0 on failure)
3246 const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializer) const
3248 btSoftBodyData* sbd = (btSoftBodyData*) dataBuffer;
3250 btCollisionObject::serialize(&sbd->m_collisionObjectData, serializer);
3252 btHashMap<btHashPtr,int> m_nodeIndexMap;
3254 sbd->m_numMaterials = m_materials.size();
3255 sbd->m_materials = sbd->m_numMaterials? (SoftBodyMaterialData**) serializer->getUniquePointer((void*)&m_materials): 0;
3257 if (sbd->m_materials)
3259 int sz = sizeof(SoftBodyMaterialData*);
3260 int numElem = sbd->m_numMaterials;
3261 btChunk* chunk = serializer->allocate(sz,numElem);
3262 //SoftBodyMaterialData** memPtr = chunk->m_oldPtr;
3263 SoftBodyMaterialData** memPtr = (SoftBodyMaterialData**)chunk->m_oldPtr;
3264 for (int i=0;i<numElem;i++,memPtr++)
3266 btSoftBody::Material* mat = m_materials[i];
3267 *memPtr = mat ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)mat) : 0;
3268 if (!serializer->findPointer(mat))
3271 btChunk* chunk = serializer->allocate(sizeof(SoftBodyMaterialData),1);
3272 SoftBodyMaterialData* memPtr = (SoftBodyMaterialData*)chunk->m_oldPtr;
3273 memPtr->m_flags = mat->m_flags;
3274 memPtr->m_angularStiffness = mat->m_kAST;
3275 memPtr->m_linearStiffness = mat->m_kLST;
3276 memPtr->m_volumeStiffness = mat->m_kVST;
3277 serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_SBMATERIAL_CODE,mat);
3280 serializer->finalizeChunk(chunk,"SoftBodyMaterialData",BT_ARRAY_CODE,(void*) &m_materials);
3286 sbd->m_numNodes = m_nodes.size();
3287 sbd->m_nodes = sbd->m_numNodes ? (SoftBodyNodeData*)serializer->getUniquePointer((void*)&m_nodes): 0;
3290 int sz = sizeof(SoftBodyNodeData);
3291 int numElem = sbd->m_numNodes;
3292 btChunk* chunk = serializer->allocate(sz,numElem);
3293 SoftBodyNodeData* memPtr = (SoftBodyNodeData*)chunk->m_oldPtr;
3294 for (int i=0;i<numElem;i++,memPtr++)
3296 m_nodes[i].m_f.serializeFloat( memPtr->m_accumulatedForce);
3297 memPtr->m_area = m_nodes[i].m_area;
3298 memPtr->m_attach = m_nodes[i].m_battach;
3299 memPtr->m_inverseMass = m_nodes[i].m_im;
3300 memPtr->m_material = m_nodes[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_nodes[i].m_material):0;
3301 m_nodes[i].m_n.serializeFloat(memPtr->m_normal);
3302 m_nodes[i].m_x.serializeFloat(memPtr->m_position);
3303 m_nodes[i].m_q.serializeFloat(memPtr->m_previousPosition);
3304 m_nodes[i].m_v.serializeFloat(memPtr->m_velocity);
3305 m_nodeIndexMap.insert(&m_nodes[i],i);
3307 serializer->finalizeChunk(chunk,"SoftBodyNodeData",BT_SBNODE_CODE,(void*) &m_nodes);
3310 sbd->m_numLinks = m_links.size();
3311 sbd->m_links = sbd->m_numLinks? (SoftBodyLinkData*) serializer->getUniquePointer((void*)&m_links[0]):0;
3314 int sz = sizeof(SoftBodyLinkData);
3315 int numElem = sbd->m_numLinks;
3316 btChunk* chunk = serializer->allocate(sz,numElem);
3317 SoftBodyLinkData* memPtr = (SoftBodyLinkData*)chunk->m_oldPtr;
3318 for (int i=0;i<numElem;i++,memPtr++)
3320 memPtr->m_bbending = m_links[i].m_bbending;
3321 memPtr->m_material = m_links[i].m_material? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_links[i].m_material):0;
3322 memPtr->m_nodeIndices[0] = m_links[i].m_n[0] ? m_links[i].m_n[0] - &m_nodes[0]: -1;
3323 memPtr->m_nodeIndices[1] = m_links[i].m_n[1] ? m_links[i].m_n[1] - &m_nodes[0]: -1;
3324 btAssert(memPtr->m_nodeIndices[0]<m_nodes.size());
3325 btAssert(memPtr->m_nodeIndices[1]<m_nodes.size());
3326 memPtr->m_restLength = m_links[i].m_rl;
3328 serializer->finalizeChunk(chunk,"SoftBodyLinkData",BT_ARRAY_CODE,(void*) &m_links[0]);
3333 sbd->m_numFaces = m_faces.size();
3334 sbd->m_faces = sbd->m_numFaces? (SoftBodyFaceData*) serializer->getUniquePointer((void*)&m_faces[0]):0;
3337 int sz = sizeof(SoftBodyFaceData);
3338 int numElem = sbd->m_numFaces;
3339 btChunk* chunk = serializer->allocate(sz,numElem);
3340 SoftBodyFaceData* memPtr = (SoftBodyFaceData*)chunk->m_oldPtr;
3341 for (int i=0;i<numElem;i++,memPtr++)
3343 memPtr->m_material = m_faces[i].m_material ? (SoftBodyMaterialData*) serializer->getUniquePointer((void*)m_faces[i].m_material): 0;
3344 m_faces[i].m_normal.serializeFloat( memPtr->m_normal);
3345 for (int j=0;j<3;j++)
3347 memPtr->m_nodeIndices[j] = m_faces[i].m_n[j]? m_faces[i].m_n[j] - &m_nodes[0]: -1;
3349 memPtr->m_restArea = m_faces[i].m_ra;
3351 serializer->finalizeChunk(chunk,"SoftBodyFaceData",BT_ARRAY_CODE,(void*) &m_faces[0]);
3355 sbd->m_numTetrahedra = m_tetras.size();
3356 sbd->m_tetrahedra = sbd->m_numTetrahedra ? (SoftBodyTetraData*) serializer->getUniquePointer((void*)&m_tetras[0]):0;
3357 if (sbd->m_tetrahedra)
3359 int sz = sizeof(SoftBodyTetraData);
3360 int numElem = sbd->m_numTetrahedra;
3361 btChunk* chunk = serializer->allocate(sz,numElem);
3362 SoftBodyTetraData* memPtr = (SoftBodyTetraData*)chunk->m_oldPtr;
3363 for (int i=0;i<numElem;i++,memPtr++)
3365 for (int j=0;j<4;j++)
3367 m_tetras[i].m_c0[j].serializeFloat( memPtr->m_c0[j] );
3368 memPtr->m_nodeIndices[j] = m_tetras[j].m_n[j]? m_tetras[j].m_n[j]-&m_nodes[0] : -1;
3370 memPtr->m_c1 = m_tetras[i].m_c1;
3371 memPtr->m_c2 = m_tetras[i].m_c2;
3372 memPtr->m_material = m_tetras[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*) m_tetras[i].m_material): 0;
3373 memPtr->m_restVolume = m_tetras[i].m_rv;
3375 serializer->finalizeChunk(chunk,"SoftBodyTetraData",BT_ARRAY_CODE,(void*) &m_tetras[0]);
3378 sbd->m_numAnchors = m_anchors.size();
3379 sbd->m_anchors = sbd->m_numAnchors ? (SoftRigidAnchorData*) serializer->getUniquePointer((void*)&m_anchors[0]):0;
3382 int sz = sizeof(SoftRigidAnchorData);
3383 int numElem = sbd->m_numAnchors;
3384 btChunk* chunk = serializer->allocate(sz,numElem);
3385 SoftRigidAnchorData* memPtr = (SoftRigidAnchorData*)chunk->m_oldPtr;
3386 for (int i=0;i<numElem;i++,memPtr++)
3388 m_anchors[i].m_c0.serializeFloat(memPtr->m_c0);
3389 m_anchors[i].m_c1.serializeFloat(memPtr->m_c1);
3390 memPtr->m_c2 = m_anchors[i].m_c2;
3391 m_anchors[i].m_local.serializeFloat(memPtr->m_localFrame);
3392 memPtr->m_nodeIndex = m_anchors[i].m_node? m_anchors[i].m_node-&m_nodes[0]: -1;
3394 memPtr->m_rigidBody = m_anchors[i].m_body? (btRigidBodyData*) serializer->getUniquePointer((void*)m_anchors[i].m_body): 0;
3395 btAssert(memPtr->m_nodeIndex < m_nodes.size());
3397 serializer->finalizeChunk(chunk,"SoftRigidAnchorData",BT_ARRAY_CODE,(void*) &m_anchors[0]);
3401 sbd->m_config.m_dynamicFriction = m_cfg.kDF;
3402 sbd->m_config.m_baumgarte = m_cfg.kVCF;
3403 sbd->m_config.m_pressure = m_cfg.kPR;
3404 sbd->m_config.m_aeroModel = this->m_cfg.aeromodel;
3405 sbd->m_config.m_lift = m_cfg.kLF;
3406 sbd->m_config.m_drag = m_cfg.kDG;
3407 sbd->m_config.m_positionIterations = m_cfg.piterations;
3408 sbd->m_config.m_driftIterations = m_cfg.diterations;
3409 sbd->m_config.m_clusterIterations = m_cfg.citerations;
3410 sbd->m_config.m_velocityIterations = m_cfg.viterations;
3411 sbd->m_config.m_maxVolume = m_cfg.maxvolume;
3412 sbd->m_config.m_damping = m_cfg.kDP;
3413 sbd->m_config.m_poseMatch = m_cfg.kMT;
3414 sbd->m_config.m_collisionFlags = m_cfg.collisions;
3415 sbd->m_config.m_volume = m_cfg.kVC;
3416 sbd->m_config.m_rigidContactHardness = m_cfg.kCHR;
3417 sbd->m_config.m_kineticContactHardness = m_cfg.kKHR;
3418 sbd->m_config.m_softContactHardness = m_cfg.kSHR;
3419 sbd->m_config.m_anchorHardness = m_cfg.kAHR;
3420 sbd->m_config.m_timeScale = m_cfg.timescale;
3421 sbd->m_config.m_maxVolume = m_cfg.maxvolume;
3422 sbd->m_config.m_softRigidClusterHardness = m_cfg.kSRHR_CL;
3423 sbd->m_config.m_softKineticClusterHardness = m_cfg.kSKHR_CL;
3424 sbd->m_config.m_softSoftClusterHardness = m_cfg.kSSHR_CL;
3425 sbd->m_config.m_softRigidClusterImpulseSplit = m_cfg.kSR_SPLT_CL;
3426 sbd->m_config.m_softKineticClusterImpulseSplit = m_cfg.kSK_SPLT_CL;
3427 sbd->m_config.m_softSoftClusterImpulseSplit = m_cfg.kSS_SPLT_CL;
3429 //pose for shape matching
3431 sbd->m_pose = (SoftBodyPoseData*)serializer->getUniquePointer((void*)&m_pose);
3433 int sz = sizeof(SoftBodyPoseData);
3434 btChunk* chunk = serializer->allocate(sz,1);
3435 SoftBodyPoseData* memPtr = (SoftBodyPoseData*)chunk->m_oldPtr;
3437 m_pose.m_aqq.serializeFloat(memPtr->m_aqq);
3438 memPtr->m_bframe = m_pose.m_bframe;
3439 memPtr->m_bvolume = m_pose.m_bvolume;
3440 m_pose.m_com.serializeFloat(memPtr->m_com);
3442 memPtr->m_numPositions = m_pose.m_pos.size();
3443 memPtr->m_positions = memPtr->m_numPositions ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_pose.m_pos[0]): 0;
3444 if (memPtr->m_numPositions)
3446 int numElem = memPtr->m_numPositions;
3447 int sz = sizeof(btVector3Data);
3448 btChunk* chunk = serializer->allocate(sz,numElem);
3449 btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr;
3450 for (int i=0;i<numElem;i++,memPtr++)
3452 m_pose.m_pos[i].serializeFloat(*memPtr);
3454 serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_pose.m_pos[0]);
3456 memPtr->m_restVolume = m_pose.m_volume;
3457 m_pose.m_rot.serializeFloat(memPtr->m_rot);
3458 m_pose.m_scl.serializeFloat(memPtr->m_scale);
3460 memPtr->m_numWeigts = m_pose.m_wgh.size();
3461 memPtr->m_weights = memPtr->m_numWeigts? (float*) serializer->getUniquePointer((void*) &m_pose.m_wgh[0]) : 0;
3462 if (memPtr->m_numWeigts)
3465 int numElem = memPtr->m_numWeigts;
3466 int sz = sizeof(float);
3467 btChunk* chunk = serializer->allocate(sz,numElem);
3468 float* memPtr = (float*) chunk->m_oldPtr;
3469 for (int i=0;i<numElem;i++,memPtr++)
3471 *memPtr = m_pose.m_wgh[i];
3473 serializer->finalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_pose.m_wgh[0]);
3476 serializer->finalizeChunk(chunk,"SoftBodyPoseData",BT_ARRAY_CODE,(void*)&m_pose);
3479 //clusters for convex-cluster collision detection
3481 sbd->m_numClusters = m_clusters.size();
3482 sbd->m_clusters = sbd->m_numClusters? (SoftBodyClusterData*) serializer->getUniquePointer((void*)m_clusters[0]) : 0;
3483 if (sbd->m_numClusters)
3485 int numElem = sbd->m_numClusters;
3486 int sz = sizeof(SoftBodyClusterData);
3487 btChunk* chunk = serializer->allocate(sz,numElem);
3488 SoftBodyClusterData* memPtr = (SoftBodyClusterData*) chunk->m_oldPtr;
3489 for (int i=0;i<numElem;i++,memPtr++)
3491 memPtr->m_adamping= m_clusters[i]->m_adamping;
3492 m_clusters[i]->m_av.serializeFloat(memPtr->m_av);
3493 memPtr->m_clusterIndex = m_clusters[i]->m_clusterIndex;
3494 memPtr->m_collide = m_clusters[i]->m_collide;
3495 m_clusters[i]->m_com.serializeFloat(memPtr->m_com);
3496 memPtr->m_containsAnchor = m_clusters[i]->m_containsAnchor;
3497 m_clusters[i]->m_dimpulses[0].serializeFloat(memPtr->m_dimpulses[0]);
3498 m_clusters[i]->m_dimpulses[1].serializeFloat(memPtr->m_dimpulses[1]);
3499 m_clusters[i]->m_framexform.serializeFloat(memPtr->m_framexform);
3500 memPtr->m_idmass = m_clusters[i]->m_idmass;
3501 memPtr->m_imass = m_clusters[i]->m_imass;
3502 m_clusters[i]->m_invwi.serializeFloat(memPtr->m_invwi);
3503 memPtr->m_ldamping = m_clusters[i]->m_ldamping;
3504 m_clusters[i]->m_locii.serializeFloat(memPtr->m_locii);
3505 m_clusters[i]->m_lv.serializeFloat(memPtr->m_lv);
3506 memPtr->m_matching = m_clusters[i]->m_matching;
3507 memPtr->m_maxSelfCollisionImpulse = m_clusters[i]->m_maxSelfCollisionImpulse;
3508 memPtr->m_ndamping = m_clusters[i]->m_ndamping;
3509 memPtr->m_ldamping = m_clusters[i]->m_ldamping;
3510 memPtr->m_adamping = m_clusters[i]->m_adamping;
3511 memPtr->m_selfCollisionImpulseFactor = m_clusters[i]->m_selfCollisionImpulseFactor;
3513 memPtr->m_numFrameRefs = m_clusters[i]->m_framerefs.size();
3514 memPtr->m_numMasses = m_clusters[i]->m_masses.size();
3515 memPtr->m_numNodes = m_clusters[i]->m_nodes.size();
3517 memPtr->m_nvimpulses = m_clusters[i]->m_nvimpulses;
3518 m_clusters[i]->m_vimpulses[0].serializeFloat(memPtr->m_vimpulses[0]);
3519 m_clusters[i]->m_vimpulses[1].serializeFloat(memPtr->m_vimpulses[1]);
3520 memPtr->m_ndimpulses = m_clusters[i]->m_ndimpulses;
3524 memPtr->m_framerefs = memPtr->m_numFrameRefs? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_clusters[i]->m_framerefs[0]) : 0;
3525 if (memPtr->m_framerefs)
3527 int numElem = memPtr->m_numFrameRefs;
3528 int sz = sizeof(btVector3FloatData);
3529 btChunk* chunk = serializer->allocate(sz,numElem);
3530 btVector3FloatData* memPtr = (btVector3FloatData*) chunk->m_oldPtr;
3531 for (int j=0;j<numElem;j++,memPtr++)
3533 m_clusters[i]->m_framerefs[j].serializeFloat(*memPtr);
3535 serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_framerefs[0]);
3538 memPtr->m_masses = memPtr->m_numMasses ? (float*) serializer->getUniquePointer((void*)&m_clusters[i]->m_masses[0]): 0;
3539 if (memPtr->m_masses)
3541 int numElem = memPtr->m_numMasses;
3542 int sz = sizeof(float);
3543 btChunk* chunk = serializer->allocate(sz,numElem);
3544 float* memPtr = (float*) chunk->m_oldPtr;
3545 for (int j=0;j<numElem;j++,memPtr++)
3547 *memPtr = m_clusters[i]->m_masses[j];
3549 serializer->finalizeChunk(chunk,"float",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_masses[0]);
3552 memPtr->m_nodeIndices = memPtr->m_numNodes ? (int*) serializer->getUniquePointer((void*) &m_clusters[i]->m_nodes) : 0;
3553 if (memPtr->m_nodeIndices )
3555 int numElem = memPtr->m_numMasses;
3556 int sz = sizeof(int);
3557 btChunk* chunk = serializer->allocate(sz,numElem);
3558 int* memPtr = (int*) chunk->m_oldPtr;
3559 for (int j=0;j<numElem;j++,memPtr++)
3561 int* indexPtr = m_nodeIndexMap.find(m_clusters[i]->m_nodes[j]);
3563 *memPtr = *indexPtr;
3565 serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_clusters[i]->m_nodes);
3568 serializer->finalizeChunk(chunk,"SoftBodyClusterData",BT_ARRAY_CODE,(void*)m_clusters[0]);
3574 sbd->m_numJoints = m_joints.size();
3575 sbd->m_joints = m_joints.size()? (btSoftBodyJointData*) serializer->getUniquePointer((void*)&m_joints[0]) : 0;
3579 int sz = sizeof(btSoftBodyJointData);
3580 int numElem = m_joints.size();
3581 btChunk* chunk = serializer->allocate(sz,numElem);
3582 btSoftBodyJointData* memPtr = (btSoftBodyJointData*)chunk->m_oldPtr;
3584 for (int i=0;i<numElem;i++,memPtr++)
3586 memPtr->m_jointType = (int)m_joints[i]->Type();
3587 m_joints[i]->m_refs[0].serializeFloat(memPtr->m_refs[0]);
3588 m_joints[i]->m_refs[1].serializeFloat(memPtr->m_refs[1]);
3589 memPtr->m_cfm = m_joints[i]->m_cfm;
3590 memPtr->m_erp = m_joints[i]->m_erp;
3591 memPtr->m_split = m_joints[i]->m_split;
3592 memPtr->m_delete = m_joints[i]->m_delete;
3594 for (int j=0;j<4;j++)
3596 memPtr->m_relPosition[0].m_floats[j] = 0.f;
3597 memPtr->m_relPosition[1].m_floats[j] = 0.f;
3599 memPtr->m_bodyA = 0;
3600 memPtr->m_bodyB = 0;
3601 if (m_joints[i]->m_bodies[0].m_soft)
3603 memPtr->m_bodyAtype = BT_JOINT_SOFT_BODY_CLUSTER;
3604 memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_soft);
3606 if (m_joints[i]->m_bodies[0].m_collisionObject)
3608 memPtr->m_bodyAtype = BT_JOINT_COLLISION_OBJECT;
3609 memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_collisionObject);
3611 if (m_joints[i]->m_bodies[0].m_rigid)
3613 memPtr->m_bodyAtype = BT_JOINT_RIGID_BODY;
3614 memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_rigid);
3617 if (m_joints[i]->m_bodies[1].m_soft)
3619 memPtr->m_bodyBtype = BT_JOINT_SOFT_BODY_CLUSTER;
3620 memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_soft);
3622 if (m_joints[i]->m_bodies[1].m_collisionObject)
3624 memPtr->m_bodyBtype = BT_JOINT_COLLISION_OBJECT;
3625 memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_collisionObject);
3627 if (m_joints[i]->m_bodies[1].m_rigid)
3629 memPtr->m_bodyBtype = BT_JOINT_RIGID_BODY;
3630 memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_rigid);
3633 serializer->finalizeChunk(chunk,"btSoftBodyJointData",BT_ARRAY_CODE,(void*) &m_joints[0]);
3637 return btSoftBodyDataName;