소스 검색

[c] Added Triangulator. Decomposition is leaking.

badlogic 8 년 전
부모
커밋
59eb90eb66

+ 1 - 1
spine-c/spine-c-unit-tests/minicppunit/MiniCppUnit.hxx

@@ -201,7 +201,7 @@ public:
 				<< errmsgTag_expected() << " " << expected << " "
 				<< errmsgTag_butWas() << " " << result << "\n";
 
-			TestsListener::theInstance().errorsLog() << anError;
+			// TestsListener::theInstance().errorsLog() << anError;
 
 			TestsListener::theInstance().testHasFailed(anError.str().c_str(), file, linia);
 		}

+ 37 - 0
spine-c/spine-c-unit-tests/tests/MemoryTestFixture.cpp

@@ -219,4 +219,41 @@ void MemoryTestFixture::reproduceIssue_Loop()
 	DisposeAll(skeleton, state, stateData, skeletonData, atlas);
 }
 
+void MemoryTestFixture::triangulator() {
+	spTriangulator* triangulator = spTriangulator_create();
+	spFloatArray* polygon = spFloatArray_create(16);
+	spFloatArray_add(polygon, 0);
+	spFloatArray_add(polygon, 0);
+	spFloatArray_add(polygon, 100);
+	spFloatArray_add(polygon, 0);
+	spFloatArray_add(polygon, 100);
+	spFloatArray_add(polygon, 100);
+	spFloatArray_add(polygon, 0);
+	spFloatArray_add(polygon, 100);
+
+	spShortArray* triangles = spTriangulator_triangulate(triangulator, polygon);
+	ASSERT(triangles->size == 6);
+	ASSERT(triangles->items[0] == 3);
+	ASSERT(triangles->items[1] == 0);
+	ASSERT(triangles->items[2] == 1);
+	ASSERT(triangles->items[3] == 3);
+	ASSERT(triangles->items[4] == 1);
+	ASSERT(triangles->items[5] == 2);
+
+	spArrayFloatArray* polys = spTriangulator_decompose(triangulator, polygon, triangles);
+	ASSERT(polys->size == 1);
+	ASSERT(polys->items[0]->size == 8);
+	ASSERT(polys->items[0]->items[0] == 0);
+	ASSERT(polys->items[0]->items[1] == 100);
+	ASSERT(polys->items[0]->items[2] == 0);
+	ASSERT(polys->items[0]->items[3] == 0);
+	ASSERT(polys->items[0]->items[4] == 100);
+	ASSERT(polys->items[0]->items[5] == 0);
+	ASSERT(polys->items[0]->items[6] == 100);
+	ASSERT(polys->items[0]->items[7] == 100);
+
+	spFloatArray_dispose(polygon);
+	spTriangulator_dispose(triangulator);
+}
+
 

+ 2 - 0
spine-c/spine-c-unit-tests/tests/MemoryTestFixture.h

@@ -18,6 +18,7 @@ public:
 		TEST_CASE(reproduceIssue_776);
 		TEST_CASE(reproduceIssue_777);
 		TEST_CASE(reproduceIssue_Loop);
+		TEST_CASE(triangulator);
 
 		initialize();
 	}
@@ -31,6 +32,7 @@ public:
 	void reproduceIssue_776();
 	void reproduceIssue_777();
 	void reproduceIssue_Loop(); // http://esotericsoftware.com/forum/spine-c-3-5-animation-jerking-7451
+	void triangulator();
 
 	//////////////////////////////////////////////////////////////////////////
 	// test fixture setup

+ 13 - 3
spine-c/spine-c/include/spine/Array.h

@@ -40,7 +40,7 @@ extern "C" {
 	name* name##_create(int initialCapacity); \
 	void name##_dispose(name* self); \
 	void name##_clear(name* self); \
-	void name##_setSize(name* self, int newSize); \
+	name* name##_setSize(name* self, int newSize); \
 	void name##_ensureCapacity(name* self, int newCapacity); \
 	void name##_add(name* self, itemType value); \
 	void name##_removeAt(name* self, int index); \
@@ -50,7 +50,7 @@ extern "C" {
 
 #define _SP_ARRAY_IMPLEMENT_TYPE(name, itemType) \
 	name* name##_create(int initialCapacity) { \
-		name* array = MALLOC(name, 1); \
+		name* array = CALLOC(name, 1); \
 		array->size = 0; \
 		array->capacity = initialCapacity; \
 		array->items = CALLOC(itemType, initialCapacity); \
@@ -63,12 +63,13 @@ extern "C" {
 	void name##_clear(name* self) { \
 		self->size = 0; \
 	} \
-	void name##_setSize(name* self, int newSize) { \
+	name* name##_setSize(name* self, int newSize) { \
 		self->size = newSize; \
 		if (self->capacity < newSize) { \
 			self->capacity = MAX(8, (int)(self->size * 1.75f)); \
 			self->items = REALLOC(self->items, itemType, self->capacity); \
 		} \
+		return self; \
 	} \
 	void name##_ensureCapacity(name* self, int newCapacity) { \
 		if (self->capacity >= newCapacity) return; \
@@ -82,6 +83,12 @@ extern "C" {
 		} \
 		self->items[self->size++] = value; \
 	} \
+	void name##_addAll(name* self, name* other) { \
+		int i = 0; \
+		for (; i < other->size; i++) { \
+			name##_add(self, other->items[i]); \
+		} \
+	} \
 	void name##_removeAt(name* self, int index) { \
 		self->size--; \
 		memmove(self->items + index, self->items + index + 1, sizeof(itemType) * (self->size - index)); \
@@ -107,6 +114,9 @@ extern "C" {
 _SP_ARRAY_DECLARE_TYPE(spFloatArray, float)
 _SP_ARRAY_DECLARE_TYPE(spIntArray, int)
 _SP_ARRAY_DECLARE_TYPE(spShortArray, short)
+_SP_ARRAY_DECLARE_TYPE(spArrayFloatArray, spFloatArray*)
+_SP_ARRAY_DECLARE_TYPE(spArrayShortArray, spShortArray*)
+
 
 #ifdef __cplusplus
 }

+ 17 - 39
spine-c/spine-c/include/spine/Triangulator.h

@@ -31,54 +31,32 @@
 #ifndef SPINE_TRIANGULATOR_H
 #define SPINE_TRIANGULATOR_H
 
+#include <spine/Array.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-typedef struct spTransformConstraintData {
-	const char* const name;
-	int order;
-	int bonesCount;
-	spBoneData** const bones;
-	spBoneData* target;
-	float rotateMix, translateMix, scaleMix, shearMix;
-	float offsetRotation, offsetX, offsetY, offsetScaleX, offsetScaleY, offsetShearY;
-	int /*boolean*/ relative;
-	int /*boolean*/ local;
+typedef struct spTriangulator {
+	spArrayFloatArray* convexPolygons;
+	spArrayShortArray* convexPolygonsIndices;
 
-#ifdef __cplusplus
-	spTransformConstraintData() :
-		name(0),
-		bonesCount(0),
-		bones(0),
-		target(0),
-		rotateMix(0),
-		translateMix(0),
-		scaleMix(0),
-		shearMix(0),
-		offsetRotation(0),
-		offsetX(0),
-		offsetY(0),
-		offsetScaleX(0),
-		offsetScaleY(0),
-		offsetShearY(0),
-		relative(0),
-		local(0) {
-	}
-#endif
-} spTransformConstraintData;
+	spShortArray* indicesArray;
+	spIntArray* isConcaveArray;
+	spShortArray* triangles;
 
-spTransformConstraintData* spTransformConstraintData_create (const char* name);
-void spTransformConstraintData_dispose (spTransformConstraintData* self);
+	spArrayFloatArray* polygonPool;
+	spArrayShortArray* polygonIndicesPool;
+} spTriangulator;
+
+spTriangulator* spTriangulator_create();
+spShortArray* spTriangulator_triangulate(spTriangulator* self, spFloatArray* verticesArray);
+spArrayFloatArray* spTriangulator_decompose(spTriangulator* self, spFloatArray* verticesArray, spShortArray* triangles);
+void spTriangulator_dispose(spTriangulator* self);
 
-#ifdef SPINE_SHORT_NAMES
-typedef spTransformConstraintData TransformConstraintData;
-#define TransformConstraintData_create(...) spTransformConstraintData_create(__VA_ARGS__)
-#define TransformConstraintData_dispose(...) spTransformConstraintData_dispose(__VA_ARGS__)
-#endif
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* SPINE_TRIANGULATOR_H_ */
+#endif /* SPINE_TRIANGULATOR_H_ */

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

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

+ 2 - 0
spine-c/spine-c/src/spine/Array.c

@@ -34,3 +34,5 @@
 _SP_ARRAY_IMPLEMENT_TYPE(spFloatArray, float)
 _SP_ARRAY_IMPLEMENT_TYPE(spIntArray, int)
 _SP_ARRAY_IMPLEMENT_TYPE(spShortArray, short)
+_SP_ARRAY_IMPLEMENT_TYPE(spArrayFloatArray, spFloatArray*)
+_SP_ARRAY_IMPLEMENT_TYPE(spArrayShortArray, spShortArray*)

+ 359 - 0
spine-c/spine-c/src/spine/Triangulator.c

@@ -0,0 +1,359 @@
+/******************************************************************************
+ * 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/Triangulator.h>
+#include <spine/extension.h>
+#include <stdio.h>
+
+spTriangulator* spTriangulator_create() {
+	spTriangulator* triangulator = CALLOC(spTriangulator, 1);
+
+	triangulator->convexPolygons = spArrayFloatArray_create(16);
+	triangulator->convexPolygonsIndices = spArrayShortArray_create(16);
+	triangulator->indicesArray = spShortArray_create(128);
+	triangulator->isConcaveArray = spIntArray_create(128);
+	triangulator->triangles = spShortArray_create(128);
+	triangulator->polygonPool = spArrayFloatArray_create(16);
+	triangulator->polygonIndicesPool = spArrayShortArray_create(128);
+
+	return triangulator;
+}
+
+void spTriangulator_dispose(spTriangulator* self) {
+	int i;
+
+	for (i = 0; i < self->convexPolygons->size; i++) {
+		spFloatArray_dispose(self->convexPolygons->items[i]);
+	}
+	spArrayFloatArray_dispose(self->convexPolygons);
+
+	for (i = 0; i < self->convexPolygonsIndices->size; i++) {
+		spShortArray_dispose(self->convexPolygonsIndices->items[i]);
+	}
+	spArrayShortArray_dispose(self->convexPolygonsIndices);
+
+	spShortArray_dispose(self->indicesArray);
+	spIntArray_dispose(self->isConcaveArray);
+	spShortArray_dispose(self->triangles);
+
+	for (i = 0; i < self->polygonPool->size; i++) {
+		spFloatArray_dispose(self->polygonPool->items[i]);
+	}
+	spArrayFloatArray_dispose(self->polygonPool);
+
+	for (i = 0; i < self->polygonIndicesPool->size; i++) {
+		spShortArray_dispose(self->polygonIndicesPool->items[i]);
+	}
+	spArrayShortArray_dispose(self->polygonIndicesPool);
+
+	FREE(self);
+}
+
+static spFloatArray* _obtainPolygon(spTriangulator* self) {
+	if (self->polygonPool->size == 0) return spFloatArray_create(16);
+	else return spArrayFloatArray_pop(self->polygonPool);
+}
+
+static void _freePolygon(spTriangulator* self, spFloatArray* polygon) {
+	spArrayFloatArray_add(self->polygonPool, polygon);
+}
+
+static void _freeAllPolygons(spTriangulator* self, spArrayFloatArray* polygons) {
+	int i;
+	for (i = 0; i < polygons->size; i++) {
+		_freePolygon(self, polygons->items[i]);
+	}
+}
+
+static spShortArray* _obtainPolygonIndices(spTriangulator* self) {
+	if (self->polygonIndicesPool->size == 0) return spShortArray_create(16);
+	else return spArrayShortArray_pop(self->polygonIndicesPool);
+}
+
+static void _freePolygonIndices(spTriangulator* self, spShortArray* indices) {
+	spArrayShortArray_add(self->polygonIndicesPool, indices);
+}
+
+static void _freeAllPolygonIndices(spTriangulator* self, spArrayShortArray* polygonIndices) {
+	int i;
+	for (i = 0; i < polygonIndices->size; i++) {
+		_freePolygonIndices(self, polygonIndices->items[i]);
+	}
+}
+
+static int _positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) {
+	return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0;
+}
+
+static int _isConcave(int index, int vertexCount, float* vertices, short* indices) {
+	int previous = indices[(vertexCount + index - 1) % vertexCount] << 1;
+	int current = indices[index] << 1;
+	int next = indices[(index + 1) % vertexCount] << 1;
+	return !_positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1],
+						 vertices[next],
+						 vertices[next + 1]);
+}
+
+static int _winding (float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) {
+	float px = p2x - p1x, py = p2y - p1y;
+	return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1;
+}
+
+spShortArray* spTriangulator_triangulate(spTriangulator* self, spFloatArray* verticesArray) {
+	float* vertices = verticesArray->items;
+	int vertexCount = verticesArray->size >> 1;
+	int i, n, ii;
+
+	spShortArray* indicesArray = self->indicesArray;
+	short* indices;
+	spIntArray* isConcaveArray;
+	int* isConcave;
+	spShortArray* triangles;
+
+	spShortArray_clear(indicesArray);
+	indices = spShortArray_setSize(indicesArray, vertexCount)->items;
+	for (i = 0; i < vertexCount; i++)
+		indices[i] = (short)i;
+
+	isConcaveArray = self->isConcaveArray;
+	isConcave = spIntArray_setSize(isConcaveArray, vertexCount)->items;
+	for (i = 0, n = vertexCount; i < n; ++i)
+		isConcave[i] = _isConcave(i, vertexCount, vertices, indices);
+
+	triangles = self->triangles;
+	spShortArray_clear(triangles);
+	spShortArray_ensureCapacity(triangles, MAX(0, vertexCount - 2) << 2);
+
+	while (vertexCount > 3) {
+		int previous = vertexCount - 1, i = 0, next = 1;
+		int previousIndex, nextIndex;
+		while (1) {
+			outer:
+			if (!isConcave[i]) {
+				int p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1;
+				float p1x = vertices[p1], p1y = vertices[p1 + 1];
+				float p2x = vertices[p2], p2y = vertices[p2 + 1];
+				float p3x = vertices[p3], p3y = vertices[p3 + 1];
+				for (ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) {
+					int v;
+					float vx, vy;
+					if (!isConcave[ii]) continue;
+					v = indices[ii] << 1;
+					vx = vertices[v]; vy = vertices[v + 1];
+					if (_positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
+						if (_positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
+							if (_positiveArea(p2x, p2y, p3x, p3y, vx, vy)) goto outer;
+						}
+					}
+				}
+				break;
+			}
+
+			if (next == 0) {
+				do {
+					if (!isConcave[i]) break;
+					i--;
+				} while (i > 0);
+				break;
+			}
+
+			previous = i;
+			i = next;
+			next = (next + 1) % vertexCount;
+		}
+
+		spShortArray_add(triangles, indices[(vertexCount + i - 1) % vertexCount]);
+		spShortArray_add(triangles, indices[i]);
+		spShortArray_add(triangles, indices[(i + 1) % vertexCount]);
+		spShortArray_removeAt(indicesArray, i);
+		spIntArray_removeAt(isConcaveArray, i);
+		vertexCount--;
+
+		previousIndex = (vertexCount + i - 1) % vertexCount;
+		nextIndex = i == vertexCount ? 0 : i;
+		isConcave[previousIndex] = _isConcave(previousIndex, vertexCount, vertices, indices);
+		isConcave[nextIndex] = _isConcave(nextIndex, vertexCount, vertices, indices);
+	}
+
+	if (vertexCount == 3) {
+		spShortArray_add(triangles, indices[2]);
+		spShortArray_add(triangles, indices[0]);
+		spShortArray_add(triangles, indices[1]);
+	}
+
+	return triangles;
+}
+
+spArrayFloatArray* spTriangulator_decompose(spTriangulator* self, spFloatArray* verticesArray, spShortArray* triangles) {
+	float* vertices = verticesArray->items;
+
+	spArrayFloatArray* convexPolygons = self->convexPolygons;
+	spArrayShortArray* convexPolygonsIndices;
+	spShortArray* polygonIndices;
+	spFloatArray* polygon;
+
+	int fanBaseIndex, lastWinding;
+	short* trianglesItems;
+	int i, n;
+
+	_freeAllPolygons(self, convexPolygons);
+	spArrayFloatArray_clear(convexPolygons);
+
+	convexPolygonsIndices = self->convexPolygonsIndices;
+	_freeAllPolygonIndices(self, convexPolygonsIndices);
+	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;
+	trianglesItems = triangles->items;
+	for (i = 0, n = triangles->size; i < n; i += 3) {
+		int t1 = trianglesItems[i] << 1, t2 = trianglesItems[i + 1] << 1, t3 = trianglesItems[i + 2] << 1;
+		float x1 = vertices[t1], y1 = vertices[t1 + 1];
+		float x2 = vertices[t2], y2 = vertices[t2 + 1];
+		float x3 = vertices[t3], y3 = vertices[t3 + 1];
+
+		int merged = 0;
+		if (fanBaseIndex == t1) {
+			int o = polygon->size - 4;
+			float* p = polygon->items;
+			int winding1 = _winding(p[o], p[o + 1], p[o + 2], p[o + 3], x3, y3);
+			int winding2 = _winding(x3, y3, p[0], p[1], p[2], p[3]);
+			if (winding1 == lastWinding && winding2 == lastWinding) {
+				spFloatArray_add(polygon, x3);
+				spFloatArray_add(polygon, y3);
+				spShortArray_add(polygonIndices, t3);
+				merged = 1;
+			}
+		}
+
+		if (!merged) {
+			if (polygon->size > 0) {
+				spArrayFloatArray_add(convexPolygons, polygon);
+				spArrayShortArray_add(convexPolygonsIndices, polygonIndices);
+			}
+			polygon = _obtainPolygon(self);
+			printf("Obtained polygon #2 0x%x\n", polygon);
+			spFloatArray_clear(polygon);
+			spFloatArray_add(polygon, x1);
+			spFloatArray_add(polygon, y1);
+			spFloatArray_add(polygon, x2);
+			spFloatArray_add(polygon, y2);
+			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);
+			spShortArray_add(polygonIndices, t3);
+			lastWinding = _winding(x1, y1, x2, y2, x3, y3);
+			fanBaseIndex = t1;
+		}
+	}
+
+	if (polygon->size > 0) {
+		spArrayFloatArray_add(convexPolygons, polygon);
+		spArrayShortArray_add(convexPolygonsIndices, polygonIndices);
+	}
+
+	for (i = 0, n = convexPolygons->size; i < n; i++) {
+		int firstIndex, lastIndex;
+		int o;
+		float* p;
+		float prevPrevX, prevPrevY, prevX, prevY, firstX, firstY, secondX, secondY;
+		int winding;
+		int ii;
+
+		polygonIndices = convexPolygonsIndices->items[i];
+		if (polygonIndices->size == 0) continue;
+		firstIndex = polygonIndices->items[0];
+		lastIndex = polygonIndices->items[polygonIndices->size - 1];
+
+		polygon = convexPolygons->items[i];
+		o = polygon->size - 4;
+		p = polygon->items;
+		prevPrevX = p[o]; prevPrevY = p[o + 1];
+		prevX = p[o + 2]; prevY = p[o + 3];
+		firstX = p[0]; firstY = p[1];
+		secondX = p[2]; secondY = p[3];
+		winding = _winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY);
+
+		for (ii = 0; ii < n; ii++) {
+			spShortArray* otherIndices;
+			int otherFirstIndex, otherSecondIndex, otherLastIndex;
+			spFloatArray* otherPoly;
+			float x3, y3;
+			int winding1, winding2;
+
+			if (ii == i) continue;
+			otherIndices = convexPolygonsIndices->items[ii];
+			if (otherIndices->size != 3) continue;
+			otherFirstIndex = otherIndices->items[0];
+			otherSecondIndex = otherIndices->items[1];
+			otherLastIndex = otherIndices->items[2];
+
+			otherPoly = convexPolygons->items[ii];
+			x3 = otherPoly->items[otherPoly->size - 2]; y3 = otherPoly->items[otherPoly->size - 1];
+
+			if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue;
+			winding1 = _winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);
+			winding2 = _winding(x3, y3, firstX, firstY, secondX, secondY);
+			if (winding1 == winding && winding2 == winding) {
+				spFloatArray_clear(otherPoly);
+				spShortArray_clear(otherIndices);
+				spFloatArray_add(polygon, x3);
+				spFloatArray_add(polygon, y3);
+				spShortArray_add(polygonIndices, otherLastIndex);
+				prevPrevX = prevX;
+				prevPrevY = prevY;
+				prevX = x3;
+				prevY = y3;
+				ii = 0;
+			}
+		}
+	}
+
+	for (i = convexPolygons->size - 1; i >= 0; i--) {
+		polygon = convexPolygons->items[i];
+		if (polygon->size == 0) {
+			spArrayFloatArray_removeAt(convexPolygons, i);
+			_freePolygon(self, polygon);
+		}
+	}
+
+	return convexPolygons;
+}

+ 11 - 0
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/utils/Triangulator.java

@@ -277,4 +277,15 @@ 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);
+	}
 }