mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 23:34:53 +08:00
[c] Added SkeletonClipping and unit/leak test
This commit is contained in:
parent
6a5e035cb5
commit
537f033dad
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)); \
|
||||
|
||||
@ -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
spine-c/spine-c/include/spine/SkeletonClipping.h
Normal file
67
spine-c/spine-c/include/spine/SkeletonClipping.h
Normal file
@ -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 */
|
||||
@ -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
spine-c/spine-c/src/spine/SkeletonClipping.c
Normal file
312
spine-c/spine-c/src/spine/SkeletonClipping.c
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user