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);
388 void btSoftBody::addVelocity(const btVector3& velocity,int node)
390 Node& n=m_nodes[node];
398 void btSoftBody::setMass(int node,btScalar mass)
400 m_nodes[node].m_im=mass>0?1/mass:0;
405 btScalar btSoftBody::getMass(int node) const
407 return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0);
411 btScalar btSoftBody::getTotalMass() const
414 for(int i=0;i<m_nodes.size();++i)
422 void btSoftBody::setTotalMass(btScalar mass,bool fromfaces)
429 for(i=0;i<m_nodes.size();++i)
433 for(i=0;i<m_faces.size();++i)
435 const Face& f=m_faces[i];
436 const btScalar twicearea=AreaOf( f.m_n[0]->m_x,
441 f.m_n[j]->m_im+=twicearea;
444 for( i=0;i<m_nodes.size();++i)
446 m_nodes[i].m_im=1/m_nodes[i].m_im;
449 const btScalar tm=getTotalMass();
450 const btScalar itm=1/tm;
451 for( i=0;i<m_nodes.size();++i)
453 m_nodes[i].m_im/=itm*mass;
459 void btSoftBody::setTotalDensity(btScalar density)
461 setTotalMass(getVolume()*density,true);
465 void btSoftBody::transform(const btTransform& trs)
467 const btScalar margin=getCollisionShape()->getMargin();
468 for(int i=0,ni=m_nodes.size();i<ni;++i)
473 n.m_n=trs.getBasis()*n.m_n;
474 m_ndbvt.update(n.m_leaf,btDbvtVolume::FromCR(n.m_x,margin));
482 void btSoftBody::translate(const btVector3& trs)
491 void btSoftBody::rotate( const btQuaternion& rot)
500 void btSoftBody::scale(const btVector3& scl)
502 const btScalar margin=getCollisionShape()->getMargin();
503 for(int i=0,ni=m_nodes.size();i<ni;++i)
508 m_ndbvt.update(n.m_leaf,btDbvtVolume::FromCR(n.m_x,margin));
516 void btSoftBody::setPose(bool bvolume,bool bframe)
518 m_pose.m_bvolume = bvolume;
519 m_pose.m_bframe = bframe;
523 const btScalar omass=getTotalMass();
524 const btScalar kmass=omass*m_nodes.size()*1000;
525 btScalar tmass=omass;
526 m_pose.m_wgh.resize(m_nodes.size());
527 for(i=0,ni=m_nodes.size();i<ni;++i)
529 if(m_nodes[i].m_im<=0) tmass+=kmass;
531 for( i=0,ni=m_nodes.size();i<ni;++i)
534 m_pose.m_wgh[i]= n.m_im>0 ?
535 1/(m_nodes[i].m_im*tmass) :
539 const btVector3 com=evaluateCom();
540 m_pose.m_pos.resize(m_nodes.size());
541 for( i=0,ni=m_nodes.size();i<ni;++i)
543 m_pose.m_pos[i]=m_nodes[i].m_x-com;
545 m_pose.m_volume = bvolume?getVolume():0;
547 m_pose.m_rot.setIdentity();
548 m_pose.m_scl.setIdentity();
552 m_pose.m_aqq[2] = btVector3(0,0,0);
553 for( i=0,ni=m_nodes.size();i<ni;++i)
555 const btVector3& q=m_pose.m_pos[i];
556 const btVector3 mq=m_pose.m_wgh[i]*q;
557 m_pose.m_aqq[0]+=mq.x()*q;
558 m_pose.m_aqq[1]+=mq.y()*q;
559 m_pose.m_aqq[2]+=mq.z()*q;
561 m_pose.m_aqq=m_pose.m_aqq.inverse();
566 btScalar btSoftBody::getVolume() const
573 const btVector3 org=m_nodes[0].m_x;
574 for(i=0,ni=m_faces.size();i<ni;++i)
576 const Face& f=m_faces[i];
577 vol+=dot(f.m_n[0]->m_x-org,cross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org));
585 int btSoftBody::clusterCount() const
587 return(m_clusters.size());
591 btVector3 btSoftBody::clusterCom(const Cluster* cluster)
593 btVector3 com(0,0,0);
594 for(int i=0,ni=cluster->m_nodes.size();i<ni;++i)
596 com+=cluster->m_nodes[i]->m_x*cluster->m_masses[i];
598 return(com*cluster->m_imass);
602 btVector3 btSoftBody::clusterCom(int cluster) const
604 return(clusterCom(m_clusters[cluster]));
608 btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos)
610 return(cluster->m_lv+cross(cluster->m_av,rpos));
614 void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
616 const btVector3 li=cluster->m_imass*impulse;
617 const btVector3 ai=cluster->m_invwi*cross(rpos,impulse);
618 cluster->m_vimpulses[0]+=li;cluster->m_lv+=li;
619 cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
620 cluster->m_nvimpulses++;
624 void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
626 const btVector3 li=cluster->m_imass*impulse;
627 const btVector3 ai=cluster->m_invwi*cross(rpos,impulse);
628 cluster->m_dimpulses[0]+=li;
629 cluster->m_dimpulses[1]+=ai;
630 cluster->m_ndimpulses++;
634 void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse)
636 if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity);
637 if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift);
641 void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse)
643 const btVector3 ai=cluster->m_invwi*impulse;
644 cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
645 cluster->m_nvimpulses++;
649 void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse)
651 const btVector3 ai=cluster->m_invwi*impulse;
652 cluster->m_dimpulses[1]+=ai;
653 cluster->m_ndimpulses++;
657 void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse)
659 if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity);
660 if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift);
664 void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse)
666 cluster->m_dimpulses[0]+=impulse*cluster->m_imass;
667 cluster->m_ndimpulses++;
671 int btSoftBody::generateBendingConstraints(int distance,Material* mat)
678 const int n=m_nodes.size();
679 const unsigned inf=(~(unsigned)0)>>1;
680 unsigned* adj=new unsigned[n*n];
681 #define IDX(_x_,_y_) ((_y_)*n+(_x_))
686 if(i!=j) adj[IDX(i,j)]=adj[IDX(j,i)]=inf;
688 adj[IDX(i,j)]=adj[IDX(j,i)]=0;
691 for( i=0;i<m_links.size();++i)
693 const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
694 const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
704 const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
705 if(adj[IDX(i,j)]>sum)
707 adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
718 if(adj[IDX(i,j)]==(unsigned)distance)
721 m_links[m_links.size()-1].m_bbending=1;
733 void btSoftBody::randomizeConstraints()
735 unsigned long seed=243703;
736 #define NEXTRAND (seed=(1664525L*seed+1013904223L)&0xffffffff)
739 for(i=0,ni=m_links.size();i<ni;++i)
741 btSwap(m_links[i],m_links[NEXTRAND%ni]);
743 for(i=0,ni=m_faces.size();i<ni;++i)
745 btSwap(m_faces[i],m_faces[NEXTRAND%ni]);
751 void btSoftBody::releaseCluster(int index)
753 Cluster* c=m_clusters[index];
754 if(c->m_leaf) m_cdbvt.remove(c->m_leaf);
757 m_clusters.remove(c);
761 void btSoftBody::releaseClusters()
763 while(m_clusters.size()>0) releaseCluster(0);
767 int btSoftBody::generateClusters(int k,int maxiterations)
771 m_clusters.resize(btMin(k,m_nodes.size()));
772 for(i=0;i<m_clusters.size();++i)
774 m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
775 m_clusters[i]->m_collide= true;
781 btAlignedObjectArray<btVector3> centers;
782 btVector3 cog(0,0,0);
784 for(i=0;i<m_nodes.size();++i)
787 m_clusters[(i*29873)%m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
789 cog/=(btScalar)m_nodes.size();
790 centers.resize(k,cog);
792 const btScalar slope=16;
796 const btScalar w=2-btMin<btScalar>(1,iterations/slope);
804 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
806 c+=m_clusters[i]->m_nodes[j]->m_x;
808 if(m_clusters[i]->m_nodes.size())
810 c /= (btScalar)m_clusters[i]->m_nodes.size();
811 c = centers[i]+(c-centers[i])*w;
812 changed |= ((c-centers[i]).length2()>SIMD_EPSILON);
814 m_clusters[i]->m_nodes.resize(0);
817 for(i=0;i<m_nodes.size();++i)
819 const btVector3 nx=m_nodes[i].m_x;
821 btScalar kdist=ClusterMetric(centers[0],nx);
824 const btScalar d=ClusterMetric(centers[j],nx);
831 m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
833 } while(changed&&(iterations<maxiterations));
835 btAlignedObjectArray<int> cids;
836 cids.resize(m_nodes.size(),-1);
837 for(i=0;i<m_clusters.size();++i)
839 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
841 cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i;
844 for(i=0;i<m_faces.size();++i)
846 const int idx[]={ int(m_faces[i].m_n[0]-&m_nodes[0]),
847 int(m_faces[i].m_n[1]-&m_nodes[0]),
848 int(m_faces[i].m_n[2]-&m_nodes[0])};
851 const int cid=cids[idx[j]];
854 const int kid=idx[(j+q)%3];
857 if(m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size())
859 m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
866 if(m_clusters.size()>1)
868 Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
869 pmaster->m_collide = false;
870 pmaster->m_nodes.reserve(m_nodes.size());
871 for(int i=0;i<m_nodes.size();++i) pmaster->m_nodes.push_back(&m_nodes[i]);
872 m_clusters.push_back(pmaster);
873 btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]);
876 for(i=0;i<m_clusters.size();++i)
878 if(m_clusters[i]->m_nodes.size()==0)
884 initializeClusters();
886 return(m_clusters.size());
892 void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
894 const Node* nbase = &m_nodes[0];
895 int ncount = m_nodes.size();
896 btSymMatrix<int> edges(ncount,-2);
901 for(i=0;i<m_links.size();++i)
906 if(!SameSign(ifn->Eval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x)))
908 btSwap(m_links[i],m_links[m_links.size()-1]);
909 m_links.pop_back();--i;
914 for(i=0;i<m_links.size();++i)
917 edges(int(l.m_n[0]-nbase),int(l.m_n[1]-nbase))=-1;
919 for(i=0;i<m_faces.size();++i)
922 edges(int(f.m_n[0]-nbase),int(f.m_n[1]-nbase))=-1;
923 edges(int(f.m_n[1]-nbase),int(f.m_n[2]-nbase))=-1;
924 edges(int(f.m_n[2]-nbase),int(f.m_n[0]-nbase))=-1;
927 for(i=0;i<ncount;++i)
929 for(j=i+1;j<ncount;++j)
935 const btScalar t=ImplicitSolve(ifn,a.m_x,b.m_x,accurary);
938 const btVector3 x=Lerp(a.m_x,b.m_x,t);
939 const btVector3 v=Lerp(a.m_v,b.m_v,t);
945 const btScalar ma=1/a.m_im;
946 const btScalar mb=1/b.m_im;
947 const btScalar mc=Lerp(ma,mb,t);
948 const btScalar f=(ma+mb)/(ma+mb+mc);
954 { a.m_im/=0.5;m=1/a.m_im; }
959 { b.m_im/=0.5;m=1/b.m_im; }
964 edges(i,j)=m_nodes.size()-1;
965 m_nodes[edges(i,j)].m_v=v;
973 for(i=0,ni=m_links.size();i<ni;++i)
975 Link& feat=m_links[i];
976 const int idx[]={ int(feat.m_n[0]-nbase),
977 int(feat.m_n[1]-nbase)};
978 if((idx[0]<ncount)&&(idx[1]<ncount))
980 const int ni=edges(idx[0],idx[1]);
984 Link* pft[]={ &m_links[i],
985 &m_links[m_links.size()-1]};
986 pft[0]->m_n[0]=&m_nodes[idx[0]];
987 pft[0]->m_n[1]=&m_nodes[ni];
988 pft[1]->m_n[0]=&m_nodes[ni];
989 pft[1]->m_n[1]=&m_nodes[idx[1]];
994 for(i=0;i<m_faces.size();++i)
996 const Face& feat=m_faces[i];
997 const int idx[]={ int(feat.m_n[0]-nbase),
998 int(feat.m_n[1]-nbase),
999 int(feat.m_n[2]-nbase)};
1000 for(j=2,k=0;k<3;j=k++)
1002 if((idx[j]<ncount)&&(idx[k]<ncount))
1004 const int ni=edges(idx[j],idx[k]);
1008 const int l=(k+1)%3;
1009 Face* pft[]={ &m_faces[i],
1010 &m_faces[m_faces.size()-1]};
1011 pft[0]->m_n[0]=&m_nodes[idx[l]];
1012 pft[0]->m_n[1]=&m_nodes[idx[j]];
1013 pft[0]->m_n[2]=&m_nodes[ni];
1014 pft[1]->m_n[0]=&m_nodes[ni];
1015 pft[1]->m_n[1]=&m_nodes[idx[k]];
1016 pft[1]->m_n[2]=&m_nodes[idx[l]];
1017 appendLink(ni,idx[l],pft[0]->m_material);
1026 btAlignedObjectArray<int> cnodes;
1027 const int pcount=ncount;
1029 ncount=m_nodes.size();
1030 cnodes.resize(ncount,0);
1032 for(i=0;i<ncount;++i)
1034 const btVector3 x=m_nodes[i].m_x;
1035 if((i>=pcount)||(btFabs(ifn->Eval(x))<accurary))
1037 const btVector3 v=m_nodes[i].m_v;
1038 btScalar m=getMass(i);
1039 if(m>0) { m*=0.5;m_nodes[i].m_im/=0.5; }
1041 cnodes[i]=m_nodes.size()-1;
1042 m_nodes[cnodes[i]].m_v=v;
1047 for(i=0,ni=m_links.size();i<ni;++i)
1049 const int id[]={ int(m_links[i].m_n[0]-nbase),
1050 int(m_links[i].m_n[1]-nbase)};
1052 if(cnodes[id[0]]&&cnodes[id[1]])
1055 todetach=m_links.size()-1;
1059 if(( (ifn->Eval(m_nodes[id[0]].m_x)<accurary)&&
1060 (ifn->Eval(m_nodes[id[1]].m_x)<accurary)))
1065 Link& l=m_links[todetach];
1066 for(int j=0;j<2;++j)
1068 int cn=cnodes[int(l.m_n[j]-nbase)];
1069 if(cn) l.m_n[j]=&m_nodes[cn];
1074 for(i=0,ni=m_faces.size();i<ni;++i)
1076 Node** n= m_faces[i].m_n;
1077 if( (ifn->Eval(n[0]->m_x)<accurary)&&
1078 (ifn->Eval(n[1]->m_x)<accurary)&&
1079 (ifn->Eval(n[2]->m_x)<accurary))
1081 for(int j=0;j<3;++j)
1083 int cn=cnodes[int(n[j]-nbase)];
1084 if(cn) n[j]=&m_nodes[cn];
1089 int nnodes=m_nodes.size();
1090 btAlignedObjectArray<int> ranks;
1091 btAlignedObjectArray<int> todelete;
1092 ranks.resize(nnodes,0);
1093 for(i=0,ni=m_links.size();i<ni;++i)
1095 for(int j=0;j<2;++j) ranks[int(m_links[i].m_n[j]-nbase)]++;
1097 for(i=0,ni=m_faces.size();i<ni;++i)
1099 for(int j=0;j<3;++j) ranks[int(m_faces[i].m_n[j]-nbase)]++;
1101 for(i=0;i<m_links.size();++i)
1103 const int id[]={ int(m_links[i].m_n[0]-nbase),
1104 int(m_links[i].m_n[1]-nbase)};
1105 const bool sg[]={ ranks[id[0]]==1,
1111 btSwap(m_links[i],m_links[m_links.size()-1]);
1112 m_links.pop_back();--i;
1116 for(i=nnodes-1;i>=0;--i)
1118 if(!ranks[i]) todelete.push_back(i);
1122 btAlignedObjectArray<int>& map=ranks;
1123 for(int i=0;i<nnodes;++i) map[i]=i;
1124 PointersToIndices(this);
1125 for(int i=0,ni=todelete.size();i<ni;++i)
1129 int& b=map[--nnodes];
1130 m_ndbvt.remove(m_nodes[a].m_leaf);m_nodes[a].m_leaf=0;
1131 btSwap(m_nodes[a],m_nodes[b]);
1134 IndicesToPointers(this,&map[0]);
1135 m_nodes.resize(nnodes);
1139 m_bUpdateRtCst=true;
1143 bool btSoftBody::cutLink(const Node* node0,const Node* node1,btScalar position)
1145 return(cutLink(int(node0-&m_nodes[0]),int(node1-&m_nodes[0]),position));
1149 bool btSoftBody::cutLink(int node0,int node1,btScalar position)
1153 const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
1154 const btVector3 x=Lerp(m_nodes[node0].m_x,m_nodes[node1].m_x,position);
1155 const btVector3 v=Lerp(m_nodes[node0].m_v,m_nodes[node1].m_v,position);
1159 Node* pa=&m_nodes[node0];
1160 Node* pb=&m_nodes[node1];
1161 Node* pn[2]={ &m_nodes[m_nodes.size()-2],
1162 &m_nodes[m_nodes.size()-1]};
1165 for(i=0,ni=m_links.size();i<ni;++i)
1167 const int mtch=MatchEdge(m_links[i].m_n[0],m_links[i].m_n[1],pa,pb);
1171 Link* pft[]={&m_links[i],&m_links[m_links.size()-1]};
1172 pft[0]->m_n[1]=pn[mtch];
1173 pft[1]->m_n[0]=pn[1-mtch];
1177 for(i=0,ni=m_faces.size();i<ni;++i)
1179 for(int k=2,l=0;l<3;k=l++)
1181 const int mtch=MatchEdge(m_faces[i].m_n[k],m_faces[i].m_n[l],pa,pb);
1185 Face* pft[]={&m_faces[i],&m_faces[m_faces.size()-1]};
1186 pft[0]->m_n[l]=pn[mtch];
1187 pft[1]->m_n[k]=pn[1-mtch];
1188 appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1189 appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1195 m_ndbvt.remove(pn[0]->m_leaf);
1196 m_ndbvt.remove(pn[1]->m_leaf);
1204 bool btSoftBody::rayCast(const btVector3& org,
1205 const btVector3& dir,
1209 if(m_faces.size()&&m_fdbvt.empty()) initializeFaceTree();
1210 results.body = this;
1211 results.time = maxtime;
1212 results.feature = eFeature::None;
1214 return(rayCast(org,dir,results.time,results.feature,results.index,false)!=0);
1218 void btSoftBody::setSolver(eSolverPresets::_ preset)
1220 m_cfg.m_vsequence.clear();
1221 m_cfg.m_psequence.clear();
1222 m_cfg.m_dsequence.clear();
1225 case eSolverPresets::Positions:
1226 m_cfg.m_psequence.push_back(ePSolver::Anchors);
1227 m_cfg.m_psequence.push_back(ePSolver::RContacts);
1228 m_cfg.m_psequence.push_back(ePSolver::SContacts);
1229 m_cfg.m_psequence.push_back(ePSolver::Linear);
1231 case eSolverPresets::Velocities:
1232 m_cfg.m_vsequence.push_back(eVSolver::Linear);
1234 m_cfg.m_psequence.push_back(ePSolver::Anchors);
1235 m_cfg.m_psequence.push_back(ePSolver::RContacts);
1236 m_cfg.m_psequence.push_back(ePSolver::SContacts);
1238 m_cfg.m_dsequence.push_back(ePSolver::Linear);
1244 void btSoftBody::predictMotion(btScalar dt)
1251 m_bUpdateRtCst=false;
1254 if(m_cfg.collisions&fCollision::VF_SS)
1256 initializeFaceTree();
1261 m_sst.sdt = dt*m_cfg.timescale;
1262 m_sst.isdt = 1/m_sst.sdt;
1263 m_sst.velmrg = m_sst.sdt*3;
1264 m_sst.radmrg = getCollisionShape()->getMargin();
1265 m_sst.updmrg = m_sst.radmrg*(btScalar)0.25;
1267 addVelocity(m_worldInfo->m_gravity*m_sst.sdt);
1270 for(i=0,ni=m_nodes.size();i<ni;++i)
1274 n.m_v += n.m_f*n.m_im*m_sst.sdt;
1275 n.m_x += n.m_v*m_sst.sdt;
1276 n.m_f = btVector3(0,0,0);
1283 for(i=0,ni=m_nodes.size();i<ni;++i)
1286 m_ndbvt.update( n.m_leaf,
1287 btDbvtVolume::FromCR(n.m_x,m_sst.radmrg),
1292 if(!m_fdbvt.empty())
1294 for(int i=0;i<m_faces.size();++i)
1297 const btVector3 v=( f.m_n[0]->m_v+
1300 m_fdbvt.update( f.m_leaf,
1301 VolumeOf(f,m_sst.radmrg),
1309 if(m_pose.m_bframe&&(m_cfg.kMT>0))
1311 const btMatrix3x3 posetrs=m_pose.m_rot;
1312 for(int i=0,ni=m_nodes.size();i<ni;++i)
1317 const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com;
1318 n.m_x=Lerp(n.m_x,x,m_cfg.kMT);
1322 /* Clear contacts */
1323 m_rcontacts.resize(0);
1324 m_scontacts.resize(0);
1325 /* Optimize dbvt's */
1326 m_ndbvt.optimizeIncremental(1);
1327 m_fdbvt.optimizeIncremental(1);
1328 m_cdbvt.optimizeIncremental(1);
1332 void btSoftBody::solveConstraints()
1334 /* Apply clusters */
1335 applyClusters(false);
1340 for(i=0,ni=m_links.size();i<ni;++i)
1343 l.m_c3 = l.m_n[1]->m_q-l.m_n[0]->m_q;
1344 l.m_c2 = 1/(l.m_c3.length2()*l.m_c0);
1346 /* Prepare anchors */
1347 for(i=0,ni=m_anchors.size();i<ni;++i)
1349 Anchor& a=m_anchors[i];
1350 const btVector3 ra=a.m_body->getWorldTransform().getBasis()*a.m_local;
1351 a.m_c0 = ImpulseMatrix( m_sst.sdt,
1353 a.m_body->getInvMass(),
1354 a.m_body->getInvInertiaTensorWorld(),
1357 a.m_c2 = m_sst.sdt*a.m_node->m_im;
1358 a.m_body->activate();
1360 /* Solve velocities */
1361 if(m_cfg.viterations>0)
1364 for(int isolve=0;isolve<m_cfg.viterations;++isolve)
1366 for(int iseq=0;iseq<m_cfg.m_vsequence.size();++iseq)
1368 getSolver(m_cfg.m_vsequence[iseq])(this,1);
1372 for(i=0,ni=m_nodes.size();i<ni;++i)
1375 n.m_x = n.m_q+n.m_v*m_sst.sdt;
1378 /* Solve positions */
1379 if(m_cfg.piterations>0)
1381 for(int isolve=0;isolve<m_cfg.piterations;++isolve)
1383 const btScalar ti=isolve/(btScalar)m_cfg.piterations;
1384 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1386 getSolver(m_cfg.m_psequence[iseq])(this,1,ti);
1389 const btScalar vc=m_sst.isdt*(1-m_cfg.kDP);
1390 for(i=0,ni=m_nodes.size();i<ni;++i)
1393 n.m_v = (n.m_x-n.m_q)*vc;
1394 n.m_f = btVector3(0,0,0);
1398 if(m_cfg.diterations>0)
1400 const btScalar vcf=m_cfg.kVCF*m_sst.isdt;
1401 for(i=0,ni=m_nodes.size();i<ni;++i)
1406 for(int idrift=0;idrift<m_cfg.diterations;++idrift)
1408 for(int iseq=0;iseq<m_cfg.m_dsequence.size();++iseq)
1410 getSolver(m_cfg.m_dsequence[iseq])(this,1,0);
1413 for(int i=0,ni=m_nodes.size();i<ni;++i)
1416 n.m_v += (n.m_x-n.m_q)*vcf;
1419 /* Apply clusters */
1421 applyClusters(true);
1425 void btSoftBody::staticSolve(int iterations)
1427 for(int isolve=0;isolve<iterations;++isolve)
1429 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1431 getSolver(m_cfg.m_psequence[iseq])(this,1,0);
1437 void btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/,int /*count*/,int /*iterations*/)
1443 void btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
1445 const int nb=bodies.size();
1451 iterations=btMax(iterations,bodies[i]->m_cfg.citerations);
1455 bodies[i]->prepareClusters(iterations);
1457 for(i=0;i<iterations;++i)
1459 const btScalar sor=1;
1460 for(int j=0;j<nb;++j)
1462 bodies[j]->solveClusters(sor);
1467 bodies[i]->cleanupClusters();
1472 void btSoftBody::integrateMotion()
1479 btSoftBody::RayCaster::RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt)
1489 void btSoftBody::RayCaster::Process(const btDbvtNode* leaf)
1491 btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data;
1492 const btScalar t=rayTriangle( o,d,
1497 if((t>0)&&(t<mint)) { mint=t;face=&f; }
1502 btScalar btSoftBody::RayCaster::rayTriangle( const btVector3& org,
1503 const btVector3& dir,
1509 static const btScalar ceps=-SIMD_EPSILON*10;
1510 static const btScalar teps=SIMD_EPSILON*10;
1511 const btVector3 n=cross(b-a,c-a);
1512 const btScalar d=dot(a,n);
1513 const btScalar den=dot(dir,n);
1514 if(!btFuzzyZero(den))
1516 const btScalar num=dot(org,n)-d;
1517 const btScalar t=-num/den;
1518 if((t>teps)&&(t<maxt))
1520 const btVector3 hit=org+dir*t;
1521 if( (dot(n,cross(a-hit,b-hit))>ceps) &&
1522 (dot(n,cross(b-hit,c-hit))>ceps) &&
1523 (dot(n,cross(c-hit,a-hit))>ceps))
1533 void btSoftBody::pointersToIndices()
1535 #define PTR2IDX(_p_,_b_) reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_))
1536 btSoftBody::Node* base=&m_nodes[0];
1539 for(i=0,ni=m_nodes.size();i<ni;++i)
1541 if(m_nodes[i].m_leaf)
1543 m_nodes[i].m_leaf->data=*(void**)&i;
1546 for(i=0,ni=m_links.size();i<ni;++i)
1548 m_links[i].m_n[0]=PTR2IDX(m_links[i].m_n[0],base);
1549 m_links[i].m_n[1]=PTR2IDX(m_links[i].m_n[1],base);
1551 for(i=0,ni=m_faces.size();i<ni;++i)
1553 m_faces[i].m_n[0]=PTR2IDX(m_faces[i].m_n[0],base);
1554 m_faces[i].m_n[1]=PTR2IDX(m_faces[i].m_n[1],base);
1555 m_faces[i].m_n[2]=PTR2IDX(m_faces[i].m_n[2],base);
1556 if(m_faces[i].m_leaf)
1558 m_faces[i].m_leaf->data=*(void**)&i;
1561 for(i=0,ni=m_anchors.size();i<ni;++i)
1563 m_anchors[i].m_node=PTR2IDX(m_anchors[i].m_node,base);
1565 for(i=0,ni=m_notes.size();i<ni;++i)
1567 for(int j=0;j<m_notes[i].m_rank;++j)
1569 m_notes[i].m_nodes[j]=PTR2IDX(m_notes[i].m_nodes[j],base);
1576 void btSoftBody::indicesToPointers(const int* map)
1578 #define IDX2PTR(_p_,_b_) map?(&(_b_)[map[(((char*)_p_)-(char*)0)]]): \
1579 (&(_b_)[(((char*)_p_)-(char*)0)])
1580 btSoftBody::Node* base=&m_nodes[0];
1583 for(i=0,ni=m_nodes.size();i<ni;++i)
1585 if(m_nodes[i].m_leaf)
1587 m_nodes[i].m_leaf->data=&m_nodes[i];
1590 for(i=0,ni=m_links.size();i<ni;++i)
1592 m_links[i].m_n[0]=IDX2PTR(m_links[i].m_n[0],base);
1593 m_links[i].m_n[1]=IDX2PTR(m_links[i].m_n[1],base);
1595 for(i=0,ni=m_faces.size();i<ni;++i)
1597 m_faces[i].m_n[0]=IDX2PTR(m_faces[i].m_n[0],base);
1598 m_faces[i].m_n[1]=IDX2PTR(m_faces[i].m_n[1],base);
1599 m_faces[i].m_n[2]=IDX2PTR(m_faces[i].m_n[2],base);
1600 if(m_faces[i].m_leaf)
1602 m_faces[i].m_leaf->data=&m_faces[i];
1605 for(i=0,ni=m_anchors.size();i<ni;++i)
1607 m_anchors[i].m_node=IDX2PTR(m_anchors[i].m_node,base);
1609 for(i=0,ni=m_notes.size();i<ni;++i)
1611 for(int j=0;j<m_notes[i].m_rank;++j)
1613 m_notes[i].m_nodes[j]=IDX2PTR(m_notes[i].m_nodes[j],base);
1620 int btSoftBody::rayCast(const btVector3& org,const btVector3& dir,
1621 btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const
1624 if(bcountonly||m_fdbvt.empty())
1626 for(int i=0,ni=m_faces.size();i<ni;++i)
1628 const btSoftBody::Face& f=m_faces[i];
1629 const btScalar t=RayCaster::rayTriangle( org,dir,
1639 feature=btSoftBody::eFeature::Face;
1648 RayCaster collider(org,dir,mint);
1649 btDbvt::collideRAY(m_fdbvt.m_root,org,dir,collider);
1653 feature=btSoftBody::eFeature::Face;
1654 index=(int)(collider.face-&m_faces[0]);
1662 void btSoftBody::initializeFaceTree()
1665 for(int i=0;i<m_faces.size();++i)
1668 f.m_leaf=m_fdbvt.insert(VolumeOf(f,0),&f);
1673 btVector3 btSoftBody::evaluateCom() const
1675 btVector3 com(0,0,0);
1678 for(int i=0,ni=m_nodes.size();i<ni;++i)
1680 com+=m_nodes[i].m_x*m_pose.m_wgh[i];
1687 bool btSoftBody::checkContact( btRigidBody* prb,
1690 btSoftBody::sCti& cti) const
1693 btCollisionShape* shp=prb->getCollisionShape();
1694 const btTransform& wtr=prb->getInterpolationWorldTransform();
1695 btScalar dst=m_worldInfo->m_sparsesdf.Evaluate( wtr.invXform(x),
1702 cti.m_normal = wtr.getBasis()*nrm;
1703 cti.m_offset = -dot( cti.m_normal,
1704 x-cti.m_normal*dst);
1711 void btSoftBody::updateNormals()
1713 const btVector3 zv(0,0,0);
1716 for(i=0,ni=m_nodes.size();i<ni;++i)
1720 for(i=0,ni=m_faces.size();i<ni;++i)
1722 btSoftBody::Face& f=m_faces[i];
1723 const btVector3 n=cross(f.m_n[1]->m_x-f.m_n[0]->m_x,
1724 f.m_n[2]->m_x-f.m_n[0]->m_x);
1725 f.m_normal=n.normalized();
1730 for(i=0,ni=m_nodes.size();i<ni;++i)
1732 btScalar len = m_nodes[i].m_n.length();
1733 if (len>SIMD_EPSILON)
1734 m_nodes[i].m_n /= len;
1739 void btSoftBody::updateBounds()
1743 const btVector3& mins=m_ndbvt.m_root->volume.Mins();
1744 const btVector3& maxs=m_ndbvt.m_root->volume.Maxs();
1745 const btScalar csm=getCollisionShape()->getMargin();
1746 const btVector3 mrg=btVector3( csm,
1748 csm)*1; // ??? to investigate...
1749 m_bounds[0]=mins-mrg;
1750 m_bounds[1]=maxs+mrg;
1751 if(0!=getBroadphaseHandle())
1753 m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(),
1756 m_worldInfo->m_dispatcher);
1762 m_bounds[1]=btVector3(0,0,0);
1768 void btSoftBody::updatePose()
1772 btSoftBody::Pose& pose=m_pose;
1773 const btVector3 com=evaluateCom();
1778 const btScalar eps=SIMD_EPSILON;
1779 Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0);
1780 Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3);
1781 for(int i=0,ni=m_nodes.size();i<ni;++i)
1783 const btVector3 a=pose.m_wgh[i]*(m_nodes[i].m_x-com);
1784 const btVector3& b=pose.m_pos[i];
1790 PolarDecompose(Apq,r,s);
1792 pose.m_scl=pose.m_aqq*r.transpose()*Apq;
1793 if(m_cfg.maxvolume>1)
1795 const btScalar idet=Clamp<btScalar>( 1/pose.m_scl.determinant(),
1797 pose.m_scl=Mul(pose.m_scl,idet);
1804 void btSoftBody::updateConstants()
1809 for(i=0,ni=m_links.size();i<ni;++i)
1812 Material& m=*l.m_material;
1813 l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
1814 l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST;
1815 l.m_c1 = l.m_rl*l.m_rl;
1818 for(i=0,ni=m_faces.size();i<ni;++i)
1821 f.m_ra = AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
1824 btAlignedObjectArray<int> counts;
1825 counts.resize(m_nodes.size(),0);
1826 for(i=0,ni=m_nodes.size();i<ni;++i)
1828 m_nodes[i].m_area = 0;
1830 for(i=0,ni=m_faces.size();i<ni;++i)
1832 btSoftBody::Face& f=m_faces[i];
1833 for(int j=0;j<3;++j)
1835 const int index=(int)(f.m_n[j]-&m_nodes[0]);
1837 f.m_n[j]->m_area+=btFabs(f.m_ra);
1840 for(i=0,ni=m_nodes.size();i<ni;++i)
1843 m_nodes[i].m_area/=(btScalar)counts[i];
1845 m_nodes[i].m_area=0;
1850 void btSoftBody::initializeClusters()
1854 for( i=0;i<m_clusters.size();++i)
1856 Cluster& c=*m_clusters[i];
1858 c.m_masses.resize(c.m_nodes.size());
1859 for(int j=0;j<c.m_nodes.size();++j)
1861 c.m_masses[j] = c.m_nodes[j]->m_im>0?1/c.m_nodes[j]->m_im:0;
1862 c.m_imass += c.m_masses[j];
1864 c.m_imass = 1/c.m_imass;
1865 c.m_com = btSoftBody::clusterCom(&c);
1866 c.m_lv = btVector3(0,0,0);
1867 c.m_av = btVector3(0,0,0);
1870 btMatrix3x3& ii=c.m_locii;
1871 ii[0]=ii[1]=ii[2]=btVector3(0,0,0);
1875 for(i=0,ni=c.m_nodes.size();i<ni;++i)
1877 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
1878 const btVector3 q=k*k;
1879 const btScalar m=c.m_masses[i];
1880 ii[0][0] += m*(q[1]+q[2]);
1881 ii[1][1] += m*(q[0]+q[2]);
1882 ii[2][2] += m*(q[0]+q[1]);
1883 ii[0][1] -= m*k[0]*k[1];
1884 ii[0][2] -= m*k[0]*k[2];
1885 ii[1][2] -= m*k[1]*k[2];
1893 c.m_framexform.setIdentity();
1894 c.m_framexform.setOrigin(c.m_com);
1895 c.m_framerefs.resize(c.m_nodes.size());
1898 for(i=0;i<c.m_framerefs.size();++i)
1900 c.m_framerefs[i]=c.m_nodes[i]->m_x-c.m_com;
1907 void btSoftBody::updateClusters()
1909 BT_PROFILE("UpdateClusters");
1912 for(i=0;i<m_clusters.size();++i)
1914 btSoftBody::Cluster& c=*m_clusters[i];
1915 const int n=c.m_nodes.size();
1916 const btScalar invn=1/(btScalar)n;
1920 const btScalar eps=btScalar(0.0001);
1922 m[0]=m[1]=m[2]=btVector3(0,0,0);
1926 c.m_com=clusterCom(&c);
1927 for(int i=0;i<c.m_nodes.size();++i)
1929 const btVector3 a=c.m_nodes[i]->m_x-c.m_com;
1930 const btVector3& b=c.m_framerefs[i];
1931 m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b;
1933 PolarDecompose(m,r,s);
1934 c.m_framexform.setOrigin(c.m_com);
1935 c.m_framexform.setBasis(r);
1938 c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose();
1941 const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass);
1942 const btVector3 inertia(rk,rk,rk);
1943 const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
1944 btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0,
1945 btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
1947 c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
1949 c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0);
1950 for(int i=0;i<n;++i)
1952 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
1953 const btVector3 q=k*k;
1954 const btScalar m=1/c.m_nodes[i]->m_im;
1955 c.m_invwi[0][0] += m*(q[1]+q[2]);
1956 c.m_invwi[1][1] += m*(q[0]+q[2]);
1957 c.m_invwi[2][2] += m*(q[0]+q[1]);
1958 c.m_invwi[0][1] -= m*k[0]*k[1];
1959 c.m_invwi[0][2] -= m*k[0]*k[2];
1960 c.m_invwi[1][2] -= m*k[1]*k[2];
1962 c.m_invwi[1][0]=c.m_invwi[0][1];
1963 c.m_invwi[2][0]=c.m_invwi[0][2];
1964 c.m_invwi[2][1]=c.m_invwi[1][2];
1965 c.m_invwi=c.m_invwi.inverse();
1969 c.m_lv=btVector3(0,0,0);
1970 c.m_av=btVector3(0,0,0);
1976 const btVector3 v=c.m_nodes[i]->m_v*c.m_masses[i];
1978 c.m_av += cross(c.m_nodes[i]->m_x-c.m_com,v);
1981 c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping);
1982 c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping);
1984 c.m_vimpulses[1] = btVector3(0,0,0);
1986 c.m_dimpulses[1] = btVector3(0,0,0);
1992 for(int j=0;j<c.m_nodes.size();++j)
1994 Node& n=*c.m_nodes[j];
1995 const btVector3 x=c.m_framexform*c.m_framerefs[j];
1996 n.m_x=Lerp(n.m_x,x,c.m_matching);
2002 btVector3 mi=c.m_nodes[0]->m_x;
2004 for(int j=1;j<n;++j)
2006 mi.setMin(c.m_nodes[j]->m_x);
2007 mx.setMax(c.m_nodes[j]->m_x);
2009 const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx);
2011 m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg);
2013 c.m_leaf=m_cdbvt.insert(bounds,&c);
2020 void btSoftBody::cleanupClusters()
2022 for(int i=0;i<m_joints.size();++i)
2024 m_joints[i]->Terminate(m_sst.sdt);
2025 if(m_joints[i]->m_delete)
2027 btAlignedFree(m_joints[i]);
2028 m_joints.remove(m_joints[i--]);
2034 void btSoftBody::prepareClusters(int iterations)
2036 for(int i=0;i<m_joints.size();++i)
2038 m_joints[i]->Prepare(m_sst.sdt,iterations);
2044 void btSoftBody::solveClusters(btScalar sor)
2046 for(int i=0,ni=m_joints.size();i<ni;++i)
2048 m_joints[i]->Solve(m_sst.sdt,sor);
2053 void btSoftBody::applyClusters(bool drift)
2055 BT_PROFILE("ApplyClusters");
2056 const btScalar f0=m_sst.sdt;
2057 const btScalar f1=f0/2;
2058 btAlignedObjectArray<btVector3> deltas;
2059 btAlignedObjectArray<btScalar> weights;
2060 deltas.resize(m_nodes.size(),btVector3(0,0,0));
2061 weights.resize(m_nodes.size(),0);
2066 for(i=0;i<m_clusters.size();++i)
2068 Cluster& c=*m_clusters[i];
2071 c.m_dimpulses[0]/=(btScalar)c.m_ndimpulses;
2072 c.m_dimpulses[1]/=(btScalar)c.m_ndimpulses;
2076 for(i=0;i<m_clusters.size();++i)
2078 Cluster& c=*m_clusters[i];
2079 if(0<(drift?c.m_ndimpulses:c.m_nvimpulses))
2081 const btVector3 v=(drift?c.m_dimpulses[0]:c.m_vimpulses[0])*m_sst.sdt;
2082 const btVector3 w=(drift?c.m_dimpulses[1]:c.m_vimpulses[1])*m_sst.sdt;
2083 for(int j=0;j<c.m_nodes.size();++j)
2085 const int idx=int(c.m_nodes[j]-&m_nodes[0]);
2086 const btVector3& x=c.m_nodes[j]->m_x;
2087 const btScalar q=c.m_masses[j];
2088 deltas[idx] += (v+cross(w,x-c.m_com))*q;
2093 for(i=0;i<deltas.size();++i)
2095 if(weights[i]>0) m_nodes[i].m_x+=deltas[i]/weights[i];
2100 void btSoftBody::dampClusters()
2104 for(i=0;i<m_clusters.size();++i)
2106 Cluster& c=*m_clusters[i];
2109 for(int j=0;j<c.m_nodes.size();++j)
2111 Node& n=*c.m_nodes[j];
2114 const btVector3 vx=c.m_lv+cross(c.m_av,c.m_nodes[j]->m_q-c.m_com);
2115 n.m_v += c.m_ndamping*(vx-n.m_v);
2123 void btSoftBody::Joint::Prepare(btScalar dt,int)
2125 m_bodies[0].activate();
2126 m_bodies[1].activate();
2130 void btSoftBody::LJoint::Prepare(btScalar dt,int iterations)
2132 static const btScalar maxdrift=4;
2133 Joint::Prepare(dt,iterations);
2134 m_rpos[0] = m_bodies[0].xform()*m_refs[0];
2135 m_rpos[1] = m_bodies[1].xform()*m_refs[1];
2136 m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt;
2137 m_rpos[0] -= m_bodies[0].xform().getOrigin();
2138 m_rpos[1] -= m_bodies[1].xform().getOrigin();
2139 m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0],
2140 m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]);
2143 m_sdrift = m_massmatrix*(m_drift*m_split);
2144 m_drift *= 1-m_split;
2146 m_drift /=(btScalar)iterations;
2150 void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor)
2152 const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
2153 const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
2154 const btVector3 vr=va-vb;
2155 btSoftBody::Impulse impulse;
2156 impulse.m_asVelocity = 1;
2157 impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor;
2158 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2159 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2163 void btSoftBody::LJoint::Terminate(btScalar dt)
2167 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2168 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2173 void btSoftBody::AJoint::Prepare(btScalar dt,int iterations)
2175 static const btScalar maxdrift=SIMD_PI/16;
2176 m_icontrol->Prepare(this);
2177 Joint::Prepare(dt,iterations);
2178 m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0];
2179 m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1];
2180 m_drift = NormalizeAny(cross(m_axis[1],m_axis[0]));
2181 m_drift *= btMin(maxdrift,btAcos(Clamp<btScalar>(dot(m_axis[0],m_axis[1]),-1,+1)));
2182 m_drift *= m_erp/dt;
2183 m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia());
2186 m_sdrift = m_massmatrix*(m_drift*m_split);
2187 m_drift *= 1-m_split;
2189 m_drift /=(btScalar)iterations;
2193 void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor)
2195 const btVector3 va=m_bodies[0].angularVelocity();
2196 const btVector3 vb=m_bodies[1].angularVelocity();
2197 const btVector3 vr=va-vb;
2198 const btScalar sp=dot(vr,m_axis[0]);
2199 const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp);
2200 btSoftBody::Impulse impulse;
2201 impulse.m_asVelocity = 1;
2202 impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor;
2203 m_bodies[0].applyAImpulse(-impulse);
2204 m_bodies[1].applyAImpulse( impulse);
2208 void btSoftBody::AJoint::Terminate(btScalar dt)
2212 m_bodies[0].applyDAImpulse(-m_sdrift);
2213 m_bodies[1].applyDAImpulse( m_sdrift);
2218 void btSoftBody::CJoint::Prepare(btScalar dt,int iterations)
2220 Joint::Prepare(dt,iterations);
2221 const bool dodrift=(m_life==0);
2222 m_delete=(++m_life)>m_maxlife;
2225 m_drift=m_drift*m_erp/dt;
2228 m_sdrift = m_massmatrix*(m_drift*m_split);
2229 m_drift *= 1-m_split;
2231 m_drift/=(btScalar)iterations;
2235 m_drift=m_sdrift=btVector3(0,0,0);
2240 void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor)
2242 const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
2243 const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
2244 const btVector3 vrel=va-vb;
2245 const btScalar rvac=dot(vrel,m_normal);
2246 btSoftBody::Impulse impulse;
2247 impulse.m_asVelocity = 1;
2248 impulse.m_velocity = m_drift;
2251 const btVector3 iv=m_normal*rvac;
2252 const btVector3 fv=vrel-iv;
2253 impulse.m_velocity += iv+fv*m_friction;
2255 impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor;
2256 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2257 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2261 void btSoftBody::CJoint::Terminate(btScalar dt)
2265 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2266 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2271 void btSoftBody::applyForces()
2273 BT_PROFILE("SoftBody applyForces");
2274 const btScalar dt=m_sst.sdt;
2275 const btScalar kLF=m_cfg.kLF;
2276 const btScalar kDG=m_cfg.kDG;
2277 const btScalar kPR=m_cfg.kPR;
2278 const btScalar kVC=m_cfg.kVC;
2279 const bool as_lift=kLF>0;
2280 const bool as_drag=kDG>0;
2281 const bool as_pressure=kPR!=0;
2282 const bool as_volume=kVC>0;
2283 const bool as_aero= as_lift ||
2285 const bool as_vaero= as_aero &&
2286 (m_cfg.aeromodel<btSoftBody::eAeroModel::F_TwoSided);
2287 const bool as_faero= as_aero &&
2288 (m_cfg.aeromodel>=btSoftBody::eAeroModel::F_TwoSided);
2289 const bool use_medium= as_aero;
2290 const bool use_volume= as_pressure ||
2293 btScalar ivolumetp=0;
2294 btScalar dvolumetv=0;
2295 btSoftBody::sMedium medium;
2298 volume = getVolume();
2299 ivolumetp = 1/btFabs(volume)*kPR;
2300 dvolumetv = (m_pose.m_volume-volume)*kVC;
2302 /* Per vertex forces */
2305 for(i=0,ni=m_nodes.size();i<ni;++i)
2307 btSoftBody::Node& n=m_nodes[i];
2312 EvaluateMedium(m_worldInfo,n.m_x,medium);
2316 const btVector3 rel_v=n.m_v-medium.m_velocity;
2317 const btScalar rel_v2=rel_v.length2();
2318 if(rel_v2>SIMD_EPSILON)
2320 btVector3 nrm=n.m_n;
2322 switch(m_cfg.aeromodel)
2324 case btSoftBody::eAeroModel::V_Point:
2325 nrm=NormalizeAny(rel_v);break;
2326 case btSoftBody::eAeroModel::V_TwoSided:
2327 nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break;
2329 const btScalar dvn=dot(rel_v,nrm);
2330 /* Compute forces */
2333 btVector3 force(0,0,0);
2334 const btScalar c0 = n.m_area*dvn*rel_v2/2;
2335 const btScalar c1 = c0*medium.m_density;
2336 force += nrm*(-c1*kLF);
2337 force += rel_v.normalized()*(-c1*kDG);
2338 ApplyClampedForce(n,force,dt);
2346 n.m_f += n.m_n*(n.m_area*ivolumetp);
2351 n.m_f += n.m_n*(n.m_area*dvolumetv);
2355 /* Per face forces */
2356 for(i=0,ni=m_faces.size();i<ni;++i)
2358 btSoftBody::Face& f=m_faces[i];
2361 const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3;
2362 const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3;
2363 EvaluateMedium(m_worldInfo,x,medium);
2364 const btVector3 rel_v=v-medium.m_velocity;
2365 const btScalar rel_v2=rel_v.length2();
2366 if(rel_v2>SIMD_EPSILON)
2368 btVector3 nrm=f.m_normal;
2370 switch(m_cfg.aeromodel)
2372 case btSoftBody::eAeroModel::F_TwoSided:
2373 nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break;
2375 const btScalar dvn=dot(rel_v,nrm);
2376 /* Compute forces */
2379 btVector3 force(0,0,0);
2380 const btScalar c0 = f.m_ra*dvn*rel_v2;
2381 const btScalar c1 = c0*medium.m_density;
2382 force += nrm*(-c1*kLF);
2383 force += rel_v.normalized()*(-c1*kDG);
2385 for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt);
2393 void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti)
2395 const btScalar kAHR=psb->m_cfg.kAHR*kst;
2396 const btScalar dt=psb->m_sst.sdt;
2397 for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
2399 const Anchor& a=psb->m_anchors[i];
2400 const btTransform& t=a.m_body->getInterpolationWorldTransform();
2402 const btVector3 wa=t*a.m_local;
2403 const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt;
2404 const btVector3 vb=n.m_x-n.m_q;
2405 const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR;
2406 const btVector3 impulse=a.m_c0*vr;
2407 n.m_x+=impulse*a.m_c2;
2408 a.m_body->applyImpulse(-impulse,a.m_c1);
2413 void btSoftBody::PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti)
2415 const btScalar dt=psb->m_sst.sdt;
2416 const btScalar mrg=psb->getCollisionShape()->getMargin();
2417 for(int i=0,ni=psb->m_rcontacts.size();i<ni;++i)
2419 const RContact& c=psb->m_rcontacts[i];
2420 const sCti& cti=c.m_cti;
2421 const btVector3 va=cti.m_body->getVelocityInLocalPoint(c.m_c1)*dt;
2422 const btVector3 vb=c.m_node->m_x-c.m_node->m_q;
2423 const btVector3 vr=vb-va;
2424 const btScalar dn=dot(vr,cti.m_normal);
2425 if(dn<=SIMD_EPSILON)
2427 const btScalar dp=btMin(dot(c.m_node->m_x,cti.m_normal)+cti.m_offset,mrg);
2428 const btVector3 fv=vr-cti.m_normal*dn;
2429 const btVector3 impulse=c.m_c0*((vr-fv*c.m_c3+cti.m_normal*(dp*c.m_c4))*kst);
2430 c.m_node->m_x-=impulse*c.m_c2;
2431 c.m_cti.m_body->applyImpulse(impulse,c.m_c1);
2437 void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti)
2439 for(int i=0,ni=psb->m_scontacts.size();i<ni;++i)
2441 const SContact& c=psb->m_scontacts[i];
2442 const btVector3& nr=c.m_normal;
2445 const btVector3 p=BaryEval( f.m_n[0]->m_x,
2449 const btVector3 q=BaryEval( f.m_n[0]->m_q,
2453 const btVector3 vr=(n.m_x-n.m_q)-(p-q);
2454 btVector3 corr(0,0,0);
2457 const btScalar j=c.m_margin-(dot(nr,n.m_x)-dot(nr,p));
2460 corr -= ProjectOnPlane(vr,nr)*c.m_friction;
2461 n.m_x += corr*c.m_cfm[0];
2462 f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x());
2463 f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y());
2464 f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z());
2469 void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti)
2471 for(int i=0,ni=psb->m_links.size();i<ni;++i)
2473 Link& l=psb->m_links[i];
2478 const btVector3 del=b.m_x-a.m_x;
2479 const btScalar len=del.length2();
2480 const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst;
2481 const btScalar t=k*a.m_im;
2482 a.m_x-=del*(k*a.m_im);
2483 b.m_x+=del*(k*b.m_im);
2489 void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst)
2491 for(int i=0,ni=psb->m_links.size();i<ni;++i)
2493 Link& l=psb->m_links[i];
2495 const btScalar j=-dot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst;
2496 n[0]->m_v+= l.m_c3*(j*n[0]->m_im);
2497 n[1]->m_v-= l.m_c3*(j*n[1]->m_im);
2502 btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver)
2506 case ePSolver::Anchors: return(&btSoftBody::PSolve_Anchors);
2507 case ePSolver::Linear: return(&btSoftBody::PSolve_Links);
2508 case ePSolver::RContacts: return(&btSoftBody::PSolve_RContacts);
2509 case ePSolver::SContacts: return(&btSoftBody::PSolve_SContacts);
2515 btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
2519 case eVSolver::Linear: return(&btSoftBody::VSolve_Links);
2525 void btSoftBody::defaultCollisionHandler(btCollisionObject* pco)
2527 switch(m_cfg.collisions&fCollision::RVSmask)
2529 case fCollision::SDF_RS:
2531 btSoftColliders::CollideSDF_RS docollide;
2532 btRigidBody* prb=btRigidBody::upcast(pco);
2533 const btTransform wtr=prb->getInterpolationWorldTransform();
2534 const btTransform ctr=prb->getWorldTransform();
2535 const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length();
2536 const btScalar basemargin=getCollisionShape()->getMargin();
2539 ATTRIBUTE_ALIGNED16(btDbvtVolume) volume;
2540 pco->getCollisionShape()->getAabb( pco->getInterpolationWorldTransform(),
2543 volume=btDbvtVolume::FromMM(mins,maxs);
2544 volume.Expand(btVector3(basemargin,basemargin,basemargin));
2545 docollide.psb = this;
2546 docollide.prb = prb;
2547 docollide.dynmargin = basemargin+timemargin;
2548 docollide.stamargin = basemargin;
2549 btDbvt::collideTV(m_ndbvt.m_root,volume,docollide);
2552 case fCollision::CL_RS:
2554 btSoftColliders::CollideCL_RS collider;
2555 collider.Process(this,btRigidBody::upcast(pco));
2562 void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
2564 const int cf=m_cfg.collisions&psb->m_cfg.collisions;
2565 switch(cf&fCollision::SVSmask)
2567 case fCollision::CL_SS:
2569 btSoftColliders::CollideCL_SS docollide;
2570 docollide.Process(this,psb);
2573 case fCollision::VF_SS:
2575 btSoftColliders::CollideVF_SS docollide;
2577 docollide.mrg= getCollisionShape()->getMargin()+
2578 psb->getCollisionShape()->getMargin();
2579 /* psb0 nodes vs psb1 faces */
2580 docollide.psb[0]=this;
2581 docollide.psb[1]=psb;
2582 btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root,
2583 docollide.psb[1]->m_fdbvt.m_root,
2585 /* psb1 nodes vs psb0 faces */
2586 docollide.psb[0]=psb;
2587 docollide.psb[1]=this;
2588 btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root,
2589 docollide.psb[1]->m_fdbvt.m_root,