Blender V2.61 - r43446

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