I see the wisdom of your words, but I think it's more complicated than just generalizing from the 15 cases. The way I'm doing it, the vertices get computed in a specific order for each cell in such a way that the vertices aren't always ordered the same relative to each other across instances of the same case. So if I just define 1 set if indices for each case, some triangles are going to get flipped. The obvious solution is to get rid of backface culling, but I only want to do that if forced to.
The table used for actually computing the vertices was not hand-written, I got it from a website (probably the same one crimsontide found).
Ensuring the winding order of triangles is valid is trivial, hence no need to remove backface culling. But that's not the issue here.
The vertices are created along the cube's edges, 12 to be exact. The order/positioning of the edges is ordered and does not change. Geti is correct, in the original marching cubes paper the 256 cases are actually derived from 15 unique cases which are just rotated/mirrored a half dozen times. So whether you have a large table that handles all possible 256 cases, or generate one from the original 15, it's pretty much the same thing.
You mentioned having problems with normals and stuff about handwritten tables which has me kinda confused. The normals are generated in the same way as vertex positions, and any other vertex-specific data (texture coords, colors, blending coefficients, ect...). The vertices of the cube are not vertices in the final output, think of them like control points. You generate the 8 control points (perhaps from voxel data, perhaps dynamically, its all the same) and the control points can have more than just position data, they can have texture mapping coords, normals, colors, anything really with them. Now you create your 12 edge vertices by linearly interpolating the adjacent control points along each edge. Your interpolation 'amount' is determined by the iso-surface values at each of the 2 control points you're interpolating across, and the iso-surface threshold that defines the surface (you're doing that right?). This will give you up to 12 vertices (in the case where both control points of an edge are on the same side of the iso-surface threshold, you won't get a vertex). These 12 vertices will have position data, possibly normal data, color data, texture data, and whatever else you want.
Now you need to store these edge vertices in a vector, possibly array, vertex buffer, or whatever. As you add them (in order) store the current offset of each vertex in a temporary variable. This is its index. You can now discard the 12 vertices, all you need is their indices which you have (well mentally discard, you don't need to really discard them as they are probably just a small array of temporary variables defined at the begining of the function).
Now you use the 8 control points to look up the marching cube 'case'. Each of the 8 control points are either in or out, which is mapped to a 0 or 1 depending on how you generated the table and/or where you pilfered it from (like in my case ; ). Or'd together the 8 'bits' now give you the marching cube 'case'. This will be a list of indices into the 12 edge vertices. Now you start adding indices to your index vector/array/buffer/whatever. For example if the list says '0, 8, 3' then you push to the index vector/array/buffer/whatever the index you previously stored for edge vertex 0, then the index for edge vertex 8, then the index for edge vertex 3.
The triangles generated will always be in the winding order that the table specifies, so backface culling will work. The actual vertex data can store anything that can be linearly interpolated; normals, colors, texture coords all work fine. Does that make sense?