Nenhuma descrição
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. /*
  2. ** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
  3. ** Copyright (C) 2011 Silicon Graphics, Inc.
  4. ** All Rights Reserved.
  5. **
  6. ** Permission is hereby granted, free of charge, to any person obtaining a copy
  7. ** of this software and associated documentation files (the "Software"), to deal
  8. ** in the Software without restriction, including without limitation the rights
  9. ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  10. ** of the Software, and to permit persons to whom the Software is furnished to do so,
  11. ** subject to the following conditions:
  12. **
  13. ** The above copyright notice including the dates of first publication and either this
  14. ** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be
  15. ** included in all copies or substantial portions of the Software.
  16. **
  17. ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  18. ** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  19. ** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC.
  20. ** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  21. ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
  22. ** OR OTHER DEALINGS IN THE SOFTWARE.
  23. **
  24. ** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not
  25. ** be used in advertising or otherwise to promote the sale, use or other dealings in
  26. ** this Software without prior written authorization from Silicon Graphics, Inc.
  27. */
  28. /*
  29. ** Original Author: Eric Veach, July 1994.
  30. ** libtess2: Mikko Mononen, http://code.google.com/p/libtess2/.
  31. ** LibTessDotNet: Remi Gillig, https://github.com/speps/LibTessDotNet
  32. */
  33. using System;
  34. using System.Diagnostics;
  35. namespace Unity.SpriteShape.External
  36. {
  37. using Real = System.Single;
  38. namespace LibTessDotNet
  39. {
  40. internal enum WindingRule
  41. {
  42. EvenOdd,
  43. NonZero,
  44. Positive,
  45. Negative,
  46. AbsGeqTwo
  47. }
  48. internal enum ElementType
  49. {
  50. Polygons,
  51. ConnectedPolygons,
  52. BoundaryContours
  53. }
  54. internal enum ContourOrientation
  55. {
  56. Original,
  57. Clockwise,
  58. CounterClockwise
  59. }
  60. internal struct ContourVertex
  61. {
  62. public Vec3 Position;
  63. public object Data;
  64. public override string ToString()
  65. {
  66. return string.Format("{0}, {1}", Position, Data);
  67. }
  68. }
  69. internal delegate object CombineCallback(Vec3 position, object[] data, Real[] weights);
  70. internal partial class Tess
  71. {
  72. private Mesh _mesh;
  73. private Vec3 _normal;
  74. private Vec3 _sUnit;
  75. private Vec3 _tUnit;
  76. private Real _bminX, _bminY, _bmaxX, _bmaxY;
  77. private WindingRule _windingRule;
  78. private Dict<ActiveRegion> _dict;
  79. private PriorityQueue<MeshUtils.Vertex> _pq;
  80. private MeshUtils.Vertex _event;
  81. private CombineCallback _combineCallback;
  82. private ContourVertex[] _vertices;
  83. private int _vertexCount;
  84. private int[] _elements;
  85. private int _elementCount;
  86. public Vec3 Normal { get { return _normal; } set { _normal = value; } }
  87. public Real SUnitX = 1;
  88. public Real SUnitY = 0;
  89. public Real SentinelCoord = 4e30f;
  90. /// <summary>
  91. /// If true, will remove empty (zero area) polygons.
  92. /// </summary>
  93. public bool NoEmptyPolygons = false;
  94. /// <summary>
  95. /// If true, will use pooling to reduce GC (compare performance with/without, can vary wildly).
  96. /// </summary>
  97. public bool UsePooling = false;
  98. public ContourVertex[] Vertices { get { return _vertices; } }
  99. public int VertexCount { get { return _vertexCount; } }
  100. public int[] Elements { get { return _elements; } }
  101. public int ElementCount { get { return _elementCount; } }
  102. public Tess()
  103. {
  104. _normal = Vec3.Zero;
  105. _bminX = _bminY = _bmaxX = _bmaxY = 0;
  106. _windingRule = WindingRule.EvenOdd;
  107. _mesh = null;
  108. _vertices = null;
  109. _vertexCount = 0;
  110. _elements = null;
  111. _elementCount = 0;
  112. }
  113. private void ComputeNormal(ref Vec3 norm)
  114. {
  115. var v = _mesh._vHead._next;
  116. var minVal = new Real[3] { v._coords.X, v._coords.Y, v._coords.Z };
  117. var minVert = new MeshUtils.Vertex[3] { v, v, v };
  118. var maxVal = new Real[3] { v._coords.X, v._coords.Y, v._coords.Z };
  119. var maxVert = new MeshUtils.Vertex[3] { v, v, v };
  120. for (; v != _mesh._vHead; v = v._next)
  121. {
  122. if (v._coords.X < minVal[0]) { minVal[0] = v._coords.X; minVert[0] = v; }
  123. if (v._coords.Y < minVal[1]) { minVal[1] = v._coords.Y; minVert[1] = v; }
  124. if (v._coords.Z < minVal[2]) { minVal[2] = v._coords.Z; minVert[2] = v; }
  125. if (v._coords.X > maxVal[0]) { maxVal[0] = v._coords.X; maxVert[0] = v; }
  126. if (v._coords.Y > maxVal[1]) { maxVal[1] = v._coords.Y; maxVert[1] = v; }
  127. if (v._coords.Z > maxVal[2]) { maxVal[2] = v._coords.Z; maxVert[2] = v; }
  128. }
  129. // Find two vertices separated by at least 1/sqrt(3) of the maximum
  130. // distance between any two vertices
  131. int i = 0;
  132. if (maxVal[1] - minVal[1] > maxVal[0] - minVal[0]) { i = 1; }
  133. if (maxVal[2] - minVal[2] > maxVal[i] - minVal[i]) { i = 2; }
  134. if (minVal[i] >= maxVal[i])
  135. {
  136. // All vertices are the same -- normal doesn't matter
  137. norm = new Vec3 { X = 0, Y = 0, Z = 1 };
  138. return;
  139. }
  140. // Look for a third vertex which forms the triangle with maximum area
  141. // (Length of normal == twice the triangle area)
  142. Real maxLen2 = 0, tLen2;
  143. var v1 = minVert[i];
  144. var v2 = maxVert[i];
  145. Vec3 d1, d2, tNorm;
  146. Vec3.Sub(ref v1._coords, ref v2._coords, out d1);
  147. for (v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
  148. {
  149. Vec3.Sub(ref v._coords, ref v2._coords, out d2);
  150. tNorm.X = d1.Y * d2.Z - d1.Z * d2.Y;
  151. tNorm.Y = d1.Z * d2.X - d1.X * d2.Z;
  152. tNorm.Z = d1.X * d2.Y - d1.Y * d2.X;
  153. tLen2 = tNorm.X*tNorm.X + tNorm.Y*tNorm.Y + tNorm.Z*tNorm.Z;
  154. if (tLen2 > maxLen2)
  155. {
  156. maxLen2 = tLen2;
  157. norm = tNorm;
  158. }
  159. }
  160. if (maxLen2 <= 0.0f)
  161. {
  162. // All points lie on a single line -- any decent normal will do
  163. norm = Vec3.Zero;
  164. i = Vec3.LongAxis(ref d1);
  165. norm[i] = 1;
  166. }
  167. }
  168. private void CheckOrientation()
  169. {
  170. // When we compute the normal automatically, we choose the orientation
  171. // so that the the sum of the signed areas of all contours is non-negative.
  172. Real area = 0.0f;
  173. for (var f = _mesh._fHead._next; f != _mesh._fHead; f = f._next)
  174. {
  175. if (f._anEdge._winding <= 0)
  176. {
  177. continue;
  178. }
  179. area += MeshUtils.FaceArea(f);
  180. }
  181. if (area < 0.0f)
  182. {
  183. // Reverse the orientation by flipping all the t-coordinates
  184. for (var v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
  185. {
  186. v._t = -v._t;
  187. }
  188. Vec3.Neg(ref _tUnit);
  189. }
  190. }
  191. private void ProjectPolygon()
  192. {
  193. var norm = _normal;
  194. bool computedNormal = false;
  195. if (norm.X == 0.0f && norm.Y == 0.0f && norm.Z == 0.0f)
  196. {
  197. ComputeNormal(ref norm);
  198. _normal = norm;
  199. computedNormal = true;
  200. }
  201. int i = Vec3.LongAxis(ref norm);
  202. _sUnit[i] = 0;
  203. _sUnit[(i + 1) % 3] = SUnitX;
  204. _sUnit[(i + 2) % 3] = SUnitY;
  205. _tUnit[i] = 0;
  206. _tUnit[(i + 1) % 3] = norm[i] > 0.0f ? -SUnitY : SUnitY;
  207. _tUnit[(i + 2) % 3] = norm[i] > 0.0f ? SUnitX : -SUnitX;
  208. // Project the vertices onto the sweep plane
  209. for (var v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
  210. {
  211. Vec3.Dot(ref v._coords, ref _sUnit, out v._s);
  212. Vec3.Dot(ref v._coords, ref _tUnit, out v._t);
  213. }
  214. if (computedNormal)
  215. {
  216. CheckOrientation();
  217. }
  218. // Compute ST bounds.
  219. bool first = true;
  220. for (var v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
  221. {
  222. if (first)
  223. {
  224. _bminX = _bmaxX = v._s;
  225. _bminY = _bmaxY = v._t;
  226. first = false;
  227. }
  228. else
  229. {
  230. if (v._s < _bminX) _bminX = v._s;
  231. if (v._s > _bmaxX) _bmaxX = v._s;
  232. if (v._t < _bminY) _bminY = v._t;
  233. if (v._t > _bmaxY) _bmaxY = v._t;
  234. }
  235. }
  236. }
  237. /// <summary>
  238. /// TessellateMonoRegion( face ) tessellates a monotone region
  239. /// (what else would it do??) The region must consist of a single
  240. /// loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this
  241. /// case means that any vertical line intersects the interior of the
  242. /// region in a single interval.
  243. ///
  244. /// Tessellation consists of adding interior edges (actually pairs of
  245. /// half-edges), to split the region into non-overlapping triangles.
  246. ///
  247. /// The basic idea is explained in Preparata and Shamos (which I don't
  248. /// have handy right now), although their implementation is more
  249. /// complicated than this one. The are two edge chains, an upper chain
  250. /// and a lower chain. We process all vertices from both chains in order,
  251. /// from right to left.
  252. ///
  253. /// The algorithm ensures that the following invariant holds after each
  254. /// vertex is processed: the untessellated region consists of two
  255. /// chains, where one chain (say the upper) is a single edge, and
  256. /// the other chain is concave. The left vertex of the single edge
  257. /// is always to the left of all vertices in the concave chain.
  258. ///
  259. /// Each step consists of adding the rightmost unprocessed vertex to one
  260. /// of the two chains, and forming a fan of triangles from the rightmost
  261. /// of two chain endpoints. Determining whether we can add each triangle
  262. /// to the fan is a simple orientation test. By making the fan as large
  263. /// as possible, we restore the invariant (check it yourself).
  264. /// </summary>
  265. private void TessellateMonoRegion(MeshUtils.Face face)
  266. {
  267. // All edges are oriented CCW around the boundary of the region.
  268. // First, find the half-edge whose origin vertex is rightmost.
  269. // Since the sweep goes from left to right, face->anEdge should
  270. // be close to the edge we want.
  271. var up = face._anEdge;
  272. Debug.Assert(up._Lnext != up && up._Lnext._Lnext != up);
  273. while (Geom.VertLeq(up._Dst, up._Org)) up = up._Lprev;
  274. while (Geom.VertLeq(up._Org, up._Dst)) up = up._Lnext;
  275. var lo = up._Lprev;
  276. while (up._Lnext != lo)
  277. {
  278. if (Geom.VertLeq(up._Dst, lo._Org))
  279. {
  280. // up.Dst is on the left. It is safe to form triangles from lo.Org.
  281. // The EdgeGoesLeft test guarantees progress even when some triangles
  282. // are CW, given that the upper and lower chains are truly monotone.
  283. while (lo._Lnext != up && (Geom.EdgeGoesLeft(lo._Lnext)
  284. || Geom.EdgeSign(lo._Org, lo._Dst, lo._Lnext._Dst) <= 0.0f))
  285. {
  286. lo = _mesh.Connect(lo._Lnext, lo)._Sym;
  287. }
  288. lo = lo._Lprev;
  289. }
  290. else
  291. {
  292. // lo.Org is on the left. We can make CCW triangles from up.Dst.
  293. while (lo._Lnext != up && (Geom.EdgeGoesRight(up._Lprev)
  294. || Geom.EdgeSign(up._Dst, up._Org, up._Lprev._Org) >= 0.0f))
  295. {
  296. up = _mesh.Connect(up, up._Lprev)._Sym;
  297. }
  298. up = up._Lnext;
  299. }
  300. }
  301. // Now lo.Org == up.Dst == the leftmost vertex. The remaining region
  302. // can be tessellated in a fan from this leftmost vertex.
  303. Debug.Assert(lo._Lnext != up);
  304. while (lo._Lnext._Lnext != up)
  305. {
  306. lo = _mesh.Connect(lo._Lnext, lo)._Sym;
  307. }
  308. }
  309. /// <summary>
  310. /// TessellateInterior( mesh ) tessellates each region of
  311. /// the mesh which is marked "inside" the polygon. Each such region
  312. /// must be monotone.
  313. /// </summary>
  314. private void TessellateInterior()
  315. {
  316. MeshUtils.Face f, next;
  317. for (f = _mesh._fHead._next; f != _mesh._fHead; f = next)
  318. {
  319. // Make sure we don't try to tessellate the new triangles.
  320. next = f._next;
  321. if (f._inside)
  322. {
  323. TessellateMonoRegion(f);
  324. }
  325. }
  326. }
  327. /// <summary>
  328. /// DiscardExterior zaps (ie. sets to null) all faces
  329. /// which are not marked "inside" the polygon. Since further mesh operations
  330. /// on NULL faces are not allowed, the main purpose is to clean up the
  331. /// mesh so that exterior loops are not represented in the data structure.
  332. /// </summary>
  333. private void DiscardExterior()
  334. {
  335. MeshUtils.Face f, next;
  336. for (f = _mesh._fHead._next; f != _mesh._fHead; f = next)
  337. {
  338. // Since f will be destroyed, save its next pointer.
  339. next = f._next;
  340. if( ! f._inside ) {
  341. _mesh.ZapFace(f);
  342. }
  343. }
  344. }
  345. /// <summary>
  346. /// SetWindingNumber( value, keepOnlyBoundary ) resets the
  347. /// winding numbers on all edges so that regions marked "inside" the
  348. /// polygon have a winding number of "value", and regions outside
  349. /// have a winding number of 0.
  350. ///
  351. /// If keepOnlyBoundary is TRUE, it also deletes all edges which do not
  352. /// separate an interior region from an exterior one.
  353. /// </summary>
  354. private void SetWindingNumber(int value, bool keepOnlyBoundary)
  355. {
  356. MeshUtils.Edge e, eNext;
  357. for (e = _mesh._eHead._next; e != _mesh._eHead; e = eNext)
  358. {
  359. eNext = e._next;
  360. if (e._Rface._inside != e._Lface._inside)
  361. {
  362. /* This is a boundary edge (one side is interior, one is exterior). */
  363. e._winding = (e._Lface._inside) ? value : -value;
  364. }
  365. else
  366. {
  367. /* Both regions are interior, or both are exterior. */
  368. if (!keepOnlyBoundary)
  369. {
  370. e._winding = 0;
  371. }
  372. else
  373. {
  374. _mesh.Delete(e);
  375. }
  376. }
  377. }
  378. }
  379. private int GetNeighbourFace(MeshUtils.Edge edge)
  380. {
  381. if (edge._Rface == null)
  382. return MeshUtils.Undef;
  383. if (!edge._Rface._inside)
  384. return MeshUtils.Undef;
  385. return edge._Rface._n;
  386. }
  387. private void OutputPolymesh(ElementType elementType, int polySize)
  388. {
  389. MeshUtils.Vertex v;
  390. MeshUtils.Face f;
  391. MeshUtils.Edge edge;
  392. int maxFaceCount = 0;
  393. int maxVertexCount = 0;
  394. int faceVerts, i;
  395. if (polySize < 3)
  396. {
  397. polySize = 3;
  398. }
  399. // Assume that the input data is triangles now.
  400. // Try to merge as many polygons as possible
  401. if (polySize > 3)
  402. {
  403. _mesh.MergeConvexFaces(polySize);
  404. }
  405. // Mark unused
  406. for (v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
  407. v._n = MeshUtils.Undef;
  408. // Create unique IDs for all vertices and faces.
  409. for (f = _mesh._fHead._next; f != _mesh._fHead; f = f._next)
  410. {
  411. f._n = MeshUtils.Undef;
  412. if (!f._inside) continue;
  413. if (NoEmptyPolygons)
  414. {
  415. var area = MeshUtils.FaceArea(f);
  416. if (Math.Abs(area) < Real.Epsilon)
  417. {
  418. continue;
  419. }
  420. }
  421. edge = f._anEdge;
  422. faceVerts = 0;
  423. do {
  424. v = edge._Org;
  425. if (v._n == MeshUtils.Undef)
  426. {
  427. v._n = maxVertexCount;
  428. maxVertexCount++;
  429. }
  430. faceVerts++;
  431. edge = edge._Lnext;
  432. }
  433. while (edge != f._anEdge);
  434. Debug.Assert(faceVerts <= polySize);
  435. f._n = maxFaceCount;
  436. ++maxFaceCount;
  437. }
  438. _elementCount = maxFaceCount;
  439. if (elementType == ElementType.ConnectedPolygons)
  440. maxFaceCount *= 2;
  441. _elements = new int[maxFaceCount * polySize];
  442. _vertexCount = maxVertexCount;
  443. _vertices = new ContourVertex[_vertexCount];
  444. // Output vertices.
  445. for (v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
  446. {
  447. if (v._n != MeshUtils.Undef)
  448. {
  449. // Store coordinate
  450. _vertices[v._n].Position = v._coords;
  451. _vertices[v._n].Data = v._data;
  452. }
  453. }
  454. // Output indices.
  455. int elementIndex = 0;
  456. for (f = _mesh._fHead._next; f != _mesh._fHead; f = f._next)
  457. {
  458. if (!f._inside) continue;
  459. if (NoEmptyPolygons)
  460. {
  461. var area = MeshUtils.FaceArea(f);
  462. if (Math.Abs(area) < Real.Epsilon)
  463. {
  464. continue;
  465. }
  466. }
  467. // Store polygon
  468. edge = f._anEdge;
  469. faceVerts = 0;
  470. do {
  471. v = edge._Org;
  472. _elements[elementIndex++] = v._n;
  473. faceVerts++;
  474. edge = edge._Lnext;
  475. } while (edge != f._anEdge);
  476. // Fill unused.
  477. for (i = faceVerts; i < polySize; ++i)
  478. {
  479. _elements[elementIndex++] = MeshUtils.Undef;
  480. }
  481. // Store polygon connectivity
  482. if (elementType == ElementType.ConnectedPolygons)
  483. {
  484. edge = f._anEdge;
  485. do
  486. {
  487. _elements[elementIndex++] = GetNeighbourFace(edge);
  488. edge = edge._Lnext;
  489. } while (edge != f._anEdge);
  490. // Fill unused.
  491. for (i = faceVerts; i < polySize; ++i)
  492. {
  493. _elements[elementIndex++] = MeshUtils.Undef;
  494. }
  495. }
  496. }
  497. }
  498. private void OutputContours()
  499. {
  500. MeshUtils.Face f;
  501. MeshUtils.Edge edge, start;
  502. int startVert = 0;
  503. int vertCount = 0;
  504. _vertexCount = 0;
  505. _elementCount = 0;
  506. for (f = _mesh._fHead._next; f != _mesh._fHead; f = f._next)
  507. {
  508. if (!f._inside) continue;
  509. start = edge = f._anEdge;
  510. do
  511. {
  512. ++_vertexCount;
  513. edge = edge._Lnext;
  514. }
  515. while (edge != start);
  516. ++_elementCount;
  517. }
  518. _elements = new int[_elementCount * 2];
  519. _vertices = new ContourVertex[_vertexCount];
  520. int vertIndex = 0;
  521. int elementIndex = 0;
  522. startVert = 0;
  523. for (f = _mesh._fHead._next; f != _mesh._fHead; f = f._next)
  524. {
  525. if (!f._inside) continue;
  526. vertCount = 0;
  527. start = edge = f._anEdge;
  528. do {
  529. _vertices[vertIndex].Position = edge._Org._coords;
  530. _vertices[vertIndex].Data = edge._Org._data;
  531. ++vertIndex;
  532. ++vertCount;
  533. edge = edge._Lnext;
  534. } while (edge != start);
  535. _elements[elementIndex++] = startVert;
  536. _elements[elementIndex++] = vertCount;
  537. startVert += vertCount;
  538. }
  539. }
  540. private Real SignedArea(ContourVertex[] vertices)
  541. {
  542. Real area = 0.0f;
  543. for (int i = 0; i < vertices.Length; i++)
  544. {
  545. var v0 = vertices[i];
  546. var v1 = vertices[(i + 1) % vertices.Length];
  547. area += v0.Position.X * v1.Position.Y;
  548. area -= v0.Position.Y * v1.Position.X;
  549. }
  550. return 0.5f * area;
  551. }
  552. public void AddContour(ContourVertex[] vertices)
  553. {
  554. AddContour(vertices, ContourOrientation.Original);
  555. }
  556. public void AddContour(ContourVertex[] vertices, ContourOrientation forceOrientation)
  557. {
  558. if (_mesh == null)
  559. {
  560. _mesh = new Mesh();
  561. }
  562. bool reverse = false;
  563. if (forceOrientation != ContourOrientation.Original)
  564. {
  565. var area = SignedArea(vertices);
  566. reverse = (forceOrientation == ContourOrientation.Clockwise && area < 0.0f) || (forceOrientation == ContourOrientation.CounterClockwise && area > 0.0f);
  567. }
  568. MeshUtils.Edge e = null;
  569. for (int i = 0; i < vertices.Length; ++i)
  570. {
  571. if (e == null)
  572. {
  573. e = _mesh.MakeEdge();
  574. _mesh.Splice(e, e._Sym);
  575. }
  576. else
  577. {
  578. // Create a new vertex and edge which immediately follow e
  579. // in the ordering around the left face.
  580. _mesh.SplitEdge(e);
  581. e = e._Lnext;
  582. }
  583. int index = reverse ? vertices.Length - 1 - i : i;
  584. // The new vertex is now e._Org.
  585. e._Org._coords = vertices[index].Position;
  586. e._Org._data = vertices[index].Data;
  587. // The winding of an edge says how the winding number changes as we
  588. // cross from the edge's right face to its left face. We add the
  589. // vertices in such an order that a CCW contour will add +1 to
  590. // the winding number of the region inside the contour.
  591. e._winding = 1;
  592. e._Sym._winding = -1;
  593. }
  594. }
  595. public void Tessellate(WindingRule windingRule, ElementType elementType, int polySize)
  596. {
  597. Tessellate(windingRule, elementType, polySize, null);
  598. }
  599. public void Tessellate(WindingRule windingRule, ElementType elementType, int polySize, CombineCallback combineCallback)
  600. {
  601. _normal = Vec3.Zero;
  602. _vertices = null;
  603. _elements = null;
  604. _windingRule = windingRule;
  605. _combineCallback = combineCallback;
  606. if (_mesh == null)
  607. {
  608. return;
  609. }
  610. // Determine the polygon normal and project vertices onto the plane
  611. // of the polygon.
  612. ProjectPolygon();
  613. // ComputeInterior computes the planar arrangement specified
  614. // by the given contours, and further subdivides this arrangement
  615. // into regions. Each region is marked "inside" if it belongs
  616. // to the polygon, according to the rule given by windingRule.
  617. // Each interior region is guaranteed be monotone.
  618. ComputeInterior();
  619. // If the user wants only the boundary contours, we throw away all edges
  620. // except those which separate the interior from the exterior.
  621. // Otherwise we tessellate all the regions marked "inside".
  622. if (elementType == ElementType.BoundaryContours)
  623. {
  624. SetWindingNumber(1, true);
  625. }
  626. else
  627. {
  628. TessellateInterior();
  629. }
  630. _mesh.Check();
  631. if (elementType == ElementType.BoundaryContours)
  632. {
  633. OutputContours();
  634. }
  635. else
  636. {
  637. OutputPolymesh(elementType, polySize);
  638. }
  639. if (UsePooling)
  640. {
  641. _mesh.Free();
  642. }
  643. _mesh = null;
  644. }
  645. }
  646. }
  647. } // namespace Unity.VectorGraphics.External