Guest User

VoxelsToMesh

a guest
Jul 20th, 2019
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.37 KB | None | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. namespace VoxelMagick
  6. {
  7.     public class VoxelsToMesh
  8.     {
  9.         public void ExtractMeshFromVoxels(sbyte[,,] voxels, int lod, ref Mesh mesh)
  10.         {
  11.             List<Vector3> vertices = new List<Vector3>();
  12.             List<int> triangles = new List<int>();
  13.             List<Vector3> normals = new List<Vector3>();
  14.  
  15.             Vector3Int chunkSize = new Vector3Int(voxels.GetLength(0), voxels.GetLength(1), voxels.GetLength(2));
  16.  
  17.             for (int z = 1; z <= chunkSize.z - 3; z++)
  18.             {
  19.                 for (int y = 1; y <= chunkSize.y - 3; y++)
  20.                 {
  21.                     for (int x = 1; x <= chunkSize.x - 3; x++)
  22.                     {
  23.                         RenderCell(voxels, new Vector3Int(x, y, z), lod, ref vertices, ref triangles, ref normals);
  24.                     }
  25.                 }
  26.             }
  27.  
  28.             mesh.name = "Chunk Mesh";
  29.             mesh.vertices = vertices.ToArray();
  30.             mesh.triangles = triangles.ToArray();
  31.             mesh.normals = normals.ToArray();
  32.         }
  33.  
  34.         private void RenderCell(sbyte[,,] voxels, Vector3Int position, int lod, ref List<Vector3> vertices, ref List<int> triangles, ref List<Vector3> normals)
  35.         {
  36.             Vector3Int offsetPosition = position * lod;
  37.  
  38.             sbyte[] densities = new sbyte[] {
  39.                 voxels[offsetPosition.x      , offsetPosition.y      , offsetPosition.z],
  40.                 voxels[offsetPosition.x + lod, offsetPosition.y      , offsetPosition.z],
  41.                 voxels[offsetPosition.x      , offsetPosition.y      , offsetPosition.z + lod],
  42.                 voxels[offsetPosition.x + lod, offsetPosition.y      , offsetPosition.z + lod],
  43.                 voxels[offsetPosition.x      , offsetPosition.y + lod, offsetPosition.z],
  44.                 voxels[offsetPosition.x + lod, offsetPosition.y + lod, offsetPosition.z],
  45.                 voxels[offsetPosition.x      , offsetPosition.y + lod, offsetPosition.z + lod],
  46.                 voxels[offsetPosition.x + lod, offsetPosition.y + lod, offsetPosition.z + lod]
  47.             };
  48.  
  49.             uint caseIndex = GetCaseIndex(densities);
  50.  
  51.             if ((caseIndex ^ ((densities[7] >> 7) & 0xFF)) == 0)
  52.                 return;
  53.  
  54.             Vector3[] cornerNormals = new Vector3[8];
  55.             for (int i = 0; i < 8; i++)
  56.             {
  57.                 Vector3Int cornerPosition = offsetPosition + VoxelMagick.TransvoxelTables.cornerPositions[i] * lod;
  58.                 cornerNormals[i].x = (voxels[cornerPosition.x + 1, cornerPosition.y, cornerPosition.z] - voxels[cornerPosition.x - 1, cornerPosition.y, cornerPosition.z]) * 0.5f;
  59.                 cornerNormals[i].y = (voxels[cornerPosition.x, cornerPosition.y + 1, cornerPosition.z] - voxels[cornerPosition.x, cornerPosition.y - 1, cornerPosition.z]) * 0.5f;
  60.                 cornerNormals[i].z = (voxels[cornerPosition.x, cornerPosition.y, cornerPosition.z + 1] - voxels[cornerPosition.x, cornerPosition.y, cornerPosition.z - 1]) * 0.5f;
  61.                 cornerNormals[i].Normalize();
  62.             }
  63.  
  64.             byte regularCellClass = VoxelMagick.TransvoxelTables.regularCellClass[caseIndex];
  65.             ushort[] vertexPositions = VoxelMagick.TransvoxelTables.regularVertexData[caseIndex];
  66.             VoxelMagick.TransvoxelTables.RegularCell cell = VoxelMagick.TransvoxelTables.regularCellData[regularCellClass];
  67.             int vertexCount = cell.getVertexCount();
  68.             int triangleCount = cell.getTriangleCount();
  69.             byte[] indexOffset = cell.getIndeces();
  70.             ushort[] mappedIndices = new ushort[indexOffset.Length];
  71.  
  72.             for (int i = 0; i < vertexCount; i++)
  73.             {
  74.                 byte edge = (byte)(vertexPositions[i] >> 8);
  75.                 byte reuseIndex = (byte)(edge & 0xF);
  76.                 byte rDir = (byte)(edge >> 4);
  77.                 byte v1 = (byte)((vertexPositions[i]) & 0x0F);
  78.                 byte v0 = (byte)((vertexPositions[i] >> 4) & 0x0F);
  79.                 sbyte d0 = densities[v0];
  80.                 sbyte d1 = densities[v1];
  81.                 int t = (d1 << 8) / (d1 - d0);
  82.                 int u = 0x0100 - t;
  83.                 float t0 = t / 256.0f;
  84.                 float t1 = u / 256.0f;
  85.                 int index = -1;
  86.  
  87.                 if (index == -1)
  88.                 {
  89.                     Vector3 normal = cornerNormals[v0] * t0 + cornerNormals[v1] * t1;
  90.                     GenerateVertex(position, ref vertices, ref normals, lod, t, v0, v1, normal);
  91.                     index = vertices.Count - 1;
  92.                 }
  93.  
  94.                 mappedIndices[i] = (ushort)index;
  95.             }
  96.  
  97.             for (int t = 0; t < triangleCount; t++)
  98.             {
  99.                 for (int i = 2; i >= 0; i--)
  100.                 {
  101.                     triangles.Add(mappedIndices[cell.getIndeces()[t * 3 + i]]);
  102.                 }
  103.             }
  104.         }
  105.  
  106.         private void GenerateVertex(Vector3Int position, ref List<Vector3> vertices, ref List<Vector3> normals, int lod, int t, byte v0, byte v1, Vector3 normal)
  107.         {
  108.             Vector3Int iP0 = (position + VoxelMagick.TransvoxelTables.cornerPositions[v0] * lod);
  109.             Vector3 P0 = new Vector3(iP0.x, iP0.y, iP0.z);
  110.  
  111.             Vector3 iP1 = (position + VoxelMagick.TransvoxelTables.cornerPositions[v1] * lod);
  112.             Vector3 P1 = new Vector3(iP1.x, iP1.y, iP1.z);
  113.  
  114.             Vector3 Q = InterpolateVoxelVector(t, P0, P1);
  115.  
  116.             vertices.Add(Q);
  117.             normals.Add(normal);
  118.         }
  119.  
  120.         internal static Vector3 InterpolateVoxelVector(int t, Vector3 P0, Vector3 P1)
  121.         {
  122.             int u = 0x0100 - t;
  123.             float s = 1.0f / 256.0f;
  124.             Vector3 Q = P0 * t + P1 * u;
  125.             Q *= s;
  126.             return Q;
  127.         }
  128.  
  129.         private uint GetCaseIndex(sbyte[] densities)
  130.         {
  131.             uint index = 0;
  132.  
  133.             index |= ((uint)(densities[0] >> 7) & 0x01);
  134.             index |= ((uint)(densities[1] >> 6) & 0x02);
  135.             index |= ((uint)(densities[2] >> 5) & 0x04);
  136.             index |= ((uint)(densities[3] >> 4) & 0x08);
  137.             index |= ((uint)(densities[4] >> 3) & 0x10);
  138.             index |= ((uint)(densities[5] >> 2) & 0x20);
  139.             index |= ((uint)(densities[6] >> 1) & 0x40);
  140.             index |= ((uint)densities[7] & 0x80);
  141.  
  142.             return index;
  143.         }
  144.     }
  145. }
Add Comment
Please, Sign In to add comment