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 is usually identity, except when colliding against btCompoundShape. See Issue 512 */
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


bullet
Author(s): Erwin Coumans, ROS package maintained by Tully Foote
autogenerated on Wed Oct 31 2012 07:54:31