MeshGenerator.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. public class MeshGenerator : MonoBehaviour
  5. {
  6. public SquareGrid squareGrid;
  7. List<Vector3> vertices;
  8. List<int> triangles;
  9. public void GenerateMesh(int[,] map, float squareSize)
  10. {
  11. squareGrid = new SquareGrid(map, squareSize);
  12. vertices = new List<Vector3>();
  13. triangles = new List<int>();
  14. for (int x = 0; x < squareGrid.squares.GetLength(0); x++)
  15. {
  16. for (int y = 0; y < squareGrid.squares.GetLength(1); y++)
  17. {
  18. TriangulateSquare(squareGrid.squares[x, y]);
  19. }
  20. }
  21. Mesh mesh = new Mesh();
  22. GetComponent<MeshFilter>().mesh = mesh;
  23. mesh.vertices = vertices.ToArray();
  24. mesh.triangles = triangles.ToArray();
  25. mesh.RecalculateNormals();
  26. }
  27. void TriangulateSquare(Square square)
  28. {
  29. switch (square.configuration)
  30. {
  31. case 0:
  32. break;
  33. // 1 points:
  34. case 1:
  35. MeshFromPoints(square.centreBottom, square.bottomLeft, square.centreLeft);
  36. break;
  37. case 2:
  38. MeshFromPoints(square.centreRight, square.bottomRight, square.centreBottom);
  39. break;
  40. case 4:
  41. MeshFromPoints(square.centreTop, square.topRight, square.centreRight);
  42. break;
  43. case 8:
  44. MeshFromPoints(square.topLeft, square.centreTop, square.centreLeft);
  45. break;
  46. // 2 points:
  47. case 3:
  48. MeshFromPoints(square.centreRight, square.bottomRight, square.bottomLeft, square.centreLeft);
  49. break;
  50. case 6:
  51. MeshFromPoints(square.centreTop, square.topRight, square.bottomRight, square.centreBottom);
  52. break;
  53. case 9:
  54. MeshFromPoints(square.topLeft, square.centreTop, square.centreBottom, square.bottomLeft);
  55. break;
  56. case 12:
  57. MeshFromPoints(square.topLeft, square.topRight, square.centreRight, square.centreLeft);
  58. break;
  59. case 5:
  60. MeshFromPoints(square.centreTop, square.topRight, square.centreRight, square.centreBottom, square.bottomLeft, square.centreLeft);
  61. break;
  62. case 10:
  63. MeshFromPoints(square.topLeft, square.centreTop, square.centreRight, square.bottomRight, square.centreBottom, square.centreLeft);
  64. break;
  65. // 3 point:
  66. case 7:
  67. MeshFromPoints(square.centreTop, square.topRight, square.bottomRight, square.bottomLeft, square.centreLeft);
  68. break;
  69. case 11:
  70. MeshFromPoints(square.topLeft, square.centreTop, square.centreRight, square.bottomRight, square.bottomLeft);
  71. break;
  72. case 13:
  73. MeshFromPoints(square.topLeft, square.topRight, square.centreRight, square.centreBottom, square.bottomLeft);
  74. break;
  75. case 14:
  76. MeshFromPoints(square.topLeft, square.topRight, square.bottomRight, square.centreBottom, square.centreLeft);
  77. break;
  78. // 4 point:
  79. case 15:
  80. MeshFromPoints(square.topLeft, square.topRight, square.bottomRight, square.bottomLeft);
  81. break;
  82. }
  83. }
  84. void MeshFromPoints(params Node[] points)
  85. {
  86. AssignVertices(points);
  87. if (points.Length >= 3)
  88. CreateTriangle(points[0], points[1], points[2]);
  89. if (points.Length >= 4)
  90. CreateTriangle(points[0], points[2], points[3]);
  91. if (points.Length >= 5)
  92. CreateTriangle(points[0], points[3], points[4]);
  93. if (points.Length >= 6)
  94. CreateTriangle(points[0], points[4], points[5]);
  95. }
  96. void AssignVertices(Node[] points)
  97. {
  98. for (int i = 0; i < points.Length; i++)
  99. {
  100. if (points[i].vertexIndex == -1)
  101. {
  102. points[i].vertexIndex = vertices.Count;
  103. vertices.Add(points[i].position);
  104. }
  105. }
  106. }
  107. void CreateTriangle(Node a, Node b, Node c)
  108. {
  109. triangles.Add(a.vertexIndex);
  110. triangles.Add(b.vertexIndex);
  111. triangles.Add(c.vertexIndex);
  112. }
  113. public class SquareGrid
  114. {
  115. public Square[,] squares;
  116. public SquareGrid(int[,] map, float squareSize)
  117. {
  118. int nodeCountX = map.GetLength(0);
  119. int nodeCountY = map.GetLength(1);
  120. float mapWidth = nodeCountX * squareSize;
  121. float mapHeight = nodeCountY * squareSize;
  122. ControlNode[,] controlNodes = new ControlNode[nodeCountX, nodeCountY];
  123. for (int x = 0; x < nodeCountX; x++)
  124. {
  125. for (int y = 0; y < nodeCountY; y++)
  126. {
  127. Vector3 pos = new Vector3(-mapWidth / 2 + x * squareSize + squareSize / 2, 0, -mapHeight / 2 + y * squareSize + squareSize / 2);
  128. controlNodes[x, y] = new ControlNode(pos, map[x, y] == 1, squareSize);
  129. }
  130. }
  131. squares = new Square[nodeCountX - 1, nodeCountY - 1];
  132. for (int x = 0; x < nodeCountX - 1; x++)
  133. {
  134. for (int y = 0; y < nodeCountY - 1; y++)
  135. {
  136. squares[x, y] = new Square(controlNodes[x, y + 1], controlNodes[x + 1, y + 1], controlNodes[x + 1, y], controlNodes[x, y]);
  137. }
  138. }
  139. }
  140. }
  141. public class Square
  142. {
  143. public ControlNode topLeft, topRight, bottomRight, bottomLeft;
  144. public Node centreTop, centreRight, centreBottom, centreLeft;
  145. public int configuration;
  146. public Square(ControlNode _topLeft, ControlNode _topRight, ControlNode _bottomRight, ControlNode _bottomLeft)
  147. {
  148. topLeft = _topLeft;
  149. topRight = _topRight;
  150. bottomRight = _bottomRight;
  151. bottomLeft = _bottomLeft;
  152. centreTop = topLeft.right;
  153. centreRight = bottomRight.above;
  154. centreBottom = bottomLeft.right;
  155. centreLeft = bottomLeft.above;
  156. if (topLeft.active)
  157. configuration += 8;
  158. if (topRight.active)
  159. configuration += 4;
  160. if (bottomRight.active)
  161. configuration += 2;
  162. if (bottomLeft.active)
  163. configuration += 1;
  164. }
  165. }
  166. public class Node
  167. {
  168. public Vector3 position;
  169. public int vertexIndex = -1;
  170. public Node(Vector3 _pos)
  171. {
  172. position = _pos;
  173. }
  174. }
  175. public class ControlNode : Node
  176. {
  177. public bool active;
  178. public Node above, right;
  179. public ControlNode(Vector3 _pos, bool _active, float squareSize) : base(_pos)
  180. {
  181. active = _active;
  182. above = new Node(position + Vector3.forward * squareSize / 2f);
  183. right = new Node(position + Vector3.right * squareSize / 2f);
  184. }
  185. }
  186. }