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 #ifndef _BT_SOFT_BODY_INTERNALS_H
18 #define _BT_SOFT_BODY_INTERNALS_H
20 #include "btSoftBody.h"
22 #include "LinearMath/btQuickprof.h"
23 #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
24 #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
25 #include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
26 #include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
34 btSymMatrix() : dim(0) {}
35 btSymMatrix(int n,const T& init=T()) { resize(n,init); }
36 void resize(int n,const T& init=T()) { dim=n;store.resize((n*(n+1))/2,init); }
37 int index(int c,int r) const { if(c>r) btSwap(c,r);btAssert(r<dim);return((r*(r+1))/2+c); }
38 T& operator()(int c,int r) { return(store[index(c,r)]); }
39 const T& operator()(int c,int r) const { return(store[index(c,r)]); }
40 btAlignedObjectArray<T> store;
45 // btSoftBodyCollisionShape
47 class btSoftBodyCollisionShape : public btConcaveShape
52 btSoftBodyCollisionShape(btSoftBody* backptr)
54 m_shapeType = SOFTBODY_SHAPE_PROXYTYPE;
58 virtual ~btSoftBodyCollisionShape()
63 void processAllTriangles(btTriangleCallback* /*callback*/,const btVector3& /*aabbMin*/,const btVector3& /*aabbMax*/) const
69 ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
70 virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
72 /* t should be identity, but better be safe than...fast? */
73 const btVector3 mins=m_body->m_bounds[0];
74 const btVector3 maxs=m_body->m_bounds[1];
75 const btVector3 crns[]={t*btVector3(mins.x(),mins.y(),mins.z()),
76 t*btVector3(maxs.x(),mins.y(),mins.z()),
77 t*btVector3(maxs.x(),maxs.y(),mins.z()),
78 t*btVector3(mins.x(),maxs.y(),mins.z()),
79 t*btVector3(mins.x(),mins.y(),maxs.z()),
80 t*btVector3(maxs.x(),mins.y(),maxs.z()),
81 t*btVector3(maxs.x(),maxs.y(),maxs.z()),
82 t*btVector3(mins.x(),maxs.y(),maxs.z())};
83 aabbMin=aabbMax=crns[0];
86 aabbMin.setMin(crns[i]);
87 aabbMax.setMax(crns[i]);
92 virtual void setLocalScaling(const btVector3& /*scaling*/)
96 virtual const btVector3& getLocalScaling() const
98 static const btVector3 dummy(1,1,1);
101 virtual void calculateLocalInertia(btScalar /*mass*/,btVector3& /*inertia*/) const
106 virtual const char* getName()const
114 // btSoftClusterCollisionShape
116 class btSoftClusterCollisionShape : public btConvexInternalShape
119 const btSoftBody::Cluster* m_cluster;
121 btSoftClusterCollisionShape (const btSoftBody::Cluster* cluster) : m_cluster(cluster) { setMargin(0); }
124 virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
126 btSoftBody::Node* const * n=&m_cluster->m_nodes[0];
127 btScalar d=dot(vec,n[0]->m_x);
129 for(int i=1,ni=m_cluster->m_nodes.size();i<ni;++i)
131 const btScalar k=dot(vec,n[i]->m_x);
136 virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
138 return(localGetSupportingVertex(vec));
140 //notice that the vectors should be unit length
141 virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
145 virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const
148 virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
151 virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; }
154 virtual const char* getName()const {return "SOFTCLUSTER";}
156 virtual void setMargin(btScalar margin)
158 btConvexInternalShape::setMargin(margin);
160 virtual btScalar getMargin() const
171 template <typename T>
172 static inline void ZeroInitialize(T& value)
174 static const T zerodummy;
178 template <typename T>
179 static inline bool CompLess(const T& a,const T& b)
182 template <typename T>
183 static inline bool CompGreater(const T& a,const T& b)
186 template <typename T>
187 static inline T Lerp(const T& a,const T& b,btScalar t)
188 { return(a+(b-a)*t); }
190 template <typename T>
191 static inline T InvLerp(const T& a,const T& b,btScalar t)
192 { return((b+a*t-b*t)/(a*b)); }
194 static inline btMatrix3x3 Lerp( const btMatrix3x3& a,
195 const btMatrix3x3& b,
199 r[0]=Lerp(a[0],b[0],t);
200 r[1]=Lerp(a[1],b[1],t);
201 r[2]=Lerp(a[2],b[2],t);
205 static inline btVector3 Clamp(const btVector3& v,btScalar maxlength)
207 const btScalar sql=v.length2();
208 if(sql>(maxlength*maxlength))
209 return((v*maxlength)/btSqrt(sql));
214 template <typename T>
215 static inline T Clamp(const T& x,const T& l,const T& h)
216 { return(x<l?l:x>h?h:x); }
218 template <typename T>
219 static inline T Sq(const T& x)
222 template <typename T>
223 static inline T Cube(const T& x)
226 template <typename T>
227 static inline T Sign(const T& x)
228 { return((T)(x<0?-1:+1)); }
230 template <typename T>
231 static inline bool SameSign(const T& x,const T& y)
234 static inline btScalar ClusterMetric(const btVector3& x,const btVector3& y)
236 const btVector3 d=x-y;
237 return(btFabs(d[0])+btFabs(d[1])+btFabs(d[2]));
240 static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a,btScalar s)
242 const btScalar xx=a.x()*a.x();
243 const btScalar yy=a.y()*a.y();
244 const btScalar zz=a.z()*a.z();
245 const btScalar xy=a.x()*a.y();
246 const btScalar yz=a.y()*a.z();
247 const btScalar zx=a.z()*a.x();
249 m[0]=btVector3(1-xx+xx*s,xy*s-xy,zx*s-zx);
250 m[1]=btVector3(xy*s-xy,1-yy+yy*s,yz*s-yz);
251 m[2]=btVector3(zx*s-zx,yz*s-yz,1-zz+zz*s);
255 static inline btMatrix3x3 Cross(const btVector3& v)
258 m[0]=btVector3(0,-v.z(),+v.y());
259 m[1]=btVector3(+v.z(),0,-v.x());
260 m[2]=btVector3(-v.y(),+v.x(),0);
264 static inline btMatrix3x3 Diagonal(btScalar x)
267 m[0]=btVector3(x,0,0);
268 m[1]=btVector3(0,x,0);
269 m[2]=btVector3(0,0,x);
273 static inline btMatrix3x3 Add(const btMatrix3x3& a,
274 const btMatrix3x3& b)
277 for(int i=0;i<3;++i) r[i]=a[i]+b[i];
281 static inline btMatrix3x3 Sub(const btMatrix3x3& a,
282 const btMatrix3x3& b)
285 for(int i=0;i<3;++i) r[i]=a[i]-b[i];
289 static inline btMatrix3x3 Mul(const btMatrix3x3& a,
293 for(int i=0;i<3;++i) r[i]=a[i]*b;
297 static inline void Orthogonalize(btMatrix3x3& m)
299 m[2]=cross(m[0],m[1]).normalized();
300 m[1]=cross(m[2],m[0]).normalized();
301 m[0]=cross(m[1],m[2]).normalized();
304 static inline btMatrix3x3 MassMatrix(btScalar im,const btMatrix3x3& iwi,const btVector3& r)
306 const btMatrix3x3 cr=Cross(r);
307 return(Sub(Diagonal(im),cr*iwi*cr));
311 static inline btMatrix3x3 ImpulseMatrix( btScalar dt,
314 const btMatrix3x3& iwi,
317 return(Diagonal(1/dt)*Add(Diagonal(ima),MassMatrix(imb,iwi,r)).inverse());
321 static inline btMatrix3x3 ImpulseMatrix( btScalar ima,const btMatrix3x3& iia,const btVector3& ra,
322 btScalar imb,const btMatrix3x3& iib,const btVector3& rb)
324 return(Add(MassMatrix(ima,iia,ra),MassMatrix(imb,iib,rb)).inverse());
328 static inline btMatrix3x3 AngularImpulseMatrix( const btMatrix3x3& iia,
329 const btMatrix3x3& iib)
331 return(Add(iia,iib).inverse());
335 static inline btVector3 ProjectOnAxis( const btVector3& v,
341 static inline btVector3 ProjectOnPlane( const btVector3& v,
344 return(v-ProjectOnAxis(v,a));
348 static inline void ProjectOrigin( const btVector3& a,
353 const btVector3 d=b-a;
354 const btScalar m2=d.length2();
357 const btScalar t=Clamp<btScalar>(-dot(a,d)/m2,0,1);
358 const btVector3 p=a+d*t;
359 const btScalar l2=p.length2();
368 static inline void ProjectOrigin( const btVector3& a,
374 const btVector3& q=cross(b-a,c-a);
375 const btScalar m2=q.length2();
378 const btVector3 n=q/btSqrt(m2);
379 const btScalar k=dot(a,n);
380 const btScalar k2=k*k;
383 const btVector3 p=n*k;
384 if( (dot(cross(a-p,b-p),q)>0)&&
385 (dot(cross(b-p,c-p),q)>0)&&
386 (dot(cross(c-p,a-p),q)>0))
393 ProjectOrigin(a,b,prj,sqd);
394 ProjectOrigin(b,c,prj,sqd);
395 ProjectOrigin(c,a,prj,sqd);
402 template <typename T>
403 static inline T BaryEval( const T& a,
406 const btVector3& coord)
408 return(a*coord.x()+b*coord.y()+c*coord.z());
411 static inline btVector3 BaryCoord( const btVector3& a,
416 const btScalar w[]={ cross(a-p,b-p).length(),
417 cross(b-p,c-p).length(),
418 cross(c-p,a-p).length()};
419 const btScalar isum=1/(w[0]+w[1]+w[2]);
420 return(btVector3(w[1]*isum,w[2]*isum,w[0]*isum));
424 static btScalar ImplicitSolve( btSoftBody::ImplicitFn* fn,
427 const btScalar accuracy,
428 const int maxiterations=256)
430 btScalar span[2]={0,1};
431 btScalar values[2]={fn->Eval(a),fn->Eval(b)};
432 if(values[0]>values[1])
434 btSwap(span[0],span[1]);
435 btSwap(values[0],values[1]);
437 if(values[0]>-accuracy) return(-1);
438 if(values[1]<+accuracy) return(-1);
439 for(int i=0;i<maxiterations;++i)
441 const btScalar t=Lerp(span[0],span[1],values[0]/(values[0]-values[1]));
442 const btScalar v=fn->Eval(Lerp(a,b,t));
443 if((t<=0)||(t>=1)) break;
444 if(btFabs(v)<accuracy) return(t);
446 { span[0]=t;values[0]=v; }
448 { span[1]=t;values[1]=v; }
454 static inline btVector3 NormalizeAny(const btVector3& v)
456 const btScalar l=v.length();
460 return(btVector3(0,0,0));
464 static inline btDbvtVolume VolumeOf( const btSoftBody::Face& f,
467 const btVector3* pts[]={ &f.m_n[0]->m_x,
470 btDbvtVolume vol=btDbvtVolume::FromPoints(pts,3);
471 vol.Expand(btVector3(margin,margin,margin));
476 static inline btVector3 CenterOf( const btSoftBody::Face& f)
478 return((f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3);
482 static inline btScalar AreaOf( const btVector3& x0,
486 const btVector3 a=x1-x0;
487 const btVector3 b=x2-x0;
488 const btVector3 cr=cross(a,b);
489 const btScalar area=cr.length();
494 static inline btScalar VolumeOf( const btVector3& x0,
499 const btVector3 a=x1-x0;
500 const btVector3 b=x2-x0;
501 const btVector3 c=x3-x0;
502 return(dot(a,cross(b,c)));
506 static void EvaluateMedium( const btSoftBodyWorldInfo* wfi,
508 btSoftBody::sMedium& medium)
510 medium.m_velocity = btVector3(0,0,0);
511 medium.m_pressure = 0;
512 medium.m_density = wfi->air_density;
513 if(wfi->water_density>0)
515 const btScalar depth=-(dot(x,wfi->water_normal)+wfi->water_offset);
518 medium.m_density = wfi->water_density;
519 medium.m_pressure = depth*wfi->water_density*wfi->m_gravity.length();
525 static inline void ApplyClampedForce( btSoftBody::Node& n,
529 const btScalar dtim=dt*n.m_im;
530 if((f*dtim).length2()>n.m_v.length2())
532 n.m_f-=ProjectOnAxis(n.m_v,f.normalized())/dtim;
541 static inline int MatchEdge( const btSoftBody::Node* a,
542 const btSoftBody::Node* b,
543 const btSoftBody::Node* ma,
544 const btSoftBody::Node* mb)
546 if((a==ma)&&(b==mb)) return(0);
547 if((a==mb)&&(b==ma)) return(1);
552 // btEigen : Extract eigen system,
553 // straitforward implementation of http://math.fullerton.edu/mathews/n2003/JacobiMethodMod.html
554 // outputs are NOT sorted.
558 static int system(btMatrix3x3& a,btMatrix3x3* vectors,btVector3* values=0)
560 static const int maxiterations=16;
561 static const btScalar accuracy=(btScalar)0.0001;
562 btMatrix3x3& v=*vectors;
564 vectors->setIdentity();
567 if(btFabs(a[p][q])<btFabs(a[0][2])) { p=0;q=2; }
568 if(btFabs(a[p][q])<btFabs(a[1][2])) { p=1;q=2; }
569 if(btFabs(a[p][q])>accuracy)
571 const btScalar w=(a[q][q]-a[p][p])/(2*a[p][q]);
572 const btScalar z=btFabs(w);
573 const btScalar t=w/(z*(btSqrt(1+w*w)+z));
574 if(t==t)/* [WARNING] let hope that one does not get thrown aways by some compilers... */
576 const btScalar c=1/btSqrt(t*t+1);
577 const btScalar s=c*t;
583 } while((++iterations)<maxiterations);
586 *values=btVector3(a[0][0],a[1][1],a[2][2]);
591 static inline void mulTPQ(btMatrix3x3& a,btScalar c,btScalar s,int p,int q)
593 const btScalar m[2][3]={ {a[p][0],a[p][1],a[p][2]},
594 {a[q][0],a[q][1],a[q][2]}};
597 for(i=0;i<3;++i) a[p][i]=c*m[0][i]-s*m[1][i];
598 for(i=0;i<3;++i) a[q][i]=c*m[1][i]+s*m[0][i];
600 static inline void mulPQ(btMatrix3x3& a,btScalar c,btScalar s,int p,int q)
602 const btScalar m[2][3]={ {a[0][p],a[1][p],a[2][p]},
603 {a[0][q],a[1][q],a[2][q]}};
606 for(i=0;i<3;++i) a[i][p]=c*m[0][i]-s*m[1][i];
607 for(i=0;i<3;++i) a[i][q]=c*m[1][i]+s*m[0][i];
612 // Polar decomposition,
613 // "Computing the Polar Decomposition with Applications", Nicholas J. Higham, 1986.
615 static inline int PolarDecompose( const btMatrix3x3& m,btMatrix3x3& q,btMatrix3x3& s)
617 static const btScalar half=(btScalar)0.5;
618 static const btScalar accuracy=(btScalar)0.0001;
619 static const int maxiterations=16;
622 q = Mul(m,1/btVector3(m[0][0],m[1][1],m[2][2]).length());
623 det = q.determinant();
624 if(!btFuzzyZero(det))
626 for(;i<maxiterations;++i)
628 q=Mul(Add(q,Mul(q.adjoint(),1/det).transpose()),half);
629 const btScalar ndet=q.determinant();
630 if(Sq(ndet-det)>accuracy) det=ndet; else break;
632 /* Final orthogonalization */
648 struct btSoftColliders
653 struct ClusterBase : btDbvt::ICollide
666 threshold =(btScalar)0;
668 bool SolveContact( const btGjkEpaSolver2::sResults& res,
669 btSoftBody::Body ba,btSoftBody::Body bb,
670 btSoftBody::CJoint& joint)
672 if(res.distance<margin)
674 const btVector3 ra=res.witnesses[0]-ba.xform().getOrigin();
675 const btVector3 rb=res.witnesses[1]-bb.xform().getOrigin();
676 const btVector3 va=ba.velocity(ra);
677 const btVector3 vb=bb.velocity(rb);
678 const btVector3 vrel=va-vb;
679 const btScalar rvac=dot(vrel,res.normal);
680 const btScalar depth=res.distance-margin;
681 const btVector3 iv=res.normal*rvac;
682 const btVector3 fv=vrel-iv;
683 joint.m_bodies[0] = ba;
684 joint.m_bodies[1] = bb;
685 joint.m_refs[0] = ra*ba.xform().getBasis();
686 joint.m_refs[1] = rb*bb.xform().getBasis();
687 joint.m_rpos[0] = ra;
688 joint.m_rpos[1] = rb;
694 joint.m_drift = depth*res.normal;
695 joint.m_normal = res.normal;
696 joint.m_delete = false;
697 joint.m_friction = fv.length2()<(-rvac*friction)?1:friction;
698 joint.m_massmatrix = ImpulseMatrix( ba.invMass(),ba.invWorldInertia(),joint.m_rpos[0],
699 bb.invMass(),bb.invWorldInertia(),joint.m_rpos[1]);
708 struct CollideCL_RS : ClusterBase
712 btCollisionObject* m_colObj;
713 void Process(const btDbvtNode* leaf)
715 btSoftBody::Cluster* cluster=(btSoftBody::Cluster*)leaf->data;
716 btSoftClusterCollisionShape cshape(cluster);
717 const btConvexShape* rshape=(const btConvexShape*)m_colObj->getCollisionShape();
718 btGjkEpaSolver2::sResults res;
719 if(btGjkEpaSolver2::SignedDistance( &cshape,btTransform::getIdentity(),
720 rshape,m_colObj->getInterpolationWorldTransform(),
721 btVector3(1,0,0),res))
723 btSoftBody::CJoint joint;
724 if(SolveContact(res,cluster,m_colObj,joint))//prb,joint))
726 btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint();
727 *pj=joint;psb->m_joints.push_back(pj);
728 if(m_colObj->isStaticOrKinematicObject())
730 pj->m_erp *= psb->m_cfg.kSKHR_CL;
731 pj->m_split *= psb->m_cfg.kSK_SPLT_CL;
735 pj->m_erp *= psb->m_cfg.kSRHR_CL;
736 pj->m_split *= psb->m_cfg.kSR_SPLT_CL;
741 void Process(btSoftBody* ps,btCollisionObject* colOb)
745 idt = ps->m_sst.isdt;
746 margin = m_colObj->getCollisionShape()->getMargin();
747 ///Bullet rigid body uses multiply instead of minimum to determine combined friction. Some customization would be useful.
748 friction = btMin(psb->m_cfg.kDF,m_colObj->getFriction());
752 ATTRIBUTE_ALIGNED16(btDbvtVolume) volume;
753 colOb->getCollisionShape()->getAabb(colOb->getInterpolationWorldTransform(),mins,maxs);
754 volume=btDbvtVolume::FromMM(mins,maxs);
755 volume.Expand(btVector3(1,1,1)*margin);
756 ps->m_cdbvt.collideTV(ps->m_cdbvt.m_root,volume,*this);
762 struct CollideCL_SS : ClusterBase
764 btSoftBody* bodies[2];
765 void Process(const btDbvtNode* la,const btDbvtNode* lb)
767 btSoftBody::Cluster* cla=(btSoftBody::Cluster*)la->data;
768 btSoftBody::Cluster* clb=(btSoftBody::Cluster*)lb->data;
771 bool connected=false;
772 if ((bodies[0]==bodies[1])&&(bodies[0]->m_clusterConnectivity.size()))
774 connected = bodies[0]->m_clusterConnectivity[cla->m_clusterIndex+bodies[0]->m_clusters.size()*clb->m_clusterIndex];
779 btSoftClusterCollisionShape csa(cla);
780 btSoftClusterCollisionShape csb(clb);
781 btGjkEpaSolver2::sResults res;
782 if(btGjkEpaSolver2::SignedDistance( &csa,btTransform::getIdentity(),
783 &csb,btTransform::getIdentity(),
784 cla->m_com-clb->m_com,res))
786 btSoftBody::CJoint joint;
787 if(SolveContact(res,cla,clb,joint))
789 btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint();
790 *pj=joint;bodies[0]->m_joints.push_back(pj);
791 pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL,bodies[1]->m_cfg.kSSHR_CL);
792 pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL+bodies[1]->m_cfg.kSS_SPLT_CL)/2;
799 //printf("count=%d\n",count);
803 void Process(btSoftBody* psa,btSoftBody* psb)
805 idt = psa->m_sst.isdt;
806 margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2;
807 friction = btMin(psa->m_cfg.kDF,psb->m_cfg.kDF);
810 psa->m_cdbvt.collideTT(psa->m_cdbvt.m_root,psb->m_cdbvt.m_root,*this);
816 struct CollideSDF_RS : btDbvt::ICollide
818 void Process(const btDbvtNode* leaf)
820 btSoftBody::Node* node=(btSoftBody::Node*)leaf->data;
823 void DoNode(btSoftBody::Node& n) const
825 const btScalar m=n.m_im>0?dynmargin:stamargin;
826 btSoftBody::RContact c;
828 psb->checkContact(m_colObj1,n.m_x,m,c.m_cti))
830 const btScalar ima=n.m_im;
831 const btScalar imb= m_rigidBody? m_rigidBody->getInvMass() : 0.f;
832 const btScalar ms=ima+imb;
835 const btTransform& wtr=m_rigidBody?m_rigidBody->getInterpolationWorldTransform() : m_colObj1->getWorldTransform();
836 static const btMatrix3x3 iwiStatic(0,0,0,0,0,0,0,0,0);
837 const btMatrix3x3& iwi=m_rigidBody?m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
838 const btVector3 ra=n.m_x-wtr.getOrigin();
839 const btVector3 va=m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra)*psb->m_sst.sdt : btVector3(0,0,0);
840 const btVector3 vb=n.m_x-n.m_q;
841 const btVector3 vr=vb-va;
842 const btScalar dn=dot(vr,c.m_cti.m_normal);
843 const btVector3 fv=vr-c.m_cti.m_normal*dn;
844 const btScalar fc=psb->m_cfg.kDF*m_colObj1->getFriction();
846 c.m_c0 = ImpulseMatrix(psb->m_sst.sdt,ima,imb,iwi,ra);
848 c.m_c2 = ima*psb->m_sst.sdt;
849 c.m_c3 = fv.length2()<(btFabs(dn)*fc)?0:1-fc;
850 c.m_c4 = m_colObj1->isStaticOrKinematicObject()?psb->m_cfg.kKHR:psb->m_cfg.kCHR;
851 psb->m_rcontacts.push_back(c);
853 m_rigidBody->activate();
858 btCollisionObject* m_colObj1;
859 btRigidBody* m_rigidBody;
866 struct CollideVF_SS : btDbvt::ICollide
868 void Process(const btDbvtNode* lnode,
869 const btDbvtNode* lface)
871 btSoftBody::Node* node=(btSoftBody::Node*)lnode->data;
872 btSoftBody::Face* face=(btSoftBody::Face*)lface->data;
873 btVector3 o=node->m_x;
875 btScalar d=SIMD_INFINITY;
876 ProjectOrigin( face->m_n[0]->m_x-o,
880 const btScalar m=mrg+(o-node->m_q).length()*2;
883 const btSoftBody::Node* n[]={face->m_n[0],face->m_n[1],face->m_n[2]};
884 const btVector3 w=BaryCoord(n[0]->m_x,n[1]->m_x,n[2]->m_x,p+o);
885 const btScalar ma=node->m_im;
886 btScalar mb=BaryEval(n[0]->m_im,n[1]->m_im,n[2]->m_im,w);
887 if( (n[0]->m_im<=0)||
893 const btScalar ms=ma+mb;
896 btSoftBody::SContact c;
897 c.m_normal = p/-btSqrt(d);
902 c.m_friction = btMax(psb[0]->m_cfg.kDF,psb[1]->m_cfg.kDF);
903 c.m_cfm[0] = ma/ms*psb[0]->m_cfg.kSHR;
904 c.m_cfm[1] = mb/ms*psb[1]->m_cfg.kSHR;
905 psb[0]->m_scontacts.push_back(c);
914 #endif //_BT_SOFT_BODY_INTERNALS_H