SafetyAreaVertexHelper.cs 9.2 KB

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