Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- using Unity.Mathematics;
- using Unity.Collections;
- using Unity.Jobs;
- using Unity.VisualScripting;
- using Unity.Burst;
- using UnityEngine.Rendering;
- using System.Collections;
- public class MeshGenerator : MonoBehaviour
- {
- public static Vector2Int chunkDimensions = new Vector2Int(32, 128);
- public Material material;
- public ComputeShader voxelGridShader;
- public int brushSize;
- public float brushStrength;
- public int lod;
- public int maxLod;
- public float surfaceLevel;
- public bool hideMeshOnPlay;
- [Header("Noise Settings")]
- public float heightMultiplier;
- public AnimationCurve heightCurve;
- public float frequency;
- public float lacunarity;
- public float persistance;
- public int octaves;
- public float density;
- public float warpingStrength;
- public float warpingFrequency;
- public float mountainHeightOffset;
- public Vector2 offset;
- [Header("")]
- public bool autoUpdate;
- public string executionTime;
- int[] caseToNumpolys;
- int[][] triTable;
- NativeArray<int> nativeTriTable;
- NativeArray<int> nativeCaseToNumPolys;
- Camera cam;
- VoxelGrid voxelGrid;
- private void Start()
- {
- Init();
- if (GameObject.Find("Mesh") != null)
- {
- GameObject.Find("Mesh").SetActive(!hideMeshOnPlay);
- }
- }
- private void Update()
- {
- if (Input.GetKeyDown(KeyCode.Space))
- {
- EditorMesh();
- }
- }
- public GameObject ChunkObject(Vector2 position)
- {
- GameObject chunk = new GameObject("Chunk");
- chunk.AddComponent<MeshFilter>().mesh = ChunkMesh(position, 0);
- chunk.AddComponent<MeshRenderer>().material = material;
- chunk.GetComponent<MeshRenderer>().receiveShadows = false;
- chunk.GetComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
- return chunk;
- }
- public Mesh ChunkMesh(Vector2 position, int lod)
- {
- lod = lod == 0 ? 1 : lod * 2;
- NativeList<float3> nativeVertices = new NativeList<float3>(Allocator.TempJob);
- NativeList<int> nativeIndices = new NativeList<int>(Allocator.TempJob);
- NativeHashMap<float3, int> vertDictionary = new NativeHashMap<float3, int>(256, Allocator.TempJob);
- NativeArray<float> nativeVoxelGrid = voxelGrid.RequestVoxelGrid(position, lod);
- MeshJob job = new MeshJob
- {
- vertices = nativeVertices,
- indices = nativeIndices,
- vertDictionary = vertDictionary,
- voxelGrid = nativeVoxelGrid,
- triTable = nativeTriTable,
- caseToNumPolys = nativeCaseToNumPolys,
- chunkDimensions = new int2(chunkDimensions.x, chunkDimensions.y),
- lod = lod
- };
- job.Schedule().Complete();
- Mesh mesh = new Mesh();
- mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
- Vector3[] vertices = new Vector3[nativeVertices.Length];
- int[] indices = new int[nativeIndices.Length];
- for (int i = 0; i < nativeVertices.Length; i++)
- {
- vertices[i] = nativeVertices[i];
- }
- for (int i = 0; i < nativeIndices.Length; i++)
- {
- indices[i] = nativeIndices[i];
- }
- mesh.vertices = vertices;
- mesh.triangles = indices;
- mesh.RecalculateNormals();
- nativeVertices.Dispose();
- nativeIndices.Dispose();
- vertDictionary.Dispose();
- nativeVoxelGrid.Dispose();
- return mesh;
- }
- public void EditorMesh()
- {
- Init();
- float startTime = Time.realtimeSinceStartup;
- Mesh mesh = ChunkMesh(offset / 10, lod);
- executionTime = ((Time.realtimeSinceStartup - startTime) * 1000f) + "ms";
- if (GameObject.Find("Mesh") == null)
- {
- GameObject obj = new GameObject("Mesh");
- obj.transform.parent = transform;
- obj.AddComponent<MeshFilter>().mesh = mesh;
- obj.AddComponent<MeshRenderer>().material = material;
- obj.AddComponent<MeshCollider>();
- }
- else
- {
- var mf = GameObject.Find("Mesh").GetComponent<MeshFilter>();
- var collider = GameObject.Find("Mesh").GetComponent<MeshCollider>();
- mf.mesh = mesh;
- collider.sharedMesh = null;
- collider.sharedMesh = mesh;
- }
- }
- void Init()
- {
- caseToNumpolys = Tables.caseToNumPolys;
- triTable = Tables.triTable;
- nativeTriTable = new NativeArray<int>(256 * 15, Allocator.Persistent);
- nativeCaseToNumPolys = new NativeArray<int>(256, Allocator.Persistent);
- for (int i = 0; i < triTable.Length; i++)
- {
- nativeCaseToNumPolys[i] = caseToNumpolys[i];
- for (int j = 0; j < 15; j++)
- {
- nativeTriTable[(i * 15) + j] = triTable[i][j];
- }
- }
- cam = Camera.main;
- voxelGrid = new VoxelGrid(frequency, lacunarity, persistance, octaves, surfaceLevel, density, heightMultiplier, voxelGridShader);
- }
- IEnumerator ReadVoxelGrid(int length, ComputeBuffer buffer)
- {
- voxelGridShader.Dispatch(0, length, 1, 1);
- AsyncGPUReadbackRequest request = AsyncGPUReadback.Request(buffer);
- while (!request.done)
- {
- yield return null;
- }
- if (request.hasError)
- {
- Debug.LogWarning("GPU readback error detected.");
- }
- else
- {
- ConstructMesh(request.GetData<float>().ToArray());
- }
- }
- void ConstructMesh(float[] voxelGrid)
- {
- }
- }
- [BurstCompile]
- struct MeshJob : IJob
- {
- public NativeList<float3> vertices;
- public NativeList<int> indices;
- public NativeHashMap<float3, int> vertDictionary;
- [ReadOnly] public NativeArray<float> voxelGrid;
- [ReadOnly] public NativeArray<int> triTable;
- [ReadOnly] public NativeArray<int> caseToNumPolys;
- [ReadOnly] public int2 chunkDimensions;
- [ReadOnly] public int lod;
- public void Execute()
- {
- for (int z = 0, i = 0; z < chunkDimensions.x; z += lod)
- {
- for (int y = 0; y < chunkDimensions.y; y += lod)
- {
- for (int x = 0; x < chunkDimensions.x; x += lod, i++)
- {
- AddVertices(i, x, y, z);
- }
- }
- }
- }
- void AddVertices(int index, int x, int y, int z)
- {
- int triCase = CalculateCase(index);
- for (int j = 0, i = 0; j < caseToNumPolys[triCase]; j++, i += 3)
- {
- for (int h = 0; h < 3; h++)
- {
- int edge = triTable[(triCase * 15) + i + (2 - h)];
- float3 vertex = GetEdgePosition(edge, index, lod, x, y, z);
- if (vertDictionary.ContainsKey(vertex))
- {
- indices.Add(vertDictionary[vertex]);
- }
- else
- {
- vertices.Add(vertex);
- indices.Add(vertices.Length - 1);
- vertDictionary.Add(vertex, vertices.Length - 1);
- }
- }
- }
- }
- float3 GetEdgePosition(int edge, int index, int lod, int x, int y, int z)
- {
- int i = index * 8;
- switch (edge)
- {
- case 0: return GetInterpolatedEdgePosition(x, y, z, voxelGrid[i], voxelGrid[i + 1], 0, 1, 0);
- case 1: return GetInterpolatedEdgePosition(x, y + lod, z, voxelGrid[i + 1], voxelGrid[i + 2], 1, 0, 0);
- case 2: return GetInterpolatedEdgePosition(x + lod, y, z, voxelGrid[i + 3], voxelGrid[i + 2], 0, 1, 0);
- case 3: return GetInterpolatedEdgePosition(x, y, z, voxelGrid[i], voxelGrid[i + 3], 1, 0, 0);
- case 4: return GetInterpolatedEdgePosition(x, y, z + lod, voxelGrid[i + 4], voxelGrid[i + 5], 0, 1, 0);
- case 5: return GetInterpolatedEdgePosition(x, y + lod, z + lod, voxelGrid[i + 5], voxelGrid[i + 6], 1, 0, 0);
- case 6: return GetInterpolatedEdgePosition(x + lod, y, z + lod, voxelGrid[i + 7], voxelGrid[i + 6], 0, 1, 0);
- case 7: return GetInterpolatedEdgePosition(x, y, z + lod, voxelGrid[i + 4], voxelGrid[i + 7], 1, 0, 0);
- case 8: return GetInterpolatedEdgePosition(x, y, z, voxelGrid[i], voxelGrid[i + 4], 0, 0, 1);
- case 9: return GetInterpolatedEdgePosition(x, y + lod, z, voxelGrid[i + 1], voxelGrid[i + 5], 0, 0, 1);
- case 10: return GetInterpolatedEdgePosition(x + lod, y + lod, z, voxelGrid[i + 2], voxelGrid[i + 6], 0, 0, 1);
- case 11: return GetInterpolatedEdgePosition(x + lod, y, z, voxelGrid[i + 3], voxelGrid[i + 7], 0, 0, 1);
- default: throw new ArgumentOutOfRangeException(nameof(edge), "Invalid edge index: " + edge);
- }
- }
- public float3 GetInterpolatedEdgePosition(int x, int y, int z, float voxelA, float voxelB, int offsetX, int offsetY, int offsetZ)
- {
- float interpolation = (0 - voxelA) / (voxelB - voxelA);
- return new float3(x + offsetX * interpolation, y + offsetY * interpolation, z + offsetZ * interpolation);
- }
- public int CalculateCase(int index)
- {
- int triCase = 0;
- for (int i = 0; i < 8; i++)
- {
- int bit = voxelGrid[(index * 8) + i] < 0 ? 1 : 0;
- triCase |= bit << i;
- }
- return triCase;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement