Skip to content

Instantly share code, notes, and snippets.

@ircnelson
Last active August 29, 2015 14:17
Show Gist options
  • Save ircnelson/d0759f6b4ae56e945d8f to your computer and use it in GitHub Desktop.
Save ircnelson/d0759f6b4ae56e945d8f to your computer and use it in GitHub Desktop.
using UnityEngine;
using System.Collections;
public class Level {
public Mesh mesh;
private bool drawDebugMesh;
private Path path;
private Face[] faces;
private int[] triangles;
private Vector3[] vertices;
private Vector2[] uvs;
public Level (int len, float startRadius, float maxRadius, float partLength, int sides, bool draw) {
float startTime = Time.realtimeSinceStartup;
drawDebugMesh = draw;
mesh = new Mesh ();
uvs = new Vector2[len * sides];
path = new Path (len, startRadius, maxRadius, partLength, drawDebugMesh);
faces = GenerateFaces (path, sides, drawDebugMesh);
vertices = GenerateVertices (len, sides, faces);
triangles = GenerateTriangles (len, sides, vertices);
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uvs;
mesh.RecalculateNormals ();
mesh.Optimize ();
Debug.Log ((Time.realtimeSinceStartup - startTime) * 1000 + "ms for generating level");
}
private Face[] GenerateFaces (Path p, int sides, bool drawDebugMesh) {
Face[] f = new Face[p.length];
for (int n = 0; n < f.Length; n++) {
f[n] = new Face (p.radius[n], sides, p.centerPoints[n], p.centerPointNormals[n], p.faceRotation[n], drawDebugMesh);
if (n != 0 && drawDebugMesh) {
for (int i = 1; i < f[n].vertices.Length; i++) {
Debug.DrawLine (f[n].vertices[i], f[n - 1].vertices[i], Color.red, 600);
}
}
}
return f;
}
private Vector3[] GenerateVertices (int len, int sides, Face[] face) {
Vector3[] v = new Vector3[len * sides];
for (int n = 0; n < face.Length; n++) {
for (int i = 0; i < sides; i++) {
v[n * (sides) + i] = face[n].vertices[i];
}
}
return v;
}
private int[] GenerateTriangles (int len, int sides, Vector3[] verts) {
int[] tris = new int[verts.Length * 6];
for (int n = 0; n < len - 1; n++) {
for (int i = 0; i < sides; i++) {
if (i != sides - 1) {
tris[n * (sides) * 6 + i * 6] = (n * sides) + i;
tris[n * (sides) * 6 + i * 6 + 1] = (n + 1) * sides + i;
tris[n * (sides) * 6 + i * 6 + 2] = (n + 1) * sides + 1 + i;
tris[n * (sides) * 6 + i * 6 + 3] = (n * sides) + i;
tris[n * (sides) * 6 + i * 6 + 4] = (n + 1) * sides + 1 + i;
tris[n * (sides) * 6 + i * 6 + 5] = (n * sides) + i + 1;
} else {
tris[n * (sides) * 6 + i * 6] = (n + 1) * sides - 1;
tris[n * (sides) * 6 + i * 6 + 1] = sides * (n + 1) + i;
tris[n * (sides) * 6 + i * 6 + 2] = sides * (n + 1);
tris[n * (sides) * 6 + i * 6 + 3] = (n + 1) * sides - 1;
tris[n * (sides) * 6 + i * 6 + 4] = sides * (n + 1);
tris[n * (sides) * 6 + i * 6 + 5] = n * sides;
}
}
}
return tris;
}
public struct Path {
public int length; // Length (in circles) of the tunnel
public float[] radius; // The radius of each circle
public Vector3[] centerPoints; // The center point of each circle
public Vector3[] centerPointNormals; // The normal of each circle
public Vector3[] faceRotation;
public Path (int len, float startRadius, float maxRadius, float partLength, bool drawDebugMesh) {
length = len;
radius = new float[length];
centerPoints = new Vector3[length];
centerPointNormals = new Vector3[length];
faceRotation = new Vector3[length];
radius[0] = startRadius;
centerPoints[0] = Vector3.zero;
faceRotation[0] = Vector3.zero;
for (int n = 1; n < length; n++) {
radius[n] = startRadius;
//radius[n] = radius[n - 1] + Random.Range (-0.5f, 0.5f);
faceRotation[n] = new Vector3 (faceRotation[n - 1].x + Random.Range (-0.2f, 0.2f), faceRotation[n - 1].y + Random.Range (-0.2f, 0.2f), 0);
centerPoints[n].x = partLength * Mathf.Sin (faceRotation[n].y) * Mathf.Cos (faceRotation[n].x) + centerPoints[n - 1].x;
centerPoints[n].y = partLength * Mathf.Cos (faceRotation[n].y) * Mathf.Sin (faceRotation[n].x) + centerPoints[n - 1].y;
centerPoints[n].z = partLength * Mathf.Cos (faceRotation[n].x) * Mathf.Cos (faceRotation[n].y) + centerPoints[n - 1].z;
if (drawDebugMesh) {
Debug.DrawLine (centerPoints[n - 1], centerPoints[n], Color.yellow, 600);
}
}
for (int n = 0; n < length - 1; n++) {
centerPointNormals[n] = centerPoints[n] - centerPoints[n + 1];
}
}
}
public struct Face {
public Vector3[] vertices;
public Face (float r, int sides, Vector3 centerPoint, Vector3 centerPointNormal, Vector3 rotation, bool drawDebugMesh) {
vertices = new Vector3[sides];
float angle = 2 * Mathf.PI / sides;
Vector3 normalized = centerPointNormal;
Vector3 ortho1 = Vector3.up;
Vector3 ortho2 = Vector3.right;
Vector3.OrthoNormalize(ref normalized, ref ortho1, ref ortho2);
for (int n = 0; n < sides; n++) {
//vertices[n].x = centerPoint.x + r * Mathf.Sin(n * angle);
//vertices[n].y = centerPoint.y + r * Mathf.Cos(n * angle);
//vertices[n].z = centerPoint.z;
vertices[n] = centerPoint + r * Mathf.Sin(n * angle) * ortho1 + r * Mathf.Cos(n * angle) * ortho2;
//vertices[n] = vertices[n] - Vector3.Dot (vertices[n] - centerPoint, normalized) * normalized;
if (n != 0 && drawDebugMesh) {
Debug.DrawLine (vertices[n], vertices[n - 1], Color.red, 600);
}
if (n == sides - 1 && drawDebugMesh) {
Debug.DrawLine (vertices[n], vertices[0], Color.red, 600);
}
}
}
}
}
using UnityEngine;
using System.Collections;
public class LevelController : MonoBehaviour {
public bool drawDebugMesh;
public Level currentLevel;
public int length;
public float startRadius;
public float maxRadius;
public float partLength;
public int sides;
[HideInInspector] public GameObject gameObj;
[HideInInspector] new public Transform transform;
void Start () {
gameObj = gameObject;
transform = gameObj.GetComponent<Transform> ();
if (length * sides >= 65000) {
length = (int)Mathf.Floor (65000 / sides);
}
currentLevel = new Level (length, startRadius, maxRadius, partLength, sides, drawDebugMesh);
transform.GetComponent<MeshFilter> ().mesh = currentLevel.mesh;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment