Blender V2.61 - r43446
|
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