Marching Cube algorithm is a traditional volume-rendering algorithm. The key of this algorithm is the matching judgment of the 15 meta-situations. Since these 15 cases are not variable so people tend to hard-code this information (actually most people will hard-code the whole 256 cases), which can also improve the runtime performance.
In my sample code, I just use the look up table from the first URL. It is a pity that there are no normals information. But the second URL offers the normal calculation method in Java, so that we can add lighting.
Let’s take a look at the core components of the program:
1. Geometry expression
I use a funtion vex_hit(GLfloat x, GLfloat y, GLfloat z) to judge when the 3D point is inside the geometry or not. Mathematically, if the calculated value is minus, the point is in the geometry, as f(X, Y, Z) = ((X-2)/2)^2 + Y^2 + (Z/2)^2 – 1. This is function is the most creative one in the whole program, you can use any valid 3D geometry maths expression here to generate more interesting shapes.
2. Vertex preprocessing
After indicating the marching volume and the unit cube size, what we need is to judge all the vertices by step 1. To eliminate calculation redundance, we can do the processing first before rendering. Consider this: if we handle the vertices cube by cube, all non-edge vertices will be calculated twice.
3. Unit cube case judgment
This is the most critical part of the whole program. By retrieving which vertices of one unit cube are IN the geometry, we can determine the specific case from the look-up table.
4. Normal calculation
To support lighting, we need to calculate the normal for each unit triangle. Since we know all three vertices of the triangle, we can generate the normal by using the cross multiplication. Actually I think it needs more consideration for some specific case. But just using this over-generalized method, the final effect is satisfactory.
Draw all the triangles cube by cube. I think it is a O(n^3) process.
Take a look at a simple geometry:
((X-2)/2)^2 + Y^2 + (Z/2)^2 = 1 OR ((X+2)/2)^2 + Y^2 + (Z/2)^2 = 1
How about 180? It looks much better, but it takes a long time!
Let’s have a look at some more interesting model:
Its geometric expression:
0.0260516*x*x*z*z + 0.028689*y*y + 0.0100072*z*z
- 0.057882*x*y + 0.0217817*x*z - 0.0187733*y*z
- 0.0812969*x + 0.086143*y + 0.00396285*z =0.04
Linear interpolation is enough for this rendering. We can put interpolation calculation on normals, also known as Vertices Merging. This technique will make the geometries much more smooth.