Advertisement
JontePonte

MeshGen before jobification

Sep 27th, 2024
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.67 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using Unity.Mathematics;
  5. using Unity.Collections;
  6. using Unity.Jobs;
  7. using Unity.VisualScripting;
  8. using Unity.Burst;
  9. using static UnityEditor.PlayerSettings;
  10.  
  11. public class MeshGenerator : MonoBehaviour
  12. {
  13.     public static Vector2Int chunkDimensions = new Vector2Int(32, 128);
  14.  
  15.     public Material material;
  16.     public ComputeShader voxelGridShader;
  17.  
  18.     public int brushSize;
  19.     public float brushStrength;
  20.  
  21.     public int lod;
  22.     public int maxLod;
  23.  
  24.     public float surfaceLevel;
  25.  
  26.     public bool hideMeshOnPlay;
  27.  
  28.     [Header("Noise Settings")]
  29.     public float heightMultiplier;
  30.     public AnimationCurve heightCurve;
  31.     public float frequency;
  32.     public float lacunarity;
  33.     public float persistance;
  34.     public int octaves;
  35.     public float density;
  36.     public float warpingStrength;
  37.     public float warpingFrequency;
  38.     public float mountainHeightOffset;
  39.     public Vector2 offset;
  40.  
  41.     [Header("")]
  42.     public bool autoUpdate;
  43.     public string executionTime;
  44.  
  45.     int[] caseToNumpolys;
  46.     int[][] triTable;
  47.     NativeArray<int> nativeTriTable;
  48.  
  49.     Camera cam;
  50.  
  51.     VoxelGrid voxelGrid;
  52.  
  53.     private void Start()
  54.     {
  55.         Init();
  56.  
  57.         if (GameObject.Find("Mesh") != null)
  58.         {
  59.             GameObject.Find("Mesh").SetActive(!hideMeshOnPlay);
  60.         }
  61.  
  62.     }
  63.  
  64.     private void Update()
  65.     {
  66.         if (Input.GetKeyDown(KeyCode.Space))
  67.         {
  68.             EditorMesh();
  69.         }
  70.     }
  71.  
  72.     public GameObject ChunkObject(Vector2 position)
  73.     {
  74.         GameObject chunk = new GameObject("Chunk");
  75.         chunk.AddComponent<MeshFilter>().mesh = ChunkMesh(position, 0);
  76.         chunk.AddComponent<MeshRenderer>().material = material;
  77.         chunk.GetComponent<MeshRenderer>().receiveShadows = false;
  78.         chunk.GetComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
  79.  
  80.         return chunk;
  81.     }
  82.  
  83.     public Mesh ChunkMesh(Vector2 position, int lod)
  84.     {
  85.         List<Vector3> vertices = new();
  86.         Dictionary<Vector3, int> vertDictionary = new();
  87.         List<int> indices = new();
  88.  
  89.         lod = lod == 0 ? 1 : lod * 2;
  90.  
  91.         MeshData meshData = new MeshData
  92.         {
  93.             vertices = vertices,
  94.             indices = indices,
  95.             vertDictionary = vertDictionary,
  96.             voxelGrid = voxelGrid.GenerateVoxelGrid(position, lod),
  97.             lod = lod
  98.         };
  99.  
  100.         //Create Mesh
  101.         for (int z = 0, i = 0; z < chunkDimensions.x; z += lod)
  102.         {
  103.             for (int y = 0; y < chunkDimensions.y; y += lod)
  104.             {
  105.                 for (int x = 0; x < chunkDimensions.x; x += lod, i++)
  106.                 {
  107.                     AddVertices(i, new Vector3Int(x, y, z), meshData);
  108.                 }
  109.             }
  110.         }
  111.  
  112.         Mesh mesh = new Mesh();
  113.         mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
  114.  
  115.         mesh.vertices = vertices.ToArray();
  116.         mesh.triangles = indices.ToArray();
  117.  
  118.         mesh.RecalculateNormals();
  119.  
  120.         return mesh;
  121.     }
  122.  
  123.     public void EditorMesh()
  124.     {
  125.         Init();
  126.  
  127.         float startTime = Time.realtimeSinceStartup;
  128.  
  129.         Mesh mesh = ChunkMesh(offset/10, lod);
  130.  
  131.         executionTime = ((Time.realtimeSinceStartup - startTime) * 1000f) + "ms";
  132.  
  133.         if (GameObject.Find("Mesh") == null)
  134.         {
  135.             GameObject obj = new GameObject("Mesh");
  136.             obj.transform.parent = transform;
  137.             obj.AddComponent<MeshFilter>().mesh = mesh;
  138.             obj.AddComponent<MeshRenderer>().material = material;
  139.             obj.AddComponent<MeshCollider>();
  140.         }
  141.  
  142.         else
  143.         {
  144.             var mf = GameObject.Find("Mesh").GetComponent<MeshFilter>();
  145.             var collider = GameObject.Find("Mesh").GetComponent<MeshCollider>();
  146.  
  147.             mf.mesh = mesh;
  148.             collider.sharedMesh = null;
  149.             collider.sharedMesh = mesh;
  150.         }
  151.     }
  152.    
  153.     void Init()
  154.     {
  155.         caseToNumpolys = Tables.caseToNumPolys;
  156.         triTable = Tables.triTable;
  157.  
  158.         nativeTriTable = new NativeArray<int>(triTable.Length * 15, Allocator.Persistent);
  159.  
  160.         for (int i = 0; i < triTable.Length; i++)
  161.         {
  162.             for (int j = 0; j < 15; j++)
  163.             {
  164.                 nativeTriTable[(i * 15) + j] = triTable[i][j];
  165.             }
  166.         }
  167.  
  168.         cam = Camera.main;
  169.  
  170.         voxelGrid = new VoxelGrid(frequency, lacunarity, persistance, octaves, surfaceLevel, density, heightMultiplier, voxelGridShader);
  171.     }
  172.  
  173.     void AddVertices(int index, Vector3Int pos, MeshData md)
  174.     {
  175.         float[] voxelData = new float[8];
  176.  
  177.         for (int i = 0; i < 8; i++)
  178.         {
  179.             voxelData[i] = md.voxelGrid[(index * 8) + i];
  180.         }
  181.  
  182.         int triCase = CalculateCase(voxelData);
  183.         int[] edges = triTable[triCase];
  184.  
  185.         for (int j = 0, i = 0; j < caseToNumpolys[triCase]; j++, i += 3)
  186.         {
  187.             for (int h = 0; h < 3; h++)
  188.             {
  189.                 Vector3 vertex = GetEdgePosition(edges[i + (2 - h)], voxelData, md.lod, pos);
  190.  
  191.                 if (md.vertDictionary.ContainsKey(vertex))
  192.                 {
  193.                     md.indices.Add(md.vertDictionary[vertex]);
  194.                 }
  195.  
  196.                 else
  197.                 {
  198.                     md.vertices.Add(vertex);
  199.                     md.indices.Add(md.vertices.Count - 1);
  200.  
  201.                     md.vertDictionary.Add(vertex, md.vertices.Count - 1);
  202.                 }
  203.             }
  204.         }
  205.     }
  206.  
  207.     Vector3 GetEdgePosition(int edge, float[] voxelData, int lod, Vector3Int pos)
  208.     {
  209.         int x = pos.x;
  210.         int y = pos.y;
  211.         int z = pos.z;
  212.  
  213.  
  214.         switch (edge)
  215.         {
  216.             case 0: return GetInterpolatedEdgePosition(x, y, z, voxelData[0], voxelData[1], 0, 1, 0);
  217.             case 1: return GetInterpolatedEdgePosition(x, y + (1 * lod), z, voxelData[1], voxelData[2], 1, 0, 0);
  218.             case 2: return GetInterpolatedEdgePosition(x + (1 * lod), y, z, voxelData[3], voxelData[2], 0, 1, 0);
  219.             case 3: return GetInterpolatedEdgePosition(x, y, z, voxelData[0], voxelData[3], 1, 0, 0);
  220.  
  221.             case 4: return GetInterpolatedEdgePosition(x, y, z + (1 * lod), voxelData[4], voxelData[5], 0, 1, 0);
  222.             case 5: return GetInterpolatedEdgePosition(x, y + (1 * lod), z + (1 * lod), voxelData[5], voxelData[6], 1, 0, 0);
  223.             case 6: return GetInterpolatedEdgePosition(x + (1 * lod), y, z + (1 * lod), voxelData[7], voxelData[6], 0, 1, 0);
  224.             case 7: return GetInterpolatedEdgePosition(x, y, z + (1 * lod), voxelData[4], voxelData[7], 1, 0, 0);
  225.  
  226.             case 8: return GetInterpolatedEdgePosition(x, y, z, voxelData[0], voxelData[4], 0, 0, 1);
  227.             case 9: return GetInterpolatedEdgePosition(x, y + (1 * lod), z, voxelData[1], voxelData[5], 0, 0, 1);
  228.             case 10: return GetInterpolatedEdgePosition(x + (1 * lod), y + (1 * lod), z, voxelData[2], voxelData[6], 0, 0, 1);
  229.             case 11: return GetInterpolatedEdgePosition(x + (1 * lod), y, z, voxelData[3], voxelData[7], 0, 0, 1);
  230.  
  231.             default: throw new ArgumentOutOfRangeException(nameof(edge), "Invalid edge index: " + edge);
  232.         }
  233.     }
  234.     public Vector3 GetInterpolatedEdgePosition(int x, int y, int z, float voxelA, float voxelB, int offsetX, int offsetY, int offsetZ)
  235.     {
  236.         float interpolation = (0 - voxelA) / (voxelB - voxelA);
  237.  
  238.         return new Vector3(x + offsetX * interpolation, y + offsetY * interpolation, z + offsetZ * interpolation);
  239.     }
  240.  
  241.     public int CalculateCase(float[] voxelData)
  242.     {
  243.         int triCase = 0;
  244.  
  245.         for (int i = 0; i < 8; i++)
  246.         {
  247.             int bit = voxelData[i] < 0 ? 1 : 0;
  248.             triCase |= bit << i;
  249.         }
  250.  
  251.         return triCase;
  252.     }
  253.  
  254.     struct MeshData
  255.     {
  256.         public List<Vector3> vertices;
  257.         public List<int> indices;
  258.         public Dictionary<Vector3, int> vertDictionary;
  259.         public float[] voxelGrid;
  260.         public int lod;
  261.     }
  262. }
  263.  
  264. struct MeshJob : IJobParallelFor
  265. {
  266.  
  267.     [WriteOnly] public NativeList<float3> vertices;
  268.     [WriteOnly] public NativeList<int> indices;
  269.  
  270.     [ReadOnly] public NativeArray<float> voxelGrid;
  271.     [ReadOnly] public NativeArray<int> triTable;
  272.     [ReadOnly] public NativeArray<int> caseToNumPolys;
  273.  
  274.     public NativeHashMap<float3, int> vertDictionary;
  275.  
  276.     [ReadOnly] public int2 chunkDimensions;
  277.     [ReadOnly] public int lod;
  278.     public void Execute(int index)
  279.     {
  280.         int z = index / (chunkDimensions.x / lod * chunkDimensions.y / lod) * lod;
  281.         int y = (index / (chunkDimensions.x / lod) * lod) - z / lod * chunkDimensions.y;
  282.         int x = index % (chunkDimensions.x / lod) * lod;
  283.  
  284.         int triCase = CalculateCase(index);
  285.  
  286.         for (int j = 0, i = 0; j < caseToNumPolys[triCase]; j++, i += 3)
  287.         {
  288.             for (int h = 0; h < 3; h++)
  289.             {
  290.                 int edge = triTable[triCase + i + (2 - h)];
  291.                 Vector3 vertex = GetEdgePosition(edge, index, x, y, z);
  292.  
  293.                 if (vertDictionary.ContainsKey(vertex))
  294.                 {
  295.                     indices.Add(vertDictionary[vertex]);
  296.                 }
  297.  
  298.                 else
  299.                 {
  300.                     vertices.Add(vertex);
  301.                     indices.Add(vertices.Length - 1);
  302.  
  303.                     vertDictionary.Add(vertex, vertices.Length - 1);
  304.                 }
  305.             }
  306.         }
  307.     }
  308.  
  309.     float3 GetEdgePosition(int edge, int index, int x, int y, int z)
  310.     {
  311.         int i = index * 8;
  312.  
  313.         switch (edge)
  314.         {
  315.             case 0: return GetInterpolatedEdgePosition(x, y, z, voxelGrid[i], voxelGrid[i + 1], 0, 1, 0);
  316.             case 1: return GetInterpolatedEdgePosition(x, y + lod, z, voxelGrid[i + 1], voxelGrid[i + 2], 1, 0, 0);
  317.             case 2: return GetInterpolatedEdgePosition(x + lod, y, z, voxelGrid[i + 3], voxelGrid[i + 2], 0, 1, 0);
  318.             case 3: return GetInterpolatedEdgePosition(x, y, z, voxelGrid[i], voxelGrid[i + 3], 1, 0, 0);
  319.  
  320.             case 4: return GetInterpolatedEdgePosition(x, y, z + lod, voxelGrid[i + 4], voxelGrid[i + 5], 0, 1, 0);
  321.             case 5: return GetInterpolatedEdgePosition(x, y + lod, z + lod, voxelGrid[i + 5], voxelGrid[i + 6], 1, 0, 0);
  322.             case 6: return GetInterpolatedEdgePosition(x + lod, y, z + lod, voxelGrid[i + 7], voxelGrid[i + 6], 0, 1, 0);
  323.             case 7: return GetInterpolatedEdgePosition(x, y, z + lod, voxelGrid[i + 4], voxelGrid[i + 7], 1, 0, 0);
  324.  
  325.             case 8: return GetInterpolatedEdgePosition(x, y, z, voxelGrid[i], voxelGrid[i + 4], 0, 0, 1);
  326.             case 9: return GetInterpolatedEdgePosition(x, y + lod, z, voxelGrid[i + 1], voxelGrid[i + 5], 0, 0, 1);
  327.             case 10: return GetInterpolatedEdgePosition(x + lod, y + lod, z, voxelGrid[i + 2], voxelGrid[i + 6], 0, 0, 1);
  328.             case 11: return GetInterpolatedEdgePosition(x + lod, y, z, voxelGrid[i + 3], voxelGrid[i + 7], 0, 0, 1);
  329.  
  330.             default: throw new ArgumentOutOfRangeException(nameof(edge), "Invalid edge index: " + edge);
  331.         }
  332.     }
  333.     public float3 GetInterpolatedEdgePosition(int x, int y, int z, float voxelA, float voxelB, int offsetX, int offsetY, int offsetZ)
  334.     {
  335.         float interpolation = (0 - voxelA) / (voxelB - voxelA);
  336.  
  337.         return new float3(x + offsetX * interpolation, y + offsetY * interpolation, z + offsetZ * interpolation);
  338.     }
  339.  
  340.  
  341.     public int CalculateCase(int index)
  342.     {
  343.         int triCase = 0;
  344.  
  345.         for (int i = 0; i < 8; i++)
  346.         {
  347.             int bit = voxelGrid[(index * 8) + i] < 0 ? 1 : 0;
  348.             triCase |= bit << i;
  349.         }
  350.  
  351.         return triCase;
  352.     }
  353. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement