[libgdx] Refactored SkeletonRenderer, moved clipping related code to SkeletonClipping, removed stencil clipping

This commit is contained in:
badlogic 2017-03-31 11:18:39 +02:00
parent 1675658f1a
commit 9ca215f2e9
4 changed files with 253 additions and 271 deletions

View File

@ -61,7 +61,6 @@ public class ClippingTest extends ApplicationAdapter {
batch = new PolygonSpriteBatch(2048);
renderer = new SkeletonRenderer();
renderer.setPremultipliedAlpha(true);
renderer.setSoftwareClipping(true);
debugRenderer = new SkeletonRendererDebug();
debugRenderer.setBoundingBoxes(false);
debugRenderer.setRegionAttachments(false);
@ -90,13 +89,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[] { 94.0f, 84.0f, 45.0f, 165.0f, 218.0f, 292.0f, 476.0f, 227.0f, 480.0f, 125.0f, 325.0f, 191.0f, 333.0f, 77.0f, 302.0f, 30.0f, 175.0f, 140.0f });
// new float[] { //
// -140, 50, //
// 250, 50, //
// 250, 350, //
// -140, 350, //
// });
// Self intersection:
// clip.setVertices(new float[] { //
// -140, -50, //
@ -104,7 +103,11 @@ public class ClippingTest extends ApplicationAdapter {
// 120, -50, //
// -140, 50, //
// });
clip.setWorldVerticesLength(8);
for (int j = 0; j < clip.getVertices().length; j+=2) {
clip.getVertices()[j] = (clip.getVertices()[j] - 150f);
clip.getVertices()[j+1] = (clip.getVertices()[j+1] + 100);
}
clip.setWorldVerticesLength(clip.getVertices().length);
clip.setEndSlot(skeleton.findSlot("front_hand").data.index);
SlotData clipSlotData = new SlotData(skeletonData.getSlots().size, "clip slot", skeletonData.getBones().first());
@ -139,11 +142,6 @@ public class ClippingTest extends ApplicationAdapter {
batch.end();
debugRenderer.draw(skeleton);
if (Gdx.input.isKeyJustPressed(Keys.S)) {
renderer.setSoftwareClipping(!renderer.getSoftwareClipping());
System.out.println("Software clipping: " + renderer.getSoftwareClipping());
}
}
public void resize (int width, int height) {

View File

@ -47,7 +47,7 @@ public class ConvexDecomposerTest extends ApplicationAdapter {
image = new Texture("skin/skin.png");
font = new BitmapFont();
float[] v = {100, 100, 120, 100, 200, 100, 200, 400, 100, 400};
float[] v = new float[] { 94.0f, 84.0f, 45.0f, 165.0f, 218.0f, 292.0f, 476.0f, 227.0f, 480.0f, 125.0f, 325.0f, 191.0f, 333.0f, 77.0f, 302.0f, 30.0f, 175.0f, 140.0f };
// float[] v = {87, 288, 217, 371, 456, 361, 539, 175, 304, 194, 392, 290, 193, 214, 123, 15, 14, 137};
// float[] v = { 336, 153, 207, 184, 364, 333, 529, 326, 584, 130, 438, 224 };

View File

@ -0,0 +1,217 @@
/******************************************************************************
* 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.
*****************************************************************************/
package com.esotericsoftware.spine;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.FloatArray;
import com.badlogic.gdx.utils.ShortArray;
import com.esotericsoftware.spine.attachments.ClippingAttachment;
import com.esotericsoftware.spine.utils.Clipper;
import com.esotericsoftware.spine.utils.ConvexDecomposer;
public class SkeletonClipping {
private ClippingAttachment clipAttachment;
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);
public void clipStart (Slot slot, ClippingAttachment clip) {
if (clipAttachment != null) return;
clipAttachment = clip;
int n = clip.getWorldVerticesLength();
float[] vertices = this.clippingPolygon.setSize(n);
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
convexClippingPolygons = decomposer.decompose(clippingPolygon);
for (FloatArray poly : convexClippingPolygons) {
Clipper.makeClockwise(poly);
poly.add(poly.items[0]);
poly.add(poly.items[1]);
}
}
public void clipEnd () {
clippedVertices.clear();
clippedTriangles.clear();
clippingPolygon.clear();
convexClippingPolygons = null;
clipAttachment = null;
}
public boolean isClipping () {
return clipAttachment != null;
}
public ClippingAttachment getClippingAttachment () {
return clipAttachment;
}
public void clipTriangles (final float[] vertices, final int verticesLength, final short[] triangles,
final int trianglesLength, final float uvs[], final float dark, final float light, final boolean twoColor) {
short idx = 0;
clippedVertices.clear();
clippedTriangles.clear();
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];
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, 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 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;
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;
}
s = clippedTriangles.size;
clippedTriangles.setSize(s + 3);
final short[] clippedTrianglesArray = clippedTriangles.items;
clippedTrianglesArray[s] = idx++;
clippedTrianglesArray[s + 1] = idx++;
clippedTrianglesArray[s + 2] = idx++;
}
}
}
}
public FloatArray getClippedVertices () {
return clippedVertices;
}
public ShortArray getClippedTriangles () {
return clippedTriangles;
}
}

View File

@ -30,15 +30,11 @@
package com.esotericsoftware.spine;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
import com.badlogic.gdx.graphics.glutils.ImmediateModeRenderer;
import com.badlogic.gdx.graphics.glutils.ImmediateModeRenderer20;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.FloatArray;
@ -49,27 +45,16 @@ import com.esotericsoftware.spine.attachments.ClippingAttachment;
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 implements Disposable {
static private final short[] quadTriangles = {0, 1, 2, 2, 3, 0};
private boolean softwareClipping;
private boolean premultipliedAlpha;
private final FloatArray vertices = new FloatArray(32);
private ClippingAttachment clipAttachment;
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);
private final Matrix4 combinedMatrix = new Matrix4();
private ImmediateModeRenderer renderer;
private final SkeletonClipping clipper = new SkeletonClipping();
public void draw (Batch batch, Skeleton skeleton) {
boolean premultipliedAlpha = this.premultipliedAlpha;
@ -102,9 +87,7 @@ public class SkeletonRenderer implements Disposable {
} else if (attachment instanceof ClippingAttachment) {
ClippingAttachment clip = (ClippingAttachment)attachment;
if (!softwareClipping) batch.end();
clipStart(batch.getProjectionMatrix(), batch.getTransformMatrix(), slot, clip);
if (!softwareClipping) batch.begin();
clipper.clipStart(slot, clip);
continue;
} else if (attachment instanceof MeshAttachment) {
@ -137,10 +120,7 @@ public class SkeletonRenderer implements Disposable {
}
}
if (clipAttachment != null && i == clipAttachment.getEndSlot()) {
batch.flush();
clipEnd();
}
if (clipper.isClipping() && clipper.getClippingAttachment().getEndSlot() == i) clipper.clipEnd();
}
}
@ -156,7 +136,7 @@ public class SkeletonRenderer implements Disposable {
float r = skeletonColor.r, g = skeletonColor.g, b = skeletonColor.b, a = skeletonColor.a;
Array<Slot> drawOrder = skeleton.drawOrder;
for (int i = 0, n = drawOrder.size; i < n; i++) {
final int vertexSize = (softwareClipping && clipAttachment != null) ? 2 : 5;
final int vertexSize = clipper.isClipping() ? 2 : 5;
Slot slot = drawOrder.get(i);
Attachment attachment = slot.attachment;
if (attachment instanceof RegionAttachment) {
@ -182,9 +162,7 @@ public class SkeletonRenderer implements Disposable {
} else if (attachment instanceof ClippingAttachment) {
ClippingAttachment clip = (ClippingAttachment)attachment;
if (!softwareClipping) batch.end();
clipStart(batch.getProjectionMatrix(), batch.getTransformMatrix(), slot, clip);
if (!softwareClipping) batch.begin();
clipper.clipStart(slot, clip);
continue;
} else if (attachment instanceof SkeletonAttachment) {
@ -226,20 +204,13 @@ public class SkeletonRenderer implements Disposable {
blendMode = slotBlendMode;
batch.setBlendFunction(blendMode.getSource(premultipliedAlpha), blendMode.getDest());
}
if (softwareClipping) {
if (clipAttachment != null) {
clipSoftware(vertices, 0, verticesLength, triangles, 0, triangles.length, uvs, 0, c, false, clippedVertices,
clippedTriangles);
batch.draw(texture, clippedVertices.items, 0, clippedVertices.size, clippedTriangles.items, 0,
clippedTriangles.size);
} else {
for (int v = 2, u = 0; v < verticesLength; v += 5, u += 2) {
vertices[v] = c;
vertices[v + 1] = uvs[u];
vertices[v + 2] = uvs[u + 1];
}
batch.draw(texture, vertices, 0, verticesLength, triangles, 0, triangles.length);
}
if (clipper.isClipping()) {
clipper.clipTriangles(vertices, verticesLength, triangles, triangles.length, uvs, 0, c, false);
FloatArray clippedVertices = clipper.getClippedVertices();
ShortArray clippedTriangles = clipper.getClippedTriangles();
batch.draw(texture, clippedVertices.items, 0, clippedVertices.size, clippedTriangles.items, 0,
clippedTriangles.size);
} else {
for (int v = 2, u = 0; v < verticesLength; v += 5, u += 2) {
vertices[v] = c;
@ -250,10 +221,7 @@ public class SkeletonRenderer implements Disposable {
}
}
if (clipAttachment != null && i == clipAttachment.getEndSlot()) {
if (!softwareClipping) batch.flush();
clipEnd();
}
if (clipper.isClipping() && clipper.getClippingAttachment().getEndSlot() == i) clipper.clipEnd();
}
}
@ -269,7 +237,7 @@ public class SkeletonRenderer implements Disposable {
float r = skeletonColor.r, g = skeletonColor.g, b = skeletonColor.b, a = skeletonColor.a;
Array<Slot> drawOrder = skeleton.drawOrder;
for (int i = 0, n = drawOrder.size; i < n; i++) {
final int vertexSize = (softwareClipping && clipAttachment != null) ? 2 : 6;
final int vertexSize = clipper.isClipping() ? 2 : 6;
Slot slot = drawOrder.get(i);
Attachment attachment = slot.attachment;
if (attachment instanceof RegionAttachment) {
@ -295,9 +263,7 @@ public class SkeletonRenderer implements Disposable {
} else if (attachment instanceof ClippingAttachment) {
ClippingAttachment clip = (ClippingAttachment)attachment;
if (!softwareClipping) batch.end();
clipStart(batch.getProjectionMatrix(), batch.getTransformMatrix(), slot, clip);
if (!softwareClipping) batch.begin();
clipper.clipStart(slot, clip);
continue;
} else if (attachment instanceof SkeletonAttachment) {
@ -346,21 +312,12 @@ public class SkeletonRenderer implements Disposable {
batch.setBlendFunction(blendMode.getSource(premultipliedAlpha), blendMode.getDest());
}
if (softwareClipping) {
if (clipAttachment != null) {
clipSoftware(vertices, 0, verticesLength, triangles, 0, triangles.length, uvs, dark, light, true,
clippedVertices, clippedTriangles);
batch.draw(texture, clippedVertices.items, 0, clippedVertices.size, clippedTriangles.items, 0,
clippedTriangles.size);
} else {
for (int v = 2, u = 0; v < verticesLength; v += 6, u += 2) {
vertices[v] = light;
vertices[v + 1] = dark;
vertices[v + 2] = uvs[u];
vertices[v + 3] = uvs[u + 1];
}
batch.draw(texture, vertices, 0, verticesLength, triangles, 0, triangles.length);
}
if (clipper.isClipping()) {
clipper.clipTriangles(vertices, verticesLength, triangles, triangles.length, uvs, dark, light, true);
FloatArray clippedVertices = clipper.getClippedVertices();
ShortArray clippedTriangles = clipper.getClippedTriangles();
batch.draw(texture, clippedVertices.items, 0, clippedVertices.size, clippedTriangles.items, 0,
clippedTriangles.size);
} else {
for (int v = 2, u = 0; v < verticesLength; v += 6, u += 2) {
vertices[v] = light;
@ -372,189 +329,7 @@ public class SkeletonRenderer implements Disposable {
}
}
if (clipAttachment != null && i == clipAttachment.getEndSlot()) {
if (!softwareClipping) batch.flush();
clipEnd();
}
}
}
private void clipStart (Matrix4 transformMatrix, Matrix4 projectionMatrix, Slot slot, ClippingAttachment clip) {
if (clipAttachment != null) return;
clipAttachment = clip;
if (!softwareClipping) {
int n = clip.getWorldVerticesLength();
float[] vertices = this.vertices.setSize(n);
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
Gdx.gl.glClearStencil(0);
Gdx.gl.glClear(GL20.GL_STENCIL_BUFFER_BIT);
Gdx.gl.glEnable(GL20.GL_STENCIL_TEST);
Gdx.gl.glStencilFunc(GL20.GL_NEVER, 0, 1);
Gdx.gl.glStencilOp(GL20.GL_INVERT, GL20.GL_INVERT, GL20.GL_INVERT);
Gdx.gl.glColorMask(false, false, false, false);
if (renderer == null || renderer.getMaxVertices() < n)
renderer = new ImmediateModeRenderer20(Math.max(100, n), false, false, 0);
renderer.begin(combinedMatrix.set(projectionMatrix).mul(transformMatrix), GL20.GL_TRIANGLE_FAN);
renderer.vertex(vertices[0], vertices[1], 0);
for (int i = 2; i < n; i += 2)
renderer.vertex(vertices[i], vertices[i + 1], 0);
renderer.end();
Gdx.gl.glColorMask(true, true, true, true);
Gdx.gl.glStencilFunc(false ? GL20.GL_NOTEQUAL : GL20.GL_EQUAL, 1, 1);
Gdx.gl.glStencilOp(GL20.GL_KEEP, GL20.GL_KEEP, GL20.GL_KEEP);
} else {
int n = clip.getWorldVerticesLength();
float[] vertices = this.clippingPolygon.setSize(n);
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
convexClippingPolygons = decomposer.decompose(clippingPolygon);
for (FloatArray poly: convexClippingPolygons) {
Clipper.makeClockwise(poly);
poly.add(poly.items[0]);
poly.add(poly.items[1]);
}
}
}
private void clipEnd() {
clippedVertices.clear();
clippedTriangles.clear();
clippingPolygon.clear();
convexClippingPolygons = null;
clipAttachment = null;
if (!softwareClipping) Gdx.gl.glDisable(GL20.GL_STENCIL_TEST);
}
private void clipSoftware (final float[] vertices, final int offset, final int verticesLength, final short[] triangles,
final int triangleOffset, final int trianglesLength, final float uvs[], final float dark, final float light,
final boolean twoColor, final FloatArray clippedVertices, final ShortArray clippedTriangles) {
short idx = 0;
clippedVertices.clear();
clippedTriangles.clear();
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];
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, 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 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;
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;
}
s = clippedTriangles.size;
clippedTriangles.setSize(s + 3);
final short[] clippedTrianglesArray = clippedTriangles.items;
clippedTrianglesArray[s] = idx++;
clippedTrianglesArray[s + 1] = idx++;
clippedTrianglesArray[s + 2] = idx++;
}
}
if (clipper.isClipping() && clipper.getClippingAttachment().getEndSlot() == i) clipper.clipEnd();
}
}
@ -565,12 +340,4 @@ public class SkeletonRenderer implements Disposable {
public void dispose () {
renderer.dispose();
}
public boolean getSoftwareClipping () {
return softwareClipping;
}
public void setSoftwareClipping (boolean softwareClipping) {
this.softwareClipping = softwareClipping;
}
}
}