public void Generate(IsoSurface isoSurface, TriangleMesh mesh) { if (isoSurface.Threshold > 0.0f) { WindingOrder[0] = 0; WindingOrder[1] = 1; WindingOrder[2] = 2; } else { WindingOrder[0] = 2; WindingOrder[1] = 1; WindingOrder[2] = 0; } for (int x = 0; x < isoSurface.Width - 1; x++) { for (int y = 0; y < isoSurface.Height - 1; y++) { for (int z = 0; z < isoSurface.Depth - 1; z++) { //Get the values in the 8 neighbours which make up a cube for (int i = 0; i < 8; i++) { int ix = x + VertexOffset[i, 0]; int iy = y + VertexOffset[i, 1]; int iz = z + VertexOffset[i, 2]; Cube[i] = isoSurface.Voxels[ix][iy][iz]; } //Perform algorithm March(isoSurface.Threshold, isoSurface.Dx, isoSurface.Dy, isoSurface.Dz, Cube, mesh); } } } }
/// <summary> /// MarchCube performs the Marching algorithm on a single cube /// </summary> protected abstract void March(double threshold, double cx, double cy, double cz, Voxel[] cube, TriangleMesh mesh);
/// <summary> /// MarchCube performs the Marching Cubes algorithm on a single cube /// </summary> protected override void March(double threshold, double cx, double cy, double cz, Voxel[] cube, TriangleMesh mesh) { //Find which vertices are inside of the surface and which are outside int flagIndex = 0; for (int i = 0; i < cube.Length; i++) { if (cube[i].Value <= threshold) { flagIndex |= 1 << i; } } //Find which edges are intersected by the surface int edgeFlags = CubeEdgeFlags[flagIndex]; //If the cube is entirely inside or outside of the surface, then there will be no intersections if (edgeFlags == 0) { return; } double x0 = cube[0].X; double y0 = cube[0].Y; double z0 = cube[0].Z; //Find the point of intersection of the surface with each edge for (int i = 0; i < EdgeVertex.Length; i++) { //if there is an intersection on this edge if ((edgeFlags & (1 << i)) != 0) { var index0 = EdgeConnection[i, 0]; var index1 = EdgeConnection[i, 1]; var voxel0 = cube[index0]; var voxel1 = cube[index1]; double v0 = voxel0.Value; double v1 = voxel1.Value; var offset = GetOffset(v0, v1, threshold); var dx = VertexOffset[index0, 0]; var dy = VertexOffset[index0, 1]; var dz = VertexOffset[index0, 2]; var xx = x0 + cx * (dx + offset * EdgeDirection[i, 0]); var yy = y0 + cy * (dy + offset * EdgeDirection[i, 1]); var zz = z0 + cz * (dz + offset * EdgeDirection[i, 2]); EdgeVertex[i] = Helper.CreatePoint(xx, yy, zz); } } //Save the triangles that were found. There can be up to five per cube var triangles = TriangleConnectionTable[flagIndex]; for (int i = 0; i < triangles.Length; i++) { var triplet = triangles[i]; var p1 = EdgeVertex[triplet.Index0]; var p2 = EdgeVertex[triplet.Index1]; var p3 = EdgeVertex[triplet.Index2]; if (p1.Equals(p2) || p1.Equals(p3) || p2.Equals(p3)) { continue; } var idx = mesh.Vertices.Count; mesh.Triplets.Add(new Triplet(idx + WindingOrder[0], idx + WindingOrder[1], idx + WindingOrder[2])); mesh.Vertices.Add(p1); mesh.Vertices.Add(p2); mesh.Vertices.Add(p3); } }