SkeletonClipping.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /******************************************************************************
  2. * Spine Runtimes License Agreement
  3. * Last updated January 1, 2020. Replaces all prior versions.
  4. *
  5. * Copyright (c) 2013-2020, Esoteric Software LLC
  6. *
  7. * Integration of the Spine Runtimes into software or otherwise creating
  8. * derivative works of the Spine Runtimes is permitted under the terms and
  9. * conditions of Section 2 of the Spine Editor License Agreement:
  10. * http://esotericsoftware.com/spine-editor-license
  11. *
  12. * Otherwise, it is permitted to integrate the Spine Runtimes into software
  13. * or otherwise create derivative works of the Spine Runtimes (collectively,
  14. * "Products"), provided that each user of the Products must obtain their own
  15. * Spine Editor license and redistribution of the Products in any form must
  16. * include this license and copyright notice.
  17. *
  18. * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
  19. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
  24. * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *****************************************************************************/
  29. #ifdef SPINE_UE4
  30. #include "SpinePluginPrivatePCH.h"
  31. #endif
  32. #include <spine/SkeletonClipping.h>
  33. #include <spine/Slot.h>
  34. #include <spine/ClippingAttachment.h>
  35. using namespace spine;
  36. SkeletonClipping::SkeletonClipping() : _clipAttachment(NULL) {
  37. _clipOutput.ensureCapacity(128);
  38. _clippedVertices.ensureCapacity(128);
  39. _clippedTriangles.ensureCapacity(128);
  40. _clippedUVs.ensureCapacity(128);
  41. }
  42. size_t SkeletonClipping::clipStart(Slot &slot, ClippingAttachment *clip) {
  43. if (_clipAttachment != NULL) {
  44. return 0;
  45. }
  46. _clipAttachment = clip;
  47. int n = clip->getWorldVerticesLength();
  48. _clippingPolygon.setSize(n, 0);
  49. clip->computeWorldVertices(slot, 0, n, _clippingPolygon, 0, 2);
  50. makeClockwise(_clippingPolygon);
  51. _clippingPolygons = &_triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon));
  52. for (size_t i = 0; i < _clippingPolygons->size(); ++i) {
  53. Vector<float> *polygonP = (*_clippingPolygons)[i];
  54. Vector<float> &polygon = *polygonP;
  55. makeClockwise(polygon);
  56. polygon.add(polygon[0]);
  57. polygon.add(polygon[1]);
  58. }
  59. return (*_clippingPolygons).size();
  60. }
  61. void SkeletonClipping::clipEnd(Slot &slot) {
  62. if (_clipAttachment != NULL && _clipAttachment->_endSlot == &slot._data) {
  63. clipEnd();
  64. }
  65. }
  66. void SkeletonClipping::clipEnd() {
  67. if (_clipAttachment == NULL) return;
  68. _clipAttachment = NULL;
  69. _clippingPolygons = NULL;
  70. _clippedVertices.clear();
  71. _clippedUVs.clear();
  72. _clippedTriangles.clear();
  73. _clippingPolygon.clear();
  74. }
  75. void SkeletonClipping::clipTriangles(Vector<float> &vertices, Vector<unsigned short> &triangles, Vector<float> &uvs, size_t stride) {
  76. clipTriangles(vertices.buffer(), triangles.buffer(), triangles.size(), uvs.buffer(), stride);
  77. }
  78. void SkeletonClipping::clipTriangles(float *vertices, unsigned short *triangles,
  79. size_t trianglesLength, float *uvs, size_t stride
  80. ) {
  81. Vector<float> &clipOutput = _clipOutput;
  82. Vector<float> &clippedVertices = _clippedVertices;
  83. Vector<unsigned short> &clippedTriangles = _clippedTriangles;
  84. Vector<Vector<float> *> &polygons = *_clippingPolygons;
  85. size_t polygonsCount = (*_clippingPolygons).size();
  86. size_t index = 0;
  87. clippedVertices.clear();
  88. _clippedUVs.clear();
  89. clippedTriangles.clear();
  90. size_t i = 0;
  91. continue_outer:
  92. for (; i < trianglesLength; i += 3) {
  93. int vertexOffset = triangles[i] * stride;
  94. float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
  95. float u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];
  96. vertexOffset = triangles[i + 1] * stride;
  97. float x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
  98. float u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];
  99. vertexOffset = triangles[i + 2] * stride;
  100. float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
  101. float u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];
  102. for (size_t p = 0; p < polygonsCount; p++) {
  103. size_t s = clippedVertices.size();
  104. if (clip(x1, y1, x2, y2, x3, y3, &(*polygons[p]), &clipOutput)) {
  105. size_t clipOutputLength = clipOutput.size();
  106. if (clipOutputLength == 0) continue;
  107. float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
  108. float d = 1 / (d0 * d2 + d1 * (y1 - y3));
  109. size_t clipOutputCount = clipOutputLength >> 1;
  110. clippedVertices.setSize(s + clipOutputCount * 2, 0);
  111. _clippedUVs.setSize(s + clipOutputCount * 2, 0);
  112. for (size_t ii = 0; ii < clipOutputLength; ii += 2) {
  113. float x = clipOutput[ii], y = clipOutput[ii + 1];
  114. clippedVertices[s] = x;
  115. clippedVertices[s + 1] = y;
  116. float c0 = x - x3, c1 = y - y3;
  117. float a = (d0 * c0 + d1 * c1) * d;
  118. float b = (d4 * c0 + d2 * c1) * d;
  119. float c = 1 - a - b;
  120. _clippedUVs[s] = u1 * a + u2 * b + u3 * c;
  121. _clippedUVs[s + 1] = v1 * a + v2 * b + v3 * c;
  122. s += 2;
  123. }
  124. s = clippedTriangles.size();
  125. clippedTriangles.setSize(s + 3 * (clipOutputCount - 2), 0);
  126. clipOutputCount--;
  127. for (size_t ii = 1; ii < clipOutputCount; ii++) {
  128. clippedTriangles[s] = (unsigned short)(index);
  129. clippedTriangles[s + 1] = (unsigned short)(index + ii);
  130. clippedTriangles[s + 2] = (unsigned short)(index + ii + 1);
  131. s += 3;
  132. }
  133. index += clipOutputCount + 1;
  134. } else {
  135. clippedVertices.setSize(s + 3 * 2, 0);
  136. _clippedUVs.setSize(s + 3 * 2, 0);
  137. clippedVertices[s] = x1;
  138. clippedVertices[s + 1] = y1;
  139. clippedVertices[s + 2] = x2;
  140. clippedVertices[s + 3] = y2;
  141. clippedVertices[s + 4] = x3;
  142. clippedVertices[s + 5] = y3;
  143. _clippedUVs[s] = u1;
  144. _clippedUVs[s + 1] = v1;
  145. _clippedUVs[s + 2] = u2;
  146. _clippedUVs[s + 3] = v2;
  147. _clippedUVs[s + 4] = u3;
  148. _clippedUVs[s + 5] = v3;
  149. s = clippedTriangles.size();
  150. clippedTriangles.setSize(s + 3, 0);
  151. clippedTriangles[s] = (unsigned short)index;
  152. clippedTriangles[s + 1] = (unsigned short)(index + 1);
  153. clippedTriangles[s + 2] = (unsigned short)(index + 2);
  154. index += 3;
  155. i += 3;
  156. goto continue_outer;
  157. }
  158. }
  159. }
  160. }
  161. bool SkeletonClipping::isClipping() {
  162. return _clipAttachment != NULL;
  163. }
  164. Vector<float> &SkeletonClipping::getClippedVertices() {
  165. return _clippedVertices;
  166. }
  167. Vector<unsigned short> &SkeletonClipping::getClippedTriangles() {
  168. return _clippedTriangles;
  169. }
  170. Vector<float> &SkeletonClipping::getClippedUVs() {
  171. return _clippedUVs;
  172. }
  173. bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector<float> *clippingArea,
  174. Vector<float> *output
  175. ) {
  176. Vector<float> *originalOutput = output;
  177. bool clipped = false;
  178. // Avoid copy at the end.
  179. Vector<float> *input;
  180. if (clippingArea->size() % 4 >= 2) {
  181. input = output;
  182. output = &_scratch;
  183. } else
  184. input = &_scratch;
  185. input->clear();
  186. input->add(x1);
  187. input->add(y1);
  188. input->add(x2);
  189. input->add(y2);
  190. input->add(x3);
  191. input->add(y3);
  192. input->add(x1);
  193. input->add(y1);
  194. output->clear();
  195. Vector<float> &clippingVertices = *clippingArea;
  196. size_t clippingVerticesLast = clippingArea->size() - 4;
  197. for (size_t i = 0;; i += 2) {
  198. float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
  199. float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
  200. float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
  201. Vector<float> &inputVertices = *input;
  202. size_t inputVerticesLength = input->size() - 2, outputStart = output->size();
  203. for (size_t ii = 0; ii < inputVerticesLength; ii += 2) {
  204. float inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
  205. float inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3];
  206. bool side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
  207. if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) {
  208. if (side2) {
  209. // v1 inside, v2 inside
  210. output->add(inputX2);
  211. output->add(inputY2);
  212. continue;
  213. }
  214. // v1 inside, v2 outside
  215. float c0 = inputY2 - inputY, c2 = inputX2 - inputX;
  216. float s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY);
  217. if (MathUtil::abs(s) > 0.000001f) {
  218. float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s;
  219. output->add(edgeX + (edgeX2 - edgeX) * ua);
  220. output->add(edgeY + (edgeY2 - edgeY) * ua);
  221. } else {
  222. output->add(edgeX);
  223. output->add(edgeY);
  224. }
  225. } else if (side2) {
  226. // v1 outside, v2 inside
  227. float c0 = inputY2 - inputY, c2 = inputX2 - inputX;
  228. float s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY);
  229. if (MathUtil::abs(s) > 0.000001f) {
  230. float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s;
  231. output->add(edgeX + (edgeX2 - edgeX) * ua);
  232. output->add(edgeY + (edgeY2 - edgeY) * ua);
  233. } else {
  234. output->add(edgeX);
  235. output->add(edgeY);
  236. }
  237. output->add(inputX2);
  238. output->add(inputY2);
  239. }
  240. clipped = true;
  241. }
  242. if (outputStart == output->size()) {
  243. // All edges outside.
  244. originalOutput->clear();
  245. return true;
  246. }
  247. output->add((*output)[0]);
  248. output->add((*output)[1]);
  249. if (i == clippingVerticesLast) {
  250. break;
  251. }
  252. Vector<float> *temp = output;
  253. output = input;
  254. output->clear();
  255. input = temp;
  256. }
  257. if (originalOutput != output) {
  258. originalOutput->clear();
  259. for (size_t i = 0, n = output->size() - 2; i < n; ++i)
  260. originalOutput->add((*output)[i]);
  261. } else
  262. originalOutput->setSize(originalOutput->size() - 2, 0);
  263. return clipped;
  264. }
  265. void SkeletonClipping::makeClockwise(Vector<float> &polygon) {
  266. size_t verticeslength = polygon.size();
  267. float area = polygon[verticeslength - 2] * polygon[1] - polygon[0] * polygon[verticeslength - 1];
  268. float p1x, p1y, p2x, p2y;
  269. for (size_t i = 0, n = verticeslength - 3; i < n; i += 2) {
  270. p1x = polygon[i];
  271. p1y = polygon[i + 1];
  272. p2x = polygon[i + 2];
  273. p2y = polygon[i + 3];
  274. area += p1x * p2y - p2x * p1y;
  275. }
  276. if (area < 0) return;
  277. for (size_t i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {
  278. float x = polygon[i], y = polygon[i + 1];
  279. int other = lastX - i;
  280. polygon[i] = polygon[other];
  281. polygon[i + 1] = polygon[other + 1];
  282. polygon[other] = x;
  283. polygon[other + 1] = y;
  284. }
  285. }