Advertisement
JontePonte

meshgen draft

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