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)
295 Face& f=m_faces[m_faces.size()-1];
296 btAssert(node0!=node1);
297 btAssert(node1!=node2);
298 btAssert(node2!=node0);
299 f.m_n[0] = &m_nodes[node0];
300 f.m_n[1] = &m_nodes[node1];
301 f.m_n[2] = &m_nodes[node2];
302 f.m_ra = AreaOf( f.m_n[0]->m_x,
309 void btSoftBody::appendAnchor(int node,btRigidBody* body)
312 a.m_node = &m_nodes[node];
314 a.m_local = body->getInterpolationWorldTransform().inverse()*a.m_node->m_x;
315 a.m_node->m_battach = 1;
316 m_anchors.push_back(a);
320 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1)
322 LJoint* pj = new(btAlignedAlloc(sizeof(LJoint),16)) LJoint();
323 pj->m_bodies[0] = body0;
324 pj->m_bodies[1] = body1;
325 pj->m_refs[0] = pj->m_bodies[0].xform().inverse()*specs.position;
326 pj->m_refs[1] = pj->m_bodies[1].xform().inverse()*specs.position;
327 pj->m_cfm = specs.cfm;
328 pj->m_erp = specs.erp;
329 pj->m_split = specs.split;
330 m_joints.push_back(pj);
334 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body)
336 appendLinearJoint(specs,m_clusters[0],body);
340 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body)
342 appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]);
346 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1)
348 AJoint* pj = new(btAlignedAlloc(sizeof(AJoint),16)) AJoint();
349 pj->m_bodies[0] = body0;
350 pj->m_bodies[1] = body1;
351 pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis()*specs.axis;
352 pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis()*specs.axis;
353 pj->m_cfm = specs.cfm;
354 pj->m_erp = specs.erp;
355 pj->m_split = specs.split;
356 pj->m_icontrol = specs.icontrol;
357 m_joints.push_back(pj);
361 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body)
363 appendAngularJoint(specs,m_clusters[0],body);
367 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body)
369 appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]);
373 void btSoftBody::addForce(const btVector3& force)
375 for(int i=0,ni=m_nodes.size();i<ni;++i) addForce(force,i);
379 void btSoftBody::addForce(const btVector3& force,int node)
381 Node& n=m_nodes[node];
389 void btSoftBody::addVelocity(const btVector3& velocity)
391 for(int i=0,ni=m_nodes.size();i<ni;++i) addVelocity(velocity,i);
394 /* Set velocity for the entire body */
395 void btSoftBody::setVelocity( const btVector3& velocity)
397 for(int i=0,ni=m_nodes.size();i<ni;++i)
409 void btSoftBody::addVelocity(const btVector3& velocity,int node)
411 Node& n=m_nodes[node];
419 void btSoftBody::setMass(int node,btScalar mass)
421 m_nodes[node].m_im=mass>0?1/mass:0;
426 btScalar btSoftBody::getMass(int node) const
428 return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0);
432 btScalar btSoftBody::getTotalMass() const
435 for(int i=0;i<m_nodes.size();++i)
443 void btSoftBody::setTotalMass(btScalar mass,bool fromfaces)
450 for(i=0;i<m_nodes.size();++i)
454 for(i=0;i<m_faces.size();++i)
456 const Face& f=m_faces[i];
457 const btScalar twicearea=AreaOf( f.m_n[0]->m_x,
462 f.m_n[j]->m_im+=twicearea;
465 for( i=0;i<m_nodes.size();++i)
467 m_nodes[i].m_im=1/m_nodes[i].m_im;
470 const btScalar tm=getTotalMass();
471 const btScalar itm=1/tm;
472 for( i=0;i<m_nodes.size();++i)
474 m_nodes[i].m_im/=itm*mass;
480 void btSoftBody::setTotalDensity(btScalar density)
482 setTotalMass(getVolume()*density,true);
486 void btSoftBody::transform(const btTransform& trs)
488 const btScalar margin=getCollisionShape()->getMargin();
489 for(int i=0,ni=m_nodes.size();i<ni;++i)
494 n.m_n=trs.getBasis()*n.m_n;
495 m_ndbvt.update(n.m_leaf,btDbvtVolume::FromCR(n.m_x,margin));
503 void btSoftBody::translate(const btVector3& trs)
512 void btSoftBody::rotate( const btQuaternion& rot)
521 void btSoftBody::scale(const btVector3& scl)
523 const btScalar margin=getCollisionShape()->getMargin();
524 for(int i=0,ni=m_nodes.size();i<ni;++i)
529 m_ndbvt.update(n.m_leaf,btDbvtVolume::FromCR(n.m_x,margin));
537 void btSoftBody::setPose(bool bvolume,bool bframe)
539 m_pose.m_bvolume = bvolume;
540 m_pose.m_bframe = bframe;
544 const btScalar omass=getTotalMass();
545 const btScalar kmass=omass*m_nodes.size()*1000;
546 btScalar tmass=omass;
547 m_pose.m_wgh.resize(m_nodes.size());
548 for(i=0,ni=m_nodes.size();i<ni;++i)
550 if(m_nodes[i].m_im<=0) tmass+=kmass;
552 for( i=0,ni=m_nodes.size();i<ni;++i)
555 m_pose.m_wgh[i]= n.m_im>0 ?
556 1/(m_nodes[i].m_im*tmass) :
560 const btVector3 com=evaluateCom();
561 m_pose.m_pos.resize(m_nodes.size());
562 for( i=0,ni=m_nodes.size();i<ni;++i)
564 m_pose.m_pos[i]=m_nodes[i].m_x-com;
566 m_pose.m_volume = bvolume?getVolume():0;
568 m_pose.m_rot.setIdentity();
569 m_pose.m_scl.setIdentity();
573 m_pose.m_aqq[2] = btVector3(0,0,0);
574 for( i=0,ni=m_nodes.size();i<ni;++i)
576 const btVector3& q=m_pose.m_pos[i];
577 const btVector3 mq=m_pose.m_wgh[i]*q;
578 m_pose.m_aqq[0]+=mq.x()*q;
579 m_pose.m_aqq[1]+=mq.y()*q;
580 m_pose.m_aqq[2]+=mq.z()*q;
582 m_pose.m_aqq=m_pose.m_aqq.inverse();
587 btScalar btSoftBody::getVolume() const
594 const btVector3 org=m_nodes[0].m_x;
595 for(i=0,ni=m_faces.size();i<ni;++i)
597 const Face& f=m_faces[i];
598 vol+=dot(f.m_n[0]->m_x-org,cross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org));
606 int btSoftBody::clusterCount() const
608 return(m_clusters.size());
612 btVector3 btSoftBody::clusterCom(const Cluster* cluster)
614 btVector3 com(0,0,0);
615 for(int i=0,ni=cluster->m_nodes.size();i<ni;++i)
617 com+=cluster->m_nodes[i]->m_x*cluster->m_masses[i];
619 return(com*cluster->m_imass);
623 btVector3 btSoftBody::clusterCom(int cluster) const
625 return(clusterCom(m_clusters[cluster]));
629 btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos)
631 return(cluster->m_lv+cross(cluster->m_av,rpos));
635 void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
637 const btVector3 li=cluster->m_imass*impulse;
638 const btVector3 ai=cluster->m_invwi*cross(rpos,impulse);
639 cluster->m_vimpulses[0]+=li;cluster->m_lv+=li;
640 cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
641 cluster->m_nvimpulses++;
645 void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
647 const btVector3 li=cluster->m_imass*impulse;
648 const btVector3 ai=cluster->m_invwi*cross(rpos,impulse);
649 cluster->m_dimpulses[0]+=li;
650 cluster->m_dimpulses[1]+=ai;
651 cluster->m_ndimpulses++;
655 void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse)
657 if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity);
658 if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift);
662 void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse)
664 const btVector3 ai=cluster->m_invwi*impulse;
665 cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
666 cluster->m_nvimpulses++;
670 void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse)
672 const btVector3 ai=cluster->m_invwi*impulse;
673 cluster->m_dimpulses[1]+=ai;
674 cluster->m_ndimpulses++;
678 void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse)
680 if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity);
681 if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift);
685 void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse)
687 cluster->m_dimpulses[0]+=impulse*cluster->m_imass;
688 cluster->m_ndimpulses++;
692 int btSoftBody::generateBendingConstraints(int distance,Material* mat)
699 const int n=m_nodes.size();
700 const unsigned inf=(~(unsigned)0)>>1;
701 unsigned* adj=new unsigned[n*n];
702 #define IDX(_x_,_y_) ((_y_)*n+(_x_))
707 if(i!=j) adj[IDX(i,j)]=adj[IDX(j,i)]=inf;
709 adj[IDX(i,j)]=adj[IDX(j,i)]=0;
712 for( i=0;i<m_links.size();++i)
714 const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
715 const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
725 const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
726 if(adj[IDX(i,j)]>sum)
728 adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
739 if(adj[IDX(i,j)]==(unsigned)distance)
742 m_links[m_links.size()-1].m_bbending=1;
754 void btSoftBody::randomizeConstraints()
756 unsigned long seed=243703;
757 #define NEXTRAND (seed=(1664525L*seed+1013904223L)&0xffffffff)
760 for(i=0,ni=m_links.size();i<ni;++i)
762 btSwap(m_links[i],m_links[NEXTRAND%ni]);
764 for(i=0,ni=m_faces.size();i<ni;++i)
766 btSwap(m_faces[i],m_faces[NEXTRAND%ni]);
772 void btSoftBody::releaseCluster(int index)
774 Cluster* c=m_clusters[index];
775 if(c->m_leaf) m_cdbvt.remove(c->m_leaf);
778 m_clusters.remove(c);
782 void btSoftBody::releaseClusters()
784 while(m_clusters.size()>0) releaseCluster(0);
788 int btSoftBody::generateClusters(int k,int maxiterations)
792 m_clusters.resize(btMin(k,m_nodes.size()));
793 for(i=0;i<m_clusters.size();++i)
795 m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
796 m_clusters[i]->m_collide= true;
802 btAlignedObjectArray<btVector3> centers;
803 btVector3 cog(0,0,0);
805 for(i=0;i<m_nodes.size();++i)
808 m_clusters[(i*29873)%m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
810 cog/=(btScalar)m_nodes.size();
811 centers.resize(k,cog);
813 const btScalar slope=16;
817 const btScalar w=2-btMin<btScalar>(1,iterations/slope);
825 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
827 c+=m_clusters[i]->m_nodes[j]->m_x;
829 if(m_clusters[i]->m_nodes.size())
831 c /= (btScalar)m_clusters[i]->m_nodes.size();
832 c = centers[i]+(c-centers[i])*w;
833 changed |= ((c-centers[i]).length2()>SIMD_EPSILON);
835 m_clusters[i]->m_nodes.resize(0);
838 for(i=0;i<m_nodes.size();++i)
840 const btVector3 nx=m_nodes[i].m_x;
842 btScalar kdist=ClusterMetric(centers[0],nx);
845 const btScalar d=ClusterMetric(centers[j],nx);
852 m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
854 } while(changed&&(iterations<maxiterations));
856 btAlignedObjectArray<int> cids;
857 cids.resize(m_nodes.size(),-1);
858 for(i=0;i<m_clusters.size();++i)
860 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
862 cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i;
865 for(i=0;i<m_faces.size();++i)
867 const int idx[]={ int(m_faces[i].m_n[0]-&m_nodes[0]),
868 int(m_faces[i].m_n[1]-&m_nodes[0]),
869 int(m_faces[i].m_n[2]-&m_nodes[0])};
872 const int cid=cids[idx[j]];
875 const int kid=idx[(j+q)%3];
878 if(m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size())
880 m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
887 if(m_clusters.size()>1)
889 Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
890 pmaster->m_collide = false;
891 pmaster->m_nodes.reserve(m_nodes.size());
892 for(int i=0;i<m_nodes.size();++i) pmaster->m_nodes.push_back(&m_nodes[i]);
893 m_clusters.push_back(pmaster);
894 btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]);
897 for(i=0;i<m_clusters.size();++i)
899 if(m_clusters[i]->m_nodes.size()==0)
905 initializeClusters();
907 return(m_clusters.size());
913 void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
915 const Node* nbase = &m_nodes[0];
916 int ncount = m_nodes.size();
917 btSymMatrix<int> edges(ncount,-2);
922 for(i=0;i<m_links.size();++i)
927 if(!SameSign(ifn->Eval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x)))
929 btSwap(m_links[i],m_links[m_links.size()-1]);
930 m_links.pop_back();--i;
935 for(i=0;i<m_links.size();++i)
938 edges(int(l.m_n[0]-nbase),int(l.m_n[1]-nbase))=-1;
940 for(i=0;i<m_faces.size();++i)
943 edges(int(f.m_n[0]-nbase),int(f.m_n[1]-nbase))=-1;
944 edges(int(f.m_n[1]-nbase),int(f.m_n[2]-nbase))=-1;
945 edges(int(f.m_n[2]-nbase),int(f.m_n[0]-nbase))=-1;
948 for(i=0;i<ncount;++i)
950 for(j=i+1;j<ncount;++j)
956 const btScalar t=ImplicitSolve(ifn,a.m_x,b.m_x,accurary);
959 const btVector3 x=Lerp(a.m_x,b.m_x,t);
960 const btVector3 v=Lerp(a.m_v,b.m_v,t);
966 const btScalar ma=1/a.m_im;
967 const btScalar mb=1/b.m_im;
968 const btScalar mc=Lerp(ma,mb,t);
969 const btScalar f=(ma+mb)/(ma+mb+mc);
975 { a.m_im/=0.5;m=1/a.m_im; }
980 { b.m_im/=0.5;m=1/b.m_im; }
985 edges(i,j)=m_nodes.size()-1;
986 m_nodes[edges(i,j)].m_v=v;
994 for(i=0,ni=m_links.size();i<ni;++i)
996 Link& feat=m_links[i];
997 const int idx[]={ int(feat.m_n[0]-nbase),
998 int(feat.m_n[1]-nbase)};
999 if((idx[0]<ncount)&&(idx[1]<ncount))
1001 const int ni=edges(idx[0],idx[1]);
1005 Link* pft[]={ &m_links[i],
1006 &m_links[m_links.size()-1]};
1007 pft[0]->m_n[0]=&m_nodes[idx[0]];
1008 pft[0]->m_n[1]=&m_nodes[ni];
1009 pft[1]->m_n[0]=&m_nodes[ni];
1010 pft[1]->m_n[1]=&m_nodes[idx[1]];
1015 for(i=0;i<m_faces.size();++i)
1017 const Face& feat=m_faces[i];
1018 const int idx[]={ int(feat.m_n[0]-nbase),
1019 int(feat.m_n[1]-nbase),
1020 int(feat.m_n[2]-nbase)};
1021 for(j=2,k=0;k<3;j=k++)
1023 if((idx[j]<ncount)&&(idx[k]<ncount))
1025 const int ni=edges(idx[j],idx[k]);
1029 const int l=(k+1)%3;
1030 Face* pft[]={ &m_faces[i],
1031 &m_faces[m_faces.size()-1]};
1032 pft[0]->m_n[0]=&m_nodes[idx[l]];
1033 pft[0]->m_n[1]=&m_nodes[idx[j]];
1034 pft[0]->m_n[2]=&m_nodes[ni];
1035 pft[1]->m_n[0]=&m_nodes[ni];
1036 pft[1]->m_n[1]=&m_nodes[idx[k]];
1037 pft[1]->m_n[2]=&m_nodes[idx[l]];
1038 appendLink(ni,idx[l],pft[0]->m_material);
1047 btAlignedObjectArray<int> cnodes;
1048 const int pcount=ncount;
1050 ncount=m_nodes.size();
1051 cnodes.resize(ncount,0);
1053 for(i=0;i<ncount;++i)
1055 const btVector3 x=m_nodes[i].m_x;
1056 if((i>=pcount)||(btFabs(ifn->Eval(x))<accurary))
1058 const btVector3 v=m_nodes[i].m_v;
1059 btScalar m=getMass(i);
1060 if(m>0) { m*=0.5;m_nodes[i].m_im/=0.5; }
1062 cnodes[i]=m_nodes.size()-1;
1063 m_nodes[cnodes[i]].m_v=v;
1068 for(i=0,ni=m_links.size();i<ni;++i)
1070 const int id[]={ int(m_links[i].m_n[0]-nbase),
1071 int(m_links[i].m_n[1]-nbase)};
1073 if(cnodes[id[0]]&&cnodes[id[1]])
1076 todetach=m_links.size()-1;
1080 if(( (ifn->Eval(m_nodes[id[0]].m_x)<accurary)&&
1081 (ifn->Eval(m_nodes[id[1]].m_x)<accurary)))
1086 Link& l=m_links[todetach];
1087 for(int j=0;j<2;++j)
1089 int cn=cnodes[int(l.m_n[j]-nbase)];
1090 if(cn) l.m_n[j]=&m_nodes[cn];
1095 for(i=0,ni=m_faces.size();i<ni;++i)
1097 Node** n= m_faces[i].m_n;
1098 if( (ifn->Eval(n[0]->m_x)<accurary)&&
1099 (ifn->Eval(n[1]->m_x)<accurary)&&
1100 (ifn->Eval(n[2]->m_x)<accurary))
1102 for(int j=0;j<3;++j)
1104 int cn=cnodes[int(n[j]-nbase)];
1105 if(cn) n[j]=&m_nodes[cn];
1110 int nnodes=m_nodes.size();
1111 btAlignedObjectArray<int> ranks;
1112 btAlignedObjectArray<int> todelete;
1113 ranks.resize(nnodes,0);
1114 for(i=0,ni=m_links.size();i<ni;++i)
1116 for(int j=0;j<2;++j) ranks[int(m_links[i].m_n[j]-nbase)]++;
1118 for(i=0,ni=m_faces.size();i<ni;++i)
1120 for(int j=0;j<3;++j) ranks[int(m_faces[i].m_n[j]-nbase)]++;
1122 for(i=0;i<m_links.size();++i)
1124 const int id[]={ int(m_links[i].m_n[0]-nbase),
1125 int(m_links[i].m_n[1]-nbase)};
1126 const bool sg[]={ ranks[id[0]]==1,
1132 btSwap(m_links[i],m_links[m_links.size()-1]);
1133 m_links.pop_back();--i;
1137 for(i=nnodes-1;i>=0;--i)
1139 if(!ranks[i]) todelete.push_back(i);
1143 btAlignedObjectArray<int>& map=ranks;
1144 for(int i=0;i<nnodes;++i) map[i]=i;
1145 PointersToIndices(this);
1146 for(int i=0,ni=todelete.size();i<ni;++i)
1150 int& b=map[--nnodes];
1151 m_ndbvt.remove(m_nodes[a].m_leaf);m_nodes[a].m_leaf=0;
1152 btSwap(m_nodes[a],m_nodes[b]);
1155 IndicesToPointers(this,&map[0]);
1156 m_nodes.resize(nnodes);
1160 m_bUpdateRtCst=true;
1164 bool btSoftBody::cutLink(const Node* node0,const Node* node1,btScalar position)
1166 return(cutLink(int(node0-&m_nodes[0]),int(node1-&m_nodes[0]),position));
1170 bool btSoftBody::cutLink(int node0,int node1,btScalar position)
1174 const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
1175 const btVector3 x=Lerp(m_nodes[node0].m_x,m_nodes[node1].m_x,position);
1176 const btVector3 v=Lerp(m_nodes[node0].m_v,m_nodes[node1].m_v,position);
1180 Node* pa=&m_nodes[node0];
1181 Node* pb=&m_nodes[node1];
1182 Node* pn[2]={ &m_nodes[m_nodes.size()-2],
1183 &m_nodes[m_nodes.size()-1]};
1186 for(i=0,ni=m_links.size();i<ni;++i)
1188 const int mtch=MatchEdge(m_links[i].m_n[0],m_links[i].m_n[1],pa,pb);
1192 Link* pft[]={&m_links[i],&m_links[m_links.size()-1]};
1193 pft[0]->m_n[1]=pn[mtch];
1194 pft[1]->m_n[0]=pn[1-mtch];
1198 for(i=0,ni=m_faces.size();i<ni;++i)
1200 for(int k=2,l=0;l<3;k=l++)
1202 const int mtch=MatchEdge(m_faces[i].m_n[k],m_faces[i].m_n[l],pa,pb);
1206 Face* pft[]={&m_faces[i],&m_faces[m_faces.size()-1]};
1207 pft[0]->m_n[l]=pn[mtch];
1208 pft[1]->m_n[k]=pn[1-mtch];
1209 appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1210 appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1216 m_ndbvt.remove(pn[0]->m_leaf);
1217 m_ndbvt.remove(pn[1]->m_leaf);
1225 bool btSoftBody::rayCast(const btVector3& org,
1226 const btVector3& dir,
1230 if(m_faces.size()&&m_fdbvt.empty()) initializeFaceTree();
1231 results.body = this;
1232 results.time = maxtime;
1233 results.feature = eFeature::None;
1235 return(rayCast(org,dir,results.time,results.feature,results.index,false)!=0);
1239 void btSoftBody::setSolver(eSolverPresets::_ preset)
1241 m_cfg.m_vsequence.clear();
1242 m_cfg.m_psequence.clear();
1243 m_cfg.m_dsequence.clear();
1246 case eSolverPresets::Positions:
1247 m_cfg.m_psequence.push_back(ePSolver::Anchors);
1248 m_cfg.m_psequence.push_back(ePSolver::RContacts);
1249 m_cfg.m_psequence.push_back(ePSolver::SContacts);
1250 m_cfg.m_psequence.push_back(ePSolver::Linear);
1252 case eSolverPresets::Velocities:
1253 m_cfg.m_vsequence.push_back(eVSolver::Linear);
1255 m_cfg.m_psequence.push_back(ePSolver::Anchors);
1256 m_cfg.m_psequence.push_back(ePSolver::RContacts);
1257 m_cfg.m_psequence.push_back(ePSolver::SContacts);
1259 m_cfg.m_dsequence.push_back(ePSolver::Linear);
1265 void btSoftBody::predictMotion(btScalar dt)
1272 m_bUpdateRtCst=false;
1275 if(m_cfg.collisions&fCollision::VF_SS)
1277 initializeFaceTree();
1282 m_sst.sdt = dt*m_cfg.timescale;
1283 m_sst.isdt = 1/m_sst.sdt;
1284 m_sst.velmrg = m_sst.sdt*3;
1285 m_sst.radmrg = getCollisionShape()->getMargin();
1286 m_sst.updmrg = m_sst.radmrg*(btScalar)0.25;
1288 addVelocity(m_worldInfo->m_gravity*m_sst.sdt);
1291 for(i=0,ni=m_nodes.size();i<ni;++i)
1295 n.m_v += n.m_f*n.m_im*m_sst.sdt;
1296 n.m_x += n.m_v*m_sst.sdt;
1297 n.m_f = btVector3(0,0,0);
1304 for(i=0,ni=m_nodes.size();i<ni;++i)
1307 m_ndbvt.update( n.m_leaf,
1308 btDbvtVolume::FromCR(n.m_x,m_sst.radmrg),
1313 if(!m_fdbvt.empty())
1315 for(int i=0;i<m_faces.size();++i)
1318 const btVector3 v=( f.m_n[0]->m_v+
1321 m_fdbvt.update( f.m_leaf,
1322 VolumeOf(f,m_sst.radmrg),
1330 if(m_pose.m_bframe&&(m_cfg.kMT>0))
1332 const btMatrix3x3 posetrs=m_pose.m_rot;
1333 for(int i=0,ni=m_nodes.size();i<ni;++i)
1338 const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com;
1339 n.m_x=Lerp(n.m_x,x,m_cfg.kMT);
1343 /* Clear contacts */
1344 m_rcontacts.resize(0);
1345 m_scontacts.resize(0);
1346 /* Optimize dbvt's */
1347 m_ndbvt.optimizeIncremental(1);
1348 m_fdbvt.optimizeIncremental(1);
1349 m_cdbvt.optimizeIncremental(1);
1353 void btSoftBody::solveConstraints()
1355 /* Apply clusters */
1356 applyClusters(false);
1361 for(i=0,ni=m_links.size();i<ni;++i)
1364 l.m_c3 = l.m_n[1]->m_q-l.m_n[0]->m_q;
1365 l.m_c2 = 1/(l.m_c3.length2()*l.m_c0);
1367 /* Prepare anchors */
1368 for(i=0,ni=m_anchors.size();i<ni;++i)
1370 Anchor& a=m_anchors[i];
1371 const btVector3 ra=a.m_body->getWorldTransform().getBasis()*a.m_local;
1372 a.m_c0 = ImpulseMatrix( m_sst.sdt,
1374 a.m_body->getInvMass(),
1375 a.m_body->getInvInertiaTensorWorld(),
1378 a.m_c2 = m_sst.sdt*a.m_node->m_im;
1379 a.m_body->activate();
1381 /* Solve velocities */
1382 if(m_cfg.viterations>0)
1385 for(int isolve=0;isolve<m_cfg.viterations;++isolve)
1387 for(int iseq=0;iseq<m_cfg.m_vsequence.size();++iseq)
1389 getSolver(m_cfg.m_vsequence[iseq])(this,1);
1393 for(i=0,ni=m_nodes.size();i<ni;++i)
1396 n.m_x = n.m_q+n.m_v*m_sst.sdt;
1399 /* Solve positions */
1400 if(m_cfg.piterations>0)
1402 for(int isolve=0;isolve<m_cfg.piterations;++isolve)
1404 const btScalar ti=isolve/(btScalar)m_cfg.piterations;
1405 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1407 getSolver(m_cfg.m_psequence[iseq])(this,1,ti);
1410 const btScalar vc=m_sst.isdt*(1-m_cfg.kDP);
1411 for(i=0,ni=m_nodes.size();i<ni;++i)
1414 n.m_v = (n.m_x-n.m_q)*vc;
1415 n.m_f = btVector3(0,0,0);
1419 if(m_cfg.diterations>0)
1421 const btScalar vcf=m_cfg.kVCF*m_sst.isdt;
1422 for(i=0,ni=m_nodes.size();i<ni;++i)
1427 for(int idrift=0;idrift<m_cfg.diterations;++idrift)
1429 for(int iseq=0;iseq<m_cfg.m_dsequence.size();++iseq)
1431 getSolver(m_cfg.m_dsequence[iseq])(this,1,0);
1434 for(int i=0,ni=m_nodes.size();i<ni;++i)
1437 n.m_v += (n.m_x-n.m_q)*vcf;
1440 /* Apply clusters */
1442 applyClusters(true);
1446 void btSoftBody::staticSolve(int iterations)
1448 for(int isolve=0;isolve<iterations;++isolve)
1450 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1452 getSolver(m_cfg.m_psequence[iseq])(this,1,0);
1458 void btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/,int /*count*/,int /*iterations*/)
1464 void btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
1466 const int nb=bodies.size();
1472 iterations=btMax(iterations,bodies[i]->m_cfg.citerations);
1476 bodies[i]->prepareClusters(iterations);
1478 for(i=0;i<iterations;++i)
1480 const btScalar sor=1;
1481 for(int j=0;j<nb;++j)
1483 bodies[j]->solveClusters(sor);
1488 bodies[i]->cleanupClusters();
1493 void btSoftBody::integrateMotion()
1500 btSoftBody::RayCaster::RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt)
1510 void btSoftBody::RayCaster::Process(const btDbvtNode* leaf)
1512 btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data;
1513 const btScalar t=rayTriangle( o,d,
1518 if((t>0)&&(t<mint)) { mint=t;face=&f; }
1523 btScalar btSoftBody::RayCaster::rayTriangle( const btVector3& org,
1524 const btVector3& dir,
1530 static const btScalar ceps=-SIMD_EPSILON*10;
1531 static const btScalar teps=SIMD_EPSILON*10;
1532 const btVector3 n=cross(b-a,c-a);
1533 const btScalar d=dot(a,n);
1534 const btScalar den=dot(dir,n);
1535 if(!btFuzzyZero(den))
1537 const btScalar num=dot(org,n)-d;
1538 const btScalar t=-num/den;
1539 if((t>teps)&&(t<maxt))
1541 const btVector3 hit=org+dir*t;
1542 if( (dot(n,cross(a-hit,b-hit))>ceps) &&
1543 (dot(n,cross(b-hit,c-hit))>ceps) &&
1544 (dot(n,cross(c-hit,a-hit))>ceps))
1554 void btSoftBody::pointersToIndices()
1556 #define PTR2IDX(_p_,_b_) reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_))
1557 btSoftBody::Node* base=&m_nodes[0];
1560 for(i=0,ni=m_nodes.size();i<ni;++i)
1562 if(m_nodes[i].m_leaf)
1564 m_nodes[i].m_leaf->data=*(void**)&i;
1567 for(i=0,ni=m_links.size();i<ni;++i)
1569 m_links[i].m_n[0]=PTR2IDX(m_links[i].m_n[0],base);
1570 m_links[i].m_n[1]=PTR2IDX(m_links[i].m_n[1],base);
1572 for(i=0,ni=m_faces.size();i<ni;++i)
1574 m_faces[i].m_n[0]=PTR2IDX(m_faces[i].m_n[0],base);
1575 m_faces[i].m_n[1]=PTR2IDX(m_faces[i].m_n[1],base);
1576 m_faces[i].m_n[2]=PTR2IDX(m_faces[i].m_n[2],base);
1577 if(m_faces[i].m_leaf)
1579 m_faces[i].m_leaf->data=*(void**)&i;
1582 for(i=0,ni=m_anchors.size();i<ni;++i)
1584 m_anchors[i].m_node=PTR2IDX(m_anchors[i].m_node,base);
1586 for(i=0,ni=m_notes.size();i<ni;++i)
1588 for(int j=0;j<m_notes[i].m_rank;++j)
1590 m_notes[i].m_nodes[j]=PTR2IDX(m_notes[i].m_nodes[j],base);
1597 void btSoftBody::indicesToPointers(const int* map)
1599 #define IDX2PTR(_p_,_b_) map?(&(_b_)[map[(((char*)_p_)-(char*)0)]]): \
1600 (&(_b_)[(((char*)_p_)-(char*)0)])
1601 btSoftBody::Node* base=&m_nodes[0];
1604 for(i=0,ni=m_nodes.size();i<ni;++i)
1606 if(m_nodes[i].m_leaf)
1608 m_nodes[i].m_leaf->data=&m_nodes[i];
1611 for(i=0,ni=m_links.size();i<ni;++i)
1613 m_links[i].m_n[0]=IDX2PTR(m_links[i].m_n[0],base);
1614 m_links[i].m_n[1]=IDX2PTR(m_links[i].m_n[1],base);
1616 for(i=0,ni=m_faces.size();i<ni;++i)
1618 m_faces[i].m_n[0]=IDX2PTR(m_faces[i].m_n[0],base);
1619 m_faces[i].m_n[1]=IDX2PTR(m_faces[i].m_n[1],base);
1620 m_faces[i].m_n[2]=IDX2PTR(m_faces[i].m_n[2],base);
1621 if(m_faces[i].m_leaf)
1623 m_faces[i].m_leaf->data=&m_faces[i];
1626 for(i=0,ni=m_anchors.size();i<ni;++i)
1628 m_anchors[i].m_node=IDX2PTR(m_anchors[i].m_node,base);
1630 for(i=0,ni=m_notes.size();i<ni;++i)
1632 for(int j=0;j<m_notes[i].m_rank;++j)
1634 m_notes[i].m_nodes[j]=IDX2PTR(m_notes[i].m_nodes[j],base);
1641 int btSoftBody::rayCast(const btVector3& org,const btVector3& dir,
1642 btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const
1645 if(bcountonly||m_fdbvt.empty())
1647 for(int i=0,ni=m_faces.size();i<ni;++i)
1649 const btSoftBody::Face& f=m_faces[i];
1650 const btScalar t=RayCaster::rayTriangle( org,dir,
1660 feature=btSoftBody::eFeature::Face;
1669 RayCaster collider(org,dir,mint);
1670 btDbvt::collideRAY(m_fdbvt.m_root,org,dir,collider);
1674 feature=btSoftBody::eFeature::Face;
1675 index=(int)(collider.face-&m_faces[0]);
1683 void btSoftBody::initializeFaceTree()
1686 for(int i=0;i<m_faces.size();++i)
1689 f.m_leaf=m_fdbvt.insert(VolumeOf(f,0),&f);
1694 btVector3 btSoftBody::evaluateCom() const
1696 btVector3 com(0,0,0);
1699 for(int i=0,ni=m_nodes.size();i<ni;++i)
1701 com+=m_nodes[i].m_x*m_pose.m_wgh[i];
1708 bool btSoftBody::checkContact( btRigidBody* prb,
1711 btSoftBody::sCti& cti) const
1714 btCollisionShape* shp=prb->getCollisionShape();
1715 const btTransform& wtr=prb->getInterpolationWorldTransform();
1716 btScalar dst=m_worldInfo->m_sparsesdf.Evaluate( wtr.invXform(x),
1723 cti.m_normal = wtr.getBasis()*nrm;
1724 cti.m_offset = -dot( cti.m_normal,
1725 x-cti.m_normal*dst);
1732 void btSoftBody::updateNormals()
1734 const btVector3 zv(0,0,0);
1737 for(i=0,ni=m_nodes.size();i<ni;++i)
1741 for(i=0,ni=m_faces.size();i<ni;++i)
1743 btSoftBody::Face& f=m_faces[i];
1744 const btVector3 n=cross(f.m_n[1]->m_x-f.m_n[0]->m_x,
1745 f.m_n[2]->m_x-f.m_n[0]->m_x);
1746 f.m_normal=n.normalized();
1751 for(i=0,ni=m_nodes.size();i<ni;++i)
1753 btScalar len = m_nodes[i].m_n.length();
1754 if (len>SIMD_EPSILON)
1755 m_nodes[i].m_n /= len;
1760 void btSoftBody::updateBounds()
1764 const btVector3& mins=m_ndbvt.m_root->volume.Mins();
1765 const btVector3& maxs=m_ndbvt.m_root->volume.Maxs();
1766 const btScalar csm=getCollisionShape()->getMargin();
1767 const btVector3 mrg=btVector3( csm,
1769 csm)*1; // ??? to investigate...
1770 m_bounds[0]=mins-mrg;
1771 m_bounds[1]=maxs+mrg;
1772 if(0!=getBroadphaseHandle())
1774 m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(),
1777 m_worldInfo->m_dispatcher);
1783 m_bounds[1]=btVector3(0,0,0);
1789 void btSoftBody::updatePose()
1793 btSoftBody::Pose& pose=m_pose;
1794 const btVector3 com=evaluateCom();
1799 const btScalar eps=SIMD_EPSILON;
1800 Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0);
1801 Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3);
1802 for(int i=0,ni=m_nodes.size();i<ni;++i)
1804 const btVector3 a=pose.m_wgh[i]*(m_nodes[i].m_x-com);
1805 const btVector3& b=pose.m_pos[i];
1811 PolarDecompose(Apq,r,s);
1813 pose.m_scl=pose.m_aqq*r.transpose()*Apq;
1814 if(m_cfg.maxvolume>1)
1816 const btScalar idet=Clamp<btScalar>( 1/pose.m_scl.determinant(),
1818 pose.m_scl=Mul(pose.m_scl,idet);
1825 void btSoftBody::updateConstants()
1830 for(i=0,ni=m_links.size();i<ni;++i)
1833 Material& m=*l.m_material;
1834 l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
1835 l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST;
1836 l.m_c1 = l.m_rl*l.m_rl;
1839 for(i=0,ni=m_faces.size();i<ni;++i)
1842 f.m_ra = AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
1845 btAlignedObjectArray<int> counts;
1846 counts.resize(m_nodes.size(),0);
1847 for(i=0,ni=m_nodes.size();i<ni;++i)
1849 m_nodes[i].m_area = 0;
1851 for(i=0,ni=m_faces.size();i<ni;++i)
1853 btSoftBody::Face& f=m_faces[i];
1854 for(int j=0;j<3;++j)
1856 const int index=(int)(f.m_n[j]-&m_nodes[0]);
1858 f.m_n[j]->m_area+=btFabs(f.m_ra);
1861 for(i=0,ni=m_nodes.size();i<ni;++i)
1864 m_nodes[i].m_area/=(btScalar)counts[i];
1866 m_nodes[i].m_area=0;
1871 void btSoftBody::initializeClusters()
1875 for( i=0;i<m_clusters.size();++i)
1877 Cluster& c=*m_clusters[i];
1879 c.m_masses.resize(c.m_nodes.size());
1880 for(int j=0;j<c.m_nodes.size();++j)
1882 c.m_masses[j] = c.m_nodes[j]->m_im>0?1/c.m_nodes[j]->m_im:0;
1883 c.m_imass += c.m_masses[j];
1885 c.m_imass = 1/c.m_imass;
1886 c.m_com = btSoftBody::clusterCom(&c);
1887 c.m_lv = btVector3(0,0,0);
1888 c.m_av = btVector3(0,0,0);
1891 btMatrix3x3& ii=c.m_locii;
1892 ii[0]=ii[1]=ii[2]=btVector3(0,0,0);
1896 for(i=0,ni=c.m_nodes.size();i<ni;++i)
1898 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
1899 const btVector3 q=k*k;
1900 const btScalar m=c.m_masses[i];
1901 ii[0][0] += m*(q[1]+q[2]);
1902 ii[1][1] += m*(q[0]+q[2]);
1903 ii[2][2] += m*(q[0]+q[1]);
1904 ii[0][1] -= m*k[0]*k[1];
1905 ii[0][2] -= m*k[0]*k[2];
1906 ii[1][2] -= m*k[1]*k[2];
1914 c.m_framexform.setIdentity();
1915 c.m_framexform.setOrigin(c.m_com);
1916 c.m_framerefs.resize(c.m_nodes.size());
1919 for(i=0;i<c.m_framerefs.size();++i)
1921 c.m_framerefs[i]=c.m_nodes[i]->m_x-c.m_com;
1928 void btSoftBody::updateClusters()
1930 BT_PROFILE("UpdateClusters");
1933 for(i=0;i<m_clusters.size();++i)
1935 btSoftBody::Cluster& c=*m_clusters[i];
1936 const int n=c.m_nodes.size();
1937 const btScalar invn=1/(btScalar)n;
1941 const btScalar eps=btScalar(0.0001);
1943 m[0]=m[1]=m[2]=btVector3(0,0,0);
1947 c.m_com=clusterCom(&c);
1948 for(int i=0;i<c.m_nodes.size();++i)
1950 const btVector3 a=c.m_nodes[i]->m_x-c.m_com;
1951 const btVector3& b=c.m_framerefs[i];
1952 m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b;
1954 PolarDecompose(m,r,s);
1955 c.m_framexform.setOrigin(c.m_com);
1956 c.m_framexform.setBasis(r);
1959 c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose();
1962 const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass);
1963 const btVector3 inertia(rk,rk,rk);
1964 const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
1965 btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0,
1966 btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
1968 c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
1970 c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0);
1971 for(int i=0;i<n;++i)
1973 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
1974 const btVector3 q=k*k;
1975 const btScalar m=1/c.m_nodes[i]->m_im;
1976 c.m_invwi[0][0] += m*(q[1]+q[2]);
1977 c.m_invwi[1][1] += m*(q[0]+q[2]);
1978 c.m_invwi[2][2] += m*(q[0]+q[1]);
1979 c.m_invwi[0][1] -= m*k[0]*k[1];
1980 c.m_invwi[0][2] -= m*k[0]*k[2];
1981 c.m_invwi[1][2] -= m*k[1]*k[2];
1983 c.m_invwi[1][0]=c.m_invwi[0][1];
1984 c.m_invwi[2][0]=c.m_invwi[0][2];
1985 c.m_invwi[2][1]=c.m_invwi[1][2];
1986 c.m_invwi=c.m_invwi.inverse();
1990 c.m_lv=btVector3(0,0,0);
1991 c.m_av=btVector3(0,0,0);
1997 const btVector3 v=c.m_nodes[i]->m_v*c.m_masses[i];
1999 c.m_av += cross(c.m_nodes[i]->m_x-c.m_com,v);
2002 c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping);
2003 c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping);
2005 c.m_vimpulses[1] = btVector3(0,0,0);
2007 c.m_dimpulses[1] = btVector3(0,0,0);
2013 for(int j=0;j<c.m_nodes.size();++j)
2015 Node& n=*c.m_nodes[j];
2016 const btVector3 x=c.m_framexform*c.m_framerefs[j];
2017 n.m_x=Lerp(n.m_x,x,c.m_matching);
2023 btVector3 mi=c.m_nodes[0]->m_x;
2025 for(int j=1;j<n;++j)
2027 mi.setMin(c.m_nodes[j]->m_x);
2028 mx.setMax(c.m_nodes[j]->m_x);
2030 const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx);
2032 m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg);
2034 c.m_leaf=m_cdbvt.insert(bounds,&c);
2041 void btSoftBody::cleanupClusters()
2043 for(int i=0;i<m_joints.size();++i)
2045 m_joints[i]->Terminate(m_sst.sdt);
2046 if(m_joints[i]->m_delete)
2048 btAlignedFree(m_joints[i]);
2049 m_joints.remove(m_joints[i--]);
2055 void btSoftBody::prepareClusters(int iterations)
2057 for(int i=0;i<m_joints.size();++i)
2059 m_joints[i]->Prepare(m_sst.sdt,iterations);
2065 void btSoftBody::solveClusters(btScalar sor)
2067 for(int i=0,ni=m_joints.size();i<ni;++i)
2069 m_joints[i]->Solve(m_sst.sdt,sor);
2074 void btSoftBody::applyClusters(bool drift)
2076 BT_PROFILE("ApplyClusters");
2077 const btScalar f0=m_sst.sdt;
2078 const btScalar f1=f0/2;
2079 btAlignedObjectArray<btVector3> deltas;
2080 btAlignedObjectArray<btScalar> weights;
2081 deltas.resize(m_nodes.size(),btVector3(0,0,0));
2082 weights.resize(m_nodes.size(),0);
2087 for(i=0;i<m_clusters.size();++i)
2089 Cluster& c=*m_clusters[i];
2092 c.m_dimpulses[0]/=(btScalar)c.m_ndimpulses;
2093 c.m_dimpulses[1]/=(btScalar)c.m_ndimpulses;
2097 for(i=0;i<m_clusters.size();++i)
2099 Cluster& c=*m_clusters[i];
2100 if(0<(drift?c.m_ndimpulses:c.m_nvimpulses))
2102 const btVector3 v=(drift?c.m_dimpulses[0]:c.m_vimpulses[0])*m_sst.sdt;
2103 const btVector3 w=(drift?c.m_dimpulses[1]:c.m_vimpulses[1])*m_sst.sdt;
2104 for(int j=0;j<c.m_nodes.size();++j)
2106 const int idx=int(c.m_nodes[j]-&m_nodes[0]);
2107 const btVector3& x=c.m_nodes[j]->m_x;
2108 const btScalar q=c.m_masses[j];
2109 deltas[idx] += (v+cross(w,x-c.m_com))*q;
2114 for(i=0;i<deltas.size();++i)
2116 if(weights[i]>0) m_nodes[i].m_x+=deltas[i]/weights[i];
2121 void btSoftBody::dampClusters()
2125 for(i=0;i<m_clusters.size();++i)
2127 Cluster& c=*m_clusters[i];
2130 for(int j=0;j<c.m_nodes.size();++j)
2132 Node& n=*c.m_nodes[j];
2135 const btVector3 vx=c.m_lv+cross(c.m_av,c.m_nodes[j]->m_q-c.m_com);
2136 n.m_v += c.m_ndamping*(vx-n.m_v);
2144 void btSoftBody::Joint::Prepare(btScalar dt,int)
2146 m_bodies[0].activate();
2147 m_bodies[1].activate();
2151 void btSoftBody::LJoint::Prepare(btScalar dt,int iterations)
2153 static const btScalar maxdrift=4;
2154 Joint::Prepare(dt,iterations);
2155 m_rpos[0] = m_bodies[0].xform()*m_refs[0];
2156 m_rpos[1] = m_bodies[1].xform()*m_refs[1];
2157 m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt;
2158 m_rpos[0] -= m_bodies[0].xform().getOrigin();
2159 m_rpos[1] -= m_bodies[1].xform().getOrigin();
2160 m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0],
2161 m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]);
2164 m_sdrift = m_massmatrix*(m_drift*m_split);
2165 m_drift *= 1-m_split;
2167 m_drift /=(btScalar)iterations;
2171 void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor)
2173 const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
2174 const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
2175 const btVector3 vr=va-vb;
2176 btSoftBody::Impulse impulse;
2177 impulse.m_asVelocity = 1;
2178 impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor;
2179 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2180 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2184 void btSoftBody::LJoint::Terminate(btScalar dt)
2188 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2189 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2194 void btSoftBody::AJoint::Prepare(btScalar dt,int iterations)
2196 static const btScalar maxdrift=SIMD_PI/16;
2197 m_icontrol->Prepare(this);
2198 Joint::Prepare(dt,iterations);
2199 m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0];
2200 m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1];
2201 m_drift = NormalizeAny(cross(m_axis[1],m_axis[0]));
2202 m_drift *= btMin(maxdrift,btAcos(Clamp<btScalar>(dot(m_axis[0],m_axis[1]),-1,+1)));
2203 m_drift *= m_erp/dt;
2204 m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia());
2207 m_sdrift = m_massmatrix*(m_drift*m_split);
2208 m_drift *= 1-m_split;
2210 m_drift /=(btScalar)iterations;
2214 void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor)
2216 const btVector3 va=m_bodies[0].angularVelocity();
2217 const btVector3 vb=m_bodies[1].angularVelocity();
2218 const btVector3 vr=va-vb;
2219 const btScalar sp=dot(vr,m_axis[0]);
2220 const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp);
2221 btSoftBody::Impulse impulse;
2222 impulse.m_asVelocity = 1;
2223 impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor;
2224 m_bodies[0].applyAImpulse(-impulse);
2225 m_bodies[1].applyAImpulse( impulse);
2229 void btSoftBody::AJoint::Terminate(btScalar dt)
2233 m_bodies[0].applyDAImpulse(-m_sdrift);
2234 m_bodies[1].applyDAImpulse( m_sdrift);
2239 void btSoftBody::CJoint::Prepare(btScalar dt,int iterations)
2241 Joint::Prepare(dt,iterations);
2242 const bool dodrift=(m_life==0);
2243 m_delete=(++m_life)>m_maxlife;
2246 m_drift=m_drift*m_erp/dt;
2249 m_sdrift = m_massmatrix*(m_drift*m_split);
2250 m_drift *= 1-m_split;
2252 m_drift/=(btScalar)iterations;
2256 m_drift=m_sdrift=btVector3(0,0,0);
2261 void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor)
2263 const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
2264 const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
2265 const btVector3 vrel=va-vb;
2266 const btScalar rvac=dot(vrel,m_normal);
2267 btSoftBody::Impulse impulse;
2268 impulse.m_asVelocity = 1;
2269 impulse.m_velocity = m_drift;
2272 const btVector3 iv=m_normal*rvac;
2273 const btVector3 fv=vrel-iv;
2274 impulse.m_velocity += iv+fv*m_friction;
2276 impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor;
2277 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2278 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2282 void btSoftBody::CJoint::Terminate(btScalar dt)
2286 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2287 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2292 void btSoftBody::applyForces()
2294 BT_PROFILE("SoftBody applyForces");
2295 const btScalar dt=m_sst.sdt;
2296 const btScalar kLF=m_cfg.kLF;
2297 const btScalar kDG=m_cfg.kDG;
2298 const btScalar kPR=m_cfg.kPR;
2299 const btScalar kVC=m_cfg.kVC;
2300 const bool as_lift=kLF>0;
2301 const bool as_drag=kDG>0;
2302 const bool as_pressure=kPR!=0;
2303 const bool as_volume=kVC>0;
2304 const bool as_aero= as_lift ||
2306 const bool as_vaero= as_aero &&
2307 (m_cfg.aeromodel<btSoftBody::eAeroModel::F_TwoSided);
2308 const bool as_faero= as_aero &&
2309 (m_cfg.aeromodel>=btSoftBody::eAeroModel::F_TwoSided);
2310 const bool use_medium= as_aero;
2311 const bool use_volume= as_pressure ||
2314 btScalar ivolumetp=0;
2315 btScalar dvolumetv=0;
2316 btSoftBody::sMedium medium;
2319 volume = getVolume();
2320 ivolumetp = 1/btFabs(volume)*kPR;
2321 dvolumetv = (m_pose.m_volume-volume)*kVC;
2323 /* Per vertex forces */
2326 for(i=0,ni=m_nodes.size();i<ni;++i)
2328 btSoftBody::Node& n=m_nodes[i];
2333 EvaluateMedium(m_worldInfo,n.m_x,medium);
2337 const btVector3 rel_v=n.m_v-medium.m_velocity;
2338 const btScalar rel_v2=rel_v.length2();
2339 if(rel_v2>SIMD_EPSILON)
2341 btVector3 nrm=n.m_n;
2343 switch(m_cfg.aeromodel)
2345 case btSoftBody::eAeroModel::V_Point:
2346 nrm=NormalizeAny(rel_v);break;
2347 case btSoftBody::eAeroModel::V_TwoSided:
2348 nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break;
2350 const btScalar dvn=dot(rel_v,nrm);
2351 /* Compute forces */
2354 btVector3 force(0,0,0);
2355 const btScalar c0 = n.m_area*dvn*rel_v2/2;
2356 const btScalar c1 = c0*medium.m_density;
2357 force += nrm*(-c1*kLF);
2358 force += rel_v.normalized()*(-c1*kDG);
2359 ApplyClampedForce(n,force,dt);
2367 n.m_f += n.m_n*(n.m_area*ivolumetp);
2372 n.m_f += n.m_n*(n.m_area*dvolumetv);
2376 /* Per face forces */
2377 for(i=0,ni=m_faces.size();i<ni;++i)
2379 btSoftBody::Face& f=m_faces[i];
2382 const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3;
2383 const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3;
2384 EvaluateMedium(m_worldInfo,x,medium);
2385 const btVector3 rel_v=v-medium.m_velocity;
2386 const btScalar rel_v2=rel_v.length2();
2387 if(rel_v2>SIMD_EPSILON)
2389 btVector3 nrm=f.m_normal;
2391 switch(m_cfg.aeromodel)
2393 case btSoftBody::eAeroModel::F_TwoSided:
2394 nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break;
2396 const btScalar dvn=dot(rel_v,nrm);
2397 /* Compute forces */
2400 btVector3 force(0,0,0);
2401 const btScalar c0 = f.m_ra*dvn*rel_v2;
2402 const btScalar c1 = c0*medium.m_density;
2403 force += nrm*(-c1*kLF);
2404 force += rel_v.normalized()*(-c1*kDG);
2406 for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt);
2414 void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti)
2416 const btScalar kAHR=psb->m_cfg.kAHR*kst;
2417 const btScalar dt=psb->m_sst.sdt;
2418 for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
2420 const Anchor& a=psb->m_anchors[i];
2421 const btTransform& t=a.m_body->getInterpolationWorldTransform();
2423 const btVector3 wa=t*a.m_local;
2424 const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt;
2425 const btVector3 vb=n.m_x-n.m_q;
2426 const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR;
2427 const btVector3 impulse=a.m_c0*vr;
2428 n.m_x+=impulse*a.m_c2;
2429 a.m_body->applyImpulse(-impulse,a.m_c1);
2434 void btSoftBody::PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti)
2436 const btScalar dt=psb->m_sst.sdt;
2437 const btScalar mrg=psb->getCollisionShape()->getMargin();
2438 for(int i=0,ni=psb->m_rcontacts.size();i<ni;++i)
2440 const RContact& c=psb->m_rcontacts[i];
2441 const sCti& cti=c.m_cti;
2442 const btVector3 va=cti.m_body->getVelocityInLocalPoint(c.m_c1)*dt;
2443 const btVector3 vb=c.m_node->m_x-c.m_node->m_q;
2444 const btVector3 vr=vb-va;
2445 const btScalar dn=dot(vr,cti.m_normal);
2446 if(dn<=SIMD_EPSILON)
2448 const btScalar dp=btMin(dot(c.m_node->m_x,cti.m_normal)+cti.m_offset,mrg);
2449 const btVector3 fv=vr-cti.m_normal*dn;
2450 const btVector3 impulse=c.m_c0*((vr-fv*c.m_c3+cti.m_normal*(dp*c.m_c4))*kst);
2451 c.m_node->m_x-=impulse*c.m_c2;
2452 c.m_cti.m_body->applyImpulse(impulse,c.m_c1);
2458 void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti)
2460 for(int i=0,ni=psb->m_scontacts.size();i<ni;++i)
2462 const SContact& c=psb->m_scontacts[i];
2463 const btVector3& nr=c.m_normal;
2466 const btVector3 p=BaryEval( f.m_n[0]->m_x,
2470 const btVector3 q=BaryEval( f.m_n[0]->m_q,
2474 const btVector3 vr=(n.m_x-n.m_q)-(p-q);
2475 btVector3 corr(0,0,0);
2478 const btScalar j=c.m_margin-(dot(nr,n.m_x)-dot(nr,p));
2481 corr -= ProjectOnPlane(vr,nr)*c.m_friction;
2482 n.m_x += corr*c.m_cfm[0];
2483 f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x());
2484 f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y());
2485 f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z());
2490 void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti)
2492 for(int i=0,ni=psb->m_links.size();i<ni;++i)
2494 Link& l=psb->m_links[i];
2499 const btVector3 del=b.m_x-a.m_x;
2500 const btScalar len=del.length2();
2501 const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst;
2502 const btScalar t=k*a.m_im;
2503 a.m_x-=del*(k*a.m_im);
2504 b.m_x+=del*(k*b.m_im);
2510 void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst)
2512 for(int i=0,ni=psb->m_links.size();i<ni;++i)
2514 Link& l=psb->m_links[i];
2516 const btScalar j=-dot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst;
2517 n[0]->m_v+= l.m_c3*(j*n[0]->m_im);
2518 n[1]->m_v-= l.m_c3*(j*n[1]->m_im);
2523 btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver)
2527 case ePSolver::Anchors: return(&btSoftBody::PSolve_Anchors);
2528 case ePSolver::Linear: return(&btSoftBody::PSolve_Links);
2529 case ePSolver::RContacts: return(&btSoftBody::PSolve_RContacts);
2530 case ePSolver::SContacts: return(&btSoftBody::PSolve_SContacts);
2536 btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
2540 case eVSolver::Linear: return(&btSoftBody::VSolve_Links);
2546 void btSoftBody::defaultCollisionHandler(btCollisionObject* pco)
2548 switch(m_cfg.collisions&fCollision::RVSmask)
2550 case fCollision::SDF_RS:
2552 btSoftColliders::CollideSDF_RS docollide;
2553 btRigidBody* prb=btRigidBody::upcast(pco);
2554 const btTransform wtr=prb->getInterpolationWorldTransform();
2555 const btTransform ctr=prb->getWorldTransform();
2556 const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length();
2557 const btScalar basemargin=getCollisionShape()->getMargin();
2560 ATTRIBUTE_ALIGNED16(btDbvtVolume) volume;
2561 pco->getCollisionShape()->getAabb( pco->getInterpolationWorldTransform(),
2564 volume=btDbvtVolume::FromMM(mins,maxs);
2565 volume.Expand(btVector3(basemargin,basemargin,basemargin));
2566 docollide.psb = this;
2567 docollide.prb = prb;
2568 docollide.dynmargin = basemargin+timemargin;
2569 docollide.stamargin = basemargin;
2570 btDbvt::collideTV(m_ndbvt.m_root,volume,docollide);
2573 case fCollision::CL_RS:
2575 btSoftColliders::CollideCL_RS collider;
2576 collider.Process(this,btRigidBody::upcast(pco));
2583 void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
2585 const int cf=m_cfg.collisions&psb->m_cfg.collisions;
2586 switch(cf&fCollision::SVSmask)
2588 case fCollision::CL_SS:
2590 btSoftColliders::CollideCL_SS docollide;
2591 docollide.Process(this,psb);
2594 case fCollision::VF_SS:
2596 btSoftColliders::CollideVF_SS docollide;
2598 docollide.mrg= getCollisionShape()->getMargin()+
2599 psb->getCollisionShape()->getMargin();
2600 /* psb0 nodes vs psb1 faces */
2601 docollide.psb[0]=this;
2602 docollide.psb[1]=psb;
2603 btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root,
2604 docollide.psb[1]->m_fdbvt.m_root,
2606 /* psb1 nodes vs psb0 faces */
2607 docollide.psb[0]=psb;
2608 docollide.psb[1]=this;
2609 btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root,
2610 docollide.psb[1]->m_fdbvt.m_root,