If you account for symmetries, there are really only 14 unique configurations in the remaining 254 possibilities. When there is only one corner less than the isovalue, this forms a single triangle which intersects the edges which meet at this corner, with the patch normal facing away from the corner. Obviously there are 8 related configurations of this sort (e.g. for configuration 2 - you may need to tweak the colormap to see the plane between the spheres/pixels). By reversing the normal we get 8 configurations which have 7 corners less than the isovalue. We don't consider these really unique, however. For configurations with 2 corners less than the isovalue, there are 3 unique configurations (e.g. for configuration 12), depending on whether the corners belong to the same edge, belong the same face of the cube, or are diagonally positioned relative to each other. For configurations with 3 corners less than the isovalue there are again 3 unique configurations (e.g. for configuration 14), depending on whether there are 0, 1, or 2 shared edges (2 shared edges gives you an 'L' shape). There are 7 unique configurations when you have 4 corners less than the isovalue, depending on whether there are 0, 2, 3 (3 variants on this one), or 4 shared edges (e.g. for configuration 30 - again you may need to tweak the colors to see the triangle for the isolated (far) inside sphere/pixel).
Each of the non-trivial configurations results in between 1 and 4 triangles being added to the isosurface. The actual vertices themselves can be computed by interpolation along edges, or, as I did, default their location to the middle of the edge. The interpolated locations will obviously give you better shading calculations and smoother surfaces.
Now that we can create surface patches for a single voxel, we can apply this process to the entire volume. We can process the volume in slabs, where each slab is comprised of 2 slices of pixels. We can either treat each cube independently, or we can propogate edge intersections between cubes which share the edges. This sharing can also be done between adjacent slabs, which increases storage and complexity a bit, but saves in computation time. The sharing of edge/vertex information also results in a more compact model, and one that is more amenable to interpolated shading.
The program mcube.c accepts a data file and an isovalue, reads the configuration table, and "marches" through the volume, classifying cubes and outputing triangles as it goes (each row of output is the number 3, followed by 3 sets of 3-D floating point coordinates). No attempt is made to share vertices or edges between triangles, which leads to pretty large output files. The program tri_inventor.c takes this output and creates a scene graph that can be imported into IRIS Inventor or Open Inventor. This can make a REALY large file, based on your data set and isovalue (press here for some sample output).
Another problem arises when you don't have a filled space of voxels. Depending on how the volume data was acquired there may be voids which need to be assigned values or circumnavigated in the surface generation algorithm. Any interpolated value used may reduce the validity of the resulting surface.
A final alternate strategy would be to ray trace the original volume data, which may be the topic of a future presentation.
matt@owl.WPI.EDU