btSoftBodyHelpers.cpp

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 #include "btSoftBodyInternals.h"
00018 #include <stdio.h>
00019 #include <string.h>
00020 #include "btSoftBodyHelpers.h"
00021 #include "LinearMath/btConvexHull.h"
00022 
00023 //
00024 static void                             drawVertex(     btIDebugDraw* idraw,
00025                                                                    const btVector3& x,btScalar s,const btVector3& c)
00026 {
00027         idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c);
00028         idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c);
00029         idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c);
00030 }
00031 
00032 //
00033 static void                             drawBox(        btIDebugDraw* idraw,
00034                                                                 const btVector3& mins,
00035                                                                 const btVector3& maxs,
00036                                                                 const btVector3& color)
00037 {
00038         const btVector3 c[]={   btVector3(mins.x(),mins.y(),mins.z()),
00039                 btVector3(maxs.x(),mins.y(),mins.z()),
00040                 btVector3(maxs.x(),maxs.y(),mins.z()),
00041                 btVector3(mins.x(),maxs.y(),mins.z()),
00042                 btVector3(mins.x(),mins.y(),maxs.z()),
00043                 btVector3(maxs.x(),mins.y(),maxs.z()),
00044                 btVector3(maxs.x(),maxs.y(),maxs.z()),
00045                 btVector3(mins.x(),maxs.y(),maxs.z())};
00046         idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color);
00047         idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color);
00048         idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color);
00049         idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color);
00050         idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color);
00051         idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color);
00052 }
00053 
00054 //
00055 static void                             drawTree(       btIDebugDraw* idraw,
00056                                                                  const btDbvtNode* node,
00057                                                                  int depth,
00058                                                                  const btVector3& ncolor,
00059                                                                  const btVector3& lcolor,
00060                                                                  int mindepth,
00061                                                                  int maxdepth)
00062 {
00063         if(node)
00064         {
00065                 if(node->isinternal()&&((depth<maxdepth)||(maxdepth<0)))
00066                 {
00067                         drawTree(idraw,node->childs[0],depth+1,ncolor,lcolor,mindepth,maxdepth);
00068                         drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth);
00069                 }
00070                 if(depth>=mindepth)
00071                 {
00072                         const btScalar  scl=(btScalar)(node->isinternal()?1:1);
00073                         const btVector3 mi=node->volume.Center()-node->volume.Extents()*scl;
00074                         const btVector3 mx=node->volume.Center()+node->volume.Extents()*scl;
00075                         drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor);
00076                 }
00077         }
00078 }
00079 
00080 //
00081 template <typename T>
00082 static inline T                         sum(const btAlignedObjectArray<T>& items)
00083 {
00084         T       v;
00085         if(items.size())
00086         {
00087                 v=items[0];
00088                 for(int i=1,ni=items.size();i<ni;++i)
00089                 {
00090                         v+=items[i];
00091                 }
00092         }
00093         return(v);
00094 }
00095 
00096 //
00097 template <typename T,typename Q>
00098 static inline void                      add(btAlignedObjectArray<T>& items,const Q& value)
00099 {
00100         for(int i=0,ni=items.size();i<ni;++i)
00101         {
00102                 items[i]+=value;
00103         }
00104 }
00105 
00106 //
00107 template <typename T,typename Q>
00108 static inline void                      mul(btAlignedObjectArray<T>& items,const Q& value)
00109 {
00110         for(int i=0,ni=items.size();i<ni;++i)
00111         {
00112                 items[i]*=value;
00113         }
00114 }
00115 
00116 //
00117 template <typename T>
00118 static inline T                         average(const btAlignedObjectArray<T>& items)
00119 {
00120         const btScalar  n=(btScalar)(items.size()>0?items.size():1);
00121         return(sum(items)/n);
00122 }
00123 
00124 //
00125 static inline btScalar          tetravolume(const btVector3& x0,
00126                                                                                 const btVector3& x1,
00127                                                                                 const btVector3& x2,
00128                                                                                 const btVector3& x3)
00129 {
00130         const btVector3 a=x1-x0;
00131         const btVector3 b=x2-x0;
00132         const btVector3 c=x3-x0;
00133         return(btDot(a,btCross(b,c)));
00134 }
00135 
00136 //
00137 #if 0
00138 static btVector3                stresscolor(btScalar stress)
00139 {
00140         static const btVector3  spectrum[]=     {       btVector3(1,0,1),
00141                 btVector3(0,0,1),
00142                 btVector3(0,1,1),
00143                 btVector3(0,1,0),
00144                 btVector3(1,1,0),
00145                 btVector3(1,0,0),
00146                 btVector3(1,0,0)};
00147         static const int                ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1;
00148         static const btScalar   one=1;
00149         stress=btMax<btScalar>(0,btMin<btScalar>(1,stress))*ncolors;
00150         const int                               sel=(int)stress;
00151         const btScalar                  frc=stress-sel;
00152         return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc);
00153 }
00154 #endif
00155 
00156 //
00157 void                    btSoftBodyHelpers::Draw(        btSoftBody* psb,
00158                                                                                 btIDebugDraw* idraw,
00159                                                                                 int drawflags)
00160 {
00161         const btScalar          scl=(btScalar)0.1;
00162         const btScalar          nscl=scl*5;
00163         const btVector3         lcolor=btVector3(0,0,0);
00164         const btVector3         ncolor=btVector3(1,1,1);
00165         const btVector3         ccolor=btVector3(1,0,0);
00166         int i,j,nj;
00167 
00168         /* Nodes        */ 
00169         if(0!=(drawflags&fDrawFlags::Nodes))
00170         {
00171                 for(i=0;i<psb->m_nodes.size();++i)
00172                 {
00173                         const btSoftBody::Node& n=psb->m_nodes[i];
00174                         if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
00175                         idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0));
00176                         idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0));
00177                         idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1));
00178                 }
00179         }
00180         /* Links        */ 
00181         if(0!=(drawflags&fDrawFlags::Links))
00182         {
00183                 for(i=0;i<psb->m_links.size();++i)
00184                 {
00185                         const btSoftBody::Link& l=psb->m_links[i];
00186                         if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
00187                         idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor);
00188                 }
00189         }
00190         /* Normals      */ 
00191         if(0!=(drawflags&fDrawFlags::Normals))
00192         {
00193                 for(i=0;i<psb->m_nodes.size();++i)
00194                 {
00195                         const btSoftBody::Node& n=psb->m_nodes[i];
00196                         if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
00197                         const btVector3                 d=n.m_n*nscl;
00198                         idraw->drawLine(n.m_x,n.m_x+d,ncolor);
00199                         idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5);
00200                 }
00201         }
00202         /* Contacts     */ 
00203         if(0!=(drawflags&fDrawFlags::Contacts))
00204         {
00205                 static const btVector3          axis[]={btVector3(1,0,0),
00206                         btVector3(0,1,0),
00207                         btVector3(0,0,1)};
00208                 for(i=0;i<psb->m_rcontacts.size();++i)
00209                 {               
00210                         const btSoftBody::RContact&     c=psb->m_rcontacts[i];
00211                         const btVector3                         o=      c.m_node->m_x-c.m_cti.m_normal*
00212                                 (btDot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset);
00213                         const btVector3                         x=btCross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized();
00214                         const btVector3                         y=btCross(x,c.m_cti.m_normal).normalized();
00215                         idraw->drawLine(o-x*nscl,o+x*nscl,ccolor);
00216                         idraw->drawLine(o-y*nscl,o+y*nscl,ccolor);
00217                         idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0));
00218                 }
00219         }
00220         /* Anchors      */ 
00221         if(0!=(drawflags&fDrawFlags::Anchors))
00222         {
00223                 for(i=0;i<psb->m_anchors.size();++i)
00224                 {
00225                         const btSoftBody::Anchor&       a=psb->m_anchors[i];
00226                         const btVector3                         q=a.m_body->getWorldTransform()*a.m_local;
00227                         drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0));
00228                         drawVertex(idraw,q,0.25,btVector3(0,1,0));
00229                         idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1));
00230                 }
00231                 for(i=0;i<psb->m_nodes.size();++i)
00232                 {
00233                         const btSoftBody::Node& n=psb->m_nodes[i];              
00234                         if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
00235                         if(n.m_im<=0)
00236                         {
00237                                 drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0));
00238                         }
00239                 }
00240         }
00241         /* Faces        */ 
00242         if(0!=(drawflags&fDrawFlags::Faces))
00243         {
00244                 const btScalar  scl=(btScalar)0.8;
00245                 const btScalar  alp=(btScalar)1;
00246                 const btVector3 col(0,(btScalar)0.7,0);
00247                 for(i=0;i<psb->m_faces.size();++i)
00248                 {
00249                         const btSoftBody::Face& f=psb->m_faces[i];
00250                         if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
00251                         const btVector3                 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x};
00252                         const btVector3                 c=(x[0]+x[1]+x[2])/3;
00253                         idraw->drawTriangle((x[0]-c)*scl+c,
00254                                 (x[1]-c)*scl+c,
00255                                 (x[2]-c)*scl+c,
00256                                 col,alp);
00257                 }       
00258         }
00259         /* Clusters     */ 
00260         if(0!=(drawflags&fDrawFlags::Clusters))
00261         {
00262                 srand(1806);
00263                 for(i=0;i<psb->m_clusters.size();++i)
00264                 {
00265                         if(psb->m_clusters[i]->m_collide)
00266                         {
00267                                 btVector3                                               color(  rand()/(btScalar)RAND_MAX,
00268                                         rand()/(btScalar)RAND_MAX,
00269                                         rand()/(btScalar)RAND_MAX);
00270                                 color=color.normalized()*0.75;
00271                                 btAlignedObjectArray<btVector3> vertices;
00272                                 vertices.resize(psb->m_clusters[i]->m_nodes.size());
00273                                 for(j=0,nj=vertices.size();j<nj;++j)
00274                                 {                               
00275                                         vertices[j]=psb->m_clusters[i]->m_nodes[j]->m_x;
00276                                 }
00277                                 HullDesc                hdsc(QF_TRIANGLES,vertices.size(),&vertices[0]);
00278                                 HullResult              hres;
00279                                 HullLibrary             hlib;
00280                                 hdsc.mMaxVertices=vertices.size();
00281                                 hlib.CreateConvexHull(hdsc,hres);
00282                                 const btVector3 center=average(hres.m_OutputVertices);
00283                                 add(hres.m_OutputVertices,-center);
00284                                 mul(hres.m_OutputVertices,(btScalar)1);
00285                                 add(hres.m_OutputVertices,center);
00286                                 for(j=0;j<(int)hres.mNumFaces;++j)
00287                                 {
00288                                         const int idx[]={hres.m_Indices[j*3+0],hres.m_Indices[j*3+1],hres.m_Indices[j*3+2]};
00289                                         idraw->drawTriangle(hres.m_OutputVertices[idx[0]],
00290                                                 hres.m_OutputVertices[idx[1]],
00291                                                 hres.m_OutputVertices[idx[2]],
00292                                                 color,1);
00293                                 }
00294                                 hlib.ReleaseResult(hres);
00295                         }
00296                         /* Velocities   */ 
00297 #if 0
00298                         for(int j=0;j<psb->m_clusters[i].m_nodes.size();++j)
00299                         {
00300                                 const btSoftBody::Cluster&      c=psb->m_clusters[i];
00301                                 const btVector3                         r=c.m_nodes[j]->m_x-c.m_com;
00302                                 const btVector3                         v=c.m_lv+btCross(c.m_av,r);
00303                                 idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0));
00304                         }
00305 #endif
00306                         /* Frame                */ 
00307                         btSoftBody::Cluster& c=*psb->m_clusters[i];
00308                         idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0));
00309                         idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0));
00310                         idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1));
00311                 }
00312         }
00313 
00314         /* Tetras       */ 
00315         if(0!=(drawflags&fDrawFlags::Tetras))
00316         {
00317                 const btScalar  scl=(btScalar)0.8;
00318                 const btScalar  alp=(btScalar)1;
00319                 const btVector3 col((btScalar)0.7,(btScalar)0.7,(btScalar)0.7);
00320                 for(int i=0;i<psb->m_tetras.size();++i)
00321                 {
00322                         const btSoftBody::Tetra&        t=psb->m_tetras[i];
00323                         if(0==(t.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
00324                         const btVector3                         x[]={t.m_n[0]->m_x,t.m_n[1]->m_x,t.m_n[2]->m_x,t.m_n[3]->m_x};
00325                         const btVector3                         c=(x[0]+x[1]+x[2]+x[3])/4;
00326                         idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[2]-c)*scl+c,col,alp);
00327                         idraw->drawTriangle((x[0]-c)*scl+c,(x[1]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
00328                         idraw->drawTriangle((x[1]-c)*scl+c,(x[2]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
00329                         idraw->drawTriangle((x[2]-c)*scl+c,(x[0]-c)*scl+c,(x[3]-c)*scl+c,col,alp);
00330                 }       
00331         }
00332 
00333         /* Notes        */ 
00334         if(0!=(drawflags&fDrawFlags::Notes))
00335         {
00336                 for(i=0;i<psb->m_notes.size();++i)
00337                 {
00338                         const btSoftBody::Note& n=psb->m_notes[i];
00339                         btVector3                               p=n.m_offset;
00340                         for(int j=0;j<n.m_rank;++j)
00341                         {
00342                                 p+=n.m_nodes[j]->m_x*n.m_coords[j];
00343                         }
00344                         idraw->draw3dText(p,n.m_text);
00345                 }
00346         }
00347         /* Node tree    */ 
00348         if(0!=(drawflags&fDrawFlags::NodeTree))         DrawNodeTree(psb,idraw);
00349         /* Face tree    */ 
00350         if(0!=(drawflags&fDrawFlags::FaceTree))         DrawFaceTree(psb,idraw);
00351         /* Cluster tree */ 
00352         if(0!=(drawflags&fDrawFlags::ClusterTree))      DrawClusterTree(psb,idraw);
00353         /* Joints               */ 
00354         if(0!=(drawflags&fDrawFlags::Joints))
00355         {
00356                 for(i=0;i<psb->m_joints.size();++i)
00357                 {
00358                         const btSoftBody::Joint*        pj=psb->m_joints[i];
00359                         switch(pj->Type())
00360                         {
00361                         case    btSoftBody::Joint::eType::Linear:
00362                                 {
00363                                         const btSoftBody::LJoint*       pjl=(const btSoftBody::LJoint*)pj;
00364                                         const btVector3 a0=pj->m_bodies[0].xform()*pjl->m_refs[0];
00365                                         const btVector3 a1=pj->m_bodies[1].xform()*pjl->m_refs[1];
00366                                         idraw->drawLine(pj->m_bodies[0].xform().getOrigin(),a0,btVector3(1,1,0));
00367                                         idraw->drawLine(pj->m_bodies[1].xform().getOrigin(),a1,btVector3(0,1,1));
00368                                         drawVertex(idraw,a0,0.25,btVector3(1,1,0));
00369                                         drawVertex(idraw,a1,0.25,btVector3(0,1,1));
00370                                 }
00371                                 break;
00372                         case    btSoftBody::Joint::eType::Angular:
00373                                 {
00374                                         //const btSoftBody::AJoint*     pja=(const btSoftBody::AJoint*)pj;
00375                                         const btVector3 o0=pj->m_bodies[0].xform().getOrigin();
00376                                         const btVector3 o1=pj->m_bodies[1].xform().getOrigin();
00377                                         const btVector3 a0=pj->m_bodies[0].xform().getBasis()*pj->m_refs[0];
00378                                         const btVector3 a1=pj->m_bodies[1].xform().getBasis()*pj->m_refs[1];
00379                                         idraw->drawLine(o0,o0+a0*10,btVector3(1,1,0));
00380                                         idraw->drawLine(o0,o0+a1*10,btVector3(1,1,0));
00381                                         idraw->drawLine(o1,o1+a0*10,btVector3(0,1,1));
00382                                         idraw->drawLine(o1,o1+a1*10,btVector3(0,1,1));
00383                                         break;
00384                                 }
00385                                 default:
00386                                 {
00387                                 }
00388                                         
00389                         }               
00390                 }
00391         }
00392 }
00393 
00394 //
00395 void                    btSoftBodyHelpers::DrawInfos(           btSoftBody* psb,
00396                                                                                          btIDebugDraw* idraw,
00397                                                                                          bool masses,
00398                                                                                          bool areas,
00399                                                                                          bool /*stress*/)
00400 {
00401         for(int i=0;i<psb->m_nodes.size();++i)
00402         {
00403                 const btSoftBody::Node& n=psb->m_nodes[i];
00404                 char                                    text[2048]={0};
00405                 char                                    buff[1024];
00406                 if(masses)
00407                 {
00408                         sprintf(buff," M(%.2f)",1/n.m_im);
00409                         strcat(text,buff);
00410                 }
00411                 if(areas)
00412                 {
00413                         sprintf(buff," A(%.2f)",n.m_area);
00414                         strcat(text,buff);
00415                 }
00416                 if(text[0]) idraw->draw3dText(n.m_x,text);
00417         }
00418 }
00419 
00420 //
00421 void                    btSoftBodyHelpers::DrawNodeTree(        btSoftBody* psb,
00422                                                                                                 btIDebugDraw* idraw,
00423                                                                                                 int mindepth,
00424                                                                                                 int maxdepth)
00425 {
00426         drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth);
00427 }
00428 
00429 //
00430 void                    btSoftBodyHelpers::DrawFaceTree(        btSoftBody* psb,
00431                                                                                                 btIDebugDraw* idraw,
00432                                                                                                 int mindepth,
00433                                                                                                 int maxdepth)
00434 {
00435         drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth);
00436 }
00437 
00438 //
00439 void                    btSoftBodyHelpers::DrawClusterTree(     btSoftBody* psb,
00440                                                                                                    btIDebugDraw* idraw,
00441                                                                                                    int mindepth,
00442                                                                                                    int maxdepth)
00443 {
00444         drawTree(idraw,psb->m_cdbvt.m_root,0,btVector3(0,1,1),btVector3(1,0,0),mindepth,maxdepth);
00445 }
00446 
00447 //
00448 void                    btSoftBodyHelpers::DrawFrame(           btSoftBody* psb,
00449                                                                                          btIDebugDraw* idraw)
00450 {
00451         if(psb->m_pose.m_bframe)
00452         {
00453                 static const btScalar   ascl=10;
00454                 static const btScalar   nscl=(btScalar)0.1;
00455                 const btVector3                 com=psb->m_pose.m_com;
00456                 const btMatrix3x3               trs=psb->m_pose.m_rot*psb->m_pose.m_scl;
00457                 const btVector3                 Xaxis=(trs*btVector3(1,0,0)).normalized();
00458                 const btVector3                 Yaxis=(trs*btVector3(0,1,0)).normalized();
00459                 const btVector3                 Zaxis=(trs*btVector3(0,0,1)).normalized();
00460                 idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0));
00461                 idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0));
00462                 idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1));
00463                 for(int i=0;i<psb->m_pose.m_pos.size();++i)
00464                 {
00465                         const btVector3 x=com+trs*psb->m_pose.m_pos[i];
00466                         drawVertex(idraw,x,nscl,btVector3(1,0,1));
00467                 }
00468         }
00469 }
00470 
00471 //
00472 btSoftBody*             btSoftBodyHelpers::CreateRope(  btSoftBodyWorldInfo& worldInfo, const btVector3& from,
00473                                                                                           const btVector3& to,
00474                                                                                           int res,
00475                                                                                           int fixeds)
00476 {
00477         /* Create nodes */ 
00478         const int               r=res+2;
00479         btVector3*              x=new btVector3[r];
00480         btScalar*               m=new btScalar[r];
00481         int i;
00482 
00483         for(i=0;i<r;++i)
00484         {
00485                 const btScalar  t=i/(btScalar)(r-1);
00486                 x[i]=lerp(from,to,t);
00487                 m[i]=1;
00488         }
00489         btSoftBody*             psb= new btSoftBody(&worldInfo,r,x,m);
00490         if(fixeds&1) psb->setMass(0,0);
00491         if(fixeds&2) psb->setMass(r-1,0);
00492         delete[] x;
00493         delete[] m;
00494         /* Create links */ 
00495         for(i=1;i<r;++i)
00496         {
00497                 psb->appendLink(i-1,i);
00498         }
00499         /* Finished             */ 
00500         return(psb);
00501 }
00502 
00503 //
00504 btSoftBody*             btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo,const btVector3& corner00,
00505                                                                                            const btVector3& corner10,
00506                                                                                            const btVector3& corner01,
00507                                                                                            const btVector3& corner11,
00508                                                                                            int resx,
00509                                                                                            int resy,
00510                                                                                            int fixeds,
00511                                                                                            bool gendiags)
00512 {
00513 #define IDX(_x_,_y_)    ((_y_)*rx+(_x_))
00514         /* Create nodes */ 
00515         if((resx<2)||(resy<2)) return(0);
00516         const int       rx=resx;
00517         const int       ry=resy;
00518         const int       tot=rx*ry;
00519         btVector3*      x=new btVector3[tot];
00520         btScalar*       m=new btScalar[tot];
00521         int iy;
00522 
00523         for(iy=0;iy<ry;++iy)
00524         {
00525                 const btScalar  ty=iy/(btScalar)(ry-1);
00526                 const btVector3 py0=lerp(corner00,corner01,ty);
00527                 const btVector3 py1=lerp(corner10,corner11,ty);
00528                 for(int ix=0;ix<rx;++ix)
00529                 {
00530                         const btScalar  tx=ix/(btScalar)(rx-1);
00531                         x[IDX(ix,iy)]=lerp(py0,py1,tx);
00532                         m[IDX(ix,iy)]=1;
00533                 }
00534         }
00535         btSoftBody*             psb=new btSoftBody(&worldInfo,tot,x,m);
00536         if(fixeds&1)    psb->setMass(IDX(0,0),0);
00537         if(fixeds&2)    psb->setMass(IDX(rx-1,0),0);
00538         if(fixeds&4)    psb->setMass(IDX(0,ry-1),0);
00539         if(fixeds&8)    psb->setMass(IDX(rx-1,ry-1),0);
00540         delete[] x;
00541         delete[] m;
00542         /* Create links and faces */ 
00543         for(iy=0;iy<ry;++iy)
00544         {
00545                 for(int ix=0;ix<rx;++ix)
00546                 {
00547                         const int       idx=IDX(ix,iy);
00548                         const bool      mdx=(ix+1)<rx;
00549                         const bool      mdy=(iy+1)<ry;
00550                         if(mdx) psb->appendLink(idx,IDX(ix+1,iy));
00551                         if(mdy) psb->appendLink(idx,IDX(ix,iy+1));
00552                         if(mdx&&mdy)
00553                         {
00554                                 if((ix+iy)&1)
00555                                 {
00556                                         psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1));
00557                                         psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1));
00558                                         if(gendiags)
00559                                         {
00560                                                 psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1));
00561                                         }
00562                                 }
00563                                 else
00564                                 {
00565                                         psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy));
00566                                         psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1));
00567                                         if(gendiags)
00568                                         {
00569                                                 psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1));
00570                                         }
00571                                 }
00572                         }
00573                 }
00574         }
00575         /* Finished             */ 
00576 #undef IDX
00577         return(psb);
00578 }
00579 
00580 //
00581 btSoftBody*             btSoftBodyHelpers::CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
00582                                                                                                  const btVector3& corner00,
00583                                                                                                  const btVector3& corner10,
00584                                                                                                  const btVector3& corner01,
00585                                                                                                  const btVector3& corner11,
00586                                                                                                  int resx,
00587                                                                                                  int resy,
00588                                                                                                  int fixeds,
00589                                                                                                  bool gendiags,
00590                                                                                                  float* tex_coords)
00591 {
00592 
00593         /*
00594         *
00595         *  corners:
00596         *
00597         *  [0][0]     corner00 ------- corner01   [resx][0]
00598         *                |                |
00599         *                |                |
00600         *  [0][resy]  corner10 -------- corner11  [resx][resy]
00601         *
00602         *
00603         *
00604         *
00605         *
00606         *
00607         *   "fixedgs" map:
00608         *
00609         *  corner00     -->   +1
00610         *  corner01     -->   +2
00611         *  corner10     -->   +4
00612         *  corner11     -->   +8
00613         *  upper middle -->  +16
00614         *  left middle  -->  +32
00615         *  right middle -->  +64
00616         *  lower middle --> +128
00617         *  center       --> +256
00618         *
00619         *
00620         *   tex_coords size   (resx-1)*(resy-1)*12
00621         *
00622         *
00623         *
00624         *     SINGLE QUAD INTERNALS
00625         *
00626         *  1) btSoftBody's nodes and links,
00627         *     diagonal link is optional ("gendiags")
00628         *
00629         *
00630         *    node00 ------ node01
00631         *      | .              
00632         *      |   .            
00633         *      |     .          
00634         *      |       .        
00635         *      |         .      
00636         *    node10        node11
00637         *
00638         *
00639         *
00640         *   2) Faces:
00641         *      two triangles,
00642         *      UV Coordinates (hier example for single quad)
00643         *      
00644         *     (0,1)          (0,1)  (1,1)
00645         *     1 |\            3 \-----| 2
00646         *       | \              \    |
00647         *       |  \              \   |
00648         *       |   \              \  |
00649         *       |    \              \ |
00650         *     2 |-----\ 3            \| 1
00651         *     (0,0)    (1,0)       (1,0)
00652         *
00653         *
00654         *
00655         *
00656         *
00657         *
00658         */
00659 
00660 #define IDX(_x_,_y_)    ((_y_)*rx+(_x_))
00661         /* Create nodes         */ 
00662         if((resx<2)||(resy<2)) return(0);
00663         const int       rx=resx;
00664         const int       ry=resy;
00665         const int       tot=rx*ry;
00666         btVector3*      x=new btVector3[tot];
00667         btScalar*       m=new btScalar[tot];
00668 
00669         int iy;
00670 
00671         for(iy=0;iy<ry;++iy)
00672         {
00673                 const btScalar  ty=iy/(btScalar)(ry-1);
00674                 const btVector3 py0=lerp(corner00,corner01,ty);
00675                 const btVector3 py1=lerp(corner10,corner11,ty);
00676                 for(int ix=0;ix<rx;++ix)
00677                 {
00678                         const btScalar  tx=ix/(btScalar)(rx-1);
00679                         x[IDX(ix,iy)]=lerp(py0,py1,tx);
00680                         m[IDX(ix,iy)]=1;
00681                 }
00682         }
00683         btSoftBody*     psb=new btSoftBody(&worldInfo,tot,x,m);
00684         if(fixeds&1)            psb->setMass(IDX(0,0),0);
00685         if(fixeds&2)            psb->setMass(IDX(rx-1,0),0);
00686         if(fixeds&4)            psb->setMass(IDX(0,ry-1),0);
00687         if(fixeds&8)            psb->setMass(IDX(rx-1,ry-1),0);
00688         if(fixeds&16)           psb->setMass(IDX((rx-1)/2,0),0);
00689         if(fixeds&32)           psb->setMass(IDX(0,(ry-1)/2),0);
00690         if(fixeds&64)           psb->setMass(IDX(rx-1,(ry-1)/2),0);
00691         if(fixeds&128)          psb->setMass(IDX((rx-1)/2,ry-1),0);
00692         if(fixeds&256)          psb->setMass(IDX((rx-1)/2,(ry-1)/2),0);
00693         delete[] x;
00694         delete[] m;
00695 
00696 
00697         int z = 0;
00698         /* Create links and faces       */ 
00699         for(iy=0;iy<ry;++iy)
00700         {
00701                 for(int ix=0;ix<rx;++ix)
00702                 {
00703                         const bool      mdx=(ix+1)<rx;
00704                         const bool      mdy=(iy+1)<ry;
00705 
00706                         int node00=IDX(ix,iy);
00707                         int node01=IDX(ix+1,iy);
00708                         int node10=IDX(ix,iy+1);
00709                         int node11=IDX(ix+1,iy+1);
00710 
00711                         if(mdx) psb->appendLink(node00,node01);
00712                         if(mdy) psb->appendLink(node00,node10);
00713                         if(mdx&&mdy)
00714                         {
00715                                 psb->appendFace(node00,node10,node11);
00716                                 if (tex_coords) {
00717                                         tex_coords[z+0]=CalculateUV(resx,resy,ix,iy,0);
00718                                         tex_coords[z+1]=CalculateUV(resx,resy,ix,iy,1);
00719                                         tex_coords[z+2]=CalculateUV(resx,resy,ix,iy,0);
00720                                         tex_coords[z+3]=CalculateUV(resx,resy,ix,iy,2);
00721                                         tex_coords[z+4]=CalculateUV(resx,resy,ix,iy,3);
00722                                         tex_coords[z+5]=CalculateUV(resx,resy,ix,iy,2);
00723                                 }
00724                                 psb->appendFace(node11,node01,node00);
00725                                 if (tex_coords) {
00726                                         tex_coords[z+6 ]=CalculateUV(resx,resy,ix,iy,3);
00727                                         tex_coords[z+7 ]=CalculateUV(resx,resy,ix,iy,2);
00728                                         tex_coords[z+8 ]=CalculateUV(resx,resy,ix,iy,3);
00729                                         tex_coords[z+9 ]=CalculateUV(resx,resy,ix,iy,1);
00730                                         tex_coords[z+10]=CalculateUV(resx,resy,ix,iy,0);
00731                                         tex_coords[z+11]=CalculateUV(resx,resy,ix,iy,1);
00732                                 }
00733                                 if (gendiags) psb->appendLink(node00,node11);
00734                                 z += 12;
00735                         }
00736                 }
00737         }
00738         /* Finished     */ 
00739 #undef IDX
00740         return(psb);
00741 }
00742 
00743 float   btSoftBodyHelpers::CalculateUV(int resx,int resy,int ix,int iy,int id)
00744 {
00745 
00746         /*
00747         *
00748         *
00749         *    node00 --- node01
00750         *      |          |
00751         *    node10 --- node11
00752         *
00753         *
00754         *   ID map:
00755         *
00756         *   node00 s --> 0
00757         *   node00 t --> 1
00758         *
00759         *   node01 s --> 3
00760         *   node01 t --> 1
00761         *
00762         *   node10 s --> 0
00763         *   node10 t --> 2
00764         *
00765         *   node11 s --> 3
00766         *   node11 t --> 2
00767         *
00768         *
00769         */
00770 
00771         float tc=0.0f;
00772         if (id == 0) {
00773                 tc = (1.0f/((resx-1))*ix);
00774         }
00775         else if (id==1) {
00776                 tc = (1.0f/((resy-1))*(resy-1-iy));
00777         }
00778         else if (id==2) {
00779                 tc = (1.0f/((resy-1))*(resy-1-iy-1));
00780         }
00781         else if (id==3) {
00782                 tc = (1.0f/((resx-1))*(ix+1));
00783         }
00784         return tc;
00785 }
00786 //
00787 btSoftBody*             btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,const btVector3& center,
00788                                                                                                    const btVector3& radius,
00789                                                                                                    int res)
00790 {
00791         struct  Hammersley
00792         {
00793                 static void     Generate(btVector3* x,int n)
00794                 {
00795                         for(int i=0;i<n;i++)
00796                         {
00797                                 btScalar        p=0.5,t=0;
00798                                 for(int j=i;j;p*=0.5,j>>=1) if(j&1) t+=p;
00799                                 btScalar        w=2*t-1;
00800                                 btScalar        a=(SIMD_PI+2*i*SIMD_PI)/n;
00801                                 btScalar        s=btSqrt(1-w*w);
00802                                 *x++=btVector3(s*btCos(a),s*btSin(a),w);
00803                         }
00804                 }
00805         };
00806         btAlignedObjectArray<btVector3> vtx;
00807         vtx.resize(3+res);
00808         Hammersley::Generate(&vtx[0],vtx.size());
00809         for(int i=0;i<vtx.size();++i)
00810         {
00811                 vtx[i]=vtx[i]*radius+center;
00812         }
00813         return(CreateFromConvexHull(worldInfo,&vtx[0],vtx.size()));
00814 }
00815 
00816 
00817 
00818 //
00819 btSoftBody*             btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo,const btScalar*     vertices,
00820                                                                                                          const int* triangles,
00821                                                                                                          int ntriangles, bool randomizeConstraints)
00822 {
00823         int             maxidx=0;
00824         int i,j,ni;
00825 
00826         for(i=0,ni=ntriangles*3;i<ni;++i)
00827         {
00828                 maxidx=btMax(triangles[i],maxidx);
00829         }
00830         ++maxidx;
00831         btAlignedObjectArray<bool>              chks;
00832         btAlignedObjectArray<btVector3> vtx;
00833         chks.resize(maxidx*maxidx,false);
00834         vtx.resize(maxidx);
00835         for(i=0,j=0,ni=maxidx*3;i<ni;++j,i+=3)
00836         {
00837                 vtx[j]=btVector3(vertices[i],vertices[i+1],vertices[i+2]);
00838         }
00839         btSoftBody*             psb=new btSoftBody(&worldInfo,vtx.size(),&vtx[0],0);
00840         for( i=0,ni=ntriangles*3;i<ni;i+=3)
00841         {
00842                 const int idx[]={triangles[i],triangles[i+1],triangles[i+2]};
00843 #define IDX(_x_,_y_) ((_y_)*maxidx+(_x_))
00844                 for(int j=2,k=0;k<3;j=k++)
00845                 {
00846                         if(!chks[IDX(idx[j],idx[k])])
00847                         {
00848                                 chks[IDX(idx[j],idx[k])]=true;
00849                                 chks[IDX(idx[k],idx[j])]=true;
00850                                 psb->appendLink(idx[j],idx[k]);
00851                         }
00852                 }
00853 #undef IDX
00854                 psb->appendFace(idx[0],idx[1],idx[2]);
00855         }
00856 
00857         if (randomizeConstraints)
00858         {
00859                 psb->randomizeConstraints();
00860         }
00861 
00862         return(psb);
00863 }
00864 
00865 //
00866 btSoftBody*             btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
00867                                                                                                                 int nvertices, bool randomizeConstraints)
00868 {
00869         HullDesc                hdsc(QF_TRIANGLES,nvertices,vertices);
00870         HullResult              hres;
00871         HullLibrary             hlib;/*??*/ 
00872         hdsc.mMaxVertices=nvertices;
00873         hlib.CreateConvexHull(hdsc,hres);
00874         btSoftBody*             psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices,
00875                 &hres.m_OutputVertices[0],0);
00876         for(int i=0;i<(int)hres.mNumFaces;++i)
00877         {
00878                 const int idx[]={       hres.m_Indices[i*3+0],
00879                         hres.m_Indices[i*3+1],
00880                         hres.m_Indices[i*3+2]};
00881                 if(idx[0]<idx[1]) psb->appendLink(      idx[0],idx[1]);
00882                 if(idx[1]<idx[2]) psb->appendLink(      idx[1],idx[2]);
00883                 if(idx[2]<idx[0]) psb->appendLink(      idx[2],idx[0]);
00884                 psb->appendFace(idx[0],idx[1],idx[2]);
00885         }
00886         hlib.ReleaseResult(hres);
00887         if (randomizeConstraints)
00888         {
00889                 psb->randomizeConstraints();
00890         }
00891         return(psb);
00892 }
00893 
00894 
00895 
00896 
00897 static int nextLine(const char* buffer)
00898 {
00899         int numBytesRead=0;
00900 
00901         while (*buffer != '\n')
00902         {
00903                 buffer++;
00904                 numBytesRead++;
00905         }
00906 
00907         
00908         if (buffer[0]==0x0a)
00909         {
00910                 buffer++;
00911                 numBytesRead++;
00912         }
00913         return numBytesRead;
00914 }
00915 
00916 /* Create from TetGen .ele, .face, .node data                                                   */ 
00917 btSoftBody*     btSoftBodyHelpers::CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo,
00918                                                                                                         const char* ele,
00919                                                                                                         const char* face,
00920                                                                                                         const char* node,
00921                                                                                                         bool bfacelinks,
00922                                                                                                         bool btetralinks,
00923                                                                                                         bool bfacesfromtetras)
00924 {
00925 btAlignedObjectArray<btVector3> pos;
00926 int                                                             nnode=0;
00927 int                                                             ndims=0;
00928 int                                                             nattrb=0;
00929 int                                                             hasbounds=0;
00930 int result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
00931 result = sscanf(node,"%d %d %d %d",&nnode,&ndims,&nattrb,&hasbounds);
00932 node += nextLine(node);
00933 
00934 pos.resize(nnode);
00935 for(int i=0;i<pos.size();++i)
00936         {
00937         int                     index=0;
00938         //int                   bound=0;
00939         float   x,y,z;
00940         sscanf(node,"%d %f %f %f",&index,&x,&y,&z);
00941 
00942 //      sn>>index;
00943 //      sn>>x;sn>>y;sn>>z;
00944         node += nextLine(node);
00945 
00946         //for(int j=0;j<nattrb;++j) 
00947         //      sn>>a;
00948 
00949         //if(hasbounds) 
00950         //      sn>>bound;
00951 
00952         pos[index].setX(btScalar(x));
00953         pos[index].setY(btScalar(y));
00954         pos[index].setZ(btScalar(z));
00955         }
00956 btSoftBody*                                             psb=new btSoftBody(&worldInfo,nnode,&pos[0],0);
00957 #if 0
00958 if(face&&face[0])
00959         {
00960         int                                                             nface=0;
00961         sf>>nface;sf>>hasbounds;
00962         for(int i=0;i<nface;++i)
00963                 {
00964                 int                     index=0;
00965                 int                     bound=0;
00966                 int                     ni[3];
00967                 sf>>index;
00968                 sf>>ni[0];sf>>ni[1];sf>>ni[2];
00969                 sf>>bound;
00970                 psb->appendFace(ni[0],ni[1],ni[2]);     
00971                 if(btetralinks)
00972                         {
00973                         psb->appendLink(ni[0],ni[1],0,true);
00974                         psb->appendLink(ni[1],ni[2],0,true);
00975                         psb->appendLink(ni[2],ni[0],0,true);
00976                         }
00977                 }
00978         }
00979 #endif
00980 
00981 if(ele&&ele[0])
00982         {
00983         int                                                             ntetra=0;
00984         int                                                             ncorner=0;
00985         int                                                             neattrb=0;
00986         sscanf(ele,"%d %d %d",&ntetra,&ncorner,&neattrb);
00987         ele += nextLine(ele);
00988         
00989         //se>>ntetra;se>>ncorner;se>>neattrb;
00990         for(int i=0;i<ntetra;++i)
00991                 {
00992                 int                     index=0;
00993                 int                     ni[4];
00994 
00995                 //se>>index;
00996                 //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3];
00997                 sscanf(ele,"%d %d %d %d %d",&index,&ni[0],&ni[1],&ni[2],&ni[3]);
00998                 ele+=nextLine(ele);
00999                 //for(int j=0;j<neattrb;++j) 
01000                 //      se>>a;
01001                 psb->appendTetra(ni[0],ni[1],ni[2],ni[3]);
01002                 if(btetralinks)
01003                         {
01004                         psb->appendLink(ni[0],ni[1],0,true);
01005                         psb->appendLink(ni[1],ni[2],0,true);
01006                         psb->appendLink(ni[2],ni[0],0,true);
01007                         psb->appendLink(ni[0],ni[3],0,true);
01008                         psb->appendLink(ni[1],ni[3],0,true);
01009                         psb->appendLink(ni[2],ni[3],0,true);
01010                         }
01011                 }
01012         }
01013 printf("Nodes:  %u\r\n",psb->m_nodes.size());
01014 printf("Links:  %u\r\n",psb->m_links.size());
01015 printf("Faces:  %u\r\n",psb->m_faces.size());
01016 printf("Tetras: %u\r\n",psb->m_tetras.size());
01017 return(psb);
01018 }
01019 

Generated on Mon Feb 15 22:17:06 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1