Tessellator.cs 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117
  1. using System;
  2. using System.Collections.Generic;
  3. using Unity.Collections;
  4. using Unity.Mathematics;
  5. using Unity.Collections.LowLevel.Unsafe;
  6. namespace UnityEngine.U2D
  7. {
  8. namespace UTess
  9. {
  10. enum TessEventType
  11. {
  12. EVENT_POINT = 0,
  13. EVENT_END = 1,
  14. EVENT_START = 2,
  15. };
  16. struct TessEdge
  17. {
  18. public int a;
  19. public int b;
  20. };
  21. struct TessEvent
  22. {
  23. public float2 a;
  24. public float2 b;
  25. public int idx;
  26. public int type;
  27. };
  28. struct TessHull
  29. {
  30. public float2 a;
  31. public float2 b;
  32. public int idx;
  33. public ArraySlice<int> ilarray;
  34. public int ilcount;
  35. public ArraySlice<int> iuarray;
  36. public int iucount;
  37. };
  38. struct TessCell
  39. {
  40. public int a;
  41. public int b;
  42. public int c;
  43. };
  44. struct TessStar
  45. {
  46. public ArraySlice<int> points;
  47. public int pointCount;
  48. };
  49. internal struct TessUtils
  50. {
  51. // From https://www.cs.cmu.edu/afs/cs/project/quake/public/code/predicates.c and is public domain. Can't find one within Unity.
  52. public static float OrientFast(float2 a, float2 b, float2 c)
  53. {
  54. float epsilon = 1.1102230246251565e-16f;
  55. float errbound3 = (3.0f + 16.0f * epsilon) * epsilon;
  56. float l = (a.y - c.y) * (b.x - c.x);
  57. float r = (a.x - c.x) * (b.y - c.y);
  58. float det = l - r;
  59. float s = 0;
  60. if (l > 0)
  61. {
  62. if (r <= 0)
  63. {
  64. return det;
  65. }
  66. else
  67. {
  68. s = l + r;
  69. }
  70. }
  71. else if (l < 0)
  72. {
  73. if (r >= 0)
  74. {
  75. return det;
  76. }
  77. else
  78. {
  79. s = -(l + r);
  80. }
  81. }
  82. else
  83. {
  84. return det;
  85. }
  86. float tol = errbound3 * s;
  87. if (det >= tol || det <= -tol)
  88. {
  89. return det;
  90. }
  91. return epsilon;
  92. }
  93. public static float Norm(float2 cV)
  94. {
  95. return cV.x * cV.x + cV.y * cV.y;
  96. }
  97. public static float Dist(float2 cV1, float2 cV2)
  98. {
  99. return (cV1.x - cV2.x) * (cV1.x - cV2.x) + (cV1.y - cV2.y) * (cV1.y - cV2.y);
  100. }
  101. public static bool IsInsideCircle(float2 a, float2 b, float2 c, float2 p)
  102. {
  103. float ab = Norm(a);
  104. float cd = Norm(b);
  105. float ef = Norm(c);
  106. float ax = a.x;
  107. float ay = a.y;
  108. float bx = b.x;
  109. float by = b.y;
  110. float cx = c.x;
  111. float cy = c.y;
  112. float circum_x = (ab * (cy - by) + cd * (ay - cy) + ef * (by - ay)) /
  113. (ax * (cy - by) + bx * (ay - cy) + cx * (by - ay));
  114. float circum_y = (ab * (cx - bx) + cd * (ax - cx) + ef * (bx - ax)) /
  115. (ay * (cx - bx) + by * (ax - cx) + cy * (bx - ax));
  116. float2 circum = new float2();
  117. circum.x = circum_x / 2;
  118. circum.y = circum_y / 2;
  119. float circum_radius = Dist(a, circum);
  120. float dist = Dist(p, circum);
  121. return circum_radius - dist > 0.00001f;
  122. }
  123. public unsafe static void InsertionSort<T, U>(void* array, int lo, int hi, U comp)
  124. where T : struct where U : IComparer<T>
  125. {
  126. int i, j;
  127. T t;
  128. for (i = lo; i < hi; i++)
  129. {
  130. j = i;
  131. t = UnsafeUtility.ReadArrayElement<T>(array, i + 1);
  132. while (j >= lo && comp.Compare(t, UnsafeUtility.ReadArrayElement<T>(array, j)) < 0)
  133. {
  134. UnsafeUtility.WriteArrayElement<T>(array, j + 1, UnsafeUtility.ReadArrayElement<T>(array, j));
  135. j--;
  136. }
  137. UnsafeUtility.WriteArrayElement<T>(array, j + 1, t);
  138. }
  139. }
  140. }
  141. struct TessEventCompare : IComparer<TessEvent>
  142. {
  143. public int Compare(TessEvent a, TessEvent b)
  144. {
  145. float f = (a.a.x - b.a.x);
  146. if (0 != f)
  147. return (f > 0) ? 1 : -1;
  148. f = (a.a.y - b.a.y);
  149. if (0 != f)
  150. return (f > 0) ? 1 : -1;
  151. int i = a.type - b.type;
  152. if (0 != i)
  153. return i;
  154. if (a.type != (int) TessEventType.EVENT_POINT)
  155. {
  156. float o = TessUtils.OrientFast(a.a, a.b, b.b);
  157. if (0 != o)
  158. {
  159. return (o > 0) ? 1 : -1;
  160. }
  161. }
  162. return a.idx - b.idx;
  163. }
  164. }
  165. struct TessEdgeCompare : IComparer<TessEdge>
  166. {
  167. public int Compare(TessEdge a, TessEdge b)
  168. {
  169. int i = a.a - b.a;
  170. if (0 != i)
  171. return i;
  172. i = a.b - b.b;
  173. return i;
  174. }
  175. }
  176. struct TessCellCompare : IComparer<TessCell>
  177. {
  178. public int Compare(TessCell a, TessCell b)
  179. {
  180. int i = a.a - b.a;
  181. if (0 != i)
  182. return i;
  183. i = a.b - b.b;
  184. if (0 != i)
  185. return i;
  186. i = a.c - b.c;
  187. return i;
  188. }
  189. }
  190. internal struct Tessellator
  191. {
  192. // For Processing.
  193. NativeArray<TessEdge> m_Edges;
  194. NativeArray<TessStar> m_Stars;
  195. NativeArray<TessCell> m_Cells;
  196. int m_CellCount;
  197. // For Storage.
  198. NativeArray<int> m_ILArray;
  199. NativeArray<int> m_IUArray;
  200. NativeArray<int> m_SPArray;
  201. int m_NumPoints;
  202. int m_StarCount;
  203. // Intermediates.
  204. NativeArray<int> m_Flags;
  205. NativeArray<int> m_Neighbors;
  206. NativeArray<int> m_Constraints;
  207. static float TestPoint(TessHull hull, float2 point)
  208. {
  209. return TessUtils.OrientFast(hull.a, hull.b, point);
  210. }
  211. static int GetLowerHullForVector(NativeArray<TessHull> hulls, int hullCount, float2 p)
  212. {
  213. int i;
  214. int l = 0;
  215. int h = hullCount - 1;
  216. i = l - 1;
  217. while (l <= h)
  218. {
  219. int m;
  220. m = ((int) (l + h)) >> 1;
  221. if (TestPoint(hulls[m], p) < 0)
  222. {
  223. i = m;
  224. l = m + 1;
  225. }
  226. else
  227. h = m - 1;
  228. }
  229. return i;
  230. }
  231. static int GetUpperHullForVector(NativeArray<TessHull> hulls, int hullCount, float2 p)
  232. {
  233. int i;
  234. int l = 0;
  235. int h = hullCount - 1;
  236. i = h + 1;
  237. while (l <= h)
  238. {
  239. int m;
  240. m = ((int) (l + h)) >> 1;
  241. if (TestPoint(hulls[m], p) > 0)
  242. {
  243. i = m;
  244. h = m - 1;
  245. }
  246. else
  247. l = m + 1;
  248. }
  249. return i;
  250. }
  251. static float FindSplit(TessHull hull, TessEvent edge)
  252. {
  253. float d = 0;
  254. if (hull.a.x < edge.a.x)
  255. {
  256. d = TessUtils.OrientFast(hull.a, hull.b, edge.a);
  257. }
  258. else
  259. {
  260. d = TessUtils.OrientFast(edge.b, edge.a, hull.a);
  261. }
  262. if (0 != d)
  263. {
  264. return d;
  265. }
  266. if (edge.b.x < hull.b.x)
  267. {
  268. d = TessUtils.OrientFast(hull.a, hull.b, edge.b);
  269. }
  270. else
  271. {
  272. d = TessUtils.OrientFast(edge.b, edge.a, hull.b);
  273. }
  274. if (0 != d)
  275. {
  276. return d;
  277. }
  278. return hull.idx - edge.idx;
  279. }
  280. static int GetLowerEqualHullForEvent(NativeArray<TessHull> hulls, int hullCount, TessEvent p)
  281. {
  282. int i;
  283. int l = 0;
  284. int h = hullCount - 1;
  285. i = l - 1;
  286. while (l <= h)
  287. {
  288. int m;
  289. m = ((int) (l + h)) >> 1;
  290. if (FindSplit(hulls[m], p) <= 0)
  291. {
  292. i = m;
  293. l = m + 1;
  294. }
  295. else
  296. h = m - 1;
  297. }
  298. return i;
  299. }
  300. static int GetEqualHullForEvent(NativeArray<TessHull> hulls, int hullCount, TessEvent p)
  301. {
  302. int l = 0;
  303. int h = hullCount - 1;
  304. while (l <= h)
  305. {
  306. int m;
  307. m = ((int) (l + h)) >> 1;
  308. float f = FindSplit(hulls[m], p);
  309. if (f == 0)
  310. {
  311. return m;
  312. }
  313. else if (f <= 0)
  314. {
  315. l = m + 1;
  316. }
  317. else
  318. h = m - 1;
  319. }
  320. return -1;
  321. }
  322. void AddPoint(NativeArray<TessHull> hulls, int hullCount, NativeArray<float2> points, float2 p,
  323. int idx)
  324. {
  325. int l = GetLowerHullForVector(hulls, hullCount, p);
  326. int u = GetUpperHullForVector(hulls, hullCount, p);
  327. for (int i = l; i < u; ++i)
  328. {
  329. TessHull hull = hulls[i];
  330. int m = hull.ilcount;
  331. while (m > 1 && TessUtils.OrientFast(points[hull.ilarray[m - 2]], points[hull.ilarray[m - 1]], p) >
  332. 0)
  333. {
  334. TessCell c = new TessCell();
  335. c.a = hull.ilarray[m - 1];
  336. c.b = hull.ilarray[m - 2];
  337. c.c = idx;
  338. m_Cells[m_CellCount++] = c;
  339. m -= 1;
  340. }
  341. hull.ilcount = m + 1;
  342. hull.ilarray[m] = idx;
  343. m = hull.iucount;
  344. while (m > 1 && TessUtils.OrientFast(points[hull.iuarray[m - 2]], points[hull.iuarray[m - 1]], p) <
  345. 0)
  346. {
  347. TessCell c = new TessCell();
  348. c.a = hull.iuarray[m - 2];
  349. c.b = hull.iuarray[m - 1];
  350. c.c = idx;
  351. m_Cells[m_CellCount++] = c;
  352. m -= 1;
  353. }
  354. hull.iucount = m + 1;
  355. hull.iuarray[m] = idx;
  356. hulls[i] = hull;
  357. }
  358. }
  359. static void InsertHull(NativeArray<TessHull> Hulls, int Pos, ref int Count, TessHull Value)
  360. {
  361. if (Count < Hulls.Length - 1)
  362. {
  363. for (int i = Count; i > Pos; --i)
  364. Hulls[i] = Hulls[i - 1];
  365. Hulls[Pos] = Value;
  366. Count++;
  367. }
  368. }
  369. static void EraseHull(NativeArray<TessHull> Hulls, int Pos, ref int Count)
  370. {
  371. if (Count < Hulls.Length)
  372. {
  373. for (int i = Pos; i < Count - 1; ++i)
  374. Hulls[i] = Hulls[i + 1];
  375. Count--;
  376. }
  377. }
  378. void SplitHulls(NativeArray<TessHull> hulls, ref int hullCount, NativeArray<float2> points,
  379. TessEvent evt)
  380. {
  381. int index = GetLowerEqualHullForEvent(hulls, hullCount, evt);
  382. TessHull hull = hulls[index];
  383. TessHull newHull;
  384. newHull.a = evt.a;
  385. newHull.b = evt.b;
  386. newHull.idx = evt.idx;
  387. int y = hull.iuarray[hull.iucount - 1];
  388. newHull.iuarray = new ArraySlice<int>(m_IUArray, newHull.idx * m_NumPoints, m_NumPoints);
  389. newHull.iucount = hull.iucount;
  390. for (int i = 0; i < newHull.iucount; ++i)
  391. newHull.iuarray[i] = hull.iuarray[i];
  392. hull.iuarray[0] = y;
  393. hull.iucount = 1;
  394. hulls[index] = hull;
  395. newHull.ilarray = new ArraySlice<int>(m_ILArray, newHull.idx * m_NumPoints, m_NumPoints);
  396. newHull.ilarray[0] = y;
  397. newHull.ilcount = 1;
  398. InsertHull(hulls, index + 1, ref hullCount, newHull);
  399. }
  400. void MergeHulls(NativeArray<TessHull> hulls, ref int hullCount, NativeArray<float2> points,
  401. TessEvent evt)
  402. {
  403. float2 temp = evt.a;
  404. evt.a = evt.b;
  405. evt.b = temp;
  406. int index = GetEqualHullForEvent(hulls, hullCount, evt);
  407. TessHull upper = hulls[index];
  408. TessHull lower = hulls[index - 1];
  409. lower.iucount = upper.iucount;
  410. for (int i = 0; i < lower.iucount; ++i)
  411. lower.iuarray[i] = upper.iuarray[i];
  412. hulls[index - 1] = lower;
  413. EraseHull(hulls, index, ref hullCount);
  414. }
  415. internal void Triangulate(NativeArray<float2> points, NativeArray<TessEdge> edgesIn)
  416. {
  417. int numEdges = edgesIn.Length;
  418. const int kStarEdges = 16;
  419. m_NumPoints = points.Length;
  420. m_StarCount = m_NumPoints > kStarEdges ? m_NumPoints : kStarEdges;
  421. m_StarCount = m_StarCount * 2;
  422. m_CellCount = 0;
  423. m_Cells = new NativeArray<TessCell>(m_NumPoints * (m_NumPoints + 1), Allocator.Temp);
  424. m_ILArray = new NativeArray<int>(m_NumPoints * (m_NumPoints + 1), Allocator.Temp); // Make room for -1 node.
  425. m_IUArray = new NativeArray<int>(m_NumPoints * (m_NumPoints + 1), Allocator.Temp); // Make room for -1 node.
  426. m_SPArray = new NativeArray<int>(m_NumPoints * (m_StarCount), Allocator.Temp); // Make room for -1 node.
  427. NativeArray<TessHull> hulls = new NativeArray<TessHull>(m_NumPoints * 8, Allocator.Temp);
  428. int hullCount = 0;
  429. NativeArray<TessEvent> events = new NativeArray<TessEvent>(m_NumPoints + (numEdges * 2), Allocator.Temp);
  430. int eventCount = 0;
  431. for (int i = 0; i < m_NumPoints; ++i)
  432. {
  433. TessEvent evt = new TessEvent();
  434. evt.a = points[i];
  435. evt.b = new float2();
  436. evt.idx = i;
  437. evt.type = (int) TessEventType.EVENT_POINT;
  438. events[eventCount++] = evt;
  439. }
  440. for (int i = 0; i < numEdges; ++i)
  441. {
  442. TessEdge e = edgesIn[i];
  443. float2 a = points[e.a];
  444. float2 b = points[e.b];
  445. if (a.x < b.x)
  446. {
  447. TessEvent _s = new TessEvent();
  448. _s.a = a;
  449. _s.b = b;
  450. _s.idx = i;
  451. _s.type = (int) TessEventType.EVENT_START;
  452. TessEvent _e = new TessEvent();
  453. _e.a = b;
  454. _e.b = a;
  455. _e.idx = i;
  456. _e.type = (int) TessEventType.EVENT_END;
  457. events[eventCount++] = _s;
  458. events[eventCount++] = _e;
  459. }
  460. else if (a.x > b.x)
  461. {
  462. TessEvent _s = new TessEvent();
  463. _s.a = b;
  464. _s.b = a;
  465. _s.idx = i;
  466. _s.type = (int) TessEventType.EVENT_START;
  467. TessEvent _e = new TessEvent();
  468. _e.a = a;
  469. _e.b = b;
  470. _e.idx = i;
  471. _e.type = (int) TessEventType.EVENT_END;
  472. events[eventCount++] = _s;
  473. events[eventCount++] = _e;
  474. }
  475. }
  476. unsafe
  477. {
  478. TessUtils.InsertionSort<TessEvent, TessEventCompare>(
  479. NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(events), 0, eventCount - 1,
  480. new TessEventCompare());
  481. ;
  482. }
  483. float minX = events[0].a.x - (1 + math.abs(events[0].a.x)) * math.pow(2.0f, -16.0f);
  484. TessHull hull;
  485. hull.a.x = minX;
  486. hull.a.y = 1;
  487. hull.b.x = minX;
  488. hull.b.y = 0;
  489. hull.idx = -1;
  490. hull.ilarray = new ArraySlice<int>(m_ILArray, m_NumPoints * m_NumPoints, m_NumPoints); // Last element
  491. hull.iuarray = new ArraySlice<int>(m_IUArray, m_NumPoints * m_NumPoints, m_NumPoints);
  492. hull.ilcount = 0;
  493. hull.iucount = 0;
  494. hulls[hullCount++] = hull;
  495. for (int i = 0, numEvents = eventCount; i < numEvents; ++i)
  496. {
  497. switch (events[i].type)
  498. {
  499. case (int) TessEventType.EVENT_POINT:
  500. {
  501. AddPoint(hulls, hullCount, points, events[i].a, events[i].idx);
  502. }
  503. break;
  504. case (int) TessEventType.EVENT_START:
  505. {
  506. SplitHulls(hulls, ref hullCount, points, events[i]);
  507. }
  508. break;
  509. default:
  510. {
  511. MergeHulls(hulls, ref hullCount, points, events[i]);
  512. }
  513. break;
  514. }
  515. }
  516. hulls.Dispose();
  517. events.Dispose();
  518. }
  519. void Prepare(NativeArray<TessEdge> edgesIn)
  520. {
  521. m_Stars = new NativeArray<TessStar>(edgesIn.Length, Allocator.Temp);
  522. for (int i = 0; i < edgesIn.Length; ++i)
  523. {
  524. TessEdge e = edgesIn[i];
  525. e.a = (edgesIn[i].a < edgesIn[i].b) ? edgesIn[i].a : edgesIn[i].b;
  526. e.b = (edgesIn[i].a > edgesIn[i].b) ? edgesIn[i].a : edgesIn[i].b;
  527. edgesIn[i] = e;
  528. TessStar s = m_Stars[i];
  529. s.points = new ArraySlice<int>(m_SPArray, i * m_StarCount, m_StarCount);
  530. s.pointCount = 0;
  531. m_Stars[i] = s;
  532. }
  533. unsafe
  534. {
  535. TessUtils.InsertionSort<TessEdge, TessEdgeCompare>(
  536. NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(edgesIn), 0, edgesIn.Length - 1,
  537. new TessEdgeCompare());
  538. }
  539. m_Edges = new NativeArray<TessEdge>(edgesIn.Length, Allocator.Temp);
  540. m_Edges.CopyFrom(edgesIn);
  541. // Fill stars.
  542. for (int i = 0; i < m_CellCount; ++i)
  543. {
  544. int a = m_Cells[i].a;
  545. int b = m_Cells[i].b;
  546. int c = m_Cells[i].c;
  547. TessStar sa = m_Stars[a];
  548. TessStar sb = m_Stars[b];
  549. TessStar sc = m_Stars[c];
  550. sa.points[sa.pointCount++] = b;
  551. sa.points[sa.pointCount++] = c;
  552. sb.points[sb.pointCount++] = c;
  553. sb.points[sb.pointCount++] = a;
  554. sc.points[sc.pointCount++] = a;
  555. sc.points[sc.pointCount++] = b;
  556. m_Stars[a] = sa;
  557. m_Stars[b] = sb;
  558. m_Stars[c] = sc;
  559. }
  560. }
  561. int OppositeOf(int a, int b)
  562. {
  563. ArraySlice<int> points = m_Stars[b].points;
  564. for (int k = 1, n = m_Stars[b].pointCount; k < n; k += 2)
  565. {
  566. if (points[k] == a)
  567. {
  568. return points[k - 1];
  569. }
  570. }
  571. return -1;
  572. }
  573. static int GetEqualHullForEdges(NativeArray<TessEdge> edges, TessEdge p)
  574. {
  575. int l = 0;
  576. int h = edges.Length - 1;
  577. TessEdgeCompare tec = new TessEdgeCompare();
  578. while (l <= h)
  579. {
  580. int m;
  581. m = ((int) (l + h)) >> 1;
  582. int f = tec.Compare(edges[m], p);
  583. if (f == 0)
  584. {
  585. return m;
  586. }
  587. else if (f <= 0)
  588. {
  589. l = m + 1;
  590. }
  591. else
  592. h = m - 1;
  593. }
  594. return -1;
  595. }
  596. int FindConstraint(int a, int b)
  597. {
  598. TessEdge e;
  599. e.a = a < b ? a : b;
  600. e.b = a > b ? a : b;
  601. return GetEqualHullForEdges(m_Edges, e);
  602. }
  603. void AddTriangle(int i, int j, int k)
  604. {
  605. TessStar si = m_Stars[i];
  606. TessStar sj = m_Stars[j];
  607. TessStar sk = m_Stars[k];
  608. si.points[si.pointCount++] = j;
  609. si.points[si.pointCount++] = k;
  610. sj.points[sj.pointCount++] = k;
  611. sj.points[sj.pointCount++] = i;
  612. sk.points[sk.pointCount++] = i;
  613. sk.points[sk.pointCount++] = j;
  614. m_Stars[i] = si;
  615. m_Stars[j] = sj;
  616. m_Stars[k] = sk;
  617. }
  618. void RemovePair(int r, int j, int k)
  619. {
  620. TessStar s = m_Stars[r];
  621. ArraySlice<int> points = s.points;
  622. for (int i = 1, n = s.pointCount; i < n; i += 2)
  623. {
  624. if (points[i - 1] == j && points[i] == k)
  625. {
  626. points[i - 1] = points[n - 2];
  627. points[i] = points[n - 1];
  628. s.points = points;
  629. s.pointCount = s.pointCount - 2;
  630. m_Stars[r] = s;
  631. return;
  632. }
  633. }
  634. }
  635. void RemoveTriangle(int i, int j, int k)
  636. {
  637. RemovePair(i, j, k);
  638. RemovePair(j, k, i);
  639. RemovePair(k, i, j);
  640. }
  641. void EdgeFlip(int i, int j)
  642. {
  643. int a = OppositeOf(i, j);
  644. int b = OppositeOf(j, i);
  645. RemoveTriangle(i, j, a);
  646. RemoveTriangle(j, i, b);
  647. AddTriangle(i, b, a);
  648. AddTriangle(j, a, b);
  649. }
  650. void Flip(NativeArray<float2> points, ref NativeArray<int> stack, ref int stackCount,
  651. int a, int b, int x)
  652. {
  653. int y = OppositeOf(a, b);
  654. if (y < 0)
  655. {
  656. return;
  657. }
  658. if (b < a)
  659. {
  660. int tmp = a;
  661. a = b;
  662. b = tmp;
  663. tmp = x;
  664. x = y;
  665. y = tmp;
  666. }
  667. if (FindConstraint(a, b) != -1)
  668. {
  669. return;
  670. }
  671. if (TessUtils.IsInsideCircle(points[a], points[b], points[x], points[y]))
  672. {
  673. stack[stackCount++] = a;
  674. stack[stackCount++] = b;
  675. }
  676. }
  677. NativeArray<TessCell> GetCells(ref int count)
  678. {
  679. NativeArray<TessCell> cellsOut = new NativeArray<TessCell>(m_NumPoints * (m_NumPoints + 1), Allocator.Temp);
  680. count = 0;
  681. for (int i = 0, n = m_Stars.Length; i < n; ++i)
  682. {
  683. ArraySlice<int> points = m_Stars[i].points;
  684. for (int j = 0, m = m_Stars[i].pointCount; j < m; j += 2)
  685. {
  686. int s = points[j];
  687. int t = points[j + 1];
  688. if (i < math.min(s, t))
  689. {
  690. TessCell c = new TessCell();
  691. c.a = i;
  692. c.b = s;
  693. c.c = t;
  694. cellsOut[count++] = c;
  695. }
  696. }
  697. }
  698. return cellsOut;
  699. }
  700. internal void ApplyDelaunay(NativeArray<float2> points, NativeArray<TessEdge> edgesIn)
  701. {
  702. NativeArray<int> stack = new NativeArray<int>(m_NumPoints * (m_NumPoints + 1), Allocator.Temp);
  703. int stackCount = 0;
  704. Prepare(edgesIn);
  705. for (int a = 0; a < m_NumPoints; ++a)
  706. {
  707. TessStar star = m_Stars[a];
  708. for (int j = 1; j < star.pointCount; j += 2)
  709. {
  710. int b = star.points[j];
  711. if (b < a)
  712. {
  713. continue;
  714. }
  715. if (FindConstraint(a, b) >= 0)
  716. {
  717. continue;
  718. }
  719. int x = star.points[j - 1], y = -1;
  720. for (int k = 1; k < star.pointCount; k += 2)
  721. {
  722. if (star.points[k - 1] == b)
  723. {
  724. y = star.points[k];
  725. break;
  726. }
  727. }
  728. if (y < 0)
  729. {
  730. continue;
  731. }
  732. if (TessUtils.IsInsideCircle(points[a], points[b], points[x], points[y]))
  733. {
  734. stack[stackCount++] = a;
  735. stack[stackCount++] = b;
  736. }
  737. }
  738. }
  739. while (stackCount > 0)
  740. {
  741. int b = stack[stackCount - 1];
  742. stackCount--;
  743. int a = stack[stackCount - 1];
  744. stackCount--;
  745. int x = -1, y = -1;
  746. TessStar star = m_Stars[a];
  747. for (int i = 1; i < star.pointCount; i += 2)
  748. {
  749. int s = star.points[i - 1];
  750. int t = star.points[i];
  751. if (s == b)
  752. {
  753. y = t;
  754. }
  755. else if (t == b)
  756. {
  757. x = s;
  758. }
  759. }
  760. if (x < 0 || y < 0)
  761. {
  762. continue;
  763. }
  764. if (!TessUtils.IsInsideCircle(points[a], points[b], points[x], points[y]))
  765. {
  766. continue;
  767. }
  768. EdgeFlip(a, b);
  769. Flip(points, ref stack, ref stackCount, x, a, y);
  770. Flip(points, ref stack, ref stackCount, a, y, x);
  771. Flip(points, ref stack, ref stackCount, y, b, x);
  772. Flip(points, ref stack, ref stackCount, b, x, y);
  773. }
  774. stack.Dispose();
  775. }
  776. int GetEqualCellForCells(NativeArray<TessCell> cells, int count, TessCell p)
  777. {
  778. int l = 0;
  779. int h = count - 1;
  780. TessCellCompare tcc = new TessCellCompare();
  781. while (l <= h)
  782. {
  783. int m;
  784. m = ((int) (l + h)) >> 1;
  785. int f = tcc.Compare(cells[m], p);
  786. if (f == 0)
  787. {
  788. return m;
  789. }
  790. else if (f <= 0)
  791. {
  792. l = m + 1;
  793. }
  794. else
  795. h = m - 1;
  796. }
  797. return -1;
  798. }
  799. int FindNeighbor(NativeArray<TessCell> cells, int count, int a, int b, int c)
  800. {
  801. int x = a, y = b, z = c;
  802. if (b < c)
  803. {
  804. if (b < a)
  805. {
  806. x = b;
  807. y = c;
  808. z = a;
  809. }
  810. }
  811. else if (c < a)
  812. {
  813. x = c;
  814. y = a;
  815. z = b;
  816. }
  817. if (x < 0)
  818. {
  819. return -1;
  820. }
  821. TessCell key;
  822. key.a = x;
  823. key.b = y;
  824. key.c = z;
  825. return GetEqualCellForCells(cells, count, key);
  826. }
  827. NativeArray<TessCell> Constrain(ref int count)
  828. {
  829. var cells = GetCells(ref count);
  830. int nc = count;
  831. for (int i = 0; i < nc; ++i)
  832. {
  833. TessCell c = cells[i];
  834. int x = c.a, y = c.b, z = c.c;
  835. if (y < z)
  836. {
  837. if (y < x)
  838. {
  839. c.a = y;
  840. c.b = z;
  841. c.c = x;
  842. }
  843. }
  844. else if (z < x)
  845. {
  846. c.a = z;
  847. c.b = x;
  848. c.c = y;
  849. }
  850. cells[i] = c;
  851. }
  852. unsafe
  853. {
  854. TessUtils.InsertionSort<TessCell, TessCellCompare>(
  855. NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(cells), 0, m_CellCount - 1,
  856. new TessCellCompare());
  857. }
  858. // Out
  859. m_Flags = new NativeArray<int>(nc, Allocator.Temp);
  860. m_Neighbors = new NativeArray<int>(nc * 3, Allocator.Temp);
  861. m_Constraints = new NativeArray<int>(nc * 3, Allocator.Temp);
  862. var next = new NativeArray<int>(nc * 3, Allocator.Temp);
  863. var active = new NativeArray<int>(nc * 3, Allocator.Temp);
  864. int side = 1, nextCount = 0, activeCount = 0;
  865. for (int i = 0; i < nc; ++i)
  866. {
  867. TessCell c = cells[i];
  868. for (int j = 0; j < 3; ++j)
  869. {
  870. int x = j, y = (j + 1) % 3;
  871. x = (x == 0) ? c.a : (j == 1) ? c.b : c.c;
  872. y = (y == 0) ? c.a : (y == 1) ? c.b : c.c;
  873. int o = OppositeOf(y, x);
  874. int a = m_Neighbors[3 * i + j] = FindNeighbor(cells, count, y, x, o);
  875. int b = m_Constraints[3 * i + j] = (-1 != FindConstraint(x, y)) ? 1 : 0;
  876. if (a < 0)
  877. {
  878. if (0 != b)
  879. {
  880. next[nextCount++] = i;
  881. }
  882. else
  883. {
  884. active[activeCount++] = i;
  885. m_Flags[i] = 1;
  886. }
  887. }
  888. }
  889. }
  890. while (activeCount > 0 || nextCount > 0)
  891. {
  892. while (activeCount > 0)
  893. {
  894. int t = active[activeCount - 1];
  895. activeCount--;
  896. if (m_Flags[t] == -side)
  897. {
  898. continue;
  899. }
  900. m_Flags[t] = side;
  901. TessCell c = cells[t];
  902. for (int j = 0; j < 3; ++j)
  903. {
  904. int f = m_Neighbors[3 * t + j];
  905. if (f >= 0 && m_Flags[f] == 0)
  906. {
  907. if (0 != m_Constraints[3 * t + j])
  908. {
  909. next[nextCount++] = f;
  910. }
  911. else
  912. {
  913. active[activeCount++] = f;
  914. m_Flags[f] = side;
  915. }
  916. }
  917. }
  918. }
  919. for (int e = 0; e < nextCount; e++)
  920. active[e] = next[e];
  921. activeCount = nextCount;
  922. nextCount = 0;
  923. side = -side;
  924. }
  925. active.Dispose();
  926. next.Dispose();
  927. return cells;
  928. }
  929. internal NativeArray<TessCell> RemoveExterior(ref int cellCount)
  930. {
  931. int constrainedCount = 0;
  932. NativeArray<TessCell> constrained = Constrain(ref constrainedCount);
  933. NativeArray<TessCell> cellsOut = new NativeArray<TessCell>(constrainedCount, Allocator.Temp);
  934. cellCount = 0;
  935. for (int i = 0; i < constrainedCount; ++i)
  936. {
  937. if (m_Flags[i] == -1)
  938. {
  939. cellsOut[cellCount++] = constrained[i];
  940. }
  941. }
  942. constrained.Dispose();
  943. return cellsOut;
  944. }
  945. internal NativeArray<TessCell> RemoveInterior(int cellCount)
  946. {
  947. int constrainedCount = 0;
  948. NativeArray<TessCell> constrained = Constrain(ref constrainedCount);
  949. NativeArray<TessCell> cellsOut = new NativeArray<TessCell>(constrainedCount, Allocator.Temp);
  950. cellCount = 0;
  951. for (int i = 0; i < constrainedCount; ++i)
  952. {
  953. if (m_Flags[i] == 1)
  954. {
  955. cellsOut[cellCount++] = constrained[i];
  956. }
  957. }
  958. constrained.Dispose();
  959. return cellsOut;
  960. }
  961. internal void Cleanup()
  962. {
  963. m_Edges.Dispose();
  964. m_Stars.Dispose();
  965. m_ILArray.Dispose();
  966. m_IUArray.Dispose();
  967. m_SPArray.Dispose();
  968. m_Cells.Dispose();
  969. m_Flags.Dispose();
  970. m_Neighbors.Dispose();
  971. m_Constraints.Dispose();
  972. }
  973. }
  974. }
  975. }