소스 검색

[libgdx] Added convex decomposition to SkeletonRenderer.

badlogic 8 년 전
부모
커밋
ace38dca5f

+ 7 - 7
spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/ClippingTest.java

@@ -90,13 +90,13 @@ public class ClippingTest extends ApplicationAdapter {
 		ClippingAttachment clip = new ClippingAttachment("clip");
 		// Rectangle:
 		clip.setVertices(
-			new float[] { 87, 288, 217, 371, 456, 361, 539, 175, 304, 194, 392, 290, 193, 214, 123, 15, 14, 137 });	
-//		new float[] { //
-//			-140, 50, //
-//			250, 50, //
-//			250, 350, //
-//			-140, 350, //
-//		});
+//			new float[] { 87, 288, 217, 371, 456, 361, 539, 175, 304, 194, 392, 290, 193, 214, 123, 15, 14, 137 });	
+		new float[] { //
+			-140, 50, //
+			250, 50, //
+			250, 350, //
+			-140, 350, //
+		});
 		// Self intersection:
 //		clip.setVertices(new float[] { //
 //			-140, -50, //

+ 125 - 117
spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonRenderer.java

@@ -49,6 +49,7 @@ import com.esotericsoftware.spine.attachments.MeshAttachment;
 import com.esotericsoftware.spine.attachments.RegionAttachment;
 import com.esotericsoftware.spine.attachments.SkeletonAttachment;
 import com.esotericsoftware.spine.utils.Clipper;
+import com.esotericsoftware.spine.utils.ConvexDecomposer;
 import com.esotericsoftware.spine.utils.TwoColorPolygonBatch;
 
 public class SkeletonRenderer {
@@ -57,12 +58,13 @@ public class SkeletonRenderer {
 	private boolean softwareClipping;
 	private boolean premultipliedAlpha;
 	private final FloatArray vertices = new FloatArray(32);
-
-	private Clipper clipper = new Clipper();
+	
 	private ClippingAttachment clipAttachment;
 	private Slot clipEnd;
-	private FloatArray clippingArea = new FloatArray();
-	private boolean clippingAreaClockwise;
+	private Clipper clipper = new Clipper();
+	private ConvexDecomposer decomposer = new ConvexDecomposer();
+	private FloatArray clippingPolygon = new FloatArray(400);
+	private Array<FloatArray> convexClippingPolygons;
 	private FloatArray clipOutput = new FloatArray(400);
 	private FloatArray clippedVertices = new FloatArray(400);	
 	private ShortArray clippedTriangles = new ShortArray(400);
@@ -404,18 +406,22 @@ public class SkeletonRenderer {
 			Gdx.gl.glStencilOp(GL20.GL_KEEP, GL20.GL_KEEP, GL20.GL_KEEP);
 		} else {
 			int n = clip.getWorldVerticesLength();
-			float[] vertices = this.clippingArea.setSize(n);
+			float[] vertices = this.clippingPolygon.setSize(n);
 			clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
-			clippingAreaClockwise = Clipper.isClockwise(this.clippingArea);
-			if (!clippingAreaClockwise) {
-				Clipper.makeClockwise(clippingArea);
+			convexClippingPolygons = decomposer.decompose(clippingPolygon);
+			for (FloatArray poly: convexClippingPolygons) {
+				Clipper.makeClockwise(poly);
+				poly.add(poly.items[0]);
+				poly.add(poly.items[1]);
 			}
-			clippingArea.add(clippingArea.items[0]);
-			clippingArea.add(clippingArea.items[1]);
 		}
 	}
 
 	private void clipEnd() {
+		clippedVertices.clear();
+		clippedTriangles.clear();
+		clippingPolygon.clear();
+		convexClippingPolygons = null;
 		clipAttachment = null;
 		clipEnd = null;
 		if (!softwareClipping) Gdx.gl.glDisable(GL20.GL_STENCIL_TEST);
@@ -425,124 +431,126 @@ public class SkeletonRenderer {
 		short idx = 0;
 		clippedVertices.clear();
 		clippedTriangles.clear();
-		for (int i = 0; i < trianglesLength; i += 3) {
-			int vertexOffset = triangles[i] << 1;
-			float x1 = vertices[vertexOffset];
-			float y1= vertices[vertexOffset + 1];
-			float u1 = uvs[vertexOffset];
-			float v1 = uvs[vertexOffset + 1];
-			
-			vertexOffset = triangles[i + 1] << 1;
-			float x2 = vertices[vertexOffset];
-			float y2 = vertices[vertexOffset + 1];
-			float u2 = uvs[vertexOffset];
-			float v2 = uvs[vertexOffset + 1];
-			
-			vertexOffset = triangles[i + 2] << 1;
-			float x3 = vertices[vertexOffset];
-			float y3 = vertices[vertexOffset + 1];
-			float u3 = uvs[vertexOffset];
-			float v3 = uvs[vertexOffset + 1];
-			
-			boolean clipped = clipper.clip(x1, y1, x2, y2, x3, y3, clippingArea, clipOutput);
-			if (clipped) {
-				if (clipOutput.size == 0) continue;
-				float d0 = y2 - y3;
-				float d1 = x3 - x2;
-				float d2 = x1 - x3;
-				float d3 = y1 - y3;
-				float d4 = y3 - y1;
+		for (FloatArray convexClippingPolygon: convexClippingPolygons) {
+			for (int i = 0; i < trianglesLength; i += 3) {
+				int vertexOffset = triangles[i] << 1;
+				float x1 = vertices[vertexOffset];
+				float y1= vertices[vertexOffset + 1];
+				float u1 = uvs[vertexOffset];
+				float v1 = uvs[vertexOffset + 1];
 				
-				float denom = 1 / (d0 * d2 + d1 * d3);
+				vertexOffset = triangles[i + 1] << 1;
+				float x2 = vertices[vertexOffset];
+				float y2 = vertices[vertexOffset + 1];
+				float u2 = uvs[vertexOffset];
+				float v2 = uvs[vertexOffset + 1];
 				
-				float[] clipVertices = clipOutput.items;
-				int s = clippedVertices.size;
-				clippedVertices.setSize(s + (clipOutput.size >> 1) * (twoColor ? 6 : 5));
-				final float[] clippedVerticesArray = clippedVertices.items;
+				vertexOffset = triangles[i + 2] << 1;
+				float x3 = vertices[vertexOffset];
+				float y3 = vertices[vertexOffset + 1];
+				float u3 = uvs[vertexOffset];
+				float v3 = uvs[vertexOffset + 1];
 				
-				for (int j = 0, n = clipOutput.size; j < n; j += 2) {				
-					float x = clipVertices[j];
-					float y = clipVertices[j + 1];
+				boolean clipped = clipper.clip(x1, y1, x2, y2, x3, y3, convexClippingPolygon, clipOutput);
+				if (clipped) {
+					if (clipOutput.size == 0) continue;
+					float d0 = y2 - y3;
+					float d1 = x3 - x2;
+					float d2 = x1 - x3;
+					float d3 = y1 - y3;
+					float d4 = y3 - y1;
+					
+					float denom = 1 / (d0 * d2 + d1 * d3);
+					
+					float[] clipVertices = clipOutput.items;
+					int s = clippedVertices.size;
+					clippedVertices.setSize(s + (clipOutput.size >> 1) * (twoColor ? 6 : 5));
+					final float[] clippedVerticesArray = clippedVertices.items;
+					
+					for (int j = 0, n = clipOutput.size; j < n; j += 2) {				
+						float x = clipVertices[j];
+						float y = clipVertices[j + 1];
+							
+						float c0 = x - x3;
+						float c1 = y - y3;
+						float a = (d0 * c0 + d1 * c1) * denom;
+						float b = (d4 * c0 + d2 * c1) * denom;
+						float c = 1.0f - a - b;
 						
-					float c0 = x - x3;
-					float c1 = y - y3;
-					float a = (d0 * c0 + d1 * c1) * denom;
-					float b = (d4 * c0 + d2 * c1) * denom;
-					float c = 1.0f - a - b;
+						float u = u1 * a + u2 * b + u3 * c;
+						float v = v1 * a + v2 * b + v3 * c;
+						clippedVerticesArray[s++] = x;
+						clippedVerticesArray[s++] = y;
+						clippedVerticesArray[s++] = light;
+						if (twoColor) clippedVerticesArray[s++] = dark;
+						clippedVerticesArray[s++] = u;
+						clippedVerticesArray[s++] = v;
+					}
 					
-					float u = u1 * a + u2 * b + u3 * c;
-					float v = v1 * a + v2 * b + v3 * c;
-					clippedVerticesArray[s++] = x;
-					clippedVerticesArray[s++] = y;
-					clippedVerticesArray[s++] = light;
-					if (twoColor) clippedVerticesArray[s++] = dark;
-					clippedVerticesArray[s++] = u;
-					clippedVerticesArray[s++] = v;
-				}
-				
-				s = clippedTriangles.size;
-				clippedTriangles.setSize(s + 3 * ((clipOutput.size >> 1) - 2));
-				final short[] clippedTrianglesArray = clippedTriangles.items;
-				
-				for (int j = 1, n = (clipOutput.size >> 1) - 1; j < n; j++) {
-					clippedTrianglesArray[s++] = idx;
-					clippedTrianglesArray[s++] = (short)(idx + j);
-					clippedTrianglesArray[s++] = (short)(idx + j + 1);
-				}
-				
-				idx += clipOutput.size >> 1;
-			} else {
-				int s = clippedVertices.size;
-				clippedVertices.setSize(s + 3 * (twoColor ? 6 : 5));
-				final float[] clippedVerticesArray = clippedVertices.items;
-				
-				if (!twoColor) { 
-					clippedVerticesArray[s] = x1;
-					clippedVerticesArray[s + 1] = y1;
-					clippedVerticesArray[s + 2] = light;
-					clippedVerticesArray[s + 3] = u1;
-					clippedVerticesArray[s + 4] = v1;
+					s = clippedTriangles.size;
+					clippedTriangles.setSize(s + 3 * ((clipOutput.size >> 1) - 2));
+					final short[] clippedTrianglesArray = clippedTriangles.items;
 					
-					clippedVerticesArray[s + 5] = x2;
-					clippedVerticesArray[s + 6] = y2;
-					clippedVerticesArray[s + 7] = light;
-					clippedVerticesArray[s + 8] = u2;
-					clippedVerticesArray[s + 9] = v2;
+					for (int j = 1, n = (clipOutput.size >> 1) - 1; j < n; j++) {
+						clippedTrianglesArray[s++] = idx;
+						clippedTrianglesArray[s++] = (short)(idx + j);
+						clippedTrianglesArray[s++] = (short)(idx + j + 1);
+					}
 					
-					clippedVerticesArray[s + 10] = x3;
-					clippedVerticesArray[s + 11] = y3;
-					clippedVerticesArray[s + 12] = light;
-					clippedVerticesArray[s + 13] = u3;
-					clippedVerticesArray[s + 14] = v3;
+					idx += clipOutput.size >> 1;
 				} else {
-					clippedVerticesArray[s] = x1;
-					clippedVerticesArray[s + 1] = y1;
-					clippedVerticesArray[s + 2] = light;
-					clippedVerticesArray[s + 3] = dark;
-					clippedVerticesArray[s + 4] = u1;
-					clippedVerticesArray[s + 5] = v1;
+					int s = clippedVertices.size;
+					clippedVertices.setSize(s + 3 * (twoColor ? 6 : 5));
+					final float[] clippedVerticesArray = clippedVertices.items;
 					
-					clippedVerticesArray[s + 6] = x2;
-					clippedVerticesArray[s + 7] = y2;
-					clippedVerticesArray[s + 8] = light;
-					clippedVerticesArray[s + 9] = dark;
-					clippedVerticesArray[s + 10] = u2;
-					clippedVerticesArray[s + 11] = v2;
+					if (!twoColor) { 
+						clippedVerticesArray[s] = x1;
+						clippedVerticesArray[s + 1] = y1;
+						clippedVerticesArray[s + 2] = light;
+						clippedVerticesArray[s + 3] = u1;
+						clippedVerticesArray[s + 4] = v1;
+						
+						clippedVerticesArray[s + 5] = x2;
+						clippedVerticesArray[s + 6] = y2;
+						clippedVerticesArray[s + 7] = light;
+						clippedVerticesArray[s + 8] = u2;
+						clippedVerticesArray[s + 9] = v2;
+						
+						clippedVerticesArray[s + 10] = x3;
+						clippedVerticesArray[s + 11] = y3;
+						clippedVerticesArray[s + 12] = light;
+						clippedVerticesArray[s + 13] = u3;
+						clippedVerticesArray[s + 14] = v3;
+					} else {
+						clippedVerticesArray[s] = x1;
+						clippedVerticesArray[s + 1] = y1;
+						clippedVerticesArray[s + 2] = light;
+						clippedVerticesArray[s + 3] = dark;
+						clippedVerticesArray[s + 4] = u1;
+						clippedVerticesArray[s + 5] = v1;
+						
+						clippedVerticesArray[s + 6] = x2;
+						clippedVerticesArray[s + 7] = y2;
+						clippedVerticesArray[s + 8] = light;
+						clippedVerticesArray[s + 9] = dark;
+						clippedVerticesArray[s + 10] = u2;
+						clippedVerticesArray[s + 11] = v2;
+						
+						clippedVerticesArray[s + 12] = x3;
+						clippedVerticesArray[s + 13] = y3;
+						clippedVerticesArray[s + 14] = light;
+						clippedVerticesArray[s + 15] = dark;
+						clippedVerticesArray[s + 16] = u3;
+						clippedVerticesArray[s + 17] = v3;
+					}
 					
-					clippedVerticesArray[s + 12] = x3;
-					clippedVerticesArray[s + 13] = y3;
-					clippedVerticesArray[s + 14] = light;
-					clippedVerticesArray[s + 15] = dark;
-					clippedVerticesArray[s + 16] = u3;
-					clippedVerticesArray[s + 17] = v3;
+					s = clippedTriangles.size;
+					clippedTriangles.setSize(s + 3);
+					final short[] clippedTrianglesArray = clippedTriangles.items;
+					clippedTrianglesArray[s] = idx++;
+					clippedTrianglesArray[s + 1] = idx++;
+					clippedTrianglesArray[s + 2] = idx++;
 				}
-				
-				s = clippedTriangles.size;
-				clippedTriangles.setSize(s + 3);
-				final short[] clippedTrianglesArray = clippedTriangles.items;
-				clippedTrianglesArray[s] = idx++;
-				clippedTrianglesArray[s + 1] = idx++;
-				clippedTrianglesArray[s + 2] = idx++;
 			}
 		}
 	}