1
0

MeshGenerator.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. using System;
  2. using System.Collections;
  3. using UnityEditor.PackageManager;
  4. using UnityEngine;
  5. using UnityEngine.UIElements;
  6. using static UnityEditor.PlayerSettings;
  7. public static class MeshGenerator
  8. {
  9. public static MeshData GenerateTerrainMesh(float[,] heightMap, float heightMultiplier, AnimationCurve _heightCurve, int levelOfDetail, bool useFlatShading)
  10. {
  11. AnimationCurve heightCurve = new AnimationCurve(_heightCurve.keys);
  12. int meshSimplificationIncrement = (levelOfDetail == 0) ? 1 : levelOfDetail * 2;
  13. int borderedSize = heightMap.GetLength(0);
  14. int meshSize = borderedSize - 2 * meshSimplificationIncrement;
  15. int meshSizeUnsimplified = borderedSize - 2;
  16. float topLeftX = (meshSizeUnsimplified - 1) / -2f;
  17. float topLeftZ = (meshSizeUnsimplified - 1) / 2f;
  18. int verticesPerLine = (meshSize - 1) / meshSimplificationIncrement + 1;
  19. MeshData meshData = new MeshData(verticesPerLine, useFlatShading);
  20. int[,] vertexIndicesMap = new int[borderedSize, borderedSize];
  21. int meshVertexIndex = 0;
  22. int borderVertexIndex = -1;
  23. for (int y = 0; y < borderedSize; y += meshSimplificationIncrement)
  24. {
  25. for (int x = 0; x < borderedSize; x += meshSimplificationIncrement)
  26. {
  27. bool isBorderVertex = y == 0 || y == borderedSize - 1 || x == 0 || x == borderedSize - 1;
  28. if (isBorderVertex)
  29. {
  30. vertexIndicesMap[x, y] = borderVertexIndex;
  31. borderVertexIndex--;
  32. }
  33. else
  34. {
  35. vertexIndicesMap[x, y] = meshVertexIndex;
  36. meshVertexIndex++;
  37. }
  38. }
  39. }
  40. for (int y = 0; y < borderedSize; y += meshSimplificationIncrement)
  41. {
  42. for (int x = 0; x < borderedSize; x += meshSimplificationIncrement)
  43. {
  44. int vertexIndex = vertexIndicesMap[x, y];
  45. Vector2 percent = new Vector2((x - meshSimplificationIncrement) / (float)meshSize, (y - meshSimplificationIncrement) / (float)meshSize);
  46. float height = heightCurve.Evaluate(heightMap[x, y]) * heightMultiplier;
  47. Vector3 vertexPosition = new Vector3(topLeftX + percent.x * meshSizeUnsimplified, height, topLeftZ - percent.y * meshSizeUnsimplified);
  48. /*
  49. try
  50. {
  51. ForestData.spawnable.Enqueue(vertexPosition);
  52. }
  53. catch (Exception e)
  54. {
  55. Debug.Log(e);
  56. }*/
  57. meshData.AddVertex(vertexPosition, percent, vertexIndex);
  58. if (x < borderedSize - 1 && y < borderedSize - 1)
  59. {
  60. int a = vertexIndicesMap[x, y];
  61. int b = vertexIndicesMap[x + meshSimplificationIncrement, y];
  62. int c = vertexIndicesMap[x, y + meshSimplificationIncrement];
  63. int d = vertexIndicesMap[x + meshSimplificationIncrement, y + meshSimplificationIncrement];
  64. meshData.AddTriangle(a, d, c);
  65. meshData.AddTriangle(d, a, b);
  66. }
  67. vertexIndex++;
  68. }
  69. }
  70. meshData.Finish();
  71. return meshData;
  72. }
  73. }
  74. public class MeshData
  75. {
  76. Vector3[] vertices;
  77. int[] triangles;
  78. Vector2[] uvs;
  79. Vector3[] bakedNormals;
  80. Vector3[] borderVertices;
  81. int[] borderTriangles;
  82. int triangleIndex;
  83. int borderTriangleIndex;
  84. bool useFlatShading;
  85. public MeshData(int verticesPerLine, bool useFlatShading)
  86. {
  87. this.useFlatShading = useFlatShading;
  88. vertices = new Vector3[verticesPerLine * verticesPerLine];
  89. uvs = new Vector2[verticesPerLine * verticesPerLine];
  90. triangles = new int[(verticesPerLine - 1) * (verticesPerLine - 1) * 6];
  91. borderVertices = new Vector3[verticesPerLine * 4 + 4];
  92. borderTriangles = new int[24 * verticesPerLine];
  93. }
  94. public void AddVertex(Vector3 vertexPosition, Vector2 uv, int vertexIndex)
  95. {
  96. if (vertexIndex < 0)
  97. {
  98. borderVertices[-vertexIndex - 1] = vertexPosition;
  99. }
  100. else
  101. {
  102. vertices[vertexIndex] = vertexPosition;
  103. uvs[vertexIndex] = uv;
  104. }
  105. }
  106. public void AddTriangle(int a, int b, int c)
  107. {
  108. if (a < 0 || b < 0 || c < 0)
  109. {
  110. borderTriangles[borderTriangleIndex] = a;
  111. borderTriangles[borderTriangleIndex + 1] = b;
  112. borderTriangles[borderTriangleIndex + 2] = c;
  113. borderTriangleIndex += 3;
  114. }
  115. else
  116. {
  117. triangles[triangleIndex] = a;
  118. triangles[triangleIndex + 1] = b;
  119. triangles[triangleIndex + 2] = c;
  120. triangleIndex += 3;
  121. }
  122. }
  123. Vector3[] CalculateNormals()
  124. {
  125. Vector3[] vertexNormals = new Vector3[vertices.Length];
  126. int triangleCount = triangles.Length / 3;
  127. for (int i = 0; i < triangleCount; i++)
  128. {
  129. int normalTriangleIndex = i * 3;
  130. int vertexIndexA = triangles[normalTriangleIndex];
  131. int vertexIndexB = triangles[normalTriangleIndex + 1];
  132. int vertexIndexC = triangles[normalTriangleIndex + 2];
  133. Vector3 triangleNormal = SurfaceNormalFromIndices(vertexIndexA, vertexIndexB, vertexIndexC);
  134. vertexNormals[vertexIndexA] += triangleNormal;
  135. vertexNormals[vertexIndexB] += triangleNormal;
  136. vertexNormals[vertexIndexC] += triangleNormal;
  137. }
  138. int borderTriangleCount = borderTriangles.Length / 3;
  139. for (int i = 0; i < borderTriangleCount; i++)
  140. {
  141. int normalTriangleIndex = i * 3;
  142. int vertexIndexA = borderTriangles[normalTriangleIndex];
  143. int vertexIndexB = borderTriangles[normalTriangleIndex + 1];
  144. int vertexIndexC = borderTriangles[normalTriangleIndex + 2];
  145. Vector3 triangleNormal = SurfaceNormalFromIndices(vertexIndexA, vertexIndexB, vertexIndexC);
  146. if (vertexIndexA >= 0)
  147. {
  148. vertexNormals[vertexIndexA] += triangleNormal;
  149. }
  150. if (vertexIndexB >= 0)
  151. {
  152. vertexNormals[vertexIndexB] += triangleNormal;
  153. }
  154. if (vertexIndexC >= 0)
  155. {
  156. vertexNormals[vertexIndexC] += triangleNormal;
  157. }
  158. }
  159. for (int i = 0; i < vertexNormals.Length; i++)
  160. {
  161. vertexNormals[i].Normalize();
  162. }
  163. return vertexNormals;
  164. }
  165. Vector3 SurfaceNormalFromIndices(int indexA, int indexB, int indexC)
  166. {
  167. Vector3 pointA = (indexA < 0) ? borderVertices[-indexA - 1] : vertices[indexA];
  168. Vector3 pointB = (indexB < 0) ? borderVertices[-indexB - 1] : vertices[indexB];
  169. Vector3 pointC = (indexC < 0) ? borderVertices[-indexC - 1] : vertices[indexC];
  170. Vector3 sideAB = pointB - pointA;
  171. Vector3 sideAC = pointC - pointA;
  172. return Vector3.Cross(sideAB, sideAC).normalized;
  173. }
  174. public void Finish()
  175. {
  176. if (useFlatShading)
  177. {
  178. FlatShading();
  179. }
  180. else
  181. {
  182. BakeNormals();
  183. }
  184. }
  185. void BakeNormals()
  186. {
  187. bakedNormals = CalculateNormals();
  188. }
  189. void FlatShading()
  190. {
  191. Vector3[] flatShadedVertices = new Vector3[triangles.Length];
  192. Vector2[] flatShadedUvs = new Vector2[triangles.Length];
  193. for (int i = 0; i < triangles.Length; i++)
  194. {
  195. flatShadedVertices[i] = vertices[triangles[i]];
  196. flatShadedUvs[i] = uvs[triangles[i]];
  197. triangles[i] = i;
  198. }
  199. vertices = flatShadedVertices;
  200. uvs = flatShadedUvs;
  201. }
  202. public Mesh CreateMesh()
  203. {
  204. Mesh mesh = new Mesh();
  205. mesh.vertices = vertices;
  206. mesh.triangles = triangles;
  207. mesh.uv = uvs;
  208. if (useFlatShading)
  209. {
  210. mesh.RecalculateNormals();
  211. }
  212. else
  213. {
  214. mesh.normals = bakedNormals;
  215. }
  216. return mesh;
  217. }
  218. }