源战役客户端
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

278 rindas
10 KiB

pirms 1 mēnesi
  1. /******************************************************************************
  2. * Spine Runtimes Software License v2.5
  3. *
  4. * Copyright (c) 2013-2016, Esoteric Software
  5. * All rights reserved.
  6. *
  7. * You are granted a perpetual, non-exclusive, non-sublicensable, and
  8. * non-transferable license to use, install, execute, and perform the Spine
  9. * Runtimes software and derivative works solely for personal or internal
  10. * use. Without the written permission of Esoteric Software (see Section 2 of
  11. * the Spine Software License Agreement), you may not (a) modify, translate,
  12. * adapt, or develop new applications using the Spine Runtimes or otherwise
  13. * create derivative works or improvements of the Spine Runtimes or (b) remove,
  14. * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
  15. * or other intellectual property or proprietary rights notices on or in the
  16. * Software, including any copy thereof. Redistributions in binary or source
  17. * form must include this license and terms.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
  20. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  22. * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  24. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
  25. * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  26. * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. *****************************************************************************/
  30. using System;
  31. namespace Spine {
  32. internal class Triangulator {
  33. private readonly ExposedList<ExposedList<float>> convexPolygons = new ExposedList<ExposedList<float>>();
  34. private readonly ExposedList<ExposedList<int>> convexPolygonsIndices = new ExposedList<ExposedList<int>>();
  35. private readonly ExposedList<int> indicesArray = new ExposedList<int>();
  36. private readonly ExposedList<bool> isConcaveArray = new ExposedList<bool>();
  37. private readonly ExposedList<int> triangles = new ExposedList<int>();
  38. private readonly Pool<ExposedList<float>> polygonPool = new Pool<ExposedList<float>>();
  39. private readonly Pool<ExposedList<int>> polygonIndicesPool = new Pool<ExposedList<int>>();
  40. public ExposedList<int> Triangulate (ExposedList<float> verticesArray) {
  41. var vertices = verticesArray.Items;
  42. int vertexCount = verticesArray.Count >> 1;
  43. var indicesArray = this.indicesArray;
  44. indicesArray.Clear();
  45. int[] indices = indicesArray.Resize(vertexCount).Items;
  46. for (int i = 0; i < vertexCount; i++)
  47. indices[i] = i;
  48. var isConcaveArray = this.isConcaveArray;
  49. bool[] isConcave = isConcaveArray.Resize(vertexCount).Items;
  50. for (int i = 0, n = vertexCount; i < n; ++i)
  51. isConcave[i] = IsConcave(i, vertexCount, vertices, indices);
  52. var triangles = this.triangles;
  53. triangles.Clear();
  54. triangles.EnsureCapacity(Math.Max(0, vertexCount - 2) << 2);
  55. while (vertexCount > 3) {
  56. // Find ear tip.
  57. int previous = vertexCount - 1, i = 0, next = 1;
  58. // outer:
  59. while (true) {
  60. if (!isConcave[i]) {
  61. int p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1;
  62. float p1x = vertices[p1], p1y = vertices[p1 + 1];
  63. float p2x = vertices[p2], p2y = vertices[p2 + 1];
  64. float p3x = vertices[p3], p3y = vertices[p3 + 1];
  65. for (int ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) {
  66. if (!isConcave[ii]) continue;
  67. int v = indices[ii] << 1;
  68. float vx = vertices[v], vy = vertices[v + 1];
  69. if (PositiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
  70. if (PositiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
  71. if (PositiveArea(p2x, p2y, p3x, p3y, vx, vy)) goto break_outer; // break outer;
  72. }
  73. }
  74. }
  75. break;
  76. }
  77. break_outer:
  78. if (next == 0) {
  79. do {
  80. if (!isConcave[i]) break;
  81. i--;
  82. } while (i > 0);
  83. break;
  84. }
  85. previous = i;
  86. i = next;
  87. next = (next + 1) % vertexCount;
  88. }
  89. // Cut ear tip.
  90. triangles.Add(indices[(vertexCount + i - 1) % vertexCount]);
  91. triangles.Add(indices[i]);
  92. triangles.Add(indices[(i + 1) % vertexCount]);
  93. indicesArray.RemoveAt(i);
  94. isConcaveArray.RemoveAt(i);
  95. vertexCount--;
  96. int previousIndex = (vertexCount + i - 1) % vertexCount;
  97. int nextIndex = i == vertexCount ? 0 : i;
  98. isConcave[previousIndex] = IsConcave(previousIndex, vertexCount, vertices, indices);
  99. isConcave[nextIndex] = IsConcave(nextIndex, vertexCount, vertices, indices);
  100. }
  101. if (vertexCount == 3) {
  102. triangles.Add(indices[2]);
  103. triangles.Add(indices[0]);
  104. triangles.Add(indices[1]);
  105. }
  106. return triangles;
  107. }
  108. public ExposedList<ExposedList<float>> Decompose (ExposedList<float> verticesArray, ExposedList<int> triangles) {
  109. var vertices = verticesArray.Items;
  110. var convexPolygons = this.convexPolygons;
  111. for (int i = 0, n = convexPolygons.Count; i < n; i++) {
  112. polygonPool.Free(convexPolygons.Items[i]);
  113. }
  114. convexPolygons.Clear();
  115. var convexPolygonsIndices = this.convexPolygonsIndices;
  116. for (int i = 0, n = convexPolygonsIndices.Count; i < n; i++) {
  117. polygonIndicesPool.Free(convexPolygonsIndices.Items[i]);
  118. }
  119. convexPolygonsIndices.Clear();
  120. var polygonIndices = polygonIndicesPool.Obtain();
  121. polygonIndices.Clear();
  122. var polygon = polygonPool.Obtain();
  123. polygon.Clear();
  124. // Merge subsequent triangles if they form a triangle fan.
  125. int fanBaseIndex = -1, lastWinding = 0;
  126. int[] trianglesItems = triangles.Items;
  127. for (int i = 0, n = triangles.Count; i < n; i += 3) {
  128. int t1 = trianglesItems[i] << 1, t2 = trianglesItems[i + 1] << 1, t3 = trianglesItems[i + 2] << 1;
  129. float x1 = vertices[t1], y1 = vertices[t1 + 1];
  130. float x2 = vertices[t2], y2 = vertices[t2 + 1];
  131. float x3 = vertices[t3], y3 = vertices[t3 + 1];
  132. // If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan).
  133. var merged = false;
  134. if (fanBaseIndex == t1) {
  135. int o = polygon.Count - 4;
  136. float[] p = polygon.Items;
  137. int winding1 = Winding(p[o], p[o + 1], p[o + 2], p[o + 3], x3, y3);
  138. int winding2 = Winding(x3, y3, p[0], p[1], p[2], p[3]);
  139. if (winding1 == lastWinding && winding2 == lastWinding) {
  140. polygon.Add(x3);
  141. polygon.Add(y3);
  142. polygonIndices.Add(t3);
  143. merged = true;
  144. }
  145. }
  146. // Otherwise make this triangle the new base.
  147. if (!merged) {
  148. if (polygon.Count > 0) {
  149. convexPolygons.Add(polygon);
  150. convexPolygonsIndices.Add(polygonIndices);
  151. } else {
  152. polygonPool.Free(polygon);
  153. polygonIndicesPool.Free(polygonIndices);
  154. }
  155. polygon = polygonPool.Obtain();
  156. polygon.Clear();
  157. polygon.Add(x1);
  158. polygon.Add(y1);
  159. polygon.Add(x2);
  160. polygon.Add(y2);
  161. polygon.Add(x3);
  162. polygon.Add(y3);
  163. polygonIndices = polygonIndicesPool.Obtain();
  164. polygonIndices.Clear();
  165. polygonIndices.Add(t1);
  166. polygonIndices.Add(t2);
  167. polygonIndices.Add(t3);
  168. lastWinding = Winding(x1, y1, x2, y2, x3, y3);
  169. fanBaseIndex = t1;
  170. }
  171. }
  172. if (polygon.Count > 0) {
  173. convexPolygons.Add(polygon);
  174. convexPolygonsIndices.Add(polygonIndices);
  175. }
  176. // Go through the list of polygons and try to merge the remaining triangles with the found triangle fans.
  177. for (int i = 0, n = convexPolygons.Count; i < n; i++) {
  178. polygonIndices = convexPolygonsIndices.Items[i];
  179. if (polygonIndices.Count == 0) continue;
  180. int firstIndex = polygonIndices.Items[0];
  181. int lastIndex = polygonIndices.Items[polygonIndices.Count - 1];
  182. polygon = convexPolygons.Items[i];
  183. int o = polygon.Count - 4;
  184. float[] p = polygon.Items;
  185. float prevPrevX = p[o], prevPrevY = p[o + 1];
  186. float prevX = p[o + 2], prevY = p[o + 3];
  187. float firstX = p[0], firstY = p[1];
  188. float secondX = p[2], secondY = p[3];
  189. int winding = Winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY);
  190. for (int ii = 0; ii < n; ii++) {
  191. if (ii == i) continue;
  192. var otherIndices = convexPolygonsIndices.Items[ii];
  193. if (otherIndices.Count != 3) continue;
  194. int otherFirstIndex = otherIndices.Items[0];
  195. int otherSecondIndex = otherIndices.Items[1];
  196. int otherLastIndex = otherIndices.Items[2];
  197. var otherPoly = convexPolygons.Items[ii];
  198. float x3 = otherPoly.Items[otherPoly.Count - 2], y3 = otherPoly.Items[otherPoly.Count - 1];
  199. if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue;
  200. int winding1 = Winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);
  201. int winding2 = Winding(x3, y3, firstX, firstY, secondX, secondY);
  202. if (winding1 == winding && winding2 == winding) {
  203. otherPoly.Clear();
  204. otherIndices.Clear();
  205. polygon.Add(x3);
  206. polygon.Add(y3);
  207. polygonIndices.Add(otherLastIndex);
  208. prevPrevX = prevX;
  209. prevPrevY = prevY;
  210. prevX = x3;
  211. prevY = y3;
  212. ii = 0;
  213. }
  214. }
  215. }
  216. // Remove empty polygons that resulted from the merge step above.
  217. for (int i = convexPolygons.Count - 1; i >= 0; i--) {
  218. polygon = convexPolygons.Items[i];
  219. if (polygon.Count == 0) {
  220. convexPolygons.RemoveAt(i);
  221. polygonPool.Free(polygon);
  222. polygonIndices = convexPolygonsIndices.Items[i];
  223. convexPolygonsIndices.RemoveAt(i);
  224. polygonIndicesPool.Free(polygonIndices);
  225. }
  226. }
  227. return convexPolygons;
  228. }
  229. static private bool IsConcave (int index, int vertexCount, float[] vertices, int[] indices) {
  230. int previous = indices[(vertexCount + index - 1) % vertexCount] << 1;
  231. int current = indices[index] << 1;
  232. int next = indices[(index + 1) % vertexCount] << 1;
  233. return !PositiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next],
  234. vertices[next + 1]);
  235. }
  236. static private bool PositiveArea (float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) {
  237. return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0;
  238. }
  239. static private int Winding (float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) {
  240. float px = p2x - p1x, py = p2y - p1y;
  241. return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1;
  242. }
  243. }
  244. }