PlaneGenerator.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. public class PlaneGenerator : MonoBehaviour
  4. {
  5. public Material material;
  6. public float noiseLevel = 0.1f;
  7. private const int pqsResolution = 16;
  8. private const int sphereRadius = 10;
  9. private readonly int[] matrixRotate0 = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; // поворот на 0 градусов
  10. private readonly int[] matrixRotateX = { 1, 0, 0, 0, 0, -1, 0, 1, 0 }; // поворот на 90 градусов вокруг X
  11. private readonly int[] matrixRotateX1 = { 1, 0, 0, 0, 0, 1, 0, -1, 0 }; // поворот на -90 градусов вокруг X
  12. private readonly int[] matrixRotateX2 = { 1, 0, 0, 0, -1, 0, 0, 0, -1 }; // поворот на 180 градусов вокруг X
  13. private readonly int[] matrixRotateY = { 0, 0, 1, 0, 1, 0, -1, 0, 0 }; // поворот на 90 градусов вокруг Y
  14. private readonly int[] matrixRotateY1 = { 0, 0, -1, 0, 1, 0, 1, 0, 0 }; // поворот на -90 градусов вокруг Y
  15. private readonly int[] matrixRotateZ = { 0, -1, 0, 1, 0, 0, 0, 0, 1 }; // поворот на 90 градусов вокруг Z
  16. private readonly int[] matrixRotateZ1 = { 0, 1, 0, -1, 0, 0, 0, 0, 1 }; // поворот на -90 градусов вокруг Z
  17. private List<Quad> quads;
  18. // Start is called once before the first execution of Update after the MonoBehaviour is created
  19. void Start()
  20. {
  21. BuildRootQuads();
  22. UpdateMeshes();
  23. }
  24. // Update is called once per frame
  25. void Update()
  26. {
  27. }
  28. private void BuildRootQuads()
  29. {
  30. quads = new List<Quad>
  31. {
  32. BuildQuad("quadY", matrixRotate0),
  33. BuildQuad("quadY1", matrixRotateX2),
  34. BuildQuad("quadZ", matrixRotateX),
  35. BuildQuad("quadZ1", matrixRotateX1),
  36. BuildQuad("quadX", matrixRotateZ),
  37. BuildQuad("quadX1", matrixRotateZ1)
  38. };
  39. }
  40. private Quad BuildQuad(string name, int[] matrix)
  41. {
  42. var (vertices, uv) = CreateVertices();
  43. RotateWithMatrix(vertices, matrix);
  44. var triangles = CreateTriangles();
  45. return new Quad
  46. {
  47. Name = name,
  48. Vertices = vertices,
  49. Triangles = triangles,
  50. Uv = uv
  51. };
  52. }
  53. private void UpdateMeshes()
  54. {
  55. foreach (var quad in quads)
  56. {
  57. CreateMesh(quad.Name, quad.Vertices, quad.Uv, quad.Triangles);
  58. }
  59. }
  60. private (Vector3[] vertices, Vector2[] uv) CreateVertices()
  61. {
  62. var half = sphereRadius / 2f;
  63. var vertices = new Vector3[(pqsResolution + 1) * (pqsResolution + 1)];
  64. Vector2[] uv = new Vector2[(pqsResolution + 1) * (pqsResolution + 1)];
  65. for (int x = 0, vertex = 0; x < pqsResolution + 1; x++)
  66. {
  67. for (int z = 0; z < pqsResolution + 1; z++, vertex++)
  68. {
  69. vertices[vertex] = new Vector3(half - (float)x / pqsResolution * sphereRadius, half, half - (float)z / pqsResolution * sphereRadius);
  70. uv[vertex] = new Vector2((float)x / pqsResolution, (float)z / pqsResolution);
  71. }
  72. }
  73. return (vertices, uv);
  74. }
  75. private int[] CreateTriangles()
  76. {
  77. var triangles = new int[(pqsResolution) * (pqsResolution) * 6];
  78. int triangle = 0;
  79. for (int x = 1, vertex = 0; x<pqsResolution + 1; x++, vertex++)
  80. {
  81. for (int z = 1; z<pqsResolution + 1; z++, vertex++)
  82. {
  83. triangles[triangle] = vertex;
  84. triangles[triangle + 1] = vertex + pqsResolution + 2;
  85. triangles[triangle + 2] = vertex + pqsResolution + 1;
  86. triangles[triangle + 3] = vertex;
  87. triangles[triangle + 4] = vertex + 1;
  88. triangles[triangle + 5] = vertex + pqsResolution + 2;
  89. triangle += 6;
  90. }
  91. }
  92. return triangles;
  93. }
  94. private void CreateMesh(string name, Vector3[] vertices, Vector2[] uv, int[] triangles)
  95. {
  96. var mesh = new GameObject(name, typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshCollider));
  97. mesh.transform.localScale = new Vector3(1, 1, 1);
  98. var meshFilter = mesh.GetComponent<MeshFilter>();
  99. meshFilter.mesh.vertices = vertices;
  100. meshFilter.mesh.triangles = triangles;
  101. meshFilter.mesh.uv = uv;
  102. mesh.GetComponent<MeshCollider>().sharedMesh = meshFilter.mesh;
  103. meshFilter.mesh.RecalculateBounds();
  104. meshFilter.mesh.RecalculateNormals();
  105. mesh.GetComponent<MeshRenderer>().material = material;
  106. }
  107. private void RotateWithMatrix(Vector3[] vertices, int[] matrix)
  108. {
  109. Vector3 v;
  110. for (int x = 0, vertex = 0; x < pqsResolution + 1; x++)
  111. {
  112. for (int z = 0; z < pqsResolution + 1; z++, vertex++)
  113. {
  114. v = vertices[vertex];
  115. vertices[vertex].x = v.x * matrix[0] + v.y * matrix[1] + v.z * matrix[2];
  116. vertices[vertex].y = v.x * matrix[3] + v.y * matrix[4] + v.z * matrix[5];
  117. vertices[vertex].z = v.x * matrix[6] + v.y * matrix[7] + v.z * matrix[8];
  118. //vertices[vertex] = Vector3.Normalize(vertices[vertex]);
  119. }
  120. }
  121. }
  122. private float GetNoise(float x, float y)
  123. {
  124. return 1 + Mathf.PerlinNoise(x, y) * noiseLevel;
  125. }
  126. private void AddHeights(Vector3[] vertices)
  127. {
  128. for (int x = 0, vertex = 0; x < pqsResolution + 1; x++)
  129. {
  130. for (int z = 0; z < pqsResolution + 1; z++, vertex++)
  131. {
  132. var noise = 1; // GetNoise(vertices[vertex].x, vertices[vertex].y);
  133. vertices[vertex] = noise * sphereRadius * vertices[vertex];
  134. }
  135. }
  136. vertices[pqsResolution + 3] *= 2f;
  137. }
  138. }