Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- private Mesh ConstructMesh(float[] voxelGrid)
- {
- Profiler.BeginSample("Construct Mesh");
- Mesh mesh = new Mesh();
- mesh.indexFormat = IndexFormat.UInt32;
- List<Vector3> vertices = new();
- List<int> indices = new();
- Dictionary<Vector3, int> vertDictionary = new();
- MeshData meshData = new MeshData
- {
- vertices = vertices,
- indices = indices,
- vertDictionary = vertDictionary,
- voxelGrid = voxelGrid,
- };
- for (int y = 0, i = 0; y < yLength; y++)
- {
- for (int z = 0; z < zxLength; z++)
- {
- for (int x = 0; x < zxLength; x++, i++)
- {
- March(x, y, z, meshData);
- }
- }
- }
- mesh.vertices = vertices.ToArray();
- mesh.triangles = indices.ToArray();
- mesh.RecalculateNormals();
- Profiler.EndSample();
- return mesh;
- }
- private void March(int x, int y, int z, MeshData md)
- {
- float[] voxelCornerValues = new float[8];
- for (int i = 0; i < 8; i++)
- {
- Vector3Int offset = Tables.cornerOffsets[i];
- int index = ((y + offset.y) * zxLength2 * zxLength2) + ((z + offset.z) * zxLength2) + x + offset.x;
- voxelCornerValues[i] = md.voxelGrid[index];
- }
- int triCase = CalculateCase(voxelCornerValues);
- int[] edgeIndices = Tables.triTable[triCase];
- for (int i = 0; i < Tables.caseToNumPolys[triCase]; i++)
- {
- //The 3 vertices the triangle should be connected to
- Vector3 vertex0 = GetEdgePosition(x, y, z, zxStep, yStep, edgeIndices[i * 3 + 2], voxelCornerValues);
- Vector3 vertex1 = GetEdgePosition(x, y, z, zxStep, yStep, edgeIndices[i * 3 + 1], voxelCornerValues);
- Vector3 vertex2 = GetEdgePosition(x, y, z, zxStep, yStep, edgeIndices[i * 3], voxelCornerValues);
- //Check if any of the vertices alredy exists, if so only add the index to that vertex to the indices list
- if (md.vertDictionary.TryGetValue(vertex0, out int triIndex0))
- {
- md.indices.Add(triIndex0);
- }
- else
- {
- md.vertDictionary.Add(vertex0, md.vertices.Count);
- md.vertices.Add(vertex0);
- md.indices.Add(md.vertices.Count - 1);
- }
- if (md.vertDictionary.TryGetValue(vertex1, out int triIndex1))
- {
- md.indices.Add(triIndex1);
- }
- else
- {
- md.vertDictionary.Add(vertex1, md.vertices.Count);
- md.vertices.Add(vertex1);
- md.indices.Add(md.vertices.Count - 1);
- }
- if (md.vertDictionary.TryGetValue(vertex2, out int triIndex2))
- {
- md.indices.Add(triIndex2);
- }
- else
- {
- md.vertDictionary.Add(vertex2, md.vertices.Count);
- md.vertices.Add(vertex2);
- md.indices.Add(md.vertices.Count - 1);
- }
- }
- }
- private Vector3 GetEdgePosition(int x, int y, int z, float zxStep, float yStep, int edgeIndex, float[] cornerValues)
- {
- float xPos = x * zxStep;
- float yPos = y * yStep;
- float zPos = z * zxStep;
- //TODO: Make this look less like magic
- switch (edgeIndex)
- {
- case 0: return GetInterpolatedEdgePosition(xPos, yPos, zPos, cornerValues[0], cornerValues[1], 0, yStep, 0);
- case 1: return GetInterpolatedEdgePosition(xPos, yPos + yStep, zPos, cornerValues[1], cornerValues[2], zxStep, 0, 0);
- case 2: return GetInterpolatedEdgePosition(xPos + zxStep, yPos, zPos, cornerValues[3], cornerValues[2], 0, yStep, 0);
- case 3: return GetInterpolatedEdgePosition(xPos, yPos, zPos, cornerValues[0], cornerValues[3], zxStep, 0, 0);
- case 4: return GetInterpolatedEdgePosition(xPos, yPos, zPos + zxStep, cornerValues[4], cornerValues[5], 0, yStep, 0);
- case 5: return GetInterpolatedEdgePosition(xPos, yPos + yStep, zPos + zxStep, cornerValues[5], cornerValues[6], zxStep, 0, 0);
- case 6: return GetInterpolatedEdgePosition(xPos + zxStep, yPos, zPos + zxStep, cornerValues[7], cornerValues[6], 0, yStep, 0);
- case 7: return GetInterpolatedEdgePosition(xPos, yPos, zPos + zxStep, cornerValues[4], cornerValues[7], zxStep, 0, 0);
- case 8: return GetInterpolatedEdgePosition(xPos, yPos, zPos, cornerValues[0], cornerValues[4], 0, 0, zxStep);
- case 9: return GetInterpolatedEdgePosition(xPos, yPos + yStep, zPos, cornerValues[1], cornerValues[5], 0, 0, zxStep);
- case 10: return GetInterpolatedEdgePosition(xPos + zxStep, yPos + yStep, zPos, cornerValues[2], cornerValues[6], 0, 0, zxStep);
- case 11: return GetInterpolatedEdgePosition(xPos + zxStep, yPos, zPos, cornerValues[3], cornerValues[7], 0, 0, zxStep);
- default: throw new ArgumentOutOfRangeException(nameof(edgeIndex), "Invalid edge index: " + edgeIndex);
- }
- }
- private Vector3 GetInterpolatedEdgePosition(float x, float y, float z, float voxelA, float voxelB, float offsetX, float offsetY, float offsetZ)
- {
- float interpolation = (0 - voxelA) / (voxelB - voxelA);
- return new Vector3(x + offsetX * interpolation, y + offsetY * interpolation, z + offsetZ * interpolation);
- }
- private int CalculateCase(float[] voxelData)
- {
- int triCase = 0;
- for (int i = 0; i < 8; i++)
- {
- int bit = voxelData[i] < 0 ? 1 : 0;
- triCase |= bit << i;
- }
- return triCase;
- }
- private struct MeshData
- {
- public List<Vector3> vertices;
- public List<int> indices;
- public Dictionary<Vector3, int> vertDictionary;
- public float[] voxelGrid;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement