Advertisement
JontePonte

Non job meshgen

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