00001 # ifndef shape_marching_cube_hpp
00002 # define shape_marching_cube_hpp
00003
00004
00005
00006
00007
00008 # define ULONG unsigned long
00009 # define TMPL template<class K>
00010
00011 namespace mmx { namespace shape {
00012
00013 extern int marching_cube_edge_table[256];
00014 extern int marching_cube_tri_table[256][16] ;
00015
00016 template <class C, class POINT>
00017 void mc_interpolate(POINT& p, const POINT& p1, const POINT& p2, C valp1, const C& valp2, const C& iso=0)
00018 {
00019 if (abs(iso-valp1) < 0.00001) p=p1;
00020 if (abs(iso-valp2) < 0.00001) p=p2;
00021 if (abs(valp1-valp2) < 0.00001) p=p1;
00022
00023 C mu = (iso - valp1) / (valp2 - valp1);
00024
00025 p.x() = p1.x() + mu * (p2.x() - p1.x());
00026 p.y() = p1.y() + mu * (p2.y() - p1.y());
00027 p.z() = p1.z() + mu * (p2.z() - p1.z());
00028 }
00029
00030 struct marching_square {
00031
00032 public:
00033
00034 marching_square(void) {};
00035 ~marching_square(void){};
00036
00037 template<class Mesh, class POINTS, class VALUES, class C>
00038 static bool polygonize(Mesh& res, const POINTS& points, const VALUES& values, const C& lvl);
00039
00040 };
00041
00042 template<class Mesh, class POINTS, class VALUES, class C> bool
00043 marching_square::polygonize(Mesh& res, const POINTS& P, const VALUES& val, const C& lvl) {
00044
00045 typedef typename Mesh::Point Point;
00046 typedef typename Mesh::Edge Edge;
00047
00048 Point pt[4];
00049
00050 int nrPoint=0;
00051
00052 if(val[0]>lvl)
00053 {
00054 if(val[1]<=lvl)
00055 {
00056 mc_interpolate(pt[nrPoint++], P[0], P[1], val[0], val[1], lvl);
00057 }
00058
00059 if(val[3]<=lvl)
00060 {
00061 mc_interpolate(pt[nrPoint++], P[0], P[3], val[0], val[3], lvl);
00062 }
00063 }
00064
00065 if(val[1]>lvl)
00066 {
00067 if(val[0]<=lvl)
00068 {
00069 mc_interpolate(pt[nrPoint++], P[1], P[0], val[1], val[0], lvl);
00070 }
00071
00072 if(val[2]<=lvl)
00073 {
00074 mc_interpolate(pt[nrPoint++], P[1], P[2], val[1], val[2], lvl);
00075 }
00076 }
00077
00078
00079 if(val[2]>lvl)
00080 {
00081 if(val[1]<=lvl)
00082 {
00083 mc_interpolate(pt[nrPoint++], P[2], P[1], val[2], val[1], lvl);
00084 }
00085
00086 if(val[3]<=lvl)
00087 {
00088 mc_interpolate(pt[nrPoint++], P[2], P[3], val[2], val[3],lvl);
00089 }
00090 }
00091
00092 if(val[3]>lvl)
00093 {
00094 if(val[2]<=lvl)
00095 {
00096 mc_interpolate(pt[nrPoint++], P[3], P[2], val[3], val[2], lvl);
00097 }
00098
00099 if(val[0]<=lvl)
00100 {
00101 mc_interpolate(pt[nrPoint++], P[3], P[0], val[3], val[0], lvl);
00102 }
00103 }
00104
00105 Point* p1, *p2;
00106 for (int i=0;i < nrPoint;i+=2) {
00107 p1 = new Point(pt[i]);
00108 res.insert_vertex(p1);
00109 p1->set_index(res.vertices().size()-1);
00110 p2 = new Point(pt[i+1]);
00111 res.insert_vertex(p2);
00112 p2->set_index(res.vertices().size()-1);
00113 Edge* e= new Edge(p1, p2);
00114 res.insert_edge(e);
00115 }
00116 return true;
00117 }
00118
00119
00120
00121
00122 struct marching_cube {
00123
00124 public:
00125
00126 marching_cube(void) {};
00127 ~marching_cube(void){};
00128
00129 template<class C>
00130 static int index (C* t, C iso=0);
00131
00132 template<class POINT, class VALUES>
00133 static bool edge_points(POINT* edges, const POINT* points, const VALUES& values, int idx);
00134
00135 template<class Mesh, class Cell>
00136 static bool polygonise(Mesh& res, const Cell& grid);
00137
00138 template<class Mesh, class POINTS>
00139 static bool polygonize(Mesh& res, const POINTS& edges, int cubeindex);
00140
00141 template<class Mesh, class POINTS, class VALUES>
00142 static bool polygonize(Mesh& res, const POINTS& points, const VALUES& values);
00143
00144 template<class Mesh, class Cell>
00145 static bool centralise(Mesh& res, const Cell& grid);
00146
00147 };
00148
00149
00150 template<class C>
00151 int marching_cube::index (C* t, C iso) {
00152 int CubeIndex=0;
00153 int s=1;
00154 for (unsigned i=0; i< 8; i++) {
00155 if (t[i] < iso) CubeIndex |= s;
00156 s*=2;
00157 }
00158 return CubeIndex;
00159 }
00160
00161
00162
00163 template<class Mesh, class Cell> bool
00164 marching_cube::polygonise(Mesh& res, const Cell& bcell) {
00165
00166 typedef typename Mesh::Point Point;
00167 typedef typename Mesh::Face Face;
00168
00169 int CubeIndex=bcell.mc_index();
00170
00171 if (marching_cube_edge_table[CubeIndex] == 0) return false;
00172
00173 Point* CELL[12];
00174 if(bcell.edge_point(CELL, marching_cube_edge_table[CubeIndex])) {
00175 for (int i=0;marching_cube_tri_table[CubeIndex][i]!=-1;i+=3) {
00176 Face* F= new Face;
00177 for(int j=0;j<3;j++) {
00178 Point* p=CELL[marching_cube_tri_table[CubeIndex][i+j]];
00179 res.insert(p);
00180 F->insert(p);
00181 }
00182 res.insert(F);
00183 }
00184 return true;
00185 } else
00186 return false;
00187 }
00188
00189
00190
00191
00192 template<class POINT, class VALUES> bool
00193 marching_cube::edge_points(POINT* edges, const POINT* points, const VALUES& values, int cubeindex) {
00194
00195
00196
00197
00198
00199 if (marching_cube_edge_table[cubeindex] == 0) return false;
00200
00201 if (marching_cube_edge_table[cubeindex] & 1)
00202 mc_interpolate(edges[0], points[0],points[1],values[0],values[1]);
00203 if (marching_cube_edge_table[cubeindex] & 2)
00204 mc_interpolate(edges[1], points[1],points[2],values[1],values[2]);
00205 if (marching_cube_edge_table[cubeindex] & 4)
00206 mc_interpolate(edges[2], points[2],points[3],values[2],values[3]);
00207 if (marching_cube_edge_table[cubeindex] & 8)
00208 mc_interpolate(edges[3], points[3],points[0],values[3],values[0]);
00209 if (marching_cube_edge_table[cubeindex] & 16)
00210 mc_interpolate(edges[4], points[4],points[5],values[4],values[5]);
00211 if (marching_cube_edge_table[cubeindex] & 32)
00212 mc_interpolate(edges[5], points[5],points[6],values[5],values[6]);
00213 if (marching_cube_edge_table[cubeindex] & 64)
00214 mc_interpolate(edges[6], points[6],points[7],values[6],values[7]);
00215 if (marching_cube_edge_table[cubeindex] & 128)
00216 mc_interpolate(edges[7], points[7],points[4],values[7],values[4]);
00217 if (marching_cube_edge_table[cubeindex] & 256)
00218 mc_interpolate(edges[8], points[0],points[4],values[0],values[4]);
00219 if (marching_cube_edge_table[cubeindex] & 512)
00220 mc_interpolate(edges[9], points[1],points[5],values[1],values[5]);
00221 if (marching_cube_edge_table[cubeindex] & 1024)
00222 mc_interpolate(edges[10], points[2],points[6],values[2],values[6]);
00223 if (marching_cube_edge_table[cubeindex] & 2048)
00224 mc_interpolate(edges[11], points[3],points[7],values[3],values[7]);
00225 return true;
00226 }
00227
00228
00229
00230
00231 template<class Mesh, class POINTS> bool
00232 marching_cube::polygonize(Mesh& res, const POINTS& edges, int cubeindex) {
00233
00234 typedef typename Mesh::Point Point;
00235 for (int i=0;marching_cube_tri_table[cubeindex][i]!=-1;i+=3) {
00236
00237
00238
00239
00240
00241 res.insert_face(new Point(edges[marching_cube_tri_table[cubeindex][i]]),
00242 new Point(edges[marching_cube_tri_table[cubeindex][i+1]]),
00243 new Point(edges[marching_cube_tri_table[cubeindex][i+2]]));
00244 }
00245 return true;
00246 }
00247
00248 template<class Mesh, class POINTS, class VALUES> bool
00249 marching_cube::polygonize(Mesh& res, const POINTS& points, const VALUES& values) {
00250
00251 typedef typename Mesh::Point Point;
00252 typedef typename Mesh::Face Face;
00253
00254 int cubeindex=marching_cube::index(values);
00255 Point edges[12];
00256 marching_cube::edge_points(edges, points, values, cubeindex);
00257 marching_cube::polygonize(res, edges, cubeindex);
00258 return true;
00259 }
00260
00261
00262
00263
00264 template<class Mesh, class Cell> bool
00265 marching_cube::centralise(Mesh& res, const Cell& bcell) {
00266
00267 typedef typename Mesh::Point Point;
00268 typedef typename Mesh::Face Face;
00269
00270 int CubeIndex=bcell.mc_index();
00271
00272 if (marching_cube_edge_table[CubeIndex] == 0) return false;
00273
00274 Point* CELL[12];
00275
00276 if(bcell.edge_point(CELL, marching_cube_edge_table[CubeIndex])) {
00277 Point* c=new Point(0,0,0);
00278 unsigned ntr=0;
00279 for (int i=0;marching_cube_tri_table[CubeIndex][i]!=-1;i+=3)
00280 ntr++;
00281 ntr/=2;
00282
00283 for(int j=0;j<3;j++) {
00284 Point* p=CELL[marching_cube_tri_table[CubeIndex][3*ntr+j]];
00285 c->x()+= p->x();
00286 c->y()+= p->y();
00287 c->z()+= p->z();
00288 }
00289 c->x()/=3.;
00290 c->y()/=3.;
00291 c->z()/=3.;
00292
00293
00294
00295
00296 res.insert(c);
00297 return true;
00298 } else
00299 return false;
00300 }
00301
00302
00303 }
00304 }
00305 # undef TMPL
00306 # undef ULONG
00307 # endif //shape_marching_cube_hpp