From 537f033dad580783ee6540f1be130b91f7859631 Mon Sep 17 00:00:00 2001 From: badlogic Date: Thu, 27 Apr 2017 14:19:02 +0200 Subject: [PATCH] [c] Added SkeletonClipping and unit/leak test --- .../tests/MemoryTestFixture.cpp | 83 ++++- .../tests/MemoryTestFixture.h | 2 + spine-c/spine-c/include/spine/Array.h | 8 + .../include/spine/ClippingAttachment.h | 1 + .../spine-c/include/spine/SkeletonClipping.h | 67 ++++ spine-c/spine-c/include/spine/spine.h | 2 +- spine-c/spine-c/src/spine/SkeletonClipping.c | 312 ++++++++++++++++++ spine-c/spine-c/src/spine/Triangulator.c | 10 +- .../spine/utils/SkeletonClipping.java | 5 + .../spine/utils/Triangulator.java | 11 - 10 files changed, 484 insertions(+), 17 deletions(-) create mode 100644 spine-c/spine-c/include/spine/SkeletonClipping.h create mode 100644 spine-c/spine-c/src/spine/SkeletonClipping.c diff --git a/spine-c/spine-c-unit-tests/tests/MemoryTestFixture.cpp b/spine-c/spine-c-unit-tests/tests/MemoryTestFixture.cpp index c6ec41380..df224718f 100755 --- a/spine-c/spine-c-unit-tests/tests/MemoryTestFixture.cpp +++ b/spine-c/spine-c-unit-tests/tests/MemoryTestFixture.cpp @@ -1,4 +1,5 @@ -#include "MemoryTestFixture.h" +#include +#include "MemoryTestFixture.h" #include "SpineEventMonitor.h" #include "spine/spine.h" @@ -256,4 +257,84 @@ void MemoryTestFixture::triangulator() { spTriangulator_dispose(triangulator); } +void MemoryTestFixture::skeletonClipper() { + spSkeletonClipping* clipping = spSkeletonClipping_create(); + + spBoneData* boneData = spBoneData_create(0, "bone", 0); + spBone* bone = spBone_create(boneData, 0, 0); + CONST_CAST(float, bone->a) = 1; + CONST_CAST(float, bone->b) = 0; + CONST_CAST(float, bone->c) = 0; + CONST_CAST(float, bone->d) = 1; + CONST_CAST(float, bone->worldX) = 0; + CONST_CAST(float, bone->worldY) = 0; + spSlotData* slotData = spSlotData_create(0, "slot", 0); + spSlot* slot = spSlot_create(slotData, bone); + spClippingAttachment* clip = spClippingAttachment_create("clipping"); + clip->endSlot = slotData; + clip->super.worldVerticesLength = 4 * 2; + clip->super.verticesCount = 4; + clip->super.vertices = MALLOC(float, 4 * 8); + clip->super.vertices[0] = 0; + clip->super.vertices[1] = 50; + clip->super.vertices[2] = 100; + clip->super.vertices[3] = 50; + clip->super.vertices[4] = 100; + clip->super.vertices[5] = 70; + clip->super.vertices[6] = 0; + clip->super.vertices[7] = 70; + + spSkeletonClipping_clipStart(clipping, slot, clip); + + spFloatArray* vertices = spFloatArray_create(16); + spFloatArray_add(vertices, 0); + spFloatArray_add(vertices, 0); + spFloatArray_add(vertices, 100); + spFloatArray_add(vertices, 0); + spFloatArray_add(vertices, 50); + spFloatArray_add(vertices, 150); + spFloatArray* uvs = spFloatArray_create(16); + spFloatArray_add(uvs, 0); + spFloatArray_add(uvs, 0); + spFloatArray_add(uvs, 1); + spFloatArray_add(uvs, 0); + spFloatArray_add(uvs, 0.5f); + spFloatArray_add(uvs, 1); + spShortArray* indices = spShortArray_create(16); + spShortArray_add(indices, 0); + spShortArray_add(indices, 1); + spShortArray_add(indices, 2); + + spSkeletonClipping_clipTriangles(clipping, vertices->items, vertices->size, indices->items, indices->size, uvs->items); + + float expectedVertices[8] = { 83.333328, 50.000000, 76.666664, 70.000000, 23.333334, 70.000000, 16.666672, 50.000000 }; + ASSERT(clipping->clippedVertices->size == 8); + for (int i = 0; i < clipping->clippedVertices->size; i++) { + ASSERT(ABS(clipping->clippedVertices->items[i] - expectedVertices[i]) < 0.001); + } + + float expectedUVs[8] = { 0.833333f, 0.333333, 0.766667, 0.466667, 0.233333, 0.466667, 0.166667, 0.333333 }; + ASSERT(clipping->clippedUVs->size == 8); + for (int i = 0; i < clipping->clippedUVs->size; i++) { + ASSERT(ABS(clipping->clippedUVs->items[i] - expectedUVs[i]) < 0.001); + } + + short expectedIndices[6] = { 0, 1, 2, 0, 2, 3 }; + ASSERT(clipping->clippedTriangles->size == 6); + for (int i = 0; i < clipping->clippedTriangles->size; i++) { + ASSERT(clipping->clippedTriangles->items[i] == expectedIndices[i]); + } + + spFloatArray_dispose(vertices); + spFloatArray_dispose(uvs); + spShortArray_dispose(indices); + + spSlotData_dispose(slotData); + spSlot_dispose(slot); + spBoneData_dispose(boneData); + spBone_dispose(bone); + _spClippingAttachment_dispose(SUPER(SUPER(clip))); + spSkeletonClipping_dispose(clipping); +} + diff --git a/spine-c/spine-c-unit-tests/tests/MemoryTestFixture.h b/spine-c/spine-c-unit-tests/tests/MemoryTestFixture.h index bca38e93f..f45c35c86 100755 --- a/spine-c/spine-c-unit-tests/tests/MemoryTestFixture.h +++ b/spine-c/spine-c-unit-tests/tests/MemoryTestFixture.h @@ -19,6 +19,7 @@ public: TEST_CASE(reproduceIssue_777); TEST_CASE(reproduceIssue_Loop); TEST_CASE(triangulator); + TEST_CASE(skeletonClipper); initialize(); } @@ -33,6 +34,7 @@ public: void reproduceIssue_777(); void reproduceIssue_Loop(); // http://esotericsoftware.com/forum/spine-c-3-5-animation-jerking-7451 void triangulator(); + void skeletonClipper(); ////////////////////////////////////////////////////////////////////////// // test fixture setup diff --git a/spine-c/spine-c/include/spine/Array.h b/spine-c/spine-c/include/spine/Array.h index f1a53a71c..8bb7c3717 100644 --- a/spine-c/spine-c/include/spine/Array.h +++ b/spine-c/spine-c/include/spine/Array.h @@ -43,6 +43,8 @@ extern "C" { name* name##_setSize(name* self, int newSize); \ void name##_ensureCapacity(name* self, int newCapacity); \ void name##_add(name* self, itemType value); \ + void name##_addAll(name* self, name* other); \ + void name##_addAllValues(name* self, itemType* values, int offset, int count); \ void name##_removeAt(name* self, int index); \ int name##_contains(name* self, itemType value); \ itemType name##_pop(name* self); \ @@ -89,6 +91,12 @@ extern "C" { name##_add(self, other->items[i]); \ } \ } \ + void name##_addAllValues(name* self, itemType* values, int offset, int count) { \ + int i = offset, n = offset + count; \ + for (; i < n; i++) { \ + name##_add(self, values[i]); \ + } \ + } \ void name##_removeAt(name* self, int index) { \ self->size--; \ memmove(self->items + index, self->items + index + 1, sizeof(itemType) * (self->size - index)); \ diff --git a/spine-c/spine-c/include/spine/ClippingAttachment.h b/spine-c/spine-c/include/spine/ClippingAttachment.h index 6fcff53b5..33e5dc875 100644 --- a/spine-c/spine-c/include/spine/ClippingAttachment.h +++ b/spine-c/spine-c/include/spine/ClippingAttachment.h @@ -45,6 +45,7 @@ typedef struct spClippingAttachment { spSlotData* endSlot; } spClippingAttachment; +void _spClippingAttachment_dispose(spAttachment* self); spClippingAttachment* spClippingAttachment_create (const char* name); #ifdef SPINE_SHORT_NAMES diff --git a/spine-c/spine-c/include/spine/SkeletonClipping.h b/spine-c/spine-c/include/spine/SkeletonClipping.h new file mode 100644 index 000000000..af147b4b4 --- /dev/null +++ b/spine-c/spine-c/include/spine/SkeletonClipping.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF + * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SKELETONCLIPPING_H +#define SPINE_SKELETONCLIPPING_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct spSkeletonClipping { + spTriangulator* triangulator; + spFloatArray* clippingPolygon; + spFloatArray* clipOutput; + spFloatArray* clippedVertices; + spFloatArray* clippedUVs; + spShortArray* clippedTriangles; + spFloatArray* scratch; + spClippingAttachment* clipAttachment; + spArrayFloatArray* clippingPolygons; +} spSkeletonClipping; + +spSkeletonClipping* spSkeletonClipping_create(); +int spSkeletonClipping_clipStart(spSkeletonClipping* self, spSlot* slot, spClippingAttachment* clip); +void spSkeletonClipping_clipEnd(spSkeletonClipping* self, spSlot* slot); +void spSkeletonClipping_clipEnd2(spSkeletonClipping* self); +int /*boolean*/ spSkeletonClipping_isClipping(spSkeletonClipping* self); +void spSkeletonClipping_clipTriangles(spSkeletonClipping* self, float* vertices, int verticesLength, short* triangles, int trianglesLength, float* uvs); +void spSkeletonClipping_dispose(spSkeletonClipping* self); + +#ifdef __cplusplus +} +#endif + +#endif /* SPINE_SKELETONCLIPPING_H */ diff --git a/spine-c/spine-c/include/spine/spine.h b/spine-c/spine-c/include/spine/spine.h index 4837ac31d..e57b33f5f 100644 --- a/spine-c/spine-c/include/spine/spine.h +++ b/spine-c/spine-c/include/spine/spine.h @@ -54,7 +54,7 @@ #include #include #include -#include +#include #include #include diff --git a/spine-c/spine-c/src/spine/SkeletonClipping.c b/spine-c/spine-c/src/spine/SkeletonClipping.c new file mode 100644 index 000000000..5a2c5ddd9 --- /dev/null +++ b/spine-c/spine-c/src/spine/SkeletonClipping.c @@ -0,0 +1,312 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF + * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +spSkeletonClipping* spSkeletonClipping_create() { + spSkeletonClipping* clipping = CALLOC(spSkeletonClipping, 1); + + clipping->triangulator = spTriangulator_create(); + clipping->clippingPolygon = spFloatArray_create(128); + clipping->clipOutput = spFloatArray_create(128); + clipping->clippedVertices = spFloatArray_create(128); + clipping->clippedUVs = spFloatArray_create(128); + clipping->clippedTriangles = spShortArray_create(128); + clipping->scratch = spFloatArray_create(128); + + return clipping; +} + +void spSkeletonClipping_dispose(spSkeletonClipping* self) { + spTriangulator_dispose(self->triangulator); + spFloatArray_dispose(self->clippingPolygon); + spFloatArray_dispose(self->clipOutput); + spFloatArray_dispose(self->clippedVertices); + spFloatArray_dispose(self->clippedUVs); + spShortArray_dispose(self->clippedTriangles); + spFloatArray_dispose(self->scratch); + FREE(self); +} + +static void _makeClockwise (spFloatArray* polygon) { + int i, n, lastX; + float* vertices = polygon->items; + int verticeslength = polygon->size; + + float area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x, p1y, p2x, p2y; + for (i = 0, n = verticeslength - 3; i < n; i += 2) { + p1x = vertices[i]; + p1y = vertices[i + 1]; + p2x = vertices[i + 2]; + p2y = vertices[i + 3]; + area += p1x * p2y - p2x * p1y; + } + if (area < 0) return; + + for (i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { + float x = vertices[i], y = vertices[i + 1]; + int other = lastX - i; + vertices[i] = vertices[other]; + vertices[i + 1] = vertices[other + 1]; + vertices[other] = x; + vertices[other + 1] = y; + } +} + +int spSkeletonClipping_clipStart(spSkeletonClipping* self, spSlot* slot, spClippingAttachment* clip) { + int i, n; + float* vertices; + if (self->clipAttachment) return 0; + self->clipAttachment = clip; + + n = clip->super.worldVerticesLength; + vertices = spFloatArray_setSize(self->clippingPolygon, n)->items; + spVertexAttachment_computeWorldVertices(SUPER(clip), slot, 0, n, vertices, 0, 2); + _makeClockwise(self->clippingPolygon); + self->clippingPolygons = spTriangulator_decompose(self->triangulator, self->clippingPolygon, spTriangulator_triangulate(self->triangulator, self->clippingPolygon)); + for (i = 0, n = self->clippingPolygons->size; i < n; i++) { + spFloatArray* polygon = self->clippingPolygons->items[i]; + _makeClockwise(polygon); + spFloatArray_add(polygon, polygon->items[0]); + spFloatArray_add(polygon, polygon->items[1]); + } + return self->clippingPolygons->size; +} + +void spSkeletonClipping_clipEnd(spSkeletonClipping* self, spSlot* slot) { + if (self->clipAttachment != 0 && self->clipAttachment->endSlot == slot->data) spSkeletonClipping_clipEnd2(self); +} + +void spSkeletonClipping_clipEnd2(spSkeletonClipping* self) { + if (!self->clipAttachment) return; + self->clipAttachment = 0; + self->clippingPolygons = 0; + spFloatArray_clear(self->clippedVertices); + spFloatArray_clear(self->clippedUVs); + spShortArray_clear(self->clippedTriangles); + spFloatArray_clear(self->clippingPolygon); +} + +int /*boolean*/ spSkeletonClipping_isClipping(spSkeletonClipping* self) { + return self->clipAttachment != 0; +} + +int /*boolean*/ _clip(spSkeletonClipping* self, float x1, float y1, float x2, float y2, float x3, float y3, spFloatArray* clippingArea, spFloatArray* output) { + int i; + spFloatArray* originalOutput = output; + int clipped = 0; + float* clippingVertices; + int clippingVerticesLast; + + spFloatArray* input = 0; + if (clippingArea->size % 4 >= 2) { + input = output; + output = self->scratch; + } else + input = self->scratch; + + spFloatArray_clear(input); + spFloatArray_add(input, x1); + spFloatArray_add(input, y1); + spFloatArray_add(input, x2); + spFloatArray_add(input, y2); + spFloatArray_add(input, x3); + spFloatArray_add(input, y3); + spFloatArray_add(input, x1); + spFloatArray_add(input, y1); + spFloatArray_clear(output); + + clippingVertices = clippingArea->items; + clippingVerticesLast = clippingArea->size - 4; + for (i = 0;; i += 2) { + int ii; + spFloatArray* temp; + float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; + float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; + + float* inputVertices = input->items; + int inputVerticesLength = input->size - 2, outputStart = output->size; + for (ii = 0; ii < inputVerticesLength; ii += 2) { + float inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + float inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; + int side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; + if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) { + float c0, c2; + float ua; + if (side2) { + spFloatArray_add(output, inputX2); + spFloatArray_add(output, inputY2); + continue; + } + c0 = inputY2 - inputY, c2 = inputX2 - inputX; + ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); + spFloatArray_add(output, edgeX + (edgeX2 - edgeX) * ua); + spFloatArray_add(output, edgeY + (edgeY2 - edgeY) * ua); + } else if (side2) { + float c0 = inputY2 - inputY, c2 = inputX2 - inputX; + float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); + spFloatArray_add(output, edgeX + (edgeX2 - edgeX) * ua); + spFloatArray_add(output, edgeY + (edgeY2 - edgeY) * ua); + spFloatArray_add(output, inputX2); + spFloatArray_add(output, inputY2); + } + clipped = 1; + } + + if (outputStart == output->size) { + spFloatArray_clear(originalOutput); + return 1; + } + + spFloatArray_add(output, output->items[0]); + spFloatArray_add(output, output->items[1]); + + if (i == clippingVerticesLast) break; + temp = output; + output = input; + spFloatArray_clear(output); + input = temp; + } + + if (originalOutput != output) { + spFloatArray_clear(originalOutput); + spFloatArray_addAllValues(originalOutput, output->items, 0, output->size - 2); + } else + spFloatArray_setSize(originalOutput, originalOutput->size - 2); + + return clipped; +} + +void spSkeletonClipping_clipTriangles(spSkeletonClipping* self, float* vertices, int verticesLength, short* triangles, int trianglesLength, float* uvs) { + int i; + spFloatArray* clipOutput = self->clipOutput; + spFloatArray* clippedVertices = self->clippedVertices; + spFloatArray* clippedUVs = self->clippedUVs; + spShortArray* clippedTriangles = self->clippedTriangles; + spFloatArray** polygons = self->clippingPolygons->items; + int polygonsCount = self->clippingPolygons->size; + int vertexSize = 2; + + short index = 0; + spFloatArray_clear(clippedVertices); + spFloatArray_clear(clippedUVs); + spShortArray_clear(clippedTriangles); + outer: + for (i = 0; i < trianglesLength; i += 3) { + int p; + int vertexOffset = triangles[i] << 1; + float x2, y2, u2, v2, x3, y3, u3, v3; + float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + float u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + + vertexOffset = triangles[i + 1] << 1; + x2 = vertices[vertexOffset]; y2 = vertices[vertexOffset + 1]; + u2 = uvs[vertexOffset]; v2 = uvs[vertexOffset + 1]; + + vertexOffset = triangles[i + 2] << 1; + x3 = vertices[vertexOffset]; y3 = vertices[vertexOffset + 1]; + u3 = uvs[vertexOffset]; v3 = uvs[vertexOffset + 1]; + + for (p = 0; p < polygonsCount; p++) { + int s = clippedVertices->size; + if (_clip(self, x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + int ii; + float d0, d1, d2, d4, d; + short* clippedTrianglesItems; + int clipOutputCount; + float* clipOutputItems; + float* clippedVerticesItems; + float* clippedUVsItems; + + int clipOutputLength = clipOutput->size; + if (clipOutputLength == 0) continue; + d0 = y2 - y3; d1 = x3 - x2; d2 = x1 - x3; d4 = y3 - y1; + d = 1 / (d0 * d2 + d1 * (y1 - y3)); + + clipOutputCount = clipOutputLength >> 1; + clipOutputItems = clipOutput->items; + clippedVerticesItems = spFloatArray_setSize(clippedVertices, s + clipOutputCount * vertexSize)->items; + clippedUVsItems = spFloatArray_setSize(clippedUVs, s + clipOutputCount * vertexSize)->items; + for (ii = 0; ii < clipOutputLength; ii += 2) { + float c0, c1, a, b, c; + float x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; + clippedVerticesItems[s] = x; + clippedVerticesItems[s + 1] = y; + c0 = x - x3; c1 = y - y3; + a = (d0 * c0 + d1 * c1) * d; + b = (d4 * c0 + d2 * c1) * d; + c = 1 - a - b; + clippedUVsItems[s] = u1 * a + u2 * b + u3 * c; + clippedUVsItems[s + 1] = v1 * a + v2 * b + v3 * c; + s += 2; + } + + s = clippedTriangles->size; + clippedTrianglesItems = spShortArray_setSize(clippedTriangles, s + 3 * (clipOutputCount - 2))->items; + clipOutputCount--; + for (ii = 1; ii < clipOutputCount; ii++) { + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = (short)(index + ii); + clippedTrianglesItems[s + 2] = (short)(index + ii + 1); + s += 3; + } + index += clipOutputCount + 1; + + } else { + short* clippedTrianglesItems; + float* clippedVerticesItems = spFloatArray_setSize(clippedVertices, s + 3 * vertexSize)->items; + float* clippedUVsItems = spFloatArray_setSize(clippedUVs, s + 3 * vertexSize)->items; + clippedVerticesItems[s] = x1; + clippedVerticesItems[s + 1] = y1; + clippedVerticesItems[s + 2] = x2; + clippedVerticesItems[s + 3] = y2; + clippedVerticesItems[s + 4] = x3; + clippedVerticesItems[s + 5] = y3; + + clippedUVsItems[s] = u1; + clippedUVsItems[s + 1] = v1; + clippedUVsItems[s + 2] = u2; + clippedUVsItems[s + 3] = v2; + clippedUVsItems[s + 4] = u3; + clippedUVsItems[s + 5] = v3; + + s = clippedTriangles->size; + clippedTrianglesItems = spShortArray_setSize(clippedTriangles, s + 3)->items; + clippedTrianglesItems[s] = index; + clippedTrianglesItems[s + 1] = (short)(index + 1); + clippedTrianglesItems[s + 2] = (short)(index + 2); + index += 3; + goto outer; + } + } + } +} diff --git a/spine-c/spine-c/src/spine/Triangulator.c b/spine-c/spine-c/src/spine/Triangulator.c index 11136a54e..c4dbde83d 100644 --- a/spine-c/spine-c/src/spine/Triangulator.c +++ b/spine-c/spine-c/src/spine/Triangulator.c @@ -231,11 +231,9 @@ spArrayFloatArray* spTriangulator_decompose(spTriangulator* self, spFloatArray* spArrayShortArray_clear(convexPolygonsIndices); polygonIndices = _obtainPolygonIndices(self); - printf("Obtained indices 0x%x\n", polygonIndices); spShortArray_clear(polygonIndices); polygon = _obtainPolygon(self); - printf("Obtained polygon 0x%x\n", polygon); spFloatArray_clear(polygon); fanBaseIndex = -1; lastWinding = 0; @@ -264,9 +262,11 @@ spArrayFloatArray* spTriangulator_decompose(spTriangulator* self, spFloatArray* if (polygon->size > 0) { spArrayFloatArray_add(convexPolygons, polygon); spArrayShortArray_add(convexPolygonsIndices, polygonIndices); + } else { + _freePolygon(self, polygon); + _freePolygonIndices(self, polygonIndices); } polygon = _obtainPolygon(self); - printf("Obtained polygon #2 0x%x\n", polygon); spFloatArray_clear(polygon); spFloatArray_add(polygon, x1); spFloatArray_add(polygon, y1); @@ -275,7 +275,6 @@ spArrayFloatArray* spTriangulator_decompose(spTriangulator* self, spFloatArray* spFloatArray_add(polygon, x3); spFloatArray_add(polygon, y3); polygonIndices = _obtainPolygonIndices(self); - printf("Obtained indices #2 0x%x\n", polygonIndices); spShortArray_clear(polygonIndices); spShortArray_add(polygonIndices, t1); spShortArray_add(polygonIndices, t2); @@ -352,6 +351,9 @@ spArrayFloatArray* spTriangulator_decompose(spTriangulator* self, spFloatArray* if (polygon->size == 0) { spArrayFloatArray_removeAt(convexPolygons, i); _freePolygon(self, polygon); + polygonIndices = convexPolygonsIndices->items[i]; + spArrayShortArray_removeAt(convexPolygonsIndices, i); + _freePolygonIndices(self, polygonIndices); } } diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java index ee60dfc42..379b9c2a1 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/SkeletonClipping.java @@ -33,7 +33,12 @@ package com.esotericsoftware.spine.utils; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.ShortArray; +import com.esotericsoftware.spine.Bone; +import com.esotericsoftware.spine.BoneData; +import com.esotericsoftware.spine.Skeleton; +import com.esotericsoftware.spine.SkeletonData; import com.esotericsoftware.spine.Slot; +import com.esotericsoftware.spine.SlotData; import com.esotericsoftware.spine.attachments.ClippingAttachment; public class SkeletonClipping { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/Triangulator.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/Triangulator.java index f7ef28207..3b97dee8c 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/Triangulator.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/Triangulator.java @@ -277,15 +277,4 @@ class Triangulator { float px = p2x - p1x, py = p2y - p1y; return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1; } - - public static void main (String[] args) { - Triangulator triangulator = new Triangulator(); - FloatArray polygon = new FloatArray(); - polygon.addAll(0, 0, 100, 0, 100, 100, 0, 100); - ShortArray triangles = triangulator.triangulate(polygon); - System.out.println(triangles); - - Array polys = triangulator.decompose(polygon, triangles); - System.out.println(polys); - } }