Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- namespace VoxelMagick
- {
- public class VoxelsToMesh
- {
- public void ExtractMeshFromVoxels(sbyte[,,] voxels, int lod, ref Mesh mesh)
- {
- List<Vector3> vertices = new List<Vector3>();
- List<int> triangles = new List<int>();
- List<Vector3> normals = new List<Vector3>();
- Vector3Int chunkSize = new Vector3Int(voxels.GetLength(0), voxels.GetLength(1), voxels.GetLength(2));
- for (int z = 1; z <= chunkSize.z - 3; z++)
- {
- for (int y = 1; y <= chunkSize.y - 3; y++)
- {
- for (int x = 1; x <= chunkSize.x - 3; x++)
- {
- RenderCell(voxels, new Vector3Int(x, y, z), lod, ref vertices, ref triangles, ref normals);
- }
- }
- }
- mesh.name = "Chunk Mesh";
- mesh.vertices = vertices.ToArray();
- mesh.triangles = triangles.ToArray();
- mesh.normals = normals.ToArray();
- }
- private void RenderCell(sbyte[,,] voxels, Vector3Int position, int lod, ref List<Vector3> vertices, ref List<int> triangles, ref List<Vector3> normals)
- {
- Vector3Int offsetPosition = position * lod;
- sbyte[] densities = new sbyte[] {
- voxels[offsetPosition.x , offsetPosition.y , offsetPosition.z],
- voxels[offsetPosition.x + lod, offsetPosition.y , offsetPosition.z],
- voxels[offsetPosition.x , offsetPosition.y , offsetPosition.z + lod],
- voxels[offsetPosition.x + lod, offsetPosition.y , offsetPosition.z + lod],
- voxels[offsetPosition.x , offsetPosition.y + lod, offsetPosition.z],
- voxels[offsetPosition.x + lod, offsetPosition.y + lod, offsetPosition.z],
- voxels[offsetPosition.x , offsetPosition.y + lod, offsetPosition.z + lod],
- voxels[offsetPosition.x + lod, offsetPosition.y + lod, offsetPosition.z + lod]
- };
- uint caseIndex = GetCaseIndex(densities);
- if ((caseIndex ^ ((densities[7] >> 7) & 0xFF)) == 0)
- return;
- Vector3[] cornerNormals = new Vector3[8];
- for (int i = 0; i < 8; i++)
- {
- Vector3Int cornerPosition = offsetPosition + VoxelMagick.TransvoxelTables.cornerPositions[i] * lod;
- cornerNormals[i].x = (voxels[cornerPosition.x + 1, cornerPosition.y, cornerPosition.z] - voxels[cornerPosition.x - 1, cornerPosition.y, cornerPosition.z]) * 0.5f;
- cornerNormals[i].y = (voxels[cornerPosition.x, cornerPosition.y + 1, cornerPosition.z] - voxels[cornerPosition.x, cornerPosition.y - 1, cornerPosition.z]) * 0.5f;
- cornerNormals[i].z = (voxels[cornerPosition.x, cornerPosition.y, cornerPosition.z + 1] - voxels[cornerPosition.x, cornerPosition.y, cornerPosition.z - 1]) * 0.5f;
- cornerNormals[i].Normalize();
- }
- byte regularCellClass = VoxelMagick.TransvoxelTables.regularCellClass[caseIndex];
- ushort[] vertexPositions = VoxelMagick.TransvoxelTables.regularVertexData[caseIndex];
- VoxelMagick.TransvoxelTables.RegularCell cell = VoxelMagick.TransvoxelTables.regularCellData[regularCellClass];
- int vertexCount = cell.getVertexCount();
- int triangleCount = cell.getTriangleCount();
- byte[] indexOffset = cell.getIndeces();
- ushort[] mappedIndices = new ushort[indexOffset.Length];
- for (int i = 0; i < vertexCount; i++)
- {
- byte edge = (byte)(vertexPositions[i] >> 8);
- byte reuseIndex = (byte)(edge & 0xF);
- byte rDir = (byte)(edge >> 4);
- byte v1 = (byte)((vertexPositions[i]) & 0x0F);
- byte v0 = (byte)((vertexPositions[i] >> 4) & 0x0F);
- sbyte d0 = densities[v0];
- sbyte d1 = densities[v1];
- int t = (d1 << 8) / (d1 - d0);
- int u = 0x0100 - t;
- float t0 = t / 256.0f;
- float t1 = u / 256.0f;
- int index = -1;
- if (index == -1)
- {
- Vector3 normal = cornerNormals[v0] * t0 + cornerNormals[v1] * t1;
- GenerateVertex(position, ref vertices, ref normals, lod, t, v0, v1, normal);
- index = vertices.Count - 1;
- }
- mappedIndices[i] = (ushort)index;
- }
- for (int t = 0; t < triangleCount; t++)
- {
- for (int i = 2; i >= 0; i--)
- {
- triangles.Add(mappedIndices[cell.getIndeces()[t * 3 + i]]);
- }
- }
- }
- private void GenerateVertex(Vector3Int position, ref List<Vector3> vertices, ref List<Vector3> normals, int lod, int t, byte v0, byte v1, Vector3 normal)
- {
- Vector3Int iP0 = (position + VoxelMagick.TransvoxelTables.cornerPositions[v0] * lod);
- Vector3 P0 = new Vector3(iP0.x, iP0.y, iP0.z);
- Vector3 iP1 = (position + VoxelMagick.TransvoxelTables.cornerPositions[v1] * lod);
- Vector3 P1 = new Vector3(iP1.x, iP1.y, iP1.z);
- Vector3 Q = InterpolateVoxelVector(t, P0, P1);
- vertices.Add(Q);
- normals.Add(normal);
- }
- internal static Vector3 InterpolateVoxelVector(int t, Vector3 P0, Vector3 P1)
- {
- int u = 0x0100 - t;
- float s = 1.0f / 256.0f;
- Vector3 Q = P0 * t + P1 * u;
- Q *= s;
- return Q;
- }
- private uint GetCaseIndex(sbyte[] densities)
- {
- uint index = 0;
- index |= ((uint)(densities[0] >> 7) & 0x01);
- index |= ((uint)(densities[1] >> 6) & 0x02);
- index |= ((uint)(densities[2] >> 5) & 0x04);
- index |= ((uint)(densities[3] >> 4) & 0x08);
- index |= ((uint)(densities[4] >> 3) & 0x10);
- index |= ((uint)(densities[5] >> 2) & 0x20);
- index |= ((uint)(densities[6] >> 1) & 0x40);
- index |= ((uint)densities[7] & 0x80);
- return index;
- }
- }
- }
Add Comment
Please, Sign In to add comment