Paste
Of Code


 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
using System;
using System.Collections.Generic;
using System.Collections;
using UnityEngine;
using System.Runtime.CompilerServices;

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class CubesMarching : MonoBehaviour
{
    public ChunkManager chunkManager;

    public bool useChunkManager;

    public int width = 10;
    public int height = 10;

    [Range(0, 1)] public float heightThreshold = .5f;

    [Range(.001f, .2f)] public float noiseFrequency = .1f;
    public float noiseAmplitude = 1.5f;
    public int noiseSeed;
    public float baseHeight;

    public bool interpolate;

    private float[,,] heights;

    private List<Vector3> vertices = new List<Vector3>();
    private List<int> triangles = new List<int>();

    private float lastHeight;
    private float lastHeightThreshold;

    public MeshFilter meshFilter;

    private FastNoiseLite fastNoise;

    private int incrementIdk;

    void Awake()
    {
        if (useChunkManager)
        {
            width = chunkManager.width;
            height = chunkManager.height;

            heightThreshold = chunkManager.heightThreshold;
            noiseAmplitude = chunkManager.noiseAmplitude;
            noiseFrequency = chunkManager.noiseFrequency;
            noiseSeed = chunkManager.noiseSeed;
            fastNoise = chunkManager.fastNoise;
        }
        else
        {
            fastNoise = new FastNoiseLite();
        }
        GetComponent<MeshCollider>().sharedMesh = meshFilter.mesh;
    }



    [ContextMenu("Generate Mesh")]
    public void GenerateMesh()
    {
        fastNoise = new FastNoiseLite();

        meshFilter = GetComponent<MeshFilter>();



        fastNoise.SetNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
        fastNoise.SetFrequency(noiseFrequency / 10);
        fastNoise.SetFractalType(FastNoiseLite.FractalType.FBm);

        SetHeights();
        MarchCubes();
        SetMesh();

        //StartCoroutine(UpdateChanged());
        GetComponent<MeshCollider>().sharedMesh = meshFilter.sharedMesh;

    }

    [ContextMenu("Regenerate Mesh")]
    public void RegenerateMesh()
    {
        ClearMesh();
        GenerateMesh();
    }

    [ContextMenu("Clear Mesh")]
    public void ClearMesh()
    {
        vertices.Clear();
        triangles.Clear();

        meshFilter.mesh = null;
    }


    public IEnumerator UpdateChanged()
    {
        yield return new WaitForSeconds(UnityEngine.Random.Range(0f, 1f));

        while (true)
        {

            if (noiseFrequency / 10 != fastNoise.GetFrequency() || noiseSeed != fastNoise.GetSeed() || height != lastHeight || heightThreshold != lastHeightThreshold)
            {
                SetHeights();
                MarchCubes();
                SetMesh();

                lastHeight = height;
                lastHeightThreshold = heightThreshold;


                yield return new WaitForSeconds(1);
            }

            yield return null;
        }
    }

    private void SetHeights()
    {
        heights = new float[width + 1, height + 1, width + 1];

        for (int x = 0; x < width + 1; x++)
        {
            for (int y = 0; y < height + 1; y++)
            {
                for (int z = 0; z < width + 1; z++)
                {
                    float currentHeight = baseHeight + GetDensity(x, z);
                    float newHeight;

                    if (y > currentHeight)
                    {
                        newHeight = y - currentHeight;
                    }
                    else
                    {
                        newHeight = currentHeight - y;
                    }

                    heights[x, y, z] = newHeight;
                }
            }
        }
    }

    private float GetDensity(float x, float z)
    {
        return noiseAmplitude * fastNoise.GetNoise(x + transform.position.x, z + transform.position.z) / 2;
    }

    private IEnumerator MarchCubes()
    {
        vertices.Clear();
        triangles.Clear();

        vertices.Capacity = width * width * height * 5 * 3;
        triangles.Capacity = width * width * height * 5 * 3;

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                for (int z = 0; z < width; z++)
                {
                    float[] cubeCorners = new float[8];

                    for (int i = 0; i < 8; i++)
                    {
                        Vector3Int corner = new Vector3Int(x, y, z) + MarchingTable.Corners[i];
                        cubeCorners[i] = heights[corner.x, corner.y, corner.z];
                        incrementIdk++;
                    }

                    MarchCube(new Vector3(x, y, z), GetConfigurationIndex(cubeCorners));
                }
                if (incrementIdk == 1000)
                {
                    yield return null;
                }
            }
        }
    }

    private void MarchCube(Vector3 position, int configIndex)
    {
        if (configIndex == 0 || configIndex == 255)
        {
            return;
        }

        int edgeIndex = 0;

        for (int t = 0; t < 5; t++)
        {
            for (int v = 0; v < 3; v++)
            {
                int triTableValue = MarchingTable.Triangles[configIndex, edgeIndex];

                if (triTableValue == -1)
                {
                    return;
                }

                Vector3 edgeStart = position + MarchingTable.Edges[triTableValue, 0];
                Vector3 edgeEnd = position + MarchingTable.Edges[triTableValue, 1];


                Vector3 vertex;
                float value1 = heights[Mathf.RoundToInt(edgeStart.x), Mathf.RoundToInt(edgeStart.y), Mathf.RoundToInt(edgeStart.z)];
                float value2 = heights[Mathf.RoundToInt(edgeEnd.x), Mathf.RoundToInt(edgeEnd.y), Mathf.RoundToInt(edgeEnd.z)];


                if (interpolate)
                    vertex = edgeStart + (heightThreshold - value1) / (value2 - value1) * (edgeEnd - edgeStart);
                else
                    vertex = (edgeStart + edgeEnd) / 2f;

                // p = p1 + (t-v1)/(v2-v1) * (p2-p1)

                vertices.Add(vertex);

                triangles.Add(vertices.Count - 1);

                edgeIndex++;
            }

        }
    }

    private int GetConfigurationIndex(float[] cubeCorners)
    {
        int configIndex = 0;

        for (int i = 0; i < 8; i++)
        {
            if (cubeCorners[i] > heightThreshold)
            {
                configIndex |= 1 << i;
            }
        }

        return configIndex;
    }


    private void SetMesh()
    {
        Mesh mesh = new Mesh();

        mesh.SetVertices(vertices);
        mesh.SetTriangles(triangles, 0);
        mesh.RecalculateNormals();

        meshFilter.mesh = mesh;
    }

}

Toggle: theme, font