[libgdx] Fixed up software clipping test

This commit is contained in:
badlogic 2017-03-30 16:03:37 +02:00
parent 23fd36a5f1
commit b8a603d6af

View File

@ -6,6 +6,7 @@ import org.lwjgl.opengl.GL11;
import com.badlogic.gdx.ApplicationAdapter; import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Buttons; import com.badlogic.gdx.Input.Buttons;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication; import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
@ -16,9 +17,11 @@ import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.FloatArray;
import com.badlogic.gdx.utils.ShortArray; import com.badlogic.gdx.utils.ShortArray;
import com.esotericsoftware.spine.utils.Clipper; import com.esotericsoftware.spine.utils.Clipper;
import com.esotericsoftware.spine.utils.ConvexDecomposer;
public class SoftwareClippingTest extends ApplicationAdapter { public class SoftwareClippingTest extends ApplicationAdapter {
OrthographicCamera sceneCamera; OrthographicCamera sceneCamera;
@ -26,13 +29,10 @@ public class SoftwareClippingTest extends ApplicationAdapter {
PolygonSpriteBatch polyBatcher; PolygonSpriteBatch polyBatcher;
Texture image; Texture image;
float[] triangleOutline = { 100, 100, 300, 100, 200, 300 }; float[] triangleOutline = {100, 100, 300, 100, 200, 300};
float[] triangle = { float[] triangle = {100, 100, Color.WHITE.toFloatBits(), 0, 1, 300, 100, Color.WHITE.toFloatBits(), 1, 1, 200, 300,
100, 100, Color.WHITE.toFloatBits(), 0, 1, Color.WHITE.toFloatBits(), 0.5f, 0};
300, 100, Color.WHITE.toFloatBits(), 1, 1, short[] triangleIndices = {0, 1, 2};
200, 300, Color.WHITE.toFloatBits(), 0.5f, 0
};
short[] triangleIndices = { 0, 1, 2 };
FloatArray clippingPolygon = new FloatArray(); FloatArray clippingPolygon = new FloatArray();
FloatArray clippedPolygon = new FloatArray(); FloatArray clippedPolygon = new FloatArray();
@ -42,6 +42,7 @@ public class SoftwareClippingTest extends ApplicationAdapter {
boolean isCreatingClippingArea = false; boolean isCreatingClippingArea = false;
Vector3 tmp = new Vector3(); Vector3 tmp = new Vector3();
Clipper clipper; Clipper clipper;
ConvexDecomposer decomposer;
@Override @Override
public void create () { public void create () {
@ -49,6 +50,7 @@ public class SoftwareClippingTest extends ApplicationAdapter {
shapes = new ShapeRenderer(); shapes = new ShapeRenderer();
polyBatcher = new PolygonSpriteBatch(); polyBatcher = new PolygonSpriteBatch();
clipper = new Clipper(); clipper = new Clipper();
decomposer = new ConvexDecomposer();
image = new Texture("skin/skin.png"); image = new Texture("skin/skin.png");
} }
@ -76,14 +78,18 @@ public class SoftwareClippingTest extends ApplicationAdapter {
isCreatingClippingArea = true; isCreatingClippingArea = true;
} }
clippingPolygon.add(tmp.x); clippingPolygon.add((int)tmp.x);
clippingPolygon.add(tmp.y); clippingPolygon.add((int)tmp.y);
if (Gdx.input.isButtonPressed(Buttons.RIGHT)) { if (Gdx.input.isButtonPressed(Buttons.RIGHT)) {
isCreatingClippingArea = false; isCreatingClippingArea = false;
clip(); clip();
} }
} }
if (Gdx.input.isKeyJustPressed(Keys.T)) {
clip();
}
} }
private void renderScene () { private void renderScene () {
@ -94,10 +100,12 @@ public class SoftwareClippingTest extends ApplicationAdapter {
polyBatcher.begin(); polyBatcher.begin();
polyBatcher.disableBlending(); polyBatcher.disableBlending();
if (clippedPolygon.size == 0) { // clipped polygon
if (clippedPolygonVertices.size == 0) {
polyBatcher.draw(image, triangle, 0, 15, triangleIndices, 0, 3); polyBatcher.draw(image, triangle, 0, 15, triangleIndices, 0, 3);
} else { } else {
polyBatcher.draw(image, clippedPolygonVertices.items, 0, clippedPolygonVertices.size, clippedPolygonIndices.items, 0, clippedPolygonIndices.size); polyBatcher.draw(image, clippedPolygonVertices.items, 0, clippedPolygonVertices.size, clippedPolygonIndices.items, 0,
clippedPolygonIndices.size);
} }
polyBatcher.end(); polyBatcher.end();
@ -107,7 +115,7 @@ public class SoftwareClippingTest extends ApplicationAdapter {
shapes.setColor(Color.GREEN); shapes.setColor(Color.GREEN);
shapes.polygon(triangleOutline); shapes.polygon(triangleOutline);
// clipped polygons // clipping area
shapes.setColor(Color.RED); shapes.setColor(Color.RED);
if (isCreatingClippingArea) { if (isCreatingClippingArea) {
tmp.set(Gdx.input.getX(), Gdx.input.getY(), 0); tmp.set(Gdx.input.getX(), Gdx.input.getY(), 0);
@ -134,41 +142,41 @@ public class SoftwareClippingTest extends ApplicationAdapter {
shapes.polygon(clippingPolygon.items, 0, clippingPolygon.size); shapes.polygon(clippingPolygon.items, 0, clippingPolygon.size);
} }
// edge normals // // edge normals
shapes.setColor(Color.YELLOW); // shapes.setColor(Color.YELLOW);
if (clippingPolygon.size > 2) { // if (clippingPolygon.size > 2) {
boolean clockwise = Clipper.isClockwise(clippingPolygon); // boolean clockwise = Clipper.isClockwise(clippingPolygon);
for (int i = 0; i < clippingPolygon.size; i += 2) { // for (int i = 0; i < clippingPolygon.size; i += 2) {
float x = clippingPolygon.get(i); // float x = clippingPolygon.get(i);
float y = clippingPolygon.get(i + 1); // float y = clippingPolygon.get(i + 1);
float x2 = clippingPolygon.get((i + 2) % clippingPolygon.size); // float x2 = clippingPolygon.get((i + 2) % clippingPolygon.size);
float y2 = clippingPolygon.get((i + 3) % clippingPolygon.size); // float y2 = clippingPolygon.get((i + 3) % clippingPolygon.size);
//
float mx = x + (x2 - x) / 2; // float mx = x + (x2 - x) / 2;
float my = y + (y2 - y) / 2; // float my = y + (y2 - y) / 2;
float nx = (y2 - y); // float nx = (y2 - y);
float ny = -(x2 - x); // float ny = -(x2 - x);
if (!clockwise) { // if (!clockwise) {
nx = -nx; // nx = -nx;
ny = -ny; // ny = -ny;
} // }
float l = 1 / (float)Math.sqrt(nx * nx + ny * ny); // float l = 1 / (float)Math.sqrt(nx * nx + ny * ny);
nx *= l * 20; // nx *= l * 20;
ny *= l * 20; // ny *= l * 20;
//
shapes.line(mx, my, mx + nx, my + ny); // shapes.line(mx, my, mx + nx, my + ny);
} // }
} // }
if (isCreatingClippingArea) { if (isCreatingClippingArea) {
clippingPolygon.setSize(clippingPolygon.size - 2); clippingPolygon.setSize(clippingPolygon.size - 2);
} }
// clipped polygon // // clipped polygon
shapes.setColor(Color.PINK); // shapes.setColor(Color.PINK);
if (clippedPolygon.size > 0) { // if (clippedPolygon.size > 0) {
shapes.polygon(clippedPolygon.items, 0, clippedPolygon.size); // shapes.polygon(clippedPolygon.items, 0, clippedPolygon.size);
} // }
shapes.end(); shapes.end();
} }
@ -181,55 +189,57 @@ public class SoftwareClippingTest extends ApplicationAdapter {
float x3 = triangle[10]; float x3 = triangle[10];
float y3 = triangle[11]; float y3 = triangle[11];
// must duplicate first vertex at end of polygon Array<FloatArray> clippingPolygons = decomposer.decompose(clippingPolygon);
// so we can avoid module/branch in clipping code clippedPolygonVertices.clear();
Clipper.makeClockwise(clippingPolygon); clippedPolygonIndices.clear();
clippingPolygon.add(clippingPolygon.get(0));
clippingPolygon.add(clippingPolygon.get(1));
boolean clipped = clipper.clip(x1, y1, x2, y2, x3, y3, clippingPolygon, clippedPolygon); for (FloatArray poly : clippingPolygons) {
System.out.println("Clipped: " + clipped); Clipper.makeClockwise(poly);
if (clipped) { poly.add(poly.get(0));
clippedPolygonVertices.clear(); poly.add(poly.get(1));
clippedPolygonIndices.clear();
float d0 = y2 - y3; boolean clipped = clipper.clip(x1, y1, x2, y2, x3, y3, poly, clippedPolygon);
float d1 = x3 - x2; System.out.println("Clipped: " + clipped);
float d2 = x1 - x3; if (clipped) {
float d3 = y1 - y3; float d0 = y2 - y3;
float d4 = y3 - y1; float d1 = x3 - x2;
float d2 = x1 - x3;
float d3 = y1 - y3;
float d4 = y3 - y1;
float denom = 1 / (d0 * d2 + d1 * d3); float denom = 1 / (d0 * d2 + d1 * d3);
// triangulate by creating a triangle fan, duplicate vertices // triangulate by creating a triangle fan, duplicate vertices
float color = Color.WHITE.toFloatBits(); int o = clippedPolygonVertices.size / 5;
for (int i = 0; i < clippedPolygon.size; i+=2) { float color = Color.WHITE.toFloatBits();
float x = clippedPolygon.get(i); for (int i = 0; i < clippedPolygon.size; i += 2) {
float y = clippedPolygon.get(i + 1); float x = clippedPolygon.get(i);
float y = clippedPolygon.get(i + 1);
float a = (d0 * (x - x3) + d1 * (y - y3)) * denom; float a = (d0 * (x - x3) + d1 * (y - y3)) * denom;
float b = (d4 * (x - x3) + d2 * (y - y3)) * denom; float b = (d4 * (x - x3) + d2 * (y - y3)) * denom;
float c = 1.0f - a - b; float c = 1.0f - a - b;
float u = triangle[3] * a + triangle[8] * b + triangle[13] * c; float u = triangle[3] * a + triangle[8] * b + triangle[13] * c;
float v = triangle[4] * a + triangle[9] * b + triangle[14] * c; float v = triangle[4] * a + triangle[9] * b + triangle[14] * c;
clippedPolygonVertices.add(x); clippedPolygonVertices.add(x);
clippedPolygonVertices.add(y); clippedPolygonVertices.add(y);
clippedPolygonVertices.add(color); clippedPolygonVertices.add(color);
clippedPolygonVertices.add(u); clippedPolygonVertices.add(u);
clippedPolygonVertices.add(v); clippedPolygonVertices.add(v);
}
for (int i = 1; i < (clippedPolygon.size >> 1) - 1; i++) {
clippedPolygonIndices.add(o);
clippedPolygonIndices.add(o + i);
clippedPolygonIndices.add(o + i + 1);
}
} else {
clippedPolygon.clear();
} }
for (int i = 1; i < (clippedPolygon.size >> 1) - 1; i++) { poly.setSize(poly.size - 2);
clippedPolygonIndices.add(0);
clippedPolygonIndices.add(i);
clippedPolygonIndices.add(i + 1);
}
} else {
clippedPolygon.clear();
} }
clippingPolygon.setSize(clippingPolygon.size - 2);
} }
public static void main (String[] args) { public static void main (String[] args) {