Skip to content
Snippets Groups Projects
TerrainGenerator.cs 5.33 KiB
Newer Older
Chang, Ryan's avatar
Chang, Ryan committed
using System.Threading;
Chang, Ryan's avatar
Chang, Ryan committed
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Mathematics;
Chang, Ryan's avatar
Chang, Ryan committed

[System.Serializable]
public struct Octave
{
    public float amplitude;
    public float frequency;
    public NoiseType type;
}

[System.Serializable]
public enum NoiseType
{
    MathfPerlin,
    MathematicsPerlin,
    Simplex,
    Celluar
Chang, Ryan's avatar
Chang, Ryan committed
}

Chang, Ryan's avatar
Chang, Ryan committed
public class TerrainGenThread
{
    private Vector2 initialCrawlPosition;
    private TerrainData terrainData;

    public TerrainGenThread(Vector2 initialCrawlPos, out TerrainData data)
    {
        initialCrawlPosition = initialCrawlPos;
        data = new();
        data.size = new(512, 512, 512);
        terrainData = data;
    }

    public void Generate()
    {

    }
}

Chang, Ryan's avatar
Chang, Ryan committed
public class TerrainGenerator : MonoBehaviour
{
Chang, Ryan's avatar
Chang, Ryan committed
    [Header("User settings")]
Chang, Ryan's avatar
Chang, Ryan committed
    public Terrain terrain;

Chang, Ryan's avatar
Chang, Ryan committed
    public Terrain[] terrains;

    public List<Octave> octaves;

    [Tooltip("The seed of the generation.")]
    public Vector2 crawlStartPosition;

    public bool generateNewSeed = true;

    public bool refresh;
Chang, Ryan's avatar
Chang, Ryan committed

    //[Tooltip("How many terrain elements are there?")]
    //public Vector2Int terrainsSize = new(1,1);

    [Tooltip("How fine grain the generated terrain will be. " +
        "Larger values = more precise. Recommended value is 513.")]
    public int xSamples = 513, ySamples = 513;
Chang, Ryan's avatar
Chang, Ryan committed

Chang, Ryan's avatar
Chang, Ryan committed
    [Header("Autogenerated values")]
    [Tooltip("Which terrain grid are we on right now?")]
    public Vector2Int currentGridPosition;

    [Tooltip("Dictionary of previously loaded terrains.")]
    public Dictionary<Vector2Int, TerrainData> previouslyLoaded;

    /// <summary>
    /// 4 threads for each cardinal direction. Responsible for creating
    /// their respective terrains in each cardinal direction.
    /// </summary>
    private Thread northThread, eastThread, southThread, westThread;
    
    //private TerrainGenThread GenerateThread(Vector2 crawlPos, Vector2Int gridPos)
    //{
    //    TerrainGenThread genThread = new(crawlPos, out TerrainData data);
    //    previouslyLoaded[gridPos] = data;

    //    return genThread;
    //}

    public virtual void GenerateSurronding(Vector2 initCrawlPos)
    {
        if (previouslyLoaded.ContainsKey(currentGridPosition + Vector2Int.up))
        {
            TerrainGenThread genThread = new(initCrawlPos + Vector2.up * ySamples, out TerrainData data);
            northThread = new Thread(new ThreadStart(genThread.Generate));
            northThread.Start();
        }
        if (previouslyLoaded.ContainsKey(currentGridPosition + Vector2Int.down))
        {
            TerrainGenThread genThread = new(initCrawlPos + Vector2.down * ySamples, out TerrainData data);
            southThread = new Thread(new ThreadStart(genThread.Generate));
            southThread.Start();
        }
        if (previouslyLoaded.ContainsKey(currentGridPosition + Vector2Int.right))
        {
            TerrainGenThread genThread = new(initCrawlPos + Vector2.right * xSamples, out TerrainData data);
            eastThread = new Thread(new ThreadStart(genThread.Generate));
            eastThread.Start();
        }
        if (previouslyLoaded.ContainsKey(currentGridPosition + Vector2Int.left))
        {
            TerrainGenThread genThread = new(initCrawlPos + Vector2.left * xSamples, out TerrainData data);
            westThread = new Thread(new ThreadStart(genThread.Generate));
            westThread.Start();
        }

        // Wait for threads to finish
        northThread.Join();
        southThread.Join();
        eastThread.Join();
        westThread.Join();

        // Add data to terrains without things.
    }

Chang, Ryan's avatar
Chang, Ryan committed
    public virtual void Generate()
Chang, Ryan's avatar
Chang, Ryan committed
    {
        float[,] heights = new float[xSamples, ySamples];

Chang, Ryan's avatar
Chang, Ryan committed
            crawlStartPosition = RNG.GetRandomVector2(-xSamples, -ySamples, xSamples, ySamples);
Chang, Ryan's avatar
Chang, Ryan committed

        foreach (var octave in octaves)
        {
            for (int x = 0; x < xSamples; x++)
            {
                for (int y = 0; y < ySamples; y++)
                {
                    float2 crawlPos = new(x * octave.frequency + crawlStartPosition.x, y * octave.frequency + crawlStartPosition.y);
                    float addition;

                    switch (octave.type)
                    {
                        default:
                        case NoiseType.MathfPerlin:
                            addition = Mathf.PerlinNoise(crawlPos.x, crawlPos.y);
                            break;
                        case NoiseType.MathematicsPerlin:
                            addition = noise.cnoise(crawlPos) / 2.3f + 0.5f;
                            break;
                        case NoiseType.Simplex:
                            addition = noise.snoise(crawlPos) / 4.6f + 0.5f;
                            break;
                        case NoiseType.Celluar:
                            addition = noise.cellular(crawlPos).x / 2.3f + 0.5f;
                            break;
                    }
                    heights[x, y] += addition * octave.amplitude;
                }
            }
        }

        terrain.terrainData.SetHeights(0, 0, heights);
    }

Chang, Ryan's avatar
Chang, Ryan committed
    private void Start()
    {
        terrains = GetComponentsInChildren<Terrain>();
        Generate();
    }

    private void Update()
    {
        if (refresh)
        {
            refresh = false;
Chang, Ryan's avatar
Chang, Ryan committed
            Generate();
Chang, Ryan's avatar
Chang, Ryan committed
    }
}