暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Tessellator.cs 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  1. using System;
  2. using Unity.Profiling;
  3. using Unity.Collections;
  4. using Unity.Mathematics;
  5. using Unity.Collections.LowLevel.Unsafe;
  6. namespace UnityEngine.U2D.Common.UTess
  7. {
  8. // Constrained Delaunay Triangulation.
  9. struct Tessellator
  10. {
  11. // For Processing.
  12. NativeArray<int2> m_Edges;
  13. NativeArray<UStar> m_Stars;
  14. Array<int3> m_Cells;
  15. int m_CellCount;
  16. // For Storage.
  17. NativeArray<int> m_ILArray;
  18. NativeArray<int> m_IUArray;
  19. NativeArray<int> m_SPArray;
  20. int m_NumEdges;
  21. int m_NumHulls;
  22. int m_NumPoints;
  23. int m_StarCount;
  24. // Intermediates.
  25. NativeArray<int> m_Flags;
  26. NativeArray<int> m_Neighbors;
  27. NativeArray<int> m_Constraints;
  28. Allocator m_Allocator;
  29. struct TestHullPointL : ICondition2<UHull, float2>
  30. {
  31. public bool Test(UHull h, float2 p, ref float t)
  32. {
  33. t = ModuleHandle.OrientFast(h.a, h.b, p);
  34. return t < 0;
  35. }
  36. }
  37. struct TestHullPointU : ICondition2<UHull, float2>
  38. {
  39. public bool Test(UHull h, float2 p, ref float t)
  40. {
  41. t = ModuleHandle.OrientFast(h.a, h.b, p);
  42. return t > 0;
  43. }
  44. }
  45. static float FindSplit(UHull hull, UEvent edge)
  46. {
  47. float d = 0;
  48. if (hull.a.x < edge.a.x)
  49. {
  50. d = ModuleHandle.OrientFast(hull.a, hull.b, edge.a);
  51. }
  52. else
  53. {
  54. d = ModuleHandle.OrientFast(edge.b, edge.a, hull.a);
  55. }
  56. if (0 != d)
  57. {
  58. return d;
  59. }
  60. if (edge.b.x < hull.b.x)
  61. {
  62. d = ModuleHandle.OrientFast(hull.a, hull.b, edge.b);
  63. }
  64. else
  65. {
  66. d = ModuleHandle.OrientFast(edge.b, edge.a, hull.b);
  67. }
  68. if (0 != d)
  69. {
  70. return d;
  71. }
  72. return hull.idx - edge.idx;
  73. }
  74. struct TestHullEventLe : ICondition2<UHull, UEvent>
  75. {
  76. public bool Test(UHull h, UEvent p, ref float t)
  77. {
  78. t = FindSplit(h, p);
  79. return t <= 0;
  80. }
  81. }
  82. struct TestHullEventE : ICondition2<UHull, UEvent>
  83. {
  84. public bool Test(UHull h, UEvent p, ref float t)
  85. {
  86. t = FindSplit(h, p);
  87. return t == 0;
  88. }
  89. }
  90. void SetAllocator(Allocator allocator)
  91. {
  92. m_Allocator = allocator;
  93. }
  94. bool AddPoint(NativeArray<UHull> hulls, int hullCount, NativeArray<float2> points, float2 p, int idx)
  95. {
  96. int l = ModuleHandle.GetLower(hulls, hullCount, p, new TestHullPointL());
  97. int u = ModuleHandle.GetUpper(hulls, hullCount, p, new TestHullPointU());
  98. if (l < 0 || u < 0)
  99. return false;
  100. for (int i = l; i < u; ++i)
  101. {
  102. UHull hull = hulls[i];
  103. int m = hull.ilcount;
  104. while (m > 1 && ModuleHandle.OrientFast(points[hull.ilarray[m - 2]], points[hull.ilarray[m - 1]], p) > 0)
  105. {
  106. int3 c = new int3();
  107. c.x = hull.ilarray[m - 1];
  108. c.y = hull.ilarray[m - 2];
  109. c.z = idx;
  110. m_Cells[m_CellCount++] = c;
  111. m -= 1;
  112. }
  113. hull.ilcount = m + 1;
  114. if (hull.ilcount > hull.ilarray.Length)
  115. return false;
  116. hull.ilarray[m] = idx;
  117. m = hull.iucount;
  118. while (m > 1 && ModuleHandle.OrientFast(points[hull.iuarray[m - 2]], points[hull.iuarray[m - 1]], p) < 0)
  119. {
  120. int3 c = new int3();
  121. c.x = hull.iuarray[m - 2];
  122. c.y = hull.iuarray[m - 1];
  123. c.z = idx;
  124. m_Cells[m_CellCount++] = c;
  125. m -= 1;
  126. }
  127. hull.iucount = m + 1;
  128. if (hull.iucount > hull.iuarray.Length)
  129. return false;
  130. hull.iuarray[m] = idx;
  131. hulls[i] = hull;
  132. }
  133. return true;
  134. }
  135. static void InsertHull(NativeArray<UHull> Hulls, int Pos, ref int Count, UHull Value)
  136. {
  137. if (Count < Hulls.Length - 1)
  138. {
  139. for (int i = Count; i > Pos; --i)
  140. Hulls[i] = Hulls[i - 1];
  141. Hulls[Pos] = Value;
  142. Count++;
  143. }
  144. }
  145. static void EraseHull(NativeArray<UHull> Hulls, int Pos, ref int Count)
  146. {
  147. if (Count < Hulls.Length)
  148. {
  149. for (int i = Pos; i < Count - 1; ++i)
  150. Hulls[i] = Hulls[i + 1];
  151. Count--;
  152. }
  153. }
  154. bool SplitHulls(NativeArray<UHull> hulls, ref int hullCount, NativeArray<float2> points, UEvent evt)
  155. {
  156. int index = ModuleHandle.GetLower(hulls, hullCount, evt, new TestHullEventLe());
  157. if (index < 0)
  158. return false;
  159. UHull hull = hulls[index];
  160. UHull newHull;
  161. newHull.a = evt.a;
  162. newHull.b = evt.b;
  163. newHull.idx = evt.idx;
  164. int y = hull.iuarray[hull.iucount - 1];
  165. newHull.iuarray = new ArraySlice<int>(m_IUArray, newHull.idx * m_NumHulls, m_NumHulls);
  166. newHull.iucount = hull.iucount;
  167. for (int i = 0; i < newHull.iucount; ++i)
  168. newHull.iuarray[i] = hull.iuarray[i];
  169. hull.iuarray[0] = y;
  170. hull.iucount = 1;
  171. hulls[index] = hull;
  172. newHull.ilarray = new ArraySlice<int>(m_ILArray, newHull.idx * m_NumHulls, m_NumHulls);
  173. newHull.ilarray[0] = y;
  174. newHull.ilcount = 1;
  175. InsertHull(hulls, index + 1, ref hullCount, newHull);
  176. return true;
  177. }
  178. bool MergeHulls(NativeArray<UHull> hulls, ref int hullCount, NativeArray<float2> points, UEvent evt)
  179. {
  180. float2 temp = evt.a;
  181. evt.a = evt.b;
  182. evt.b = temp;
  183. int index = ModuleHandle.GetEqual(hulls, hullCount, evt, new TestHullEventE());
  184. if (index < 0)
  185. return false;
  186. UHull upper = hulls[index];
  187. UHull lower = hulls[index - 1];
  188. lower.iucount = upper.iucount;
  189. for (int i = 0; i < lower.iucount; ++i)
  190. lower.iuarray[i] = upper.iuarray[i];
  191. hulls[index - 1] = lower;
  192. EraseHull(hulls, index, ref hullCount);
  193. return true;
  194. }
  195. static void InsertUniqueEdge(NativeArray<int2> edges, int2 e, ref int edgeCount)
  196. {
  197. TessEdgeCompare edgeComparer = new TessEdgeCompare();
  198. var validEdge = true;
  199. for (int j = 0; validEdge && j < edgeCount; ++j)
  200. if (edgeComparer.Compare(e, edges[j]) == 0)
  201. validEdge = false;
  202. if (validEdge)
  203. edges[edgeCount++] = e;
  204. }
  205. void PrepareDelaunay(NativeArray<int2> edges, int edgeCount)
  206. {
  207. m_StarCount = m_CellCount * 3;
  208. m_Stars = new NativeArray<UStar>(m_StarCount, m_Allocator);
  209. m_SPArray = new NativeArray<int>(m_StarCount * m_StarCount, m_Allocator, NativeArrayOptions.UninitializedMemory);
  210. var UEdgeCount = 0;
  211. var UEdges = new NativeArray<int2>(m_StarCount, m_Allocator);
  212. // Input Edges.
  213. for (int i = 0; i < edgeCount; ++i)
  214. {
  215. int2 e = edges[i];
  216. e.x = (edges[i].x < edges[i].y) ? edges[i].x : edges[i].y;
  217. e.y = (edges[i].x > edges[i].y) ? edges[i].x : edges[i].y;
  218. edges[i] = e;
  219. InsertUniqueEdge(UEdges, e, ref UEdgeCount);
  220. }
  221. m_Edges = new NativeArray<int2>(UEdgeCount, m_Allocator);
  222. for (int i = 0; i < UEdgeCount; ++i)
  223. m_Edges[i] = UEdges[i];
  224. UEdges.Dispose();
  225. unsafe
  226. {
  227. ModuleHandle.InsertionSort<int2, TessEdgeCompare>(
  228. NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(m_Edges), 0, m_Edges.Length - 1,
  229. new TessEdgeCompare());
  230. }
  231. // Init Stars.
  232. for (int i = 0; i < m_StarCount; ++i)
  233. {
  234. UStar s = m_Stars[i];
  235. s.points = new ArraySlice<int>(m_SPArray, i * m_StarCount, m_StarCount);
  236. s.pointCount = 0;
  237. m_Stars[i] = s;
  238. }
  239. // Fill stars.
  240. for (int i = 0; i < m_CellCount; ++i)
  241. {
  242. int a = m_Cells[i].x;
  243. int b = m_Cells[i].y;
  244. int c = m_Cells[i].z;
  245. UStar sa = m_Stars[a];
  246. UStar sb = m_Stars[b];
  247. UStar sc = m_Stars[c];
  248. sa.points[sa.pointCount++] = b;
  249. sa.points[sa.pointCount++] = c;
  250. sb.points[sb.pointCount++] = c;
  251. sb.points[sb.pointCount++] = a;
  252. sc.points[sc.pointCount++] = a;
  253. sc.points[sc.pointCount++] = b;
  254. m_Stars[a] = sa;
  255. m_Stars[b] = sb;
  256. m_Stars[c] = sc;
  257. }
  258. }
  259. int OppositeOf(int a, int b)
  260. {
  261. ArraySlice<int> points = m_Stars[b].points;
  262. for (int k = 1, n = m_Stars[b].pointCount; k < n; k += 2)
  263. if (points[k] == a)
  264. return points[k - 1];
  265. return -1;
  266. }
  267. struct TestEdgePointE : ICondition2<int2, int2>
  268. {
  269. public bool Test(int2 h, int2 p, ref float t)
  270. {
  271. TessEdgeCompare tc = new TessEdgeCompare();
  272. t = tc.Compare(h, p);
  273. return t == 0;
  274. }
  275. }
  276. int FindConstraint(int a, int b)
  277. {
  278. int2 e;
  279. e.x = a < b ? a : b;
  280. e.y = a > b ? a : b;
  281. return ModuleHandle.GetEqual(m_Edges, m_Edges.Length, e, new TestEdgePointE());
  282. }
  283. void AddTriangle(int i, int j, int k)
  284. {
  285. UStar si = m_Stars[i];
  286. UStar sj = m_Stars[j];
  287. UStar sk = m_Stars[k];
  288. si.points[si.pointCount++] = j;
  289. si.points[si.pointCount++] = k;
  290. sj.points[sj.pointCount++] = k;
  291. sj.points[sj.pointCount++] = i;
  292. sk.points[sk.pointCount++] = i;
  293. sk.points[sk.pointCount++] = j;
  294. m_Stars[i] = si;
  295. m_Stars[j] = sj;
  296. m_Stars[k] = sk;
  297. }
  298. void RemovePair(int r, int j, int k)
  299. {
  300. UStar s = m_Stars[r];
  301. ArraySlice<int> points = s.points;
  302. for (int i = 1, n = s.pointCount; i < n; i += 2)
  303. {
  304. if (points[i - 1] == j && points[i] == k)
  305. {
  306. points[i - 1] = points[n - 2];
  307. points[i] = points[n - 1];
  308. s.points = points;
  309. s.pointCount = s.pointCount - 2;
  310. m_Stars[r] = s;
  311. return;
  312. }
  313. }
  314. }
  315. void RemoveTriangle(int i, int j, int k)
  316. {
  317. RemovePair(i, j, k);
  318. RemovePair(j, k, i);
  319. RemovePair(k, i, j);
  320. }
  321. void EdgeFlip(int i, int j)
  322. {
  323. int a = OppositeOf(i, j);
  324. int b = OppositeOf(j, i);
  325. RemoveTriangle(i, j, a);
  326. RemoveTriangle(j, i, b);
  327. AddTriangle(i, b, a);
  328. AddTriangle(j, a, b);
  329. }
  330. bool Flip(NativeArray<float2> points, ref Array<int> stack, ref int stackCount, int a, int b, int x)
  331. {
  332. int y = OppositeOf(a, b);
  333. if (y < 0)
  334. {
  335. return true;
  336. }
  337. if (b < a)
  338. {
  339. int tmp = a;
  340. a = b;
  341. b = tmp;
  342. tmp = x;
  343. x = y;
  344. y = tmp;
  345. }
  346. if (FindConstraint(a, b) != -1)
  347. {
  348. return true;
  349. }
  350. if (ModuleHandle.IsInsideCircle(points[a], points[b], points[x], points[y]))
  351. {
  352. if ((2 + stackCount) >= stack.Length)
  353. return false;
  354. stack[stackCount++] = a;
  355. stack[stackCount++] = b;
  356. }
  357. return true;
  358. }
  359. Array<int3> GetCells(ref int count)
  360. {
  361. var cellsOut = new Array<int3>(m_NumPoints * 4, m_NumPoints * (m_NumPoints + 1), m_Allocator, NativeArrayOptions.UninitializedMemory);
  362. count = 0;
  363. for (int i = 0, n = m_Stars.Length; i < n; ++i)
  364. {
  365. ArraySlice<int> points = m_Stars[i].points;
  366. for (int j = 0, m = m_Stars[i].pointCount; j < m; j += 2)
  367. {
  368. int s = points[j];
  369. int t = points[j + 1];
  370. if (i < math.min(s, t))
  371. {
  372. int3 c = new int3();
  373. c.x = i;
  374. c.y = s;
  375. c.z = t;
  376. cellsOut[count++] = c;
  377. }
  378. }
  379. }
  380. return cellsOut;
  381. }
  382. internal bool ApplyDelaunay(NativeArray<float2> points, NativeArray<int2> edges)
  383. {
  384. // Early out if cannot find any valid cells.
  385. if (0 == m_CellCount)
  386. return false;
  387. var stack = new Array<int>(m_NumPoints * 4, m_NumPoints * (m_NumPoints + 1), m_Allocator, NativeArrayOptions.UninitializedMemory);
  388. int stackCount = 0;
  389. var valid = true;
  390. PrepareDelaunay(edges, m_NumEdges);
  391. for (int a = 0; valid && (a < m_NumPoints); ++a)
  392. {
  393. UStar star = m_Stars[a];
  394. for (int j = 1; j < star.pointCount; j += 2)
  395. {
  396. int b = star.points[j];
  397. if (b < a)
  398. {
  399. continue;
  400. }
  401. if (FindConstraint(a, b) >= 0)
  402. {
  403. continue;
  404. }
  405. int x = star.points[j - 1], y = -1;
  406. for (int k = 1; k < star.pointCount; k += 2)
  407. {
  408. if (star.points[k - 1] == b)
  409. {
  410. y = star.points[k];
  411. break;
  412. }
  413. }
  414. if (y < 0)
  415. {
  416. continue;
  417. }
  418. if (ModuleHandle.IsInsideCircle(points[a], points[b], points[x], points[y]))
  419. {
  420. if ((2 + stackCount) >= stack.Length)
  421. {
  422. valid = false;
  423. break;
  424. }
  425. stack[stackCount++] = a;
  426. stack[stackCount++] = b;
  427. }
  428. }
  429. }
  430. var flipFlops = m_NumPoints * m_NumPoints;
  431. while (stackCount > 0 && valid)
  432. {
  433. int b = stack[stackCount - 1];
  434. stackCount--;
  435. int a = stack[stackCount - 1];
  436. stackCount--;
  437. int x = -1, y = -1;
  438. UStar star = m_Stars[a];
  439. for (int i = 1; i < star.pointCount; i += 2)
  440. {
  441. int s = star.points[i - 1];
  442. int t = star.points[i];
  443. if (s == b)
  444. {
  445. y = t;
  446. }
  447. else if (t == b)
  448. {
  449. x = s;
  450. }
  451. }
  452. if (x < 0 || y < 0)
  453. {
  454. continue;
  455. }
  456. if (!ModuleHandle.IsInsideCircle(points[a], points[b], points[x], points[y]))
  457. {
  458. continue;
  459. }
  460. EdgeFlip(a, b);
  461. valid = Flip(points, ref stack, ref stackCount, x, a, y);
  462. valid = valid && Flip(points, ref stack, ref stackCount, a, y, x);
  463. valid = valid && Flip(points, ref stack, ref stackCount, y, b, x);
  464. valid = valid && Flip(points, ref stack, ref stackCount, b, x, y);
  465. valid = valid && (--flipFlops > 0);
  466. }
  467. stack.Dispose();
  468. return valid;
  469. }
  470. struct TestCellE : ICondition2<int3, int3>
  471. {
  472. public bool Test(int3 h, int3 p, ref float t)
  473. {
  474. TessCellCompare tc = new TessCellCompare();
  475. t = tc.Compare(h, p);
  476. return t == 0;
  477. }
  478. }
  479. int FindNeighbor(Array<int3> cells, int count, int a, int b, int c)
  480. {
  481. int x = a, y = b, z = c;
  482. if (b < c)
  483. {
  484. if (b < a)
  485. {
  486. x = b;
  487. y = c;
  488. z = a;
  489. }
  490. }
  491. else if (c < a)
  492. {
  493. x = c;
  494. y = a;
  495. z = b;
  496. }
  497. if (x < 0)
  498. {
  499. return -1;
  500. }
  501. int3 key;
  502. key.x = x;
  503. key.y = y;
  504. key.z = z;
  505. return ModuleHandle.GetEqual(cells, count, key, new TestCellE());
  506. }
  507. Array<int3> Constrain(ref int count)
  508. {
  509. var cells = GetCells(ref count);
  510. int nc = count;
  511. for (int i = 0; i < nc; ++i)
  512. {
  513. int3 c = cells[i];
  514. int x = c.x, y = c.y, z = c.z;
  515. if (y < z)
  516. {
  517. if (y < x)
  518. {
  519. c.x = y;
  520. c.y = z;
  521. c.z = x;
  522. }
  523. }
  524. else if (z < x)
  525. {
  526. c.x = z;
  527. c.y = x;
  528. c.z = y;
  529. }
  530. cells[i] = c;
  531. }
  532. unsafe
  533. {
  534. ModuleHandle.InsertionSort<int3, TessCellCompare>(
  535. cells.UnsafePtr, 0, m_CellCount - 1,
  536. new TessCellCompare());
  537. }
  538. // Out
  539. m_Flags = new NativeArray<int>(nc, m_Allocator);
  540. m_Neighbors = new NativeArray<int>(nc * 3, m_Allocator);
  541. m_Constraints = new NativeArray<int>(nc * 3, m_Allocator);
  542. var next = new NativeArray<int>(nc * 3, m_Allocator);
  543. var active = new NativeArray<int>(nc * 3, m_Allocator);
  544. int side = 1, nextCount = 0, activeCount = 0;
  545. for (int i = 0; i < nc; ++i)
  546. {
  547. int3 c = cells[i];
  548. for (int j = 0; j < 3; ++j)
  549. {
  550. int x = j, y = (j + 1) % 3;
  551. x = (x == 0) ? c.x : (j == 1) ? c.y : c.z;
  552. y = (y == 0) ? c.x : (y == 1) ? c.y : c.z;
  553. int o = OppositeOf(y, x);
  554. int a = m_Neighbors[3 * i + j] = FindNeighbor(cells, count, y, x, o);
  555. int b = m_Constraints[3 * i + j] = (-1 != FindConstraint(x, y)) ? 1 : 0;
  556. if (a < 0)
  557. {
  558. if (0 != b)
  559. {
  560. next[nextCount++] = i;
  561. }
  562. else
  563. {
  564. active[activeCount++] = i;
  565. m_Flags[i] = 1;
  566. }
  567. }
  568. }
  569. }
  570. while (activeCount > 0 || nextCount > 0)
  571. {
  572. while (activeCount > 0)
  573. {
  574. int t = active[activeCount - 1];
  575. activeCount--;
  576. if (m_Flags[t] == -side)
  577. {
  578. continue;
  579. }
  580. m_Flags[t] = side;
  581. int3 c = cells[t];
  582. for (int j = 0; j < 3; ++j)
  583. {
  584. int f = m_Neighbors[3 * t + j];
  585. if (f >= 0 && m_Flags[f] == 0)
  586. {
  587. if (0 != m_Constraints[3 * t + j])
  588. {
  589. next[nextCount++] = f;
  590. }
  591. else
  592. {
  593. active[activeCount++] = f;
  594. m_Flags[f] = side;
  595. }
  596. }
  597. }
  598. }
  599. for (int e = 0; e < nextCount; e++)
  600. active[e] = next[e];
  601. activeCount = nextCount;
  602. nextCount = 0;
  603. side = -side;
  604. }
  605. active.Dispose();
  606. next.Dispose();
  607. return cells;
  608. }
  609. internal NativeArray<int3> RemoveExterior(ref int cellCount)
  610. {
  611. int constrainedCount = 0;
  612. var constrained = Constrain(ref constrainedCount);
  613. var cellsOut = new NativeArray<int3>(constrainedCount, m_Allocator);
  614. cellCount = 0;
  615. for (int i = 0; i < constrainedCount; ++i)
  616. {
  617. if (m_Flags[i] == -1)
  618. {
  619. cellsOut[cellCount++] = constrained[i];
  620. }
  621. }
  622. constrained.Dispose();
  623. return cellsOut;
  624. }
  625. internal NativeArray<int3> RemoveInterior(int cellCount)
  626. {
  627. int constrainedCount = 0;
  628. var constrained = Constrain(ref constrainedCount);
  629. var cellsOut = new NativeArray<int3>(constrainedCount, m_Allocator);
  630. cellCount = 0;
  631. for (int i = 0; i < constrainedCount; ++i)
  632. {
  633. if (m_Flags[i] == 1)
  634. {
  635. cellsOut[cellCount++] = constrained[i];
  636. }
  637. }
  638. constrained.Dispose();
  639. return cellsOut;
  640. }
  641. internal bool Triangulate(NativeArray<float2> points, int pointCount, NativeArray<int2> edges, int edgeCount)
  642. {
  643. m_NumEdges = edgeCount;
  644. m_NumHulls = edgeCount * 2;
  645. m_NumPoints = pointCount;
  646. m_CellCount = 0;
  647. int allocSize = m_NumHulls * (m_NumHulls + 1);
  648. m_Cells = new Array<int3>(allocSize, ModuleHandle.kMaxTriangleCount, m_Allocator, NativeArrayOptions.UninitializedMemory);
  649. m_ILArray = new NativeArray<int>(allocSize, m_Allocator); // Make room for -1 node.
  650. m_IUArray = new NativeArray<int>(allocSize, m_Allocator); // Make room for -1 node.
  651. NativeArray<UHull> hulls = new NativeArray<UHull>(m_NumPoints * 8, m_Allocator);
  652. int hullCount = 0;
  653. NativeArray<UEvent> events = new NativeArray<UEvent>(m_NumPoints + (m_NumEdges * 2), m_Allocator);
  654. int eventCount = 0;
  655. for (int i = 0; i < m_NumPoints; ++i)
  656. {
  657. UEvent evt = new UEvent();
  658. evt.a = points[i];
  659. evt.b = new float2();
  660. evt.idx = i;
  661. evt.type = (int)UEventType.EVENT_POINT;
  662. events[eventCount++] = evt;
  663. }
  664. for (int i = 0; i < m_NumEdges; ++i)
  665. {
  666. int2 e = edges[i];
  667. float2 a = points[e.x];
  668. float2 b = points[e.y];
  669. if (a.x < b.x)
  670. {
  671. UEvent _s = new UEvent();
  672. _s.a = a;
  673. _s.b = b;
  674. _s.idx = i;
  675. _s.type = (int)UEventType.EVENT_START;
  676. UEvent _e = new UEvent();
  677. _e.a = b;
  678. _e.b = a;
  679. _e.idx = i;
  680. _e.type = (int)UEventType.EVENT_END;
  681. events[eventCount++] = _s;
  682. events[eventCount++] = _e;
  683. }
  684. else if (a.x > b.x)
  685. {
  686. UEvent _s = new UEvent();
  687. _s.a = b;
  688. _s.b = a;
  689. _s.idx = i;
  690. _s.type = (int)UEventType.EVENT_START;
  691. UEvent _e = new UEvent();
  692. _e.a = a;
  693. _e.b = b;
  694. _e.idx = i;
  695. _e.type = (int)UEventType.EVENT_END;
  696. events[eventCount++] = _s;
  697. events[eventCount++] = _e;
  698. }
  699. }
  700. unsafe
  701. {
  702. ModuleHandle.InsertionSort<UEvent, TessEventCompare>(
  703. NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(events), 0, eventCount - 1,
  704. new TessEventCompare());
  705. ;
  706. }
  707. var hullOp = true;
  708. float minX = events[0].a.x - (1 + math.abs(events[0].a.x)) * math.pow(2.0f, -16.0f);
  709. UHull hull;
  710. hull.a.x = minX;
  711. hull.a.y = 1;
  712. hull.b.x = minX;
  713. hull.b.y = 0;
  714. hull.idx = -1;
  715. hull.ilarray = new ArraySlice<int>(m_ILArray, m_NumHulls * m_NumHulls, m_NumHulls); // Last element
  716. hull.iuarray = new ArraySlice<int>(m_IUArray, m_NumHulls * m_NumHulls, m_NumHulls);
  717. hull.ilcount = 0;
  718. hull.iucount = 0;
  719. hulls[hullCount++] = hull;
  720. for (int i = 0, numEvents = eventCount; i < numEvents; ++i)
  721. {
  722. switch (events[i].type)
  723. {
  724. case (int) UEventType.EVENT_POINT:
  725. {
  726. hullOp = AddPoint(hulls, hullCount, points, events[i].a, events[i].idx);
  727. }
  728. break;
  729. case (int) UEventType.EVENT_START:
  730. {
  731. hullOp = SplitHulls(hulls, ref hullCount, points, events[i]);
  732. }
  733. break;
  734. default:
  735. {
  736. hullOp = MergeHulls(hulls, ref hullCount, points, events[i]);
  737. }
  738. break;
  739. }
  740. if (!hullOp)
  741. break;
  742. }
  743. events.Dispose();
  744. hulls.Dispose();
  745. return hullOp;
  746. }
  747. internal static bool Tessellate(Allocator allocator, NativeArray<float2> pgPoints, int pgPointCount, NativeArray<int2> pgEdges, int pgEdgeCount, ref NativeArray<float2> outputVertices, ref int vertexCount, ref NativeArray<int> outputIndices, ref int indexCount)
  748. {
  749. // Process.
  750. Tessellator tess = new Tessellator();
  751. tess.SetAllocator(allocator);
  752. int maxCount = 0, triCount = 0;
  753. var valid = true;
  754. valid = tess.Triangulate(pgPoints, pgPointCount, pgEdges, pgEdgeCount);
  755. valid = valid && tess.ApplyDelaunay(pgPoints, pgEdges);
  756. if (valid)
  757. {
  758. // Output.
  759. NativeArray<int3> cells = tess.RemoveExterior(ref triCount);
  760. for (var i = 0; i < triCount; ++i)
  761. {
  762. var a = (UInt16)cells[i].x;
  763. var b = (UInt16)cells[i].y;
  764. var c = (UInt16)cells[i].z;
  765. if (a != b && b != c && a != c)
  766. {
  767. outputIndices[indexCount++] = a;
  768. outputIndices[indexCount++] = c;
  769. outputIndices[indexCount++] = b;
  770. }
  771. maxCount = math.max(math.max(math.max(cells[i].x, cells[i].y), cells[i].z), maxCount);
  772. }
  773. maxCount = (maxCount != 0) ? (maxCount + 1) : 0;
  774. for (var i = 0; i < maxCount; ++i)
  775. outputVertices[vertexCount++] = pgPoints[i];
  776. cells.Dispose();
  777. }
  778. tess.Cleanup();
  779. return valid;
  780. }
  781. internal void Cleanup()
  782. {
  783. if (m_Edges.IsCreated) m_Edges.Dispose();
  784. if (m_Stars.IsCreated) m_Stars.Dispose();
  785. if (m_SPArray.IsCreated) m_SPArray.Dispose();
  786. if (m_Cells.IsCreated) m_Cells.Dispose();
  787. if (m_ILArray.IsCreated) m_ILArray.Dispose();
  788. if (m_IUArray.IsCreated) m_IUArray.Dispose();
  789. if (m_Flags.IsCreated) m_Flags.Dispose();
  790. if (m_Neighbors.IsCreated) m_Neighbors.Dispose();
  791. if (m_Constraints.IsCreated) m_Constraints.Dispose();
  792. }
  793. }
  794. }