Fluid3D.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #include <sofa/component/behaviormodel/eulerianfluid/Fluid3D.h>
00026 #include <sofa/helper/gl/template.h>
00027 #include <sofa/core/ObjectFactory.h>
00028 #include <iostream>
00029 #include <string.h>
00030 namespace sofa
00031 {
00032 
00033 namespace component
00034 {
00035 
00036 namespace behaviormodel
00037 {
00038 
00039 namespace eulerianfluid
00040 {
00041 
00042 SOFA_DECL_CLASS(Fluid3D)
00043 
00044 int Fluid3DClass = core::RegisterObject("Eulerian 3D fluid")
00045 .add< Fluid3D >()
00046 .addLicense("LGPL")
00047 .addAuthor("Jeremie Allard")
00048 ;
00049 
00050 Fluid3D::Fluid3D()
00051 : nx(16), ny(16), nz(16), cellwidth(1.0f),
00052   f_nx ( initDataPtr(&f_nx, &nx, "nx", "grid size along x axis") ),
00053   f_ny ( initDataPtr(&f_ny, &ny, "ny", "grid size along y axis") ),
00054   f_nz ( initDataPtr(&f_nz, &nz, "nz", "grid size along z axis") ),
00055   f_cellwidth ( initDataPtr(&f_cellwidth, &cellwidth, "cellwidth", "width of each cell") ),
00056   f_center ( initData(&f_center, vec3(0,0,0), "center", "position of grid center") ),
00057   f_height ( initData(&f_height, 5.0f, "height", "initial fluid height") ),
00058   f_dir ( initData(&f_dir, vec3(0,1,0), "dir", "initial fluid surface normal") ),
00059   f_tstart ( initData(&f_tstart, 0.0f, "tstart", "starting time for fluid source") ),
00060   f_tstop ( initData(&f_tstop, 60.0f, "tstop", "stopping time for fluid source") )
00061 {
00062     fluid = new Grid3D;
00063     fnext = new Grid3D;
00064     ftemp = new Grid3D;
00065 }
00066 
00067 Fluid3D::~Fluid3D()
00068 {
00069     delete fluid;
00070     delete fnext;
00071     delete ftemp;
00072 }
00073 
00074 void Fluid3D::init()
00075 {
00076     f_nx.beginEdit();
00077     f_ny.beginEdit();
00078     f_nz.beginEdit();
00079     f_cellwidth.beginEdit();
00080     fluid->clear(nx,ny,nz);
00081     fnext->clear(nx,ny,nz);
00082     ftemp->clear(nx,ny,nz);
00083     if (f_height.getValue() != 0)
00084     {
00085         //fluid->seed(f_height.getValue());
00086         fluid->seed(f_height.getValue(), f_dir.getValue());
00087         //fluid->seed(vec3(3.5,3.5,3.5), vec3(12.5,8.5,12.5));
00088     }
00089     fluid->t = -f_tstart.getValue();
00090     fluid->tend = f_tstop.getValue() - f_tstart.getValue();
00091 }
00092 
00093 void Fluid3D::reset()
00094 {
00095     init();
00096 }
00097 
00098 void Fluid3D::updatePosition(double dt)
00099 {
00100     fnext->gravity = getContext()->getLocalGravity()/cellwidth;
00101     fnext->step(fluid, ftemp, (real)dt);
00102     Grid3D* p = fluid; fluid=fnext; fnext=p;
00103 }
00104 
00105 void Fluid3D::drawVisual()
00106 {
00107     glPushMatrix();
00108     vec3 center = f_center.getValue();
00109     glTranslatef(center[0]-(nx-1)*cellwidth/2,center[1]-(ny-1)*cellwidth/2,center[2]-(nz-1)*cellwidth/2);
00110     glScalef(cellwidth,cellwidth,cellwidth);
00111     //if (getContext()->getShowBehaviorModels())
00112     {
00113         glDisable(GL_LIGHTING);
00114         glColor4f(1,1,1,1);
00115         glBegin(GL_LINES);
00116         glVertex3i(    0,    0,    0 ); glVertex3i( nx-1,    0,    0 );
00117         glVertex3i(    0, ny-1,    0 ); glVertex3i( nx-1, ny-1,    0 );
00118         glVertex3i(    0,    0, nz-1 ); glVertex3i( nx-1,    0, nz-1 );
00119         glVertex3i(    0, ny-1, nz-1 ); glVertex3i( nx-1, ny-1, nz-1 );
00120         
00121         glVertex3i(    0,    0,    0 ); glVertex3i(    0, ny-1,    0 );
00122         glVertex3i( nx-1,    0,    0 ); glVertex3i( nx-1, ny-1,    0 );
00123         glVertex3i(    0,    0, nz-1 ); glVertex3i(    0, ny-1, nz-1 );
00124         glVertex3i( nx-1,    0, nz-1 ); glVertex3i( nx-1, ny-1, nz-1 );
00125             
00126         glVertex3i(    0,    0,    0 ); glVertex3i(    0,    0, nz-1 );
00127         glVertex3i( nx-1,    0,    0 ); glVertex3i( nx-1,    0, nz-1 );
00128         glVertex3i(    0, ny-1,    0 ); glVertex3i(    0, ny-1, nz-1 );
00129         glVertex3i( nx-1, ny-1,    0 ); glVertex3i( nx-1, ny-1, nz-1 );
00130         glEnd();
00131     }
00132     if (getContext()->getShowBehaviorModels())
00133     {
00134         glDisable(GL_LIGHTING);
00135         const real s = (real)getContext()->getDt()*5;
00136         glBegin(GL_LINES);
00137         for (int z=0;z<nz;z++)
00138             for (int y=0;y<ny;y++)
00139                 for (int x=0;x<nx;x++)
00140         {
00141             vec3 u = fluid->get(x,y,z)->u;
00142             real r;
00143             r = u[0]*s;
00144             if (rabs(r) > 0.001f)
00145             {
00146                 if (r>0.9f) r=0.9f;
00147                 glColor4f(1,0,0,1);
00148                 glVertex3f((real)x-0.5f  , (real)y, (real)z);
00149                 glVertex3f((real)x-0.5f+r, (real)y, (real)z);
00150             }
00151             r = u[1]*s;
00152             if (rabs(r) > 0.001f)
00153             {
00154                 if (r>0.9f) r=0.9f;
00155                 glColor4f(0,1,0,1);
00156                 glVertex3f((real)x, (real)y-0.5f  , (real)z);
00157                 glVertex3f((real)x, (real)y-0.5f+r, (real)z);
00158             }
00159             r = u[2]*s;
00160             if (rabs(r) > 0.001f)
00161             {
00162                 if (r>1) r=1;
00163                 glColor4f(0,0,1,1);
00164                 glVertex3f((real)x, (real)y, (real)z-0.5f  );
00165                 glVertex3f((real)x, (real)y, (real)z-0.5f+r);
00166             }
00167         }
00168         glEnd();
00169         glPointSize(3);
00170         glBegin(GL_POINTS);
00171         for (int z=0;z<nz;z++)
00172             for (int y=0;y<ny;y++)
00173                 for (int x=0;x<nx;x++)
00174         {
00175             real l = *fluid->getlevelset(x,y,z);
00176             if (rabs(l)>=5) continue;
00177             if (l<0)
00178             {
00179                 glColor4f(0,1+l/5,1+l/5,1);
00180             }
00181             else
00182             {
00183                 glColor4f(1-l/5,1-l/5,0,1);
00184             }
00185             glVertex3i(x,y,z);
00186         }
00187         glEnd();
00188         glPointSize(1);
00189     }
00190     if (getContext()->getShowVisualModels())
00191     {
00192         if (getContext()->getShowWireFrame())
00193             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00194 
00195         glEnable(GL_LIGHTING);
00196 
00197         static const float color[4] = { 0.0f, 1.0f, 1.0f, 1.0f};
00198         glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
00199         static const float emissive[4] = { 0.0f, 0.0f, 0.0f, 0.0f};
00200         static const float specular[4] = { 1.0f, 1.0f, 1.0f, 1.0f};
00201         glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, emissive);
00202         glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
00203         glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 20);
00204         
00205         glBegin(GL_TRIANGLES);
00206         for (unsigned int i=0;i<facets.size();i++)
00207         {
00208             for (int j=0;j<3;j++)
00209             {
00210                 int idx = facets[i].p[j];
00211                 glNormal3fv(points[idx].n.ptr());
00212                 glVertex3fv(points[idx].p.ptr());
00213             }
00214         }
00215         glEnd();
00216         
00217         glDisable(GL_LIGHTING);
00218         if (getContext()->getShowWireFrame())
00219             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00220     }
00221     glPopMatrix();
00222 }
00223 
00224 void Fluid3D::exportOBJ(std::string name, std::ostream* out, std::ostream* /*mtl*/, int& vindex, int& nindex, int& /*tindex*/)
00225 {
00226     vec3 corner = f_center.getValue() - vec3((real)nx-1,(real)ny-1,(real)nz-1)*cellwidth/2;
00227 
00228     *out << "g "<<name<<"\n";
00229     
00230     for(unsigned i=0;i<points.size();++i)
00231     {
00232         vec3 p = points[i].p*cellwidth + corner;
00233         *out << "v "<< std::fixed << p[0]<<' '<< std::fixed <<p[1]<<' '<< std::fixed <<p[2]<<'\n';
00234     }
00235     
00236     
00237     for(unsigned i=0;i<points.size();++i)
00238         *out << "vn "<< std::fixed << points[i].n[0]<<' '<< std::fixed <<points[i].n[1]<<' '<< std::fixed <<points[i].n[2]<<'\n';
00239         
00240     
00241     for (unsigned int i = 0; i < facets.size() ; i++)
00242         *out << "f "<<facets[i].p[0]+vindex+1<<"//"<<facets[i].p[0]+nindex+1<<' '<< facets[i].p[1]+vindex+1<<"//"<<facets[i].p[1]+nindex+1<<' '<< facets[i].p[2]+vindex+1<<"//"<<facets[i].p[2]+nindex+1<<'\n';
00243         
00244     
00245     *out << std::endl;
00246     
00247     vindex+=points.size();
00248     nindex+=points.size();
00249 }
00250 
00251 void Fluid3D::updateVisual()
00252 {
00253     points.clear();
00254     facets.clear();
00255     
00256     const real* data = fluid->levelset;
00257 
00258     planes.resize(2*nx*ny);
00259     CubeData *P = &(planes[0]);
00260     CubeData *P0 = P;
00261     CubeData *P1 = P+(nx*ny);
00262     //P0 = planes.begin()+0;
00263     //P1 = planes.begin()+nx*ny;
00264 
00266     
00267     const real isoval = 0.0f;
00268     const real iso = isoval;
00269 
00270     const int dx = 1;
00271     const int dy = nx;
00272     const int dz = nx*ny;
00273 
00274     int x,y,z,i,mk;
00275     const int *tri;
00276     
00277 
00278     i=0;
00279     // First plane
00280     memset(P1,-1,nx*ny*sizeof(CubeData));
00281     {
00282         z=0;
00283         // First line
00284         {
00285             y=0;
00286             ++i;
00287             for(x=1;x<nx;x++)
00288             {
00289                 if ((data[i]>isoval)^(data[i-dx]>isoval))
00290                 {
00291                     P1[i].p[0] = addPoint<0>(x,y,z,data[i],data[i-dx],iso);
00292                 }
00293                 ++i;
00294             }
00295         }
00296         for(y=1;y<ny;y++)
00297         {
00298             // First column
00299             x=0;
00300             if ((data[i]>isoval)^(data[i-dy]>isoval))
00301             {
00302                 P1[i].p[1] = addPoint<1>(x,y,z,data[i],data[i-dy],iso);
00303             }
00304             ++i;
00305       
00306             for(x=1;x<nx;x++)
00307             {
00308                 if ((data[i]>isoval)^(data[i-dx]>isoval))
00309                 {
00310                     P1[i].p[0] = addPoint<0>(x,y,z,data[i],data[i-dx],iso);
00311                 }
00312                 if ((data[i]>isoval)^(data[i-dy]>isoval))
00313                 {
00314                     P1[i].p[1] = addPoint<1>(x,y,z,data[i],data[i-dy],iso);
00315                 }
00316                 ++i;
00317             }
00318         }
00319     }
00320     for (z=1;z<nz;z++)
00321     {
00322         i=0; data+=dz;
00323 
00324         { CubeData* p=P0; P0=P1; P1=p; }
00325         memset(P1,-1,nx*ny*sizeof(CubeData));
00326 
00327         int edgepts[12];
00328         int* base = &(P[0].p[0]);
00329         edgepts[0] = &(P0[-dy].p[0])-base;
00330         edgepts[1] = &(P0[0  ].p[1])-base;
00331         edgepts[2] = &(P0[0  ].p[0])-base;
00332         edgepts[3] = &(P0[-dx].p[1])-base;
00333         edgepts[4] = &(P1[-dy].p[0])-base;
00334         edgepts[5] = &(P1[0  ].p[1])-base;
00335         edgepts[6] = &(P1[0  ].p[0])-base;
00336         edgepts[7] = &(P1[-dx].p[1])-base;
00337         edgepts[8] =  &(P1[-dx-dy].p[2])-base;
00338         edgepts[9] =  &(P1[   -dy].p[2])-base;
00339         edgepts[10] = &(P1[0     ].p[2])-base;
00340         edgepts[11] = &(P1[-dx   ].p[2])-base;
00341 
00342         // First line
00343         {
00344             y=0;
00345             x=0;
00346             if ((data[i]>isoval)^(data[i-dz]>isoval))
00347             {
00348                 P1[i].p[2] = addPoint<2>(x,y,z,data[i],data[i-dz],iso);
00349             }
00350             ++i;
00351             for(x=1;x<nx;x++)
00352             {
00353                 if ((data[i]>isoval)^(data[i-dx]>isoval))
00354                 {
00355                     P1[i].p[0] = addPoint<0>(x,y,z,data[i],data[i-dx],iso);
00356                 }
00357                 if ((data[i]>isoval)^(data[i-dz]>isoval))
00358                 {
00359                     P1[i].p[2] = addPoint<2>(x,y,z,data[i],data[i-dz],iso);
00360                 }
00361                 ++i;
00362             }
00363         }
00364         for(y=1;y<ny;y++)
00365         {
00366             // First column
00367             x=0;
00368             if ((data[i]>isoval)^(data[i-dy]>isoval))
00369             {
00370                 P1[i].p[1] = addPoint<1>(x,y,z,data[i],data[i-dy],iso);
00371             }
00372             if ((data[i]>isoval)^(data[i-dz]>isoval))
00373             {
00374                 P1[i].p[2] = addPoint<2>(x,y,z,data[i],data[i-dz],iso);
00375             }
00376             ++i;
00377       
00378             for(x=1;x<nx;x++)
00379             {
00380                 if ((data[i]>isoval)^(data[i-dx]>isoval))
00381                 {
00382                     P1[i].p[0] = addPoint<0>(x,y,z,data[i],data[i-dx],iso);
00383                 }
00384                 if ((data[i]>isoval)^(data[i-dy]>isoval))
00385                 {
00386                     P1[i].p[1] = addPoint<1>(x,y,z,data[i],data[i-dy],iso);
00387                 }
00388                 if ((data[i]>isoval)^(data[i-dz]>isoval))
00389                 {
00390                     P1[i].p[2] = addPoint<2>(x,y,z,data[i],data[i-dz],iso);
00391                 }
00392                 
00393                 // All points should now be created
00394 
00395                 if (data[i-dx-dy-dz]>iso) mk = 1; else mk=0;
00396                 if (data[i   -dy-dz]>iso) mk|= 2;
00397                 if (data[i      -dz]>iso) mk|= 4;
00398                 if (data[i-dx   -dz]>iso) mk|= 8;
00399                 if (data[i-dx-dy   ]>iso) mk|= 16;
00400                 if (data[i   -dy   ]>iso) mk|= 32;
00401                 if (data[i         ]>iso) mk|= 64;
00402                 if (data[i-dx      ]>iso) mk|= 128;
00403 
00404                 tri = helper::MarchingCubeTriTable[mk];
00405                 while (*tri>=0)
00406                 {
00407                     int* b = base+3*i;
00408                     if (addFace(b[edgepts[tri[0]]],b[edgepts[tri[1]]],b[edgepts[tri[2]]])<0)
00409                     {
00410                         std::cerr << "  mk=0x"<<std::hex<<mk<<std::dec<<" p1="<<tri[0]<<" p2="<<tri[1]<<" p3="<<tri[2]<<std::endl;
00411                         for (int e=0;e<12;e++) std::cerr << "  e"<<e<<"="<<b[edgepts[e]];
00412                         std::cerr<<std::endl;
00413                         for (int ddz=-1;ddz<=0;ddz++)
00414                             for (int ddy=-1;ddy<=0;ddy++)
00415                                 for (int ddx=-1;ddx<=0;ddx++)
00416                         {
00417                             std::cerr << " val("<<x+ddx<<','<<y+ddy<<','<<z+ddz<<")="<<(double)data[i+ddx*dx+ddy*dy+ddz*dz]<<std::endl;
00418                         }
00419                     }
00420                     tri+=3;
00421                 }
00422                 ++i;
00423             }
00424         }
00425     }
00426     //std::cout << points.size() << " points, "<<facets.size() <<" faces"<<std::endl;
00427 
00428     for (unsigned int i=0;i<points.size();i++)
00429     {
00430         points[i].n.clear();
00431     }
00432 
00433     for (unsigned int i=0;i<facets.size();i++)
00434     {
00435         Vec3f n = cross(points[facets[i].p[1]].p-points[facets[i].p[0]].p,points[facets[i].p[2]].p-points[facets[i].p[0]].p);
00436         n.normalize();
00437         points[facets[i].p[0]].n += n;
00438         points[facets[i].p[1]].n += n;
00439         points[facets[i].p[2]].n += n;
00440     }
00441   
00442     for (unsigned int i=0;i<points.size();i++)
00443         points[i].n.normalize();
00444 }
00445 
00446 bool Fluid3D::addBBox(double* minBBox, double* maxBBox)
00447 {
00448     vec3 center = f_center.getValue();
00449     SReal size[3] = { (nx-1)*cellwidth, (ny-1)*cellwidth, (nz-1)*cellwidth };
00450     SReal pos[3] = { center[0]-size[0]/2, center[1]-size[1]/2, center[2]-size[2]/2 };
00451     for (int c=0;c<3;c++)
00452     {
00453         if (minBBox[c] > pos[c]        ) minBBox[c] = pos[c];
00454         if (maxBBox[c] < pos[c]+size[c]) maxBBox[c] = pos[c]+size[c];
00455     }
00456     return true;
00457 }
00458 
00459 } // namespace eulerianfluid
00460 
00461 } // namespace behaviormodel
00462 
00463 } // namespace component
00464 
00465 } // namespace sofa
00466 

Generated on Sun Nov 23 02:29:31 2008 for Sofa by  doxygen 1.5.7.1