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"
20 btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m)
21 :m_worldInfo(worldInfo)
24 m_internalType = CO_SOFT_BODY;
25 m_cfg.aeromodel = eAeroModel::V_Point;
32 m_cfg.kDF = (btScalar)0.2;
34 m_cfg.kCHR = (btScalar)1.0;
35 m_cfg.kKHR = (btScalar)0.1;
36 m_cfg.kSHR = (btScalar)1.0;
37 m_cfg.kAHR = (btScalar)0.7;
38 m_cfg.kSRHR_CL = (btScalar)0.1;
39 m_cfg.kSKHR_CL = (btScalar)1;
40 m_cfg.kSSHR_CL = (btScalar)0.5;
41 m_cfg.kSR_SPLT_CL = (btScalar)0.5;
42 m_cfg.kSK_SPLT_CL = (btScalar)0.5;
43 m_cfg.kSS_SPLT_CL = (btScalar)0.5;
44 m_cfg.maxvolume = (btScalar)1;
46 m_cfg.viterations = 0;
47 m_cfg.piterations = 1;
48 m_cfg.diterations = 0;
49 m_cfg.citerations = 4;
50 m_cfg.collisions = fCollision::Default;
51 m_pose.m_bvolume = false;
52 m_pose.m_bframe = false;
54 m_pose.m_com = btVector3(0,0,0);
55 m_pose.m_rot.setIdentity();
56 m_pose.m_scl.setIdentity();
59 m_bUpdateRtCst = true;
60 m_bounds[0] = btVector3(0,0,0);
61 m_bounds[1] = btVector3(0,0,0);
62 m_worldTransform.setIdentity();
63 setSolver(eSolverPresets::Positions);
64 /* Default material */
65 Material* pm=appendMaterial();
69 pm->m_flags = fMaterial::Default;
71 ///for now, create a collision shape internally
72 m_collisionShape = new btSoftBodyCollisionShape(this);
73 m_collisionShape->setMargin(0.25);
75 const btScalar margin=getCollisionShape()->getMargin();
76 m_nodes.resize(node_count);
77 for(int i=0,ni=node_count;i<ni;++i)
81 n.m_x = x?*x++:btVector3(0,0,0);
84 n.m_im = n.m_im>0?1/n.m_im:0;
85 n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
94 btSoftBody::~btSoftBody()
96 //for now, delete the internal shape
97 delete m_collisionShape;
101 for(i=0;i<m_materials.size();++i)
102 btAlignedFree(m_materials[i]);
103 for(i=0;i<m_joints.size();++i)
104 btAlignedFree(m_joints[i]);
108 bool btSoftBody::checkLink(int node0,int node1) const
110 return(checkLink(&m_nodes[node0],&m_nodes[node1]));
114 bool btSoftBody::checkLink(const Node* node0,const Node* node1) const
116 const Node* n[]={node0,node1};
117 for(int i=0,ni=m_links.size();i<ni;++i)
119 const Link& l=m_links[i];
120 if( (l.m_n[0]==n[0]&&l.m_n[1]==n[1])||
121 (l.m_n[0]==n[1]&&l.m_n[1]==n[0]))
130 bool btSoftBody::checkFace(int node0,int node1,int node2) const
132 const Node* n[]={ &m_nodes[node0],
135 for(int i=0,ni=m_faces.size();i<ni;++i)
137 const Face& f=m_faces[i];
141 if( (f.m_n[j]==n[0])||
143 (f.m_n[j]==n[2])) c|=1<<j; else break;
145 if(c==7) return(true);
151 btSoftBody::Material* btSoftBody::appendMaterial()
153 Material* pm=new(btAlignedAlloc(sizeof(Material),16)) Material();
154 if(m_materials.size()>0)
158 m_materials.push_back(pm);
163 void btSoftBody::appendNote( const char* text,
176 n.m_coords[0] = c.x();
177 n.m_coords[1] = c.y();
178 n.m_coords[2] = c.z();
179 n.m_coords[3] = c.w();
180 n.m_nodes[0] = n0;n.m_rank+=n0?1:0;
181 n.m_nodes[1] = n1;n.m_rank+=n1?1:0;
182 n.m_nodes[2] = n2;n.m_rank+=n2?1:0;
183 n.m_nodes[3] = n3;n.m_rank+=n3?1:0;
184 m_notes.push_back(n);
188 void btSoftBody::appendNote( const char* text,
192 appendNote(text,o,btVector4(1,0,0,0),feature);
196 void btSoftBody::appendNote( const char* text,
200 static const btScalar w=1/(btScalar)2;
201 appendNote(text,o,btVector4(w,w,0,0), feature->m_n[0],
206 void btSoftBody::appendNote( const char* text,
210 static const btScalar w=1/(btScalar)3;
211 appendNote(text,o,btVector4(w,w,w,0), feature->m_n[0],
217 void btSoftBody::appendNode( const btVector3& x,btScalar m)
219 if(m_nodes.capacity()==m_nodes.size())
222 m_nodes.reserve(m_nodes.size()*2+1);
225 const btScalar margin=getCollisionShape()->getMargin();
226 m_nodes.push_back(Node());
227 Node& n=m_nodes[m_nodes.size()-1];
232 n.m_material = m_materials[0];
233 n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
237 void btSoftBody::appendLink(int model,Material* mat)
243 { ZeroInitialize(l);l.m_material=mat?mat:m_materials[0]; }
244 m_links.push_back(l);
248 void btSoftBody::appendLink( int node0,
253 appendLink(&m_nodes[node0],&m_nodes[node1],mat,bcheckexist);
257 void btSoftBody::appendLink( Node* node0,
262 if((!bcheckexist)||(!checkLink(node0,node1)))
265 Link& l=m_links[m_links.size()-1];
268 l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
274 void btSoftBody::appendFace(int model,Material* mat)
278 { f=m_faces[model]; }
280 { ZeroInitialize(f);f.m_material=mat?mat:m_materials[0]; }
281 m_faces.push_back(f);
285 void btSoftBody::appendFace(int node0,int node1,int node2,Material* mat)
288 Face& f=m_faces[m_faces.size()-1];
289 btAssert(node0!=node1);
290 btAssert(node1!=node2);
291 btAssert(node2!=node0);
292 f.m_n[0] = &m_nodes[node0];
293 f.m_n[1] = &m_nodes[node1];
294 f.m_n[2] = &m_nodes[node2];
295 f.m_ra = AreaOf( f.m_n[0]->m_x,
302 void btSoftBody::appendAnchor(int node,btRigidBody* body)
305 a.m_node = &m_nodes[node];
307 a.m_local = body->getInterpolationWorldTransform().inverse()*a.m_node->m_x;
308 a.m_node->m_battach = 1;
309 m_anchors.push_back(a);
313 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1)
315 LJoint* pj = new(btAlignedAlloc(sizeof(LJoint),16)) LJoint();
316 pj->m_bodies[0] = body0;
317 pj->m_bodies[1] = body1;
318 pj->m_refs[0] = pj->m_bodies[0].xform().inverse()*specs.position;
319 pj->m_refs[1] = pj->m_bodies[1].xform().inverse()*specs.position;
320 pj->m_cfm = specs.cfm;
321 pj->m_erp = specs.erp;
322 pj->m_split = specs.split;
323 m_joints.push_back(pj);
327 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body)
329 appendLinearJoint(specs,m_clusters[0],body);
333 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body)
335 appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]);
339 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1)
341 AJoint* pj = new(btAlignedAlloc(sizeof(AJoint),16)) AJoint();
342 pj->m_bodies[0] = body0;
343 pj->m_bodies[1] = body1;
344 pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis()*specs.axis;
345 pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis()*specs.axis;
346 pj->m_cfm = specs.cfm;
347 pj->m_erp = specs.erp;
348 pj->m_split = specs.split;
349 pj->m_icontrol = specs.icontrol;
350 m_joints.push_back(pj);
354 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body)
356 appendAngularJoint(specs,m_clusters[0],body);
360 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body)
362 appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]);
366 void btSoftBody::addForce(const btVector3& force)
368 for(int i=0,ni=m_nodes.size();i<ni;++i) addForce(force,i);
372 void btSoftBody::addForce(const btVector3& force,int node)
374 Node& n=m_nodes[node];
382 void btSoftBody::addVelocity(const btVector3& velocity)
384 for(int i=0,ni=m_nodes.size();i<ni;++i) addVelocity(velocity,i);
387 /* Set velocity for the entire body */
388 void btSoftBody::setVelocity( const btVector3& velocity)
390 for(int i=0,ni=m_nodes.size();i<ni;++i)
402 void btSoftBody::addVelocity(const btVector3& velocity,int node)
404 Node& n=m_nodes[node];
412 void btSoftBody::setMass(int node,btScalar mass)
414 m_nodes[node].m_im=mass>0?1/mass:0;
419 btScalar btSoftBody::getMass(int node) const
421 return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0);
425 btScalar btSoftBody::getTotalMass() const
428 for(int i=0;i<m_nodes.size();++i)
436 void btSoftBody::setTotalMass(btScalar mass,bool fromfaces)
443 for(i=0;i<m_nodes.size();++i)
447 for(i=0;i<m_faces.size();++i)
449 const Face& f=m_faces[i];
450 const btScalar twicearea=AreaOf( f.m_n[0]->m_x,
455 f.m_n[j]->m_im+=twicearea;
458 for( i=0;i<m_nodes.size();++i)
460 m_nodes[i].m_im=1/m_nodes[i].m_im;
463 const btScalar tm=getTotalMass();
464 const btScalar itm=1/tm;
465 for( i=0;i<m_nodes.size();++i)
467 m_nodes[i].m_im/=itm*mass;
473 void btSoftBody::setTotalDensity(btScalar density)
475 setTotalMass(getVolume()*density,true);
479 void btSoftBody::transform(const btTransform& trs)
481 const btScalar margin=getCollisionShape()->getMargin();
482 for(int i=0,ni=m_nodes.size();i<ni;++i)
487 n.m_n=trs.getBasis()*n.m_n;
488 m_ndbvt.update(n.m_leaf,btDbvtVolume::FromCR(n.m_x,margin));
496 void btSoftBody::translate(const btVector3& trs)
505 void btSoftBody::rotate( const btQuaternion& rot)
514 void btSoftBody::scale(const btVector3& scl)
516 const btScalar margin=getCollisionShape()->getMargin();
517 for(int i=0,ni=m_nodes.size();i<ni;++i)
522 m_ndbvt.update(n.m_leaf,btDbvtVolume::FromCR(n.m_x,margin));
530 void btSoftBody::setPose(bool bvolume,bool bframe)
532 m_pose.m_bvolume = bvolume;
533 m_pose.m_bframe = bframe;
537 const btScalar omass=getTotalMass();
538 const btScalar kmass=omass*m_nodes.size()*1000;
539 btScalar tmass=omass;
540 m_pose.m_wgh.resize(m_nodes.size());
541 for(i=0,ni=m_nodes.size();i<ni;++i)
543 if(m_nodes[i].m_im<=0) tmass+=kmass;
545 for( i=0,ni=m_nodes.size();i<ni;++i)
548 m_pose.m_wgh[i]= n.m_im>0 ?
549 1/(m_nodes[i].m_im*tmass) :
553 const btVector3 com=evaluateCom();
554 m_pose.m_pos.resize(m_nodes.size());
555 for( i=0,ni=m_nodes.size();i<ni;++i)
557 m_pose.m_pos[i]=m_nodes[i].m_x-com;
559 m_pose.m_volume = bvolume?getVolume():0;
561 m_pose.m_rot.setIdentity();
562 m_pose.m_scl.setIdentity();
566 m_pose.m_aqq[2] = btVector3(0,0,0);
567 for( i=0,ni=m_nodes.size();i<ni;++i)
569 const btVector3& q=m_pose.m_pos[i];
570 const btVector3 mq=m_pose.m_wgh[i]*q;
571 m_pose.m_aqq[0]+=mq.x()*q;
572 m_pose.m_aqq[1]+=mq.y()*q;
573 m_pose.m_aqq[2]+=mq.z()*q;
575 m_pose.m_aqq=m_pose.m_aqq.inverse();
580 btScalar btSoftBody::getVolume() const
587 const btVector3 org=m_nodes[0].m_x;
588 for(i=0,ni=m_faces.size();i<ni;++i)
590 const Face& f=m_faces[i];
591 vol+=dot(f.m_n[0]->m_x-org,cross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org));
599 int btSoftBody::clusterCount() const
601 return(m_clusters.size());
605 btVector3 btSoftBody::clusterCom(const Cluster* cluster)
607 btVector3 com(0,0,0);
608 for(int i=0,ni=cluster->m_nodes.size();i<ni;++i)
610 com+=cluster->m_nodes[i]->m_x*cluster->m_masses[i];
612 return(com*cluster->m_imass);
616 btVector3 btSoftBody::clusterCom(int cluster) const
618 return(clusterCom(m_clusters[cluster]));
622 btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos)
624 return(cluster->m_lv+cross(cluster->m_av,rpos));
628 void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
630 const btVector3 li=cluster->m_imass*impulse;
631 const btVector3 ai=cluster->m_invwi*cross(rpos,impulse);
632 cluster->m_vimpulses[0]+=li;cluster->m_lv+=li;
633 cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
634 cluster->m_nvimpulses++;
638 void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
640 const btVector3 li=cluster->m_imass*impulse;
641 const btVector3 ai=cluster->m_invwi*cross(rpos,impulse);
642 cluster->m_dimpulses[0]+=li;
643 cluster->m_dimpulses[1]+=ai;
644 cluster->m_ndimpulses++;
648 void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse)
650 if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity);
651 if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift);
655 void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse)
657 const btVector3 ai=cluster->m_invwi*impulse;
658 cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
659 cluster->m_nvimpulses++;
663 void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse)
665 const btVector3 ai=cluster->m_invwi*impulse;
666 cluster->m_dimpulses[1]+=ai;
667 cluster->m_ndimpulses++;
671 void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse)
673 if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity);
674 if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift);
678 void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse)
680 cluster->m_dimpulses[0]+=impulse*cluster->m_imass;
681 cluster->m_ndimpulses++;
685 int btSoftBody::generateBendingConstraints(int distance,Material* mat)
692 const int n=m_nodes.size();
693 const unsigned inf=(~(unsigned)0)>>1;
694 unsigned* adj=new unsigned[n*n];
695 #define IDX(_x_,_y_) ((_y_)*n+(_x_))
700 if(i!=j) adj[IDX(i,j)]=adj[IDX(j,i)]=inf;
702 adj[IDX(i,j)]=adj[IDX(j,i)]=0;
705 for( i=0;i<m_links.size();++i)
707 const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
708 const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
718 const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
719 if(adj[IDX(i,j)]>sum)
721 adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
732 if(adj[IDX(i,j)]==(unsigned)distance)
735 m_links[m_links.size()-1].m_bbending=1;
747 void btSoftBody::randomizeConstraints()
749 unsigned long seed=243703;
750 #define NEXTRAND (seed=(1664525L*seed+1013904223L)&0xffffffff)
753 for(i=0,ni=m_links.size();i<ni;++i)
755 btSwap(m_links[i],m_links[NEXTRAND%ni]);
757 for(i=0,ni=m_faces.size();i<ni;++i)
759 btSwap(m_faces[i],m_faces[NEXTRAND%ni]);
765 void btSoftBody::releaseCluster(int index)
767 Cluster* c=m_clusters[index];
768 if(c->m_leaf) m_cdbvt.remove(c->m_leaf);
771 m_clusters.remove(c);
775 void btSoftBody::releaseClusters()
777 while(m_clusters.size()>0) releaseCluster(0);
781 int btSoftBody::generateClusters(int k,int maxiterations)
785 m_clusters.resize(btMin(k,m_nodes.size()));
786 for(i=0;i<m_clusters.size();++i)
788 m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
789 m_clusters[i]->m_collide= true;
795 btAlignedObjectArray<btVector3> centers;
796 btVector3 cog(0,0,0);
798 for(i=0;i<m_nodes.size();++i)
801 m_clusters[(i*29873)%m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
803 cog/=(btScalar)m_nodes.size();
804 centers.resize(k,cog);
806 const btScalar slope=16;
810 const btScalar w=2-btMin<btScalar>(1,iterations/slope);
818 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
820 c+=m_clusters[i]->m_nodes[j]->m_x;
822 if(m_clusters[i]->m_nodes.size())
824 c /= (btScalar)m_clusters[i]->m_nodes.size();
825 c = centers[i]+(c-centers[i])*w;
826 changed |= ((c-centers[i]).length2()>SIMD_EPSILON);
828 m_clusters[i]->m_nodes.resize(0);
831 for(i=0;i<m_nodes.size();++i)
833 const btVector3 nx=m_nodes[i].m_x;
835 btScalar kdist=ClusterMetric(centers[0],nx);
838 const btScalar d=ClusterMetric(centers[j],nx);
845 m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
847 } while(changed&&(iterations<maxiterations));
849 btAlignedObjectArray<int> cids;
850 cids.resize(m_nodes.size(),-1);
851 for(i=0;i<m_clusters.size();++i)
853 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
855 cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i;
858 for(i=0;i<m_faces.size();++i)
860 const int idx[]={ int(m_faces[i].m_n[0]-&m_nodes[0]),
861 int(m_faces[i].m_n[1]-&m_nodes[0]),
862 int(m_faces[i].m_n[2]-&m_nodes[0])};
865 const int cid=cids[idx[j]];
868 const int kid=idx[(j+q)%3];
871 if(m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size())
873 m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
880 if(m_clusters.size()>1)
882 Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
883 pmaster->m_collide = false;
884 pmaster->m_nodes.reserve(m_nodes.size());
885 for(int i=0;i<m_nodes.size();++i) pmaster->m_nodes.push_back(&m_nodes[i]);
886 m_clusters.push_back(pmaster);
887 btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]);
890 for(i=0;i<m_clusters.size();++i)
892 if(m_clusters[i]->m_nodes.size()==0)
898 initializeClusters();
900 return(m_clusters.size());
906 void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
908 const Node* nbase = &m_nodes[0];
909 int ncount = m_nodes.size();
910 btSymMatrix<int> edges(ncount,-2);
915 for(i=0;i<m_links.size();++i)
920 if(!SameSign(ifn->Eval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x)))
922 btSwap(m_links[i],m_links[m_links.size()-1]);
923 m_links.pop_back();--i;
928 for(i=0;i<m_links.size();++i)
931 edges(int(l.m_n[0]-nbase),int(l.m_n[1]-nbase))=-1;
933 for(i=0;i<m_faces.size();++i)
936 edges(int(f.m_n[0]-nbase),int(f.m_n[1]-nbase))=-1;
937 edges(int(f.m_n[1]-nbase),int(f.m_n[2]-nbase))=-1;
938 edges(int(f.m_n[2]-nbase),int(f.m_n[0]-nbase))=-1;
941 for(i=0;i<ncount;++i)
943 for(j=i+1;j<ncount;++j)
949 const btScalar t=ImplicitSolve(ifn,a.m_x,b.m_x,accurary);
952 const btVector3 x=Lerp(a.m_x,b.m_x,t);
953 const btVector3 v=Lerp(a.m_v,b.m_v,t);
959 const btScalar ma=1/a.m_im;
960 const btScalar mb=1/b.m_im;
961 const btScalar mc=Lerp(ma,mb,t);
962 const btScalar f=(ma+mb)/(ma+mb+mc);
968 { a.m_im/=0.5;m=1/a.m_im; }
973 { b.m_im/=0.5;m=1/b.m_im; }
978 edges(i,j)=m_nodes.size()-1;
979 m_nodes[edges(i,j)].m_v=v;
987 for(i=0,ni=m_links.size();i<ni;++i)
989 Link& feat=m_links[i];
990 const int idx[]={ int(feat.m_n[0]-nbase),
991 int(feat.m_n[1]-nbase)};
992 if((idx[0]<ncount)&&(idx[1]<ncount))
994 const int ni=edges(idx[0],idx[1]);
998 Link* pft[]={ &m_links[i],
999 &m_links[m_links.size()-1]};
1000 pft[0]->m_n[0]=&m_nodes[idx[0]];
1001 pft[0]->m_n[1]=&m_nodes[ni];
1002 pft[1]->m_n[0]=&m_nodes[ni];
1003 pft[1]->m_n[1]=&m_nodes[idx[1]];
1008 for(i=0;i<m_faces.size();++i)
1010 const Face& feat=m_faces[i];
1011 const int idx[]={ int(feat.m_n[0]-nbase),
1012 int(feat.m_n[1]-nbase),
1013 int(feat.m_n[2]-nbase)};
1014 for(j=2,k=0;k<3;j=k++)
1016 if((idx[j]<ncount)&&(idx[k]<ncount))
1018 const int ni=edges(idx[j],idx[k]);
1022 const int l=(k+1)%3;
1023 Face* pft[]={ &m_faces[i],
1024 &m_faces[m_faces.size()-1]};
1025 pft[0]->m_n[0]=&m_nodes[idx[l]];
1026 pft[0]->m_n[1]=&m_nodes[idx[j]];
1027 pft[0]->m_n[2]=&m_nodes[ni];
1028 pft[1]->m_n[0]=&m_nodes[ni];
1029 pft[1]->m_n[1]=&m_nodes[idx[k]];
1030 pft[1]->m_n[2]=&m_nodes[idx[l]];
1031 appendLink(ni,idx[l],pft[0]->m_material);
1040 btAlignedObjectArray<int> cnodes;
1041 const int pcount=ncount;
1043 ncount=m_nodes.size();
1044 cnodes.resize(ncount,0);
1046 for(i=0;i<ncount;++i)
1048 const btVector3 x=m_nodes[i].m_x;
1049 if((i>=pcount)||(btFabs(ifn->Eval(x))<accurary))
1051 const btVector3 v=m_nodes[i].m_v;
1052 btScalar m=getMass(i);
1053 if(m>0) { m*=0.5;m_nodes[i].m_im/=0.5; }
1055 cnodes[i]=m_nodes.size()-1;
1056 m_nodes[cnodes[i]].m_v=v;
1061 for(i=0,ni=m_links.size();i<ni;++i)
1063 const int id[]={ int(m_links[i].m_n[0]-nbase),
1064 int(m_links[i].m_n[1]-nbase)};
1066 if(cnodes[id[0]]&&cnodes[id[1]])
1069 todetach=m_links.size()-1;
1073 if(( (ifn->Eval(m_nodes[id[0]].m_x)<accurary)&&
1074 (ifn->Eval(m_nodes[id[1]].m_x)<accurary)))
1079 Link& l=m_links[todetach];
1080 for(int j=0;j<2;++j)
1082 int cn=cnodes[int(l.m_n[j]-nbase)];
1083 if(cn) l.m_n[j]=&m_nodes[cn];
1088 for(i=0,ni=m_faces.size();i<ni;++i)
1090 Node** n= m_faces[i].m_n;
1091 if( (ifn->Eval(n[0]->m_x)<accurary)&&
1092 (ifn->Eval(n[1]->m_x)<accurary)&&
1093 (ifn->Eval(n[2]->m_x)<accurary))
1095 for(int j=0;j<3;++j)
1097 int cn=cnodes[int(n[j]-nbase)];
1098 if(cn) n[j]=&m_nodes[cn];
1103 int nnodes=m_nodes.size();
1104 btAlignedObjectArray<int> ranks;
1105 btAlignedObjectArray<int> todelete;
1106 ranks.resize(nnodes,0);
1107 for(i=0,ni=m_links.size();i<ni;++i)
1109 for(int j=0;j<2;++j) ranks[int(m_links[i].m_n[j]-nbase)]++;
1111 for(i=0,ni=m_faces.size();i<ni;++i)
1113 for(int j=0;j<3;++j) ranks[int(m_faces[i].m_n[j]-nbase)]++;
1115 for(i=0;i<m_links.size();++i)
1117 const int id[]={ int(m_links[i].m_n[0]-nbase),
1118 int(m_links[i].m_n[1]-nbase)};
1119 const bool sg[]={ ranks[id[0]]==1,
1125 btSwap(m_links[i],m_links[m_links.size()-1]);
1126 m_links.pop_back();--i;
1130 for(i=nnodes-1;i>=0;--i)
1132 if(!ranks[i]) todelete.push_back(i);
1136 btAlignedObjectArray<int>& map=ranks;
1137 for(int i=0;i<nnodes;++i) map[i]=i;
1138 PointersToIndices(this);
1139 for(int i=0,ni=todelete.size();i<ni;++i)
1143 int& b=map[--nnodes];
1144 m_ndbvt.remove(m_nodes[a].m_leaf);m_nodes[a].m_leaf=0;
1145 btSwap(m_nodes[a],m_nodes[b]);
1148 IndicesToPointers(this,&map[0]);
1149 m_nodes.resize(nnodes);
1153 m_bUpdateRtCst=true;
1157 bool btSoftBody::cutLink(const Node* node0,const Node* node1,btScalar position)
1159 return(cutLink(int(node0-&m_nodes[0]),int(node1-&m_nodes[0]),position));
1163 bool btSoftBody::cutLink(int node0,int node1,btScalar position)
1167 const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
1168 const btVector3 x=Lerp(m_nodes[node0].m_x,m_nodes[node1].m_x,position);
1169 const btVector3 v=Lerp(m_nodes[node0].m_v,m_nodes[node1].m_v,position);
1173 Node* pa=&m_nodes[node0];
1174 Node* pb=&m_nodes[node1];
1175 Node* pn[2]={ &m_nodes[m_nodes.size()-2],
1176 &m_nodes[m_nodes.size()-1]};
1179 for(i=0,ni=m_links.size();i<ni;++i)
1181 const int mtch=MatchEdge(m_links[i].m_n[0],m_links[i].m_n[1],pa,pb);
1185 Link* pft[]={&m_links[i],&m_links[m_links.size()-1]};
1186 pft[0]->m_n[1]=pn[mtch];
1187 pft[1]->m_n[0]=pn[1-mtch];
1191 for(i=0,ni=m_faces.size();i<ni;++i)
1193 for(int k=2,l=0;l<3;k=l++)
1195 const int mtch=MatchEdge(m_faces[i].m_n[k],m_faces[i].m_n[l],pa,pb);
1199 Face* pft[]={&m_faces[i],&m_faces[m_faces.size()-1]};
1200 pft[0]->m_n[l]=pn[mtch];
1201 pft[1]->m_n[k]=pn[1-mtch];
1202 appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1203 appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1209 m_ndbvt.remove(pn[0]->m_leaf);
1210 m_ndbvt.remove(pn[1]->m_leaf);
1218 bool btSoftBody::rayCast(const btVector3& org,
1219 const btVector3& dir,
1223 if(m_faces.size()&&m_fdbvt.empty()) initializeFaceTree();
1224 results.body = this;
1225 results.time = maxtime;
1226 results.feature = eFeature::None;
1228 return(rayCast(org,dir,results.time,results.feature,results.index,false)!=0);
1232 void btSoftBody::setSolver(eSolverPresets::_ preset)
1234 m_cfg.m_vsequence.clear();
1235 m_cfg.m_psequence.clear();
1236 m_cfg.m_dsequence.clear();
1239 case eSolverPresets::Positions:
1240 m_cfg.m_psequence.push_back(ePSolver::Anchors);
1241 m_cfg.m_psequence.push_back(ePSolver::RContacts);
1242 m_cfg.m_psequence.push_back(ePSolver::SContacts);
1243 m_cfg.m_psequence.push_back(ePSolver::Linear);
1245 case eSolverPresets::Velocities:
1246 m_cfg.m_vsequence.push_back(eVSolver::Linear);
1248 m_cfg.m_psequence.push_back(ePSolver::Anchors);
1249 m_cfg.m_psequence.push_back(ePSolver::RContacts);
1250 m_cfg.m_psequence.push_back(ePSolver::SContacts);
1252 m_cfg.m_dsequence.push_back(ePSolver::Linear);
1258 void btSoftBody::predictMotion(btScalar dt)
1265 m_bUpdateRtCst=false;
1268 if(m_cfg.collisions&fCollision::VF_SS)
1270 initializeFaceTree();
1275 m_sst.sdt = dt*m_cfg.timescale;
1276 m_sst.isdt = 1/m_sst.sdt;
1277 m_sst.velmrg = m_sst.sdt*3;
1278 m_sst.radmrg = getCollisionShape()->getMargin();
1279 m_sst.updmrg = m_sst.radmrg*(btScalar)0.25;
1281 addVelocity(m_worldInfo->m_gravity*m_sst.sdt);
1284 for(i=0,ni=m_nodes.size();i<ni;++i)
1288 n.m_v += n.m_f*n.m_im*m_sst.sdt;
1289 n.m_x += n.m_v*m_sst.sdt;
1290 n.m_f = btVector3(0,0,0);
1297 for(i=0,ni=m_nodes.size();i<ni;++i)
1300 m_ndbvt.update( n.m_leaf,
1301 btDbvtVolume::FromCR(n.m_x,m_sst.radmrg),
1306 if(!m_fdbvt.empty())
1308 for(int i=0;i<m_faces.size();++i)
1311 const btVector3 v=( f.m_n[0]->m_v+
1314 m_fdbvt.update( f.m_leaf,
1315 VolumeOf(f,m_sst.radmrg),
1323 if(m_pose.m_bframe&&(m_cfg.kMT>0))
1325 const btMatrix3x3 posetrs=m_pose.m_rot;
1326 for(int i=0,ni=m_nodes.size();i<ni;++i)
1331 const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com;
1332 n.m_x=Lerp(n.m_x,x,m_cfg.kMT);
1336 /* Clear contacts */
1337 m_rcontacts.resize(0);
1338 m_scontacts.resize(0);
1339 /* Optimize dbvt's */
1340 m_ndbvt.optimizeIncremental(1);
1341 m_fdbvt.optimizeIncremental(1);
1342 m_cdbvt.optimizeIncremental(1);
1346 void btSoftBody::solveConstraints()
1348 /* Apply clusters */
1349 applyClusters(false);
1354 for(i=0,ni=m_links.size();i<ni;++i)
1357 l.m_c3 = l.m_n[1]->m_q-l.m_n[0]->m_q;
1358 l.m_c2 = 1/(l.m_c3.length2()*l.m_c0);
1360 /* Prepare anchors */
1361 for(i=0,ni=m_anchors.size();i<ni;++i)
1363 Anchor& a=m_anchors[i];
1364 const btVector3 ra=a.m_body->getWorldTransform().getBasis()*a.m_local;
1365 a.m_c0 = ImpulseMatrix( m_sst.sdt,
1367 a.m_body->getInvMass(),
1368 a.m_body->getInvInertiaTensorWorld(),
1371 a.m_c2 = m_sst.sdt*a.m_node->m_im;
1372 a.m_body->activate();
1374 /* Solve velocities */
1375 if(m_cfg.viterations>0)
1378 for(int isolve=0;isolve<m_cfg.viterations;++isolve)
1380 for(int iseq=0;iseq<m_cfg.m_vsequence.size();++iseq)
1382 getSolver(m_cfg.m_vsequence[iseq])(this,1);
1386 for(i=0,ni=m_nodes.size();i<ni;++i)
1389 n.m_x = n.m_q+n.m_v*m_sst.sdt;
1392 /* Solve positions */
1393 if(m_cfg.piterations>0)
1395 for(int isolve=0;isolve<m_cfg.piterations;++isolve)
1397 const btScalar ti=isolve/(btScalar)m_cfg.piterations;
1398 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1400 getSolver(m_cfg.m_psequence[iseq])(this,1,ti);
1403 const btScalar vc=m_sst.isdt*(1-m_cfg.kDP);
1404 for(i=0,ni=m_nodes.size();i<ni;++i)
1407 n.m_v = (n.m_x-n.m_q)*vc;
1408 n.m_f = btVector3(0,0,0);
1412 if(m_cfg.diterations>0)
1414 const btScalar vcf=m_cfg.kVCF*m_sst.isdt;
1415 for(i=0,ni=m_nodes.size();i<ni;++i)
1420 for(int idrift=0;idrift<m_cfg.diterations;++idrift)
1422 for(int iseq=0;iseq<m_cfg.m_dsequence.size();++iseq)
1424 getSolver(m_cfg.m_dsequence[iseq])(this,1,0);
1427 for(int i=0,ni=m_nodes.size();i<ni;++i)
1430 n.m_v += (n.m_x-n.m_q)*vcf;
1433 /* Apply clusters */
1435 applyClusters(true);
1439 void btSoftBody::staticSolve(int iterations)
1441 for(int isolve=0;isolve<iterations;++isolve)
1443 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1445 getSolver(m_cfg.m_psequence[iseq])(this,1,0);
1451 void btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/,int /*count*/,int /*iterations*/)
1457 void btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
1459 const int nb=bodies.size();
1465 iterations=btMax(iterations,bodies[i]->m_cfg.citerations);
1469 bodies[i]->prepareClusters(iterations);
1471 for(i=0;i<iterations;++i)
1473 const btScalar sor=1;
1474 for(int j=0;j<nb;++j)
1476 bodies[j]->solveClusters(sor);
1481 bodies[i]->cleanupClusters();
1486 void btSoftBody::integrateMotion()
1493 btSoftBody::RayCaster::RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt)
1503 void btSoftBody::RayCaster::Process(const btDbvtNode* leaf)
1505 btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data;
1506 const btScalar t=rayTriangle( o,d,
1511 if((t>0)&&(t<mint)) { mint=t;face=&f; }
1516 btScalar btSoftBody::RayCaster::rayTriangle( const btVector3& org,
1517 const btVector3& dir,
1523 static const btScalar ceps=-SIMD_EPSILON*10;
1524 static const btScalar teps=SIMD_EPSILON*10;
1525 const btVector3 n=cross(b-a,c-a);
1526 const btScalar d=dot(a,n);
1527 const btScalar den=dot(dir,n);
1528 if(!btFuzzyZero(den))
1530 const btScalar num=dot(org,n)-d;
1531 const btScalar t=-num/den;
1532 if((t>teps)&&(t<maxt))
1534 const btVector3 hit=org+dir*t;
1535 if( (dot(n,cross(a-hit,b-hit))>ceps) &&
1536 (dot(n,cross(b-hit,c-hit))>ceps) &&
1537 (dot(n,cross(c-hit,a-hit))>ceps))
1547 void btSoftBody::pointersToIndices()
1549 #define PTR2IDX(_p_,_b_) reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_))
1550 btSoftBody::Node* base=&m_nodes[0];
1553 for(i=0,ni=m_nodes.size();i<ni;++i)
1555 if(m_nodes[i].m_leaf)
1557 m_nodes[i].m_leaf->data=*(void**)&i;
1560 for(i=0,ni=m_links.size();i<ni;++i)
1562 m_links[i].m_n[0]=PTR2IDX(m_links[i].m_n[0],base);
1563 m_links[i].m_n[1]=PTR2IDX(m_links[i].m_n[1],base);
1565 for(i=0,ni=m_faces.size();i<ni;++i)
1567 m_faces[i].m_n[0]=PTR2IDX(m_faces[i].m_n[0],base);
1568 m_faces[i].m_n[1]=PTR2IDX(m_faces[i].m_n[1],base);
1569 m_faces[i].m_n[2]=PTR2IDX(m_faces[i].m_n[2],base);
1570 if(m_faces[i].m_leaf)
1572 m_faces[i].m_leaf->data=*(void**)&i;
1575 for(i=0,ni=m_anchors.size();i<ni;++i)
1577 m_anchors[i].m_node=PTR2IDX(m_anchors[i].m_node,base);
1579 for(i=0,ni=m_notes.size();i<ni;++i)
1581 for(int j=0;j<m_notes[i].m_rank;++j)
1583 m_notes[i].m_nodes[j]=PTR2IDX(m_notes[i].m_nodes[j],base);
1590 void btSoftBody::indicesToPointers(const int* map)
1592 #define IDX2PTR(_p_,_b_) map?(&(_b_)[map[(((char*)_p_)-(char*)0)]]): \
1593 (&(_b_)[(((char*)_p_)-(char*)0)])
1594 btSoftBody::Node* base=&m_nodes[0];
1597 for(i=0,ni=m_nodes.size();i<ni;++i)
1599 if(m_nodes[i].m_leaf)
1601 m_nodes[i].m_leaf->data=&m_nodes[i];
1604 for(i=0,ni=m_links.size();i<ni;++i)
1606 m_links[i].m_n[0]=IDX2PTR(m_links[i].m_n[0],base);
1607 m_links[i].m_n[1]=IDX2PTR(m_links[i].m_n[1],base);
1609 for(i=0,ni=m_faces.size();i<ni;++i)
1611 m_faces[i].m_n[0]=IDX2PTR(m_faces[i].m_n[0],base);
1612 m_faces[i].m_n[1]=IDX2PTR(m_faces[i].m_n[1],base);
1613 m_faces[i].m_n[2]=IDX2PTR(m_faces[i].m_n[2],base);
1614 if(m_faces[i].m_leaf)
1616 m_faces[i].m_leaf->data=&m_faces[i];
1619 for(i=0,ni=m_anchors.size();i<ni;++i)
1621 m_anchors[i].m_node=IDX2PTR(m_anchors[i].m_node,base);
1623 for(i=0,ni=m_notes.size();i<ni;++i)
1625 for(int j=0;j<m_notes[i].m_rank;++j)
1627 m_notes[i].m_nodes[j]=IDX2PTR(m_notes[i].m_nodes[j],base);
1634 int btSoftBody::rayCast(const btVector3& org,const btVector3& dir,
1635 btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const
1638 if(bcountonly||m_fdbvt.empty())
1640 for(int i=0,ni=m_faces.size();i<ni;++i)
1642 const btSoftBody::Face& f=m_faces[i];
1643 const btScalar t=RayCaster::rayTriangle( org,dir,
1653 feature=btSoftBody::eFeature::Face;
1662 RayCaster collider(org,dir,mint);
1663 btDbvt::collideRAY(m_fdbvt.m_root,org,dir,collider);
1667 feature=btSoftBody::eFeature::Face;
1668 index=(int)(collider.face-&m_faces[0]);
1676 void btSoftBody::initializeFaceTree()
1679 for(int i=0;i<m_faces.size();++i)
1682 f.m_leaf=m_fdbvt.insert(VolumeOf(f,0),&f);
1687 btVector3 btSoftBody::evaluateCom() const
1689 btVector3 com(0,0,0);
1692 for(int i=0,ni=m_nodes.size();i<ni;++i)
1694 com+=m_nodes[i].m_x*m_pose.m_wgh[i];
1701 bool btSoftBody::checkContact( btRigidBody* prb,
1704 btSoftBody::sCti& cti) const
1707 btCollisionShape* shp=prb->getCollisionShape();
1708 const btTransform& wtr=prb->getInterpolationWorldTransform();
1709 btScalar dst=m_worldInfo->m_sparsesdf.Evaluate( wtr.invXform(x),
1716 cti.m_normal = wtr.getBasis()*nrm;
1717 cti.m_offset = -dot( cti.m_normal,
1718 x-cti.m_normal*dst);
1725 void btSoftBody::updateNormals()
1727 const btVector3 zv(0,0,0);
1730 for(i=0,ni=m_nodes.size();i<ni;++i)
1734 for(i=0,ni=m_faces.size();i<ni;++i)
1736 btSoftBody::Face& f=m_faces[i];
1737 const btVector3 n=cross(f.m_n[1]->m_x-f.m_n[0]->m_x,
1738 f.m_n[2]->m_x-f.m_n[0]->m_x);
1739 f.m_normal=n.normalized();
1744 for(i=0,ni=m_nodes.size();i<ni;++i)
1746 btScalar len = m_nodes[i].m_n.length();
1747 if (len>SIMD_EPSILON)
1748 m_nodes[i].m_n /= len;
1753 void btSoftBody::updateBounds()
1757 const btVector3& mins=m_ndbvt.m_root->volume.Mins();
1758 const btVector3& maxs=m_ndbvt.m_root->volume.Maxs();
1759 const btScalar csm=getCollisionShape()->getMargin();
1760 const btVector3 mrg=btVector3( csm,
1762 csm)*1; // ??? to investigate...
1763 m_bounds[0]=mins-mrg;
1764 m_bounds[1]=maxs+mrg;
1765 if(0!=getBroadphaseHandle())
1767 m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(),
1770 m_worldInfo->m_dispatcher);
1776 m_bounds[1]=btVector3(0,0,0);
1782 void btSoftBody::updatePose()
1786 btSoftBody::Pose& pose=m_pose;
1787 const btVector3 com=evaluateCom();
1792 const btScalar eps=SIMD_EPSILON;
1793 Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0);
1794 Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3);
1795 for(int i=0,ni=m_nodes.size();i<ni;++i)
1797 const btVector3 a=pose.m_wgh[i]*(m_nodes[i].m_x-com);
1798 const btVector3& b=pose.m_pos[i];
1804 PolarDecompose(Apq,r,s);
1806 pose.m_scl=pose.m_aqq*r.transpose()*Apq;
1807 if(m_cfg.maxvolume>1)
1809 const btScalar idet=Clamp<btScalar>( 1/pose.m_scl.determinant(),
1811 pose.m_scl=Mul(pose.m_scl,idet);
1818 void btSoftBody::updateConstants()
1823 for(i=0,ni=m_links.size();i<ni;++i)
1826 Material& m=*l.m_material;
1827 l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
1828 l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST;
1829 l.m_c1 = l.m_rl*l.m_rl;
1832 for(i=0,ni=m_faces.size();i<ni;++i)
1835 f.m_ra = AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
1838 btAlignedObjectArray<int> counts;
1839 counts.resize(m_nodes.size(),0);
1840 for(i=0,ni=m_nodes.size();i<ni;++i)
1842 m_nodes[i].m_area = 0;
1844 for(i=0,ni=m_faces.size();i<ni;++i)
1846 btSoftBody::Face& f=m_faces[i];
1847 for(int j=0;j<3;++j)
1849 const int index=(int)(f.m_n[j]-&m_nodes[0]);
1851 f.m_n[j]->m_area+=btFabs(f.m_ra);
1854 for(i=0,ni=m_nodes.size();i<ni;++i)
1857 m_nodes[i].m_area/=(btScalar)counts[i];
1859 m_nodes[i].m_area=0;
1864 void btSoftBody::initializeClusters()
1868 for( i=0;i<m_clusters.size();++i)
1870 Cluster& c=*m_clusters[i];
1872 c.m_masses.resize(c.m_nodes.size());
1873 for(int j=0;j<c.m_nodes.size();++j)
1875 c.m_masses[j] = c.m_nodes[j]->m_im>0?1/c.m_nodes[j]->m_im:0;
1876 c.m_imass += c.m_masses[j];
1878 c.m_imass = 1/c.m_imass;
1879 c.m_com = btSoftBody::clusterCom(&c);
1880 c.m_lv = btVector3(0,0,0);
1881 c.m_av = btVector3(0,0,0);
1884 btMatrix3x3& ii=c.m_locii;
1885 ii[0]=ii[1]=ii[2]=btVector3(0,0,0);
1889 for(i=0,ni=c.m_nodes.size();i<ni;++i)
1891 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
1892 const btVector3 q=k*k;
1893 const btScalar m=c.m_masses[i];
1894 ii[0][0] += m*(q[1]+q[2]);
1895 ii[1][1] += m*(q[0]+q[2]);
1896 ii[2][2] += m*(q[0]+q[1]);
1897 ii[0][1] -= m*k[0]*k[1];
1898 ii[0][2] -= m*k[0]*k[2];
1899 ii[1][2] -= m*k[1]*k[2];
1907 c.m_framexform.setIdentity();
1908 c.m_framexform.setOrigin(c.m_com);
1909 c.m_framerefs.resize(c.m_nodes.size());
1912 for(i=0;i<c.m_framerefs.size();++i)
1914 c.m_framerefs[i]=c.m_nodes[i]->m_x-c.m_com;
1921 void btSoftBody::updateClusters()
1923 BT_PROFILE("UpdateClusters");
1926 for(i=0;i<m_clusters.size();++i)
1928 btSoftBody::Cluster& c=*m_clusters[i];
1929 const int n=c.m_nodes.size();
1930 const btScalar invn=1/(btScalar)n;
1934 const btScalar eps=btScalar(0.0001);
1936 m[0]=m[1]=m[2]=btVector3(0,0,0);
1940 c.m_com=clusterCom(&c);
1941 for(int i=0;i<c.m_nodes.size();++i)
1943 const btVector3 a=c.m_nodes[i]->m_x-c.m_com;
1944 const btVector3& b=c.m_framerefs[i];
1945 m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b;
1947 PolarDecompose(m,r,s);
1948 c.m_framexform.setOrigin(c.m_com);
1949 c.m_framexform.setBasis(r);
1952 c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose();
1955 const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass);
1956 const btVector3 inertia(rk,rk,rk);
1957 const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
1958 btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0,
1959 btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
1961 c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
1963 c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0);
1964 for(int i=0;i<n;++i)
1966 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
1967 const btVector3 q=k*k;
1968 const btScalar m=1/c.m_nodes[i]->m_im;
1969 c.m_invwi[0][0] += m*(q[1]+q[2]);
1970 c.m_invwi[1][1] += m*(q[0]+q[2]);
1971 c.m_invwi[2][2] += m*(q[0]+q[1]);
1972 c.m_invwi[0][1] -= m*k[0]*k[1];
1973 c.m_invwi[0][2] -= m*k[0]*k[2];
1974 c.m_invwi[1][2] -= m*k[1]*k[2];
1976 c.m_invwi[1][0]=c.m_invwi[0][1];
1977 c.m_invwi[2][0]=c.m_invwi[0][2];
1978 c.m_invwi[2][1]=c.m_invwi[1][2];
1979 c.m_invwi=c.m_invwi.inverse();
1983 c.m_lv=btVector3(0,0,0);
1984 c.m_av=btVector3(0,0,0);
1990 const btVector3 v=c.m_nodes[i]->m_v*c.m_masses[i];
1992 c.m_av += cross(c.m_nodes[i]->m_x-c.m_com,v);
1995 c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping);
1996 c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping);
1998 c.m_vimpulses[1] = btVector3(0,0,0);
2000 c.m_dimpulses[1] = btVector3(0,0,0);
2006 for(int j=0;j<c.m_nodes.size();++j)
2008 Node& n=*c.m_nodes[j];
2009 const btVector3 x=c.m_framexform*c.m_framerefs[j];
2010 n.m_x=Lerp(n.m_x,x,c.m_matching);
2016 btVector3 mi=c.m_nodes[0]->m_x;
2018 for(int j=1;j<n;++j)
2020 mi.setMin(c.m_nodes[j]->m_x);
2021 mx.setMax(c.m_nodes[j]->m_x);
2023 const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx);
2025 m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg);
2027 c.m_leaf=m_cdbvt.insert(bounds,&c);
2034 void btSoftBody::cleanupClusters()
2036 for(int i=0;i<m_joints.size();++i)
2038 m_joints[i]->Terminate(m_sst.sdt);
2039 if(m_joints[i]->m_delete)
2041 btAlignedFree(m_joints[i]);
2042 m_joints.remove(m_joints[i--]);
2048 void btSoftBody::prepareClusters(int iterations)
2050 for(int i=0;i<m_joints.size();++i)
2052 m_joints[i]->Prepare(m_sst.sdt,iterations);
2058 void btSoftBody::solveClusters(btScalar sor)
2060 for(int i=0,ni=m_joints.size();i<ni;++i)
2062 m_joints[i]->Solve(m_sst.sdt,sor);
2067 void btSoftBody::applyClusters(bool drift)
2069 BT_PROFILE("ApplyClusters");
2070 const btScalar f0=m_sst.sdt;
2071 const btScalar f1=f0/2;
2072 btAlignedObjectArray<btVector3> deltas;
2073 btAlignedObjectArray<btScalar> weights;
2074 deltas.resize(m_nodes.size(),btVector3(0,0,0));
2075 weights.resize(m_nodes.size(),0);
2080 for(i=0;i<m_clusters.size();++i)
2082 Cluster& c=*m_clusters[i];
2085 c.m_dimpulses[0]/=(btScalar)c.m_ndimpulses;
2086 c.m_dimpulses[1]/=(btScalar)c.m_ndimpulses;
2090 for(i=0;i<m_clusters.size();++i)
2092 Cluster& c=*m_clusters[i];
2093 if(0<(drift?c.m_ndimpulses:c.m_nvimpulses))
2095 const btVector3 v=(drift?c.m_dimpulses[0]:c.m_vimpulses[0])*m_sst.sdt;
2096 const btVector3 w=(drift?c.m_dimpulses[1]:c.m_vimpulses[1])*m_sst.sdt;
2097 for(int j=0;j<c.m_nodes.size();++j)
2099 const int idx=int(c.m_nodes[j]-&m_nodes[0]);
2100 const btVector3& x=c.m_nodes[j]->m_x;
2101 const btScalar q=c.m_masses[j];
2102 deltas[idx] += (v+cross(w,x-c.m_com))*q;
2107 for(i=0;i<deltas.size();++i)
2109 if(weights[i]>0) m_nodes[i].m_x+=deltas[i]/weights[i];
2114 void btSoftBody::dampClusters()
2118 for(i=0;i<m_clusters.size();++i)
2120 Cluster& c=*m_clusters[i];
2123 for(int j=0;j<c.m_nodes.size();++j)
2125 Node& n=*c.m_nodes[j];
2128 const btVector3 vx=c.m_lv+cross(c.m_av,c.m_nodes[j]->m_q-c.m_com);
2129 n.m_v += c.m_ndamping*(vx-n.m_v);
2137 void btSoftBody::Joint::Prepare(btScalar dt,int)
2139 m_bodies[0].activate();
2140 m_bodies[1].activate();
2144 void btSoftBody::LJoint::Prepare(btScalar dt,int iterations)
2146 static const btScalar maxdrift=4;
2147 Joint::Prepare(dt,iterations);
2148 m_rpos[0] = m_bodies[0].xform()*m_refs[0];
2149 m_rpos[1] = m_bodies[1].xform()*m_refs[1];
2150 m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt;
2151 m_rpos[0] -= m_bodies[0].xform().getOrigin();
2152 m_rpos[1] -= m_bodies[1].xform().getOrigin();
2153 m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0],
2154 m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]);
2157 m_sdrift = m_massmatrix*(m_drift*m_split);
2158 m_drift *= 1-m_split;
2160 m_drift /=(btScalar)iterations;
2164 void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor)
2166 const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
2167 const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
2168 const btVector3 vr=va-vb;
2169 btSoftBody::Impulse impulse;
2170 impulse.m_asVelocity = 1;
2171 impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor;
2172 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2173 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2177 void btSoftBody::LJoint::Terminate(btScalar dt)
2181 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2182 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2187 void btSoftBody::AJoint::Prepare(btScalar dt,int iterations)
2189 static const btScalar maxdrift=SIMD_PI/16;
2190 m_icontrol->Prepare(this);
2191 Joint::Prepare(dt,iterations);
2192 m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0];
2193 m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1];
2194 m_drift = NormalizeAny(cross(m_axis[1],m_axis[0]));
2195 m_drift *= btMin(maxdrift,btAcos(Clamp<btScalar>(dot(m_axis[0],m_axis[1]),-1,+1)));
2196 m_drift *= m_erp/dt;
2197 m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia());
2200 m_sdrift = m_massmatrix*(m_drift*m_split);
2201 m_drift *= 1-m_split;
2203 m_drift /=(btScalar)iterations;
2207 void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor)
2209 const btVector3 va=m_bodies[0].angularVelocity();
2210 const btVector3 vb=m_bodies[1].angularVelocity();
2211 const btVector3 vr=va-vb;
2212 const btScalar sp=dot(vr,m_axis[0]);
2213 const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp);
2214 btSoftBody::Impulse impulse;
2215 impulse.m_asVelocity = 1;
2216 impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor;
2217 m_bodies[0].applyAImpulse(-impulse);
2218 m_bodies[1].applyAImpulse( impulse);
2222 void btSoftBody::AJoint::Terminate(btScalar dt)
2226 m_bodies[0].applyDAImpulse(-m_sdrift);
2227 m_bodies[1].applyDAImpulse( m_sdrift);
2232 void btSoftBody::CJoint::Prepare(btScalar dt,int iterations)
2234 Joint::Prepare(dt,iterations);
2235 const bool dodrift=(m_life==0);
2236 m_delete=(++m_life)>m_maxlife;
2239 m_drift=m_drift*m_erp/dt;
2242 m_sdrift = m_massmatrix*(m_drift*m_split);
2243 m_drift *= 1-m_split;
2245 m_drift/=(btScalar)iterations;
2249 m_drift=m_sdrift=btVector3(0,0,0);
2254 void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor)
2256 const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
2257 const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
2258 const btVector3 vrel=va-vb;
2259 const btScalar rvac=dot(vrel,m_normal);
2260 btSoftBody::Impulse impulse;
2261 impulse.m_asVelocity = 1;
2262 impulse.m_velocity = m_drift;
2265 const btVector3 iv=m_normal*rvac;
2266 const btVector3 fv=vrel-iv;
2267 impulse.m_velocity += iv+fv*m_friction;
2269 impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor;
2270 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2271 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2275 void btSoftBody::CJoint::Terminate(btScalar dt)
2279 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2280 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2285 void btSoftBody::applyForces()
2287 BT_PROFILE("SoftBody applyForces");
2288 const btScalar dt=m_sst.sdt;
2289 const btScalar kLF=m_cfg.kLF;
2290 const btScalar kDG=m_cfg.kDG;
2291 const btScalar kPR=m_cfg.kPR;
2292 const btScalar kVC=m_cfg.kVC;
2293 const bool as_lift=kLF>0;
2294 const bool as_drag=kDG>0;
2295 const bool as_pressure=kPR!=0;
2296 const bool as_volume=kVC>0;
2297 const bool as_aero= as_lift ||
2299 const bool as_vaero= as_aero &&
2300 (m_cfg.aeromodel<btSoftBody::eAeroModel::F_TwoSided);
2301 const bool as_faero= as_aero &&
2302 (m_cfg.aeromodel>=btSoftBody::eAeroModel::F_TwoSided);
2303 const bool use_medium= as_aero;
2304 const bool use_volume= as_pressure ||
2307 btScalar ivolumetp=0;
2308 btScalar dvolumetv=0;
2309 btSoftBody::sMedium medium;
2312 volume = getVolume();
2313 ivolumetp = 1/btFabs(volume)*kPR;
2314 dvolumetv = (m_pose.m_volume-volume)*kVC;
2316 /* Per vertex forces */
2319 for(i=0,ni=m_nodes.size();i<ni;++i)
2321 btSoftBody::Node& n=m_nodes[i];
2326 EvaluateMedium(m_worldInfo,n.m_x,medium);
2330 const btVector3 rel_v=n.m_v-medium.m_velocity;
2331 const btScalar rel_v2=rel_v.length2();
2332 if(rel_v2>SIMD_EPSILON)
2334 btVector3 nrm=n.m_n;
2336 switch(m_cfg.aeromodel)
2338 case btSoftBody::eAeroModel::V_Point:
2339 nrm=NormalizeAny(rel_v);break;
2340 case btSoftBody::eAeroModel::V_TwoSided:
2341 nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break;
2343 const btScalar dvn=dot(rel_v,nrm);
2344 /* Compute forces */
2347 btVector3 force(0,0,0);
2348 const btScalar c0 = n.m_area*dvn*rel_v2/2;
2349 const btScalar c1 = c0*medium.m_density;
2350 force += nrm*(-c1*kLF);
2351 force += rel_v.normalized()*(-c1*kDG);
2352 ApplyClampedForce(n,force,dt);
2360 n.m_f += n.m_n*(n.m_area*ivolumetp);
2365 n.m_f += n.m_n*(n.m_area*dvolumetv);
2369 /* Per face forces */
2370 for(i=0,ni=m_faces.size();i<ni;++i)
2372 btSoftBody::Face& f=m_faces[i];
2375 const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3;
2376 const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3;
2377 EvaluateMedium(m_worldInfo,x,medium);
2378 const btVector3 rel_v=v-medium.m_velocity;
2379 const btScalar rel_v2=rel_v.length2();
2380 if(rel_v2>SIMD_EPSILON)
2382 btVector3 nrm=f.m_normal;
2384 switch(m_cfg.aeromodel)
2386 case btSoftBody::eAeroModel::F_TwoSided:
2387 nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break;
2389 const btScalar dvn=dot(rel_v,nrm);
2390 /* Compute forces */
2393 btVector3 force(0,0,0);
2394 const btScalar c0 = f.m_ra*dvn*rel_v2;
2395 const btScalar c1 = c0*medium.m_density;
2396 force += nrm*(-c1*kLF);
2397 force += rel_v.normalized()*(-c1*kDG);
2399 for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt);
2407 void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti)
2409 const btScalar kAHR=psb->m_cfg.kAHR*kst;
2410 const btScalar dt=psb->m_sst.sdt;
2411 for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
2413 const Anchor& a=psb->m_anchors[i];
2414 const btTransform& t=a.m_body->getInterpolationWorldTransform();
2416 const btVector3 wa=t*a.m_local;
2417 const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt;
2418 const btVector3 vb=n.m_x-n.m_q;
2419 const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR;
2420 const btVector3 impulse=a.m_c0*vr;
2421 n.m_x+=impulse*a.m_c2;
2422 a.m_body->applyImpulse(-impulse,a.m_c1);
2427 void btSoftBody::PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti)
2429 const btScalar dt=psb->m_sst.sdt;
2430 const btScalar mrg=psb->getCollisionShape()->getMargin();
2431 for(int i=0,ni=psb->m_rcontacts.size();i<ni;++i)
2433 const RContact& c=psb->m_rcontacts[i];
2434 const sCti& cti=c.m_cti;
2435 const btVector3 va=cti.m_body->getVelocityInLocalPoint(c.m_c1)*dt;
2436 const btVector3 vb=c.m_node->m_x-c.m_node->m_q;
2437 const btVector3 vr=vb-va;
2438 const btScalar dn=dot(vr,cti.m_normal);
2439 if(dn<=SIMD_EPSILON)
2441 const btScalar dp=btMin(dot(c.m_node->m_x,cti.m_normal)+cti.m_offset,mrg);
2442 const btVector3 fv=vr-cti.m_normal*dn;
2443 const btVector3 impulse=c.m_c0*((vr-fv*c.m_c3+cti.m_normal*(dp*c.m_c4))*kst);
2444 c.m_node->m_x-=impulse*c.m_c2;
2445 c.m_cti.m_body->applyImpulse(impulse,c.m_c1);
2451 void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti)
2453 for(int i=0,ni=psb->m_scontacts.size();i<ni;++i)
2455 const SContact& c=psb->m_scontacts[i];
2456 const btVector3& nr=c.m_normal;
2459 const btVector3 p=BaryEval( f.m_n[0]->m_x,
2463 const btVector3 q=BaryEval( f.m_n[0]->m_q,
2467 const btVector3 vr=(n.m_x-n.m_q)-(p-q);
2468 btVector3 corr(0,0,0);
2471 const btScalar j=c.m_margin-(dot(nr,n.m_x)-dot(nr,p));
2474 corr -= ProjectOnPlane(vr,nr)*c.m_friction;
2475 n.m_x += corr*c.m_cfm[0];
2476 f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x());
2477 f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y());
2478 f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z());
2483 void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti)
2485 for(int i=0,ni=psb->m_links.size();i<ni;++i)
2487 Link& l=psb->m_links[i];
2492 const btVector3 del=b.m_x-a.m_x;
2493 const btScalar len=del.length2();
2494 const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst;
2495 const btScalar t=k*a.m_im;
2496 a.m_x-=del*(k*a.m_im);
2497 b.m_x+=del*(k*b.m_im);
2503 void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst)
2505 for(int i=0,ni=psb->m_links.size();i<ni;++i)
2507 Link& l=psb->m_links[i];
2509 const btScalar j=-dot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst;
2510 n[0]->m_v+= l.m_c3*(j*n[0]->m_im);
2511 n[1]->m_v-= l.m_c3*(j*n[1]->m_im);
2516 btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver)
2520 case ePSolver::Anchors: return(&btSoftBody::PSolve_Anchors);
2521 case ePSolver::Linear: return(&btSoftBody::PSolve_Links);
2522 case ePSolver::RContacts: return(&btSoftBody::PSolve_RContacts);
2523 case ePSolver::SContacts: return(&btSoftBody::PSolve_SContacts);
2529 btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
2533 case eVSolver::Linear: return(&btSoftBody::VSolve_Links);
2539 void btSoftBody::defaultCollisionHandler(btCollisionObject* pco)
2541 switch(m_cfg.collisions&fCollision::RVSmask)
2543 case fCollision::SDF_RS:
2545 btSoftColliders::CollideSDF_RS docollide;
2546 btRigidBody* prb=btRigidBody::upcast(pco);
2547 const btTransform wtr=prb->getInterpolationWorldTransform();
2548 const btTransform ctr=prb->getWorldTransform();
2549 const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length();
2550 const btScalar basemargin=getCollisionShape()->getMargin();
2553 ATTRIBUTE_ALIGNED16(btDbvtVolume) volume;
2554 pco->getCollisionShape()->getAabb( pco->getInterpolationWorldTransform(),
2557 volume=btDbvtVolume::FromMM(mins,maxs);
2558 volume.Expand(btVector3(basemargin,basemargin,basemargin));
2559 docollide.psb = this;
2560 docollide.prb = prb;
2561 docollide.dynmargin = basemargin+timemargin;
2562 docollide.stamargin = basemargin;
2563 btDbvt::collideTV(m_ndbvt.m_root,volume,docollide);
2566 case fCollision::CL_RS:
2568 btSoftColliders::CollideCL_RS collider;
2569 collider.Process(this,btRigidBody::upcast(pco));
2576 void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
2578 const int cf=m_cfg.collisions&psb->m_cfg.collisions;
2579 switch(cf&fCollision::SVSmask)
2581 case fCollision::CL_SS:
2583 btSoftColliders::CollideCL_SS docollide;
2584 docollide.Process(this,psb);
2587 case fCollision::VF_SS:
2589 btSoftColliders::CollideVF_SS docollide;
2591 docollide.mrg= getCollisionShape()->getMargin()+
2592 psb->getCollisionShape()->getMargin();
2593 /* psb0 nodes vs psb1 faces */
2594 docollide.psb[0]=this;
2595 docollide.psb[1]=psb;
2596 btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root,
2597 docollide.psb[1]->m_fdbvt.m_root,
2599 /* psb1 nodes vs psb0 faces */
2600 docollide.psb[0]=psb;
2601 docollide.psb[1]=this;
2602 btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root,
2603 docollide.psb[1]->m_fdbvt.m_root,