/// Generate the visible triangles for a grid cell with the Marching Cubes Algorithm public List <Triangle> GenerateTriangles(float isolevel, Gridcell grid) { // Create a list to store the triangles we will return List <Triangle> returnTriangles = new List <Triangle>(); int cubeIndex = 0; if (grid.val[0] < isolevel) { cubeIndex += 1; } if (grid.val[1] < isolevel) { cubeIndex += 2; } if (grid.val[2] < isolevel) { cubeIndex += 4; } if (grid.val[3] < isolevel) { cubeIndex += 8; } if (grid.val[4] < isolevel) { cubeIndex += 16; } if (grid.val[5] < isolevel) { cubeIndex += 32; } if (grid.val[6] < isolevel) { cubeIndex += 64; } if (grid.val[7] < isolevel) { cubeIndex += 128; } if (cubeIndex == 0 || cubeIndex == 255) { return(returnTriangles); } Vector3[] vertlist = new Vector3[12]; if (IsBitSet(edgeTable[cubeIndex], 1)) { vertlist[0] = VertexInterp(isolevel, grid.p[0], grid.p[1], grid.val[0], grid.val[1]); } if (IsBitSet(edgeTable[cubeIndex], 2)) { vertlist[1] = VertexInterp(isolevel, grid.p[1], grid.p[2], grid.val[1], grid.val[2]); } if (IsBitSet(edgeTable[cubeIndex], 4)) { vertlist[2] = VertexInterp(isolevel, grid.p[2], grid.p[3], grid.val[2], grid.val[3]); } if (IsBitSet(edgeTable[cubeIndex], 8)) { vertlist[3] = VertexInterp(isolevel, grid.p[3], grid.p[0], grid.val[3], grid.val[0]); } if (IsBitSet(edgeTable[cubeIndex], 16)) { vertlist[4] = VertexInterp(isolevel, grid.p[4], grid.p[5], grid.val[4], grid.val[5]); } if (IsBitSet(edgeTable[cubeIndex], 32)) { vertlist[5] = VertexInterp(isolevel, grid.p[5], grid.p[6], grid.val[5], grid.val[6]); } if (IsBitSet(edgeTable[cubeIndex], 64)) { vertlist[6] = VertexInterp(isolevel, grid.p[6], grid.p[7], grid.val[6], grid.val[7]); } if (IsBitSet(edgeTable[cubeIndex], 128)) { vertlist[7] = VertexInterp(isolevel, grid.p[7], grid.p[4], grid.val[7], grid.val[4]); } if (IsBitSet(edgeTable[cubeIndex], 256)) { vertlist[8] = VertexInterp(isolevel, grid.p[0], grid.p[4], grid.val[0], grid.val[4]); } if (IsBitSet(edgeTable[cubeIndex], 512)) { vertlist[9] = VertexInterp(isolevel, grid.p[1], grid.p[5], grid.val[1], grid.val[5]); } if (IsBitSet(edgeTable[cubeIndex], 1024)) { vertlist[10] = VertexInterp(isolevel, grid.p[2], grid.p[6], grid.val[2], grid.val[6]); } if (IsBitSet(edgeTable[cubeIndex], 2048)) { vertlist[11] = VertexInterp(isolevel, grid.p[3], grid.p[7], grid.val[3], grid.val[7]); } for (int i = 0; triTable[cubeIndex][i] != -1; i += 3) { returnTriangles.Add(new Triangle(vertlist[triTable[cubeIndex][i]], vertlist[triTable[cubeIndex][i + 1]], vertlist[triTable[cubeIndex][i + 2]])); } /*for (int p = 0; p < returnTriangles.Count; p++) * Debug.Log("v1: " + returnTriangles[p].pointOne.ToString() + ", v2: " + * returnTriangles[p].pointTwo.ToString() + ", v3: " + * returnTriangles[p].pointThree.ToString()); * Debug.Log("______________________");*/ return(returnTriangles); }
Mesh GenerateMesh(float[,,] voxels) { var grids = new NativeList <Gridcell>(Allocator.TempJob); var gridOffsets = new NativeList <Vector3Int>(Allocator.TempJob); for (int x = 0; x < dimensions.x - 1; x++) { for (int y = 0; y < dimensions.y; y++) { for (int z = 0; z < dimensions.z - 1; z++) { Gridcell gridcell; try { gridcell = new Gridcell { val1 = voxels[x, y, z], val2 = voxels[x, y, 1 + z], val3 = voxels[1 + x, y, 1 + z], val4 = voxels[1 + x, y, z], val5 = voxels[x, 1 + y, z], val6 = voxels[x, 1 + y, 1 + z], val7 = voxels[1 + x, 1 + y, 1 + z], val8 = voxels[1 + x, 1 + y, z], }; } catch { gridcell = new Gridcell { val1 = voxels[x, y, z], val2 = voxels[x, y, 1 + z], val3 = voxels[1 + x, y, 1 + z], val4 = voxels[1 + x, y, z], val5 = 0, val6 = 0, val7 = 0, val8 = 0, }; } if (gridcell.Equals(Gridcell.one) || gridcell.Equals(Gridcell.zero)) { continue; } int index = x + dimensions.y * (y + (dimensions.z - 1) * z); grids.Add(gridcell); gridOffsets.Add(new Vector3Int(x, y, z)); } } } var trianglesMC = new NativeQueue <Triangle>(Allocator.Persistent); new PolygoniseJob() { grids = grids, gridOffsets = gridOffsets, isolevel = isolevel, trianglesMC = trianglesMC, }.Schedule(grids.Length, 64).Complete(); grids.Dispose(); gridOffsets.Dispose(); Dictionary <Vector3, int> vertexDictionary = new Dictionary <Vector3, int>(Vec3EqComparer.c); NativeList <int> triangles = new NativeList <int>(Allocator.TempJob); while (trianglesMC.TryDequeue(out Triangle triangle)) { foreach (Vector3 vertex in triangle.Verts) { if (!vertexDictionary.TryGetValue(vertex, out int vertexIndex)) { vertexIndex = vertexDictionary.Count; vertexDictionary.Add(vertex, vertexIndex); } triangles.Add(vertexIndex); } } var vertices = new NativeArray <Vector3>(vertexDictionary.Keys.ToArray(), Allocator.TempJob); trianglesMC.Dispose(); var uv = new NativeArray <Vector2>(vertices.Length, Allocator.TempJob); new GetUVJob() { verts = vertices, uv = uv, dimensions = dimensions, }.Schedule(uv.Length, 64).Complete(); Mesh terrainMesh = new Mesh { name = "Terrain" + System.DateTime.UtcNow.ToFileTime().ToString() + " Mesh", vertices = vertices.ToArray(), triangles = triangles.ToArray(), uv = uv.ToArray(), }; vertices.Dispose(); triangles.Dispose(); uv.Dispose(); terrainMesh.RecalculateBounds(); terrainMesh.RecalculateTangents(); terrainMesh.RecalculateNormals(); AssetDatabase.CreateAsset(terrainMesh, "Assets/Terrain Data/" + terrainMesh.name + ".asset"); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); return((Mesh)AssetDatabase.LoadAssetAtPath("Assets/Terrain Data/" + terrainMesh.name + ".asset", typeof(Mesh))); }