This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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