SafetyAreaVertexHelper.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class SafetyAreaVertexHelper
  5. {
  6. private static List<int> effectIndicesList = new List<int>();
  7. /// <summary>
  8. /// When raycast hit the plane mesh, caculate the brush effected vertex index
  9. /// </summary>
  10. /// <param name="localHitPoint"></param>
  11. public static List<int> CaculateEffectVerticeIndices(Vector3 localHitPoint)
  12. {
  13. effectIndicesList.Clear();
  14. if (localHitPoint.x == 0f && localHitPoint.z == 0f)
  15. {
  16. return effectIndicesList;
  17. }
  18. float x = localHitPoint.x + PlayAreaConstant.GRID_SIZE * PlayAreaConstant.CELL_SIZE / 2f;
  19. float z = localHitPoint.z + PlayAreaConstant.GRID_SIZE * PlayAreaConstant.CELL_SIZE / 2f;
  20. float rangeDown = Mathf.Clamp(z - PlayAreaConstant.BRUSH_SIZE, 0, PlayAreaConstant.GRID_SIZE * PlayAreaConstant.CELL_SIZE);
  21. float rangeUp = Mathf.Clamp(z + PlayAreaConstant.BRUSH_SIZE, 0, PlayAreaConstant.GRID_SIZE * PlayAreaConstant.CELL_SIZE);
  22. float columnDistance = PlayAreaConstant.CELL_SIZE;
  23. int effectColumnStart = Mathf.CeilToInt(rangeDown / columnDistance);
  24. int effectColumnStop = Mathf.FloorToInt(rangeUp / columnDistance);
  25. for (int i = effectColumnStart; i <= effectColumnStop; i++)
  26. {
  27. float zDistance = Mathf.Abs(z - i * columnDistance);
  28. float rowRangeSize = Mathf.Sqrt(Mathf.Pow(PlayAreaConstant.BRUSH_SIZE, 2) - Mathf.Pow(zDistance, 2) + Mathf.Epsilon);
  29. float rangeLeft = Mathf.Clamp(x - rowRangeSize, 0, PlayAreaConstant.GRID_SIZE * PlayAreaConstant.CELL_SIZE);
  30. float rangeRight = Mathf.Clamp(x + rowRangeSize, 0, PlayAreaConstant.GRID_SIZE * PlayAreaConstant.CELL_SIZE);
  31. float rowDistance = PlayAreaConstant.CELL_SIZE;
  32. int effectRowStart = Mathf.CeilToInt(rangeLeft / rowDistance);
  33. int effectRowStop = Mathf.FloorToInt(rangeRight / rowDistance) - 1;
  34. for (int j = effectRowStart; j <= effectRowStop; j++)
  35. {
  36. int index = i * (PlayAreaConstant.GRID_SIZE + 1) + j + 1;
  37. if (index <= ((PlayAreaConstant.GRID_SIZE + 1) * (PlayAreaConstant.GRID_SIZE + 1) - 1))
  38. {
  39. effectIndicesList.Add(index);
  40. }
  41. }
  42. }
  43. return effectIndicesList;
  44. }
  45. private static Vector2 _cellSize = new Vector2(PlayAreaConstant.CELL_SIZE, PlayAreaConstant.CELL_SIZE);
  46. private static Vector2Int _gridSize = new Vector2Int(PlayAreaConstant.GRID_SIZE, PlayAreaConstant.GRID_SIZE);
  47. public static Mesh GeneratePlaneMesh()
  48. {
  49. Mesh planeMesh = new Mesh();
  50. //计算Plane大小
  51. Vector2 size;
  52. size.x = _cellSize.x * _gridSize.x;
  53. size.y = _cellSize.y * _gridSize.y;
  54. //计算Plane一半大小
  55. Vector2 halfSize = size / 2;
  56. //计算顶点及UV
  57. List<Vector3> vertices = new List<Vector3>();
  58. List<Vector2> uvs = new List<Vector2>();
  59. Vector3 vertice = Vector3.zero;
  60. Vector2 uv = Vector3.zero;
  61. for (int y = 0; y < _gridSize.y + 1; y++)
  62. {
  63. vertice.z = y * _cellSize.y - halfSize.y;//计算顶点Y轴
  64. uv.y = y * _cellSize.y / size.y;//计算顶点纹理坐标V
  65. for (int x = 0; x < _gridSize.x + 1; x++)
  66. {
  67. vertice.x = x * _cellSize.x - halfSize.x;//计算顶点X轴
  68. uv.x = x * _cellSize.x / size.x;//计算顶点纹理坐标U
  69. vertices.Add(vertice);//添加到顶点数组
  70. uvs.Add(uv);//添加到纹理坐标数组
  71. }
  72. }
  73. //顶点序列
  74. int a = 0;
  75. int b = 0;
  76. int c = 0;
  77. int d = 0;
  78. int startIndex = 0;
  79. int[] indexs = new int[_gridSize.x * _gridSize.y * 2 * 3];//顶点序列
  80. for (int y = 0; y < _gridSize.y; y++)
  81. {
  82. for (int x = 0; x < _gridSize.x; x++)
  83. {
  84. //四边形四个顶点
  85. a = y * (_gridSize.x + 1) + x;//0
  86. b = (y + 1) * (_gridSize.x + 1) + x;//1
  87. c = b + 1;//2
  88. d = a + 1;//3
  89. //计算在数组中的起点序号
  90. startIndex = y * _gridSize.x * 2 * 3 + x * 2 * 3;
  91. //左上三角形
  92. indexs[startIndex] = a;//0
  93. indexs[startIndex + 1] = b;//1
  94. indexs[startIndex + 2] = c;//2
  95. //右下三角形
  96. indexs[startIndex + 3] = c;//2
  97. indexs[startIndex + 4] = d;//3
  98. indexs[startIndex + 5] = a;//0
  99. }
  100. }
  101. planeMesh.SetVertices(vertices);//设置顶点
  102. planeMesh.SetUVs(0, uvs);//设置UV
  103. planeMesh.SetIndices(indexs, MeshTopology.Triangles, 0);//设置顶点序列
  104. planeMesh.RecalculateNormals();
  105. planeMesh.RecalculateBounds();
  106. planeMesh.RecalculateTangents();
  107. return planeMesh;
  108. }
  109. public static Mesh GenerateEdgeMesh(Mesh planeMesh, List<int> vertexIndexList, float topY, float bottomY)
  110. {
  111. List<Vector3> geometry = new List<Vector3>();
  112. for (int i = 0; i < vertexIndexList.Count; i++)
  113. {
  114. geometry.Add(planeMesh.vertices[vertexIndexList[i]]);
  115. }
  116. int numPoints = geometry.Count;
  117. Vector3[] vertices = new Vector3[numPoints * 2];
  118. Vector2[] uvs = new Vector2[numPoints * 2];
  119. for (int i = 0; i < numPoints; ++i)
  120. {
  121. Vector3 v = geometry[i];
  122. vertices[i] = new Vector3(v.x, bottomY, v.z);
  123. vertices[i + numPoints] = new Vector3(v.x, topY, v.z);
  124. uvs[i] = new Vector2((float)i / (numPoints - 1), 0.0f);
  125. uvs[i + numPoints] = new Vector2(uvs[i].x, 1.0f);
  126. }
  127. int[] triangles = new int[(numPoints - 1) * 2 * 3];
  128. for (int i = 0; i < numPoints - 1; ++i)
  129. {
  130. // the geometry is built clockwised. only the back faces should be rendered in the camera frame mask
  131. triangles[i * 6 + 0] = i;
  132. triangles[i * 6 + 1] = i + numPoints;
  133. triangles[i * 6 + 2] = i + 1 + numPoints;
  134. triangles[i * 6 + 3] = i;
  135. triangles[i * 6 + 4] = i + 1 + numPoints;
  136. triangles[i * 6 + 5] = i + 1;
  137. }
  138. Mesh edgeMesh = new Mesh();
  139. edgeMesh.vertices = vertices;
  140. edgeMesh.uv = uvs;
  141. edgeMesh.triangles = triangles;
  142. return edgeMesh;
  143. }
  144. public static Mesh GenerateCylinderMesh(Vector3 circleCenter, float topY, float bottomY)
  145. {
  146. List<Vector3> geometry = new List<Vector3>();
  147. float angleSpace = 2 * Mathf.PI / PlayAreaConstant.CYLINDER_SPLIT_COUNT;
  148. for (int i = 0; i <= PlayAreaConstant.CYLINDER_SPLIT_COUNT; i++)
  149. {
  150. float angle = i * angleSpace;
  151. float x = PlayAreaConstant.STATIONARY_AREA_RADIUS * Mathf.Cos(angle);
  152. float z = PlayAreaConstant.STATIONARY_AREA_RADIUS * Mathf.Sin(angle);
  153. geometry.Add(new Vector3(circleCenter.x + x, circleCenter.y, circleCenter.z + z));
  154. }
  155. int numPoints = geometry.Count;
  156. Vector3[] vertices = new Vector3[numPoints * 2];
  157. Vector2[] uvs = new Vector2[numPoints * 2];
  158. for (int i = 0; i < numPoints; ++i)
  159. {
  160. Vector3 v = geometry[i];
  161. vertices[i] = new Vector3(v.x, bottomY, v.z);
  162. vertices[i + numPoints] = new Vector3(v.x, topY, v.z);
  163. uvs[i] = new Vector2((float)i / (numPoints - 1), 0.0f);
  164. uvs[i + numPoints] = new Vector2(uvs[i].x, 1.0f);
  165. }
  166. int[] triangles = new int[(numPoints - 1) * 2 * 3];
  167. for (int i = 0; i < numPoints - 1; ++i)
  168. {
  169. // the geometry is built clockwised. only the back faces should be rendered in the camera frame mask
  170. triangles[i * 6 + 0] = i;
  171. triangles[i * 6 + 1] = i + numPoints;
  172. triangles[i * 6 + 2] = i + 1 + numPoints;
  173. triangles[i * 6 + 3] = i;
  174. triangles[i * 6 + 4] = i + 1 + numPoints;
  175. triangles[i * 6 + 5] = i + 1;
  176. }
  177. Mesh cylinderMesh = new Mesh();
  178. cylinderMesh.vertices = vertices;
  179. cylinderMesh.uv = uvs;
  180. cylinderMesh.triangles = triangles;
  181. return cylinderMesh;
  182. }
  183. }