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);
90 m_initialWorldTransform.setIdentity();
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));
500 m_initialWorldTransform = trs;
504 void btSoftBody::translate(const btVector3& trs)
513 void btSoftBody::rotate( const btQuaternion& rot)
522 void btSoftBody::scale(const btVector3& scl)
524 const btScalar margin=getCollisionShape()->getMargin();
525 for(int i=0,ni=m_nodes.size();i<ni;++i)
530 m_ndbvt.update(n.m_leaf,btDbvtVolume::FromCR(n.m_x,margin));
538 void btSoftBody::setPose(bool bvolume,bool bframe)
540 m_pose.m_bvolume = bvolume;
541 m_pose.m_bframe = bframe;
545 const btScalar omass=getTotalMass();
546 const btScalar kmass=omass*m_nodes.size()*1000;
547 btScalar tmass=omass;
548 m_pose.m_wgh.resize(m_nodes.size());
549 for(i=0,ni=m_nodes.size();i<ni;++i)
551 if(m_nodes[i].m_im<=0) tmass+=kmass;
553 for( i=0,ni=m_nodes.size();i<ni;++i)
556 m_pose.m_wgh[i]= n.m_im>0 ?
557 1/(m_nodes[i].m_im*tmass) :
561 const btVector3 com=evaluateCom();
562 m_pose.m_pos.resize(m_nodes.size());
563 for( i=0,ni=m_nodes.size();i<ni;++i)
565 m_pose.m_pos[i]=m_nodes[i].m_x-com;
567 m_pose.m_volume = bvolume?getVolume():0;
569 m_pose.m_rot.setIdentity();
570 m_pose.m_scl.setIdentity();
574 m_pose.m_aqq[2] = btVector3(0,0,0);
575 for( i=0,ni=m_nodes.size();i<ni;++i)
577 const btVector3& q=m_pose.m_pos[i];
578 const btVector3 mq=m_pose.m_wgh[i]*q;
579 m_pose.m_aqq[0]+=mq.x()*q;
580 m_pose.m_aqq[1]+=mq.y()*q;
581 m_pose.m_aqq[2]+=mq.z()*q;
583 m_pose.m_aqq=m_pose.m_aqq.inverse();
588 btScalar btSoftBody::getVolume() const
595 const btVector3 org=m_nodes[0].m_x;
596 for(i=0,ni=m_faces.size();i<ni;++i)
598 const Face& f=m_faces[i];
599 vol+=dot(f.m_n[0]->m_x-org,cross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org));
607 int btSoftBody::clusterCount() const
609 return(m_clusters.size());
613 btVector3 btSoftBody::clusterCom(const Cluster* cluster)
615 btVector3 com(0,0,0);
616 for(int i=0,ni=cluster->m_nodes.size();i<ni;++i)
618 com+=cluster->m_nodes[i]->m_x*cluster->m_masses[i];
620 return(com*cluster->m_imass);
624 btVector3 btSoftBody::clusterCom(int cluster) const
626 return(clusterCom(m_clusters[cluster]));
630 btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos)
632 return(cluster->m_lv+cross(cluster->m_av,rpos));
636 void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
638 const btVector3 li=cluster->m_imass*impulse;
639 const btVector3 ai=cluster->m_invwi*cross(rpos,impulse);
640 cluster->m_vimpulses[0]+=li;cluster->m_lv+=li;
641 cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
642 cluster->m_nvimpulses++;
646 void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
648 const btVector3 li=cluster->m_imass*impulse;
649 const btVector3 ai=cluster->m_invwi*cross(rpos,impulse);
650 cluster->m_dimpulses[0]+=li;
651 cluster->m_dimpulses[1]+=ai;
652 cluster->m_ndimpulses++;
656 void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse)
658 if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity);
659 if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift);
663 void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse)
665 const btVector3 ai=cluster->m_invwi*impulse;
666 cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
667 cluster->m_nvimpulses++;
671 void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse)
673 const btVector3 ai=cluster->m_invwi*impulse;
674 cluster->m_dimpulses[1]+=ai;
675 cluster->m_ndimpulses++;
679 void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse)
681 if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity);
682 if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift);
686 void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse)
688 cluster->m_dimpulses[0]+=impulse*cluster->m_imass;
689 cluster->m_ndimpulses++;
693 int btSoftBody::generateBendingConstraints(int distance,Material* mat)
700 const int n=m_nodes.size();
701 const unsigned inf=(~(unsigned)0)>>1;
702 unsigned* adj=new unsigned[n*n];
703 #define IDX(_x_,_y_) ((_y_)*n+(_x_))
708 if(i!=j) adj[IDX(i,j)]=adj[IDX(j,i)]=inf;
710 adj[IDX(i,j)]=adj[IDX(j,i)]=0;
713 for( i=0;i<m_links.size();++i)
715 const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
716 const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
726 const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
727 if(adj[IDX(i,j)]>sum)
729 adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
740 if(adj[IDX(i,j)]==(unsigned)distance)
743 m_links[m_links.size()-1].m_bbending=1;
755 void btSoftBody::randomizeConstraints()
757 unsigned long seed=243703;
758 #define NEXTRAND (seed=(1664525L*seed+1013904223L)&0xffffffff)
761 for(i=0,ni=m_links.size();i<ni;++i)
763 btSwap(m_links[i],m_links[NEXTRAND%ni]);
765 for(i=0,ni=m_faces.size();i<ni;++i)
767 btSwap(m_faces[i],m_faces[NEXTRAND%ni]);
773 void btSoftBody::releaseCluster(int index)
775 Cluster* c=m_clusters[index];
776 if(c->m_leaf) m_cdbvt.remove(c->m_leaf);
779 m_clusters.remove(c);
783 void btSoftBody::releaseClusters()
785 while(m_clusters.size()>0) releaseCluster(0);
789 int btSoftBody::generateClusters(int k,int maxiterations)
793 m_clusters.resize(btMin(k,m_nodes.size()));
794 for(i=0;i<m_clusters.size();++i)
796 m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
797 m_clusters[i]->m_collide= true;
803 btAlignedObjectArray<btVector3> centers;
804 btVector3 cog(0,0,0);
806 for(i=0;i<m_nodes.size();++i)
809 m_clusters[(i*29873)%m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
811 cog/=(btScalar)m_nodes.size();
812 centers.resize(k,cog);
814 const btScalar slope=16;
818 const btScalar w=2-btMin<btScalar>(1,iterations/slope);
826 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
828 c+=m_clusters[i]->m_nodes[j]->m_x;
830 if(m_clusters[i]->m_nodes.size())
832 c /= (btScalar)m_clusters[i]->m_nodes.size();
833 c = centers[i]+(c-centers[i])*w;
834 changed |= ((c-centers[i]).length2()>SIMD_EPSILON);
836 m_clusters[i]->m_nodes.resize(0);
839 for(i=0;i<m_nodes.size();++i)
841 const btVector3 nx=m_nodes[i].m_x;
843 btScalar kdist=ClusterMetric(centers[0],nx);
846 const btScalar d=ClusterMetric(centers[j],nx);
853 m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
855 } while(changed&&(iterations<maxiterations));
857 btAlignedObjectArray<int> cids;
858 cids.resize(m_nodes.size(),-1);
859 for(i=0;i<m_clusters.size();++i)
861 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
863 cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i;
866 for(i=0;i<m_faces.size();++i)
868 const int idx[]={ int(m_faces[i].m_n[0]-&m_nodes[0]),
869 int(m_faces[i].m_n[1]-&m_nodes[0]),
870 int(m_faces[i].m_n[2]-&m_nodes[0])};
873 const int cid=cids[idx[j]];
876 const int kid=idx[(j+q)%3];
879 if(m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size())
881 m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
888 if(m_clusters.size()>1)
890 Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
891 pmaster->m_collide = false;
892 pmaster->m_nodes.reserve(m_nodes.size());
893 for(int i=0;i<m_nodes.size();++i) pmaster->m_nodes.push_back(&m_nodes[i]);
894 m_clusters.push_back(pmaster);
895 btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]);
898 for(i=0;i<m_clusters.size();++i)
900 if(m_clusters[i]->m_nodes.size()==0)
906 initializeClusters();
908 return(m_clusters.size());
914 void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
916 const Node* nbase = &m_nodes[0];
917 int ncount = m_nodes.size();
918 btSymMatrix<int> edges(ncount,-2);
923 for(i=0;i<m_links.size();++i)
928 if(!SameSign(ifn->Eval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x)))
930 btSwap(m_links[i],m_links[m_links.size()-1]);
931 m_links.pop_back();--i;
936 for(i=0;i<m_links.size();++i)
939 edges(int(l.m_n[0]-nbase),int(l.m_n[1]-nbase))=-1;
941 for(i=0;i<m_faces.size();++i)
944 edges(int(f.m_n[0]-nbase),int(f.m_n[1]-nbase))=-1;
945 edges(int(f.m_n[1]-nbase),int(f.m_n[2]-nbase))=-1;
946 edges(int(f.m_n[2]-nbase),int(f.m_n[0]-nbase))=-1;
949 for(i=0;i<ncount;++i)
951 for(j=i+1;j<ncount;++j)
957 const btScalar t=ImplicitSolve(ifn,a.m_x,b.m_x,accurary);
960 const btVector3 x=Lerp(a.m_x,b.m_x,t);
961 const btVector3 v=Lerp(a.m_v,b.m_v,t);
967 const btScalar ma=1/a.m_im;
968 const btScalar mb=1/b.m_im;
969 const btScalar mc=Lerp(ma,mb,t);
970 const btScalar f=(ma+mb)/(ma+mb+mc);
976 { a.m_im/=0.5;m=1/a.m_im; }
981 { b.m_im/=0.5;m=1/b.m_im; }
986 edges(i,j)=m_nodes.size()-1;
987 m_nodes[edges(i,j)].m_v=v;
995 for(i=0,ni=m_links.size();i<ni;++i)
997 Link& feat=m_links[i];
998 const int idx[]={ int(feat.m_n[0]-nbase),
999 int(feat.m_n[1]-nbase)};
1000 if((idx[0]<ncount)&&(idx[1]<ncount))
1002 const int ni=edges(idx[0],idx[1]);
1006 Link* pft[]={ &m_links[i],
1007 &m_links[m_links.size()-1]};
1008 pft[0]->m_n[0]=&m_nodes[idx[0]];
1009 pft[0]->m_n[1]=&m_nodes[ni];
1010 pft[1]->m_n[0]=&m_nodes[ni];
1011 pft[1]->m_n[1]=&m_nodes[idx[1]];
1016 for(i=0;i<m_faces.size();++i)
1018 const Face& feat=m_faces[i];
1019 const int idx[]={ int(feat.m_n[0]-nbase),
1020 int(feat.m_n[1]-nbase),
1021 int(feat.m_n[2]-nbase)};
1022 for(j=2,k=0;k<3;j=k++)
1024 if((idx[j]<ncount)&&(idx[k]<ncount))
1026 const int ni=edges(idx[j],idx[k]);
1030 const int l=(k+1)%3;
1031 Face* pft[]={ &m_faces[i],
1032 &m_faces[m_faces.size()-1]};
1033 pft[0]->m_n[0]=&m_nodes[idx[l]];
1034 pft[0]->m_n[1]=&m_nodes[idx[j]];
1035 pft[0]->m_n[2]=&m_nodes[ni];
1036 pft[1]->m_n[0]=&m_nodes[ni];
1037 pft[1]->m_n[1]=&m_nodes[idx[k]];
1038 pft[1]->m_n[2]=&m_nodes[idx[l]];
1039 appendLink(ni,idx[l],pft[0]->m_material);
1048 btAlignedObjectArray<int> cnodes;
1049 const int pcount=ncount;
1051 ncount=m_nodes.size();
1052 cnodes.resize(ncount,0);
1054 for(i=0;i<ncount;++i)
1056 const btVector3 x=m_nodes[i].m_x;
1057 if((i>=pcount)||(btFabs(ifn->Eval(x))<accurary))
1059 const btVector3 v=m_nodes[i].m_v;
1060 btScalar m=getMass(i);
1061 if(m>0) { m*=0.5;m_nodes[i].m_im/=0.5; }
1063 cnodes[i]=m_nodes.size()-1;
1064 m_nodes[cnodes[i]].m_v=v;
1069 for(i=0,ni=m_links.size();i<ni;++i)
1071 const int id[]={ int(m_links[i].m_n[0]-nbase),
1072 int(m_links[i].m_n[1]-nbase)};
1074 if(cnodes[id[0]]&&cnodes[id[1]])
1077 todetach=m_links.size()-1;
1081 if(( (ifn->Eval(m_nodes[id[0]].m_x)<accurary)&&
1082 (ifn->Eval(m_nodes[id[1]].m_x)<accurary)))
1087 Link& l=m_links[todetach];
1088 for(int j=0;j<2;++j)
1090 int cn=cnodes[int(l.m_n[j]-nbase)];
1091 if(cn) l.m_n[j]=&m_nodes[cn];
1096 for(i=0,ni=m_faces.size();i<ni;++i)
1098 Node** n= m_faces[i].m_n;
1099 if( (ifn->Eval(n[0]->m_x)<accurary)&&
1100 (ifn->Eval(n[1]->m_x)<accurary)&&
1101 (ifn->Eval(n[2]->m_x)<accurary))
1103 for(int j=0;j<3;++j)
1105 int cn=cnodes[int(n[j]-nbase)];
1106 if(cn) n[j]=&m_nodes[cn];
1111 int nnodes=m_nodes.size();
1112 btAlignedObjectArray<int> ranks;
1113 btAlignedObjectArray<int> todelete;
1114 ranks.resize(nnodes,0);
1115 for(i=0,ni=m_links.size();i<ni;++i)
1117 for(int j=0;j<2;++j) ranks[int(m_links[i].m_n[j]-nbase)]++;
1119 for(i=0,ni=m_faces.size();i<ni;++i)
1121 for(int j=0;j<3;++j) ranks[int(m_faces[i].m_n[j]-nbase)]++;
1123 for(i=0;i<m_links.size();++i)
1125 const int id[]={ int(m_links[i].m_n[0]-nbase),
1126 int(m_links[i].m_n[1]-nbase)};
1127 const bool sg[]={ ranks[id[0]]==1,
1133 btSwap(m_links[i],m_links[m_links.size()-1]);
1134 m_links.pop_back();--i;
1138 for(i=nnodes-1;i>=0;--i)
1140 if(!ranks[i]) todelete.push_back(i);
1144 btAlignedObjectArray<int>& map=ranks;
1145 for(int i=0;i<nnodes;++i) map[i]=i;
1146 PointersToIndices(this);
1147 for(int i=0,ni=todelete.size();i<ni;++i)
1151 int& b=map[--nnodes];
1152 m_ndbvt.remove(m_nodes[a].m_leaf);m_nodes[a].m_leaf=0;
1153 btSwap(m_nodes[a],m_nodes[b]);
1156 IndicesToPointers(this,&map[0]);
1157 m_nodes.resize(nnodes);
1161 m_bUpdateRtCst=true;
1165 bool btSoftBody::cutLink(const Node* node0,const Node* node1,btScalar position)
1167 return(cutLink(int(node0-&m_nodes[0]),int(node1-&m_nodes[0]),position));
1171 bool btSoftBody::cutLink(int node0,int node1,btScalar position)
1175 const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
1176 const btVector3 x=Lerp(m_nodes[node0].m_x,m_nodes[node1].m_x,position);
1177 const btVector3 v=Lerp(m_nodes[node0].m_v,m_nodes[node1].m_v,position);
1181 Node* pa=&m_nodes[node0];
1182 Node* pb=&m_nodes[node1];
1183 Node* pn[2]={ &m_nodes[m_nodes.size()-2],
1184 &m_nodes[m_nodes.size()-1]};
1187 for(i=0,ni=m_links.size();i<ni;++i)
1189 const int mtch=MatchEdge(m_links[i].m_n[0],m_links[i].m_n[1],pa,pb);
1193 Link* pft[]={&m_links[i],&m_links[m_links.size()-1]};
1194 pft[0]->m_n[1]=pn[mtch];
1195 pft[1]->m_n[0]=pn[1-mtch];
1199 for(i=0,ni=m_faces.size();i<ni;++i)
1201 for(int k=2,l=0;l<3;k=l++)
1203 const int mtch=MatchEdge(m_faces[i].m_n[k],m_faces[i].m_n[l],pa,pb);
1207 Face* pft[]={&m_faces[i],&m_faces[m_faces.size()-1]};
1208 pft[0]->m_n[l]=pn[mtch];
1209 pft[1]->m_n[k]=pn[1-mtch];
1210 appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1211 appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1217 m_ndbvt.remove(pn[0]->m_leaf);
1218 m_ndbvt.remove(pn[1]->m_leaf);
1226 bool btSoftBody::rayCast(const btVector3& org,
1227 const btVector3& dir,
1231 if(m_faces.size()&&m_fdbvt.empty()) initializeFaceTree();
1232 results.body = this;
1233 results.time = maxtime;
1234 results.feature = eFeature::None;
1236 return(rayCast(org,dir,results.time,results.feature,results.index,false)!=0);
1240 void btSoftBody::setSolver(eSolverPresets::_ preset)
1242 m_cfg.m_vsequence.clear();
1243 m_cfg.m_psequence.clear();
1244 m_cfg.m_dsequence.clear();
1247 case eSolverPresets::Positions:
1248 m_cfg.m_psequence.push_back(ePSolver::Anchors);
1249 m_cfg.m_psequence.push_back(ePSolver::RContacts);
1250 m_cfg.m_psequence.push_back(ePSolver::SContacts);
1251 m_cfg.m_psequence.push_back(ePSolver::Linear);
1253 case eSolverPresets::Velocities:
1254 m_cfg.m_vsequence.push_back(eVSolver::Linear);
1256 m_cfg.m_psequence.push_back(ePSolver::Anchors);
1257 m_cfg.m_psequence.push_back(ePSolver::RContacts);
1258 m_cfg.m_psequence.push_back(ePSolver::SContacts);
1260 m_cfg.m_dsequence.push_back(ePSolver::Linear);
1266 void btSoftBody::predictMotion(btScalar dt)
1273 m_bUpdateRtCst=false;
1276 if(m_cfg.collisions&fCollision::VF_SS)
1278 initializeFaceTree();
1283 m_sst.sdt = dt*m_cfg.timescale;
1284 m_sst.isdt = 1/m_sst.sdt;
1285 m_sst.velmrg = m_sst.sdt*3;
1286 m_sst.radmrg = getCollisionShape()->getMargin();
1287 m_sst.updmrg = m_sst.radmrg*(btScalar)0.25;
1289 addVelocity(m_worldInfo->m_gravity*m_sst.sdt);
1292 for(i=0,ni=m_nodes.size();i<ni;++i)
1296 n.m_v += n.m_f*n.m_im*m_sst.sdt;
1297 n.m_x += n.m_v*m_sst.sdt;
1298 n.m_f = btVector3(0,0,0);
1305 for(i=0,ni=m_nodes.size();i<ni;++i)
1308 m_ndbvt.update( n.m_leaf,
1309 btDbvtVolume::FromCR(n.m_x,m_sst.radmrg),
1314 if(!m_fdbvt.empty())
1316 for(int i=0;i<m_faces.size();++i)
1319 const btVector3 v=( f.m_n[0]->m_v+
1322 m_fdbvt.update( f.m_leaf,
1323 VolumeOf(f,m_sst.radmrg),
1331 if(m_pose.m_bframe&&(m_cfg.kMT>0))
1333 const btMatrix3x3 posetrs=m_pose.m_rot;
1334 for(int i=0,ni=m_nodes.size();i<ni;++i)
1339 const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com;
1340 n.m_x=Lerp(n.m_x,x,m_cfg.kMT);
1344 /* Clear contacts */
1345 m_rcontacts.resize(0);
1346 m_scontacts.resize(0);
1347 /* Optimize dbvt's */
1348 m_ndbvt.optimizeIncremental(1);
1349 m_fdbvt.optimizeIncremental(1);
1350 m_cdbvt.optimizeIncremental(1);
1354 void btSoftBody::solveConstraints()
1356 /* Apply clusters */
1357 applyClusters(false);
1362 for(i=0,ni=m_links.size();i<ni;++i)
1365 l.m_c3 = l.m_n[1]->m_q-l.m_n[0]->m_q;
1366 l.m_c2 = 1/(l.m_c3.length2()*l.m_c0);
1368 /* Prepare anchors */
1369 for(i=0,ni=m_anchors.size();i<ni;++i)
1371 Anchor& a=m_anchors[i];
1372 const btVector3 ra=a.m_body->getWorldTransform().getBasis()*a.m_local;
1373 a.m_c0 = ImpulseMatrix( m_sst.sdt,
1375 a.m_body->getInvMass(),
1376 a.m_body->getInvInertiaTensorWorld(),
1379 a.m_c2 = m_sst.sdt*a.m_node->m_im;
1380 a.m_body->activate();
1382 /* Solve velocities */
1383 if(m_cfg.viterations>0)
1386 for(int isolve=0;isolve<m_cfg.viterations;++isolve)
1388 for(int iseq=0;iseq<m_cfg.m_vsequence.size();++iseq)
1390 getSolver(m_cfg.m_vsequence[iseq])(this,1);
1394 for(i=0,ni=m_nodes.size();i<ni;++i)
1397 n.m_x = n.m_q+n.m_v*m_sst.sdt;
1400 /* Solve positions */
1401 if(m_cfg.piterations>0)
1403 for(int isolve=0;isolve<m_cfg.piterations;++isolve)
1405 const btScalar ti=isolve/(btScalar)m_cfg.piterations;
1406 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1408 getSolver(m_cfg.m_psequence[iseq])(this,1,ti);
1411 const btScalar vc=m_sst.isdt*(1-m_cfg.kDP);
1412 for(i=0,ni=m_nodes.size();i<ni;++i)
1415 n.m_v = (n.m_x-n.m_q)*vc;
1416 n.m_f = btVector3(0,0,0);
1420 if(m_cfg.diterations>0)
1422 const btScalar vcf=m_cfg.kVCF*m_sst.isdt;
1423 for(i=0,ni=m_nodes.size();i<ni;++i)
1428 for(int idrift=0;idrift<m_cfg.diterations;++idrift)
1430 for(int iseq=0;iseq<m_cfg.m_dsequence.size();++iseq)
1432 getSolver(m_cfg.m_dsequence[iseq])(this,1,0);
1435 for(int i=0,ni=m_nodes.size();i<ni;++i)
1438 n.m_v += (n.m_x-n.m_q)*vcf;
1441 /* Apply clusters */
1443 applyClusters(true);
1447 void btSoftBody::staticSolve(int iterations)
1449 for(int isolve=0;isolve<iterations;++isolve)
1451 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1453 getSolver(m_cfg.m_psequence[iseq])(this,1,0);
1459 void btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/,int /*count*/,int /*iterations*/)
1465 void btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
1467 const int nb=bodies.size();
1473 iterations=btMax(iterations,bodies[i]->m_cfg.citerations);
1477 bodies[i]->prepareClusters(iterations);
1479 for(i=0;i<iterations;++i)
1481 const btScalar sor=1;
1482 for(int j=0;j<nb;++j)
1484 bodies[j]->solveClusters(sor);
1489 bodies[i]->cleanupClusters();
1494 void btSoftBody::integrateMotion()
1501 btSoftBody::RayCaster::RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt)
1511 void btSoftBody::RayCaster::Process(const btDbvtNode* leaf)
1513 btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data;
1514 const btScalar t=rayTriangle( o,d,
1519 if((t>0)&&(t<mint)) { mint=t;face=&f; }
1524 btScalar btSoftBody::RayCaster::rayTriangle( const btVector3& org,
1525 const btVector3& dir,
1531 static const btScalar ceps=-SIMD_EPSILON*10;
1532 static const btScalar teps=SIMD_EPSILON*10;
1533 const btVector3 n=cross(b-a,c-a);
1534 const btScalar d=dot(a,n);
1535 const btScalar den=dot(dir,n);
1536 if(!btFuzzyZero(den))
1538 const btScalar num=dot(org,n)-d;
1539 const btScalar t=-num/den;
1540 if((t>teps)&&(t<maxt))
1542 const btVector3 hit=org+dir*t;
1543 if( (dot(n,cross(a-hit,b-hit))>ceps) &&
1544 (dot(n,cross(b-hit,c-hit))>ceps) &&
1545 (dot(n,cross(c-hit,a-hit))>ceps))
1555 void btSoftBody::pointersToIndices()
1557 #define PTR2IDX(_p_,_b_) reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_))
1558 btSoftBody::Node* base=&m_nodes[0];
1561 for(i=0,ni=m_nodes.size();i<ni;++i)
1563 if(m_nodes[i].m_leaf)
1565 m_nodes[i].m_leaf->data=*(void**)&i;
1568 for(i=0,ni=m_links.size();i<ni;++i)
1570 m_links[i].m_n[0]=PTR2IDX(m_links[i].m_n[0],base);
1571 m_links[i].m_n[1]=PTR2IDX(m_links[i].m_n[1],base);
1573 for(i=0,ni=m_faces.size();i<ni;++i)
1575 m_faces[i].m_n[0]=PTR2IDX(m_faces[i].m_n[0],base);
1576 m_faces[i].m_n[1]=PTR2IDX(m_faces[i].m_n[1],base);
1577 m_faces[i].m_n[2]=PTR2IDX(m_faces[i].m_n[2],base);
1578 if(m_faces[i].m_leaf)
1580 m_faces[i].m_leaf->data=*(void**)&i;
1583 for(i=0,ni=m_anchors.size();i<ni;++i)
1585 m_anchors[i].m_node=PTR2IDX(m_anchors[i].m_node,base);
1587 for(i=0,ni=m_notes.size();i<ni;++i)
1589 for(int j=0;j<m_notes[i].m_rank;++j)
1591 m_notes[i].m_nodes[j]=PTR2IDX(m_notes[i].m_nodes[j],base);
1598 void btSoftBody::indicesToPointers(const int* map)
1600 #define IDX2PTR(_p_,_b_) map?(&(_b_)[map[(((char*)_p_)-(char*)0)]]): \
1601 (&(_b_)[(((char*)_p_)-(char*)0)])
1602 btSoftBody::Node* base=&m_nodes[0];
1605 for(i=0,ni=m_nodes.size();i<ni;++i)
1607 if(m_nodes[i].m_leaf)
1609 m_nodes[i].m_leaf->data=&m_nodes[i];
1612 for(i=0,ni=m_links.size();i<ni;++i)
1614 m_links[i].m_n[0]=IDX2PTR(m_links[i].m_n[0],base);
1615 m_links[i].m_n[1]=IDX2PTR(m_links[i].m_n[1],base);
1617 for(i=0,ni=m_faces.size();i<ni;++i)
1619 m_faces[i].m_n[0]=IDX2PTR(m_faces[i].m_n[0],base);
1620 m_faces[i].m_n[1]=IDX2PTR(m_faces[i].m_n[1],base);
1621 m_faces[i].m_n[2]=IDX2PTR(m_faces[i].m_n[2],base);
1622 if(m_faces[i].m_leaf)
1624 m_faces[i].m_leaf->data=&m_faces[i];
1627 for(i=0,ni=m_anchors.size();i<ni;++i)
1629 m_anchors[i].m_node=IDX2PTR(m_anchors[i].m_node,base);
1631 for(i=0,ni=m_notes.size();i<ni;++i)
1633 for(int j=0;j<m_notes[i].m_rank;++j)
1635 m_notes[i].m_nodes[j]=IDX2PTR(m_notes[i].m_nodes[j],base);
1642 int btSoftBody::rayCast(const btVector3& org,const btVector3& dir,
1643 btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const
1646 if(bcountonly||m_fdbvt.empty())
1648 for(int i=0,ni=m_faces.size();i<ni;++i)
1650 const btSoftBody::Face& f=m_faces[i];
1651 const btScalar t=RayCaster::rayTriangle( org,dir,
1661 feature=btSoftBody::eFeature::Face;
1670 RayCaster collider(org,dir,mint);
1671 btDbvt::collideRAY(m_fdbvt.m_root,org,dir,collider);
1675 feature=btSoftBody::eFeature::Face;
1676 index=(int)(collider.face-&m_faces[0]);
1684 void btSoftBody::initializeFaceTree()
1687 for(int i=0;i<m_faces.size();++i)
1690 f.m_leaf=m_fdbvt.insert(VolumeOf(f,0),&f);
1695 btVector3 btSoftBody::evaluateCom() const
1697 btVector3 com(0,0,0);
1700 for(int i=0,ni=m_nodes.size();i<ni;++i)
1702 com+=m_nodes[i].m_x*m_pose.m_wgh[i];
1709 bool btSoftBody::checkContact( btRigidBody* prb,
1712 btSoftBody::sCti& cti) const
1715 btCollisionShape* shp=prb->getCollisionShape();
1716 const btTransform& wtr=prb->getInterpolationWorldTransform();
1717 btScalar dst=m_worldInfo->m_sparsesdf.Evaluate( wtr.invXform(x),
1724 cti.m_normal = wtr.getBasis()*nrm;
1725 cti.m_offset = -dot( cti.m_normal,
1726 x-cti.m_normal*dst);
1733 void btSoftBody::updateNormals()
1735 const btVector3 zv(0,0,0);
1738 for(i=0,ni=m_nodes.size();i<ni;++i)
1742 for(i=0,ni=m_faces.size();i<ni;++i)
1744 btSoftBody::Face& f=m_faces[i];
1745 const btVector3 n=cross(f.m_n[1]->m_x-f.m_n[0]->m_x,
1746 f.m_n[2]->m_x-f.m_n[0]->m_x);
1747 f.m_normal=n.normalized();
1752 for(i=0,ni=m_nodes.size();i<ni;++i)
1754 btScalar len = m_nodes[i].m_n.length();
1755 if (len>SIMD_EPSILON)
1756 m_nodes[i].m_n /= len;
1761 void btSoftBody::updateBounds()
1765 const btVector3& mins=m_ndbvt.m_root->volume.Mins();
1766 const btVector3& maxs=m_ndbvt.m_root->volume.Maxs();
1767 const btScalar csm=getCollisionShape()->getMargin();
1768 const btVector3 mrg=btVector3( csm,
1770 csm)*1; // ??? to investigate...
1771 m_bounds[0]=mins-mrg;
1772 m_bounds[1]=maxs+mrg;
1773 if(0!=getBroadphaseHandle())
1775 m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(),
1778 m_worldInfo->m_dispatcher);
1784 m_bounds[1]=btVector3(0,0,0);
1790 void btSoftBody::updatePose()
1794 btSoftBody::Pose& pose=m_pose;
1795 const btVector3 com=evaluateCom();
1800 const btScalar eps=SIMD_EPSILON;
1801 Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0);
1802 Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3);
1803 for(int i=0,ni=m_nodes.size();i<ni;++i)
1805 const btVector3 a=pose.m_wgh[i]*(m_nodes[i].m_x-com);
1806 const btVector3& b=pose.m_pos[i];
1812 PolarDecompose(Apq,r,s);
1814 pose.m_scl=pose.m_aqq*r.transpose()*Apq;
1815 if(m_cfg.maxvolume>1)
1817 const btScalar idet=Clamp<btScalar>( 1/pose.m_scl.determinant(),
1819 pose.m_scl=Mul(pose.m_scl,idet);
1826 void btSoftBody::updateConstants()
1831 for(i=0,ni=m_links.size();i<ni;++i)
1834 Material& m=*l.m_material;
1835 l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
1836 l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST;
1837 l.m_c1 = l.m_rl*l.m_rl;
1840 for(i=0,ni=m_faces.size();i<ni;++i)
1843 f.m_ra = AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
1846 btAlignedObjectArray<int> counts;
1847 counts.resize(m_nodes.size(),0);
1848 for(i=0,ni=m_nodes.size();i<ni;++i)
1850 m_nodes[i].m_area = 0;
1852 for(i=0,ni=m_faces.size();i<ni;++i)
1854 btSoftBody::Face& f=m_faces[i];
1855 for(int j=0;j<3;++j)
1857 const int index=(int)(f.m_n[j]-&m_nodes[0]);
1859 f.m_n[j]->m_area+=btFabs(f.m_ra);
1862 for(i=0,ni=m_nodes.size();i<ni;++i)
1865 m_nodes[i].m_area/=(btScalar)counts[i];
1867 m_nodes[i].m_area=0;
1872 void btSoftBody::initializeClusters()
1876 for( i=0;i<m_clusters.size();++i)
1878 Cluster& c=*m_clusters[i];
1880 c.m_masses.resize(c.m_nodes.size());
1881 for(int j=0;j<c.m_nodes.size();++j)
1883 c.m_masses[j] = c.m_nodes[j]->m_im>0?1/c.m_nodes[j]->m_im:0;
1884 c.m_imass += c.m_masses[j];
1886 c.m_imass = 1/c.m_imass;
1887 c.m_com = btSoftBody::clusterCom(&c);
1888 c.m_lv = btVector3(0,0,0);
1889 c.m_av = btVector3(0,0,0);
1892 btMatrix3x3& ii=c.m_locii;
1893 ii[0]=ii[1]=ii[2]=btVector3(0,0,0);
1897 for(i=0,ni=c.m_nodes.size();i<ni;++i)
1899 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
1900 const btVector3 q=k*k;
1901 const btScalar m=c.m_masses[i];
1902 ii[0][0] += m*(q[1]+q[2]);
1903 ii[1][1] += m*(q[0]+q[2]);
1904 ii[2][2] += m*(q[0]+q[1]);
1905 ii[0][1] -= m*k[0]*k[1];
1906 ii[0][2] -= m*k[0]*k[2];
1907 ii[1][2] -= m*k[1]*k[2];
1915 c.m_framexform.setIdentity();
1916 c.m_framexform.setOrigin(c.m_com);
1917 c.m_framerefs.resize(c.m_nodes.size());
1920 for(i=0;i<c.m_framerefs.size();++i)
1922 c.m_framerefs[i]=c.m_nodes[i]->m_x-c.m_com;
1929 void btSoftBody::updateClusters()
1931 BT_PROFILE("UpdateClusters");
1934 for(i=0;i<m_clusters.size();++i)
1936 btSoftBody::Cluster& c=*m_clusters[i];
1937 const int n=c.m_nodes.size();
1938 const btScalar invn=1/(btScalar)n;
1942 const btScalar eps=btScalar(0.0001);
1944 m[0]=m[1]=m[2]=btVector3(0,0,0);
1948 c.m_com=clusterCom(&c);
1949 for(int i=0;i<c.m_nodes.size();++i)
1951 const btVector3 a=c.m_nodes[i]->m_x-c.m_com;
1952 const btVector3& b=c.m_framerefs[i];
1953 m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b;
1955 PolarDecompose(m,r,s);
1956 c.m_framexform.setOrigin(c.m_com);
1957 c.m_framexform.setBasis(r);
1960 c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose();
1963 const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass);
1964 const btVector3 inertia(rk,rk,rk);
1965 const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
1966 btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0,
1967 btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
1969 c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
1971 c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0);
1972 for(int i=0;i<n;++i)
1974 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
1975 const btVector3 q=k*k;
1976 const btScalar m=1/c.m_nodes[i]->m_im;
1977 c.m_invwi[0][0] += m*(q[1]+q[2]);
1978 c.m_invwi[1][1] += m*(q[0]+q[2]);
1979 c.m_invwi[2][2] += m*(q[0]+q[1]);
1980 c.m_invwi[0][1] -= m*k[0]*k[1];
1981 c.m_invwi[0][2] -= m*k[0]*k[2];
1982 c.m_invwi[1][2] -= m*k[1]*k[2];
1984 c.m_invwi[1][0]=c.m_invwi[0][1];
1985 c.m_invwi[2][0]=c.m_invwi[0][2];
1986 c.m_invwi[2][1]=c.m_invwi[1][2];
1987 c.m_invwi=c.m_invwi.inverse();
1991 c.m_lv=btVector3(0,0,0);
1992 c.m_av=btVector3(0,0,0);
1998 const btVector3 v=c.m_nodes[i]->m_v*c.m_masses[i];
2000 c.m_av += cross(c.m_nodes[i]->m_x-c.m_com,v);
2003 c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping);
2004 c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping);
2006 c.m_vimpulses[1] = btVector3(0,0,0);
2008 c.m_dimpulses[1] = btVector3(0,0,0);
2014 for(int j=0;j<c.m_nodes.size();++j)
2016 Node& n=*c.m_nodes[j];
2017 const btVector3 x=c.m_framexform*c.m_framerefs[j];
2018 n.m_x=Lerp(n.m_x,x,c.m_matching);
2024 btVector3 mi=c.m_nodes[0]->m_x;
2026 for(int j=1;j<n;++j)
2028 mi.setMin(c.m_nodes[j]->m_x);
2029 mx.setMax(c.m_nodes[j]->m_x);
2031 const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx);
2033 m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg);
2035 c.m_leaf=m_cdbvt.insert(bounds,&c);
2042 void btSoftBody::cleanupClusters()
2044 for(int i=0;i<m_joints.size();++i)
2046 m_joints[i]->Terminate(m_sst.sdt);
2047 if(m_joints[i]->m_delete)
2049 btAlignedFree(m_joints[i]);
2050 m_joints.remove(m_joints[i--]);
2056 void btSoftBody::prepareClusters(int iterations)
2058 for(int i=0;i<m_joints.size();++i)
2060 m_joints[i]->Prepare(m_sst.sdt,iterations);
2066 void btSoftBody::solveClusters(btScalar sor)
2068 for(int i=0,ni=m_joints.size();i<ni;++i)
2070 m_joints[i]->Solve(m_sst.sdt,sor);
2075 void btSoftBody::applyClusters(bool drift)
2077 BT_PROFILE("ApplyClusters");
2078 const btScalar f0=m_sst.sdt;
2079 const btScalar f1=f0/2;
2080 btAlignedObjectArray<btVector3> deltas;
2081 btAlignedObjectArray<btScalar> weights;
2082 deltas.resize(m_nodes.size(),btVector3(0,0,0));
2083 weights.resize(m_nodes.size(),0);
2088 for(i=0;i<m_clusters.size();++i)
2090 Cluster& c=*m_clusters[i];
2093 c.m_dimpulses[0]/=(btScalar)c.m_ndimpulses;
2094 c.m_dimpulses[1]/=(btScalar)c.m_ndimpulses;
2098 for(i=0;i<m_clusters.size();++i)
2100 Cluster& c=*m_clusters[i];
2101 if(0<(drift?c.m_ndimpulses:c.m_nvimpulses))
2103 const btVector3 v=(drift?c.m_dimpulses[0]:c.m_vimpulses[0])*m_sst.sdt;
2104 const btVector3 w=(drift?c.m_dimpulses[1]:c.m_vimpulses[1])*m_sst.sdt;
2105 for(int j=0;j<c.m_nodes.size();++j)
2107 const int idx=int(c.m_nodes[j]-&m_nodes[0]);
2108 const btVector3& x=c.m_nodes[j]->m_x;
2109 const btScalar q=c.m_masses[j];
2110 deltas[idx] += (v+cross(w,x-c.m_com))*q;
2115 for(i=0;i<deltas.size();++i)
2117 if(weights[i]>0) m_nodes[i].m_x+=deltas[i]/weights[i];
2122 void btSoftBody::dampClusters()
2126 for(i=0;i<m_clusters.size();++i)
2128 Cluster& c=*m_clusters[i];
2131 for(int j=0;j<c.m_nodes.size();++j)
2133 Node& n=*c.m_nodes[j];
2136 const btVector3 vx=c.m_lv+cross(c.m_av,c.m_nodes[j]->m_q-c.m_com);
2137 n.m_v += c.m_ndamping*(vx-n.m_v);
2145 void btSoftBody::Joint::Prepare(btScalar dt,int)
2147 m_bodies[0].activate();
2148 m_bodies[1].activate();
2152 void btSoftBody::LJoint::Prepare(btScalar dt,int iterations)
2154 static const btScalar maxdrift=4;
2155 Joint::Prepare(dt,iterations);
2156 m_rpos[0] = m_bodies[0].xform()*m_refs[0];
2157 m_rpos[1] = m_bodies[1].xform()*m_refs[1];
2158 m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt;
2159 m_rpos[0] -= m_bodies[0].xform().getOrigin();
2160 m_rpos[1] -= m_bodies[1].xform().getOrigin();
2161 m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0],
2162 m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]);
2165 m_sdrift = m_massmatrix*(m_drift*m_split);
2166 m_drift *= 1-m_split;
2168 m_drift /=(btScalar)iterations;
2172 void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor)
2174 const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
2175 const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
2176 const btVector3 vr=va-vb;
2177 btSoftBody::Impulse impulse;
2178 impulse.m_asVelocity = 1;
2179 impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor;
2180 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2181 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2185 void btSoftBody::LJoint::Terminate(btScalar dt)
2189 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2190 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2195 void btSoftBody::AJoint::Prepare(btScalar dt,int iterations)
2197 static const btScalar maxdrift=SIMD_PI/16;
2198 m_icontrol->Prepare(this);
2199 Joint::Prepare(dt,iterations);
2200 m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0];
2201 m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1];
2202 m_drift = NormalizeAny(cross(m_axis[1],m_axis[0]));
2203 m_drift *= btMin(maxdrift,btAcos(Clamp<btScalar>(dot(m_axis[0],m_axis[1]),-1,+1)));
2204 m_drift *= m_erp/dt;
2205 m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia());
2208 m_sdrift = m_massmatrix*(m_drift*m_split);
2209 m_drift *= 1-m_split;
2211 m_drift /=(btScalar)iterations;
2215 void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor)
2217 const btVector3 va=m_bodies[0].angularVelocity();
2218 const btVector3 vb=m_bodies[1].angularVelocity();
2219 const btVector3 vr=va-vb;
2220 const btScalar sp=dot(vr,m_axis[0]);
2221 const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp);
2222 btSoftBody::Impulse impulse;
2223 impulse.m_asVelocity = 1;
2224 impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor;
2225 m_bodies[0].applyAImpulse(-impulse);
2226 m_bodies[1].applyAImpulse( impulse);
2230 void btSoftBody::AJoint::Terminate(btScalar dt)
2234 m_bodies[0].applyDAImpulse(-m_sdrift);
2235 m_bodies[1].applyDAImpulse( m_sdrift);
2240 void btSoftBody::CJoint::Prepare(btScalar dt,int iterations)
2242 Joint::Prepare(dt,iterations);
2243 const bool dodrift=(m_life==0);
2244 m_delete=(++m_life)>m_maxlife;
2247 m_drift=m_drift*m_erp/dt;
2250 m_sdrift = m_massmatrix*(m_drift*m_split);
2251 m_drift *= 1-m_split;
2253 m_drift/=(btScalar)iterations;
2257 m_drift=m_sdrift=btVector3(0,0,0);
2262 void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor)
2264 const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
2265 const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
2266 const btVector3 vrel=va-vb;
2267 const btScalar rvac=dot(vrel,m_normal);
2268 btSoftBody::Impulse impulse;
2269 impulse.m_asVelocity = 1;
2270 impulse.m_velocity = m_drift;
2273 const btVector3 iv=m_normal*rvac;
2274 const btVector3 fv=vrel-iv;
2275 impulse.m_velocity += iv+fv*m_friction;
2277 impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor;
2278 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2279 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2283 void btSoftBody::CJoint::Terminate(btScalar dt)
2287 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2288 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2293 void btSoftBody::applyForces()
2295 BT_PROFILE("SoftBody applyForces");
2296 const btScalar dt=m_sst.sdt;
2297 const btScalar kLF=m_cfg.kLF;
2298 const btScalar kDG=m_cfg.kDG;
2299 const btScalar kPR=m_cfg.kPR;
2300 const btScalar kVC=m_cfg.kVC;
2301 const bool as_lift=kLF>0;
2302 const bool as_drag=kDG>0;
2303 const bool as_pressure=kPR!=0;
2304 const bool as_volume=kVC>0;
2305 const bool as_aero= as_lift ||
2307 const bool as_vaero= as_aero &&
2308 (m_cfg.aeromodel<btSoftBody::eAeroModel::F_TwoSided);
2309 const bool as_faero= as_aero &&
2310 (m_cfg.aeromodel>=btSoftBody::eAeroModel::F_TwoSided);
2311 const bool use_medium= as_aero;
2312 const bool use_volume= as_pressure ||
2315 btScalar ivolumetp=0;
2316 btScalar dvolumetv=0;
2317 btSoftBody::sMedium medium;
2320 volume = getVolume();
2321 ivolumetp = 1/btFabs(volume)*kPR;
2322 dvolumetv = (m_pose.m_volume-volume)*kVC;
2324 /* Per vertex forces */
2327 for(i=0,ni=m_nodes.size();i<ni;++i)
2329 btSoftBody::Node& n=m_nodes[i];
2334 EvaluateMedium(m_worldInfo,n.m_x,medium);
2338 const btVector3 rel_v=n.m_v-medium.m_velocity;
2339 const btScalar rel_v2=rel_v.length2();
2340 if(rel_v2>SIMD_EPSILON)
2342 btVector3 nrm=n.m_n;
2344 switch(m_cfg.aeromodel)
2346 case btSoftBody::eAeroModel::V_Point:
2347 nrm=NormalizeAny(rel_v);break;
2348 case btSoftBody::eAeroModel::V_TwoSided:
2349 nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break;
2351 const btScalar dvn=dot(rel_v,nrm);
2352 /* Compute forces */
2355 btVector3 force(0,0,0);
2356 const btScalar c0 = n.m_area*dvn*rel_v2/2;
2357 const btScalar c1 = c0*medium.m_density;
2358 force += nrm*(-c1*kLF);
2359 force += rel_v.normalized()*(-c1*kDG);
2360 ApplyClampedForce(n,force,dt);
2368 n.m_f += n.m_n*(n.m_area*ivolumetp);
2373 n.m_f += n.m_n*(n.m_area*dvolumetv);
2377 /* Per face forces */
2378 for(i=0,ni=m_faces.size();i<ni;++i)
2380 btSoftBody::Face& f=m_faces[i];
2383 const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3;
2384 const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3;
2385 EvaluateMedium(m_worldInfo,x,medium);
2386 const btVector3 rel_v=v-medium.m_velocity;
2387 const btScalar rel_v2=rel_v.length2();
2388 if(rel_v2>SIMD_EPSILON)
2390 btVector3 nrm=f.m_normal;
2392 switch(m_cfg.aeromodel)
2394 case btSoftBody::eAeroModel::F_TwoSided:
2395 nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break;
2397 const btScalar dvn=dot(rel_v,nrm);
2398 /* Compute forces */
2401 btVector3 force(0,0,0);
2402 const btScalar c0 = f.m_ra*dvn*rel_v2;
2403 const btScalar c1 = c0*medium.m_density;
2404 force += nrm*(-c1*kLF);
2405 force += rel_v.normalized()*(-c1*kDG);
2407 for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt);
2415 void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti)
2417 const btScalar kAHR=psb->m_cfg.kAHR*kst;
2418 const btScalar dt=psb->m_sst.sdt;
2419 for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
2421 const Anchor& a=psb->m_anchors[i];
2422 const btTransform& t=a.m_body->getInterpolationWorldTransform();
2424 const btVector3 wa=t*a.m_local;
2425 const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt;
2426 const btVector3 vb=n.m_x-n.m_q;
2427 const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR;
2428 const btVector3 impulse=a.m_c0*vr;
2429 n.m_x+=impulse*a.m_c2;
2430 a.m_body->applyImpulse(-impulse,a.m_c1);
2435 void btSoftBody::PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti)
2437 const btScalar dt=psb->m_sst.sdt;
2438 const btScalar mrg=psb->getCollisionShape()->getMargin();
2439 for(int i=0,ni=psb->m_rcontacts.size();i<ni;++i)
2441 const RContact& c=psb->m_rcontacts[i];
2442 ///skip object that don't have collision response
2443 if (!psb->getWorldInfo()->m_dispatcher->needsResponse(psb,c.m_cti.m_body))
2446 const sCti& cti=c.m_cti;
2447 const btVector3 va=cti.m_body->getVelocityInLocalPoint(c.m_c1)*dt;
2448 const btVector3 vb=c.m_node->m_x-c.m_node->m_q;
2449 const btVector3 vr=vb-va;
2450 const btScalar dn=dot(vr,cti.m_normal);
2451 if(dn<=SIMD_EPSILON)
2453 const btScalar dp=btMin(dot(c.m_node->m_x,cti.m_normal)+cti.m_offset,mrg);
2454 const btVector3 fv=vr-cti.m_normal*dn;
2455 const btVector3 impulse=c.m_c0*((vr-fv*c.m_c3+cti.m_normal*(dp*c.m_c4))*kst);
2456 c.m_node->m_x-=impulse*c.m_c2;
2457 c.m_cti.m_body->applyImpulse(impulse,c.m_c1);
2463 void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti)
2465 for(int i=0,ni=psb->m_scontacts.size();i<ni;++i)
2467 const SContact& c=psb->m_scontacts[i];
2468 const btVector3& nr=c.m_normal;
2471 const btVector3 p=BaryEval( f.m_n[0]->m_x,
2475 const btVector3 q=BaryEval( f.m_n[0]->m_q,
2479 const btVector3 vr=(n.m_x-n.m_q)-(p-q);
2480 btVector3 corr(0,0,0);
2483 const btScalar j=c.m_margin-(dot(nr,n.m_x)-dot(nr,p));
2486 corr -= ProjectOnPlane(vr,nr)*c.m_friction;
2487 n.m_x += corr*c.m_cfm[0];
2488 f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x());
2489 f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y());
2490 f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z());
2495 void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti)
2497 for(int i=0,ni=psb->m_links.size();i<ni;++i)
2499 Link& l=psb->m_links[i];
2504 const btVector3 del=b.m_x-a.m_x;
2505 const btScalar len=del.length2();
2506 const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst;
2507 const btScalar t=k*a.m_im;
2508 a.m_x-=del*(k*a.m_im);
2509 b.m_x+=del*(k*b.m_im);
2515 void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst)
2517 for(int i=0,ni=psb->m_links.size();i<ni;++i)
2519 Link& l=psb->m_links[i];
2521 const btScalar j=-dot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst;
2522 n[0]->m_v+= l.m_c3*(j*n[0]->m_im);
2523 n[1]->m_v-= l.m_c3*(j*n[1]->m_im);
2528 btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver)
2532 case ePSolver::Anchors: return(&btSoftBody::PSolve_Anchors);
2533 case ePSolver::Linear: return(&btSoftBody::PSolve_Links);
2534 case ePSolver::RContacts: return(&btSoftBody::PSolve_RContacts);
2535 case ePSolver::SContacts: return(&btSoftBody::PSolve_SContacts);
2541 btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
2545 case eVSolver::Linear: return(&btSoftBody::VSolve_Links);
2551 void btSoftBody::defaultCollisionHandler(btCollisionObject* pco)
2553 switch(m_cfg.collisions&fCollision::RVSmask)
2555 case fCollision::SDF_RS:
2557 btSoftColliders::CollideSDF_RS docollide;
2558 btRigidBody* prb=btRigidBody::upcast(pco);
2559 const btTransform wtr=prb->getInterpolationWorldTransform();
2560 const btTransform ctr=prb->getWorldTransform();
2561 const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length();
2562 const btScalar basemargin=getCollisionShape()->getMargin();
2565 ATTRIBUTE_ALIGNED16(btDbvtVolume) volume;
2566 pco->getCollisionShape()->getAabb( pco->getInterpolationWorldTransform(),
2569 volume=btDbvtVolume::FromMM(mins,maxs);
2570 volume.Expand(btVector3(basemargin,basemargin,basemargin));
2571 docollide.psb = this;
2572 docollide.prb = prb;
2573 docollide.dynmargin = basemargin+timemargin;
2574 docollide.stamargin = basemargin;
2575 btDbvt::collideTV(m_ndbvt.m_root,volume,docollide);
2578 case fCollision::CL_RS:
2580 btSoftColliders::CollideCL_RS collider;
2581 collider.Process(this,btRigidBody::upcast(pco));
2588 void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
2590 const int cf=m_cfg.collisions&psb->m_cfg.collisions;
2591 switch(cf&fCollision::SVSmask)
2593 case fCollision::CL_SS:
2595 btSoftColliders::CollideCL_SS docollide;
2596 docollide.Process(this,psb);
2599 case fCollision::VF_SS:
2601 btSoftColliders::CollideVF_SS docollide;
2603 docollide.mrg= getCollisionShape()->getMargin()+
2604 psb->getCollisionShape()->getMargin();
2605 /* psb0 nodes vs psb1 faces */
2606 docollide.psb[0]=this;
2607 docollide.psb[1]=psb;
2608 btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root,
2609 docollide.psb[1]->m_fdbvt.m_root,
2611 /* psb1 nodes vs psb0 faces */
2612 docollide.psb[0]=psb;
2613 docollide.psb[1]=this;
2614 btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root,
2615 docollide.psb[1]->m_fdbvt.m_root,