[libgdx] More micro optimizations for clipper.

This commit is contained in:
badlogic 2017-03-28 12:20:10 +02:00
parent 8866925570
commit a10fd95e1b
2 changed files with 42 additions and 57 deletions

View File

@ -186,7 +186,8 @@ public class SoftwareClippingTest extends ApplicationAdapter {
clippingPolygon.add(clippingPolygon.get(0)); clippingPolygon.add(clippingPolygon.get(0));
clippingPolygon.add(clippingPolygon.get(1)); clippingPolygon.add(clippingPolygon.get(1));
boolean clipped = clipper.clip(x1, y1, x2, y2, x3, y3, clippingPolygon, clippedPolygon); boolean isClockwise = SutherlandHodgmanClipper.clockwise(clippingPolygon);
boolean clipped = clipper.clip(x1, y1, x2, y2, x3, y3, clippingPolygon, clippedPolygon, isClockwise);
System.out.println("Clipped: " + clipped); System.out.println("Clipped: " + clipped);
if (clipped) { if (clipped) {
clippedPolygonVertices.clear(); clippedPolygonVertices.clear();

View File

@ -1,27 +1,15 @@
package com.esotericsoftware.spine.utils; package com.esotericsoftware.spine.utils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.FloatArray; import com.badlogic.gdx.utils.FloatArray;
public class SutherlandHodgmanClipper { public class SutherlandHodgmanClipper {
Vector2 tmp = new Vector2();
final FloatArray scratch = new FloatArray(); final FloatArray scratch = new FloatArray();
public boolean clip(float x1, float y1, float x2, float y2, float x3, float y3, FloatArray clippingArea, /** Clips the input triangle against the convex clipping area. If the triangle lies entirely within the clipping area, false is
FloatArray output) { * returned. The clipping area must duplicate the first vertex at the end of the vertices list! */
boolean isClockwise = clockwise(clippingArea); public boolean clip (float x1, float y1, float x2, float y2, float x3, float y3, FloatArray clippingArea, FloatArray output,
return clip(x1, y1, x2, y2, x3, y3, clippingArea, output, isClockwise); boolean isClockwise) {
}
/**
* Clips the input triangle against the convex clipping area. If the
* triangle lies entirely within the clipping area, false is returned. The
* clipping area must duplicate the first vertex at the end of the vertices
* list!
*/
public boolean clip(float x1, float y1, float x2, float y2, float x3, float y3, FloatArray clippingArea,
FloatArray output, boolean isClockwise) {
final FloatArray originalOutput = output; final FloatArray originalOutput = output;
boolean clipped = false; boolean clipped = false;
@ -75,36 +63,35 @@ public class SutherlandHodgmanClipper {
final float inputX2 = inputVertices[j + 2]; final float inputX2 = inputVertices[j + 2];
final float inputY2 = inputVertices[j + 3]; final float inputY2 = inputVertices[j + 3];
final int side = pointLineSide(deltaX, deltaY, edgeX2, edgeY2, inputX, inputY); final int side = (int)Math.signum(deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2));
final int side2 = pointLineSide(deltaX, deltaY, edgeX2, edgeY2, inputX2, inputY2); final int side2 = (int)Math.signum(deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2));
if (side >= 0) {
// v1 inside, v2 inside // v1 inside, v2 inside
if (side >= 0 && side2 >= 0) { if (side2 >= 0) {
output.add(inputX2); output.add(inputX2);
output.add(inputY2); output.add(inputY2);
} }
// v1 inside, v2 outside // v1 inside, v2 outside
else if (side >= 0 && side2 < 0) { else {
intersectLines(edgeX, edgeY, edgeX2, edgeY2, inputX, inputY, inputX2, inputY2, tmp); intersectLines(edgeX, edgeY, edgeX2, edgeY2, inputX, inputY, inputX2, inputY2, output);
output.add(tmp.x);
output.add(tmp.y);
clipped = true; clipped = true;
} }
} else {
// v1 outside, v2 outside // v1 outside, v2 outside
else if (side < 0 && side2 < 0) { if (side2 < 0) {
// no output // no output
clipped = true; clipped = true;
} }
// v1 outside, v2 inside // v1 outside, v2 inside
else if (side < 0 && side2 >= 0) { else {
intersectLines(edgeX, edgeY, edgeX2, edgeY2, inputX, inputY, inputX2, inputY2, tmp); intersectLines(edgeX, edgeY, edgeX2, edgeY2, inputX, inputY, inputX2, inputY2, output);
output.add(tmp.x);
output.add(tmp.y);
output.add(inputX2); output.add(inputX2);
output.add(inputY2); output.add(inputY2);
clipped = true; clipped = true;
} }
} }
}
output.add(output.items[0]); output.add(output.items[0]);
output.add(output.items[1]); output.add(output.items[1]);
@ -127,12 +114,8 @@ public class SutherlandHodgmanClipper {
return clipped; return clipped;
} }
private int pointLineSide(float deltaX, float deltaY, float lineX, float lineY, float pointX, float pointY) {
return (int) Math.signum(deltaX * (pointY - lineY) - deltaY * (pointX - lineX));
}
public static void intersectLines (float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, public static void intersectLines (float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4,
Vector2 intersection) { FloatArray output) {
float c0 = y4 - y3; float c0 = y4 - y3;
float c1 = x2 - x1; float c1 = x2 - x1;
float c2 = x4 - x3; float c2 = x4 - x3;
@ -140,7 +123,8 @@ public class SutherlandHodgmanClipper {
float d = c0 * c1 - c2 * c3; float d = c0 * c1 - c2 * c3;
float ua = (c2 * (y1 - y3) - c0 * (x1 - x3)) / d; float ua = (c2 * (y1 - y3) - c0 * (x1 - x3)) / d;
intersection.set(x1 + (x2 - x1) * ua, y1 + (y2 - y1) * ua); output.add(x1 + (x2 - x1) * ua);
output.add(y1 + (y2 - y1) * ua);
} }
public static boolean clockwise (FloatArray poly) { public static boolean clockwise (FloatArray poly) {