Fluid2D.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/Fluid2D.h>
00026 #include <sofa/helper/gl/template.h>
00027 #include <sofa/core/ObjectFactory.h>
00028 #include <iostream>
00029 #include <string.h>
00030 #include <sofa/helper/MarchingCubeUtility.h> // for marching cube tables
00031 
00032 namespace sofa
00033 {
00034 
00035 namespace component
00036 {
00037 
00038 namespace behaviormodel
00039 {
00040 
00041 namespace eulerianfluid
00042 {
00043 
00044 SOFA_DECL_CLASS(Fluid2D)
00045 
00046 int Fluid2DClass = core::RegisterObject("Eulerian 2D fluid")
00047 .add< Fluid2D >()
00048 .addLicense("LGPL")
00049 .addAuthor("Jeremie Allard")
00050 ;
00051 
00052 Fluid2D::Fluid2D()
00053 : nx(16), ny(16), cellwidth(1.0f),
00054   f_nx ( initDataPtr(&f_nx, &nx, "nx", "grid size along x axis") ),
00055   f_ny ( initDataPtr(&f_ny, &ny, "ny", "grid size along y axis") ),
00056   f_cellwidth ( initDataPtr(&f_cellwidth, &cellwidth, "cellwidth", "width of each cell") ),
00057   f_height ( initData(&f_height, 5.0f, "height", "initial fluid height") ),
00058   f_dir ( initData(&f_dir, vec2(0,1), "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 Grid2D;
00063     fnext = new Grid2D;
00064     ftemp = new Grid2D;
00065 }
00066 
00067 Fluid2D::~Fluid2D()
00068 {
00069     delete fluid;
00070     delete fnext;
00071     delete ftemp;
00072 }
00073 
00074 void Fluid2D::init()
00075 {
00076     f_nx.beginEdit();
00077     f_ny.beginEdit(); 
00078     f_cellwidth.beginEdit();
00079     fluid->clear(nx,ny);
00080     fnext->clear(nx,ny);
00081     ftemp->clear(nx,ny);
00082     if (f_height.getValue() != 0)
00083     {
00084         //fluid->seed(f_height.getValue());
00085         fluid->seed(f_height.getValue(), f_dir.getValue());
00086         //fluid->seed(vec2(3.5,3.5), vec2(12.5,8.5));
00087     }
00088     fluid->t = -f_tstart.getValue();
00089     fluid->tend = f_tstop.getValue() - f_tstart.getValue();
00090 }
00091 
00092 void Fluid2D::reset()
00093 {
00094     init();
00095 }
00096 
00097 void Fluid2D::updatePosition(double dt)
00098 {
00099     fnext->step(fluid, ftemp, (real)dt);
00100     Grid2D* p = fluid; fluid=fnext; fnext=p;
00101 }
00102 
00103 void Fluid2D::drawVisual()
00104 {
00105     glPushMatrix();
00106     glTranslatef(-(nx-1)*cellwidth/2,-(ny-1)*cellwidth/2,0.0f);
00107     glScalef(cellwidth,cellwidth,cellwidth);
00108     //if (getContext()->getShowBehaviorModels())
00109     {
00110         glDisable(GL_LIGHTING);
00111         glColor4f(1,1,1,1);
00112         glBegin(GL_LINES);
00113         glVertex2i(    0,    0 ); glVertex2i( nx-1,    0 );
00114         glVertex2i(    0, ny-1 ); glVertex2i( nx-1, ny-1 );
00115         
00116         glVertex2i(    0,    0 ); glVertex2i(    0, ny-1 );
00117         glVertex2i( nx-1,    0 ); glVertex2i( nx-1, ny-1 );
00118         glEnd();
00119     }
00120     if (getContext()->getShowBehaviorModels())
00121     {
00122         glDisable(GL_LIGHTING);
00123         const real s = (real)getContext()->getDt()*5;
00124         glBegin(GL_LINES);
00125         for (int y=0;y<ny;y++)
00126             for (int x=0;x<nx;x++)
00127         {
00128             vec2 u = fluid->get(x,y)->u;
00129             real r;
00130             r = u[0]*s;
00131             if (rabs(r) > 0.001f)
00132             {
00133                 if (r>0.9f) r=0.9f;
00134                 glColor4f(1,0,0,1);
00135                 glVertex2f((float)x-0.5f       , (float)y);
00136                 glVertex2f((float)x-0.5f+     r, (float)y);
00137                 glVertex2f((float)x-0.5f+     r, (float)y);
00138                 glVertex2f((float)x-0.5f+0.8f*r, (float)y+0.2f*r);
00139                 glVertex2f((float)x-0.5f+     r, (float)y);
00140                 glVertex2f((float)x-0.5f+0.8f*r, (float)y-0.2f*r);
00141             }
00142             r = u[1]*s;
00143             if (rabs(r) > 0.001f)
00144             {
00145                 if (r>0.9f) r=0.9f;
00146                 glColor4f(0,1,0,1);
00147                 glVertex2f((float)x, y-0.5f  );
00148                 glVertex2f((float)x, y-0.5f+r);
00149                 glVertex2f((float)x, y-0.5f+r);
00150                 glVertex2f((float)x+0.2f*r, y-0.5f+0.8f*r);
00151                 glVertex2f((float)x, y-0.5f+r);
00152                 glVertex2f((float)x-0.2f*(float)r, y-0.5f+0.8f*r);
00153             }
00154         }
00155         glEnd();
00156         glPointSize(3);
00157         glBegin(GL_POINTS);
00158         for (int y=0;y<ny;y++)
00159             for (int x=0;x<nx;x++)
00160         {
00161             real l = *fluid->getlevelset(x,y);
00162             if (rabs(l)>=5) continue;
00163             if (l<0)
00164             {
00165                 glColor4f(0,1+l/5,1+l/5,1);
00166             }
00167             else
00168             {
00169                 glColor4f(1-l/5,1-l/5,0,1);
00170             }
00171             glVertex2i(x,y);
00172         }
00173         glEnd();
00174         glPointSize(1);
00175     }
00176     if (getContext()->getShowVisualModels())
00177     {
00178         if (getContext()->getShowWireFrame())
00179             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00180         glEnable(GL_LIGHTING);
00181 
00182         static const float color[4] = { 0.0f, 1.0f, 1.0f, 1.0f};
00183         glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
00184         static const float emissive[4] = { 0.0f, 0.0f, 0.0f, 0.0f};
00185         static const float specular[4] = { 1.0f, 1.0f, 1.0f, 1.0f};
00186         glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, emissive);
00187         glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, specular);
00188         glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 20);
00189         
00190         glBegin(GL_TRIANGLES);
00191         for (unsigned int i=0;i<facets.size();i++)
00192         {
00193             for (int j=0;j<3;j++)
00194             {
00195                 int idx = facets[i].p[j];
00196                 glNormal3fv(points[idx].n.ptr());
00197                 glVertex3fv(points[idx].p.ptr());
00198             }
00199         }
00200         glEnd();
00201         
00202         glDisable(GL_LIGHTING);
00203         if (getContext()->getShowWireFrame())
00204             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00205     }
00206     glPopMatrix();
00207 }
00208 
00209 void Fluid2D::updateVisual()
00210 {
00211     points.clear();
00212     facets.clear();
00213     
00214     const real* data = fluid->levelset;
00215 
00216     planes.resize(2*nx*ny);
00217     CubeData *P = &(planes[0]);
00218     CubeData *P0 = P;
00219     CubeData *P1 = P+(nx*ny);
00220     //P0 = planes.begin()+0;
00221     //P1 = planes.begin()+nx*ny;
00222 
00224     
00225     const real isoval = 0.0f;
00226     const real iso = isoval;
00227 
00228     const int dx = 1;
00229     const int dy = nx;
00230     const int dz = 0; //nx*ny;
00231     const int nz = 2;
00232     const real data2 = 5;
00233 
00234     int x,y,z,i,mk;
00235     const int *tri;
00236     
00237 
00238     i=0;
00239     // First plane
00240     memset(P1,-1,nx*ny*sizeof(CubeData));
00241     {
00242         z=0;
00243         // First line
00244         {
00245             y=0;
00246             ++i;
00247             for(x=1;x<nx;x++)
00248             {
00249                 if ((data[i]>=isoval)^(data[i-dx]>=isoval))
00250                 {
00251                     P1[i].p[0] = addPoint<0>(x,y,z,data[i],data[i-dx],iso);
00252                 }
00253                 ++i;
00254             }
00255         }
00256         for(y=1;y<ny;y++)
00257         {
00258             // First column
00259             x=0;
00260             if ((data[i]>=isoval)^(data[i-dy]>=isoval))
00261             {
00262                 P1[i].p[1] = addPoint<1>(x,y,z,data[i],data[i-dy],iso);
00263             }
00264             ++i;
00265       
00266             for(x=1;x<nx;x++)
00267             {
00268                 if ((data[i]>=isoval)^(data[i-dx]>=isoval))
00269                 {
00270                     P1[i].p[0] = addPoint<0>(x,y,z,data[i],data[i-dx],iso);
00271                 }
00272                 if ((data[i]>=isoval)^(data[i-dy]>=isoval))
00273                 {
00274                     P1[i].p[1] = addPoint<1>(x,y,z,data[i],data[i-dy],iso);
00275                 }
00276                 ++i;
00277             }
00278         }
00279     }
00280     for (z=1;z<nz;z++)
00281     {
00282         i=0; data+=dz;
00283 
00284         { CubeData* p=P0; P0=P1; P1=p; }
00285         memset(P1,-1,nx*ny*sizeof(CubeData));
00286 
00287         int edgepts[12];
00288         int* base = &(P[0].p[0]);
00289         edgepts[0] = &(P0[-dy].p[0])-base;
00290         edgepts[1] = &(P0[0  ].p[1])-base;
00291         edgepts[2] = &(P0[0  ].p[0])-base;
00292         edgepts[3] = &(P0[-dx].p[1])-base;
00293         edgepts[4] = &(P1[-dy].p[0])-base;
00294         edgepts[5] = &(P1[0  ].p[1])-base;
00295         edgepts[6] = &(P1[0  ].p[0])-base;
00296         edgepts[7] = &(P1[-dx].p[1])-base;
00297         edgepts[8] =  &(P1[-dx-dy].p[2])-base;
00298         edgepts[9] =  &(P1[   -dy].p[2])-base;
00299         edgepts[10] = &(P1[0     ].p[2])-base;
00300         edgepts[11] = &(P1[-dx   ].p[2])-base;
00301 
00302         // First line
00303         {
00304             y=0;
00305             x=0;
00306             if ((data2/*data[i]*/>=isoval)^(data[i-dz]>=isoval))
00307             {
00308                 P1[i].p[2] = addPoint<2>(x,y,z,data2/*data[i]*/,data[i-dz],iso);
00309             }
00310             ++i;
00311             for(x=1;x<nx;x++)
00312             {
00313                 //if ((data[i]>=isoval)^(data[i-dx]>=isoval))
00314                 //{
00315                 //    P1[i].p[0] = addPoint<0>(x,y,z,data[i],data[i-dx],iso);
00316                 //}
00317                 if ((data2/*data[i]*/>=isoval)^(data[i-dz]>=isoval))
00318                 {
00319                     P1[i].p[2] = addPoint<2>(x,y,z,data2/*data[i]*/,data[i-dz],iso);
00320                 }
00321                 ++i;
00322             }
00323         }
00324         for(y=1;y<ny;y++)
00325         {
00326             // First column
00327             x=0;
00328             //if ((data[i]>=isoval)^(data[i-dy]>=isoval))
00329             //{
00330             //    P1[i].p[1] = addPoint<1>(x,y,z,data[i],data[i-dy],iso);
00331             //}
00332             if ((data2/*data[i]*/>=isoval)^(data[i-dz]>=isoval))
00333             {
00334                 P1[i].p[2] = addPoint<2>(x,y,z,data2/*data[i]*/,data[i-dz],iso);
00335             }
00336             ++i;
00337       
00338             for(x=1;x<nx;x++)
00339             {
00340                 //if ((data[i]>=isoval)^(data[i-dx]>=isoval))
00341                 //{
00342                 //    P1[i].p[0] = addPoint<0>(x,y,z,data[i],data[i-dx],iso);
00343                 //}
00344                 //if ((data[i]>=isoval)^(data[i-dy]>=isoval))
00345                 //{
00346                 //    P1[i].p[1] = addPoint<1>(x,y,z,data[i],data[i-dy],iso);
00347                 //}
00348                 if ((data2/*data[i]*/>=isoval)^(data[i-dz]>=isoval))
00349                 {
00350                     P1[i].p[2] = addPoint<2>(x,y,z,data2/*data[i]*/,data[i-dz],iso);
00351                 }
00352                 
00353                 // All points should now be created
00354 
00355                 if (data[i-dx-dy-dz]>=iso) mk = 1; else mk=0;
00356                 if (data[i   -dy-dz]>=iso) mk|= 2;
00357                 if (data[i      -dz]>=iso) mk|= 4;
00358                 if (data[i-dx   -dz]>=iso) mk|= 8;
00359                 if (data2/*data[i-dx-dy   ]*/>=iso) mk|= 16;
00360                 if (data2/*data[i   -dy   ]*/>=iso) mk|= 32;
00361                 if (data2/*data[i         ]*/>=iso) mk|= 64;
00362                 if (data2/*data[i-dx      ]*/>=iso) mk|= 128;
00363 
00364                 tri= helper::MarchingCubeTriTable[mk];
00365                 while (*tri>=0)
00366                 {
00367                     int* b = base+3*i;
00368                     if (addFace(b[edgepts[tri[0]]],b[edgepts[tri[1]]],b[edgepts[tri[2]]])<0)
00369                     {
00370                         std::cerr << "  mk=0x"<<std::hex<<mk<<std::dec<<" p1="<<tri[0]<<" p2="<<tri[1]<<" p3="<<tri[2]<<std::endl;
00371                         for (int e=0;e<12;e++) std::cerr << "  e"<<e<<"="<<b[edgepts[e]];
00372                         std::cerr<<std::endl;
00373                         for (int ddz=-1;ddz<=0;ddz++)
00374                             for (int ddy=-1;ddy<=0;ddy++)
00375                                 for (int ddx=-1;ddx<=0;ddx++)
00376                         {
00377                             std::cerr << " val("<<x+ddx<<','<<y+ddy<<','<<z+ddz<<")="<<(double)data[i+ddx*dx+ddy*dy+ddz*dz]<<std::endl;
00378                         }
00379                     }
00380                     tri+=3;
00381                 }
00382                 ++i;
00383             }
00384         }
00385     }
00386     //std::cout << points.size() << " points, "<<facets.size() <<" faces"<<std::endl;
00387 
00388     for (unsigned int i=0;i<points.size();i++)
00389     {
00390         points[i].n.clear();
00391     }
00392 
00393     for (unsigned int i=0;i<facets.size();i++)
00394     {
00395         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);
00396         n.normalize();
00397         points[facets[i].p[0]].n += n;
00398         points[facets[i].p[1]].n += n;
00399         points[facets[i].p[2]].n += n;
00400     }
00401   
00402     for (unsigned int i=0;i<points.size();i++)
00403         points[i].n.normalize();
00404 }
00405 
00406 bool Fluid2D::addBBox(double* minBBox, double* maxBBox)
00407 {
00408   SReal size[3] = { (nx-1)*cellwidth, (ny-1)*cellwidth, cellwidth/2 };
00409   SReal pos[3] = { -size[0]/2, -size[1]/2, 0 };
00410     for (int c=0;c<3;c++)
00411     {
00412         if (minBBox[c] > pos[c]        ) minBBox[c] = pos[c];
00413         if (maxBBox[c] < pos[c]+size[c]) maxBBox[c] = pos[c]+size[c];
00414     }
00415     return true;
00416 }
00417 
00418 } // namespace eulerianfluid
00419 
00420 } // namespace behaviormodel
00421 
00422 } // namespace component
00423 
00424 } // namespace sofa
00425 

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