Skip to content

Instantly share code, notes, and snippets.

@dmillerw
Last active August 29, 2015 13:56
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save dmillerw/b50bc0b8d15a5454871a to your computer and use it in GitHub Desktop.
using UnityEngine;
using System.Collections.Generic;
public class CaveRenderer : MonoBehaviour {
// Size of each cell
private static int PlaneSize = 10;
// Material the mesh should take on
public Material MeshMaterial;
// Whether to draw the map boarder
public bool DrawMapBorder = false;
public bool DrawFloor = true;
public bool DrawWalls = true;
public bool DrawCeiling = true;
public bool GenerateFloorCollider = true;
// Map dimensions
public int MapX = 50;
public int MapY = 50;
// How many steps to take
public int Iterations = 500;
// Cave smoothing
public bool SmoothCaves = true;
// How many neighbors are required to fill the cell
public int SmoothingNeighborStart = 2;
// How many times should the map be passed over
public int SmoothPasses = 1;
// Corridor bias - If true will continue going in the same direction as the last step
public bool CorridorBias = true;
public int CorridorBiasProbability = 50;
public int CorridorIterationHold = 0;
// Center bias - If true will try and head for the center of the map
public bool CenterBias = false;
public int CenterBiasProbablility = 50;
public int CenterIterationHold = 0;
// Origin bias - If true will try and head back to the starting point
public bool OriginBias = false;
public int OriginBiasProbablility = 50;
public int OriginIterationHold = 0;
// Whether steps can go over already active cells - Note, if the active cell is completely enclosed, it will ignore this rule
public bool RetraceSteps = false;
// Starting point
public int OriginX,OriginY = 0;
void Start() {
// Assign Material if not already
if (MeshMaterial == null) {
MeshMaterial = Resources.Load("Smooth", typeof(Material)) as Material;
}
// Setup generator
DrunkenGenerator Generator = new DrunkenGenerator();
Generator.MapX = MapX;
Generator.MapY = MapY;
Generator.Iterations = Iterations;
Generator.SmoothCaves = SmoothCaves;
Generator.SmoothingNeighborStart = SmoothingNeighborStart;
Generator.SmoothPasses = SmoothPasses;
Generator.CorridorBias = CorridorBias;
Generator.CorridorBiasProbability = CorridorBiasProbability;
Generator.CorridorIterationHold = CorridorIterationHold;
Generator.CenterBias = CenterBias;
Generator.CenterBiasProbablility = CenterBiasProbablility;
Generator.CenterIterationHold = CenterIterationHold;
Generator.OriginBias = OriginBias;
Generator.OriginBiasProbablility = OriginBiasProbablility;
Generator.OriginIterationHold = OriginIterationHold;
Generator.RetraceSteps = RetraceSteps;
Generator.OriginX = OriginX;
Generator.OriginY = OriginY;
// Generate
Generator.Build();
// Draw map border
if (DrawMapBorder) {
for (int i=0; i<Generator.MapX; i++) {
for (int j=0; j<Generator.MapY; j++) {
if ((i == 0 || i == Generator.MapX - 1) || (j == 0 || j == Generator.MapY - 1)) {
GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
plane.transform.position = new Vector3(i * PlaneSize, 0, j * PlaneSize);
plane.transform.localScale = new Vector3(PlaneSize / 10, 1, PlaneSize / 10);
}
}
}
}
// Generate mesh
if (DrawFloor) {
GenerateFloorMesh(Generator, MeshMaterial, GenerateFloorCollider);
}
if (DrawWalls) {
GenerateWalls(Generator, MeshMaterial);
}
if (DrawCeiling) {
GenerateCeilingMesh(Generator, MeshMaterial);
}
}
public static void GenerateFloorMesh(DrunkenGenerator Generator, Material MeshMaterial, bool GenerateCollider) {
List<Vector3> VertexList = new List<Vector3>();
List<Vector2> UVList = new List<Vector2>();
List<int> TriList = new List<int>();
int CurrentCell = 0;
for (int i=0; i<Generator.MapX; i++) {
for (int j=0; j<Generator.MapY; j++) {
if (Generator.GetCellState(i, j)) {
// If we end up adding more than 65000 vertices to the mesh, send what we have to be generated, then start a new one
if (VertexList.Count + 4 >= 65000) {
GenerateMesh("Floor", VertexList.ToArray(), UVList.ToArray(), TriList.ToArray(), MeshMaterial, GenerateCollider);
VertexList.Clear();
UVList.Clear();
TriList.Clear();
CurrentCell = 0;
}
float CellX = (i - 0.5f) * PlaneSize;
float CellY = (j - 0.5f) * PlaneSize;
VertexList.Add(new Vector3(CellX, 0, CellY));
VertexList.Add(new Vector3(CellX + PlaneSize, 0, CellY));
VertexList.Add(new Vector3(CellX, 0, CellY + PlaneSize));
VertexList.Add(new Vector3(CellX + PlaneSize, 0, CellY + PlaneSize));
UVList.Add(new Vector2(0f, 0f));
UVList.Add(new Vector2(1f, 0f));
UVList.Add(new Vector2(0f, 1f));
UVList.Add(new Vector2(1f, 1f));
TriList.Add(0 + (4 * CurrentCell));
TriList.Add(3 + (4 * CurrentCell));
TriList.Add(1 + (4 * CurrentCell));
TriList.Add(0 + (4 * CurrentCell));
TriList.Add(2 + (4 * CurrentCell));
TriList.Add(3 + (4 * CurrentCell));
CurrentCell++;
}
}
}
GenerateMesh("Floor", VertexList.ToArray(), UVList.ToArray(), TriList.ToArray(), MeshMaterial, GenerateCollider);
}
public static void GenerateWalls(DrunkenGenerator Generator, Material MeshMaterial) {
for (int i=0; i<Generator.MapX; i++) {
for (int j=0; j<Generator.MapY; j++) {
for (int x=0; x<4; x++) {
if (Generator.GetCellState(i, j)) {
int AX = i;
int AY = j;
switch(x) {
case 0: AY++; break;
case 1: AX++; break;
case 2: AY--; break;
case 3: AX--; break;
}
if (!Generator.GetCellState(AX, AY)) {
Vector3 Position = new Vector3(0, 0, 0);
Vector3 Rotation = new Vector3(0, 0, 0);
switch(x) {
case 0: {
Position = new Vector3(i * PlaneSize, PlaneSize / 2, (j + (0.5f)) * PlaneSize);
Rotation = new Vector3(0, 270, 90);
break;
}
case 1: {
Position = new Vector3((i + (0.5f)) * PlaneSize, PlaneSize / 2, j * PlaneSize);
Rotation = new Vector3(0, 0, 90);
break;
}
case 2: {
Position = new Vector3(i * PlaneSize, PlaneSize / 2, (j - (0.5f)) * PlaneSize);
Rotation = new Vector3(0, 90, 90);
break;
}
case 3: {
Position = new Vector3((i - (0.5f)) * PlaneSize, PlaneSize / 2, j * PlaneSize);
Rotation = new Vector3(0, 180, 90);
break;
}
}
GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
plane.transform.position = Position;
plane.transform.Rotate(Rotation);
plane.transform.localScale = new Vector3(PlaneSize / 10, 1, PlaneSize / 10);
plane.renderer.material = MeshMaterial;
plane.tag = "Element";
}
}
}
}
}
}
public static void GenerateCeilingMesh(DrunkenGenerator Generator, Material MeshMaterial) {
List<Vector3> VertexList = new List<Vector3>();
List<Vector2> UVList = new List<Vector2>();
List<int> TriList = new List<int>();
int CurrentCell = 0;
for (int i=0; i<Generator.MapX; i++) {
for (int j=0; j<Generator.MapY; j++) {
if (Generator.GetCellState(i, j)) {
// If we end up adding more than 65000 vertices to the mesh, send what we have to be generated, then start a new one
if (VertexList.Count + 4 >= 65000) {
GenerateMesh("Ceiling", VertexList.ToArray(), UVList.ToArray(), TriList.ToArray(), MeshMaterial, false);
VertexList.Clear();
UVList.Clear();
TriList.Clear();
CurrentCell = 0;
}
float CellX = (i - 0.5f) * PlaneSize;
float CellY = (j - 0.5f) * PlaneSize;
VertexList.Add(new Vector3(CellX, PlaneSize, CellY));
VertexList.Add(new Vector3(CellX + PlaneSize, PlaneSize, CellY));
VertexList.Add(new Vector3(CellX, PlaneSize, CellY + PlaneSize));
VertexList.Add(new Vector3(CellX + PlaneSize, PlaneSize, CellY + PlaneSize));
UVList.Add(new Vector2(0f, 0f));
UVList.Add(new Vector2(1f, 0f));
UVList.Add(new Vector2(0f, 1f));
UVList.Add(new Vector2(1f, 1f));
TriList.Add(1 + (4 * CurrentCell));
TriList.Add(3 + (4 * CurrentCell));
TriList.Add(0 + (4 * CurrentCell));
TriList.Add(3 + (4 * CurrentCell));
TriList.Add(2 + (4 * CurrentCell));
TriList.Add(0 + (4 * CurrentCell));
CurrentCell++;
}
}
}
GenerateMesh("Ceiling", VertexList.ToArray(), UVList.ToArray(), TriList.ToArray(), MeshMaterial, false);
}
static void GenerateMesh(string Name, Vector3[] Vertices, Vector2[] UV, int[] Triangles, Material MeshMaterial, bool GenerateCollider) {
GameObject MeshObject = new GameObject(Name);
MeshObject.tag = "Element";
Mesh ObjectMesh = new Mesh();
MeshObject.AddComponent("MeshFilter");
MeshObject.AddComponent("MeshRenderer");
if (GenerateCollider) {
MeshObject.AddComponent("MeshCollider");
}
MeshObject.renderer.material = MeshMaterial;
ObjectMesh.vertices = Vertices;
ObjectMesh.uv = UV;
ObjectMesh.triangles = Triangles;
ObjectMesh.RecalculateNormals();
MeshObject.GetComponent<MeshFilter>().mesh = ObjectMesh;
if (GenerateCollider) {
MeshObject.GetComponent<MeshCollider>().sharedMesh = MeshObject.GetComponent<MeshFilter>().mesh;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment