Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Isosurface.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2011 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include <math.h>
00012 #include "Inform.h"
00013 #include "utilities.h"
00014 
00015 #define ISOSURFACE_INTERNAL 1
00016 #include "Isosurface.h"
00017 #include "VolumetricData.h"
00018 
00019 #define MIN(X,Y) (((X)<(Y))? (X) : (Y))
00020 #define MAX(X,Y) (((X)>(Y))? (X) : (Y))
00021 
00022 IsoSurface::IsoSurface(void) {}
00023 
00024 void IsoSurface::clear(void) {
00025   numtriangles=0;
00026   v.clear();
00027   n.clear();
00028   c.clear();
00029   f.clear();
00030 }
00031 
00032 
00033 int IsoSurface::compute(const VolumetricData *data, float isovalue, int step) {
00034   int x, y, z; 
00035   int tricount=0;
00036 
00037   vol=data;
00038 
00039   // calculate cell axes
00040   vol->cell_axes(xax, yax, zax);
00041   vol->cell_dirs(xad, yad, zad);
00042 
00043   // flip normals if coordinate system is in the wrong handedness
00044   float vtmp[3];
00045   cross_prod(vtmp, xad, yad);
00046   if (dot_prod(vtmp, zad) < 0) {
00047     xad[0] *= -1;
00048     xad[1] *= -1;
00049     xad[2] *= -1;
00050     yad[0] *= -1;
00051     yad[1] *= -1;
00052     yad[2] *= -1;
00053     zad[0] *= -1;
00054     zad[1] *= -1;
00055     zad[2] *= -1;
00056   }
00057 
00058   int i;
00059   int axisposnorms = 1;
00060   for (i=0; i<3; i++) {
00061     if (xad[i] < 0 || yad[i] < 0 || zad[i] < 0)  
00062       axisposnorms = 0;
00063   }
00064 
00065   // check that the grid is axis-aligned
00066   if (axisposnorms) {
00067     float xtmp[3] = {1.0f, 0.0f, 0.0f};
00068     if (dot_prod(xtmp, xax) != xax[0])
00069       axisposnorms = 0;
00070 
00071     float ytmp[3] = {0.0f, 1.0f, 0.0f};
00072     if (dot_prod(ytmp, yax) != yax[1])
00073       axisposnorms = 0;
00074 
00075     float ztmp[3] = {0.0f, 0.0f, 1.0f};
00076     if (dot_prod(ztmp, zax) != zax[2])
00077       axisposnorms = 0;
00078   }
00079 
00080   if (axisposnorms) {
00081     tricount = DoGridPosNorms(isovalue, step);
00082   } else {
00083     // general case, any handedness, non-rectangular grids
00084     for (z=0; z<(vol->zsize - step); z+=step) {
00085       for (y=0; y<(vol->ysize - step); y+=step) {
00086         for (x=0; x<(vol->xsize - step); x+=step) {
00087           tricount += DoCellGeneral(x, y, z, isovalue, step);
00088         }
00089       }
00090     }
00091   }
00092 
00093   return 1;
00094 }
00095 
00096 
00097 //
00098 // Special case for axis-aligned grid with positive unit vector normals
00099 //
00100 int IsoSurface::DoGridPosNorms(float isovalue, int step) {
00101   GRIDCELL gc;
00102   TRIANGLE tris[5];
00103   int tricount=0;
00104   int globtricount=0;
00105   int row = vol->xsize; 
00106   int plane = vol->xsize * vol->ysize;
00107   int rowstep = row*step;
00108   int planestep = plane*step;
00109 
00110   int x, y, z;
00111   for (z=0; z<(vol->zsize - step); z+=step) {
00112     for (y=0; y<(vol->ysize - step); y+=step) {
00113       for (x=0; x<(vol->xsize - step); x+=step) {
00114         int addr = z*plane + y*row + x;
00115         gc.val[0] = vol->data[addr                             ];
00116         gc.val[1] = vol->data[addr + step                      ];
00117         gc.val[3] = vol->data[addr +        rowstep            ];
00118         gc.val[2] = vol->data[addr + step + rowstep            ];
00119         gc.val[4] = vol->data[addr +                  planestep];
00120         gc.val[5] = vol->data[addr + step +           planestep];
00121         gc.val[7] = vol->data[addr +        rowstep + planestep];
00122         gc.val[6] = vol->data[addr + step + rowstep + planestep];
00123 
00124         // Determine the index into the edge table which
00125         // tells us which vertices are inside of the surface
00126         int cubeindex = 0;
00127         if (gc.val[0] < isovalue) cubeindex |= 1;
00128         if (gc.val[1] < isovalue) cubeindex |= 2;
00129         if (gc.val[2] < isovalue) cubeindex |= 4;
00130         if (gc.val[3] < isovalue) cubeindex |= 8;
00131         if (gc.val[4] < isovalue) cubeindex |= 16;
00132         if (gc.val[5] < isovalue) cubeindex |= 32;
00133         if (gc.val[6] < isovalue) cubeindex |= 64;
00134         if (gc.val[7] < isovalue) cubeindex |= 128;
00135 
00136         // Cube is entirely in/out of the surface
00137         if (edgeTable[cubeindex] == 0)
00138           continue;
00139 
00140         gc.cubeindex = cubeindex;
00141 
00142         gc.p[0].x = (float) x;
00143         gc.p[0].y = (float) y;
00144         gc.p[0].z = (float) z;
00145         VOXEL_GRADIENT_FAST(vol, x, y, z, &gc.g[0].x)
00146 
00147         gc.p[1].x = (float) x + step;
00148         gc.p[1].y = (float) y;
00149         gc.p[1].z = (float) z;
00150         VOXEL_GRADIENT_FAST(vol, x + step, y, z, &gc.g[1].x)
00151 
00152         gc.p[3].x = (float) x;
00153         gc.p[3].y = (float) y + step;
00154         gc.p[3].z = (float) z;
00155         VOXEL_GRADIENT_FAST(vol, x, y + step, z, &gc.g[3].x)
00156 
00157         gc.p[2].x = (float) x + step;
00158         gc.p[2].y = (float) y + step;
00159         gc.p[2].z = (float) z;
00160         VOXEL_GRADIENT_FAST(vol, x + step, y + step, z, &gc.g[2].x)
00161 
00162         gc.p[4].x = (float) x;
00163         gc.p[4].y = (float) y;
00164         gc.p[4].z = (float) z + step;
00165         VOXEL_GRADIENT_FAST(vol, x, y, z + step, &gc.g[4].x)
00166 
00167         gc.p[5].x = (float) x + step;
00168         gc.p[5].y = (float) y;
00169         gc.p[5].z = (float) z + step;
00170         VOXEL_GRADIENT_FAST(vol, x + step, y, z + step, &gc.g[5].x)
00171 
00172         gc.p[7].x = (float) x;
00173         gc.p[7].y = (float) y + step;
00174         gc.p[7].z = (float) z + step;
00175         VOXEL_GRADIENT_FAST(vol, x, y + step, z + step, &gc.g[7].x)
00176 
00177         gc.p[6].x = (float) x + step;
00178         gc.p[6].y = (float) y + step;
00179         gc.p[6].z = (float) z + step;
00180         VOXEL_GRADIENT_FAST(vol, x + step, y + step, z + step, &gc.g[6].x)
00181 
00182         // calculate vertices and facets for this cube,
00183         // calculate normals by interpolating between the negated 
00184         // normalized volume gradients for the 8 reference voxels
00185         tricount = Polygonise(gc, isovalue, (TRIANGLE *) &tris);
00186         globtricount += tricount;
00187 
00188         int i;
00189         for (i=0; i<tricount; i++) {
00190           float xx, yy, zz;
00191           f.append(numtriangles * 3    );
00192           f.append(numtriangles * 3 + 1);
00193           f.append(numtriangles * 3 + 2);
00194           numtriangles++;
00195 
00196           // add new vertices and normals into vertex and normal lists
00197           xx = tris[i].p[0].x;
00198           yy = tris[i].p[0].y;
00199           zz = tris[i].p[0].z;
00200           v.append((float) vol->origin[0] + xx * xax[0]);
00201           v.append((float) vol->origin[1] + yy * yax[1]);
00202           v.append((float) vol->origin[2] + zz * zax[2]);
00203 
00204           n.append(tris[i].n[0].x);
00205           n.append(tris[i].n[0].y);
00206           n.append(tris[i].n[0].z);
00207 
00208           xx = tris[i].p[1].x;
00209           yy = tris[i].p[1].y;
00210           zz = tris[i].p[1].z;
00211           v.append((float) vol->origin[0] + xx * xax[0]);
00212           v.append((float) vol->origin[1] + yy * yax[1]);
00213           v.append((float) vol->origin[2] + zz * zax[2]);
00214           n.append(tris[i].n[1].x);
00215           n.append(tris[i].n[1].y);
00216           n.append(tris[i].n[1].z);
00217 
00218           xx = tris[i].p[2].x;
00219           yy = tris[i].p[2].y;
00220           zz = tris[i].p[2].z;
00221           v.append((float) vol->origin[0] + xx * xax[0]);
00222           v.append((float) vol->origin[1] + yy * yax[1]);
00223           v.append((float) vol->origin[2] + zz * zax[2]);
00224           n.append(tris[i].n[2].x);
00225           n.append(tris[i].n[2].y);
00226           n.append(tris[i].n[2].z);
00227         }
00228       }
00229     }
00230   }
00231 
00232   return globtricount;
00233 }
00234 
00235 
00236 int IsoSurface::DoCellGeneral(int x, int y, int z, float isovalue, int step) {
00237   GRIDCELL gc;
00238   int addr, row, plane, rowstep, planestep, tricount;
00239   TRIANGLE tris[5];
00240 
00241   row = vol->xsize; 
00242   plane = vol->xsize * vol->ysize;
00243   addr = z*plane + y*row + x;
00244   rowstep = row*step;
00245   planestep = plane*step;
00246   
00247   gc.val[0] = vol->data[addr                             ];
00248   gc.val[1] = vol->data[addr + step                      ];
00249   gc.val[3] = vol->data[addr +        rowstep            ];
00250   gc.val[2] = vol->data[addr + step + rowstep            ];
00251   gc.val[4] = vol->data[addr +                  planestep];
00252   gc.val[5] = vol->data[addr + step +           planestep];
00253   gc.val[7] = vol->data[addr +        rowstep + planestep];
00254   gc.val[6] = vol->data[addr + step + rowstep + planestep];
00255 
00256   // Determine the index into the edge table which
00257   // tells us which vertices are inside of the surface
00258   int cubeindex = 0;
00259   if (gc.val[0] < isovalue) cubeindex |= 1;
00260   if (gc.val[1] < isovalue) cubeindex |= 2;
00261   if (gc.val[2] < isovalue) cubeindex |= 4;
00262   if (gc.val[3] < isovalue) cubeindex |= 8;
00263   if (gc.val[4] < isovalue) cubeindex |= 16;
00264   if (gc.val[5] < isovalue) cubeindex |= 32;
00265   if (gc.val[6] < isovalue) cubeindex |= 64;
00266   if (gc.val[7] < isovalue) cubeindex |= 128;
00267 
00268   // Cube is entirely in/out of the surface
00269   if (edgeTable[cubeindex] == 0)
00270     return 0;
00271 
00272   gc.cubeindex = cubeindex;
00273 
00274   gc.p[0].x = (float) x;
00275   gc.p[0].y = (float) y;
00276   gc.p[0].z = (float) z;
00277   VOXEL_GRADIENT_FAST(vol, x, y, z, &gc.g[0].x)
00278 
00279   gc.p[1].x = (float) x + step;
00280   gc.p[1].y = (float) y;
00281   gc.p[1].z = (float) z;
00282   VOXEL_GRADIENT_FAST(vol, x + step, y, z, &gc.g[1].x)
00283 
00284   gc.p[3].x = (float) x;
00285   gc.p[3].y = (float) y + step;
00286   gc.p[3].z = (float) z;
00287   VOXEL_GRADIENT_FAST(vol, x, y + step, z, &gc.g[3].x)
00288 
00289   gc.p[2].x = (float) x + step;
00290   gc.p[2].y = (float) y + step;
00291   gc.p[2].z = (float) z;
00292   VOXEL_GRADIENT_FAST(vol, x + step, y + step, z, &gc.g[2].x)
00293 
00294   gc.p[4].x = (float) x;
00295   gc.p[4].y = (float) y;
00296   gc.p[4].z = (float) z + step;
00297   VOXEL_GRADIENT_FAST(vol, x, y, z + step, &gc.g[4].x)
00298 
00299   gc.p[5].x = (float) x + step;
00300   gc.p[5].y = (float) y;
00301   gc.p[5].z = (float) z + step;
00302   VOXEL_GRADIENT_FAST(vol, x + step, y, z + step, &gc.g[5].x)
00303 
00304   gc.p[7].x = (float) x;
00305   gc.p[7].y = (float) y + step;
00306   gc.p[7].z = (float) z + step;
00307   VOXEL_GRADIENT_FAST(vol, x, y + step, z + step, &gc.g[7].x)
00308 
00309   gc.p[6].x = (float) x + step;
00310   gc.p[6].y = (float) y + step;
00311   gc.p[6].z = (float) z + step;
00312   VOXEL_GRADIENT_FAST(vol, x + step, y + step, z + step, &gc.g[6].x)
00313 
00314   // calculate vertices and facets for this cube,
00315   // calculate normals by interpolating between the negated 
00316   // normalized volume gradients for the 8 reference voxels
00317   tricount = Polygonise(gc, isovalue, (TRIANGLE *) &tris);
00318 
00319   int i;
00320   for (i=0; i<tricount; i++) {
00321     float xx, yy, zz;
00322     float xn, yn, zn;
00323 
00324     f.append(numtriangles * 3    );
00325     f.append(numtriangles * 3 + 1);
00326     f.append(numtriangles * 3 + 2);
00327     numtriangles++;
00328 
00329     // add new vertices and normals into vertex and normal lists
00330     xx = tris[i].p[0].x;
00331     yy = tris[i].p[0].y;
00332     zz = tris[i].p[0].z;
00333 
00334     v.append((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0]);
00335     v.append((float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1]);
00336     v.append((float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00337 
00338     xn = tris[i].n[0].x;
00339     yn = tris[i].n[0].y;
00340     zn = tris[i].n[0].z;
00341     n.append((float) xn * xad[0] + yn * yad[0] + zn * zad[0]);
00342     n.append((float) xn * xad[1] + yn * yad[1] + zn * zad[1]);
00343     n.append((float) xn * xad[2] + yn * yad[2] + zn * zad[2]);
00344 
00345     xx = tris[i].p[1].x;
00346     yy = tris[i].p[1].y;
00347     zz = tris[i].p[1].z;
00348     v.append((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0]);
00349     v.append((float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1]);
00350     v.append((float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00351     xn = tris[i].n[1].x;
00352     yn = tris[i].n[1].y;
00353     zn = tris[i].n[1].z;
00354     n.append((float) xn * xad[0] + yn * yad[0] + zn * zad[0]);
00355     n.append((float) xn * xad[1] + yn * yad[1] + zn * zad[1]);
00356     n.append((float) xn * xad[2] + yn * yad[2] + zn * zad[2]);
00357 
00358     xx = tris[i].p[2].x;
00359     yy = tris[i].p[2].y;
00360     zz = tris[i].p[2].z;
00361     v.append((float) vol->origin[0] + xx * xax[0] + yy * yax[0] + zz * zax[0]);
00362     v.append((float) vol->origin[1] + xx * xax[1] + yy * yax[1] + zz * zax[1]);
00363     v.append((float) vol->origin[2] + xx * xax[2] + yy * yax[2] + zz * zax[2]);
00364     xn = tris[i].n[2].x;
00365     yn = tris[i].n[2].y;
00366     zn = tris[i].n[2].z;
00367     n.append((float) xn * xad[0] + yn * yad[0] + zn * zad[0]);
00368     n.append((float) xn * xad[1] + yn * yad[1] + zn * zad[1]);
00369     n.append((float) xn * xad[2] + yn * yad[2] + zn * zad[2]);
00370   }
00371 
00372   return tricount;
00373 }
00374 
00375 
00376 
00377 // normalize surface normals resulting from interpolation between 
00378 // unnormalized volume gradients
00379 void IsoSurface::normalize() {
00380   int i;
00381   for (i=0; i<n.num(); i+=3) {
00382     vec_normalize(&n[i]); 
00383   }  
00384 }
00385 
00386 // merge duplicated vertices detected by a simple windowed search
00387 int IsoSurface::vertexfusion(const VolumetricData *data, int offset, int len) {
00388   int i, j, newverts, oldverts, faceverts, matchcount;
00389 
00390   faceverts = f.num();
00391   oldverts = v.num() / 3; 
00392 
00393   // abort if we get an empty list
00394   if (!faceverts || !oldverts)
00395     return 0;
00396 
00397   int * vmap = new int[oldverts];
00398 
00399   vmap[0] = 0;
00400   newverts = 1;
00401   matchcount = 0;
00402 
00403   for (i=1; i<oldverts; i++) {
00404     int matchindex = -1;
00405     int start = ((newverts - offset) < 0)  ? 0        : (newverts - offset);
00406     int end   = ((start + len) > newverts) ? newverts : (start + len);
00407     int matched = 0;
00408     int vi = i * 3;
00409     for (j=start; j<end; j++) {
00410       int vj = j * 3;
00411       if (v[vi  ] == v[vj  ] && 
00412           v[vi+1] == v[vj+1] &&
00413           v[vi+2] == v[vj+2]) {
00414         matched = 1;
00415         matchindex = j;
00416         matchcount++;
00417         break;
00418       } 
00419     }
00420 
00421     if (matched) {
00422       vmap[i] = matchindex;
00423     } else {
00424       int vn = newverts * 3;
00425       v[vn    ] = v[vi    ];
00426       v[vn + 1] = v[vi + 1];
00427       v[vn + 2] = v[vi + 2];
00428       n[vn    ] = n[vi    ];
00429       n[vn + 1] = n[vi + 1];
00430       n[vn + 2] = n[vi + 2];
00431       vmap[i] = newverts;
00432       newverts++;
00433     } 
00434   }
00435 
00436 //  printf("Info) Vertex fusion: found %d shared vertices of %d, %d unique\n",
00437 //         matchcount, oldverts, newverts);
00438 
00439   // zap the old face, vertex, and normal arrays and replace with the new ones
00440   for (i=0; i<faceverts; i++) {
00441     f[i] = vmap[f[i]];
00442   }
00443   delete [] vmap;
00444 
00445   v.truncatelastn((oldverts - newverts) * 3);
00446   n.truncatelastn((oldverts - newverts) * 3);
00447 
00448   return 0;
00449 }
00450 
00451 
00452 /*
00453    Given a grid cell and an isolevel, calculate the triangular
00454    facets required to represent the isosurface through the cell.
00455    Return the number of triangular facets, the array "triangles"
00456    will be loaded up with the vertices at most 5 triangular facets.
00457         0 will be returned if the grid cell is either totally above
00458    of totally below the isolevel.
00459    This code calculates vertex normals by interpolating the volume gradients.
00460 */
00461 int IsoSurface::Polygonise(const GRIDCELL grid, const float isolevel, TRIANGLE *triangles) {
00462    int i,ntriang;
00463    int cubeindex = grid.cubeindex;
00464    XYZ vertlist[12];
00465    XYZ normlist[12];
00466 
00467    /* Find the vertices where the surface intersects the cube */
00468    if (edgeTable[cubeindex] & 1)
00469       VertexInterp(isolevel, grid, 0, 1, &vertlist[0], &normlist[0]);
00470    if (edgeTable[cubeindex] & 2)
00471       VertexInterp(isolevel, grid, 1, 2, &vertlist[1], &normlist[1]);
00472    if (edgeTable[cubeindex] & 4)
00473       VertexInterp(isolevel, grid, 2, 3, &vertlist[2], &normlist[2]);
00474    if (edgeTable[cubeindex] & 8)
00475       VertexInterp(isolevel, grid, 3, 0, &vertlist[3], &normlist[3]);
00476    if (edgeTable[cubeindex] & 16)
00477       VertexInterp(isolevel, grid, 4, 5, &vertlist[4], &normlist[4]);
00478    if (edgeTable[cubeindex] & 32)
00479       VertexInterp(isolevel, grid, 5, 6, &vertlist[5], &normlist[5]);
00480    if (edgeTable[cubeindex] & 64)
00481       VertexInterp(isolevel, grid, 6, 7, &vertlist[6], &normlist[6]);
00482    if (edgeTable[cubeindex] & 128)
00483       VertexInterp(isolevel, grid, 7, 4, &vertlist[7], &normlist[7]);
00484    if (edgeTable[cubeindex] & 256)
00485       VertexInterp(isolevel, grid, 0, 4, &vertlist[8], &normlist[8]);
00486    if (edgeTable[cubeindex] & 512)
00487       VertexInterp(isolevel, grid, 1, 5, &vertlist[9], &normlist[9]);
00488    if (edgeTable[cubeindex] & 1024)
00489       VertexInterp(isolevel, grid, 2, 6, &vertlist[10], &normlist[10]);
00490    if (edgeTable[cubeindex] & 2048)
00491       VertexInterp(isolevel, grid, 3, 7, &vertlist[11], &normlist[11]);
00492 
00493    /* Create the triangle */
00494    ntriang = 0;
00495    for (i=0;triTable[cubeindex][i]!=-1;i+=3) {
00496      triangles[ntriang].p[0] = vertlist[triTable[cubeindex][i  ]];
00497      triangles[ntriang].p[1] = vertlist[triTable[cubeindex][i+1]];
00498      triangles[ntriang].p[2] = vertlist[triTable[cubeindex][i+2]];
00499      triangles[ntriang].n[0] = normlist[triTable[cubeindex][i  ]];
00500      triangles[ntriang].n[1] = normlist[triTable[cubeindex][i+1]];
00501      triangles[ntriang].n[2] = normlist[triTable[cubeindex][i+2]];
00502      ntriang++;
00503    }
00504 
00505    return ntriang;
00506 }
00507 
00508 
00509 /*
00510    Linearly interpolate the position where an isosurface cuts
00511    an edge between two vertices, each with their own scalar value,
00512    interpolating vertex position and vertex normal based on the 
00513    isovalue.
00514 */
00515 void IsoSurface::VertexInterp(float isolevel, const GRIDCELL grid, int ind1, int ind2, XYZ * vert, XYZ * norm) {
00516   XYZ p1 = grid.p[ind1];
00517   XYZ p2 = grid.p[ind2];
00518   XYZ n1 = grid.g[ind1];
00519   XYZ n2 = grid.g[ind2];
00520   float valp1 = grid.val[ind1];
00521   float valp2 = grid.val[ind2];
00522   float isodiffp1   = isolevel - valp1;
00523   float diffvalp2p1 = valp2 - valp1;
00524   float mu = 0.0f;
00525 
00526   // if the difference between vertex values is zero or nearly
00527   // zero, we can get an IEEE NAN for mu.  We must either avoid this
00528   // by testing the denominator beforehand, by coping with the resulting
00529   // NAN value after the fact.  The only important thing is that mu be
00530   // assigned a value between zero and one.
00531   
00532 #if 0
00533   if (fabsf(isodiffp1) < 0.00001) {
00534     *vert = p1;
00535     *norm = n1;
00536     return;
00537   }
00538 
00539   if (fabsf(isolevel-valp2) < 0.00001) {
00540     *vert = p2;
00541     *norm = n2;
00542     return;
00543   }
00544 
00545   if (fabsf(diffvalp2p1) < 0.00001) {
00546     *vert = p1;
00547     *norm = n1;
00548     return;
00549   }
00550 #endif
00551 
00552   if (fabsf(diffvalp2p1) > 0.0f) 
00553     mu = isodiffp1 / diffvalp2p1;
00554 
00555 #if 0
00556   if (mu > 1.0f)
00557     mu=1.0f;
00558 
00559   if (mu < 0.0f)
00560     mu=0.0f;
00561 #endif
00562 
00563   vert->x = p1.x + mu * (p2.x - p1.x);
00564   vert->y = p1.y + mu * (p2.y - p1.y);
00565   vert->z = p1.z + mu * (p2.z - p1.z);
00566 
00567   norm->x = n1.x + mu * (n2.x - n1.x);
00568   norm->y = n1.y + mu * (n2.y - n1.y);
00569   norm->z = n1.z + mu * (n2.z - n1.z);
00570 }
00571 
00572 
00574 int IsoSurface::set_color_rgb3fv(const float *rgb) {
00575   int i;
00576   int numverts = v.num() / 3; 
00577   for (i=0; i<numverts; i++) {
00578     c.append(rgb[0]); // Red
00579     c.append(rgb[1]); // Green
00580     c.append(rgb[2]); // Blue
00581   }
00582 
00583   return 0;
00584 }
00585 
00589 int IsoSurface::set_color_voltex_rgb3fv(const float *voltex) {
00590   int i;
00591   int numverts = v.num() / 3;
00592   int row = vol->xsize; 
00593   int plane = vol->xsize * vol->ysize;
00594  
00595   float xinv = 1.0f / xax[0];
00596   float yinv = 1.0f / yax[1];
00597   float zinv = 1.0f / zax[2];
00598   int xs = vol->xsize - 1;
00599   int ys = vol->ysize - 1;
00600   int zs = vol->zsize - 1;
00601 
00602   for (i=0; i<numverts; i++) {
00603     int ind = i*3;
00604     float vx = ((v[ind    ] - vol->origin[0]) * xinv);
00605     float vy = ((v[ind + 1] - vol->origin[1]) * yinv);
00606     float vz = ((v[ind + 2] - vol->origin[2]) * zinv);
00607 
00608     int x = MIN(MAX(((int) vx), 0), xs);
00609     int y = MIN(MAX(((int) vy), 0), ys);
00610     int z = MIN(MAX(((int) vz), 0), zs);
00611 
00612     int caddr = (z*plane + y*row + x)*3;
00613 
00614 #if 0
00615     // non-interpolated texture lookup
00616     float rgb[3];
00617     vec_copy(rgb, &voltex[caddr]);
00618 
00619     // normalize colors to eliminate gridding artifacts for the time being
00620     vec_normalize(rgb);
00621 #else
00622     float mux = (vx - x);
00623     float muy = (vy - y);
00624     float muz = (vz - z);
00625 
00626     float c0[3], c1[3], c2[3], c3[3]; 
00627 
00628     int caddrp1 = (x < xs) ? caddr+3 : caddr;
00629     c0[0] = (1-mux)*voltex[caddr    ] + mux*voltex[caddrp1    ];
00630     c0[1] = (1-mux)*voltex[caddr + 1] + mux*voltex[caddrp1 + 1];
00631     c0[2] = (1-mux)*voltex[caddr + 2] + mux*voltex[caddrp1 + 2];
00632 
00633     int yinc = (y < ys) ? row*3 : 0; 
00634     caddr += yinc;
00635     caddrp1 += yinc;
00636     c1[0] = (1-mux)*voltex[caddr    ] + mux*voltex[caddrp1    ];
00637     c1[1] = (1-mux)*voltex[caddr + 1] + mux*voltex[caddrp1 + 1];
00638     c1[2] = (1-mux)*voltex[caddr + 2] + mux*voltex[caddrp1 + 2];
00639     
00640     int zinc = (z < zs) ? plane*3 : 0; 
00641     caddr += zinc;
00642     caddrp1 += zinc;
00643     c3[0] = (1-mux)*voltex[caddr    ] + mux*voltex[caddrp1    ];
00644     c3[1] = (1-mux)*voltex[caddr + 1] + mux*voltex[caddrp1 + 1];
00645     c3[2] = (1-mux)*voltex[caddr + 2] + mux*voltex[caddrp1 + 2];
00646 
00647     caddr -= yinc;
00648     caddrp1 -= yinc;
00649     c2[0] = (1-mux)*voltex[caddr    ] + mux*voltex[caddrp1    ];
00650     c2[1] = (1-mux)*voltex[caddr + 1] + mux*voltex[caddrp1 + 1];
00651     c2[2] = (1-mux)*voltex[caddr + 2] + mux*voltex[caddrp1 + 2];
00652 
00653     float cz0[3];
00654     cz0[0] = (1-muy)*c0[0] + muy*c1[0];
00655     cz0[1] = (1-muy)*c0[1] + muy*c1[1];
00656     cz0[2] = (1-muy)*c0[2] + muy*c1[2];
00657 
00658     float cz1[3];
00659     cz1[0] = (1-muy)*c2[0] + muy*c3[0];
00660     cz1[1] = (1-muy)*c2[1] + muy*c3[1];
00661     cz1[2] = (1-muy)*c2[2] + muy*c3[2];
00662    
00663     float rgb[3];
00664     rgb[0] = (1-muz)*cz0[0] + muz*cz1[0];
00665     rgb[1] = (1-muz)*cz0[1] + muz*cz1[1];
00666     rgb[2] = (1-muz)*cz0[2] + muz*cz1[2];
00667 #endif
00668 
00669     c.append(rgb[0]);
00670     c.append(rgb[1]);
00671     c.append(rgb[2]);
00672   }
00673 
00674   return 0;
00675 }
00676 
00677 
00678 
00679 

Generated on Sat May 26 01:48:03 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002