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, bool disableCollisionBetweenLinkedBodies)
311 if (disableCollisionBetweenLinkedBodies)
313 if (m_collisionDisabledObjects.findLinearSearch(body)==m_collisionDisabledObjects.size())
315 m_collisionDisabledObjects.push_back(body);
320 a.m_node = &m_nodes[node];
322 a.m_local = body->getInterpolationWorldTransform().inverse()*a.m_node->m_x;
323 a.m_node->m_battach = 1;
324 m_anchors.push_back(a);
328 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1)
330 LJoint* pj = new(btAlignedAlloc(sizeof(LJoint),16)) LJoint();
331 pj->m_bodies[0] = body0;
332 pj->m_bodies[1] = body1;
333 pj->m_refs[0] = pj->m_bodies[0].xform().inverse()*specs.position;
334 pj->m_refs[1] = pj->m_bodies[1].xform().inverse()*specs.position;
335 pj->m_cfm = specs.cfm;
336 pj->m_erp = specs.erp;
337 pj->m_split = specs.split;
338 m_joints.push_back(pj);
342 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body)
344 appendLinearJoint(specs,m_clusters[0],body);
348 void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body)
350 appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]);
354 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1)
356 AJoint* pj = new(btAlignedAlloc(sizeof(AJoint),16)) AJoint();
357 pj->m_bodies[0] = body0;
358 pj->m_bodies[1] = body1;
359 pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis()*specs.axis;
360 pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis()*specs.axis;
361 pj->m_cfm = specs.cfm;
362 pj->m_erp = specs.erp;
363 pj->m_split = specs.split;
364 pj->m_icontrol = specs.icontrol;
365 m_joints.push_back(pj);
369 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body)
371 appendAngularJoint(specs,m_clusters[0],body);
375 void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body)
377 appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]);
381 void btSoftBody::addForce(const btVector3& force)
383 for(int i=0,ni=m_nodes.size();i<ni;++i) addForce(force,i);
387 void btSoftBody::addForce(const btVector3& force,int node)
389 Node& n=m_nodes[node];
397 void btSoftBody::addVelocity(const btVector3& velocity)
399 for(int i=0,ni=m_nodes.size();i<ni;++i) addVelocity(velocity,i);
402 /* Set velocity for the entire body */
403 void btSoftBody::setVelocity( const btVector3& velocity)
405 for(int i=0,ni=m_nodes.size();i<ni;++i)
417 void btSoftBody::addVelocity(const btVector3& velocity,int node)
419 Node& n=m_nodes[node];
427 void btSoftBody::setMass(int node,btScalar mass)
429 m_nodes[node].m_im=mass>0?1/mass:0;
434 btScalar btSoftBody::getMass(int node) const
436 return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0);
440 btScalar btSoftBody::getTotalMass() const
443 for(int i=0;i<m_nodes.size();++i)
451 void btSoftBody::setTotalMass(btScalar mass,bool fromfaces)
458 for(i=0;i<m_nodes.size();++i)
462 for(i=0;i<m_faces.size();++i)
464 const Face& f=m_faces[i];
465 const btScalar twicearea=AreaOf( f.m_n[0]->m_x,
470 f.m_n[j]->m_im+=twicearea;
473 for( i=0;i<m_nodes.size();++i)
475 m_nodes[i].m_im=1/m_nodes[i].m_im;
478 const btScalar tm=getTotalMass();
479 const btScalar itm=1/tm;
480 for( i=0;i<m_nodes.size();++i)
482 m_nodes[i].m_im/=itm*mass;
488 void btSoftBody::setTotalDensity(btScalar density)
490 setTotalMass(getVolume()*density,true);
494 void btSoftBody::transform(const btTransform& trs)
496 const btScalar margin=getCollisionShape()->getMargin();
497 ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
499 for(int i=0,ni=m_nodes.size();i<ni;++i)
504 n.m_n=trs.getBasis()*n.m_n;
505 vol = btDbvtVolume::FromCR(n.m_x,margin);
507 m_ndbvt.update(n.m_leaf,vol);
512 m_initialWorldTransform = trs;
516 void btSoftBody::translate(const btVector3& trs)
525 void btSoftBody::rotate( const btQuaternion& rot)
534 void btSoftBody::scale(const btVector3& scl)
536 const btScalar margin=getCollisionShape()->getMargin();
537 ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
539 for(int i=0,ni=m_nodes.size();i<ni;++i)
544 vol = btDbvtVolume::FromCR(n.m_x,margin);
545 m_ndbvt.update(n.m_leaf,vol);
553 void btSoftBody::setPose(bool bvolume,bool bframe)
555 m_pose.m_bvolume = bvolume;
556 m_pose.m_bframe = bframe;
560 const btScalar omass=getTotalMass();
561 const btScalar kmass=omass*m_nodes.size()*1000;
562 btScalar tmass=omass;
563 m_pose.m_wgh.resize(m_nodes.size());
564 for(i=0,ni=m_nodes.size();i<ni;++i)
566 if(m_nodes[i].m_im<=0) tmass+=kmass;
568 for( i=0,ni=m_nodes.size();i<ni;++i)
571 m_pose.m_wgh[i]= n.m_im>0 ?
572 1/(m_nodes[i].m_im*tmass) :
576 const btVector3 com=evaluateCom();
577 m_pose.m_pos.resize(m_nodes.size());
578 for( i=0,ni=m_nodes.size();i<ni;++i)
580 m_pose.m_pos[i]=m_nodes[i].m_x-com;
582 m_pose.m_volume = bvolume?getVolume():0;
584 m_pose.m_rot.setIdentity();
585 m_pose.m_scl.setIdentity();
589 m_pose.m_aqq[2] = btVector3(0,0,0);
590 for( i=0,ni=m_nodes.size();i<ni;++i)
592 const btVector3& q=m_pose.m_pos[i];
593 const btVector3 mq=m_pose.m_wgh[i]*q;
594 m_pose.m_aqq[0]+=mq.x()*q;
595 m_pose.m_aqq[1]+=mq.y()*q;
596 m_pose.m_aqq[2]+=mq.z()*q;
598 m_pose.m_aqq=m_pose.m_aqq.inverse();
603 btScalar btSoftBody::getVolume() const
610 const btVector3 org=m_nodes[0].m_x;
611 for(i=0,ni=m_faces.size();i<ni;++i)
613 const Face& f=m_faces[i];
614 vol+=dot(f.m_n[0]->m_x-org,cross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org));
622 int btSoftBody::clusterCount() const
624 return(m_clusters.size());
628 btVector3 btSoftBody::clusterCom(const Cluster* cluster)
630 btVector3 com(0,0,0);
631 for(int i=0,ni=cluster->m_nodes.size();i<ni;++i)
633 com+=cluster->m_nodes[i]->m_x*cluster->m_masses[i];
635 return(com*cluster->m_imass);
639 btVector3 btSoftBody::clusterCom(int cluster) const
641 return(clusterCom(m_clusters[cluster]));
645 btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos)
647 return(cluster->m_lv+cross(cluster->m_av,rpos));
651 void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
653 const btVector3 li=cluster->m_imass*impulse;
654 const btVector3 ai=cluster->m_invwi*cross(rpos,impulse);
655 cluster->m_vimpulses[0]+=li;cluster->m_lv+=li;
656 cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
657 cluster->m_nvimpulses++;
661 void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
663 const btVector3 li=cluster->m_imass*impulse;
664 const btVector3 ai=cluster->m_invwi*cross(rpos,impulse);
665 cluster->m_dimpulses[0]+=li;
666 cluster->m_dimpulses[1]+=ai;
667 cluster->m_ndimpulses++;
671 void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse)
673 if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity);
674 if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift);
678 void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse)
680 const btVector3 ai=cluster->m_invwi*impulse;
681 cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
682 cluster->m_nvimpulses++;
686 void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse)
688 const btVector3 ai=cluster->m_invwi*impulse;
689 cluster->m_dimpulses[1]+=ai;
690 cluster->m_ndimpulses++;
694 void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse)
696 if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity);
697 if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift);
701 void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse)
703 cluster->m_dimpulses[0]+=impulse*cluster->m_imass;
704 cluster->m_ndimpulses++;
708 int btSoftBody::generateBendingConstraints(int distance,Material* mat)
715 const int n=m_nodes.size();
716 const unsigned inf=(~(unsigned)0)>>1;
717 unsigned* adj=new unsigned[n*n];
718 #define IDX(_x_,_y_) ((_y_)*n+(_x_))
723 if(i!=j) adj[IDX(i,j)]=adj[IDX(j,i)]=inf;
725 adj[IDX(i,j)]=adj[IDX(j,i)]=0;
728 for( i=0;i<m_links.size();++i)
730 const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
731 const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
741 const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
742 if(adj[IDX(i,j)]>sum)
744 adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
755 if(adj[IDX(i,j)]==(unsigned)distance)
758 m_links[m_links.size()-1].m_bbending=1;
770 void btSoftBody::randomizeConstraints()
772 unsigned long seed=243703;
773 #define NEXTRAND (seed=(1664525L*seed+1013904223L)&0xffffffff)
776 for(i=0,ni=m_links.size();i<ni;++i)
778 btSwap(m_links[i],m_links[NEXTRAND%ni]);
780 for(i=0,ni=m_faces.size();i<ni;++i)
782 btSwap(m_faces[i],m_faces[NEXTRAND%ni]);
788 void btSoftBody::releaseCluster(int index)
790 Cluster* c=m_clusters[index];
791 if(c->m_leaf) m_cdbvt.remove(c->m_leaf);
794 m_clusters.remove(c);
798 void btSoftBody::releaseClusters()
800 while(m_clusters.size()>0) releaseCluster(0);
804 int btSoftBody::generateClusters(int k,int maxiterations)
808 m_clusters.resize(btMin(k,m_nodes.size()));
809 for(i=0;i<m_clusters.size();++i)
811 m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
812 m_clusters[i]->m_collide= true;
818 btAlignedObjectArray<btVector3> centers;
819 btVector3 cog(0,0,0);
821 for(i=0;i<m_nodes.size();++i)
824 m_clusters[(i*29873)%m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
826 cog/=(btScalar)m_nodes.size();
827 centers.resize(k,cog);
829 const btScalar slope=16;
833 const btScalar w=2-btMin<btScalar>(1,iterations/slope);
841 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
843 c+=m_clusters[i]->m_nodes[j]->m_x;
845 if(m_clusters[i]->m_nodes.size())
847 c /= (btScalar)m_clusters[i]->m_nodes.size();
848 c = centers[i]+(c-centers[i])*w;
849 changed |= ((c-centers[i]).length2()>SIMD_EPSILON);
851 m_clusters[i]->m_nodes.resize(0);
854 for(i=0;i<m_nodes.size();++i)
856 const btVector3 nx=m_nodes[i].m_x;
858 btScalar kdist=ClusterMetric(centers[0],nx);
861 const btScalar d=ClusterMetric(centers[j],nx);
868 m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
870 } while(changed&&(iterations<maxiterations));
872 btAlignedObjectArray<int> cids;
873 cids.resize(m_nodes.size(),-1);
874 for(i=0;i<m_clusters.size();++i)
876 for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
878 cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i;
881 for(i=0;i<m_faces.size();++i)
883 const int idx[]={ int(m_faces[i].m_n[0]-&m_nodes[0]),
884 int(m_faces[i].m_n[1]-&m_nodes[0]),
885 int(m_faces[i].m_n[2]-&m_nodes[0])};
888 const int cid=cids[idx[j]];
891 const int kid=idx[(j+q)%3];
894 if(m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size())
896 m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
903 if(m_clusters.size()>1)
905 Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
906 pmaster->m_collide = false;
907 pmaster->m_nodes.reserve(m_nodes.size());
908 for(int i=0;i<m_nodes.size();++i) pmaster->m_nodes.push_back(&m_nodes[i]);
909 m_clusters.push_back(pmaster);
910 btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]);
913 for(i=0;i<m_clusters.size();++i)
915 if(m_clusters[i]->m_nodes.size()==0)
921 initializeClusters();
925 m_clusterConnectivity.resize(m_clusters.size()*m_clusters.size());
927 for (int c0=0;c0<m_clusters.size();c0++)
929 m_clusters[c0]->m_clusterIndex=c0;
930 for (int c1=0;c1<m_clusters.size();c1++)
933 bool connected=false;
934 Cluster* cla = m_clusters[c0];
935 Cluster* clb = m_clusters[c1];
936 for (int i=0;!connected&&i<cla->m_nodes.size();i++)
938 for (int j=0;j<clb->m_nodes.size();j++)
940 if (cla->m_nodes[i] == clb->m_nodes[j])
947 m_clusterConnectivity[c0+c1*m_clusters.size()]=connected;
952 return(m_clusters.size());
958 void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
960 const Node* nbase = &m_nodes[0];
961 int ncount = m_nodes.size();
962 btSymMatrix<int> edges(ncount,-2);
967 for(i=0;i<m_links.size();++i)
972 if(!SameSign(ifn->Eval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x)))
974 btSwap(m_links[i],m_links[m_links.size()-1]);
975 m_links.pop_back();--i;
980 for(i=0;i<m_links.size();++i)
983 edges(int(l.m_n[0]-nbase),int(l.m_n[1]-nbase))=-1;
985 for(i=0;i<m_faces.size();++i)
988 edges(int(f.m_n[0]-nbase),int(f.m_n[1]-nbase))=-1;
989 edges(int(f.m_n[1]-nbase),int(f.m_n[2]-nbase))=-1;
990 edges(int(f.m_n[2]-nbase),int(f.m_n[0]-nbase))=-1;
993 for(i=0;i<ncount;++i)
995 for(j=i+1;j<ncount;++j)
1001 const btScalar t=ImplicitSolve(ifn,a.m_x,b.m_x,accurary);
1004 const btVector3 x=Lerp(a.m_x,b.m_x,t);
1005 const btVector3 v=Lerp(a.m_v,b.m_v,t);
1011 const btScalar ma=1/a.m_im;
1012 const btScalar mb=1/b.m_im;
1013 const btScalar mc=Lerp(ma,mb,t);
1014 const btScalar f=(ma+mb)/(ma+mb+mc);
1020 { a.m_im/=0.5;m=1/a.m_im; }
1025 { b.m_im/=0.5;m=1/b.m_im; }
1030 edges(i,j)=m_nodes.size()-1;
1031 m_nodes[edges(i,j)].m_v=v;
1039 for(i=0,ni=m_links.size();i<ni;++i)
1041 Link& feat=m_links[i];
1042 const int idx[]={ int(feat.m_n[0]-nbase),
1043 int(feat.m_n[1]-nbase)};
1044 if((idx[0]<ncount)&&(idx[1]<ncount))
1046 const int ni=edges(idx[0],idx[1]);
1050 Link* pft[]={ &m_links[i],
1051 &m_links[m_links.size()-1]};
1052 pft[0]->m_n[0]=&m_nodes[idx[0]];
1053 pft[0]->m_n[1]=&m_nodes[ni];
1054 pft[1]->m_n[0]=&m_nodes[ni];
1055 pft[1]->m_n[1]=&m_nodes[idx[1]];
1060 for(i=0;i<m_faces.size();++i)
1062 const Face& feat=m_faces[i];
1063 const int idx[]={ int(feat.m_n[0]-nbase),
1064 int(feat.m_n[1]-nbase),
1065 int(feat.m_n[2]-nbase)};
1066 for(j=2,k=0;k<3;j=k++)
1068 if((idx[j]<ncount)&&(idx[k]<ncount))
1070 const int ni=edges(idx[j],idx[k]);
1074 const int l=(k+1)%3;
1075 Face* pft[]={ &m_faces[i],
1076 &m_faces[m_faces.size()-1]};
1077 pft[0]->m_n[0]=&m_nodes[idx[l]];
1078 pft[0]->m_n[1]=&m_nodes[idx[j]];
1079 pft[0]->m_n[2]=&m_nodes[ni];
1080 pft[1]->m_n[0]=&m_nodes[ni];
1081 pft[1]->m_n[1]=&m_nodes[idx[k]];
1082 pft[1]->m_n[2]=&m_nodes[idx[l]];
1083 appendLink(ni,idx[l],pft[0]->m_material);
1092 btAlignedObjectArray<int> cnodes;
1093 const int pcount=ncount;
1095 ncount=m_nodes.size();
1096 cnodes.resize(ncount,0);
1098 for(i=0;i<ncount;++i)
1100 const btVector3 x=m_nodes[i].m_x;
1101 if((i>=pcount)||(btFabs(ifn->Eval(x))<accurary))
1103 const btVector3 v=m_nodes[i].m_v;
1104 btScalar m=getMass(i);
1105 if(m>0) { m*=0.5;m_nodes[i].m_im/=0.5; }
1107 cnodes[i]=m_nodes.size()-1;
1108 m_nodes[cnodes[i]].m_v=v;
1113 for(i=0,ni=m_links.size();i<ni;++i)
1115 const int id[]={ int(m_links[i].m_n[0]-nbase),
1116 int(m_links[i].m_n[1]-nbase)};
1118 if(cnodes[id[0]]&&cnodes[id[1]])
1121 todetach=m_links.size()-1;
1125 if(( (ifn->Eval(m_nodes[id[0]].m_x)<accurary)&&
1126 (ifn->Eval(m_nodes[id[1]].m_x)<accurary)))
1131 Link& l=m_links[todetach];
1132 for(int j=0;j<2;++j)
1134 int cn=cnodes[int(l.m_n[j]-nbase)];
1135 if(cn) l.m_n[j]=&m_nodes[cn];
1140 for(i=0,ni=m_faces.size();i<ni;++i)
1142 Node** n= m_faces[i].m_n;
1143 if( (ifn->Eval(n[0]->m_x)<accurary)&&
1144 (ifn->Eval(n[1]->m_x)<accurary)&&
1145 (ifn->Eval(n[2]->m_x)<accurary))
1147 for(int j=0;j<3;++j)
1149 int cn=cnodes[int(n[j]-nbase)];
1150 if(cn) n[j]=&m_nodes[cn];
1155 int nnodes=m_nodes.size();
1156 btAlignedObjectArray<int> ranks;
1157 btAlignedObjectArray<int> todelete;
1158 ranks.resize(nnodes,0);
1159 for(i=0,ni=m_links.size();i<ni;++i)
1161 for(int j=0;j<2;++j) ranks[int(m_links[i].m_n[j]-nbase)]++;
1163 for(i=0,ni=m_faces.size();i<ni;++i)
1165 for(int j=0;j<3;++j) ranks[int(m_faces[i].m_n[j]-nbase)]++;
1167 for(i=0;i<m_links.size();++i)
1169 const int id[]={ int(m_links[i].m_n[0]-nbase),
1170 int(m_links[i].m_n[1]-nbase)};
1171 const bool sg[]={ ranks[id[0]]==1,
1177 btSwap(m_links[i],m_links[m_links.size()-1]);
1178 m_links.pop_back();--i;
1182 for(i=nnodes-1;i>=0;--i)
1184 if(!ranks[i]) todelete.push_back(i);
1188 btAlignedObjectArray<int>& map=ranks;
1189 for(int i=0;i<nnodes;++i) map[i]=i;
1190 PointersToIndices(this);
1191 for(int i=0,ni=todelete.size();i<ni;++i)
1195 int& b=map[--nnodes];
1196 m_ndbvt.remove(m_nodes[a].m_leaf);m_nodes[a].m_leaf=0;
1197 btSwap(m_nodes[a],m_nodes[b]);
1200 IndicesToPointers(this,&map[0]);
1201 m_nodes.resize(nnodes);
1205 m_bUpdateRtCst=true;
1209 bool btSoftBody::cutLink(const Node* node0,const Node* node1,btScalar position)
1211 return(cutLink(int(node0-&m_nodes[0]),int(node1-&m_nodes[0]),position));
1215 bool btSoftBody::cutLink(int node0,int node1,btScalar position)
1219 const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
1220 const btVector3 x=Lerp(m_nodes[node0].m_x,m_nodes[node1].m_x,position);
1221 const btVector3 v=Lerp(m_nodes[node0].m_v,m_nodes[node1].m_v,position);
1225 Node* pa=&m_nodes[node0];
1226 Node* pb=&m_nodes[node1];
1227 Node* pn[2]={ &m_nodes[m_nodes.size()-2],
1228 &m_nodes[m_nodes.size()-1]};
1231 for(i=0,ni=m_links.size();i<ni;++i)
1233 const int mtch=MatchEdge(m_links[i].m_n[0],m_links[i].m_n[1],pa,pb);
1237 Link* pft[]={&m_links[i],&m_links[m_links.size()-1]};
1238 pft[0]->m_n[1]=pn[mtch];
1239 pft[1]->m_n[0]=pn[1-mtch];
1243 for(i=0,ni=m_faces.size();i<ni;++i)
1245 for(int k=2,l=0;l<3;k=l++)
1247 const int mtch=MatchEdge(m_faces[i].m_n[k],m_faces[i].m_n[l],pa,pb);
1251 Face* pft[]={&m_faces[i],&m_faces[m_faces.size()-1]};
1252 pft[0]->m_n[l]=pn[mtch];
1253 pft[1]->m_n[k]=pn[1-mtch];
1254 appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1255 appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
1261 m_ndbvt.remove(pn[0]->m_leaf);
1262 m_ndbvt.remove(pn[1]->m_leaf);
1270 bool btSoftBody::rayTest(const btVector3& rayFrom,
1271 const btVector3& rayTo,
1274 if(m_faces.size()&&m_fdbvt.empty())
1275 initializeFaceTree();
1277 results.body = this;
1278 results.fraction = 1.f;
1279 results.feature = eFeature::None;
1282 return(rayTest(rayFrom,rayTo,results.fraction,results.feature,results.index,false)!=0);
1286 void btSoftBody::setSolver(eSolverPresets::_ preset)
1288 m_cfg.m_vsequence.clear();
1289 m_cfg.m_psequence.clear();
1290 m_cfg.m_dsequence.clear();
1293 case eSolverPresets::Positions:
1294 m_cfg.m_psequence.push_back(ePSolver::Anchors);
1295 m_cfg.m_psequence.push_back(ePSolver::RContacts);
1296 m_cfg.m_psequence.push_back(ePSolver::SContacts);
1297 m_cfg.m_psequence.push_back(ePSolver::Linear);
1299 case eSolverPresets::Velocities:
1300 m_cfg.m_vsequence.push_back(eVSolver::Linear);
1302 m_cfg.m_psequence.push_back(ePSolver::Anchors);
1303 m_cfg.m_psequence.push_back(ePSolver::RContacts);
1304 m_cfg.m_psequence.push_back(ePSolver::SContacts);
1306 m_cfg.m_dsequence.push_back(ePSolver::Linear);
1312 void btSoftBody::predictMotion(btScalar dt)
1319 m_bUpdateRtCst=false;
1322 if(m_cfg.collisions&fCollision::VF_SS)
1324 initializeFaceTree();
1329 m_sst.sdt = dt*m_cfg.timescale;
1330 m_sst.isdt = 1/m_sst.sdt;
1331 m_sst.velmrg = m_sst.sdt*3;
1332 m_sst.radmrg = getCollisionShape()->getMargin();
1333 m_sst.updmrg = m_sst.radmrg*(btScalar)0.25;
1335 addVelocity(m_worldInfo->m_gravity*m_sst.sdt);
1338 for(i=0,ni=m_nodes.size();i<ni;++i)
1342 n.m_v += n.m_f*n.m_im*m_sst.sdt;
1343 n.m_x += n.m_v*m_sst.sdt;
1344 n.m_f = btVector3(0,0,0);
1351 ATTRIBUTE_ALIGNED16(btDbvtVolume) vol;
1352 for(i=0,ni=m_nodes.size();i<ni;++i)
1355 vol = btDbvtVolume::FromCR(n.m_x,m_sst.radmrg);
1356 m_ndbvt.update( n.m_leaf,
1362 if(!m_fdbvt.empty())
1364 for(int i=0;i<m_faces.size();++i)
1367 const btVector3 v=( f.m_n[0]->m_v+
1370 vol = VolumeOf(f,m_sst.radmrg);
1371 m_fdbvt.update( f.m_leaf,
1380 if(m_pose.m_bframe&&(m_cfg.kMT>0))
1382 const btMatrix3x3 posetrs=m_pose.m_rot;
1383 for(int i=0,ni=m_nodes.size();i<ni;++i)
1388 const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com;
1389 n.m_x=Lerp(n.m_x,x,m_cfg.kMT);
1393 /* Clear contacts */
1394 m_rcontacts.resize(0);
1395 m_scontacts.resize(0);
1396 /* Optimize dbvt's */
1397 m_ndbvt.optimizeIncremental(1);
1398 m_fdbvt.optimizeIncremental(1);
1399 m_cdbvt.optimizeIncremental(1);
1403 void btSoftBody::solveConstraints()
1405 /* Apply clusters */
1406 applyClusters(false);
1411 for(i=0,ni=m_links.size();i<ni;++i)
1414 l.m_c3 = l.m_n[1]->m_q-l.m_n[0]->m_q;
1415 l.m_c2 = 1/(l.m_c3.length2()*l.m_c0);
1417 /* Prepare anchors */
1418 for(i=0,ni=m_anchors.size();i<ni;++i)
1420 Anchor& a=m_anchors[i];
1421 const btVector3 ra=a.m_body->getWorldTransform().getBasis()*a.m_local;
1422 a.m_c0 = ImpulseMatrix( m_sst.sdt,
1424 a.m_body->getInvMass(),
1425 a.m_body->getInvInertiaTensorWorld(),
1428 a.m_c2 = m_sst.sdt*a.m_node->m_im;
1429 a.m_body->activate();
1431 /* Solve velocities */
1432 if(m_cfg.viterations>0)
1435 for(int isolve=0;isolve<m_cfg.viterations;++isolve)
1437 for(int iseq=0;iseq<m_cfg.m_vsequence.size();++iseq)
1439 getSolver(m_cfg.m_vsequence[iseq])(this,1);
1443 for(i=0,ni=m_nodes.size();i<ni;++i)
1446 n.m_x = n.m_q+n.m_v*m_sst.sdt;
1449 /* Solve positions */
1450 if(m_cfg.piterations>0)
1452 for(int isolve=0;isolve<m_cfg.piterations;++isolve)
1454 const btScalar ti=isolve/(btScalar)m_cfg.piterations;
1455 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1457 getSolver(m_cfg.m_psequence[iseq])(this,1,ti);
1460 const btScalar vc=m_sst.isdt*(1-m_cfg.kDP);
1461 for(i=0,ni=m_nodes.size();i<ni;++i)
1464 n.m_v = (n.m_x-n.m_q)*vc;
1465 n.m_f = btVector3(0,0,0);
1469 if(m_cfg.diterations>0)
1471 const btScalar vcf=m_cfg.kVCF*m_sst.isdt;
1472 for(i=0,ni=m_nodes.size();i<ni;++i)
1477 for(int idrift=0;idrift<m_cfg.diterations;++idrift)
1479 for(int iseq=0;iseq<m_cfg.m_dsequence.size();++iseq)
1481 getSolver(m_cfg.m_dsequence[iseq])(this,1,0);
1484 for(int i=0,ni=m_nodes.size();i<ni;++i)
1487 n.m_v += (n.m_x-n.m_q)*vcf;
1490 /* Apply clusters */
1492 applyClusters(true);
1496 void btSoftBody::staticSolve(int iterations)
1498 for(int isolve=0;isolve<iterations;++isolve)
1500 for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
1502 getSolver(m_cfg.m_psequence[iseq])(this,1,0);
1508 void btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/,int /*count*/,int /*iterations*/)
1514 void btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
1516 const int nb=bodies.size();
1522 iterations=btMax(iterations,bodies[i]->m_cfg.citerations);
1526 bodies[i]->prepareClusters(iterations);
1528 for(i=0;i<iterations;++i)
1530 const btScalar sor=1;
1531 for(int j=0;j<nb;++j)
1533 bodies[j]->solveClusters(sor);
1538 bodies[i]->cleanupClusters();
1543 void btSoftBody::integrateMotion()
1550 btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom,const btVector3& rayTo,btScalar mxt)
1552 m_rayFrom = rayFrom;
1553 m_rayNormalizedDirection = (rayTo-rayFrom);
1561 void btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf)
1563 btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data;
1564 const btScalar t=rayFromToTriangle( m_rayFrom,m_rayTo,m_rayNormalizedDirection,
1569 if((t>0)&&(t<m_mint))
1577 btScalar btSoftBody::RayFromToCaster::rayFromToTriangle( const btVector3& rayFrom,
1578 const btVector3& rayTo,
1579 const btVector3& rayNormalizedDirection,
1585 static const btScalar ceps=-SIMD_EPSILON*10;
1586 static const btScalar teps=SIMD_EPSILON*10;
1588 const btVector3 n=cross(b-a,c-a);
1589 const btScalar d=dot(a,n);
1590 const btScalar den=dot(rayNormalizedDirection,n);
1591 if(!btFuzzyZero(den))
1593 const btScalar num=dot(rayFrom,n)-d;
1594 const btScalar t=-num/den;
1595 if((t>teps)&&(t<maxt))
1597 const btVector3 hit=rayFrom+rayNormalizedDirection*t;
1598 if( (dot(n,cross(a-hit,b-hit))>ceps) &&
1599 (dot(n,cross(b-hit,c-hit))>ceps) &&
1600 (dot(n,cross(c-hit,a-hit))>ceps))
1610 void btSoftBody::pointersToIndices()
1612 #define PTR2IDX(_p_,_b_) reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_))
1613 btSoftBody::Node* base=&m_nodes[0];
1616 for(i=0,ni=m_nodes.size();i<ni;++i)
1618 if(m_nodes[i].m_leaf)
1620 m_nodes[i].m_leaf->data=*(void**)&i;
1623 for(i=0,ni=m_links.size();i<ni;++i)
1625 m_links[i].m_n[0]=PTR2IDX(m_links[i].m_n[0],base);
1626 m_links[i].m_n[1]=PTR2IDX(m_links[i].m_n[1],base);
1628 for(i=0,ni=m_faces.size();i<ni;++i)
1630 m_faces[i].m_n[0]=PTR2IDX(m_faces[i].m_n[0],base);
1631 m_faces[i].m_n[1]=PTR2IDX(m_faces[i].m_n[1],base);
1632 m_faces[i].m_n[2]=PTR2IDX(m_faces[i].m_n[2],base);
1633 if(m_faces[i].m_leaf)
1635 m_faces[i].m_leaf->data=*(void**)&i;
1638 for(i=0,ni=m_anchors.size();i<ni;++i)
1640 m_anchors[i].m_node=PTR2IDX(m_anchors[i].m_node,base);
1642 for(i=0,ni=m_notes.size();i<ni;++i)
1644 for(int j=0;j<m_notes[i].m_rank;++j)
1646 m_notes[i].m_nodes[j]=PTR2IDX(m_notes[i].m_nodes[j],base);
1653 void btSoftBody::indicesToPointers(const int* map)
1655 #define IDX2PTR(_p_,_b_) map?(&(_b_)[map[(((char*)_p_)-(char*)0)]]): \
1656 (&(_b_)[(((char*)_p_)-(char*)0)])
1657 btSoftBody::Node* base=&m_nodes[0];
1660 for(i=0,ni=m_nodes.size();i<ni;++i)
1662 if(m_nodes[i].m_leaf)
1664 m_nodes[i].m_leaf->data=&m_nodes[i];
1667 for(i=0,ni=m_links.size();i<ni;++i)
1669 m_links[i].m_n[0]=IDX2PTR(m_links[i].m_n[0],base);
1670 m_links[i].m_n[1]=IDX2PTR(m_links[i].m_n[1],base);
1672 for(i=0,ni=m_faces.size();i<ni;++i)
1674 m_faces[i].m_n[0]=IDX2PTR(m_faces[i].m_n[0],base);
1675 m_faces[i].m_n[1]=IDX2PTR(m_faces[i].m_n[1],base);
1676 m_faces[i].m_n[2]=IDX2PTR(m_faces[i].m_n[2],base);
1677 if(m_faces[i].m_leaf)
1679 m_faces[i].m_leaf->data=&m_faces[i];
1682 for(i=0,ni=m_anchors.size();i<ni;++i)
1684 m_anchors[i].m_node=IDX2PTR(m_anchors[i].m_node,base);
1686 for(i=0,ni=m_notes.size();i<ni;++i)
1688 for(int j=0;j<m_notes[i].m_rank;++j)
1690 m_notes[i].m_nodes[j]=IDX2PTR(m_notes[i].m_nodes[j],base);
1697 int btSoftBody::rayTest(const btVector3& rayFrom,const btVector3& rayTo,
1698 btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const
1701 if(bcountonly||m_fdbvt.empty())
1703 btVector3 dir = rayTo-rayFrom;
1706 for(int i=0,ni=m_faces.size();i<ni;++i)
1708 const btSoftBody::Face& f=m_faces[i];
1710 const btScalar t=RayFromToCaster::rayFromToTriangle( rayFrom,rayTo,dir,
1720 feature=btSoftBody::eFeature::Face;
1729 RayFromToCaster collider(rayFrom,rayTo,mint);
1731 btDbvt::rayTest(m_fdbvt.m_root,rayFrom,rayTo,collider);
1734 mint=collider.m_mint;
1735 feature=btSoftBody::eFeature::Face;
1736 index=(int)(collider.m_face-&m_faces[0]);
1744 void btSoftBody::initializeFaceTree()
1747 for(int i=0;i<m_faces.size();++i)
1750 f.m_leaf=m_fdbvt.insert(VolumeOf(f,0),&f);
1755 btVector3 btSoftBody::evaluateCom() const
1757 btVector3 com(0,0,0);
1760 for(int i=0,ni=m_nodes.size();i<ni;++i)
1762 com+=m_nodes[i].m_x*m_pose.m_wgh[i];
1769 bool btSoftBody::checkContact( btCollisionObject* colObj,
1772 btSoftBody::sCti& cti) const
1775 btCollisionShape* shp=colObj->getCollisionShape();
1776 btRigidBody* tmpRigid = btRigidBody::upcast(colObj);
1777 const btTransform& wtr=tmpRigid? tmpRigid->getInterpolationWorldTransform() : colObj->getWorldTransform();
1778 btScalar dst=m_worldInfo->m_sparsesdf.Evaluate( wtr.invXform(x),
1784 cti.m_colObj = colObj;
1785 cti.m_normal = wtr.getBasis()*nrm;
1786 cti.m_offset = -dot( cti.m_normal,
1787 x-cti.m_normal*dst);
1794 void btSoftBody::updateNormals()
1796 const btVector3 zv(0,0,0);
1799 for(i=0,ni=m_nodes.size();i<ni;++i)
1803 for(i=0,ni=m_faces.size();i<ni;++i)
1805 btSoftBody::Face& f=m_faces[i];
1806 const btVector3 n=cross(f.m_n[1]->m_x-f.m_n[0]->m_x,
1807 f.m_n[2]->m_x-f.m_n[0]->m_x);
1808 f.m_normal=n.normalized();
1813 for(i=0,ni=m_nodes.size();i<ni;++i)
1815 btScalar len = m_nodes[i].m_n.length();
1816 if (len>SIMD_EPSILON)
1817 m_nodes[i].m_n /= len;
1822 void btSoftBody::updateBounds()
1826 const btVector3& mins=m_ndbvt.m_root->volume.Mins();
1827 const btVector3& maxs=m_ndbvt.m_root->volume.Maxs();
1828 const btScalar csm=getCollisionShape()->getMargin();
1829 const btVector3 mrg=btVector3( csm,
1831 csm)*1; // ??? to investigate...
1832 m_bounds[0]=mins-mrg;
1833 m_bounds[1]=maxs+mrg;
1834 if(0!=getBroadphaseHandle())
1836 m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(),
1839 m_worldInfo->m_dispatcher);
1845 m_bounds[1]=btVector3(0,0,0);
1851 void btSoftBody::updatePose()
1855 btSoftBody::Pose& pose=m_pose;
1856 const btVector3 com=evaluateCom();
1861 const btScalar eps=SIMD_EPSILON;
1862 Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0);
1863 Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3);
1864 for(int i=0,ni=m_nodes.size();i<ni;++i)
1866 const btVector3 a=pose.m_wgh[i]*(m_nodes[i].m_x-com);
1867 const btVector3& b=pose.m_pos[i];
1873 PolarDecompose(Apq,r,s);
1875 pose.m_scl=pose.m_aqq*r.transpose()*Apq;
1876 if(m_cfg.maxvolume>1)
1878 const btScalar idet=Clamp<btScalar>( 1/pose.m_scl.determinant(),
1880 pose.m_scl=Mul(pose.m_scl,idet);
1887 void btSoftBody::updateConstants()
1892 for(i=0,ni=m_links.size();i<ni;++i)
1895 Material& m=*l.m_material;
1896 l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
1897 l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST;
1898 l.m_c1 = l.m_rl*l.m_rl;
1901 for(i=0,ni=m_faces.size();i<ni;++i)
1904 f.m_ra = AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
1907 btAlignedObjectArray<int> counts;
1908 counts.resize(m_nodes.size(),0);
1909 for(i=0,ni=m_nodes.size();i<ni;++i)
1911 m_nodes[i].m_area = 0;
1913 for(i=0,ni=m_faces.size();i<ni;++i)
1915 btSoftBody::Face& f=m_faces[i];
1916 for(int j=0;j<3;++j)
1918 const int index=(int)(f.m_n[j]-&m_nodes[0]);
1920 f.m_n[j]->m_area+=btFabs(f.m_ra);
1923 for(i=0,ni=m_nodes.size();i<ni;++i)
1926 m_nodes[i].m_area/=(btScalar)counts[i];
1928 m_nodes[i].m_area=0;
1933 void btSoftBody::initializeClusters()
1937 for( i=0;i<m_clusters.size();++i)
1939 Cluster& c=*m_clusters[i];
1941 c.m_masses.resize(c.m_nodes.size());
1942 for(int j=0;j<c.m_nodes.size();++j)
1944 c.m_masses[j] = c.m_nodes[j]->m_im>0?1/c.m_nodes[j]->m_im:0;
1945 c.m_imass += c.m_masses[j];
1947 c.m_imass = 1/c.m_imass;
1948 c.m_com = btSoftBody::clusterCom(&c);
1949 c.m_lv = btVector3(0,0,0);
1950 c.m_av = btVector3(0,0,0);
1953 btMatrix3x3& ii=c.m_locii;
1954 ii[0]=ii[1]=ii[2]=btVector3(0,0,0);
1958 for(i=0,ni=c.m_nodes.size();i<ni;++i)
1960 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
1961 const btVector3 q=k*k;
1962 const btScalar m=c.m_masses[i];
1963 ii[0][0] += m*(q[1]+q[2]);
1964 ii[1][1] += m*(q[0]+q[2]);
1965 ii[2][2] += m*(q[0]+q[1]);
1966 ii[0][1] -= m*k[0]*k[1];
1967 ii[0][2] -= m*k[0]*k[2];
1968 ii[1][2] -= m*k[1]*k[2];
1976 c.m_framexform.setIdentity();
1977 c.m_framexform.setOrigin(c.m_com);
1978 c.m_framerefs.resize(c.m_nodes.size());
1981 for(i=0;i<c.m_framerefs.size();++i)
1983 c.m_framerefs[i]=c.m_nodes[i]->m_x-c.m_com;
1990 void btSoftBody::updateClusters()
1992 BT_PROFILE("UpdateClusters");
1995 for(i=0;i<m_clusters.size();++i)
1997 btSoftBody::Cluster& c=*m_clusters[i];
1998 const int n=c.m_nodes.size();
1999 const btScalar invn=1/(btScalar)n;
2003 const btScalar eps=btScalar(0.0001);
2005 m[0]=m[1]=m[2]=btVector3(0,0,0);
2009 c.m_com=clusterCom(&c);
2010 for(int i=0;i<c.m_nodes.size();++i)
2012 const btVector3 a=c.m_nodes[i]->m_x-c.m_com;
2013 const btVector3& b=c.m_framerefs[i];
2014 m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b;
2016 PolarDecompose(m,r,s);
2017 c.m_framexform.setOrigin(c.m_com);
2018 c.m_framexform.setBasis(r);
2021 c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose();
2024 const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass);
2025 const btVector3 inertia(rk,rk,rk);
2026 const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
2027 btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0,
2028 btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
2030 c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
2032 c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0);
2033 for(int i=0;i<n;++i)
2035 const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
2036 const btVector3 q=k*k;
2037 const btScalar m=1/c.m_nodes[i]->m_im;
2038 c.m_invwi[0][0] += m*(q[1]+q[2]);
2039 c.m_invwi[1][1] += m*(q[0]+q[2]);
2040 c.m_invwi[2][2] += m*(q[0]+q[1]);
2041 c.m_invwi[0][1] -= m*k[0]*k[1];
2042 c.m_invwi[0][2] -= m*k[0]*k[2];
2043 c.m_invwi[1][2] -= m*k[1]*k[2];
2045 c.m_invwi[1][0]=c.m_invwi[0][1];
2046 c.m_invwi[2][0]=c.m_invwi[0][2];
2047 c.m_invwi[2][1]=c.m_invwi[1][2];
2048 c.m_invwi=c.m_invwi.inverse();
2052 c.m_lv=btVector3(0,0,0);
2053 c.m_av=btVector3(0,0,0);
2059 const btVector3 v=c.m_nodes[i]->m_v*c.m_masses[i];
2061 c.m_av += cross(c.m_nodes[i]->m_x-c.m_com,v);
2064 c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping);
2065 c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping);
2067 c.m_vimpulses[1] = btVector3(0,0,0);
2069 c.m_dimpulses[1] = btVector3(0,0,0);
2075 for(int j=0;j<c.m_nodes.size();++j)
2077 Node& n=*c.m_nodes[j];
2078 const btVector3 x=c.m_framexform*c.m_framerefs[j];
2079 n.m_x=Lerp(n.m_x,x,c.m_matching);
2085 btVector3 mi=c.m_nodes[0]->m_x;
2087 for(int j=1;j<n;++j)
2089 mi.setMin(c.m_nodes[j]->m_x);
2090 mx.setMax(c.m_nodes[j]->m_x);
2092 ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx);
2094 m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg);
2096 c.m_leaf=m_cdbvt.insert(bounds,&c);
2108 void btSoftBody::cleanupClusters()
2110 for(int i=0;i<m_joints.size();++i)
2112 m_joints[i]->Terminate(m_sst.sdt);
2113 if(m_joints[i]->m_delete)
2115 btAlignedFree(m_joints[i]);
2116 m_joints.remove(m_joints[i--]);
2122 void btSoftBody::prepareClusters(int iterations)
2124 for(int i=0;i<m_joints.size();++i)
2126 m_joints[i]->Prepare(m_sst.sdt,iterations);
2132 void btSoftBody::solveClusters(btScalar sor)
2134 for(int i=0,ni=m_joints.size();i<ni;++i)
2136 m_joints[i]->Solve(m_sst.sdt,sor);
2141 void btSoftBody::applyClusters(bool drift)
2143 BT_PROFILE("ApplyClusters");
2144 const btScalar f0=m_sst.sdt;
2145 const btScalar f1=f0/2;
2146 btAlignedObjectArray<btVector3> deltas;
2147 btAlignedObjectArray<btScalar> weights;
2148 deltas.resize(m_nodes.size(),btVector3(0,0,0));
2149 weights.resize(m_nodes.size(),0);
2154 for(i=0;i<m_clusters.size();++i)
2156 Cluster& c=*m_clusters[i];
2159 c.m_dimpulses[0]/=(btScalar)c.m_ndimpulses;
2160 c.m_dimpulses[1]/=(btScalar)c.m_ndimpulses;
2165 for(i=0;i<m_clusters.size();++i)
2167 Cluster& c=*m_clusters[i];
2168 if(0<(drift?c.m_ndimpulses:c.m_nvimpulses))
2170 const btVector3 v=(drift?c.m_dimpulses[0]:c.m_vimpulses[0])*m_sst.sdt;
2171 const btVector3 w=(drift?c.m_dimpulses[1]:c.m_vimpulses[1])*m_sst.sdt;
2172 for(int j=0;j<c.m_nodes.size();++j)
2174 const int idx=int(c.m_nodes[j]-&m_nodes[0]);
2175 const btVector3& x=c.m_nodes[j]->m_x;
2176 const btScalar q=c.m_masses[j];
2177 deltas[idx] += (v+cross(w,x-c.m_com))*q;
2182 for(i=0;i<deltas.size();++i)
2184 if(weights[i]>0) m_nodes[i].m_x+=deltas[i]/weights[i];
2189 void btSoftBody::dampClusters()
2193 for(i=0;i<m_clusters.size();++i)
2195 Cluster& c=*m_clusters[i];
2198 for(int j=0;j<c.m_nodes.size();++j)
2200 Node& n=*c.m_nodes[j];
2203 const btVector3 vx=c.m_lv+cross(c.m_av,c.m_nodes[j]->m_q-c.m_com);
2204 if(vx.length2()<=n.m_v.length2())
2206 n.m_v += c.m_ndamping*(vx-n.m_v);
2215 void btSoftBody::Joint::Prepare(btScalar dt,int)
2217 m_bodies[0].activate();
2218 m_bodies[1].activate();
2222 void btSoftBody::LJoint::Prepare(btScalar dt,int iterations)
2224 static const btScalar maxdrift=4;
2225 Joint::Prepare(dt,iterations);
2226 m_rpos[0] = m_bodies[0].xform()*m_refs[0];
2227 m_rpos[1] = m_bodies[1].xform()*m_refs[1];
2228 m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt;
2229 m_rpos[0] -= m_bodies[0].xform().getOrigin();
2230 m_rpos[1] -= m_bodies[1].xform().getOrigin();
2231 m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0],
2232 m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]);
2235 m_sdrift = m_massmatrix*(m_drift*m_split);
2236 m_drift *= 1-m_split;
2238 m_drift /=(btScalar)iterations;
2242 void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor)
2244 const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
2245 const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
2246 const btVector3 vr=va-vb;
2247 btSoftBody::Impulse impulse;
2248 impulse.m_asVelocity = 1;
2249 impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor;
2250 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2251 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2255 void btSoftBody::LJoint::Terminate(btScalar dt)
2259 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2260 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2265 void btSoftBody::AJoint::Prepare(btScalar dt,int iterations)
2267 static const btScalar maxdrift=SIMD_PI/16;
2268 m_icontrol->Prepare(this);
2269 Joint::Prepare(dt,iterations);
2270 m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0];
2271 m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1];
2272 m_drift = NormalizeAny(cross(m_axis[1],m_axis[0]));
2273 m_drift *= btMin(maxdrift,btAcos(Clamp<btScalar>(dot(m_axis[0],m_axis[1]),-1,+1)));
2274 m_drift *= m_erp/dt;
2275 m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia());
2278 m_sdrift = m_massmatrix*(m_drift*m_split);
2279 m_drift *= 1-m_split;
2281 m_drift /=(btScalar)iterations;
2285 void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor)
2287 const btVector3 va=m_bodies[0].angularVelocity();
2288 const btVector3 vb=m_bodies[1].angularVelocity();
2289 const btVector3 vr=va-vb;
2290 const btScalar sp=dot(vr,m_axis[0]);
2291 const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp);
2292 btSoftBody::Impulse impulse;
2293 impulse.m_asVelocity = 1;
2294 impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor;
2295 m_bodies[0].applyAImpulse(-impulse);
2296 m_bodies[1].applyAImpulse( impulse);
2300 void btSoftBody::AJoint::Terminate(btScalar dt)
2304 m_bodies[0].applyDAImpulse(-m_sdrift);
2305 m_bodies[1].applyDAImpulse( m_sdrift);
2310 void btSoftBody::CJoint::Prepare(btScalar dt,int iterations)
2312 Joint::Prepare(dt,iterations);
2313 const bool dodrift=(m_life==0);
2314 m_delete=(++m_life)>m_maxlife;
2317 m_drift=m_drift*m_erp/dt;
2320 m_sdrift = m_massmatrix*(m_drift*m_split);
2321 m_drift *= 1-m_split;
2323 m_drift/=(btScalar)iterations;
2327 m_drift=m_sdrift=btVector3(0,0,0);
2332 void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor)
2334 const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
2335 const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
2336 const btVector3 vrel=va-vb;
2337 const btScalar rvac=dot(vrel,m_normal);
2338 btSoftBody::Impulse impulse;
2339 impulse.m_asVelocity = 1;
2340 impulse.m_velocity = m_drift;
2343 const btVector3 iv=m_normal*rvac;
2344 const btVector3 fv=vrel-iv;
2345 impulse.m_velocity += iv+fv*m_friction;
2347 impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor;
2348 m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
2349 m_bodies[1].applyImpulse( impulse,m_rpos[1]);
2353 void btSoftBody::CJoint::Terminate(btScalar dt)
2357 m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
2358 m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
2363 void btSoftBody::applyForces()
2366 BT_PROFILE("SoftBody applyForces");
2367 const btScalar dt=m_sst.sdt;
2368 const btScalar kLF=m_cfg.kLF;
2369 const btScalar kDG=m_cfg.kDG;
2370 const btScalar kPR=m_cfg.kPR;
2371 const btScalar kVC=m_cfg.kVC;
2372 const bool as_lift=kLF>0;
2373 const bool as_drag=kDG>0;
2374 const bool as_pressure=kPR!=0;
2375 const bool as_volume=kVC>0;
2376 const bool as_aero= as_lift ||
2378 const bool as_vaero= as_aero &&
2379 (m_cfg.aeromodel<btSoftBody::eAeroModel::F_TwoSided);
2380 const bool as_faero= as_aero &&
2381 (m_cfg.aeromodel>=btSoftBody::eAeroModel::F_TwoSided);
2382 const bool use_medium= as_aero;
2383 const bool use_volume= as_pressure ||
2386 btScalar ivolumetp=0;
2387 btScalar dvolumetv=0;
2388 btSoftBody::sMedium medium;
2391 volume = getVolume();
2392 ivolumetp = 1/btFabs(volume)*kPR;
2393 dvolumetv = (m_pose.m_volume-volume)*kVC;
2395 /* Per vertex forces */
2398 for(i=0,ni=m_nodes.size();i<ni;++i)
2400 btSoftBody::Node& n=m_nodes[i];
2405 EvaluateMedium(m_worldInfo,n.m_x,medium);
2409 const btVector3 rel_v=n.m_v-medium.m_velocity;
2410 const btScalar rel_v2=rel_v.length2();
2411 if(rel_v2>SIMD_EPSILON)
2413 btVector3 nrm=n.m_n;
2415 switch(m_cfg.aeromodel)
2417 case btSoftBody::eAeroModel::V_Point:
2418 nrm=NormalizeAny(rel_v);break;
2419 case btSoftBody::eAeroModel::V_TwoSided:
2420 nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break;
2422 const btScalar dvn=dot(rel_v,nrm);
2423 /* Compute forces */
2426 btVector3 force(0,0,0);
2427 const btScalar c0 = n.m_area*dvn*rel_v2/2;
2428 const btScalar c1 = c0*medium.m_density;
2429 force += nrm*(-c1*kLF);
2430 force += rel_v.normalized()*(-c1*kDG);
2431 ApplyClampedForce(n,force,dt);
2439 n.m_f += n.m_n*(n.m_area*ivolumetp);
2444 n.m_f += n.m_n*(n.m_area*dvolumetv);
2448 /* Per face forces */
2449 for(i=0,ni=m_faces.size();i<ni;++i)
2451 btSoftBody::Face& f=m_faces[i];
2454 const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3;
2455 const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3;
2456 EvaluateMedium(m_worldInfo,x,medium);
2457 const btVector3 rel_v=v-medium.m_velocity;
2458 const btScalar rel_v2=rel_v.length2();
2459 if(rel_v2>SIMD_EPSILON)
2461 btVector3 nrm=f.m_normal;
2463 switch(m_cfg.aeromodel)
2465 case btSoftBody::eAeroModel::F_TwoSided:
2466 nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break;
2468 const btScalar dvn=dot(rel_v,nrm);
2469 /* Compute forces */
2472 btVector3 force(0,0,0);
2473 const btScalar c0 = f.m_ra*dvn*rel_v2;
2474 const btScalar c1 = c0*medium.m_density;
2475 force += nrm*(-c1*kLF);
2476 force += rel_v.normalized()*(-c1*kDG);
2478 for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt);
2486 void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti)
2488 const btScalar kAHR=psb->m_cfg.kAHR*kst;
2489 const btScalar dt=psb->m_sst.sdt;
2490 for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
2492 const Anchor& a=psb->m_anchors[i];
2493 const btTransform& t=a.m_body->getInterpolationWorldTransform();
2495 const btVector3 wa=t*a.m_local;
2496 const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt;
2497 const btVector3 vb=n.m_x-n.m_q;
2498 const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR;
2499 const btVector3 impulse=a.m_c0*vr;
2500 n.m_x+=impulse*a.m_c2;
2501 a.m_body->applyImpulse(-impulse,a.m_c1);
2506 void btSoftBody::PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti)
2508 const btScalar dt=psb->m_sst.sdt;
2509 const btScalar mrg=psb->getCollisionShape()->getMargin();
2510 for(int i=0,ni=psb->m_rcontacts.size();i<ni;++i)
2512 const RContact& c=psb->m_rcontacts[i];
2513 const sCti& cti=c.m_cti;
2514 btRigidBody* tmpRigid = btRigidBody::upcast(cti.m_colObj);
2516 const btVector3 va=tmpRigid ? tmpRigid->getVelocityInLocalPoint(c.m_c1)*dt : btVector3(0,0,0);
2517 const btVector3 vb=c.m_node->m_x-c.m_node->m_q;
2518 const btVector3 vr=vb-va;
2519 const btScalar dn=dot(vr,cti.m_normal);
2520 if(dn<=SIMD_EPSILON)
2522 const btScalar dp=btMin(dot(c.m_node->m_x,cti.m_normal)+cti.m_offset,mrg);
2523 const btVector3 fv=vr-cti.m_normal*dn;
2524 const btVector3 impulse=c.m_c0*((vr-fv*c.m_c3+cti.m_normal*(dp*c.m_c4))*kst);
2525 c.m_node->m_x-=impulse*c.m_c2;
2527 tmpRigid->applyImpulse(impulse,c.m_c1);
2533 void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti)
2535 for(int i=0,ni=psb->m_scontacts.size();i<ni;++i)
2537 const SContact& c=psb->m_scontacts[i];
2538 const btVector3& nr=c.m_normal;
2541 const btVector3 p=BaryEval( f.m_n[0]->m_x,
2545 const btVector3 q=BaryEval( f.m_n[0]->m_q,
2549 const btVector3 vr=(n.m_x-n.m_q)-(p-q);
2550 btVector3 corr(0,0,0);
2553 const btScalar j=c.m_margin-(dot(nr,n.m_x)-dot(nr,p));
2556 corr -= ProjectOnPlane(vr,nr)*c.m_friction;
2557 n.m_x += corr*c.m_cfm[0];
2558 f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x());
2559 f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y());
2560 f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z());
2565 void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti)
2567 for(int i=0,ni=psb->m_links.size();i<ni;++i)
2569 Link& l=psb->m_links[i];
2574 const btVector3 del=b.m_x-a.m_x;
2575 const btScalar len=del.length2();
2576 const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst;
2577 const btScalar t=k*a.m_im;
2578 a.m_x-=del*(k*a.m_im);
2579 b.m_x+=del*(k*b.m_im);
2585 void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst)
2587 for(int i=0,ni=psb->m_links.size();i<ni;++i)
2589 Link& l=psb->m_links[i];
2591 const btScalar j=-dot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst;
2592 n[0]->m_v+= l.m_c3*(j*n[0]->m_im);
2593 n[1]->m_v-= l.m_c3*(j*n[1]->m_im);
2598 btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver)
2602 case ePSolver::Anchors: return(&btSoftBody::PSolve_Anchors);
2603 case ePSolver::Linear: return(&btSoftBody::PSolve_Links);
2604 case ePSolver::RContacts: return(&btSoftBody::PSolve_RContacts);
2605 case ePSolver::SContacts: return(&btSoftBody::PSolve_SContacts);
2611 btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
2615 case eVSolver::Linear: return(&btSoftBody::VSolve_Links);
2621 void btSoftBody::defaultCollisionHandler(btCollisionObject* pco)
2623 switch(m_cfg.collisions&fCollision::RVSmask)
2625 case fCollision::SDF_RS:
2627 btSoftColliders::CollideSDF_RS docollide;
2628 btRigidBody* prb1=btRigidBody::upcast(pco);
2629 btTransform wtr=prb1 ? prb1->getInterpolationWorldTransform() : pco->getWorldTransform();
2631 const btTransform ctr=pco->getWorldTransform();
2632 const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length();
2633 const btScalar basemargin=getCollisionShape()->getMargin();
2636 ATTRIBUTE_ALIGNED16(btDbvtVolume) volume;
2637 pco->getCollisionShape()->getAabb( pco->getInterpolationWorldTransform(),
2640 volume=btDbvtVolume::FromMM(mins,maxs);
2641 volume.Expand(btVector3(basemargin,basemargin,basemargin));
2642 docollide.psb = this;
2643 docollide.m_colObj1 = pco;
2644 docollide.m_rigidBody = prb1;
2646 docollide.dynmargin = basemargin+timemargin;
2647 docollide.stamargin = basemargin;
2648 m_ndbvt.collideTV(m_ndbvt.m_root,volume,docollide);
2651 case fCollision::CL_RS:
2653 btSoftColliders::CollideCL_RS collider;
2654 collider.Process(this,pco);
2661 void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
2663 const int cf=m_cfg.collisions&psb->m_cfg.collisions;
2664 switch(cf&fCollision::SVSmask)
2666 case fCollision::CL_SS:
2668 btSoftColliders::CollideCL_SS docollide;
2669 docollide.Process(this,psb);
2672 case fCollision::VF_SS:
2674 //only self-collision for Cluster, not Vertex-Face yet
2677 btSoftColliders::CollideVF_SS docollide;
2679 docollide.mrg= getCollisionShape()->getMargin()+
2680 psb->getCollisionShape()->getMargin();
2681 /* psb0 nodes vs psb1 faces */
2682 docollide.psb[0]=this;
2683 docollide.psb[1]=psb;
2684 docollide.psb[0]->m_ndbvt.collideTT( docollide.psb[0]->m_ndbvt.m_root,
2685 docollide.psb[1]->m_fdbvt.m_root,
2687 /* psb1 nodes vs psb0 faces */
2688 docollide.psb[0]=psb;
2689 docollide.psb[1]=this;
2690 docollide.psb[0]->m_ndbvt.collideTT( docollide.psb[0]->m_ndbvt.m_root,
2691 docollide.psb[1]->m_fdbvt.m_root,