More prettying.

This commit is contained in:
Nathan Sweet 2017-04-01 10:14:06 +09:00
parent 6e97b7e75f
commit 058b7587e1
2 changed files with 62 additions and 74 deletions

View File

@ -145,7 +145,7 @@ public class Clipper {
} }
if (area + vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1] < 0) return; if (area + vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1] < 0) return;
for (int i = 0, lastX = verticeslength - 2, n = verticeslength / 2; i < n; i += 2) { for (int i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {
float x = vertices[i], y = vertices[i + 1]; float x = vertices[i], y = vertices[i + 1];
int other = lastX - i; int other = lastX - i;
vertices[i] = vertices[other]; vertices[i] = vertices[other];

View File

@ -30,8 +30,6 @@
package com.esotericsoftware.spine.utils; package com.esotericsoftware.spine.utils;
import java.util.Iterator;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.BooleanArray; import com.badlogic.gdx.utils.BooleanArray;
import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.FloatArray;
@ -43,79 +41,99 @@ public class ConvexDecomposer {
private final Array<ShortArray> convexPolygonsIndices = new Array(); private final Array<ShortArray> convexPolygonsIndices = new Array();
private final ShortArray indicesArray = new ShortArray(); private final ShortArray indicesArray = new ShortArray();
private short[] indices;
private float[] vertices;
private int vertexCount;
private final BooleanArray isConcaveArray = new BooleanArray(); private final BooleanArray isConcaveArray = new BooleanArray();
private final ShortArray triangles = new ShortArray(); private final ShortArray triangles = new ShortArray();
private final Pool<FloatArray> polygonPool = new Pool<FloatArray>() { private final Pool<FloatArray> polygonPool = new Pool() {
protected FloatArray newObject () { protected FloatArray newObject () {
return new FloatArray(16); return new FloatArray(16);
} }
}; };
private final Pool<ShortArray> polygonIndicesPool = new Pool<ShortArray>() { private final Pool<ShortArray> polygonIndicesPool = new Pool() {
protected ShortArray newObject () { protected ShortArray newObject () {
return new ShortArray(16); return new ShortArray(16);
} }
}; };
public Array<FloatArray> decompose (FloatArray input) { public Array<FloatArray> decompose (FloatArray input) {
vertices = input.items; float[] vertices = input.items;
int vertexCount = this.vertexCount = input.size / 2; int vertexCount = input.size >> 1;
ShortArray indicesArray = this.indicesArray; ShortArray indicesArray = this.indicesArray;
indicesArray.clear(); indicesArray.clear();
short[] indices = this.indices = indicesArray.setSize(vertexCount); short[] indices = indicesArray.setSize(vertexCount);
for (short i = 0; i < vertexCount; i++) for (short i = 0; i < vertexCount; i++)
indices[i] = i; indices[i] = i;
BooleanArray isConcaveArray = this.isConcaveArray;
boolean[] isConcave = isConcaveArray.setSize(vertexCount); boolean[] isConcave = isConcaveArray.setSize(vertexCount);
for (int i = 0, n = vertexCount; i < n; ++i) for (int i = 0, n = vertexCount; i < n; ++i)
isConcave[i] = isConcave(i); isConcave[i] = isConcave(i, vertexCount, vertices, indices);
ShortArray triangles = this.triangles; ShortArray triangles = this.triangles;
triangles.clear(); triangles.clear();
triangles.ensureCapacity(Math.max(0, vertexCount - 2) * 4); triangles.ensureCapacity(Math.max(0, vertexCount - 2) << 2);
// Triangulate. // Triangulate.
while (this.vertexCount > 3) { while (vertexCount > 3) {
int earTipIndex = findEarTip(); // Find ear tip.
cutEarTip(earTipIndex); int i = 0;
while (true) {
if (!isConcave[i] && isEarTip(i, vertexCount, vertices, indices)) break;
i++;
if (i == vertexCount) {
do {
i--;
if (!isConcave[i]) break;
} while (i > 0);
break;
}
}
int previousIndex = previousIndex(earTipIndex); // Cut ear tip.
int nextIndex = earTipIndex == vertexCount ? 0 : earTipIndex; triangles.add(indices[previousIndex(i, vertexCount)]);
isConcave[previousIndex] = isConcave(previousIndex); triangles.add(indices[i]);
isConcave[nextIndex] = isConcave(nextIndex); triangles.add(indices[nextIndex(i, vertexCount)]);
indicesArray.removeIndex(i);
isConcaveArray.removeIndex(i);
vertexCount--;
int previousIndex = previousIndex(i, vertexCount);
int nextIndex = i == vertexCount ? 0 : i;
isConcave[previousIndex] = isConcave(previousIndex, vertexCount, vertices, indices);
isConcave[nextIndex] = isConcave(nextIndex, vertexCount, vertices, indices);
} }
if (this.vertexCount == 3) { if (vertexCount == 3) {
triangles.add(indicesArray.get(2)); triangles.add(indicesArray.get(2));
triangles.add(indicesArray.get(0)); triangles.add(indicesArray.get(0));
triangles.add(indicesArray.get(1)); triangles.add(indicesArray.get(1));
} }
Array<FloatArray> convexPolygons = this.convexPolygons;
polygonPool.freeAll(convexPolygons); polygonPool.freeAll(convexPolygons);
convexPolygons.clear(); convexPolygons.clear();
Array<ShortArray> convexPolygonsIndices = this.convexPolygonsIndices;
polygonIndicesPool.freeAll(convexPolygonsIndices); polygonIndicesPool.freeAll(convexPolygonsIndices);
convexPolygonsIndices.clear(); convexPolygonsIndices.clear();
ShortArray polygonIndices = polygonIndicesPool.obtain(); ShortArray polygonIndices = polygonIndicesPool.obtain();
polygonIndices.clear(); polygonIndices.clear();
FloatArray polygon = polygonPool.obtain(); FloatArray polygon = polygonPool.obtain();
polygon.clear(); polygon.clear();
int fanBaseIndex = -1, lastWinding = 0;
// Merge subsequent triangles if they form a triangle fan. // Merge subsequent triangles if they form a triangle fan.
int fanBaseIndex = -1, lastWinding = 0;
for (int i = 0, n = triangles.size; i < n; i += 3) { for (int i = 0, n = triangles.size; i < n; i += 3) {
int t1 = triangles.get(i) << 1, t2 = triangles.get(i + 1) << 1, t3 = triangles.get(i + 2) << 1; int t1 = triangles.get(i) << 1, t2 = triangles.get(i + 1) << 1, t3 = triangles.get(i + 2) << 1;
float x1 = input.get(t1), y1 = input.get(t1 + 1); float x1 = input.get(t1), y1 = input.get(t1 + 1);
float x2 = input.get(t2), y2 = input.get(t2 + 1); float x2 = input.get(t2), y2 = input.get(t2 + 1);
float x3 = input.get(t3), y3 = input.get(t3 + 1); float x3 = input.get(t3), y3 = input.get(t3 + 1);
// If the base of the last triangle is the same as this triangle's base, check if they form a convex polygon (triangle // If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan).
// fan).
boolean merged = false; boolean merged = false;
if (fanBaseIndex == t1) { if (fanBaseIndex == t1) {
int o = polygon.size - 4; int o = polygon.size - 4;
@ -204,10 +222,10 @@ public class ConvexDecomposer {
} }
// Remove empty polygons that resulted from the merge step above. // Remove empty polygons that resulted from the merge step above.
for (Iterator<FloatArray> iter = convexPolygons.iterator(); iter.hasNext();) { for (int i = convexPolygons.size - 1; i >= 0; i--) {
polygon = iter.next(); polygon = convexPolygons.get(i);
if (polygon.size == 0) { if (polygon.size == 0) {
iter.remove(); convexPolygons.removeIndex(i);
polygonPool.free(polygon); polygonPool.free(polygon);
} }
} }
@ -215,45 +233,20 @@ public class ConvexDecomposer {
return convexPolygons; return convexPolygons;
} }
private boolean isConcave (int index) { private boolean isEarTip (int earTipIndex, int vertexCount, float[] vertices, short[] indices) {
short[] indices = this.indices; int previousIndex = previousIndex(earTipIndex, vertexCount);
int previous = indices[previousIndex(index)] * 2; int nextIndex = nextIndex(earTipIndex, vertexCount);
int current = indices[index] * 2; int p1 = indices[previousIndex] << 1;
int next = indices[nextIndex(index)] * 2; int p2 = indices[earTipIndex] << 1;
float[] vertices = this.vertices; int p3 = indices[nextIndex] << 1;
return !positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next],
vertices[next + 1]);
}
private int findEarTip () {
int vertexCount = this.vertexCount;
for (int i = 0; i < vertexCount; i++)
if (isEarTip(i)) return i;
boolean[] isConcave = this.isConcaveArray.items;
for (int i = 0; i < vertexCount; i++)
if (!isConcave[i]) return i;
return 0;
}
private boolean isEarTip (int earTipIndex) {
boolean[] isConcave = this.isConcaveArray.items;
if (isConcave[earTipIndex]) return false;
int previousIndex = previousIndex(earTipIndex);
int nextIndex = nextIndex(earTipIndex);
short[] indices = this.indices;
int p1 = indices[previousIndex] * 2;
int p2 = indices[earTipIndex] * 2;
int p3 = indices[nextIndex] * 2;
float[] vertices = this.vertices;
float p1x = vertices[p1], p1y = vertices[p1 + 1]; float p1x = vertices[p1], p1y = vertices[p1 + 1];
float p2x = vertices[p2], p2y = vertices[p2 + 1]; float p2x = vertices[p2], p2y = vertices[p2 + 1];
float p3x = vertices[p3], p3y = vertices[p3 + 1]; float p3x = vertices[p3], p3y = vertices[p3 + 1];
boolean[] isConcave = this.isConcaveArray.items;
for (int i = nextIndex(nextIndex); i != previousIndex; i = nextIndex(i)) { for (int i = nextIndex(nextIndex, vertexCount); i != previousIndex; i = nextIndex(i, vertexCount)) {
if (isConcave[i]) { if (isConcave[i]) {
int v = indices[i] * 2; int v = indices[i] << 1;
float vx = vertices[v], vy = vertices[v + 1]; float vx = vertices[v], vy = vertices[v + 1];
if (positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { if (positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
if (positiveArea(p1x, p1y, p2x, p2y, vx, vy)) { if (positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
@ -265,24 +258,19 @@ public class ConvexDecomposer {
return true; return true;
} }
private void cutEarTip (int earTipIndex) { static private boolean isConcave (int index, int vertexCount, float[] vertices, short[] indices) {
short[] indices = this.indices; int previous = indices[previousIndex(index, vertexCount)] << 1;
ShortArray triangles = this.triangles; int current = indices[index] << 1;
int next = indices[nextIndex(index, vertexCount)] << 1;
triangles.add(indices[previousIndex(earTipIndex)]); return !positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next],
triangles.add(indices[earTipIndex]); vertices[next + 1]);
triangles.add(indices[nextIndex(earTipIndex)]);
indicesArray.removeIndex(earTipIndex);
isConcaveArray.removeIndex(earTipIndex);
vertexCount--;
} }
private int previousIndex (int index) { static private int previousIndex (int index, int vertexCount) {
return (index == 0 ? vertexCount : index) - 1; return (index == 0 ? vertexCount : index) - 1;
} }
private int nextIndex (int index) { static private int nextIndex (int index, int vertexCount) {
return (index + 1) % vertexCount; return (index + 1) % vertexCount;
} }