Blender V2.61 - r43446

btSoftBodyInternals.h

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose,
00008 including commercial applications, and to alter it and redistribute it freely,
00009 subject to the following restrictions:
00010 
00011 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.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00016 
00017 #ifndef _BT_SOFT_BODY_INTERNALS_H
00018 #define _BT_SOFT_BODY_INTERNALS_H
00019 
00020 #include "btSoftBody.h"
00021 
00022 
00023 #include "LinearMath/btQuickprof.h"
00024 #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
00025 #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
00026 #include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
00027 #include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
00028 #include <string.h> //for memset
00029 //
00030 // btSymMatrix
00031 //
00032 template <typename T>
00033 struct btSymMatrix
00034 {
00035     btSymMatrix() : dim(0)                  {}
00036     btSymMatrix(int n,const T& init=T())    { resize(n,init); }
00037     void                    resize(int n,const T& init=T())         { dim=n;store.resize((n*(n+1))/2,init); }
00038     int                     index(int c,int r) const                { if(c>r) btSwap(c,r);btAssert(r<dim);return((r*(r+1))/2+c); }
00039     T&                      operator()(int c,int r)                 { return(store[index(c,r)]); }
00040     const T&                operator()(int c,int r) const           { return(store[index(c,r)]); }
00041     btAlignedObjectArray<T> store;
00042     int                     dim;
00043 };  
00044 
00045 //
00046 // btSoftBodyCollisionShape
00047 //
00048 class btSoftBodyCollisionShape : public btConcaveShape
00049 {
00050 public:
00051     btSoftBody*                     m_body;
00052 
00053     btSoftBodyCollisionShape(btSoftBody* backptr)
00054     {
00055         m_shapeType = SOFTBODY_SHAPE_PROXYTYPE;
00056         m_body=backptr;
00057     }
00058 
00059     virtual ~btSoftBodyCollisionShape()
00060     {
00061 
00062     }
00063 
00064     void    processAllTriangles(btTriangleCallback* /*callback*/,const btVector3& /*aabbMin*/,const btVector3& /*aabbMax*/) const
00065     {
00066         //not yet
00067         btAssert(0);
00068     }
00069 
00071     virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
00072     {
00073         /* t should be identity, but better be safe than...fast? */ 
00074         const btVector3 mins=m_body->m_bounds[0];
00075         const btVector3 maxs=m_body->m_bounds[1];
00076         const btVector3 crns[]={t*btVector3(mins.x(),mins.y(),mins.z()),
00077             t*btVector3(maxs.x(),mins.y(),mins.z()),
00078             t*btVector3(maxs.x(),maxs.y(),mins.z()),
00079             t*btVector3(mins.x(),maxs.y(),mins.z()),
00080             t*btVector3(mins.x(),mins.y(),maxs.z()),
00081             t*btVector3(maxs.x(),mins.y(),maxs.z()),
00082             t*btVector3(maxs.x(),maxs.y(),maxs.z()),
00083             t*btVector3(mins.x(),maxs.y(),maxs.z())};
00084         aabbMin=aabbMax=crns[0];
00085         for(int i=1;i<8;++i)
00086         {
00087             aabbMin.setMin(crns[i]);
00088             aabbMax.setMax(crns[i]);
00089         }
00090     }
00091 
00092 
00093     virtual void    setLocalScaling(const btVector3& /*scaling*/)
00094     {       
00096     }
00097     virtual const btVector3& getLocalScaling() const
00098     {
00099         static const btVector3 dummy(1,1,1);
00100         return dummy;
00101     }
00102     virtual void    calculateLocalInertia(btScalar /*mass*/,btVector3& /*inertia*/) const
00103     {
00105         btAssert(0);
00106     }
00107     virtual const char* getName()const
00108     {
00109         return "SoftBody";
00110     }
00111 
00112 };
00113 
00114 //
00115 // btSoftClusterCollisionShape
00116 //
00117 class btSoftClusterCollisionShape : public btConvexInternalShape
00118 {
00119 public:
00120     const btSoftBody::Cluster*  m_cluster;
00121 
00122     btSoftClusterCollisionShape (const btSoftBody::Cluster* cluster) : m_cluster(cluster) { setMargin(0); }
00123 
00124 
00125     virtual btVector3   localGetSupportingVertex(const btVector3& vec) const
00126     {
00127         btSoftBody::Node* const *                       n=&m_cluster->m_nodes[0];
00128         btScalar                                        d=btDot(vec,n[0]->m_x);
00129         int                                             j=0;
00130         for(int i=1,ni=m_cluster->m_nodes.size();i<ni;++i)
00131         {
00132             const btScalar  k=btDot(vec,n[i]->m_x);
00133             if(k>d) { d=k;j=i; }
00134         }
00135         return(n[j]->m_x);
00136     }
00137     virtual btVector3   localGetSupportingVertexWithoutMargin(const btVector3& vec)const
00138     {
00139         return(localGetSupportingVertex(vec));
00140     }
00141     //notice that the vectors should be unit length
00142     virtual void    batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
00143     {}
00144 
00145 
00146     virtual void    calculateLocalInertia(btScalar mass,btVector3& inertia) const
00147     {}
00148 
00149     virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
00150     {}
00151 
00152     virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; }
00153 
00154     //debugging
00155     virtual const char* getName()const {return "SOFTCLUSTER";}
00156 
00157     virtual void    setMargin(btScalar margin)
00158     {
00159         btConvexInternalShape::setMargin(margin);
00160     }
00161     virtual btScalar    getMargin() const
00162     {
00163         return getMargin();
00164     }
00165 };
00166 
00167 //
00168 // Inline's
00169 //
00170 
00171 //
00172 template <typename T>
00173 static inline void          ZeroInitialize(T& value)
00174 {
00175     memset(&value,0,sizeof(T));
00176 }
00177 //
00178 template <typename T>
00179 static inline bool          CompLess(const T& a,const T& b)
00180 { return(a<b); }
00181 //
00182 template <typename T>
00183 static inline bool          CompGreater(const T& a,const T& b)
00184 { return(a>b); }
00185 //
00186 template <typename T>
00187 static inline T             Lerp(const T& a,const T& b,btScalar t)
00188 { return(a+(b-a)*t); }
00189 //
00190 template <typename T>
00191 static inline T             InvLerp(const T& a,const T& b,btScalar t)
00192 { return((b+a*t-b*t)/(a*b)); }
00193 //
00194 static inline btMatrix3x3   Lerp(   const btMatrix3x3& a,
00195                                  const btMatrix3x3& b,
00196                                  btScalar t)
00197 {
00198     btMatrix3x3 r;
00199     r[0]=Lerp(a[0],b[0],t);
00200     r[1]=Lerp(a[1],b[1],t);
00201     r[2]=Lerp(a[2],b[2],t);
00202     return(r);
00203 }
00204 //
00205 static inline btVector3     Clamp(const btVector3& v,btScalar maxlength)
00206 {
00207     const btScalar sql=v.length2();
00208     if(sql>(maxlength*maxlength))
00209         return((v*maxlength)/btSqrt(sql));
00210     else
00211         return(v);
00212 }
00213 //
00214 template <typename T>
00215 static inline T             Clamp(const T& x,const T& l,const T& h)
00216 { return(x<l?l:x>h?h:x); }
00217 //
00218 template <typename T>
00219 static inline T             Sq(const T& x)
00220 { return(x*x); }
00221 //
00222 template <typename T>
00223 static inline T             Cube(const T& x)
00224 { return(x*x*x); }
00225 //
00226 template <typename T>
00227 static inline T             Sign(const T& x)
00228 { return((T)(x<0?-1:+1)); }
00229 //
00230 template <typename T>
00231 static inline bool          SameSign(const T& x,const T& y)
00232 { return((x*y)>0); }
00233 //
00234 static inline btScalar      ClusterMetric(const btVector3& x,const btVector3& y)
00235 {
00236     const btVector3 d=x-y;
00237     return(btFabs(d[0])+btFabs(d[1])+btFabs(d[2]));
00238 }
00239 //
00240 static inline btMatrix3x3   ScaleAlongAxis(const btVector3& a,btScalar s)
00241 {
00242     const btScalar  xx=a.x()*a.x();
00243     const btScalar  yy=a.y()*a.y();
00244     const btScalar  zz=a.z()*a.z();
00245     const btScalar  xy=a.x()*a.y();
00246     const btScalar  yz=a.y()*a.z();
00247     const btScalar  zx=a.z()*a.x();
00248     btMatrix3x3     m;
00249     m[0]=btVector3(1-xx+xx*s,xy*s-xy,zx*s-zx);
00250     m[1]=btVector3(xy*s-xy,1-yy+yy*s,yz*s-yz);
00251     m[2]=btVector3(zx*s-zx,yz*s-yz,1-zz+zz*s);
00252     return(m);
00253 }
00254 //
00255 static inline btMatrix3x3   Cross(const btVector3& v)
00256 {
00257     btMatrix3x3 m;
00258     m[0]=btVector3(0,-v.z(),+v.y());
00259     m[1]=btVector3(+v.z(),0,-v.x());
00260     m[2]=btVector3(-v.y(),+v.x(),0);
00261     return(m);
00262 }
00263 //
00264 static inline btMatrix3x3   Diagonal(btScalar x)
00265 {
00266     btMatrix3x3 m;
00267     m[0]=btVector3(x,0,0);
00268     m[1]=btVector3(0,x,0);
00269     m[2]=btVector3(0,0,x);
00270     return(m);
00271 }
00272 //
00273 static inline btMatrix3x3   Add(const btMatrix3x3& a,
00274                                 const btMatrix3x3& b)
00275 {
00276     btMatrix3x3 r;
00277     for(int i=0;i<3;++i) r[i]=a[i]+b[i];
00278     return(r);
00279 }
00280 //
00281 static inline btMatrix3x3   Sub(const btMatrix3x3& a,
00282                                 const btMatrix3x3& b)
00283 {
00284     btMatrix3x3 r;
00285     for(int i=0;i<3;++i) r[i]=a[i]-b[i];
00286     return(r);
00287 }
00288 //
00289 static inline btMatrix3x3   Mul(const btMatrix3x3& a,
00290                                 btScalar b)
00291 {
00292     btMatrix3x3 r;
00293     for(int i=0;i<3;++i) r[i]=a[i]*b;
00294     return(r);
00295 }
00296 //
00297 static inline void          Orthogonalize(btMatrix3x3& m)
00298 {
00299     m[2]=btCross(m[0],m[1]).normalized();
00300     m[1]=btCross(m[2],m[0]).normalized();
00301     m[0]=btCross(m[1],m[2]).normalized();
00302 }
00303 //
00304 static inline btMatrix3x3   MassMatrix(btScalar im,const btMatrix3x3& iwi,const btVector3& r)
00305 {
00306     const btMatrix3x3   cr=Cross(r);
00307     return(Sub(Diagonal(im),cr*iwi*cr));
00308 }
00309 
00310 //
00311 static inline btMatrix3x3   ImpulseMatrix(  btScalar dt,
00312                                           btScalar ima,
00313                                           btScalar imb,
00314                                           const btMatrix3x3& iwi,
00315                                           const btVector3& r)
00316 {
00317     return(Diagonal(1/dt)*Add(Diagonal(ima),MassMatrix(imb,iwi,r)).inverse());
00318 }
00319 
00320 //
00321 static inline btMatrix3x3   ImpulseMatrix(  btScalar ima,const btMatrix3x3& iia,const btVector3& ra,
00322                                           btScalar imb,const btMatrix3x3& iib,const btVector3& rb)  
00323 {
00324     return(Add(MassMatrix(ima,iia,ra),MassMatrix(imb,iib,rb)).inverse());
00325 }
00326 
00327 //
00328 static inline btMatrix3x3   AngularImpulseMatrix(   const btMatrix3x3& iia,
00329                                                  const btMatrix3x3& iib)
00330 {
00331     return(Add(iia,iib).inverse());
00332 }
00333 
00334 //
00335 static inline btVector3     ProjectOnAxis(  const btVector3& v,
00336                                           const btVector3& a)
00337 {
00338     return(a*btDot(v,a));
00339 }
00340 //
00341 static inline btVector3     ProjectOnPlane( const btVector3& v,
00342                                            const btVector3& a)
00343 {
00344     return(v-ProjectOnAxis(v,a));
00345 }
00346 
00347 //
00348 static inline void          ProjectOrigin(  const btVector3& a,
00349                                           const btVector3& b,
00350                                           btVector3& prj,
00351                                           btScalar& sqd)
00352 {
00353     const btVector3 d=b-a;
00354     const btScalar  m2=d.length2();
00355     if(m2>SIMD_EPSILON)
00356     {   
00357         const btScalar  t=Clamp<btScalar>(-btDot(a,d)/m2,0,1);
00358         const btVector3 p=a+d*t;
00359         const btScalar  l2=p.length2();
00360         if(l2<sqd)
00361         {
00362             prj=p;
00363             sqd=l2;
00364         }
00365     }
00366 }
00367 //
00368 static inline void          ProjectOrigin(  const btVector3& a,
00369                                           const btVector3& b,
00370                                           const btVector3& c,
00371                                           btVector3& prj,
00372                                           btScalar& sqd)
00373 {
00374     const btVector3&    q=btCross(b-a,c-a);
00375     const btScalar      m2=q.length2();
00376     if(m2>SIMD_EPSILON)
00377     {
00378         const btVector3 n=q/btSqrt(m2);
00379         const btScalar  k=btDot(a,n);
00380         const btScalar  k2=k*k;
00381         if(k2<sqd)
00382         {
00383             const btVector3 p=n*k;
00384             if( (btDot(btCross(a-p,b-p),q)>0)&&
00385                 (btDot(btCross(b-p,c-p),q)>0)&&
00386                 (btDot(btCross(c-p,a-p),q)>0))
00387             {           
00388                 prj=p;
00389                 sqd=k2;
00390             }
00391             else
00392             {
00393                 ProjectOrigin(a,b,prj,sqd);
00394                 ProjectOrigin(b,c,prj,sqd);
00395                 ProjectOrigin(c,a,prj,sqd);
00396             }
00397         }
00398     }
00399 }
00400 
00401 //
00402 template <typename T>
00403 static inline T             BaryEval(       const T& a,
00404                                      const T& b,
00405                                      const T& c,
00406                                      const btVector3& coord)
00407 {
00408     return(a*coord.x()+b*coord.y()+c*coord.z());
00409 }
00410 //
00411 static inline btVector3     BaryCoord(  const btVector3& a,
00412                                       const btVector3& b,
00413                                       const btVector3& c,
00414                                       const btVector3& p)
00415 {
00416     const btScalar  w[]={   btCross(a-p,b-p).length(),
00417         btCross(b-p,c-p).length(),
00418         btCross(c-p,a-p).length()};
00419     const btScalar  isum=1/(w[0]+w[1]+w[2]);
00420     return(btVector3(w[1]*isum,w[2]*isum,w[0]*isum));
00421 }
00422 
00423 //
00424 static btScalar             ImplicitSolve(  btSoftBody::ImplicitFn* fn,
00425                                           const btVector3& a,
00426                                           const btVector3& b,
00427                                           const btScalar accuracy,
00428                                           const int maxiterations=256)
00429 {
00430     btScalar    span[2]={0,1};
00431     btScalar    values[2]={fn->Eval(a),fn->Eval(b)};
00432     if(values[0]>values[1])
00433     {
00434         btSwap(span[0],span[1]);
00435         btSwap(values[0],values[1]);
00436     }
00437     if(values[0]>-accuracy) return(-1);
00438     if(values[1]<+accuracy) return(-1);
00439     for(int i=0;i<maxiterations;++i)
00440     {
00441         const btScalar  t=Lerp(span[0],span[1],values[0]/(values[0]-values[1]));
00442         const btScalar  v=fn->Eval(Lerp(a,b,t));
00443         if((t<=0)||(t>=1))      break;
00444         if(btFabs(v)<accuracy)  return(t);
00445         if(v<0)
00446         { span[0]=t;values[0]=v; }
00447         else
00448         { span[1]=t;values[1]=v; }
00449     }
00450     return(-1);
00451 }
00452 
00453 //
00454 static inline btVector3     NormalizeAny(const btVector3& v)
00455 {
00456     const btScalar l=v.length();
00457     if(l>SIMD_EPSILON)
00458         return(v/l);
00459     else
00460         return(btVector3(0,0,0));
00461 }
00462 
00463 //
00464 static inline btDbvtVolume  VolumeOf(   const btSoftBody::Face& f,
00465                                      btScalar margin)
00466 {
00467     const btVector3*    pts[]={ &f.m_n[0]->m_x,
00468         &f.m_n[1]->m_x,
00469         &f.m_n[2]->m_x};
00470     btDbvtVolume        vol=btDbvtVolume::FromPoints(pts,3);
00471     vol.Expand(btVector3(margin,margin,margin));
00472     return(vol);
00473 }
00474 
00475 //
00476 static inline btVector3         CenterOf(   const btSoftBody::Face& f)
00477 {
00478     return((f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3);
00479 }
00480 
00481 //
00482 static inline btScalar          AreaOf(     const btVector3& x0,
00483                                        const btVector3& x1,
00484                                        const btVector3& x2)
00485 {
00486     const btVector3 a=x1-x0;
00487     const btVector3 b=x2-x0;
00488     const btVector3 cr=btCross(a,b);
00489     const btScalar  area=cr.length();
00490     return(area);
00491 }
00492 
00493 //
00494 static inline btScalar      VolumeOf(   const btVector3& x0,
00495                                      const btVector3& x1,
00496                                      const btVector3& x2,
00497                                      const btVector3& x3)
00498 {
00499     const btVector3 a=x1-x0;
00500     const btVector3 b=x2-x0;
00501     const btVector3 c=x3-x0;
00502     return(btDot(a,btCross(b,c)));
00503 }
00504 
00505 //
00506 static void                 EvaluateMedium( const btSoftBodyWorldInfo* wfi,
00507                                            const btVector3& x,
00508                                            btSoftBody::sMedium& medium)
00509 {
00510     medium.m_velocity   =   btVector3(0,0,0);
00511     medium.m_pressure   =   0;
00512     medium.m_density    =   wfi->air_density;
00513     if(wfi->water_density>0)
00514     {
00515         const btScalar  depth=-(btDot(x,wfi->water_normal)+wfi->water_offset);
00516         if(depth>0)
00517         {
00518             medium.m_density    =   wfi->water_density;
00519             medium.m_pressure   =   depth*wfi->water_density*wfi->m_gravity.length();
00520         }
00521     }
00522 }
00523 
00524 //
00525 static inline void          ApplyClampedForce(  btSoftBody::Node& n,
00526                                               const btVector3& f,
00527                                               btScalar dt)
00528 {
00529     const btScalar  dtim=dt*n.m_im;
00530     if((f*dtim).length2()>n.m_v.length2())
00531     {/* Clamp   */ 
00532         n.m_f-=ProjectOnAxis(n.m_v,f.normalized())/dtim;                        
00533     }
00534     else
00535     {/* Apply   */ 
00536         n.m_f+=f;
00537     }
00538 }
00539 
00540 //
00541 static inline int       MatchEdge(  const btSoftBody::Node* a,
00542                                   const btSoftBody::Node* b,
00543                                   const btSoftBody::Node* ma,
00544                                   const btSoftBody::Node* mb)
00545 {
00546     if((a==ma)&&(b==mb)) return(0);
00547     if((a==mb)&&(b==ma)) return(1);
00548     return(-1);
00549 }
00550 
00551 //
00552 // btEigen : Extract eigen system,
00553 // straitforward implementation of http://math.fullerton.edu/mathews/n2003/JacobiMethodMod.html
00554 // outputs are NOT sorted.
00555 //
00556 struct  btEigen
00557 {
00558     static int          system(btMatrix3x3& a,btMatrix3x3* vectors,btVector3* values=0)
00559     {
00560         static const int        maxiterations=16;
00561         static const btScalar   accuracy=(btScalar)0.0001;
00562         btMatrix3x3&            v=*vectors;
00563         int                     iterations=0;
00564         vectors->setIdentity();
00565         do  {
00566             int             p=0,q=1;
00567             if(btFabs(a[p][q])<btFabs(a[0][2])) { p=0;q=2; }
00568             if(btFabs(a[p][q])<btFabs(a[1][2])) { p=1;q=2; }
00569             if(btFabs(a[p][q])>accuracy)
00570             {
00571                 const btScalar  w=(a[q][q]-a[p][p])/(2*a[p][q]);
00572                 const btScalar  z=btFabs(w);
00573                 const btScalar  t=w/(z*(btSqrt(1+w*w)+z));
00574                 if(t==t)/* [WARNING] let hope that one does not get thrown aways by some compilers... */ 
00575                 {
00576                     const btScalar  c=1/btSqrt(t*t+1);
00577                     const btScalar  s=c*t;
00578                     mulPQ(a,c,s,p,q);
00579                     mulTPQ(a,c,s,p,q);
00580                     mulPQ(v,c,s,p,q);
00581                 } else break;
00582             } else break;
00583         } while((++iterations)<maxiterations);
00584         if(values)
00585         {
00586             *values=btVector3(a[0][0],a[1][1],a[2][2]);
00587         }
00588         return(iterations);
00589     }
00590 private:
00591     static inline void  mulTPQ(btMatrix3x3& a,btScalar c,btScalar s,int p,int q)
00592     {
00593         const btScalar  m[2][3]={   {a[p][0],a[p][1],a[p][2]},
00594         {a[q][0],a[q][1],a[q][2]}};
00595         int i;
00596 
00597         for(i=0;i<3;++i) a[p][i]=c*m[0][i]-s*m[1][i];
00598         for(i=0;i<3;++i) a[q][i]=c*m[1][i]+s*m[0][i];
00599     }
00600     static inline void  mulPQ(btMatrix3x3& a,btScalar c,btScalar s,int p,int q)
00601     {
00602         const btScalar  m[2][3]={   {a[0][p],a[1][p],a[2][p]},
00603         {a[0][q],a[1][q],a[2][q]}};
00604         int i;
00605 
00606         for(i=0;i<3;++i) a[i][p]=c*m[0][i]-s*m[1][i];
00607         for(i=0;i<3;++i) a[i][q]=c*m[1][i]+s*m[0][i];
00608     }
00609 };
00610 
00611 //
00612 // Polar decomposition,
00613 // "Computing the Polar Decomposition with Applications", Nicholas J. Higham, 1986.
00614 //
00615 static inline int           PolarDecompose( const btMatrix3x3& m,btMatrix3x3& q,btMatrix3x3& s)
00616 {
00617     static const btScalar   half=(btScalar)0.5;
00618     static const btScalar   accuracy=(btScalar)0.0001;
00619     static const int        maxiterations=16;
00620     int                     i=0;
00621     btScalar                det=0;
00622     q   =   Mul(m,1/btVector3(m[0][0],m[1][1],m[2][2]).length());
00623     det =   q.determinant();
00624     if(!btFuzzyZero(det))
00625     {
00626         for(;i<maxiterations;++i)
00627         {
00628             q=Mul(Add(q,Mul(q.adjoint(),1/det).transpose()),half);
00629             const btScalar  ndet=q.determinant();
00630             if(Sq(ndet-det)>accuracy) det=ndet; else break;
00631         }
00632         /* Final orthogonalization  */ 
00633         Orthogonalize(q);
00634         /* Compute 'S'              */ 
00635         s=q.transpose()*m;
00636     }
00637     else
00638     {
00639         q.setIdentity();
00640         s.setIdentity();
00641     }
00642     return(i);
00643 }
00644 
00645 //
00646 // btSoftColliders
00647 //
00648 struct btSoftColliders
00649 {
00650     //
00651     // ClusterBase
00652     //
00653     struct  ClusterBase : btDbvt::ICollide
00654     {
00655         btScalar            erp;
00656         btScalar            idt;
00657         btScalar            m_margin;
00658         btScalar            friction;
00659         btScalar            threshold;
00660         ClusterBase()
00661         {
00662             erp         =(btScalar)1;
00663             idt         =0;
00664             m_margin        =0;
00665             friction    =0;
00666             threshold   =(btScalar)0;
00667         }
00668         bool                SolveContact(   const btGjkEpaSolver2::sResults& res,
00669             btSoftBody::Body ba,btSoftBody::Body bb,
00670             btSoftBody::CJoint& joint)
00671         {
00672             if(res.distance<m_margin)
00673             {
00674                 btVector3 norm = res.normal;
00675                 norm.normalize();//is it necessary?
00676 
00677                 const btVector3     ra=res.witnesses[0]-ba.xform().getOrigin();
00678                 const btVector3     rb=res.witnesses[1]-bb.xform().getOrigin();
00679                 const btVector3     va=ba.velocity(ra);
00680                 const btVector3     vb=bb.velocity(rb);
00681                 const btVector3     vrel=va-vb;
00682                 const btScalar      rvac=btDot(vrel,norm);
00683                  btScalar       depth=res.distance-m_margin;
00684                 
00685 //              printf("depth=%f\n",depth);
00686                 const btVector3     iv=norm*rvac;
00687                 const btVector3     fv=vrel-iv;
00688                 joint.m_bodies[0]   =   ba;
00689                 joint.m_bodies[1]   =   bb;
00690                 joint.m_refs[0]     =   ra*ba.xform().getBasis();
00691                 joint.m_refs[1]     =   rb*bb.xform().getBasis();
00692                 joint.m_rpos[0]     =   ra;
00693                 joint.m_rpos[1]     =   rb;
00694                 joint.m_cfm         =   1;
00695                 joint.m_erp         =   1;
00696                 joint.m_life        =   0;
00697                 joint.m_maxlife     =   0;
00698                 joint.m_split       =   1;
00699                 
00700                 joint.m_drift       =   depth*norm;
00701 
00702                 joint.m_normal      =   norm;
00703 //              printf("normal=%f,%f,%f\n",res.normal.getX(),res.normal.getY(),res.normal.getZ());
00704                 joint.m_delete      =   false;
00705                 joint.m_friction    =   fv.length2()<(-rvac*friction)?1:friction;
00706                 joint.m_massmatrix  =   ImpulseMatrix(  ba.invMass(),ba.invWorldInertia(),joint.m_rpos[0],
00707                     bb.invMass(),bb.invWorldInertia(),joint.m_rpos[1]);
00708 
00709                 return(true);
00710             }
00711             return(false);
00712         }
00713     };
00714     //
00715     // CollideCL_RS
00716     //
00717     struct  CollideCL_RS : ClusterBase
00718     {
00719         btSoftBody*     psb;
00720         
00721         btCollisionObject*  m_colObj;
00722         void        Process(const btDbvtNode* leaf)
00723         {
00724             btSoftBody::Cluster*        cluster=(btSoftBody::Cluster*)leaf->data;
00725             btSoftClusterCollisionShape cshape(cluster);
00726             
00727             const btConvexShape*        rshape=(const btConvexShape*)m_colObj->getCollisionShape();
00728 
00730             if(m_colObj->isStaticOrKinematicObject() && cluster->m_containsAnchor)
00731                 return;
00732 
00733             btGjkEpaSolver2::sResults   res;        
00734             if(btGjkEpaSolver2::SignedDistance( &cshape,btTransform::getIdentity(),
00735                 rshape,m_colObj->getWorldTransform(),
00736                 btVector3(1,0,0),res))
00737             {
00738                 btSoftBody::CJoint  joint;
00739                 if(SolveContact(res,cluster,m_colObj,joint))//prb,joint))
00740                 {
00741                     btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint();
00742                     *pj=joint;psb->m_joints.push_back(pj);
00743                     if(m_colObj->isStaticOrKinematicObject())
00744                     {
00745                         pj->m_erp   *=  psb->m_cfg.kSKHR_CL;
00746                         pj->m_split *=  psb->m_cfg.kSK_SPLT_CL;
00747                     }
00748                     else
00749                     {
00750                         pj->m_erp   *=  psb->m_cfg.kSRHR_CL;
00751                         pj->m_split *=  psb->m_cfg.kSR_SPLT_CL;
00752                     }
00753                 }
00754             }
00755         }
00756         void        Process(btSoftBody* ps,btCollisionObject* colOb)
00757         {
00758             psb         =   ps;
00759             m_colObj            =   colOb;
00760             idt         =   ps->m_sst.isdt;
00761             m_margin        =   m_colObj->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin();
00763             friction    =   btMin(psb->m_cfg.kDF,m_colObj->getFriction());
00764             btVector3           mins;
00765             btVector3           maxs;
00766 
00767             ATTRIBUTE_ALIGNED16(btDbvtVolume)       volume;
00768             colOb->getCollisionShape()->getAabb(colOb->getWorldTransform(),mins,maxs);
00769             volume=btDbvtVolume::FromMM(mins,maxs);
00770             volume.Expand(btVector3(1,1,1)*m_margin);
00771             ps->m_cdbvt.collideTV(ps->m_cdbvt.m_root,volume,*this);
00772         }   
00773     };
00774     //
00775     // CollideCL_SS
00776     //
00777     struct  CollideCL_SS : ClusterBase
00778     {
00779         btSoftBody* bodies[2];
00780         void        Process(const btDbvtNode* la,const btDbvtNode* lb)
00781         {
00782             btSoftBody::Cluster*        cla=(btSoftBody::Cluster*)la->data;
00783             btSoftBody::Cluster*        clb=(btSoftBody::Cluster*)lb->data;
00784 
00785 
00786             bool connected=false;
00787             if ((bodies[0]==bodies[1])&&(bodies[0]->m_clusterConnectivity.size()))
00788             {
00789                 connected = bodies[0]->m_clusterConnectivity[cla->m_clusterIndex+bodies[0]->m_clusters.size()*clb->m_clusterIndex];
00790             }
00791 
00792             if (!connected)
00793             {
00794                 btSoftClusterCollisionShape csa(cla);
00795                 btSoftClusterCollisionShape csb(clb);
00796                 btGjkEpaSolver2::sResults   res;        
00797                 if(btGjkEpaSolver2::SignedDistance( &csa,btTransform::getIdentity(),
00798                     &csb,btTransform::getIdentity(),
00799                     cla->m_com-clb->m_com,res))
00800                 {
00801                     btSoftBody::CJoint  joint;
00802                     if(SolveContact(res,cla,clb,joint))
00803                     {
00804                         btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint();
00805                         *pj=joint;bodies[0]->m_joints.push_back(pj);
00806                         pj->m_erp   *=  btMax(bodies[0]->m_cfg.kSSHR_CL,bodies[1]->m_cfg.kSSHR_CL);
00807                         pj->m_split *=  (bodies[0]->m_cfg.kSS_SPLT_CL+bodies[1]->m_cfg.kSS_SPLT_CL)/2;
00808                     }
00809                 }
00810             } else
00811             {
00812                 static int count=0;
00813                 count++;
00814                 //printf("count=%d\n",count);
00815                 
00816             }
00817         }
00818         void        Process(btSoftBody* psa,btSoftBody* psb)
00819         {
00820             idt         =   psa->m_sst.isdt;
00821             //m_margin      =   (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2;
00822             m_margin        =   (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin());
00823             friction    =   btMin(psa->m_cfg.kDF,psb->m_cfg.kDF);
00824             bodies[0]   =   psa;
00825             bodies[1]   =   psb;
00826             psa->m_cdbvt.collideTT(psa->m_cdbvt.m_root,psb->m_cdbvt.m_root,*this);
00827         }   
00828     };
00829     //
00830     // CollideSDF_RS
00831     //
00832     struct  CollideSDF_RS : btDbvt::ICollide
00833     {
00834         void        Process(const btDbvtNode* leaf)
00835         {
00836             btSoftBody::Node*   node=(btSoftBody::Node*)leaf->data;
00837             DoNode(*node);
00838         }
00839         void        DoNode(btSoftBody::Node& n) const
00840         {
00841             const btScalar          m=n.m_im>0?dynmargin:stamargin;
00842             btSoftBody::RContact    c;
00843             if( (!n.m_battach)&&
00844                 psb->checkContact(m_colObj1,n.m_x,m,c.m_cti))
00845             {
00846                 const btScalar  ima=n.m_im;
00847                 const btScalar  imb= m_rigidBody? m_rigidBody->getInvMass() : 0.f;
00848                 const btScalar  ms=ima+imb;
00849                 if(ms>0)
00850                 {
00851                     const btTransform&  wtr=m_rigidBody?m_rigidBody->getWorldTransform() : m_colObj1->getWorldTransform();
00852                     static const btMatrix3x3    iwiStatic(0,0,0,0,0,0,0,0,0);
00853                     const btMatrix3x3&  iwi=m_rigidBody?m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
00854                     const btVector3     ra=n.m_x-wtr.getOrigin();
00855                     const btVector3     va=m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra)*psb->m_sst.sdt : btVector3(0,0,0);
00856                     const btVector3     vb=n.m_x-n.m_q; 
00857                     const btVector3     vr=vb-va;
00858                     const btScalar      dn=btDot(vr,c.m_cti.m_normal);
00859                     const btVector3     fv=vr-c.m_cti.m_normal*dn;
00860                     const btScalar      fc=psb->m_cfg.kDF*m_colObj1->getFriction();
00861                     c.m_node    =   &n;
00862                     c.m_c0      =   ImpulseMatrix(psb->m_sst.sdt,ima,imb,iwi,ra);
00863                     c.m_c1      =   ra;
00864                     c.m_c2      =   ima*psb->m_sst.sdt;
00865                     c.m_c3      =   fv.length2()<(btFabs(dn)*fc)?0:1-fc;
00866                     c.m_c4      =   m_colObj1->isStaticOrKinematicObject()?psb->m_cfg.kKHR:psb->m_cfg.kCHR;
00867                     psb->m_rcontacts.push_back(c);
00868                     if (m_rigidBody)
00869                         m_rigidBody->activate();
00870                 }
00871             }
00872         }
00873         btSoftBody*     psb;
00874         btCollisionObject*  m_colObj1;
00875         btRigidBody*    m_rigidBody;
00876         btScalar        dynmargin;
00877         btScalar        stamargin;
00878     };
00879     //
00880     // CollideVF_SS
00881     //
00882     struct  CollideVF_SS : btDbvt::ICollide
00883     {
00884         void        Process(const btDbvtNode* lnode,
00885             const btDbvtNode* lface)
00886         {
00887             btSoftBody::Node*   node=(btSoftBody::Node*)lnode->data;
00888             btSoftBody::Face*   face=(btSoftBody::Face*)lface->data;
00889             btVector3           o=node->m_x;
00890             btVector3           p;
00891             btScalar            d=SIMD_INFINITY;
00892             ProjectOrigin(  face->m_n[0]->m_x-o,
00893                 face->m_n[1]->m_x-o,
00894                 face->m_n[2]->m_x-o,
00895                 p,d);
00896             const btScalar  m=mrg+(o-node->m_q).length()*2;
00897             if(d<(m*m))
00898             {
00899                 const btSoftBody::Node* n[]={face->m_n[0],face->m_n[1],face->m_n[2]};
00900                 const btVector3         w=BaryCoord(n[0]->m_x,n[1]->m_x,n[2]->m_x,p+o);
00901                 const btScalar          ma=node->m_im;
00902                 btScalar                mb=BaryEval(n[0]->m_im,n[1]->m_im,n[2]->m_im,w);
00903                 if( (n[0]->m_im<=0)||
00904                     (n[1]->m_im<=0)||
00905                     (n[2]->m_im<=0))
00906                 {
00907                     mb=0;
00908                 }
00909                 const btScalar  ms=ma+mb;
00910                 if(ms>0)
00911                 {
00912                     btSoftBody::SContact    c;
00913                     c.m_normal      =   p/-btSqrt(d);
00914                     c.m_margin      =   m;
00915                     c.m_node        =   node;
00916                     c.m_face        =   face;
00917                     c.m_weights     =   w;
00918                     c.m_friction    =   btMax(psb[0]->m_cfg.kDF,psb[1]->m_cfg.kDF);
00919                     c.m_cfm[0]      =   ma/ms*psb[0]->m_cfg.kSHR;
00920                     c.m_cfm[1]      =   mb/ms*psb[1]->m_cfg.kSHR;
00921                     psb[0]->m_scontacts.push_back(c);
00922                 }
00923             }   
00924         }
00925         btSoftBody*     psb[2];
00926         btScalar        mrg;
00927     };
00928 };
00929 
00930 #endif //_BT_SOFT_BODY_INTERNALS_H