00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <string.h>
00012 #include <math.h>
00013 #include "Inform.h"
00014 #include "utilities.h"
00015
00016 #define ISOSURFACE_INTERNAL 1
00017 #include "Isosurface.h"
00018 #include "VolumetricData.h"
00019
00020 IsoSurface::IsoSurface(void) {}
00021
00022 void IsoSurface::clear(void) {
00023 numtriangles=0;
00024 v.clear();
00025 n.clear();
00026 f.clear();
00027 }
00028
00029
00030 int IsoSurface::compute(const VolumetricData *data, float isovalue, int step) {
00031 int x, y, z;
00032 int tricount=0;
00033
00034 vol=data;
00035
00036
00037 vol->cell_axes(xax, yax, zax);
00038 vol->cell_dirs(xad, yad, zad);
00039
00040
00041 float vtmp[3];
00042 cross_prod(vtmp, xad, yad);
00043 if (dot_prod(vtmp, zad) < 0) {
00044 xad[0] *= -1;
00045 xad[1] *= -1;
00046 xad[2] *= -1;
00047 yad[0] *= -1;
00048 yad[1] *= -1;
00049 yad[2] *= -1;
00050 zad[0] *= -1;
00051 zad[1] *= -1;
00052 zad[2] *= -1;
00053 }
00054
00055 for (z=0; z<(vol->zsize - step); z+=step) {
00056 for (y=0; y<(vol->ysize - step); y+=step) {
00057 for (x=0; x<(vol->xsize - step); x+=step) {
00058 tricount += DoCell(x, y, z, isovalue, step);
00059 }
00060 }
00061 }
00062
00063 return 1;
00064 }
00065
00066
00067
00068 int IsoSurface::DoCell(int x, int y, int z, float isovalue, int step) {
00069 GRIDCELL gc;
00070 int addr, row, plane, rowstep, planestep, tricount;
00071 TRIANGLE tris[5];
00072
00073 row = vol->xsize;
00074 plane = vol->xsize * vol->ysize;
00075 addr = z*plane + y*row + x;
00076 rowstep = row*step;
00077 planestep = plane*step;
00078
00079 gc.val[0] = vol->data[addr ];
00080 gc.val[1] = vol->data[addr + step ];
00081 gc.val[3] = vol->data[addr + rowstep ];
00082 gc.val[2] = vol->data[addr + step + rowstep ];
00083 gc.val[4] = vol->data[addr + planestep];
00084 gc.val[5] = vol->data[addr + step + planestep];
00085 gc.val[7] = vol->data[addr + rowstep + planestep];
00086 gc.val[6] = vol->data[addr + step + rowstep + planestep];
00087
00088
00089
00090
00091
00092 int cubeindex = 0;
00093 if (gc.val[0] < isovalue) cubeindex |= 1;
00094 if (gc.val[1] < isovalue) cubeindex |= 2;
00095 if (gc.val[2] < isovalue) cubeindex |= 4;
00096 if (gc.val[3] < isovalue) cubeindex |= 8;
00097 if (gc.val[4] < isovalue) cubeindex |= 16;
00098 if (gc.val[5] < isovalue) cubeindex |= 32;
00099 if (gc.val[6] < isovalue) cubeindex |= 64;
00100 if (gc.val[7] < isovalue) cubeindex |= 128;
00101
00102
00103 if (edgeTable[cubeindex] == 0)
00104 return(0);
00105 gc.cubeindex = cubeindex;
00106
00107 gc.p[0].x = (float) x;
00108 gc.p[0].y = (float) y;
00109 gc.p[0].z = (float) z;
00110
00111 VOXEL_GRADIENT_FAST(vol, x, y, z, &gc.g[0].x)
00112
00113 gc.p[1].x = (float) x + step;
00114 gc.p[1].y = (float) y;
00115 gc.p[1].z = (float) z;
00116
00117 VOXEL_GRADIENT_FAST(vol, x + step, y, z, &gc.g[1].x)
00118
00119 gc.p[3].x = (float) x;
00120 gc.p[3].y = (float) y + step;
00121 gc.p[3].z = (float) z;
00122
00123 VOXEL_GRADIENT_FAST(vol, x, y + step, z, &gc.g[3].x)
00124
00125 gc.p[2].x = (float) x + step;
00126 gc.p[2].y = (float) y + step;
00127 gc.p[2].z = (float) z;
00128
00129 VOXEL_GRADIENT_FAST(vol, x + step, y + step, z, &gc.g[2].x)
00130
00131 gc.p[4].x = (float) x;
00132 gc.p[4].y = (float) y;
00133 gc.p[4].z = (float) z + step;
00134
00135 VOXEL_GRADIENT_FAST(vol, x, y, z + step, &gc.g[4].x)
00136
00137 gc.p[5].x = (float) x + step;
00138 gc.p[5].y = (float) y;
00139 gc.p[5].z = (float) z + step;
00140
00141 VOXEL_GRADIENT_FAST(vol, x + step, y, z + step, &gc.g[5].x)
00142
00143 gc.p[7].x = (float) x;
00144 gc.p[7].y = (float) y + step;
00145 gc.p[7].z = (float) z + step;
00146
00147 VOXEL_GRADIENT_FAST(vol, x, y + step, z + step, &gc.g[7].x)
00148
00149 gc.p[6].x = (float) x + step;
00150 gc.p[6].y = (float) y + step;
00151 gc.p[6].z = (float) z + step;
00152
00153 VOXEL_GRADIENT_FAST(vol, x + step, y + step, z + step, &gc.g[6].x)
00154
00155
00156
00157
00158 tricount = Polygonise(gc, isovalue, (TRIANGLE *) &tris);
00159
00160 if (tricount > 0) {
00161 int i;
00162
00163 for (i=0; i<tricount; i++) {
00164 float xx, yy, zz;
00165 float xn, yn, zn;
00166
00167 f.append(numtriangles * 3 );
00168 f.append(numtriangles * 3 + 1);
00169 f.append(numtriangles * 3 + 2);
00170 numtriangles++;
00171
00172
00173 xx = tris[i].p[0].x;
00174 yy = tris[i].p[0].y;
00175 zz = tris[i].p[0].z;
00176
00177 v.append((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0]);
00178 v.append((float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1]);
00179 v.append((float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00180
00181 xn = tris[i].n[0].x;
00182 yn = tris[i].n[0].y;
00183 zn = tris[i].n[0].z;
00184 n.append((float) xn * xad[0] + yn * yad[0] + zn * zad[0]);
00185 n.append((float) xn * xad[1] + yn * yad[1] + zn * zad[1]);
00186 n.append((float) xn * xad[2] + yn * yad[2] + zn * zad[2]);
00187
00188 xx = tris[i].p[1].x;
00189 yy = tris[i].p[1].y;
00190 zz = tris[i].p[1].z;
00191 v.append((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0]);
00192 v.append((float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1]);
00193 v.append((float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00194 xn = tris[i].n[1].x;
00195 yn = tris[i].n[1].y;
00196 zn = tris[i].n[1].z;
00197 n.append((float) xn * xad[0] + yn * yad[0] + zn * zad[0]);
00198 n.append((float) xn * xad[1] + yn * yad[1] + zn * zad[1]);
00199 n.append((float) xn * xad[2] + yn * yad[2] + zn * zad[2]);
00200
00201 xx = tris[i].p[2].x;
00202 yy = tris[i].p[2].y;
00203 zz = tris[i].p[2].z;
00204 v.append((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0]);
00205 v.append((float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1]);
00206 v.append((float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00207 xn = tris[i].n[2].x;
00208 yn = tris[i].n[2].y;
00209 zn = tris[i].n[2].z;
00210 n.append((float) xn * xad[0] + yn * yad[0] + zn * zad[0]);
00211 n.append((float) xn * xad[1] + yn * yad[1] + zn * zad[1]);
00212 n.append((float) xn * xad[2] + yn * yad[2] + zn * zad[2]);
00213 }
00214 }
00215
00216 return tricount;
00217 }
00218
00219
00220
00221
00222 void IsoSurface::normalize() {
00223 int i;
00224 for (i=0; i<n.num(); i+=3) {
00225 vec_normalize(&n[i]);
00226 }
00227 }
00228
00229
00230 int IsoSurface::vertexfusion(const VolumetricData *data, int offset, int len) {
00231 int i, j, newverts, oldverts, faceverts, matchcount;
00232
00233 faceverts = f.num();
00234 oldverts = v.num() / 3;
00235
00236
00237 if (!faceverts || !oldverts)
00238 return 0;
00239
00240 int * vmap = new int[oldverts];
00241
00242 vmap[0] = 0;
00243 newverts = 1;
00244 matchcount = 0;
00245
00246 for (i=1; i<oldverts; i++) {
00247 int matchindex = -1;
00248 int start = ((newverts - offset) < 0) ? 0 : (newverts - offset);
00249 int end = ((start + len) > newverts) ? newverts : (start + len);
00250 int matched = 0;
00251 int vi = i * 3;
00252 for (j=start; j<end; j++) {
00253 int vj = j * 3;
00254 if (v[vi ] == v[vj ] &&
00255 v[vi+1] == v[vj+1] &&
00256 v[vi+2] == v[vj+2]) {
00257 matched = 1;
00258 matchindex = j;
00259 matchcount++;
00260 break;
00261 }
00262 }
00263
00264 if (matched) {
00265 vmap[i] = matchindex;
00266 } else {
00267 int vn = newverts * 3;
00268 v[vn ] = v[vi ];
00269 v[vn + 1] = v[vi + 1];
00270 v[vn + 2] = v[vi + 2];
00271 n[vn ] = n[vi ];
00272 n[vn + 1] = n[vi + 1];
00273 n[vn + 2] = n[vi + 2];
00274 vmap[i] = newverts;
00275 newverts++;
00276 }
00277 }
00278
00279
00280
00281
00282
00283 for (i=0; i<faceverts; i++) {
00284 f[i] = vmap[f[i]];
00285 }
00286 delete [] vmap;
00287
00288 v.truncatelastn((oldverts - newverts) * 3);
00289 n.truncatelastn((oldverts - newverts) * 3);
00290
00291 return 0;
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 int IsoSurface::Polygonise(const GRIDCELL grid, const float isolevel, TRIANGLE *triangles) {
00305 int i,ntriang;
00306 int cubeindex = grid.cubeindex;
00307 XYZ vertlist[12];
00308 XYZ normlist[12];
00309
00310
00311 if (edgeTable[cubeindex] & 1)
00312 VertexInterp(isolevel, grid, 0, 1, &vertlist[0], &normlist[0]);
00313 if (edgeTable[cubeindex] & 2)
00314 VertexInterp(isolevel, grid, 1, 2, &vertlist[1], &normlist[1]);
00315 if (edgeTable[cubeindex] & 4)
00316 VertexInterp(isolevel, grid, 2, 3, &vertlist[2], &normlist[2]);
00317 if (edgeTable[cubeindex] & 8)
00318 VertexInterp(isolevel, grid, 3, 0, &vertlist[3], &normlist[3]);
00319 if (edgeTable[cubeindex] & 16)
00320 VertexInterp(isolevel, grid, 4, 5, &vertlist[4], &normlist[4]);
00321 if (edgeTable[cubeindex] & 32)
00322 VertexInterp(isolevel, grid, 5, 6, &vertlist[5], &normlist[5]);
00323 if (edgeTable[cubeindex] & 64)
00324 VertexInterp(isolevel, grid, 6, 7, &vertlist[6], &normlist[6]);
00325 if (edgeTable[cubeindex] & 128)
00326 VertexInterp(isolevel, grid, 7, 4, &vertlist[7], &normlist[7]);
00327 if (edgeTable[cubeindex] & 256)
00328 VertexInterp(isolevel, grid, 0, 4, &vertlist[8], &normlist[8]);
00329 if (edgeTable[cubeindex] & 512)
00330 VertexInterp(isolevel, grid, 1, 5, &vertlist[9], &normlist[9]);
00331 if (edgeTable[cubeindex] & 1024)
00332 VertexInterp(isolevel, grid, 2, 6, &vertlist[10], &normlist[10]);
00333 if (edgeTable[cubeindex] & 2048)
00334 VertexInterp(isolevel, grid, 3, 7, &vertlist[11], &normlist[11]);
00335
00336
00337 ntriang = 0;
00338 for (i=0;triTable[cubeindex][i]!=-1;i+=3) {
00339 triangles[ntriang].p[0] = vertlist[triTable[cubeindex][i ]];
00340 triangles[ntriang].p[1] = vertlist[triTable[cubeindex][i+1]];
00341 triangles[ntriang].p[2] = vertlist[triTable[cubeindex][i+2]];
00342 triangles[ntriang].n[0] = normlist[triTable[cubeindex][i ]];
00343 triangles[ntriang].n[1] = normlist[triTable[cubeindex][i+1]];
00344 triangles[ntriang].n[2] = normlist[triTable[cubeindex][i+2]];
00345 ntriang++;
00346 }
00347
00348 return ntriang;
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358 void IsoSurface::VertexInterp(float isolevel, const GRIDCELL grid, int ind1, int ind2, XYZ * vert, XYZ * norm) {
00359 XYZ p1 = grid.p[ind1];
00360 XYZ p2 = grid.p[ind2];
00361 XYZ n1 = grid.g[ind1];
00362 XYZ n2 = grid.g[ind2];
00363 float valp1 = grid.val[ind1];
00364 float valp2 = grid.val[ind2];
00365 float isodiffp1 = isolevel - valp1;
00366 float diffvalp2p1 = valp2 - valp1;
00367 float mu = 0.0f;
00368
00369
00370
00371
00372
00373
00374
00375 #if 0
00376 if (fabsf(isodiffp1) < 0.00001) {
00377 *vert = p1;
00378 *norm = n1;
00379 return;
00380 }
00381
00382 if (fabsf(isolevel-valp2) < 0.00001) {
00383 *vert = p2;
00384 *norm = n2;
00385 return;
00386 }
00387
00388 if (fabsf(diffvalp2p1) < 0.00001) {
00389 *vert = p1;
00390 *norm = n1;
00391 return;
00392 }
00393 #endif
00394
00395 if (fabsf(diffvalp2p1) > 0.0f)
00396 mu = isodiffp1 / diffvalp2p1;
00397
00398 #if 0
00399 if (mu > 1.0f)
00400 mu=1.0f;
00401
00402 if (mu < 0.0f)
00403 mu=0.0f;
00404 #endif
00405
00406 vert->x = p1.x + mu * (p2.x - p1.x);
00407 vert->y = p1.y + mu * (p2.y - p1.y);
00408 vert->z = p1.z + mu * (p2.z - p1.z);
00409
00410 norm->x = n1.x + mu * (n2.x - n1.x);
00411 norm->y = n1.y + mu * (n2.y - n1.y);
00412 norm->z = n1.z + mu * (n2.z - n1.z);
00413 }
00414