Advertisement
JontePonte

Slightly less shitty voxel engine

Jul 25th, 2024
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.59 KB | None | 0 0
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3.  
  4. public class ChunkGenerator : MonoBehaviour
  5. {
  6.     public int maxVoxelHeight;
  7.     public static int _maxVoxelHeight;
  8.  
  9.     public float amplitude;
  10.     public float frequency;
  11.  
  12.     public Texture2D atlas;
  13.  
  14.     public string executionTime;
  15.  
  16.     Noise noise;
  17.     Vector3[][] faces;
  18.     Vector2[] uvCoords;
  19.     Vector3Int[] directions;
  20.     int[] voxelValues;
  21.  
  22.     private void Start()
  23.     {
  24.         Initialize();
  25.         executionTime = "N/A";
  26.     }
  27.  
  28.     public void GenerateChunk()
  29.     {
  30.         Initialize();
  31.      
  32.         float startTime = Time.realtimeSinceStartup;
  33.  
  34.         CreateChunkObject(Vector2Int.zero);
  35.  
  36.         executionTime = (Time.realtimeSinceStartup - startTime) * 1000f + " ms";
  37.     }
  38.  
  39.     public Mesh CreateChunkMesh(Vector2Int offset)
  40.     {
  41.         Mesh mesh = new Mesh();
  42.         mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
  43.  
  44.         List<Vector3> vertices = new List<Vector3>();
  45.         List<int> triangles = new List<int>();
  46.         List<Vector2> uvs = new List<Vector2>();
  47.  
  48.         voxelValues = noise.GetVoxelValues(offset);
  49.  
  50.         for (int i = 0; i < 256 * maxVoxelHeight; i++)
  51.         {
  52.             int x = i / (maxVoxelHeight * 16);
  53.             int y = ((i % (maxVoxelHeight * 16))) / 16;
  54.             int z = i % 16;
  55.  
  56.             if (voxelValues[GetVoxelIndex(x, y, z)] == 1)
  57.             {
  58.                 AddVoxel(new Vector3Int(x, y, z), vertices, triangles, uvs);
  59.             }
  60.         }
  61.  
  62.         mesh.vertices = vertices.ToArray();
  63.         mesh.triangles = triangles.ToArray();
  64.         mesh.uv = uvs.ToArray();
  65.  
  66.         return mesh;
  67.     }
  68.  
  69.     public GameObject CreateChunkObject(Vector2Int offset)
  70.     {
  71.         GameObject chunk = new GameObject();
  72.         chunk.name = "Chunk";
  73.         chunk.AddComponent<MeshRenderer>().sharedMaterial = new Material(Shader.Find("Unlit/Texture"));
  74.         chunk.GetComponent<MeshRenderer>().sharedMaterial.mainTexture = atlas;
  75.         chunk.AddComponent<MeshFilter>().mesh = CreateChunkMesh(offset);
  76.  
  77.         return chunk;
  78.     }
  79.  
  80.     private void AddVoxel(Vector3Int pos, List<Vector3> vertices, List<int> triangles, List<Vector2> uvs)
  81.     {
  82.         for (int i = 0; i < 6; i++)
  83.         {
  84.             //Only add a face if it's visible
  85.             if (IsAirVoxel(pos + directions[i]))
  86.             {
  87.                 AddQuad(faces[i], pos, i, vertices, triangles, uvs);
  88.             }
  89.         }
  90.     }
  91.  
  92.     private void AddQuad(Vector3[] vertexPos, Vector3 quadPos, int i, List<Vector3> vertices, List<int> triangles, List<Vector2> uvs)
  93.     {
  94.         int vertCount = vertices.Count;
  95.  
  96.         Vector2 bottomLeft = uvCoords[i];
  97.  
  98.         vertices.AddRange(new List<Vector3> {
  99.             vertexPos[0] + quadPos,
  100.             vertexPos[1] + quadPos,
  101.             vertexPos[2] + quadPos,
  102.             vertexPos[3] + quadPos });
  103.  
  104.         triangles.AddRange(new List<int> {
  105.             vertCount,
  106.             vertCount + 1,
  107.             vertCount + 3,
  108.             vertCount + 3,
  109.             vertCount + 1,
  110.             vertCount + 2 });
  111.  
  112.         uvs.AddRange(new List<Vector2> {
  113.             bottomLeft + new Vector2(.5f, 0),
  114.             bottomLeft + new Vector2(.5f, .5f),
  115.             bottomLeft + new Vector2(0, .5f),
  116.             bottomLeft});
  117.     }
  118.  
  119.     bool IsAirVoxel(Vector3Int coord)
  120.     {
  121.         int x = coord.x;
  122.         int y = coord.y;
  123.         int z = coord.z;
  124.  
  125.         bool xOutOfRange = x < 0 || x > 15;
  126.         bool yOutOfRange = y < 0 || y > _maxVoxelHeight - 1;
  127.         bool zOutOfRange = z < 0 || z > 15;
  128.  
  129.         if (xOutOfRange || yOutOfRange || zOutOfRange)
  130.         {
  131.             return true;
  132.         }
  133.  
  134.         return voxelValues[GetVoxelIndex(x,y,z)] == 0 ? true : false;
  135.     }
  136.  
  137.     private void Initialize()
  138.     {  
  139.         noise = new Noise(_maxVoxelHeight, amplitude, frequency);
  140.         _maxVoxelHeight = maxVoxelHeight;
  141.  
  142.         //The vertex positions for each face
  143.         faces = new Vector3[6][];
  144.  
  145.         // Bottom
  146.         faces[0] = new Vector3[] { new Vector3(1, 0, 0), new Vector3(1, 0, 1), new Vector3(0, 0, 1), new Vector3(0, 0, 0) };
  147.         // Front
  148.         faces[1] = new Vector3[] { new Vector3(1, 0, 1), new Vector3(1, 1, 1), new Vector3(0, 1, 1), new Vector3(0, 0, 1) };
  149.         // Back
  150.         faces[2] = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 1, 0), new Vector3(1, 0, 0) };
  151.         // Left
  152.         faces[3] = new Vector3[] { new Vector3(0, 0, 1), new Vector3(0, 1, 1), new Vector3(0, 1, 0), new Vector3(0, 0, 0) };
  153.         // Right
  154.         faces[4] = new Vector3[] { new Vector3(1, 0, 0), new Vector3(1, 1, 0), new Vector3(1, 1, 1), new Vector3(1, 0, 1) };
  155.         // Top
  156.         faces[5] = new Vector3[] { new Vector3(0, 1, 0), new Vector3(0, 1, 1), new Vector3(1, 1, 1), new Vector3(1, 1, 0) };
  157.  
  158.         //The bottom left of each texture in the atlas
  159.         Vector2 topTex = Vector2.zero;
  160.         Vector2 sideTex = new Vector2(.5f, .5f);
  161.         Vector2 bottomTex = new Vector2(.5f, 0);
  162.  
  163.         uvCoords = new Vector2[]
  164.         {
  165.             bottomTex,
  166.             sideTex,
  167.             sideTex,
  168.             sideTex,
  169.             sideTex,
  170.             topTex
  171.         };
  172.  
  173.         directions = new Vector3Int[]
  174.         {
  175.             Vector3Int.down,
  176.             Vector3Int.forward,
  177.             Vector3Int.back,
  178.             Vector3Int.left,
  179.             Vector3Int.right,
  180.             Vector3Int.up,
  181.         };
  182.     }
  183.  
  184.     public static int GetVoxelIndex(int x, int y, int z)
  185.     {
  186.         return x * (_maxVoxelHeight * 16) + y * 16 + z;
  187.     }
  188. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement