Browse Source

[c] Added SkeletonClipping and unit/leak test

badlogic 8 years ago
parent
commit
537f033dad

+ 82 - 1
spine-c/spine-c-unit-tests/tests/MemoryTestFixture.cpp

@@ -1,4 +1,5 @@
-#include "MemoryTestFixture.h" 
+#include <spine/extension.h>
+#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);
+}
+
 

+ 2 - 0
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

+ 8 - 0
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)); \

+ 1 - 0
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

+ 67 - 0
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 <spine/Array.h>
+#include <spine/ClippingAttachment.h>
+#include <spine/Slot.h>
+#include <spine/Triangulator.h>
+
+#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 */

+ 1 - 1
spine-c/spine-c/include/spine/spine.h

@@ -54,7 +54,7 @@
 #include <spine/Skin.h>
 #include <spine/Slot.h>
 #include <spine/SlotData.h>
-#include <spine/Triangulator.h>
+#include <spine/SkeletonClipping.h>
 #include <spine/Event.h>
 #include <spine/EventData.h>
 

+ 312 - 0
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 <spine/SkeletonClipping.h>
+#include <spine/extension.h>
+
+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;
+			}
+		}
+	}
+}

+ 6 - 4
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);
 		}
 	}
 

+ 5 - 0
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 {

+ 0 - 11
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<FloatArray> polys = triangulator.decompose(polygon,  triangles);
-		System.out.println(polys);
-	}
 }