Skip to content

Instantly share code, notes, and snippets.

@worldOneo
Created August 28, 2022 12:31
Show Gist options
  • Select an option

  • Save worldOneo/9a59b178071f10542ce691252ae08459 to your computer and use it in GitHub Desktop.

Select an option

Save worldOneo/9a59b178071f10542ce691252ae08459 to your computer and use it in GitHub Desktop.

Revisions

  1. worldOneo created this gist Aug 28, 2022.
    198 changes: 198 additions & 0 deletions Handler.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,198 @@
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;

    [RequireComponent(typeof(MeshFilter))]
    public class GameHandler : MonoBehaviour
    {
    Mesh mesh;

    byte[] data;
    List<Vector3> vertices = new List<Vector3>();
    int[] vertexIndices;
    List<int> triangles = new List<int>();

    public int xSize = 32;
    public int zSize = 32;
    public int ySize = 32;

    float noiseScale = 0.1f;

    // Start is called before the first frame update
    void Start()
    {
    mesh = new Mesh();
    GetComponent<MeshFilter>().mesh = mesh;
    float start = Time.realtimeSinceStartup;
    CreateShape();
    Debug.Log(Time.realtimeSinceStartup - start + " seconds for map generation");
    UpdateMesh();
    }

    void CreateShape()
    {
    vertexIndices = new int[(xSize + 1) * (zSize + 1) * (ySize + 1)];
    data = new Byte[xSize * zSize * ySize];

    for (int i = 0, z = 0; z < zSize; z++)
    {
    for (int x = 0; x < xSize; x++)
    {
    for (int y = 0; y < ySize; y++)
    {
    data[Create3DIndex(x, y, z)] = Perlin3D(x, y, z) > 0.5f ? (byte)1 : (byte)0;
    i++;
    }
    }
    }

    int vert = 0;
    int tris = 0;
    for (int z = 0; z < zSize; z++)
    {
    for (int x = 0; x < xSize; x++)
    {
    for (int y = 0; y < zSize; y++)
    {
    int self = Create3DIndex(x, y, z);
    if (data[self] == 0)
    {
    continue;
    }
    for (int face = 0; face < VertPos.Length; face++)
    {
    Vector3Int next = VertPos[face];
    if (!InChunk(x + next.x, y + next.y, z + next.z))
    {
    CreateQuad(x, y, z, (Face)face);
    continue;
    }
    int index = Create3DIndex(x + next.x, y + next.y, z + next.z);
    if (data[index] == 0)
    {
    CreateQuad(x, y, z, (Face)face);
    }
    }
    }
    vert++;
    tris += 6;
    }
    vert++;
    }
    }

    void CreateQuad(int x, int y, int z, Face face)
    {
    int[] quad = CalculateQuad(x, y, z, face)
    .Select(v => CreateVertex(v.x, v.y, v.z) - 1)
    .ToArray();
    triangles.Add(quad[3]);
    triangles.Add(quad[1]);
    triangles.Add(quad[0]);
    triangles.Add(quad[3]);
    triangles.Add(quad[2]);
    triangles.Add(quad[1]);
    }

    int Create3DIndex(int x, int y, int z) => y + x * ySize + z * ySize * xSize;

    int Create3DOverIndex(int x, int y, int z) =>
    y + x * (ySize + 1) + z * (zSize + 1) * (xSize + 1);

    bool InChunk(int index) => index >= 0 && index < data.Length;

    bool InChunk(int x, int y, int z) =>
    x >= 0 && x < xSize && y >= 0 && y < ySize && z >= 0 && z < zSize;

    int CreateVertex(int x, int y, int z)
    {
    int index = Create3DOverIndex(x, y, z);
    int vertex = vertexIndices[index];
    if (vertex != 0)
    return vertex;
    vertices.Add(new Vector3(x, y, z));
    vertexIndices[index] = vertices.Count();
    return vertices.Count();
    }

    void UpdateMesh()
    {
    mesh.Clear();
    mesh.vertices = vertices.ToArray();
    mesh.triangles = triangles.ToArray();
    mesh.RecalculateNormals();
    mesh.RecalculateBounds();
    MeshCollider meshCollider = gameObject.GetComponent<MeshCollider>();
    meshCollider.sharedMesh = mesh;
    }

    //dunno how this works. copied it from somewhere.
    public float Perlin3D(float _x, float _y, float _z)
    {
    float x = _x * noiseScale;
    float y = _y * noiseScale;
    float z = _z * noiseScale;
    float ab = Mathf.PerlinNoise(x, y);
    float bc = Mathf.PerlinNoise(y, z);
    float ac = Mathf.PerlinNoise(x, z);

    float ba = Mathf.PerlinNoise(y, x);
    float cb = Mathf.PerlinNoise(z, y);
    float ca = Mathf.PerlinNoise(z, x);

    float abc = ab + bc + ac + ba + cb + ca;
    return abc / 6f;
    }

    Vector3Int[] VertPos = new Vector3Int[6]
    {
    new Vector3Int(0, 1, 0),
    new Vector3Int(0, -1, 0),
    new Vector3Int(0, 0, 1),
    new Vector3Int(0, 0, -1),
    new Vector3Int(1, 0, 0),
    new Vector3Int(-1, 0, 0),
    };

    enum Face
    {
    Top = 0,
    Bottom = 1,
    Right = 2,
    Left = 3,
    Front = 4,
    Back = 5,
    }

    Vector3Int[] CalculateQuad(int x, int y, int z, Face face)
    {
    int[,] offset = QuadVertices[(int)face];
    Vector3Int[] vertices = new Vector3Int[4];
    for (int i = 0; i < 4; i++)
    {
    vertices[i] = new Vector3Int(x + offset[i, 0], y + offset[i, 1], z + offset[i, 2]);
    }
    return vertices;
    }

    int[,] Faces = new int[6, 3]
    {
    { 0, 1, 0 }, //top
    { 0, -1, 0 }, //bottom
    { 0, 0, 1 }, //right
    { 0, 0, -1 }, //left
    { 1, 0, 0 }, //front
    { -1, 0, 0 } //back
    };

    int[][,] QuadVertices = new int[6][,]
    {
    new int[,] { { 0, 1, 0 }, { 1, 1, 0 }, { 1, 1, 1 }, { 0, 1, 1 } }, // top
    new int[,] { { 0, 0, 1 }, { 1, 0, 1 }, { 1, 0, 0 }, { 0, 0, 0 } }, // bottom
    new int[,] { { 0, 0, 1 }, { 0, 1, 1 }, { 1, 1, 1 }, { 1, 0, 1 } }, // right
    new int[,] { { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 0, 0 } }, // left
    new int[,] { { 1, 0, 1 }, { 1, 1, 1 }, { 1, 1, 0 }, { 1, 0, 0 } }, // front
    new int[,] { { 0, 0, 0 }, { 0, 1, 0 }, { 0, 1, 1 }, { 0, 0, 1 } }, // back
    };
    }