Skip to content

Instantly share code, notes, and snippets.

@soraphis
Last active January 31, 2017 04:03
Show Gist options
  • Save soraphis/eca47b2fcce35fb891a2e79ceb25bcc7 to your computer and use it in GitHub Desktop.
Save soraphis/eca47b2fcce35fb891a2e79ceb25bcc7 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using UnityEngine;
public class MeshGenerator : MonoBehaviour {
public SquareGrid squareGrid;
List<Vector3> vertices;
List<int> triangles;
public void GenerateMesh(int[,] map, float squareSize) {
squareGrid = new SquareGrid(map, squareSize);
vertices = new List<Vector3>();
triangles = new List<int>();
for (int x = 0; x < squareGrid.squares.GetLength(0); x ++) {
for (int y = 0; y < squareGrid.squares.GetLength(1); y ++) {
TriangulateSquare(squareGrid.squares[x,y]);
}
}
Mesh mesh = new Mesh();
GetComponent<MeshFilter>().mesh = mesh;
mesh.vertices = vertices.ToArray();
mesh.triangles = triangles.ToArray();
mesh.RecalculateNormals();
}
void TriangulateSquare(Square square) {
if (square.configuration == 0) return;
List<Node> nodelist = new List<Node>(6);
for (int i = 0; i < 4; ++i) {
var i_prev = (3 + i)%4; // i->i_prev => 4->3, 3->2, 2->1, 1->4
if (!square.CNodes[i].active) continue;
if (nodelist.Count > 0) {
if (nodelist[nodelist.Count - 1] == square.Nodes[i_prev])
nodelist.RemoveAt(nodelist.Count - 1);
else
nodelist.Add(square.Nodes[i_prev]);
} else
nodelist.Add(square.Nodes[i_prev]);
nodelist.Add(square.CNodes[i]);
nodelist.Add(square.Nodes[i]);
}
if (nodelist[nodelist.Count - 1] == nodelist[0]) {
nodelist.RemoveAt(nodelist.Count - 1);
nodelist.RemoveAt(0);
}
MeshFromPoints(nodelist.ToArray());
}
void MeshFromPoints(params Node[] points) {
AssignVertices(points);
if (points.Length < 3) throw new ArgumentException("cant generate triangle from less than 3 points");
if (points.Length > 6) Debug.LogError("(points.Length > 6) this is not supposed to happen, but this method could handle it (points.Length = " + points.Length +")");
for (int i = 0; i < points.Length - 2; ++i) {
CreateTriangle(points[0], points[i+1], points[i+2]);
}
}
void AssignVertices(Node[] points) {
for (int i = 0; i < points.Length; i ++) {
if (points[i].vertexIndex == -1) {
points[i].vertexIndex = vertices.Count;
vertices.Add(points[i].position);
}
}
}
void CreateTriangle(Node a, Node b, Node c) {
triangles.Add(a.vertexIndex);
triangles.Add(b.vertexIndex);
triangles.Add(c.vertexIndex);
}
void OnDrawGizmos() {
/*
if (squareGrid != null) {
for (int x = 0; x < squareGrid.squares.GetLength(0); x ++) {
for (int y = 0; y < squareGrid.squares.GetLength(1); y ++) {
Gizmos.color = (squareGrid.squares[x,y].topLeft.active)?Color.black:Color.white;
Gizmos.DrawCube(squareGrid.squares[x,y].topLeft.position, Vector3.one * .4f);
Gizmos.color = (squareGrid.squares[x,y].topRight.active)?Color.black:Color.white;
Gizmos.DrawCube(squareGrid.squares[x,y].topRight.position, Vector3.one * .4f);
Gizmos.color = (squareGrid.squares[x,y].bottomRight.active)?Color.black:Color.white;
Gizmos.DrawCube(squareGrid.squares[x,y].bottomRight.position, Vector3.one * .4f);
Gizmos.color = (squareGrid.squares[x,y].bottomLeft.active)?Color.black:Color.white;
Gizmos.DrawCube(squareGrid.squares[x,y].bottomLeft.position, Vector3.one * .4f);
Gizmos.color = Color.grey;
Gizmos.DrawCube(squareGrid.squares[x,y].centreTop.position, Vector3.one * .15f);
Gizmos.DrawCube(squareGrid.squares[x,y].centreRight.position, Vector3.one * .15f);
Gizmos.DrawCube(squareGrid.squares[x,y].centreBottom.position, Vector3.one * .15f);
Gizmos.DrawCube(squareGrid.squares[x,y].centreLeft.position, Vector3.one * .15f);
}
}
}
*/
}
public class SquareGrid {
public Square[,] squares;
public SquareGrid(int[,] map, float squareSize) {
int nodeCountX = map.GetLength(0);
int nodeCountY = map.GetLength(1);
float mapWidth = nodeCountX*squareSize;
float mapHeight = nodeCountY*squareSize;
ControlNode[,] controlNodes = new ControlNode[nodeCountX, nodeCountY];
for (int x = 0; x < nodeCountX; x ++) {
for (int y = 0; y < nodeCountY; y ++) {
Vector3 pos = new Vector3(-mapWidth/2 + x*squareSize + squareSize/2, 0,
-mapHeight/2 + y*squareSize + squareSize/2);
controlNodes[x, y] = new ControlNode(pos, map[x, y] == 1, squareSize);
}
}
squares = new Square[nodeCountX - 1, nodeCountY - 1];
for (int x = 0; x < nodeCountX - 1; x ++) {
for (int y = 0; y < nodeCountY - 1; y ++) {
squares[x, y] = new Square(controlNodes[x, y + 1], controlNodes[x + 1, y + 1],
controlNodes[x + 1, y], controlNodes[x, y]);
}
}
}
}
public class Square {
public ControlNode[] CNodes; // order: topLeft, topRight, bottomRight, bottomLeft;
public Node[] Nodes; // order: centreTop, centreRight, centreBottom, centreLeft;
public int configuration;
public Square(params ControlNode[] cnodes) {
if (cnodes.Length != 4)
throw new ArgumentException("expected the 4 controll nodes: topLeft, topRight, bottomRight, bottomLeft");
CNodes = cnodes;
Nodes = new Node[4];
Nodes[0] = CNodes[0].right;
Nodes[1] = CNodes[2].above;
Nodes[2] = CNodes[3].right;
Nodes[3] = CNodes[3].above;
foreach (var node in CNodes) {
configuration = configuration << 1;
if (node.active) configuration++;
}
}
}
public class Node {
public Vector3 position;
public int vertexIndex = -1;
public Node(Vector3 _pos) { position = _pos; }
}
public class ControlNode : Node {
public bool active;
public Node above, right;
public ControlNode(Vector3 _pos, bool _active, float squareSize) : base(_pos) {
active = _active;
above = new Node(position + Vector3.forward*squareSize/2f);
right = new Node(position + Vector3.right*squareSize/2f);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment