LegacyHull.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. // Shatter Toolkit
  2. // Copyright 2015 Gustav Olsson
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. namespace ShatterToolkit
  6. {
  7. public class LegacyHull : IHull
  8. {
  9. protected static float smallestValidLength = 0.01f;
  10. protected static float smallestValidRatio = 0.05f;
  11. protected Object key = new Object();
  12. protected IList<Vector3> vertices;
  13. protected IList<Vector3> normals;
  14. protected IList<Vector4> tangents;
  15. protected IList<Vector2> uvs;
  16. protected IList<Point> vertexToPointMap;
  17. protected IList<Point> points;
  18. protected IList<Edge> edges;
  19. protected IList<Triangle> triangles;
  20. public LegacyHull(Mesh mesh)
  21. {
  22. // Initialize lists
  23. vertices = new List<Vector3>(mesh.vertices);
  24. normals = new List<Vector3>(mesh.normals);
  25. tangents = new List<Vector4>(mesh.tangents);
  26. uvs = new List<Vector2>(mesh.uv);
  27. vertexToPointMap = new List<Point>(vertices.Count);
  28. points = new List<Point>();
  29. edges = new List<Edge>();
  30. triangles = new List<Triangle>();
  31. // Add points
  32. for (int i = 0; i < vertices.Count; i++)
  33. {
  34. Point uniquePoint;
  35. AddUniquePoint(vertices[i], out uniquePoint);
  36. vertexToPointMap.Add(uniquePoint);
  37. }
  38. // Add edges and triangles
  39. int[] indices = mesh.triangles;
  40. for (int i = 0; i < indices.Length / 3; i++)
  41. {
  42. int triangle = i * 3;
  43. AddTriangle(indices[triangle + 0], indices[triangle + 1], indices[triangle + 2]);
  44. }
  45. }
  46. public LegacyHull(LegacyHull reference)
  47. {
  48. int vertexCount = reference.vertices.Count * 2;
  49. vertices = new List<Vector3>(vertexCount);
  50. normals = new List<Vector3>(vertexCount);
  51. tangents = new List<Vector4>(vertexCount);
  52. uvs = new List<Vector2>(vertexCount);
  53. vertexToPointMap = new List<Point>(vertexCount);
  54. points = new List<Point>(reference.points.Count * 2);
  55. edges = new List<Edge>(reference.edges.Count * 2);
  56. triangles = new List<Triangle>(reference.triangles.Count * 2);
  57. }
  58. protected void AddUniquePoint(Vector3 position, out Point uniquePoint)
  59. {
  60. // Is there already a point with this position?
  61. foreach (Point point in points)
  62. {
  63. if (point.position == position)
  64. {
  65. uniquePoint = point;
  66. return;
  67. }
  68. }
  69. // No existing point was found, create a new one
  70. uniquePoint = new Point(position);
  71. points.Add(uniquePoint);
  72. }
  73. protected void AddUniqueEdge(Point point0, Point point1, out Edge uniqueEdge)
  74. {
  75. // Is there already an edge between these points?
  76. foreach (Edge edge in edges)
  77. {
  78. if ((edge.point0 == point0 && edge.point1 == point1) ||
  79. (edge.point0 == point1 && edge.point1 == point0))
  80. {
  81. uniqueEdge = edge;
  82. return;
  83. }
  84. }
  85. // No existing edge was found, create a new one
  86. uniqueEdge = new Edge(point0, point1);
  87. edges.Add(uniqueEdge);
  88. }
  89. protected void AddTriangle(int vertex0, int vertex1, int vertex2)
  90. {
  91. Point point0 = vertexToPointMap[vertex0];
  92. Point point1 = vertexToPointMap[vertex1];
  93. Point point2 = vertexToPointMap[vertex2];
  94. Edge edge0, edge1, edge2;
  95. AddUniqueEdge(point0, point1, out edge0);
  96. AddUniqueEdge(point1, point2, out edge1);
  97. AddUniqueEdge(point2, point0, out edge2);
  98. Triangle triangle = new Triangle(vertex0, vertex1, vertex2, point0, point1, point2, edge0, edge1, edge2);
  99. triangles.Add(triangle);
  100. }
  101. protected void AddVertex(Vector3 vertex, Vector3 normal, Vector4 tangent, Vector2 uv, Point point, out int index)
  102. {
  103. index = vertices.Count;
  104. vertices.Add(vertex);
  105. normals.Add(normal);
  106. tangents.Add(tangent);
  107. uvs.Add(uv);
  108. vertexToPointMap.Add(point);
  109. }
  110. public bool IsEmpty
  111. {
  112. get
  113. {
  114. lock (key)
  115. {
  116. return points.Count < 3 || edges.Count < 3 || triangles.Count < 1;
  117. }
  118. }
  119. }
  120. public void Clear()
  121. {
  122. lock (key)
  123. {
  124. vertices.Clear();
  125. normals.Clear();
  126. tangents.Clear();
  127. uvs.Clear();
  128. vertexToPointMap.Clear();
  129. points.Clear();
  130. edges.Clear();
  131. triangles.Clear();
  132. }
  133. }
  134. public Mesh GetMesh()
  135. {
  136. lock (key)
  137. {
  138. if (!IsEmpty)
  139. {
  140. // Create vertex array
  141. Vector3[] vertices = new Vector3[this.vertices.Count];
  142. Vector3[] normals = new Vector3[this.normals.Count];
  143. Vector4[] tangents = new Vector4[this.tangents.Count];
  144. Vector2[] uvs = new Vector2[this.uvs.Count];
  145. this.vertices.CopyTo(vertices, 0);
  146. this.normals.CopyTo(normals, 0);
  147. this.tangents.CopyTo(tangents, 0);
  148. this.uvs.CopyTo(uvs, 0);
  149. // Create index array
  150. int[] indices = new int[triangles.Count * 3];
  151. int count = 0;
  152. foreach (Triangle triangle in triangles)
  153. {
  154. indices[count++] = triangle.vertex0;
  155. indices[count++] = triangle.vertex1;
  156. indices[count++] = triangle.vertex2;
  157. }
  158. // Create output mesh
  159. Mesh mesh = new Mesh();
  160. mesh.vertices = vertices;
  161. mesh.normals = normals;
  162. mesh.tangents = tangents;
  163. mesh.uv = uvs;
  164. mesh.triangles = indices;
  165. return mesh;
  166. }
  167. return null;
  168. }
  169. }
  170. public void Split(Vector3 localPointOnPlane, Vector3 localPlaneNormal, bool fillCut, UvMapper uvMapper, ColorMapper colorMapper, out IHull resultA, out IHull resultB)
  171. {
  172. lock (key)
  173. {
  174. if (localPlaneNormal == Vector3.zero)
  175. {
  176. localPlaneNormal = Vector3.up;
  177. }
  178. LegacyHull a = new LegacyHull(this);
  179. LegacyHull b = new LegacyHull(this);
  180. SetIndices();
  181. bool[] pointAbovePlane;
  182. AssignPoints(a, b, localPointOnPlane, localPlaneNormal, out pointAbovePlane);
  183. int[] oldToNewVertex;
  184. AssignVertices(a, b, pointAbovePlane, out oldToNewVertex);
  185. bool[] edgeIntersectsPlane;
  186. EdgeHit[] edgeHits;
  187. AssignEdges(a, b, pointAbovePlane, localPointOnPlane, localPlaneNormal, out edgeIntersectsPlane, out edgeHits);
  188. IList<Edge> cutEdgesA, cutEdgesB;
  189. AssignTriangles(a, b, pointAbovePlane, edgeIntersectsPlane, edgeHits, oldToNewVertex, out cutEdgesA, out cutEdgesB);
  190. if (fillCut)
  191. {
  192. SortCutEdges(cutEdgesA, cutEdgesB);
  193. FillCutEdges(a, b, cutEdgesA, cutEdgesB, localPlaneNormal, uvMapper);
  194. }
  195. ValidateOutput(a, b, localPlaneNormal);
  196. Clear();
  197. // Set output
  198. resultA = a;
  199. resultB = b;
  200. }
  201. }
  202. protected void SetIndices()
  203. {
  204. int pointCount = 0;
  205. foreach (Point point in points)
  206. {
  207. point.index = pointCount++;
  208. }
  209. int edgeCount = 0;
  210. foreach (Edge edge in edges)
  211. {
  212. edge.index = edgeCount++;
  213. }
  214. }
  215. protected void AssignPoints(LegacyHull a, LegacyHull b, Vector3 pointOnPlane, Vector3 planeNormal, out bool[] pointAbovePlane)
  216. {
  217. pointAbovePlane = new bool[points.Count];
  218. foreach (Point point in points)
  219. {
  220. bool abovePlane = Vector3.Dot(point.position - pointOnPlane, planeNormal) >= 0.0f;
  221. pointAbovePlane[point.index] = abovePlane;
  222. if (abovePlane)
  223. {
  224. // Assign this point to hull A
  225. a.points.Add(point);
  226. }
  227. else
  228. {
  229. // Assign this point to hull B
  230. b.points.Add(point);
  231. }
  232. }
  233. }
  234. protected void AssignVertices(LegacyHull a, LegacyHull b, bool[] pointAbovePlane, out int[] oldToNewVertex)
  235. {
  236. oldToNewVertex = new int[vertices.Count];
  237. for (int i = 0; i < vertices.Count; i++)
  238. {
  239. Point correspondingPoint = vertexToPointMap[i];
  240. if (pointAbovePlane[correspondingPoint.index])
  241. {
  242. // Assign this vertex to hull A
  243. a.AddVertex(vertices[i], normals[i], tangents[i], uvs[i], correspondingPoint, out oldToNewVertex[i]);
  244. }
  245. else
  246. {
  247. // Assign this vertex to hull B
  248. b.AddVertex(vertices[i], normals[i], tangents[i], uvs[i], correspondingPoint, out oldToNewVertex[i]);
  249. }
  250. }
  251. }
  252. protected void AssignEdges(LegacyHull a, LegacyHull b, bool[] pointAbovePlane, Vector3 pointOnPlane, Vector3 planeNormal, out bool[] edgeIntersectsPlane, out EdgeHit[] edgeHits)
  253. {
  254. edgeIntersectsPlane = new bool[edges.Count];
  255. edgeHits = new EdgeHit[edges.Count];
  256. foreach (Edge edge in edges)
  257. {
  258. bool abovePlane0 = pointAbovePlane[edge.point0.index];
  259. bool abovePlane1 = pointAbovePlane[edge.point1.index];
  260. if (abovePlane0 && abovePlane1)
  261. {
  262. // Assign this edge to hull A
  263. a.edges.Add(edge);
  264. }
  265. else if (!abovePlane0 && !abovePlane1)
  266. {
  267. // Assign this edge to hull B
  268. b.edges.Add(edge);
  269. }
  270. else
  271. {
  272. // Split edge
  273. float denominator = Vector3.Dot(edge.line, planeNormal);
  274. float scalar = Mathf.Clamp01(Vector3.Dot(pointOnPlane - edge.point0.position, planeNormal) / denominator);
  275. Vector3 intersection = edge.point0.position + edge.line * scalar;
  276. // Create new points
  277. Point pointA = new Point(intersection);
  278. Point pointB = new Point(intersection);
  279. a.points.Add(pointA);
  280. b.points.Add(pointB);
  281. // Create new edges
  282. Edge splitA, splitB;
  283. if (pointAbovePlane[edge.point0.index])
  284. {
  285. splitA = new Edge(pointA, edge.point0);
  286. splitB = new Edge(pointB, edge.point1);
  287. }
  288. else
  289. {
  290. splitA = new Edge(pointA, edge.point1);
  291. splitB = new Edge(pointB, edge.point0);
  292. }
  293. a.edges.Add(splitA);
  294. b.edges.Add(splitB);
  295. // Set flags
  296. edgeIntersectsPlane[edge.index] = true;
  297. edgeHits[edge.index] = new EdgeHit();
  298. edgeHits[edge.index].scalar = scalar;
  299. edgeHits[edge.index].splitA = splitA;
  300. edgeHits[edge.index].splitB = splitB;
  301. }
  302. }
  303. }
  304. protected void AssignTriangles(LegacyHull a, LegacyHull b, bool[] pointAbovePlane, bool[] edgeIntersectsPlane, EdgeHit[] edgeHits, int[] oldToNewVertex, out IList<Edge> cutEdgesA, out IList<Edge> cutEdgesB)
  305. {
  306. cutEdgesA = new List<Edge>();
  307. cutEdgesB = new List<Edge>();
  308. foreach (Triangle triangle in triangles)
  309. {
  310. bool abovePlane0 = pointAbovePlane[triangle.point0.index];
  311. bool abovePlane1 = pointAbovePlane[triangle.point1.index];
  312. bool abovePlane2 = pointAbovePlane[triangle.point2.index];
  313. if (abovePlane0 && abovePlane1 && abovePlane2)
  314. {
  315. // Assign this triangle to hull A
  316. triangle.vertex0 = oldToNewVertex[triangle.vertex0];
  317. triangle.vertex1 = oldToNewVertex[triangle.vertex1];
  318. triangle.vertex2 = oldToNewVertex[triangle.vertex2];
  319. a.triangles.Add(triangle);
  320. }
  321. else if (!abovePlane0 && !abovePlane1 && !abovePlane2)
  322. {
  323. // Assign this triangle to hull B
  324. triangle.vertex0 = oldToNewVertex[triangle.vertex0];
  325. triangle.vertex1 = oldToNewVertex[triangle.vertex1];
  326. triangle.vertex2 = oldToNewVertex[triangle.vertex2];
  327. b.triangles.Add(triangle);
  328. }
  329. else
  330. {
  331. // Split triangle
  332. Point topPoint;
  333. Edge edge0, edge1, edge2;
  334. int vertex0, vertex1, vertex2;
  335. if (edgeIntersectsPlane[triangle.edge0.index] && edgeIntersectsPlane[triangle.edge1.index])
  336. {
  337. topPoint = triangle.point1;
  338. edge0 = triangle.edge0;
  339. edge1 = triangle.edge1;
  340. edge2 = triangle.edge2;
  341. vertex0 = triangle.vertex0;
  342. vertex1 = triangle.vertex1;
  343. vertex2 = triangle.vertex2;
  344. }
  345. else if (edgeIntersectsPlane[triangle.edge1.index] && edgeIntersectsPlane[triangle.edge2.index])
  346. {
  347. topPoint = triangle.point2;
  348. edge0 = triangle.edge1;
  349. edge1 = triangle.edge2;
  350. edge2 = triangle.edge0;
  351. vertex0 = triangle.vertex1;
  352. vertex1 = triangle.vertex2;
  353. vertex2 = triangle.vertex0;
  354. }
  355. else
  356. {
  357. topPoint = triangle.point0;
  358. edge0 = triangle.edge2;
  359. edge1 = triangle.edge0;
  360. edge2 = triangle.edge1;
  361. vertex0 = triangle.vertex2;
  362. vertex1 = triangle.vertex0;
  363. vertex2 = triangle.vertex1;
  364. }
  365. EdgeHit edgeHit0 = edgeHits[edge0.index];
  366. EdgeHit edgeHit1 = edgeHits[edge1.index];
  367. // Convert edge hit scalars to the triangle winding order
  368. float scalar0 = topPoint == edge0.point1 ? edgeHit0.scalar : 1.0f - edgeHit0.scalar;
  369. float scalar1 = topPoint == edge1.point0 ? edgeHit1.scalar : 1.0f - edgeHit1.scalar;
  370. Edge cutEdgeA, cutEdgeB;
  371. if (pointAbovePlane[topPoint.index])
  372. {
  373. // Assign top triangle to hull A, bottom triangle to hull B
  374. cutEdgeA = new Edge(edgeHit1.splitA.point0, edgeHit0.splitA.point0);
  375. cutEdgeB = new Edge(edgeHit1.splitB.point0, edgeHit0.splitB.point0);
  376. a.edges.Add(cutEdgeA);
  377. b.edges.Add(cutEdgeB);
  378. SplitTriangle(a, b, edgeHit0.splitA, edgeHit1.splitA, cutEdgeA, edgeHit0.splitB, edgeHit1.splitB, cutEdgeB, edge2, vertex0, vertex1, vertex2, scalar0, scalar1, oldToNewVertex);
  379. }
  380. else
  381. {
  382. // Assign top triangle to hull B, bottom triangle to hull A
  383. cutEdgeA = new Edge(edgeHit0.splitA.point0, edgeHit1.splitA.point0);
  384. cutEdgeB = new Edge(edgeHit0.splitB.point0, edgeHit1.splitB.point0);
  385. a.edges.Add(cutEdgeA);
  386. b.edges.Add(cutEdgeB);
  387. SplitTriangle(b, a, edgeHit0.splitB, edgeHit1.splitB, cutEdgeB, edgeHit0.splitA, edgeHit1.splitA, cutEdgeA, edge2, vertex0, vertex1, vertex2, scalar0, scalar1, oldToNewVertex);
  388. }
  389. cutEdgesA.Add(cutEdgeA);
  390. cutEdgesB.Add(cutEdgeB);
  391. }
  392. }
  393. }
  394. protected void SplitTriangle(LegacyHull topHull, LegacyHull bottomHull, Edge topEdge0, Edge topEdge1, Edge topCutEdge, Edge bottomEdge0, Edge bottomEdge1, Edge bottomCutEdge, Edge bottomEdge2, int vertex0, int vertex1, int vertex2, float scalar0, float scalar1, int[] oldToNewVertex)
  395. {
  396. Vector3 n0 = normals[vertex0];
  397. Vector3 n1 = normals[vertex1];
  398. Vector3 n2 = normals[vertex2];
  399. Vector4 t0 = tangents[vertex0];
  400. Vector4 t1 = tangents[vertex1];
  401. Vector4 t2 = tangents[vertex2];
  402. Vector2 uv0 = uvs[vertex0];
  403. Vector2 uv1 = uvs[vertex1];
  404. Vector2 uv2 = uvs[vertex2];
  405. // Calculate the cut vertex data by interpolating original triangle values
  406. Vector3 cutNormal0 = new Vector3();
  407. cutNormal0.x = n0.x + (n1.x - n0.x) * scalar0;
  408. cutNormal0.y = n0.y + (n1.y - n0.y) * scalar0;
  409. cutNormal0.z = n0.z + (n1.z - n0.z) * scalar0;
  410. cutNormal0.Normalize();
  411. Vector3 cutNormal1 = new Vector3();
  412. cutNormal1.x = n1.x + (n2.x - n1.x) * scalar1;
  413. cutNormal1.y = n1.y + (n2.y - n1.y) * scalar1;
  414. cutNormal1.z = n1.z + (n2.z - n1.z) * scalar1;
  415. cutNormal1.Normalize();
  416. Vector4 cutTangent0 = new Vector4();
  417. cutTangent0.x = t0.x + (t1.x - t0.x) * scalar0;
  418. cutTangent0.y = t0.y + (t1.y - t0.y) * scalar0;
  419. cutTangent0.z = t0.z + (t1.z - t0.z) * scalar0;
  420. cutTangent0.Normalize();
  421. cutTangent0.w = t0.w;
  422. Vector4 cutTangent1 = new Vector4();
  423. cutTangent1.x = t1.x + (t2.x - t1.x) * scalar1;
  424. cutTangent1.y = t1.y + (t2.y - t1.y) * scalar1;
  425. cutTangent1.z = t1.z + (t2.z - t1.z) * scalar1;
  426. cutTangent1.Normalize();
  427. cutTangent1.w = t1.w;
  428. Vector2 cutUv0 = new Vector2();
  429. cutUv0.x = uv0.x + (uv1.x - uv0.x) * scalar0;
  430. cutUv0.y = uv0.y + (uv1.y - uv0.y) * scalar0;
  431. Vector2 cutUv1 = new Vector2();
  432. cutUv1.x = uv1.x + (uv2.x - uv1.x) * scalar1;
  433. cutUv1.y = uv1.y + (uv2.y - uv1.y) * scalar1;
  434. // Add the cut vertices to the hulls
  435. int topCutVertex0, topCutVertex1;
  436. topHull.AddVertex(topEdge0.point0.position, cutNormal0, cutTangent0, cutUv0, topEdge0.point0, out topCutVertex0);
  437. topHull.AddVertex(topEdge1.point0.position, cutNormal1, cutTangent1, cutUv1, topEdge1.point0, out topCutVertex1);
  438. int bottomCutVertex0, bottomCutVertex1;
  439. bottomHull.AddVertex(bottomEdge0.point0.position, cutNormal0, cutTangent0, cutUv0, bottomEdge0.point0, out bottomCutVertex0);
  440. bottomHull.AddVertex(bottomEdge1.point0.position, cutNormal1, cutTangent1, cutUv1, bottomEdge1.point0, out bottomCutVertex1);
  441. // Create the top of the original triangle
  442. Triangle topTriangle = new Triangle(topCutVertex0, oldToNewVertex[vertex1], topCutVertex1, topEdge0.point0, topEdge0.point1, topEdge1.point0, topEdge0, topEdge1, topCutEdge);
  443. topHull.triangles.Add(topTriangle);
  444. // Create the bottom of the original triangle
  445. Edge bottomCrossEdge = new Edge(bottomEdge0.point1, bottomEdge1.point0);
  446. Triangle bottomTriangle0 = new Triangle(oldToNewVertex[vertex0], bottomCutVertex0, bottomCutVertex1, bottomEdge0.point1, bottomEdge0.point0, bottomEdge1.point0, bottomEdge0, bottomCutEdge, bottomCrossEdge);
  447. Triangle bottomTriangle1 = new Triangle(oldToNewVertex[vertex0], bottomCutVertex1, oldToNewVertex[vertex2], bottomEdge0.point1, bottomEdge1.point0, bottomEdge1.point1, bottomCrossEdge, bottomEdge1, bottomEdge2);
  448. bottomHull.edges.Add(bottomCrossEdge);
  449. bottomHull.triangles.Add(bottomTriangle0);
  450. bottomHull.triangles.Add(bottomTriangle1);
  451. }
  452. protected void SortCutEdges(IList<Edge> edgesA, IList<Edge> edgesB)
  453. {
  454. Edge start = null;
  455. for (int i = 0; i < edgesA.Count; i++)
  456. {
  457. if (start == null)
  458. {
  459. start = edgesA[i];
  460. }
  461. else
  462. {
  463. Edge previous = edgesA[i - 1];
  464. for (int j = i; j < edgesA.Count; j++)
  465. {
  466. Edge edgeA = edgesA[j];
  467. // Does this edge continue the previous one?
  468. if (previous.point1 == edgeA.point0)
  469. {
  470. // Swap edges
  471. Edge currentEdgeA = edgesA[i];
  472. edgesA[i] = edgeA;
  473. edgesA[j] = currentEdgeA;
  474. Edge currentEdgeB = edgesB[i];
  475. edgesB[i] = edgesB[j];
  476. edgesB[j] = currentEdgeB;
  477. // Does this edge end the current loop?
  478. if (edgeA.point1 == start.point0)
  479. {
  480. start = null;
  481. }
  482. break;
  483. }
  484. }
  485. }
  486. }
  487. }
  488. protected void FillCutEdges(LegacyHull a, LegacyHull b, IList<Edge> edgesA, IList<Edge> edgesB, Vector3 planeNormal, UvMapper uvMapper)
  489. {
  490. // Create outline data
  491. int outlineEdgeCount = edgesA.Count;
  492. Vector3[] outlinePoints = new Vector3[outlineEdgeCount];
  493. int[] outlineEdges = new int[outlineEdgeCount * 2];
  494. int startIndex = 0;
  495. for (int i = 0; i < outlineEdgeCount; i++)
  496. {
  497. int currentIndex = i;
  498. int nextIndex = (i + 1) % outlineEdgeCount;
  499. Edge current = edgesA[currentIndex];
  500. Edge next = edgesA[nextIndex];
  501. // Set point
  502. outlinePoints[i] = current.point0.position;
  503. // Set edge
  504. outlineEdges[i * 2 + 0] = currentIndex;
  505. if (current.point1 == next.point0)
  506. {
  507. outlineEdges[i * 2 + 1] = nextIndex;
  508. }
  509. else
  510. {
  511. outlineEdges[i * 2 + 1] = startIndex;
  512. startIndex = nextIndex;
  513. }
  514. }
  515. // Triangulate
  516. int[] newEdges, newTriangles, newTriangleEdges;
  517. ITriangulator triangulator = new Triangulator(outlinePoints, outlineEdges, planeNormal);
  518. triangulator.Fill(out newEdges, out newTriangles, out newTriangleEdges);
  519. // Calculate vertex properties
  520. Vector3 normalA = -planeNormal;
  521. Vector3 normalB = planeNormal;
  522. Vector4[] tangentsA, tangentsB;
  523. Vector2[] uvsA, uvsB;
  524. uvMapper.Map(outlinePoints, planeNormal, out tangentsA, out tangentsB, out uvsA, out uvsB);
  525. // Create new vertices
  526. int[] verticesA = new int[outlineEdgeCount];
  527. int[] verticesB = new int[outlineEdgeCount];
  528. for (int i = 0; i < outlineEdgeCount; i++)
  529. {
  530. a.AddVertex(outlinePoints[i], normalA, tangentsA[i], uvsA[i], edgesA[i].point0, out verticesA[i]);
  531. b.AddVertex(outlinePoints[i], normalB, tangentsB[i], uvsB[i], edgesB[i].point0, out verticesB[i]);
  532. }
  533. // Create new edges
  534. for (int i = 0; i < newEdges.Length / 2; i++)
  535. {
  536. int point0 = newEdges[i * 2 + 0];
  537. int point1 = newEdges[i * 2 + 1];
  538. Edge edgeA = new Edge(edgesA[point0].point0, edgesA[point1].point0);
  539. Edge edgeB = new Edge(edgesB[point0].point0, edgesB[point1].point0);
  540. edgesA.Add(edgeA);
  541. edgesB.Add(edgeB);
  542. a.edges.Add(edgeA);
  543. b.edges.Add(edgeB);
  544. }
  545. // Create new triangles
  546. for (int i = 0; i < newTriangles.Length / 3; i++)
  547. {
  548. int point0 = newTriangles[i * 3 + 0];
  549. int point1 = newTriangles[i * 3 + 1];
  550. int point2 = newTriangles[i * 3 + 2];
  551. int edge0 = newTriangleEdges[i * 3 + 0];
  552. int edge1 = newTriangleEdges[i * 3 + 1];
  553. int edge2 = newTriangleEdges[i * 3 + 2];
  554. Triangle triangleA = new Triangle(verticesA[point0], verticesA[point2], verticesA[point1], edgesA[point0].point0, edgesA[point2].point0, edgesA[point1].point0, edgesA[edge2], edgesA[edge1], edgesA[edge0]);
  555. Triangle triangleB = new Triangle(verticesB[point0], verticesB[point1], verticesB[point2], edgesB[point0].point0, edgesB[point1].point0, edgesB[point2].point0, edgesB[edge0], edgesB[edge1], edgesB[edge2]);
  556. a.triangles.Add(triangleA);
  557. b.triangles.Add(triangleB);
  558. }
  559. }
  560. protected void ValidateOutput(LegacyHull a, LegacyHull b, Vector3 planeNormal)
  561. {
  562. float lengthA = a.LengthAlongAxis(planeNormal);
  563. float lengthB = b.LengthAlongAxis(planeNormal);
  564. float sum = lengthA + lengthB;
  565. if (sum < smallestValidLength)
  566. {
  567. a.Clear();
  568. b.Clear();
  569. }
  570. else if (lengthA / sum < smallestValidRatio)
  571. {
  572. a.Clear();
  573. }
  574. else if (lengthB / sum < smallestValidRatio)
  575. {
  576. b.Clear();
  577. }
  578. }
  579. protected float LengthAlongAxis(Vector3 axis)
  580. {
  581. float min = 0.0f;
  582. float max = 0.0f;
  583. for (int i = 0; i < points.Count; i++)
  584. {
  585. float distance = Vector3.Dot(points[i].position, axis);
  586. if (i == 0)
  587. {
  588. min = distance;
  589. max = distance;
  590. }
  591. else
  592. {
  593. min = Mathf.Min(distance, min);
  594. max = Mathf.Max(distance, max);
  595. }
  596. }
  597. return max - min;
  598. }
  599. }
  600. }