Advertisement
JontePonte

ConstructMesh

Oct 24th, 2024
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.07 KB | None | 0 0
  1. private Mesh ConstructMesh(float[] voxelGrid)
  2.     {
  3.         Profiler.BeginSample("Construct Mesh");
  4.  
  5.         Mesh mesh = new Mesh();
  6.         mesh.indexFormat = IndexFormat.UInt32;
  7.  
  8.         List<Vector3> vertices = new();
  9.         List<int> indices = new();
  10.         Dictionary<Vector3, int> vertDictionary = new();
  11.  
  12.         MeshData meshData = new MeshData
  13.         {
  14.             vertices = vertices,
  15.             indices = indices,
  16.             vertDictionary = vertDictionary,
  17.             voxelGrid = voxelGrid,
  18.         };
  19.  
  20.  
  21.         for (int y = 0, i = 0; y < yLength; y++)
  22.         {
  23.             for (int z = 0; z < zxLength; z++)
  24.             {
  25.                 for (int x = 0; x < zxLength; x++, i++)
  26.                 {
  27.                     March(x, y, z, meshData);
  28.                 }
  29.             }
  30.         }
  31.  
  32.         mesh.vertices = vertices.ToArray();
  33.         mesh.triangles = indices.ToArray();
  34.         mesh.RecalculateNormals();
  35.  
  36.         Profiler.EndSample();
  37.  
  38.         return mesh;
  39.     }
  40.  
  41.     private void March(int x, int y, int z, MeshData md)
  42.     {
  43.         float[] voxelCornerValues = new float[8];
  44.         for (int i = 0; i < 8; i++)
  45.         {
  46.             Vector3Int offset = Tables.cornerOffsets[i];
  47.  
  48.             int index = ((y + offset.y) * zxLength2 * zxLength2) + ((z + offset.z) * zxLength2) + x + offset.x;
  49.  
  50.             voxelCornerValues[i] = md.voxelGrid[index];
  51.         }
  52.  
  53.         int triCase = CalculateCase(voxelCornerValues);
  54.         int[] edgeIndices = Tables.triTable[triCase];
  55.  
  56.         for (int i = 0; i < Tables.caseToNumPolys[triCase]; i++)
  57.         {
  58.             //The 3 vertices the triangle should be connected to
  59.             Vector3 vertex0 = GetEdgePosition(x, y, z, zxStep, yStep, edgeIndices[i * 3 + 2], voxelCornerValues);
  60.             Vector3 vertex1 = GetEdgePosition(x, y, z, zxStep, yStep, edgeIndices[i * 3 + 1], voxelCornerValues);
  61.             Vector3 vertex2 = GetEdgePosition(x, y, z, zxStep, yStep, edgeIndices[i * 3], voxelCornerValues);
  62.  
  63.             //Check if any of the vertices alredy exists, if so only add the index to that vertex to the indices list
  64.  
  65.             if (md.vertDictionary.TryGetValue(vertex0, out int triIndex0))
  66.             {
  67.                 md.indices.Add(triIndex0);
  68.             }
  69.             else
  70.             {
  71.                 md.vertDictionary.Add(vertex0, md.vertices.Count);
  72.                 md.vertices.Add(vertex0);
  73.                 md.indices.Add(md.vertices.Count - 1);
  74.             }
  75.  
  76.             if (md.vertDictionary.TryGetValue(vertex1, out int triIndex1))
  77.             {
  78.                 md.indices.Add(triIndex1);
  79.             }
  80.             else
  81.             {
  82.                 md.vertDictionary.Add(vertex1, md.vertices.Count);
  83.                 md.vertices.Add(vertex1);
  84.                 md.indices.Add(md.vertices.Count - 1);
  85.             }
  86.  
  87.             if (md.vertDictionary.TryGetValue(vertex2, out int triIndex2))
  88.             {
  89.                 md.indices.Add(triIndex2);
  90.             }
  91.             else
  92.             {
  93.                 md.vertDictionary.Add(vertex2, md.vertices.Count);
  94.                 md.vertices.Add(vertex2);
  95.                 md.indices.Add(md.vertices.Count - 1);
  96.             }
  97.         }
  98.     }
  99.  
  100.     private Vector3 GetEdgePosition(int x, int y, int z, float zxStep, float yStep, int edgeIndex, float[] cornerValues)
  101.     {
  102.         float xPos = x * zxStep;
  103.         float yPos = y * yStep;
  104.         float zPos = z * zxStep;
  105.  
  106.         //TODO: Make this look less like magic
  107.         switch (edgeIndex)
  108.         {
  109.             case 0: return GetInterpolatedEdgePosition(xPos, yPos, zPos, cornerValues[0], cornerValues[1], 0, yStep, 0);
  110.             case 1: return GetInterpolatedEdgePosition(xPos, yPos + yStep, zPos, cornerValues[1], cornerValues[2], zxStep, 0, 0);
  111.             case 2: return GetInterpolatedEdgePosition(xPos + zxStep, yPos, zPos, cornerValues[3], cornerValues[2], 0, yStep, 0);
  112.             case 3: return GetInterpolatedEdgePosition(xPos, yPos, zPos, cornerValues[0], cornerValues[3], zxStep, 0, 0);
  113.  
  114.             case 4: return GetInterpolatedEdgePosition(xPos, yPos, zPos + zxStep, cornerValues[4], cornerValues[5], 0, yStep, 0);
  115.             case 5: return GetInterpolatedEdgePosition(xPos, yPos + yStep, zPos + zxStep, cornerValues[5], cornerValues[6], zxStep, 0, 0);
  116.             case 6: return GetInterpolatedEdgePosition(xPos + zxStep, yPos, zPos + zxStep, cornerValues[7], cornerValues[6], 0, yStep, 0);
  117.             case 7: return GetInterpolatedEdgePosition(xPos, yPos, zPos + zxStep, cornerValues[4], cornerValues[7], zxStep, 0, 0);
  118.  
  119.             case 8: return GetInterpolatedEdgePosition(xPos, yPos, zPos, cornerValues[0], cornerValues[4], 0, 0, zxStep);
  120.             case 9: return GetInterpolatedEdgePosition(xPos, yPos + yStep, zPos, cornerValues[1], cornerValues[5], 0, 0, zxStep);
  121.             case 10: return GetInterpolatedEdgePosition(xPos + zxStep, yPos + yStep, zPos, cornerValues[2], cornerValues[6], 0, 0, zxStep);
  122.             case 11: return GetInterpolatedEdgePosition(xPos + zxStep, yPos, zPos, cornerValues[3], cornerValues[7], 0, 0, zxStep);
  123.  
  124.  
  125.             default: throw new ArgumentOutOfRangeException(nameof(edgeIndex), "Invalid edge index: " + edgeIndex);
  126.         }
  127.     }
  128.  
  129.     private Vector3 GetInterpolatedEdgePosition(float x, float y, float z, float voxelA, float voxelB, float offsetX, float offsetY, float offsetZ)
  130.     {
  131.         float interpolation = (0 - voxelA) / (voxelB - voxelA);
  132.  
  133.         return new Vector3(x + offsetX * interpolation, y + offsetY * interpolation, z + offsetZ * interpolation);
  134.     }
  135.  
  136.     private int CalculateCase(float[] voxelData)
  137.     {
  138.         int triCase = 0;
  139.  
  140.         for (int i = 0; i < 8; i++)
  141.         {
  142.             int bit = voxelData[i] < 0 ? 1 : 0;
  143.             triCase |= bit << i;
  144.         }
  145.  
  146.         return triCase;
  147.     }
  148.  
  149.     private struct MeshData
  150.     {
  151.         public List<Vector3> vertices;
  152.         public List<int> indices;
  153.         public Dictionary<Vector3, int> vertDictionary;
  154.         public float[] voxelGrid;
  155.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement