// Function to check each corner of a given cube - this is the "March" of Marching Cubes // The x,y,z arguments are the positions of nodes in a chunk's node matrix // The currChunk argument is the nodes within the current chunk's matrix data ChunkMatrix PolygonizeCube(ChunkMatrix currChunk, int x, int y, int z) { Node[,,] nodes = currChunk.nodes; // get the type of cube dependant on the active vertices within it int cubeIndex = MarchingCubes.CheckVertices(currChunk, chunks, surfaceLevel, x, y, z); // if there were no active nodes in this cube, break the function if (cubeIndex == 0) { return(currChunk); } // use the edge table to obtain which edges are active for this cube configuration int edges = MarchingCubes.edgeTable[cubeIndex]; // array holding the positions of each edge vertex Vector3[] edgeVertices = emptyVertices; // value of which vertex is being worked on at the moment for the mesh creation int vert; // Find the vertices for the triangles in the cube - TODO: do the interpolation here ***************************************** for (int i = 0; i < edgeVertices.Length; i++) // edge vertices length is the numver of edges in the cube { if ((edges & (1 << i)) != 0) // checks the boolean values from the edges table to see which edges are active { // start by assuming a hard edge - turn softEdge to false to create a more flat terrain float edgeOffset = 1 / (float)cubeResolution / 2f; // turning on softEdge will use the linear interpolation to smooth out the edges if (softEdge) { float[] cube = MarchingCubes.GetIsovaluesOfCube(nodes, x, y, z); edgeOffset = MarchingCubes.CalculateEdgeOffset(cube[MarchingCubes.edgeConnection[i, 0]], cube[MarchingCubes.edgeConnection[i, 1]], surfaceLevel) / (float)cubeResolution; } // The edgeVertices array holds the position for where the vertex will be drawn along the edge // To figure this out, we need the position of the current node added to the // VertexOffset defined by the LUT that shows where the next edge is in comparison to this current one // The vertex offset needs to be divided by the cube resolution because the distance between edges will change if there are more cubes in the same amount of space // The edgeOffset is the linear interpolated value we found and it is basically a percentage of how far between the current and next node that the vertex should be placed // The edgeOffset needs to be multiplied by the edgeDirection value in order to know which direction that the offset is in edgeVertices[i].x = nodes[x, y, z].position.x + MarchingCubes.vertexOffset[MarchingCubes.edgeConnection[i, 0], 0] / (float)cubeResolution + edgeOffset * MarchingCubes.edgeDirection[i, 0]; edgeVertices[i].y = nodes[x, y, z].position.y + MarchingCubes.vertexOffset[MarchingCubes.edgeConnection[i, 0], 1] / (float)cubeResolution + edgeOffset * MarchingCubes.edgeDirection[i, 1]; edgeVertices[i].z = nodes[x, y, z].position.z + MarchingCubes.vertexOffset[MarchingCubes.edgeConnection[i, 0], 2] / (float)cubeResolution + edgeOffset * MarchingCubes.edgeDirection[i, 2]; } } // Create the triangles from these verts - there will be at most 5 triangles to be made per cube for (int i = 0; i < 5; i++) { if (MarchingCubes.triTable[cubeIndex, 3 * i] < 0) // no triangles to be made { break; } // get the current number of verts in the mesh int vertexCount = currChunk.vertices.Count; for (int j = 0; j < 3; j++) // iterate through the triangle verts { vert = MarchingCubes.triTable[cubeIndex, 3 * i + j]; currChunk.indices.Add(vertexCount + windingOrder[j]); currChunk.vertices.Add(edgeVertices[vert]); } } return(currChunk); }