[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,34 +63,33 @@ 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));
// v1 inside, v2 inside if (side >= 0) {
if (side >= 0 && side2 >= 0) { // v1 inside, v2 inside
output.add(inputX2); if (side2 >= 0) {
output.add(inputY2); output.add(inputX2);
} output.add(inputY2);
// v1 inside, v2 outside }
else if (side >= 0 && side2 < 0) { // v1 inside, v2 outside
intersectLines(edgeX, edgeY, edgeX2, edgeY2, inputX, inputY, inputX2, inputY2, tmp); else {
output.add(tmp.x); intersectLines(edgeX, edgeY, edgeX2, edgeY2, inputX, inputY, inputX2, inputY2, output);
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(inputX2);
output.add(tmp.y); output.add(inputY2);
output.add(inputX2); clipped = true;
output.add(inputY2); }
clipped = true;
} }
} }
@ -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) { public static void intersectLines (float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4,
return (int) Math.signum(deltaX * (pointY - lineY) - deltaY * (pointX - lineX)); FloatArray output) {
}
public static void intersectLines(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4,
Vector2 intersection) {
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,14 +123,15 @@ 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) {
return area(poly) < 0; return area(poly) < 0;
} }
public static float area(FloatArray poly) { public static float area (FloatArray poly) {
float area = 0; float area = 0;
final float[] polyVertices = poly.items; final float[] polyVertices = poly.items;