00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef SOFA_COMPONENT_MAPPING_SPHFLUIDSURFACEMAPPING_INL
00026 #define SOFA_COMPONENT_MAPPING_SPHFLUIDSURFACEMAPPING_INL
00027
00028 #include <sofa/component/mapping/SPHFluidSurfaceMapping.h>
00029 #include <sofa/component/container/SpatialGridContainer.inl>
00030 #include <sofa/core/Mapping.inl>
00031 #include <sofa/helper/rmath.h>
00032 #include <sofa/simulation/tree/GNode.h>
00033 #include <sofa/helper/gl/template.h>
00034 #include <map>
00035 #include <list>
00036
00037
00038
00039 namespace sofa
00040 {
00041
00042 namespace component
00043 {
00044
00045 namespace mapping
00046 {
00047
00048 using namespace sofa::defaulttype;
00049
00050
00051 template <class In, class Out>
00052 void SPHFluidSurfaceMapping<In,Out>::init()
00053 {
00054 this->Inherit::init();
00055 simulation::tree::GNode* node = dynamic_cast<simulation::tree::GNode*>(this->getFrom()->getContext());
00056 if (node)
00057 {
00058
00059
00060 node->getNodeObject(sph);
00061 }
00062 if (sph)
00063 {
00064
00065 if (mIsoValue.getValue() == 0.5)
00066 mIsoValue.setValue( mIsoValue.getValue()/ sph->getParticleFieldConstant((InReal)mRadius.getValue()));
00067 }
00068
00069 grid = new Grid((InReal)mStep.getValue());
00070 }
00071
00072 template <class In, class Out>
00073 void SPHFluidSurfaceMapping<In,Out>::createPoints(OutVecCoord& out, int x, int y, int z, Cell* c, const Cell* cx, const Cell* cy, const Cell* cz, const OutReal isoval)
00074 {
00075 if (c->data.val>isoval)
00076 {
00077 if (!(cx->data.val>isoval))
00078 c->data.p[0] = addPoint<0>(out, x,y,z,c->data.val,cx->data.val,isoval);
00079 if (!(cy->data.val>isoval))
00080 c->data.p[1] = addPoint<1>(out, x,y,z,c->data.val,cy->data.val,isoval);
00081 if (!(cz->data.val>isoval))
00082 c->data.p[2] = addPoint<2>(out, x,y,z,c->data.val,cz->data.val,isoval);
00083 }
00084 else
00085 {
00086 if (cx->data.val>isoval)
00087 c->data.p[0] = addPoint<0>(out, x,y,z,c->data.val,cx->data.val,isoval);
00088 if (cy->data.val>isoval)
00089 c->data.p[1] = addPoint<1>(out, x,y,z,c->data.val,cy->data.val,isoval);
00090 if (cz->data.val>isoval)
00091 c->data.p[2] = addPoint<2>(out, x,y,z,c->data.val,cz->data.val,isoval);
00092 }
00093 }
00094
00095
00096 template <class In, class Out>
00097 void SPHFluidSurfaceMapping<In,Out>::createFaces(OutVecCoord& out, const Cell** cells, const OutReal isoval)
00098 {
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 static const int edgecell[12] = { 0, 1, 2, 0, 4, 5, 6, 4, 0, 1, 3, 2 };
00122 static const int edgepts [12] = { 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2 };
00123
00124 int mk;
00125 if (cells[0]->data.val > isoval) mk = 1; else mk=0;
00126 if (cells[1]->data.val > isoval) mk|= 2;
00127 if (cells[3]->data.val > isoval) mk|= 4;
00128 if (cells[2]->data.val > isoval) mk|= 8;
00129 if (cells[4]->data.val > isoval) mk|= 16;
00130 if (cells[5]->data.val > isoval) mk|= 32;
00131 if (cells[7]->data.val > isoval) mk|= 64;
00132 if (cells[6]->data.val > isoval) mk|= 128;
00133
00134 const int* tri=helper::MarchingCubeTriTable[mk];
00135 while (*tri>=0)
00136 {
00137 if (addFace(cells[edgecell[tri[0]]]->data.p[edgepts[tri[0]]],
00138 cells[edgecell[tri[1]]]->data.p[edgepts[tri[1]]],
00139 cells[edgecell[tri[2]]]->data.p[edgepts[tri[2]]], out.size())<0)
00140 {
00141 std::cerr << " mk=0x"<<std::hex<<mk<<std::dec<<" p1="<<tri[0]<<" p2="<<tri[1]<<" p3="<<tri[2]<<std::endl;
00142 for (int e=0;e<12;e++) std::cerr << " e"<<e<<"="<<cells[edgecell[e]]->data.p[edgepts[e]];
00143 std::cerr<<std::endl;
00144 }
00145 tri+=3;
00146 }
00147 }
00148
00149 template <class In, class Out>
00150 void SPHFluidSurfaceMapping<In,Out>::apply( OutVecCoord& out, const InVecCoord& in )
00151 {
00152 if (!sph) return;
00153
00154 out.resize(0);
00155 clear();
00156 if (in.size()==0) return;
00157 const InReal r = (InReal)(getRadius());
00158 grid->begin();
00159 for (unsigned int ip=0; ip<in.size(); ip++)
00160 {
00161 grid->add(ip, in[ip], true);
00162 }
00163 grid->end();
00164
00166 grid->computeField(sph, r);
00167
00169
00170 const OutReal isoval = (OutReal) getIsoValue();
00171 typename Grid::iterator end = grid->gridEnd();
00172 typename Grid::iterator it;
00173
00174
00175 for (it = grid->gridBegin();it!=end;++it)
00176 {
00177 typename Grid::Key p0 = it->first;
00178 const int x0 = p0[0]*GRIDDIM;
00179 const int y0 = p0[1]*GRIDDIM;
00180 const int z0 = p0[2]*GRIDDIM;
00181 typename Grid::Grid* g = it->second;
00182 const typename Grid::Grid* gx1 = g->neighbors[1];
00183 const typename Grid::Grid* gy1 = g->neighbors[3];
00184 const typename Grid::Grid* gz1 = g->neighbors[5];
00185 int x,y,z;
00186 Cell* c = g->cell;
00187 const Cell* cx1 = gx1->cell;
00188 const Cell* cy1 = gy1->cell;
00189 const Cell* cz1 = gz1->cell;
00190 for (z=0; z<GRIDDIM-1; z++)
00191 {
00192 for (y=0; y<GRIDDIM-1; y++)
00193 {
00194 for (x=0; x<GRIDDIM-1; x++)
00195 {
00196 createPoints(out, x0+x, y0+y, z0+z, c, c+DX, c+DY, c+DZ, isoval);
00197 c+=DX;
00198 }
00199
00200 createPoints(out, x0+x, y0+y, z0+z, c, cx1, c+DY, c+DZ, isoval);
00201 c+=DX;
00202 cx1+=DY;
00203 }
00204
00205 {
00206 for (x=0; x<GRIDDIM-1; x++)
00207 {
00208 createPoints(out, x0+x, y0+y, z0+z, c, c+DX, cy1, c+DZ, isoval);
00209 c+=DX;
00210 cy1+=DX;
00211 }
00212
00213 createPoints(out, x0+x, y0+y, z0+z, c, cx1, cy1, c+DZ, isoval);
00214 c+=DX;
00215 cx1+=DY;
00216 cy1+=DZ+DX-DY;
00217 }
00218 }
00219
00220 for (y=0; y<GRIDDIM-1; y++)
00221 {
00222 for (x=0; x<GRIDDIM-1; x++)
00223 {
00224 createPoints(out, x0+x, y0+y, z0+z, c, c+DX, c+DY, cz1, isoval);
00225 c+=DX;
00226 cz1+=DX;
00227 }
00228
00229 createPoints(out, x0+x, y0+y, z0+z, c, cx1, c+DY, cz1, isoval);
00230 c+=DX;
00231 cx1+=DY;
00232 cz1+=DX;
00233 }
00234
00235 {
00236 for (x=0; x<GRIDDIM-1; x++)
00237 {
00238 createPoints(out, x0+x, y0+y, z0+z, c, c+DX, cy1, cz1, isoval);
00239 c+=DX;
00240 cy1+=DX;
00241 cz1+=DX;
00242 }
00243
00244 createPoints(out, x0+x, y0+y, z0+z, c, cx1, cy1, cz1, isoval);
00245 }
00246 }
00247
00248
00249 for (it = grid->gridBegin();it!=end;++it)
00250 {
00251 typename Grid::Grid* g = it->second;
00252 const typename Grid::Grid* gx1 = g->neighbors[1];
00253 const typename Grid::Grid* gy1 = g->neighbors[3];
00254 const typename Grid::Grid* gz1 = g->neighbors[5];
00255 int x,y,z;
00256 const Cell* cells[8];
00257 const Cell* c = g->cell;
00258 const Cell* cx1 = gx1->cell;
00259 const Cell* cy1 = gy1->cell;
00260 const Cell* cz1 = gz1->cell;
00261 const Cell* cx1y1 = g->neighbors[1]->neighbors[3]->cell;
00262 const Cell* cx1z1 = g->neighbors[1]->neighbors[5]->cell;
00263 const Cell* cy1z1 = g->neighbors[3]->neighbors[5]->cell;
00264 const Cell* cx1y1z1 = g->neighbors[1]->neighbors[3]->neighbors[5]->cell;
00265 for (z=0; z<GRIDDIM-1; z++)
00266 {
00267 for (y=0; y<GRIDDIM-1; y++)
00268 {
00269 for (x=0; x<GRIDDIM-1; x++)
00270 {
00271 cells[0] = c; cells[1] = c+DX; cells[2] = c+DY; cells[3] = c+DX+DY;
00272 cells[4] = cells[0]+DZ; cells[5] = cells[1]+DZ; cells[6] = cells[2]+DZ; cells[7] = cells[3]+DZ;
00273 createFaces(out, cells, isoval);
00274 c+=DX;
00275 }
00276
00277 cells[0] = c; cells[1] = cx1; cells[2] = c+DY; cells[3] = cx1+DY;
00278 cells[4] = cells[0]+DZ; cells[5] = cells[1]+DZ; cells[6] = cells[2]+DZ; cells[7] = cells[3]+DZ;
00279 createFaces(out, cells, isoval);
00280 c+=DX;
00281 cx1+=DY;
00282 }
00283
00284 {
00285 for (x=0; x<GRIDDIM-1; x++)
00286 {
00287 cells[0] = c; cells[1] = c+DX; cells[2] = cy1; cells[3] = cy1+DX;
00288 cells[4] = cells[0]+DZ; cells[5] = cells[1]+DZ; cells[6] = cells[2]+DZ; cells[7] = cells[3]+DZ;
00289 createFaces(out, cells, isoval);
00290 c+=DX;
00291 cy1+=DX;
00292 }
00293
00294 cells[0] = c; cells[1] = cx1; cells[2] = cy1; cells[3] = cx1y1;
00295 cells[4] = cells[0]+DZ; cells[5] = cells[1]+DZ; cells[6] = cells[2]+DZ; cells[7] = cells[3]+DZ;
00296 createFaces(out, cells, isoval);
00297 c+=DX;
00298 cx1+=DY;
00299 cy1+=DZ+DX-DY;
00300 cx1y1+=DZ;
00301 }
00302 }
00303
00304 for (y=0; y<GRIDDIM-1; y++)
00305 {
00306 for (x=0; x<GRIDDIM-1; x++)
00307 {
00308 cells[0] = c; cells[1] = c+DX; cells[2] = c+DY; cells[3] = c+DX+DY;
00309 cells[4] = cz1; cells[5] = cz1+DX; cells[6] = cz1+DY; cells[7] = cz1+DX+DY;
00310 createFaces(out, cells, isoval);
00311 c+=DX;
00312 cz1+=DX;
00313 }
00314
00315 cells[0] = c; cells[1] = cx1; cells[2] = c+DY; cells[3] = cx1+DY;
00316 cells[4] = cz1; cells[5] = cx1z1; cells[6] = cz1+DY; cells[7] = cx1z1+DY;
00317 createFaces(out, cells, isoval);
00318 c+=DX;
00319 cx1+=DY;
00320 cz1+=DX;
00321 cx1z1+=DY;
00322 }
00323
00324 {
00325 for (x=0; x<GRIDDIM-1; x++)
00326 {
00327 cells[0] = c; cells[1] = c+DX; cells[2] = cy1; cells[3] = cy1+DX;
00328 cells[4] = cz1; cells[5] = cz1+DX; cells[6] = cy1z1; cells[7] = cy1z1+DX;
00329 createFaces(out, cells, isoval);
00330 c+=DX;
00331 cy1+=DX;
00332 cz1+=DX;
00333 cy1z1+=DX;
00334 }
00335
00336 cells[0] = c; cells[1] = cx1; cells[2] = cy1; cells[3] = cx1y1;
00337 cells[4] = cz1; cells[5] = cx1z1; cells[6] = cy1z1; cells[7] = cx1y1z1;
00338 createFaces(out, cells, isoval);
00339 }
00340 }
00341
00342
00343 }
00344
00345 template <class In, class Out>
00346 void SPHFluidSurfaceMapping<In,Out>::applyJ( OutVecDeriv& , const InVecDeriv& )
00347 {
00348 }
00349
00350 template <class In, class Out>
00351 void SPHFluidSurfaceMapping<In,Out>::draw()
00352 {
00353 if (!getContext()->getShowMappings()) return;
00354 if (!grid) return;
00355 grid->draw();
00356
00357 float scale = (float)mStep.getValue();
00358 typename Grid::iterator end = grid->gridEnd();
00359 typename Grid::iterator it;
00360
00361 glPointSize(3);
00362 glColor4f(1,1,1,1);
00363 glBegin(GL_POINTS);
00364 for (it = grid->gridBegin();it!=end;++it)
00365 {
00366 typename Grid::Key p0 = it->first;
00367 const int x0 = p0[0]*GRIDDIM;
00368 const int y0 = p0[1]*GRIDDIM;
00369 const int z0 = p0[2]*GRIDDIM;
00370 typename Grid::Grid* g = it->second;
00371 int x,y,z;
00372 Cell* c = g->cell;
00373 for (z=0; z<GRIDDIM; z++)
00374 {
00375 for (y=0; y<GRIDDIM; y++)
00376 {
00377 for (x=0; x<GRIDDIM; x++)
00378 {
00379 if (c->data.val > mIsoValue.getValue())
00380 glVertex3f((x0+x)*scale,(y0+y)*scale,(z0+z)*scale);
00381 c+=DX;
00382 }
00383 }
00384 }
00385 }
00386 glEnd();
00387 glPointSize(1);
00388
00389 glPointSize(5);
00390 glColor4f(0.5f,1,0.5f,1);
00391 glBegin(GL_POINTS);
00392 const OutVecCoord& out = *this->toModel->getX();
00393 for (unsigned int i=0; i<out.size(); ++i)
00394 {
00395 helper::gl::glVertexT(out[i]);
00396 }
00397 glEnd();
00398 glPointSize(1);
00399
00400
00401 glColor4f(0,1,0,1);
00402 glBegin(GL_LINES);
00403 for (it = grid->gridBegin();it!=end;++it)
00404 {
00405 typename Grid::Key p0 = it->first;
00406 const int x0 = p0[0]*GRIDDIM;
00407 const int y0 = p0[1]*GRIDDIM;
00408 const int z0 = p0[2]*GRIDDIM;
00409 typename Grid::Grid* g = it->second;
00410 int x,y,z;
00411 Cell* c = g->cell;
00412 for (z=0; z<GRIDDIM; z++)
00413 {
00414 for (y=0; y<GRIDDIM; y++)
00415 {
00416 for (x=0; x<GRIDDIM; x++)
00417 {
00418 if (c->data.p[0]>0)
00419 {
00420 glVertex3f((x0+x)*scale,(y0+y)*scale,(z0+z)*scale);
00421 glVertex3f((x0+x+1)*scale,(y0+y)*scale,(z0+z)*scale);
00422 }
00423 if (c->data.p[1]>0)
00424 {
00425 glVertex3f((x0+x)*scale,(y0+y)*scale,(z0+z)*scale);
00426 glVertex3f((x0+x)*scale,(y0+y+1)*scale,(z0+z)*scale);
00427 }
00428 if (c->data.p[2]>0)
00429 {
00430 glVertex3f((x0+x)*scale,(y0+y)*scale,(z0+z)*scale);
00431 glVertex3f((x0+x)*scale,(y0+y)*scale,(z0+z+1)*scale);
00432 }
00433 c+=DX;
00434 }
00435 }
00436 }
00437 }
00438 glEnd();
00439
00440 }
00441
00442 }
00443
00444 }
00445
00446 }
00447
00448 #endif