Skip to content

Instantly share code, notes, and snippets.

@worldOneo
Created August 28, 2022 12:31
Show Gist options
  • Save worldOneo/9a59b178071f10542ce691252ae08459 to your computer and use it in GitHub Desktop.
Save worldOneo/9a59b178071f10542ce691252ae08459 to your computer and use it in GitHub Desktop.
Unity procedural voxel generator
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
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment