2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
15 ///btSoftBody implementation by Nathanael Presson
17 #include "btSoftBodyInternals.h"
18 #include "BulletSoftBody/btSoftBodySolvers.h"
19 #include "btSoftBodyData.h"
20 #include "LinearMath/btSerializer.h"
23 btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m)
24 :m_worldInfo(worldInfo),m_softBodySolver(0)
29 /* Default material */
30 Material* pm=appendMaterial();
34 pm->m_flags = fMaterial::Default;
37 const btScalar margin=getCollisionShape()->getMargin();
38 m_nodes.resize(node_count);
39 for(int i=0,ni=node_count;i<ni;++i)
43 n.m_x = x?*x++:btVector3(0,0,0);
46 n.m_im = n.m_im>0?1/n.m_im:0;
47 n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
54 btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo)
55 :m_worldInfo(worldInfo)
61 void btSoftBody::initDefaults()
63 m_internalType = CO_SOFT_BODY;
64 m_cfg.aeromodel = eAeroModel::V_Point;
71 m_cfg.kDF = (btScalar)0.2;
73 m_cfg.kCHR = (btScalar)1.0;
74 m_cfg.kKHR = (btScalar)0.1;
75 m_cfg.kSHR = (btScalar)1.0;
76 m_cfg.kAHR = (btScalar)0.7;
77 m_cfg.kSRHR_CL = (btScalar)0.1;
78 m_cfg.kSKHR_CL = (btScalar)1;
79 m_cfg.kSSHR_CL = (btScalar)0.5;
80 m_cfg.kSR_SPLT_CL = (btScalar)0.5;
81 m_cfg.kSK_SPLT_CL = (btScalar)0.5;
82 m_cfg.kSS_SPLT_CL = (btScalar)0.5;
83 m_cfg.maxvolume = (btScalar)1;
85 m_cfg.viterations = 0;
86 m_cfg.piterations = 1;
87 m_cfg.diterations = 0;
88 m_cfg.citerations = 4;
89 m_cfg.collisions = fCollision::Default;
90 m_pose.m_bvolume = false;
91 m_pose.m_bframe = false;
93 m_pose.m_com = btVector3(0,0,0);
94 m_pose.m_rot.setIdentity();
95 m_pose.m_scl.setIdentity();
98 m_bUpdateRtCst = true;
99 m_bounds[0] = btVector3(0,0,0);
100 m_bounds[1] = btVector3(0,0,0);
101 m_worldTransform.setIdentity();
102 setSolver(eSolverPresets::Positions);
104 /* Collision shape */
105 ///for now, create a collision shape internally
106 m_collisionShape = new btSoftBodyCollisionShape(this);
107 m_collisionShape->setMargin(0.25);
109 m_initialWorldTransform.setIdentity();
111 m_windVelocity = btVector3(0,0,0);
116 btSoftBody::~btSoftBody()
118 //for now, delete the internal shape
119 delete m_collisionShape;
123 for(i=0;i<m_materials.size();++i)
124 btAlignedFree(m_materials[i]);
125 for(i=0;i<m_joints.size();++i)
126 btAlignedFree(m_joints[i]);
130 bool btSoftBody::checkLink(int node0,int node1) const
132 return(checkLink(&m_nodes[node0],&m_nodes[node1]));
136 bool btSoftBody::checkLink(const Node* node0,const Node* node1) const
138 const Node* n[]={node0,node1};
139 for(int i=0,ni=m_links.size();i<ni;++i)
141 const Link& l=m_links[i];
142 if( (l.m_n[0]==n[0]&&l.m_n[1]==n[1])||
143 (l.m_n[0]==n[1]&&l.m_n[1]==n[0]))
152 bool btSoftBody::checkFace(int node0,int node1,int node2) const
154 const Node* n[]={ &m_nodes[node0],
157 for(int i=0,ni=m_faces.size();i<ni;++i)
159 const Face& f=m_faces[i];
163 if( (f.m_n[j]==n[0])||
165 (f.m_n[j]==n[2])) c|=1<<j; else break;
167 if(c==7) return(true);
173 btSoftBody::Material* btSoftBody::appendMaterial()
175 Material* pm=new(btAlignedAlloc(sizeof(Material),16)) Material();
176 if(m_materials.size()>0)
180 m_materials.push_back(pm);
185 void btSoftBody::appendNote( const char* text,
198 n.m_coords[0] = c.x();
199 n.m_coords[1] = c.y();
200 n.m_coords[2] = c.z();
201 n.m_coords[3] = c.w();
202 n.m_nodes[0] = n0;n.m_rank+=n0?1:0;
203 n.m_nodes[1] = n1;n.m_rank+=n1?1:0;
204 n.m_nodes[2] = n2;n.m_rank+=n2?1:0;
205 n.m_nodes[3] = n3;n.m_rank+=n3?1:0;
206 m_notes.push_back(n);
210 void btSoftBody::appendNote( const char* text,
214 appendNote(text,o,btVector4(1,0,0,0),feature);
218 void btSoftBody::appendNote( const char* text,
222 static const btScalar w=1/(btScalar)2;
223 appendNote(text,o,btVector4(w,w,0,0), feature->m_n[0],
228 void btSoftBody::appendNote( const char* text,
232 static const btScalar w=1/(btScalar)3;
233 appendNote(text,o,btVector4(w,w,w,0), feature->m_n[0],
239 void btSoftBody::appendNode( const btVector3& x,btScalar m)
241 if(m_nodes.capacity()==m_nodes.size())
244 m_nodes.reserve(m_nodes.size()*2+1);
247 const btScalar margin=getCollisionShape()->getMargin();
248 m_nodes.push_back(Node());
249 Node& n=m_nodes[m_nodes.size()-1];
254 n.m_material = m_materials[0];
255 n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
259 void btSoftBody::appendLink(int model,Material* mat)
265 { ZeroInitialize(l);l.m_material=mat?mat:m_materials[0]; }
266 m_links.push_back(l);
270 void btSoftBody::appendLink( int node0,
275 appendLink(&m_nodes[node0],&m_nodes[node1],mat,bcheckexist);
279 void btSoftBody::appendLink( Node* node0,
284 if((!bcheckexist)||(!checkLink(node0,node1)))
287 Link& l=m_links[m_links.size()-1];
290 l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
296 void btSoftBody::appendFace(int model,Material* mat)
300 { f=m_faces[model]; }
302 { ZeroInitialize(f);f.m_material=mat?mat:m_materials[0]; }
303 m_faces.push_back(f);
307 void btSoftBody::appendFace(int node0,int node1,int node2,Material* mat)
317 Face& f=m_faces[m_faces.size()-1];
318 btAssert(node0!=node1);
319 btAssert(node1!=node2);
320 btAssert(node2!=node0);
321 f.m_n[0] = &m_nodes[node0];
322 f.m_n[1] = &m_nodes[node1];
323 f.m_n[2] = &m_nodes[node2];
324 f.m_ra = AreaOf( f.m_n[0]->m_x,
331 void btSoftBody::appendTetra(int model,Material* mat)
337 { ZeroInitialize(t);t.m_material=mat?mat:m_materials[0]; }
338 m_tetras.push_back(t);
342 void btSoftBody::appendTetra(int node0,
349 Tetra& t=m_tetras[m_tetras.size()-1];
350 t.m_n[0] = &m_nodes[node0];
351 t.m_n[1] = &m_nodes[node1];
352 t.m_n[2] = &m_nodes[node2];
353 t.m_n[3] = &m_nodes[node3];
354 t.m_rv = VolumeOf(t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x);
360 void btSoftBody::appendAnchor(int node,btRigidBody* body, bool disableCollisionBetweenLinkedBodies)
362 btVector3 local = body->getWorldTransform().inverse()*m_nodes[node].m_x;
363 appendAnchor(node,body,local,disableCollisionBetweenLinkedBodies);
367 void btSoftBody::appendAnchor(int node,btRigidBody* body, const btVector3& localPivot,bool disableCollisionBetweenLinkedBodies)
369 if (disableCollisionBetweenLinkedBodies)
371 if (m_collisionDisabledObjects.findLinearSearch(body)==m_collisionDisabledObjects.size())
373 m_collisionDisabledObjects.push_back(body);
378 a.m_node = &m_nodes[node];
380 a.m_local = localPivot;
381 a.m_node->m_battach = 1;
382 m_anchors.push_back(a);
386 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1)
388 LJoint* pj = new(btAlignedAlloc(sizeof(LJoint),16)) LJoint();
389 pj->m_bodies[0] = body0;
390 pj->m_bodies[1] = body1;
391 pj->m_refs[0] = pj->m_bodies[0].xform().inverse()*specs.position;
392 pj->m_refs[1] = pj->m_bodies[1].xform().inverse()*specs.position;
393 pj->m_cfm = specs.cfm;
394 pj->m_erp = specs.erp;
395 pj->m_split = specs.split;
396 m_joints.push_back(pj);
400 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body)
402 appendLinearJoint(specs,m_clusters[0],body);
406 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body)
408 appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]);
412 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1)
414 AJoint* pj = new(btAlignedAlloc(sizeof(AJoint),16)) AJoint();
415 pj->m_bodies[0] = body0;
416 pj->m_bodies[1] = body1;
417 pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis()*specs.axis;
418 pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis()*specs.axis;
419 pj->m_cfm = specs.cfm;
420 pj->m_erp = specs.erp;
421 pj->m_split = specs.split;
422 pj->m_icontrol = specs.icontrol;
423 m_joints.push_back(pj);
427 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body)
429 appendAngularJoint(specs,m_clusters[0],body);
433 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body)
435 appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]);
439 void btSoftBody::addForce(const btVector3& force)
441 for(int i=0,ni=m_nodes.size();i<ni;++i) addForce(force,i);
445 void btSoftBody::addForce(const btVector3& force,int node)
447 Node& n=m_nodes[node];
455 void btSoftBody::addVelocity(const btVector3& velocity)
457 for(int i=0,ni=m_nodes.size();i<ni;++i) addVelocity(velocity,i);
460 /* Set velocity for the entire body */
461 void btSoftBody::setVelocity( const btVector3& velocity)
463 for(int i=0,ni=m_nodes.size();i<ni;++i)
475 void btSoftBody::addVelocity(const btVector3& velocity,int node)
477 Node& n=m_nodes[node];
485 void btSoftBody::setMass(int node,btScalar mass)
487 m_nodes[node].m_im=mass>0?1/mass:0;
492 btScalar btSoftBody::getMass(int node) const
494 return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0);
498 btScalar btSoftBody::getTotalMass() const
501 for(int i=0;i<m_nodes.size();++i)
509 void btSoftBody::setTotalMass(btScalar mass,bool fromfaces)
516 for(i=0;i<m_nodes.size();++i)
520 for(i=0;i<m_faces.size();++i)
522 const Face& f=m_faces[i];
523 const btScalar twicearea=AreaOf( f.m_n[0]->m_x,
528 f.m_n[j]->m_im+=twicearea;
531 for( i=0;i<m_nodes.size();++i)
533 m_nodes[i].m_im=1/m_nodes[i].m_im;
536 const btScalar tm=getTotalMass();
537 const btScalar itm=1/tm;
538 for( i=0;i<m_nodes.size();++i)
540 m_nodes[i].m_im/=itm*mass;
546 void btSoftBody::setTotalDensity(btScalar density)
548 setTotalMass(getVolume()*density,true);
552 void btSoftBody::setVolumeMass(btScalar mass)
554 btAlignedObjectArray<btScalar> ranks;
555 ranks.resize(m_nodes.size(),0);
558 for(i=0;i<m_nodes.size();++i)
562 for(i=0;i<m_tetras.size();++i)
564 const Tetra& t=m_tetras[i];
567 t.m_n[j]->m_im+=btFabs(t.m_rv);
568 ranks[int(t.m_n[j]-&m_nodes[0])]+=1;
571 for( i=0;i<m_nodes.size();++i)
573 if(m_nodes[i].m_im>0)
575 m_nodes[i].m_im=ranks[i]/m_nodes[i].m_im;
578 setTotalMass(mass,false);
582 void btSoftBody::setVolumeDensity(btScalar density)
585 for(int i=0;i<m_tetras.size();++i)
587 const Tetra& t=m_tetras[i];
590 volume+=btFabs(t.m_rv);
593 setVolumeMass(volume*density/6);
597 void btSoftBody::transform(const btTransform& trs)
599 const btScalar margin=getCollisionShape()->getMargin();
600 ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
602 for(int i=0,ni=m_nodes.size();i<ni;++i)
607 n.m_n=trs.getBasis()*n.m_n;
608 vol = btDbvtVolume::FromCR(n.m_x,margin);
610 m_ndbvt.update(n.m_leaf,vol);
615 m_initialWorldTransform = trs;
619 void btSoftBody::translate(const btVector3& trs)
628 void btSoftBody::rotate( const btQuaternion& rot)
637 void btSoftBody::scale(const btVector3& scl)
640 const btScalar margin=getCollisionShape()->getMargin();
641 ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
643 for(int i=0,ni=m_nodes.size();i<ni;++i)
648 vol = btDbvtVolume::FromCR(n.m_x,margin);
649 m_ndbvt.update(n.m_leaf,vol);
657 void btSoftBody::setPose(bool bvolume,bool bframe)
659 m_pose.m_bvolume = bvolume;
660 m_pose.m_bframe = bframe;
664 const btScalar omass=getTotalMass();
665 const btScalar kmass=omass*m_nodes.size()*1000;
666 btScalar tmass=omass;
667 m_pose.m_wgh.resize(m_nodes.size());
668 for(i=0,ni=m_nodes.size();i<ni;++i)
670 if(m_nodes[i].m_im<=0) tmass+=kmass;
672 for( i=0,ni=m_nodes.size();i<ni;++i)
675 m_pose.m_wgh[i]= n.m_im>0 ?
676 1/(m_nodes[i].m_im*tmass) :
680 const btVector3 com=evaluateCom();
681 m_pose.m_pos.resize(m_nodes.size());
682 for( i=0,ni=m_nodes.size();i<ni;++i)
684 m_pose.m_pos[i]=m_nodes[i].m_x-com;
686 m_pose.m_volume = bvolume?getVolume():0;
688 m_pose.m_rot.setIdentity();
689 m_pose.m_scl.setIdentity();
693 m_pose.m_aqq[2] = btVector3(0,0,0);
694 for( i=0,ni=m_nodes.size();i<ni;++i)
696 const btVector3& q=m_pose.m_pos[i];
697 const btVector3 mq=m_pose.m_wgh[i]*q;
698 m_pose.m_aqq[0]+=mq.x()*q;
699 m_pose.m_aqq[1]+=mq.y()*q;
700 m_pose.m_aqq[2]+=mq.z()*q;
702 m_pose.m_aqq=m_pose.m_aqq.inverse();
707 btScalar btSoftBody::getVolume() const
714 const btVector3 org=m_nodes[0].m_x;
715 for(i=0,ni=m_faces.size();i<ni;++i)
717 const Face& f=m_faces[i];
718 vol+=btDot(f.m_n[0]->m_x-org,btCross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org));
726 int btSoftBody::clusterCount() const
728 return(m_clusters.size());
732 btVector3 btSoftBody::clusterCom(const Cluster* cluster)
734 btVector3 com(0,0,0);
735 for(int i=0,ni=cluster->m_nodes.size();i<ni;++i)
737 com+=cluster->m_nodes[i]->m_x*cluster->m_masses[i];
739 return(com*cluster->m_imass);
743 btVector3 btSoftBody::clusterCom(int cluster) const
745 return(clusterCom(m_clusters[cluster]));
749 btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos)
751 return(cluster->m_lv+btCross(cluster->m_av,rpos));
755 void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
757 const btVector3 li=cluster->m_imass*impulse;
758 const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse);
759 cluster->m_vimpulses[0]+=li;cluster->m_lv+=li;
760 cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
761 cluster->m_nvimpulses++;
765 void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
767 const btVector3 li=cluster->m_imass*impulse;
768 const btVector3 ai=cluster->m_invwi*btCross(rpos,impulse);
769 cluster->m_dimpulses[0]+=li;
770 cluster->m_dimpulses[1]+=ai;
771 cluster->m_ndimpulses++;
775 void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse)
777 if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity);
778 if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift);
782 void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse)
784 const btVector3 ai=cluster->m_invwi*impulse;
785 cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
786 cluster->m_nvimpulses++;
790 void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse)
792 const btVector3 ai=cluster->m_invwi*impulse;
793 cluster->m_dimpulses[1]+=ai;
794 cluster->m_ndimpulses++;
798 void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse)
800 if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity);
801 if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift);
805 void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse)
807 cluster->m_dimpulses[0]+=impulse*cluster->m_imass;
808 cluster->m_ndimpulses++;
813 btAlignedObjectArray<int> m_links;
819 int btSoftBody::generateBendingConstraints(int distance,Material* mat)
826 const int n=m_nodes.size();
827 const unsigned inf=(~(unsigned)0)>>1;
828 unsigned* adj=new unsigned[n*n];
831 #define IDX(_x_,_y_) ((_y_)*n+(_x_))
838 adj[IDX(i,j)]=adj[IDX(j,i)]=inf;
842 adj[IDX(i,j)]=adj[IDX(j,i)]=0;
846 for( i=0;i<m_links.size();++i)
848 const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
849 const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
855 //special optimized case for distance == 2
859 btAlignedObjectArray<NodeLinks> nodeLinks;
862 /* Build node links */
863 nodeLinks.resize(m_nodes.size());
865 for( i=0;i<m_links.size();++i)
867 const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
868 const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
869 if (nodeLinks[ia].m_links.findLinearSearch(ib)==nodeLinks[ia].m_links.size())
870 nodeLinks[ia].m_links.push_back(ib);
872 if (nodeLinks[ib].m_links.findLinearSearch(ia)==nodeLinks[ib].m_links.size())
873 nodeLinks[ib].m_links.push_back(ia);
875 for (int ii=0;ii<nodeLinks.size();ii++)
879 for (int jj=0;jj<nodeLinks[ii].m_links.size();jj++)
881 int k = nodeLinks[ii].m_links[jj];
882 for (int kk=0;kk<nodeLinks[k].m_links.size();kk++)
884 int j = nodeLinks[k].m_links[kk];
887 const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
889 if(adj[IDX(i,j)]>sum)
891 adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
900 ///generic Floyd's algorithm
907 const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
908 if(adj[IDX(i,j)]>sum)
910 adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
924 if(adj[IDX(i,j)]==(unsigned)distance)
927 m_links[m_links.size()-1].m_bbending=1;
939 void btSoftBody::randomizeConstraints()
941 unsigned long seed=243703;
942 #define NEXTRAND (seed=(1664525L*seed+1013904223L)&0xffffffff)
945 for(i=0,ni=m_links.size();i<ni;++i)
947 btSwap(m_links[i],m_links[NEXTRAND%ni]);
949 for(i=0,ni=m_faces.size();i<ni;++i)
951 btSwap(m_faces[i],m_faces[NEXTRAND%ni]);
957 void btSoftBody::releaseCluster(int index)
959 Cluster* c=m_clusters[index];
960 if(c->m_leaf) m_cdbvt.remove(c->m_leaf);
963 m_clusters.remove(c);
967 void btSoftBody::releaseClusters()
969 while(m_clusters.size()>0) releaseCluster(0);
973 int btSoftBody::generateClusters(int k,int maxiterations)
977 m_clusters.resize(btMin(k,m_nodes.size()));
978 for(i=0;i<m_clusters.size();++i)
980 m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
981 m_clusters[i]->m_collide= true;
987 btAlignedObjectArray<btVector3> centers;
988 btVector3 cog(0,0,0);
990 for(i=0;i<m_nodes.size();++i)
993 m_clusters[(i*29873)%m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
995 cog/=(btScalar)m_nodes.size();
996 centers.resize(k,cog);
998 const btScalar slope=16;
1002 const btScalar w=2-btMin<btScalar>(1,iterations/slope);
1010 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
1012 c+=m_clusters[i]->m_nodes[j]->m_x;
1014 if(m_clusters[i]->m_nodes.size())
1016 c /= (btScalar)m_clusters[i]->m_nodes.size();
1017 c = centers[i]+(c-centers[i])*w;
1018 changed |= ((c-centers[i]).length2()>SIMD_EPSILON);
1020 m_clusters[i]->m_nodes.resize(0);
1023 for(i=0;i<m_nodes.size();++i)
1025 const btVector3 nx=m_nodes[i].m_x;
1027 btScalar kdist=ClusterMetric(centers[0],nx);
1028 for(int j=1;j<k;++j)
1030 const btScalar d=ClusterMetric(centers[j],nx);
1037 m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
1039 } while(changed&&(iterations<maxiterations));
1041 btAlignedObjectArray<int> cids;
1042 cids.resize(m_nodes.size(),-1);
1043 for(i=0;i<m_clusters.size();++i)
1045 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
1047 cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i;
1050 for(i=0;i<m_faces.size();++i)
1052 const int idx[]={ int(m_faces[i].m_n[0]-&m_nodes[0]),
1053 int(m_faces[i].m_n[1]-&m_nodes[0]),
1054 int(m_faces[i].m_n[2]-&m_nodes[0])};
1055 for(int j=0;j<3;++j)
1057 const int cid=cids[idx[j]];
1058 for(int q=1;q<3;++q)
1060 const int kid=idx[(j+q)%3];
1063 if(m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size())
1065 m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
1072 if(m_clusters.size()>1)
1074 Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
1075 pmaster->m_collide = false;
1076 pmaster->m_nodes.reserve(m_nodes.size());
1077 for(int i=0;i<m_nodes.size();++i) pmaster->m_nodes.push_back(&m_nodes[i]);
1078 m_clusters.push_back(pmaster);
1079 btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]);
1082 for(i=0;i<m_clusters.size();++i)
1084 if(m_clusters[i]->m_nodes.size()==0)
1086 releaseCluster(i--);
1091 //create a cluster for each tetrahedron (if tetrahedra exist) or each face
1092 if (m_tetras.size())
1094 m_clusters.resize(m_tetras.size());
1095 for(i=0;i<m_clusters.size();++i)
1097 m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
1098 m_clusters[i]->m_collide= true;
1100 for (i=0;i<m_tetras.size();i++)
1102 for (int j=0;j<4;j++)
1104 m_clusters[i]->m_nodes.push_back(m_tetras[i].m_n[j]);
1110 m_clusters.resize(m_faces.size());
1111 for(i=0;i<m_clusters.size();++i)
1113 m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
1114 m_clusters[i]->m_collide= true;
1117 for(i=0;i<m_faces.size();++i)
1119 for(int j=0;j<3;++j)
1121 m_clusters[i]->m_nodes.push_back(m_faces[i].m_n[j]);
1127 if (m_clusters.size())
1129 initializeClusters();
1133 //for self-collision
1134 m_clusterConnectivity.resize(m_clusters.size()*m_clusters.size());
1136 for (int c0=0;c0<m_clusters.size();c0++)
1138 m_clusters[c0]->m_clusterIndex=c0;
1139 for (int c1=0;c1<m_clusters.size();c1++)
1142 bool connected=false;
1143 Cluster* cla = m_clusters[c0];
1144 Cluster* clb = m_clusters[c1];
1145 for (int i=0;!connected&&i<cla->m_nodes.size();i++)
1147 for (int j=0;j<clb->m_nodes.size();j++)
1149 if (cla->m_nodes[i] == clb->m_nodes[j])
1156 m_clusterConnectivity[c0+c1*m_clusters.size()]=connected;
1162 return(m_clusters.size());
1166 void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
1168 const Node* nbase = &m_nodes[0];
1169 int ncount = m_nodes.size();
1170 btSymMatrix<int> edges(ncount,-2);
1175 for(i=0;i<m_links.size();++i)
1180 if(!SameSign(ifn->Eval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x)))
1182 btSwap(m_links[i],m_links[m_links.size()-1]);
1183 m_links.pop_back();--i;
1188 for(i=0;i<m_links.size();++i)
1191 edges(int(l.m_n[0]-nbase),int(l.m_n[1]-nbase))=-1;
1193 for(i=0;i<m_faces.size();++i)
1196 edges(int(f.m_n[0]-nbase),int(f.m_n[1]-nbase))=-1;
1197 edges(int(f.m_n[1]-nbase),int(f.m_n[2]-nbase))=-1;
1198 edges(int(f.m_n[2]-nbase),int(f.m_n[0]-nbase))=-1;
1201 for(i=0;i<ncount;++i)
1203 for(j=i+1;j<ncount;++j)
1209 const btScalar t=ImplicitSolve(ifn,a.m_x,b.m_x,accurary);
1212 const btVector3 x=Lerp(a.m_x,b.m_x,t);
1213 const btVector3 v=Lerp(a.m_v,b.m_v,t);
1219 const btScalar ma=1/a.m_im;
1220 const btScalar mb=1/b.m_im;
1221 const btScalar mc=Lerp(ma,mb,t);
1222 const btScalar f=(ma+mb)/(ma+mb+mc);
1228 { a.m_im/=0.5;m=1/a.m_im; }
1233 { b.m_im/=0.5;m=1/b.m_im; }
1238 edges(i,j)=m_nodes.size()-1;
1239 m_nodes[edges(i,j)].m_v=v;
1247 for(i=0,ni=m_links.size();i<ni;++i)
1249 Link& feat=m_links[i];
1250 const int idx[]={ int(feat.m_n[0]-nbase),
1251 int(feat.m_n[1]-nbase)};
1252 if((idx[0]<ncount)&&(idx[1]<ncount))
1254 const int ni=edges(idx[0],idx[1]);
1258 Link* pft[]={ &m_links[i],
1259 &m_links[m_links.size()-1]};
1260 pft[0]->m_n[0]=&m_nodes[idx[0]];
1261 pft[0]->m_n[1]=&m_nodes[ni];
1262 pft[1]->m_n[0]=&m_nodes[ni];
1263 pft[1]->m_n[1]=&m_nodes[idx[1]];
1268 for(i=0;i<m_faces.size();++i)
1270 const Face& feat=m_faces[i];
1271 const int idx[]={ int(feat.m_n[0]-nbase),
1272 int(feat.m_n[1]-nbase),
1273 int(feat.m_n[2]-nbase)};
1274 for(j=2,k=0;k<3;j=k++)
1276 if((idx[j]<ncount)&&(idx[k]<ncount))
1278 const int ni=edges(idx[j],idx[k]);
1282 const int l=(k+1)%3;
1283 Face* pft[]={ &m_faces[i],
1284 &m_faces[m_faces.size()-1]};
1285 pft[0]->m_n[0]=&m_nodes[idx[l]];
1286 pft[0]->m_n[1]=&m_nodes[idx[j]];
1287 pft[0]->m_n[2]=&m_nodes[ni];
1288 pft[1]->m_n[0]=&m_nodes[ni];
1289 pft[1]->m_n[1]=&m_nodes[idx[k]];
1290 pft[1]->m_n[2]=&m_nodes[idx[l]];
1291 appendLink(ni,idx[l],pft[0]->m_material);
1300 btAlignedObjectArray<int> cnodes;
1301 const int pcount=ncount;
1303 ncount=m_nodes.size();
1304 cnodes.resize(ncount,0);
1306 for(i=0;i<ncount;++i)
1308 const btVector3 x=m_nodes[i].m_x;
1309 if((i>=pcount)||(btFabs(ifn->Eval(x))<accurary))
1311 const btVector3 v=m_nodes[i].m_v;
1312 btScalar m=getMass(i);
1313 if(m>0) { m*=0.5;m_nodes[i].m_im/=0.5; }
1315 cnodes[i]=m_nodes.size()-1;
1316 m_nodes[cnodes[i]].m_v=v;
1321 for(i=0,ni=m_links.size();i<ni;++i)
1323 const int id[]={ int(m_links[i].m_n[0]-nbase),
1324 int(m_links[i].m_n[1]-nbase)};
1326 if(cnodes[id[0]]&&cnodes[id[1]])
1329 todetach=m_links.size()-1;
1333 if(( (ifn->Eval(m_nodes[id[0]].m_x)<accurary)&&
1334 (ifn->Eval(m_nodes[id[1]].m_x)<accurary)))
1339 Link& l=m_links[todetach];
1340 for(int j=0;j<2;++j)
1342 int cn=cnodes[int(l.m_n[j]-nbase)];
1343 if(cn) l.m_n[j]=&m_nodes[cn];
1348 for(i=0,ni=m_faces.size();i<ni;++i)
1350 Node** n= m_faces[i].m_n;
1351 if( (ifn->Eval(n[0]->m_x)<accurary)&&
1352 (ifn->Eval(n[1]->m_x)<accurary)&&
1353 (ifn->Eval(n[2]->m_x)<accurary))
1355 for(int j=0;j<3;++j)
1357 int cn=cnodes[int(n[j]-nbase)];
1358 if(cn) n[j]=&m_nodes[cn];
1363 int nnodes=m_nodes.size();
1364 btAlignedObjectArray<int> ranks;
1365 btAlignedObjectArray<int> todelete;
1366 ranks.resize(nnodes,0);
1367 for(i=0,ni=m_links.size();i<ni;++i)
1369 for(int j=0;j<2;++j) ranks[int(m_links[i].m_n[j]-nbase)]++;
1371 for(i=0,ni=m_faces.size();i<ni;++i)
1373 for(int j=0;j<3;++j) ranks[int(m_faces[i].m_n[j]-nbase)]++;
1375 for(i=0;i<m_links.size();++i)
1377 const int id[]={ int(m_links[i].m_n[0]-nbase),
1378 int(m_links[i].m_n[1]-nbase)};
1379 const bool sg[]={ ranks[id[0]]==1,
1385 btSwap(m_links[i],m_links[m_links.size()-1]);
1386 m_links.pop_back();--i;
1390 for(i=nnodes-1;i>=0;--i)
1392 if(!ranks[i]) todelete.push_back(i);
1396 btAlignedObjectArray<int>& map=ranks;
1397 for(int i=0;i<nnodes;++i) map[i]=i;
1398 PointersToIndices(this);
1399 for(int i=0,ni=todelete.size();i<ni;++i)
1403 int& b=map[--nnodes];
1404 m_ndbvt.remove(m_nodes[a].m_leaf);m_nodes[a].m_leaf=0;
1405 btSwap(m_nodes[a],m_nodes[b]);
1408 IndicesToPointers(this,&map[0]);
1409 m_nodes.resize(nnodes);
1413 m_bUpdateRtCst=true;
1417 bool btSoftBody::cutLink(const Node* node0,const Node* node1,btScalar position)
1419 return(cutLink(int(node0-&m_nodes[0]),int(node1-&m_nodes[0]),position));
1423 bool btSoftBody::cutLink(int node0,int node1,btScalar position)
1427 const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
1428 const btVector3 x=Lerp(m_nodes[node0].m_x,m_nodes[node1].m_x,position);
1429 const btVector3 v=Lerp(m_nodes[node0].m_v,m_nodes[node1].m_v,position);
1433 Node* pa=&m_nodes[node0];
1434 Node* pb=&m_nodes[node1];
1435 Node* pn[2]={ &m_nodes[m_nodes.size()-2],
1436 &m_nodes[m_nodes.size()-1]};
1439 for(i=0,ni=m_links.size();i<ni;++i)
1441 const int mtch=MatchEdge(m_links[i].m_n[0],m_links[i].m_n[1],pa,pb);
1445 Link* pft[]={&m_links[i],&m_links[m_links.size()-1]};
1446 pft[0]->m_n[1]=pn[mtch];
1447 pft[1]->m_n[0]=pn[1-mtch];
1451 for(i=0,ni=m_faces.size();i<ni;++i)
1453 for(int k=2,l=0;l<3;k=l++)
1455 const int mtch=MatchEdge(m_faces[i].m_n[k],m_faces[i].m_n[l],pa,pb);
1459 Face* pft[]={&m_faces[i],&m_faces[m_faces.size()-1]};
1460 pft[0]->m_n[l]=pn[mtch];
1461 pft[1]->m_n[k]=pn[1-mtch];
1462 appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1463 appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1469 m_ndbvt.remove(pn[0]->m_leaf);
1470 m_ndbvt.remove(pn[1]->m_leaf);
1478 bool btSoftBody::rayTest(const btVector3& rayFrom,
1479 const btVector3& rayTo,
1482 if(m_faces.size()&&m_fdbvt.empty())
1483 initializeFaceTree();
1485 results.body = this;
1486 results.fraction = 1.f;
1487 results.feature = eFeature::None;
1490 return(rayTest(rayFrom,rayTo,results.fraction,results.feature,results.index,false)!=0);
1494 void btSoftBody::setSolver(eSolverPresets::_ preset)
1496 m_cfg.m_vsequence.clear();
1497 m_cfg.m_psequence.clear();
1498 m_cfg.m_dsequence.clear();
1501 case eSolverPresets::Positions:
1502 m_cfg.m_psequence.push_back(ePSolver::Anchors);
1503 m_cfg.m_psequence.push_back(ePSolver::RContacts);
1504 m_cfg.m_psequence.push_back(ePSolver::SContacts);
1505 m_cfg.m_psequence.push_back(ePSolver::Linear);
1507 case eSolverPresets::Velocities:
1508 m_cfg.m_vsequence.push_back(eVSolver::Linear);
1510 m_cfg.m_psequence.push_back(ePSolver::Anchors);
1511 m_cfg.m_psequence.push_back(ePSolver::RContacts);
1512 m_cfg.m_psequence.push_back(ePSolver::SContacts);
1514 m_cfg.m_dsequence.push_back(ePSolver::Linear);
1520 void btSoftBody::predictMotion(btScalar dt)
1528 m_bUpdateRtCst=false;
1531 if(m_cfg.collisions&fCollision::VF_SS)
1533 initializeFaceTree();
1538 m_sst.sdt = dt*m_cfg.timescale;
1539 m_sst.isdt = 1/m_sst.sdt;
1540 m_sst.velmrg = m_sst.sdt*3;
1541 m_sst.radmrg = getCollisionShape()->getMargin();
1542 m_sst.updmrg = m_sst.radmrg*(btScalar)0.25;
1544 addVelocity(m_worldInfo->m_gravity*m_sst.sdt);
1547 for(i=0,ni=m_nodes.size();i<ni;++i)
1551 n.m_v += n.m_f*n.m_im*m_sst.sdt;
1552 n.m_x += n.m_v*m_sst.sdt;
1553 n.m_f = btVector3(0,0,0);
1560 ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
1561 for(i=0,ni=m_nodes.size();i<ni;++i)
1564 vol = btDbvtVolume::FromCR(n.m_x,m_sst.radmrg);
1565 m_ndbvt.update( n.m_leaf,
1571 if(!m_fdbvt.empty())
1573 for(int i=0;i<m_faces.size();++i)
1576 const btVector3 v=( f.m_n[0]->m_v+
1579 vol = VolumeOf(f,m_sst.radmrg);
1580 m_fdbvt.update( f.m_leaf,
1589 if(m_pose.m_bframe&&(m_cfg.kMT>0))
1591 const btMatrix3x3 posetrs=m_pose.m_rot;
1592 for(int i=0,ni=m_nodes.size();i<ni;++i)
1597 const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com;
1598 n.m_x=Lerp(n.m_x,x,m_cfg.kMT);
1602 /* Clear contacts */
1603 m_rcontacts.resize(0);
1604 m_scontacts.resize(0);
1605 /* Optimize dbvt's */
1606 m_ndbvt.optimizeIncremental(1);
1607 m_fdbvt.optimizeIncremental(1);
1608 m_cdbvt.optimizeIncremental(1);
1612 void btSoftBody::solveConstraints()
1615 /* Apply clusters */
1616 applyClusters(false);
1621 for(i=0,ni=m_links.size();i<ni;++i)
1624 l.m_c3 = l.m_n[1]->m_q-l.m_n[0]->m_q;
1625 l.m_c2 = 1/(l.m_c3.length2()*l.m_c0);
1627 /* Prepare anchors */
1628 for(i=0,ni=m_anchors.size();i<ni;++i)
1630 Anchor& a=m_anchors[i];
1631 const btVector3 ra=a.m_body->getWorldTransform().getBasis()*a.m_local;
1632 a.m_c0 = ImpulseMatrix( m_sst.sdt,
1634 a.m_body->getInvMass(),
1635 a.m_body->getInvInertiaTensorWorld(),
1638 a.m_c2 = m_sst.sdt*a.m_node->m_im;
1639 a.m_body->activate();
1641 /* Solve velocities */
1642 if(m_cfg.viterations>0)
1645 for(int isolve=0;isolve<m_cfg.viterations;++isolve)
1647 for(int iseq=0;iseq<m_cfg.m_vsequence.size();++iseq)
1649 getSolver(m_cfg.m_vsequence[iseq])(this,1);
1653 for(i=0,ni=m_nodes.size();i<ni;++i)
1656 n.m_x = n.m_q+n.m_v*m_sst.sdt;
1659 /* Solve positions */
1660 if(m_cfg.piterations>0)
1662 for(int isolve=0;isolve<m_cfg.piterations;++isolve)
1664 const btScalar ti=isolve/(btScalar)m_cfg.piterations;
1665 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1667 getSolver(m_cfg.m_psequence[iseq])(this,1,ti);
1670 const btScalar vc=m_sst.isdt*(1-m_cfg.kDP);
1671 for(i=0,ni=m_nodes.size();i<ni;++i)
1674 n.m_v = (n.m_x-n.m_q)*vc;
1675 n.m_f = btVector3(0,0,0);
1679 if(m_cfg.diterations>0)
1681 const btScalar vcf=m_cfg.kVCF*m_sst.isdt;
1682 for(i=0,ni=m_nodes.size();i<ni;++i)
1687 for(int idrift=0;idrift<m_cfg.diterations;++idrift)
1689 for(int iseq=0;iseq<m_cfg.m_dsequence.size();++iseq)
1691 getSolver(m_cfg.m_dsequence[iseq])(this,1,0);
1694 for(int i=0,ni=m_nodes.size();i<ni;++i)
1697 n.m_v += (n.m_x-n.m_q)*vcf;
1700 /* Apply clusters */
1702 applyClusters(true);
1706 void btSoftBody::staticSolve(int iterations)
1708 for(int isolve=0;isolve<iterations;++isolve)
1710 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1712 getSolver(m_cfg.m_psequence[iseq])(this,1,0);
1718 void btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/,int /*count*/,int /*iterations*/)
1724 void btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
1726 const int nb=bodies.size();
1732 iterations=btMax(iterations,bodies[i]->m_cfg.citerations);
1736 bodies[i]->prepareClusters(iterations);
1738 for(i=0;i<iterations;++i)
1740 const btScalar sor=1;
1741 for(int j=0;j<nb;++j)
1743 bodies[j]->solveClusters(sor);
1748 bodies[i]->cleanupClusters();
1753 void btSoftBody::integrateMotion()
1760 btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt)
1762 m_rayFrom = rayFrom;
1763 m_rayNormalizedDirection = (rayTo-rayFrom);
1771 void btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf)
1773 btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data;
1774 const btScalar t=rayFromToTriangle( m_rayFrom,m_rayTo,m_rayNormalizedDirection,
1779 if((t>0)&&(t<m_mint))
1787 btScalar btSoftBody::RayFromToCaster::rayFromToTriangle( const btVector3& rayFrom,
1788 const btVector3& rayTo,
1789 const btVector3& rayNormalizedDirection,
1795 static const btScalar ceps=-SIMD_EPSILON*10;
1796 static const btScalar teps=SIMD_EPSILON*10;
1798 const btVector3 n=btCross(b-a,c-a);
1799 const btScalar d=btDot(a,n);
1800 const btScalar den=btDot(rayNormalizedDirection,n);
1801 if(!btFuzzyZero(den))
1803 const btScalar num=btDot(rayFrom,n)-d;
1804 const btScalar t=-num/den;
1805 if((t>teps)&&(t<maxt))
1807 const btVector3 hit=rayFrom+rayNormalizedDirection*t;
1808 if( (btDot(n,btCross(a-hit,b-hit))>ceps) &&
1809 (btDot(n,btCross(b-hit,c-hit))>ceps) &&
1810 (btDot(n,btCross(c-hit,a-hit))>ceps))
1820 void btSoftBody::pointersToIndices()
1822 #define PTR2IDX(_p_,_b_) reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_))
1823 btSoftBody::Node* base=&m_nodes[0];
1826 for(i=0,ni=m_nodes.size();i<ni;++i)
1828 if(m_nodes[i].m_leaf)
1830 m_nodes[i].m_leaf->data=*(void**)&i;
1833 for(i=0,ni=m_links.size();i<ni;++i)
1835 m_links[i].m_n[0]=PTR2IDX(m_links[i].m_n[0],base);
1836 m_links[i].m_n[1]=PTR2IDX(m_links[i].m_n[1],base);
1838 for(i=0,ni=m_faces.size();i<ni;++i)
1840 m_faces[i].m_n[0]=PTR2IDX(m_faces[i].m_n[0],base);
1841 m_faces[i].m_n[1]=PTR2IDX(m_faces[i].m_n[1],base);
1842 m_faces[i].m_n[2]=PTR2IDX(m_faces[i].m_n[2],base);
1843 if(m_faces[i].m_leaf)
1845 m_faces[i].m_leaf->data=*(void**)&i;
1848 for(i=0,ni=m_anchors.size();i<ni;++i)
1850 m_anchors[i].m_node=PTR2IDX(m_anchors[i].m_node,base);
1852 for(i=0,ni=m_notes.size();i<ni;++i)
1854 for(int j=0;j<m_notes[i].m_rank;++j)
1856 m_notes[i].m_nodes[j]=PTR2IDX(m_notes[i].m_nodes[j],base);
1863 void btSoftBody::indicesToPointers(const int* map)
1865 #define IDX2PTR(_p_,_b_) map?(&(_b_)[map[(((char*)_p_)-(char*)0)]]): \
1866 (&(_b_)[(((char*)_p_)-(char*)0)])
1867 btSoftBody::Node* base=&m_nodes[0];
1870 for(i=0,ni=m_nodes.size();i<ni;++i)
1872 if(m_nodes[i].m_leaf)
1874 m_nodes[i].m_leaf->data=&m_nodes[i];
1877 for(i=0,ni=m_links.size();i<ni;++i)
1879 m_links[i].m_n[0]=IDX2PTR(m_links[i].m_n[0],base);
1880 m_links[i].m_n[1]=IDX2PTR(m_links[i].m_n[1],base);
1882 for(i=0,ni=m_faces.size();i<ni;++i)
1884 m_faces[i].m_n[0]=IDX2PTR(m_faces[i].m_n[0],base);
1885 m_faces[i].m_n[1]=IDX2PTR(m_faces[i].m_n[1],base);
1886 m_faces[i].m_n[2]=IDX2PTR(m_faces[i].m_n[2],base);
1887 if(m_faces[i].m_leaf)
1889 m_faces[i].m_leaf->data=&m_faces[i];
1892 for(i=0,ni=m_anchors.size();i<ni;++i)
1894 m_anchors[i].m_node=IDX2PTR(m_anchors[i].m_node,base);
1896 for(i=0,ni=m_notes.size();i<ni;++i)
1898 for(int j=0;j<m_notes[i].m_rank;++j)
1900 m_notes[i].m_nodes[j]=IDX2PTR(m_notes[i].m_nodes[j],base);
1907 int btSoftBody::rayTest(const btVector3& rayFrom,const btVector3& rayTo,
1908 btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const
1911 if(bcountonly||m_fdbvt.empty())
1913 btVector3 dir = rayTo-rayFrom;
1916 for(int i=0,ni=m_faces.size();i<ni;++i)
1918 const btSoftBody::Face& f=m_faces[i];
1920 const btScalar t=RayFromToCaster::rayFromToTriangle( rayFrom,rayTo,dir,
1930 feature=btSoftBody::eFeature::Face;
1939 RayFromToCaster collider(rayFrom,rayTo,mint);
1941 btDbvt::rayTest(m_fdbvt.m_root,rayFrom,rayTo,collider);
1944 mint=collider.m_mint;
1945 feature=btSoftBody::eFeature::Face;
1946 index=(int)(collider.m_face-&m_faces[0]);
1954 void btSoftBody::initializeFaceTree()
1957 for(int i=0;i<m_faces.size();++i)
1960 f.m_leaf=m_fdbvt.insert(VolumeOf(f,0),&f);
1965 btVector3 btSoftBody::evaluateCom() const
1967 btVector3 com(0,0,0);
1970 for(int i=0,ni=m_nodes.size();i<ni;++i)
1972 com+=m_nodes[i].m_x*m_pose.m_wgh[i];
1979 bool btSoftBody::checkContact( btCollisionObject* colObj,
1982 btSoftBody::sCti& cti) const
1985 btCollisionShape *shp = colObj->getCollisionShape();
1986 btRigidBody *tmpRigid = btRigidBody::upcast(colObj);
1987 const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObj->getWorldTransform();
1989 m_worldInfo->m_sparsesdf.Evaluate(
1996 cti.m_colObj = colObj;
1997 cti.m_normal = wtr.getBasis()*nrm;
1998 cti.m_offset = -btDot( cti.m_normal, x - cti.m_normal * dst );
2005 void btSoftBody::updateNormals()
2008 const btVector3 zv(0,0,0);
2011 for(i=0,ni=m_nodes.size();i<ni;++i)
2015 for(i=0,ni=m_faces.size();i<ni;++i)
2017 btSoftBody::Face& f=m_faces[i];
2018 const btVector3 n=btCross(f.m_n[1]->m_x-f.m_n[0]->m_x,
2019 f.m_n[2]->m_x-f.m_n[0]->m_x);
2020 f.m_normal=n.normalized();
2025 for(i=0,ni=m_nodes.size();i<ni;++i)
2027 btScalar len = m_nodes[i].m_n.length();
2028 if (len>SIMD_EPSILON)
2029 m_nodes[i].m_n /= len;
2034 void btSoftBody::updateBounds()
2036 /*if( m_acceleratedSoftBody )
2038 // If we have an accelerated softbody we need to obtain the bounds correctly
2039 // For now (slightly hackily) just have a very large AABB
2040 // TODO: Write get bounds kernel
2041 // If that is updating in place, atomic collisions might be low (when the cloth isn't perfectly aligned to an axis) and we could
2042 // probably do a test and exchange reasonably efficiently.
2044 m_bounds[0] = btVector3(-1000, -1000, -1000);
2045 m_bounds[1] = btVector3(1000, 1000, 1000);
2050 const btVector3& mins=m_ndbvt.m_root->volume.Mins();
2051 const btVector3& maxs=m_ndbvt.m_root->volume.Maxs();
2052 const btScalar csm=getCollisionShape()->getMargin();
2053 const btVector3 mrg=btVector3( csm,
2055 csm)*1; // ??? to investigate...
2056 m_bounds[0]=mins-mrg;
2057 m_bounds[1]=maxs+mrg;
2058 if(0!=getBroadphaseHandle())
2060 m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(),
2063 m_worldInfo->m_dispatcher);
2069 m_bounds[1]=btVector3(0,0,0);
2076 void btSoftBody::updatePose()
2080 btSoftBody::Pose& pose=m_pose;
2081 const btVector3 com=evaluateCom();
2086 const btScalar eps=SIMD_EPSILON;
2087 Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0);
2088 Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3);
2089 for(int i=0,ni=m_nodes.size();i<ni;++i)
2091 const btVector3 a=pose.m_wgh[i]*(m_nodes[i].m_x-com);
2092 const btVector3& b=pose.m_pos[i];
2098 PolarDecompose(Apq,r,s);
2100 pose.m_scl=pose.m_aqq*r.transpose()*Apq;
2101 if(m_cfg.maxvolume>1)
2103 const btScalar idet=Clamp<btScalar>( 1/pose.m_scl.determinant(),
2105 pose.m_scl=Mul(pose.m_scl,idet);
2112 void btSoftBody::updateConstants()
2117 for(i=0,ni=m_links.size();i<ni;++i)
2120 Material& m=*l.m_material;
2121 l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
2122 l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST;
2123 l.m_c1 = l.m_rl*l.m_rl;
2126 for(i=0,ni=m_faces.size();i<ni;++i)
2129 f.m_ra = AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
2132 btAlignedObjectArray<int> counts;
2133 counts.resize(m_nodes.size(),0);
2134 for(i=0,ni=m_nodes.size();i<ni;++i)
2136 m_nodes[i].m_area = 0;
2138 for(i=0,ni=m_faces.size();i<ni;++i)
2140 btSoftBody::Face& f=m_faces[i];
2141 for(int j=0;j<3;++j)
2143 const int index=(int)(f.m_n[j]-&m_nodes[0]);
2145 f.m_n[j]->m_area+=btFabs(f.m_ra);
2148 for(i=0,ni=m_nodes.size();i<ni;++i)
2151 m_nodes[i].m_area/=(btScalar)counts[i];
2153 m_nodes[i].m_area=0;
2158 void btSoftBody::initializeClusters()
2162 for( i=0;i<m_clusters.size();++i)
2164 Cluster& c=*m_clusters[i];
2166 c.m_masses.resize(c.m_nodes.size());
2167 for(int j=0;j<c.m_nodes.size();++j)
2169 if (c.m_nodes[j]->m_im==0)
2171 c.m_containsAnchor = true;
2172 c.m_masses[j] = BT_LARGE_FLOAT;
2175 c.m_masses[j] = btScalar(1.)/c.m_nodes[j]->m_im;
2177 c.m_imass += c.m_masses[j];
2179 c.m_imass = btScalar(1.)/c.m_imass;
2180 c.m_com = btSoftBody::clusterCom(&c);
2181 c.m_lv = btVector3(0,0,0);
2182 c.m_av = btVector3(0,0,0);
2185 btMatrix3x3& ii=c.m_locii;
2186 ii[0]=ii[1]=ii[2]=btVector3(0,0,0);
2190 for(i=0,ni=c.m_nodes.size();i<ni;++i)
2192 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
2193 const btVector3 q=k*k;
2194 const btScalar m=c.m_masses[i];
2195 ii[0][0] += m*(q[1]+q[2]);
2196 ii[1][1] += m*(q[0]+q[2]);
2197 ii[2][2] += m*(q[0]+q[1]);
2198 ii[0][1] -= m*k[0]*k[1];
2199 ii[0][2] -= m*k[0]*k[2];
2200 ii[1][2] -= m*k[1]*k[2];
2210 c.m_framexform.setIdentity();
2211 c.m_framexform.setOrigin(c.m_com);
2212 c.m_framerefs.resize(c.m_nodes.size());
2215 for(i=0;i<c.m_framerefs.size();++i)
2217 c.m_framerefs[i]=c.m_nodes[i]->m_x-c.m_com;
2224 void btSoftBody::updateClusters()
2226 BT_PROFILE("UpdateClusters");
2229 for(i=0;i<m_clusters.size();++i)
2231 btSoftBody::Cluster& c=*m_clusters[i];
2232 const int n=c.m_nodes.size();
2233 //const btScalar invn=1/(btScalar)n;
2237 const btScalar eps=btScalar(0.0001);
2239 m[0]=m[1]=m[2]=btVector3(0,0,0);
2243 c.m_com=clusterCom(&c);
2244 for(int i=0;i<c.m_nodes.size();++i)
2246 const btVector3 a=c.m_nodes[i]->m_x-c.m_com;
2247 const btVector3& b=c.m_framerefs[i];
2248 m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b;
2250 PolarDecompose(m,r,s);
2251 c.m_framexform.setOrigin(c.m_com);
2252 c.m_framexform.setBasis(r);
2255 c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose();
2258 const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass);
2259 const btVector3 inertia(rk,rk,rk);
2260 const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
2261 btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0,
2262 btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
2264 c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
2266 c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0);
2267 for(int i=0;i<n;++i)
2269 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
2270 const btVector3 q=k*k;
2271 const btScalar m=1/c.m_nodes[i]->m_im;
2272 c.m_invwi[0][0] += m*(q[1]+q[2]);
2273 c.m_invwi[1][1] += m*(q[0]+q[2]);
2274 c.m_invwi[2][2] += m*(q[0]+q[1]);
2275 c.m_invwi[0][1] -= m*k[0]*k[1];
2276 c.m_invwi[0][2] -= m*k[0]*k[2];
2277 c.m_invwi[1][2] -= m*k[1]*k[2];
2279 c.m_invwi[1][0]=c.m_invwi[0][1];
2280 c.m_invwi[2][0]=c.m_invwi[0][2];
2281 c.m_invwi[2][1]=c.m_invwi[1][2];
2282 c.m_invwi=c.m_invwi.inverse();
2286 c.m_lv=btVector3(0,0,0);
2287 c.m_av=btVector3(0,0,0);
2293 const btVector3 v=c.m_nodes[i]->m_v*c.m_masses[i];
2295 c.m_av += btCross(c.m_nodes[i]->m_x-c.m_com,v);
2298 c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping);
2299 c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping);
2301 c.m_vimpulses[1] = btVector3(0,0,0);
2303 c.m_dimpulses[1] = btVector3(0,0,0);
2309 for(int j=0;j<c.m_nodes.size();++j)
2311 Node& n=*c.m_nodes[j];
2312 const btVector3 x=c.m_framexform*c.m_framerefs[j];
2313 n.m_x=Lerp(n.m_x,x,c.m_matching);
2319 btVector3 mi=c.m_nodes[0]->m_x;
2321 for(int j=1;j<n;++j)
2323 mi.setMin(c.m_nodes[j]->m_x);
2324 mx.setMax(c.m_nodes[j]->m_x);
2326 ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx);
2328 m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg);
2330 c.m_leaf=m_cdbvt.insert(bounds,&c);
2342 void btSoftBody::cleanupClusters()
2344 for(int i=0;i<m_joints.size();++i)
2346 m_joints[i]->Terminate(m_sst.sdt);
2347 if(m_joints[i]->m_delete)
2349 btAlignedFree(m_joints[i]);
2350 m_joints.remove(m_joints[i--]);
2356 void btSoftBody::prepareClusters(int iterations)
2358 for(int i=0;i<m_joints.size();++i)
2360 m_joints[i]->Prepare(m_sst.sdt,iterations);
2366 void btSoftBody::solveClusters(btScalar sor)
2368 for(int i=0,ni=m_joints.size();i<ni;++i)
2370 m_joints[i]->Solve(m_sst.sdt,sor);
2375 void btSoftBody::applyClusters(bool drift)
2377 BT_PROFILE("ApplyClusters");
2378 // const btScalar f0=m_sst.sdt;
2379 //const btScalar f1=f0/2;
2380 btAlignedObjectArray<btVector3> deltas;
2381 btAlignedObjectArray<btScalar> weights;
2382 deltas.resize(m_nodes.size(),btVector3(0,0,0));
2383 weights.resize(m_nodes.size(),0);
2388 for(i=0;i<m_clusters.size();++i)
2390 Cluster& c=*m_clusters[i];
2393 c.m_dimpulses[0]/=(btScalar)c.m_ndimpulses;
2394 c.m_dimpulses[1]/=(btScalar)c.m_ndimpulses;
2399 for(i=0;i<m_clusters.size();++i)
2401 Cluster& c=*m_clusters[i];
2402 if(0<(drift?c.m_ndimpulses:c.m_nvimpulses))
2404 const btVector3 v=(drift?c.m_dimpulses[0]:c.m_vimpulses[0])*m_sst.sdt;
2405 const btVector3 w=(drift?c.m_dimpulses[1]:c.m_vimpulses[1])*m_sst.sdt;
2406 for(int j=0;j<c.m_nodes.size();++j)
2408 const int idx=int(c.m_nodes[j]-&m_nodes[0]);
2409 const btVector3& x=c.m_nodes[j]->m_x;
2410 const btScalar q=c.m_masses[j];
2411 deltas[idx] += (v+btCross(w,x-c.m_com))*q;
2416 for(i=0;i<deltas.size();++i)
2420 m_nodes[i].m_x+=deltas[i]/weights[i];
2426 void btSoftBody::dampClusters()
2430 for(i=0;i<m_clusters.size();++i)
2432 Cluster& c=*m_clusters[i];
2435 for(int j=0;j<c.m_nodes.size();++j)
2437 Node& n=*c.m_nodes[j];
2440 const btVector3 vx=c.m_lv+btCross(c.m_av,c.m_nodes[j]->m_q-c.m_com);
2441 if(vx.length2()<=n.m_v.length2())
2443 n.m_v += c.m_ndamping*(vx-n.m_v);
2452 void btSoftBody::Joint::Prepare(btScalar dt,int)
2454 m_bodies[0].activate();
2455 m_bodies[1].activate();
2459 void btSoftBody::LJoint::Prepare(btScalar dt,int iterations)
2461 static const btScalar maxdrift=4;
2462 Joint::Prepare(dt,iterations);
2463 m_rpos[0] = m_bodies[0].xform()*m_refs[0];
2464 m_rpos[1] = m_bodies[1].xform()*m_refs[1];
2465 m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt;
2466 m_rpos[0] -= m_bodies[0].xform().getOrigin();
2467 m_rpos[1] -= m_bodies[1].xform().getOrigin();
2468 m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0],
2469 m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]);
2472 m_sdrift = m_massmatrix*(m_drift*m_split);
2473 m_drift *= 1-m_split;
2475 m_drift /=(btScalar)iterations;
2479 void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor)
2481 const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
2482 const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
2483 const btVector3 vr=va-vb;
2484 btSoftBody::Impulse impulse;
2485 impulse.m_asVelocity = 1;
2486 impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor;
2487 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2488 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2492 void btSoftBody::LJoint::Terminate(btScalar dt)
2496 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2497 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2502 void btSoftBody::AJoint::Prepare(btScalar dt,int iterations)
2504 static const btScalar maxdrift=SIMD_PI/16;
2505 m_icontrol->Prepare(this);
2506 Joint::Prepare(dt,iterations);
2507 m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0];
2508 m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1];
2509 m_drift = NormalizeAny(btCross(m_axis[1],m_axis[0]));
2510 m_drift *= btMin(maxdrift,btAcos(Clamp<btScalar>(btDot(m_axis[0],m_axis[1]),-1,+1)));
2511 m_drift *= m_erp/dt;
2512 m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia());
2515 m_sdrift = m_massmatrix*(m_drift*m_split);
2516 m_drift *= 1-m_split;
2518 m_drift /=(btScalar)iterations;
2522 void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor)
2524 const btVector3 va=m_bodies[0].angularVelocity();
2525 const btVector3 vb=m_bodies[1].angularVelocity();
2526 const btVector3 vr=va-vb;
2527 const btScalar sp=btDot(vr,m_axis[0]);
2528 const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp);
2529 btSoftBody::Impulse impulse;
2530 impulse.m_asVelocity = 1;
2531 impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor;
2532 m_bodies[0].applyAImpulse(-impulse);
2533 m_bodies[1].applyAImpulse( impulse);
2537 void btSoftBody::AJoint::Terminate(btScalar dt)
2541 m_bodies[0].applyDAImpulse(-m_sdrift);
2542 m_bodies[1].applyDAImpulse( m_sdrift);
2547 void btSoftBody::CJoint::Prepare(btScalar dt,int iterations)
2549 Joint::Prepare(dt,iterations);
2550 const bool dodrift=(m_life==0);
2551 m_delete=(++m_life)>m_maxlife;
2554 m_drift=m_drift*m_erp/dt;
2557 m_sdrift = m_massmatrix*(m_drift*m_split);
2558 m_drift *= 1-m_split;
2560 m_drift/=(btScalar)iterations;
2564 m_drift=m_sdrift=btVector3(0,0,0);
2569 void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor)
2571 const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
2572 const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
2573 const btVector3 vrel=va-vb;
2574 const btScalar rvac=btDot(vrel,m_normal);
2575 btSoftBody::Impulse impulse;
2576 impulse.m_asVelocity = 1;
2577 impulse.m_velocity = m_drift;
2580 const btVector3 iv=m_normal*rvac;
2581 const btVector3 fv=vrel-iv;
2582 impulse.m_velocity += iv+fv*m_friction;
2584 impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor;
2586 if (m_bodies[0].m_soft==m_bodies[1].m_soft)
2588 if ((impulse.m_velocity.getX() ==impulse.m_velocity.getX())&&(impulse.m_velocity.getY() ==impulse.m_velocity.getY())&&
2589 (impulse.m_velocity.getZ() ==impulse.m_velocity.getZ()))
2591 if (impulse.m_asVelocity)
2593 if (impulse.m_velocity.length() <m_bodies[0].m_soft->m_maxSelfCollisionImpulse)
2598 m_bodies[0].applyImpulse(-impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[0]);
2599 m_bodies[1].applyImpulse( impulse*m_bodies[0].m_soft->m_selfCollisionImpulseFactor,m_rpos[1]);
2605 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2606 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2611 void btSoftBody::CJoint::Terminate(btScalar dt)
2615 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2616 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2621 void btSoftBody::applyForces()
2624 BT_PROFILE("SoftBody applyForces");
2625 const btScalar dt = m_sst.sdt;
2626 const btScalar kLF = m_cfg.kLF;
2627 const btScalar kDG = m_cfg.kDG;
2628 const btScalar kPR = m_cfg.kPR;
2629 const btScalar kVC = m_cfg.kVC;
2630 const bool as_lift = kLF>0;
2631 const bool as_drag = kDG>0;
2632 const bool as_pressure = kPR!=0;
2633 const bool as_volume = kVC>0;
2634 const bool as_aero = as_lift ||
2636 const bool as_vaero = as_aero &&
2637 (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
2638 const bool as_faero = as_aero &&
2639 (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
2640 const bool use_medium = as_aero;
2641 const bool use_volume = as_pressure ||
2643 btScalar volume = 0;
2644 btScalar ivolumetp = 0;
2645 btScalar dvolumetv = 0;
2646 btSoftBody::sMedium medium;
2649 volume = getVolume();
2650 ivolumetp = 1/btFabs(volume)*kPR;
2651 dvolumetv = (m_pose.m_volume-volume)*kVC;
2653 /* Per vertex forces */
2656 for(i=0,ni=m_nodes.size();i<ni;++i)
2658 btSoftBody::Node& n=m_nodes[i];
2663 EvaluateMedium(m_worldInfo, n.m_x, medium);
2664 medium.m_velocity = m_windVelocity;
2665 medium.m_density = m_worldInfo->air_density;
2670 const btVector3 rel_v = n.m_v - medium.m_velocity;
2671 const btScalar rel_v2 = rel_v.length2();
2672 if(rel_v2>SIMD_EPSILON)
2674 btVector3 nrm = n.m_n;
2676 switch(m_cfg.aeromodel)
2678 case btSoftBody::eAeroModel::V_Point:
2679 nrm = NormalizeAny(rel_v);
2681 case btSoftBody::eAeroModel::V_TwoSided:
2682 nrm *= (btScalar)( (btDot(nrm,rel_v) < 0) ? -1 : +1);
2688 const btScalar dvn = btDot(rel_v,nrm);
2689 /* Compute forces */
2692 btVector3 force(0,0,0);
2693 const btScalar c0 = n.m_area * dvn * rel_v2/2;
2694 const btScalar c1 = c0 * medium.m_density;
2695 force += nrm*(-c1*kLF);
2696 force += rel_v.normalized() * (-c1 * kDG);
2697 ApplyClampedForce(n, force, dt);
2705 n.m_f += n.m_n*(n.m_area*ivolumetp);
2710 n.m_f += n.m_n*(n.m_area*dvolumetv);
2714 /* Per face forces */
2715 for(i=0,ni=m_faces.size();i<ni;++i)
2717 btSoftBody::Face& f=m_faces[i];
2720 const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3;
2721 const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3;
2722 EvaluateMedium(m_worldInfo,x,medium);
2723 const btVector3 rel_v=v-medium.m_velocity;
2724 const btScalar rel_v2=rel_v.length2();
2725 if(rel_v2>SIMD_EPSILON)
2727 btVector3 nrm=f.m_normal;
2729 switch(m_cfg.aeromodel)
2731 case btSoftBody::eAeroModel::F_TwoSided:
2732 nrm*=(btScalar)(btDot(nrm,rel_v)<0?-1:+1);break;
2737 const btScalar dvn=btDot(rel_v,nrm);
2738 /* Compute forces */
2741 btVector3 force(0,0,0);
2742 const btScalar c0 = f.m_ra*dvn*rel_v2;
2743 const btScalar c1 = c0*medium.m_density;
2744 force += nrm*(-c1*kLF);
2745 force += rel_v.normalized()*(-c1*kDG);
2747 for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt);
2755 void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti)
2757 const btScalar kAHR=psb->m_cfg.kAHR*kst;
2758 const btScalar dt=psb->m_sst.sdt;
2759 for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
2761 const Anchor& a=psb->m_anchors[i];
2762 const btTransform& t=a.m_body->getWorldTransform();
2764 const btVector3 wa=t*a.m_local;
2765 const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt;
2766 const btVector3 vb=n.m_x-n.m_q;
2767 const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR;
2768 const btVector3 impulse=a.m_c0*vr;
2769 n.m_x+=impulse*a.m_c2;
2770 a.m_body->applyImpulse(-impulse,a.m_c1);
2775 void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti)
2777 const btScalar dt = psb->m_sst.sdt;
2778 const btScalar mrg = psb->getCollisionShape()->getMargin();
2779 for(int i=0,ni=psb->m_rcontacts.size();i<ni;++i)
2781 const RContact& c = psb->m_rcontacts[i];
2782 const sCti& cti = c.m_cti;
2783 btRigidBody* tmpRigid = btRigidBody::upcast(cti.m_colObj);
2785 const btVector3 va = tmpRigid ? tmpRigid->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0);
2786 const btVector3 vb = c.m_node->m_x-c.m_node->m_q;
2787 const btVector3 vr = vb-va;
2788 const btScalar dn = btDot(vr, cti.m_normal);
2789 if(dn<=SIMD_EPSILON)
2791 const btScalar dp = btMin( (btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg );
2792 const btVector3 fv = vr - (cti.m_normal * dn);
2793 // c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient
2794 const btVector3 impulse = c.m_c0 * ( (vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst );
2795 c.m_node->m_x -= impulse * c.m_c2;
2797 tmpRigid->applyImpulse(impulse,c.m_c1);
2803 void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti)
2805 for(int i=0,ni=psb->m_scontacts.size();i<ni;++i)
2807 const SContact& c=psb->m_scontacts[i];
2808 const btVector3& nr=c.m_normal;
2811 const btVector3 p=BaryEval( f.m_n[0]->m_x,
2815 const btVector3 q=BaryEval( f.m_n[0]->m_q,
2819 const btVector3 vr=(n.m_x-n.m_q)-(p-q);
2820 btVector3 corr(0,0,0);
2821 btScalar dot = btDot(vr,nr);
2824 const btScalar j=c.m_margin-(btDot(nr,n.m_x)-btDot(nr,p));
2827 corr -= ProjectOnPlane(vr,nr)*c.m_friction;
2828 n.m_x += corr*c.m_cfm[0];
2829 f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x());
2830 f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y());
2831 f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z());
2836 void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti)
2838 for(int i=0,ni=psb->m_links.size();i<ni;++i)
2840 Link& l=psb->m_links[i];
2845 const btVector3 del=b.m_x-a.m_x;
2846 const btScalar len=del.length2();
2847 if (l.m_c1+len > SIMD_EPSILON)
2849 const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst;
2850 a.m_x-=del*(k*a.m_im);
2851 b.m_x+=del*(k*b.m_im);
2858 void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst)
2860 for(int i=0,ni=psb->m_links.size();i<ni;++i)
2862 Link& l=psb->m_links[i];
2864 const btScalar j=-btDot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst;
2865 n[0]->m_v+= l.m_c3*(j*n[0]->m_im);
2866 n[1]->m_v-= l.m_c3*(j*n[1]->m_im);
2871 btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver)
2875 case ePSolver::Anchors:
2876 return(&btSoftBody::PSolve_Anchors);
2877 case ePSolver::Linear:
2878 return(&btSoftBody::PSolve_Links);
2879 case ePSolver::RContacts:
2880 return(&btSoftBody::PSolve_RContacts);
2881 case ePSolver::SContacts:
2882 return(&btSoftBody::PSolve_SContacts);
2891 btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
2895 case eVSolver::Linear: return(&btSoftBody::VSolve_Links);