-
-
Save soraphis/eca47b2fcce35fb891a2e79ceb25bcc7 to your computer and use it in GitHub Desktop.
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 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