mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
[libgdx] Many micro optimizations, shaved off 40% of software clipping runtime.
This commit is contained in:
parent
019a8e6587
commit
8866925570
@ -116,7 +116,8 @@ public class ClippingTest extends ApplicationAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void render () {
|
public void render () {
|
||||||
state.update(Gdx.graphics.getDeltaTime() * 0.3f);
|
// state.update(Gdx.graphics.getDeltaTime() * 0.3f);
|
||||||
|
state.update(0);
|
||||||
|
|
||||||
Gdx.gl.glClearColor(0.3f, 0.3f, 0.3f, 1);
|
Gdx.gl.glClearColor(0.3f, 0.3f, 0.3f, 1);
|
||||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||||
|
|||||||
@ -174,12 +174,6 @@ public class SoftwareClippingTest extends ApplicationAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void clip () {
|
private void clip () {
|
||||||
boolean clipped = clipper.clip(triangle, 0, triangle.length, 5, clippingPolygon, clippedPolygon);
|
|
||||||
System.out.println("Clipped: " + clipped);
|
|
||||||
if (clipped) {
|
|
||||||
clippedPolygonVertices.clear();
|
|
||||||
clippedPolygonIndices.clear();
|
|
||||||
|
|
||||||
float x1 = triangle[0];
|
float x1 = triangle[0];
|
||||||
float y1 = triangle[1];
|
float y1 = triangle[1];
|
||||||
float x2 = triangle[5];
|
float x2 = triangle[5];
|
||||||
@ -187,6 +181,17 @@ 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
|
||||||
|
// so we can avoid module/branch in clipping code
|
||||||
|
clippingPolygon.add(clippingPolygon.get(0));
|
||||||
|
clippingPolygon.add(clippingPolygon.get(1));
|
||||||
|
|
||||||
|
boolean clipped = clipper.clip(x1, y1, x2, y2, x3, y3, clippingPolygon, clippedPolygon);
|
||||||
|
System.out.println("Clipped: " + clipped);
|
||||||
|
if (clipped) {
|
||||||
|
clippedPolygonVertices.clear();
|
||||||
|
clippedPolygonIndices.clear();
|
||||||
|
|
||||||
float d0 = y2 - y3;
|
float d0 = y2 - y3;
|
||||||
float d1 = x3 - x2;
|
float d1 = x3 - x2;
|
||||||
float d2 = x1 - x3;
|
float d2 = x1 - x3;
|
||||||
@ -222,6 +227,8 @@ public class SoftwareClippingTest extends ApplicationAdapter {
|
|||||||
} else {
|
} else {
|
||||||
clippedPolygon.clear();
|
clippedPolygon.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clippingPolygon.setSize(clippingPolygon.size - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main (String[] args) {
|
public static void main (String[] args) {
|
||||||
|
|||||||
@ -62,7 +62,7 @@ public class SkeletonRenderer {
|
|||||||
private ClippingAttachment clipAttachment;
|
private ClippingAttachment clipAttachment;
|
||||||
private Slot clipEnd;
|
private Slot clipEnd;
|
||||||
private FloatArray clippingArea = new FloatArray();
|
private FloatArray clippingArea = new FloatArray();
|
||||||
private float[] clipInput = new float[6];
|
private boolean clippingAreaClockwise;
|
||||||
private FloatArray clipOutput = new FloatArray(400);
|
private FloatArray clipOutput = new FloatArray(400);
|
||||||
private FloatArray clippedVertices = new FloatArray(400);
|
private FloatArray clippedVertices = new FloatArray(400);
|
||||||
private ShortArray clippedTriangles = new ShortArray(400);
|
private ShortArray clippedTriangles = new ShortArray(400);
|
||||||
@ -100,9 +100,9 @@ public class SkeletonRenderer {
|
|||||||
|
|
||||||
} else if (attachment instanceof ClippingAttachment) {
|
} else if (attachment instanceof ClippingAttachment) {
|
||||||
ClippingAttachment clip = (ClippingAttachment) attachment;
|
ClippingAttachment clip = (ClippingAttachment) attachment;
|
||||||
batch.end();
|
if (!softwareClipping) batch.end();
|
||||||
clipStart(batch.getProjectionMatrix(), batch.getTransformMatrix(), slot, clip);
|
clipStart(batch.getProjectionMatrix(), batch.getTransformMatrix(), slot, clip);
|
||||||
batch.begin();
|
if (!softwareClipping) batch.begin();
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else if (attachment instanceof MeshAttachment) {
|
} else if (attachment instanceof MeshAttachment) {
|
||||||
@ -179,9 +179,9 @@ public class SkeletonRenderer {
|
|||||||
|
|
||||||
} else if (attachment instanceof ClippingAttachment) {
|
} else if (attachment instanceof ClippingAttachment) {
|
||||||
ClippingAttachment clip = (ClippingAttachment) attachment;
|
ClippingAttachment clip = (ClippingAttachment) attachment;
|
||||||
batch.end();
|
if (!softwareClipping) batch.end();
|
||||||
clipStart(batch.getProjectionMatrix(), batch.getTransformMatrix(), slot, clip);
|
clipStart(batch.getProjectionMatrix(), batch.getTransformMatrix(), slot, clip);
|
||||||
batch.begin();
|
if (!softwareClipping) batch.begin();
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else if (attachment instanceof SkeletonAttachment) {
|
} else if (attachment instanceof SkeletonAttachment) {
|
||||||
@ -284,9 +284,9 @@ public class SkeletonRenderer {
|
|||||||
|
|
||||||
} else if (attachment instanceof ClippingAttachment) {
|
} else if (attachment instanceof ClippingAttachment) {
|
||||||
ClippingAttachment clip = (ClippingAttachment) attachment;
|
ClippingAttachment clip = (ClippingAttachment) attachment;
|
||||||
batch.end();
|
if (!softwareClipping) batch.end();
|
||||||
clipStart(batch.getProjectionMatrix(), batch.getTransformMatrix(), slot, clip);
|
clipStart(batch.getProjectionMatrix(), batch.getTransformMatrix(), slot, clip);
|
||||||
batch.begin();
|
if (!softwareClipping) batch.begin();
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else if (attachment instanceof SkeletonAttachment) {
|
} else if (attachment instanceof SkeletonAttachment) {
|
||||||
@ -393,6 +393,9 @@ public class SkeletonRenderer {
|
|||||||
int n = clip.getWorldVerticesLength();
|
int n = clip.getWorldVerticesLength();
|
||||||
float[] vertices = this.clippingArea.setSize(n);
|
float[] vertices = this.clippingArea.setSize(n);
|
||||||
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
|
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
|
||||||
|
clippingAreaClockwise = SutherlandHodgmanClipper.clockwise(this.clippingArea);
|
||||||
|
clippingArea.add(clippingArea.items[0]);
|
||||||
|
clippingArea.add(clippingArea.items[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,7 +405,7 @@ public class SkeletonRenderer {
|
|||||||
if (!softwareClipping) Gdx.gl.glDisable(GL20.GL_STENCIL_TEST);
|
if (!softwareClipping) Gdx.gl.glDisable(GL20.GL_STENCIL_TEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clipSoftware(float[] vertices, int offset, int verticesLength, short[] triangles, int triangleOffset, int trianglesLength, FloatArray clippedVertices, ShortArray clippedTriangles, float dark, float light, boolean twoColor) {
|
private void clipSoftware(final float[] vertices, final int offset, final int verticesLength, final short[] triangles, final int triangleOffset, final int trianglesLength, final FloatArray clippedVertices, final ShortArray clippedTriangles, final float dark, final float light, final boolean twoColor) {
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
clippedVertices.clear();
|
clippedVertices.clear();
|
||||||
clippedTriangles.clear();
|
clippedTriangles.clear();
|
||||||
@ -410,32 +413,25 @@ public class SkeletonRenderer {
|
|||||||
final int uvOffset = twoColor ? 4 : 3;
|
final int uvOffset = twoColor ? 4 : 3;
|
||||||
for (int i = 0; i < trianglesLength; i += 3) {
|
for (int i = 0; i < trianglesLength; i += 3) {
|
||||||
int triOffset = triangles[i] * vertexSize;
|
int triOffset = triangles[i] * vertexSize;
|
||||||
clipInput[0] = vertices[triOffset];
|
float x1 = vertices[triOffset];
|
||||||
clipInput[1] = vertices[triOffset + 1];
|
float y1= vertices[triOffset + 1];
|
||||||
float u1 = vertices[triOffset + uvOffset];
|
float u1 = vertices[triOffset + uvOffset];
|
||||||
float v1 = vertices[triOffset + uvOffset + 1];
|
float v1 = vertices[triOffset + uvOffset + 1];
|
||||||
|
|
||||||
triOffset = triangles[i + 1] * vertexSize;
|
triOffset = triangles[i + 1] * vertexSize;
|
||||||
clipInput[2] = vertices[triOffset];
|
float x2 = vertices[triOffset];
|
||||||
clipInput[3] = vertices[triOffset + 1];
|
float y2 = vertices[triOffset + 1];
|
||||||
float u2 = vertices[triOffset + uvOffset];
|
float u2 = vertices[triOffset + uvOffset];
|
||||||
float v2 = vertices[triOffset + uvOffset + 1];
|
float v2 = vertices[triOffset + uvOffset + 1];
|
||||||
|
|
||||||
triOffset = triangles[i + 2] * vertexSize;
|
triOffset = triangles[i + 2] * vertexSize;
|
||||||
clipInput[4] = vertices[triOffset];
|
float x3 = vertices[triOffset];
|
||||||
clipInput[5] = vertices[triOffset + 1];
|
float y3 = vertices[triOffset + 1];
|
||||||
float u3 = vertices[triOffset + uvOffset];
|
float u3 = vertices[triOffset + uvOffset];
|
||||||
float v3 = vertices[triOffset + uvOffset + 1];
|
float v3 = vertices[triOffset + uvOffset + 1];
|
||||||
|
|
||||||
boolean clipped = clipper.clip(clipInput, 0, 6, 2, clippingArea, clipOutput);
|
boolean clipped = clipper.clip(x1, y1, x2, y2, x3, y3, clippingArea, clipOutput, clippingAreaClockwise);
|
||||||
if (clipped) {
|
if (clipped) {
|
||||||
float x1 = clipInput[0];
|
|
||||||
float y1 = clipInput[1];
|
|
||||||
float x2 = clipInput[2];
|
|
||||||
float y2 = clipInput[3];
|
|
||||||
float x3 = clipInput[4];
|
|
||||||
float y3 = clipInput[5];
|
|
||||||
|
|
||||||
float d0 = y2 - y3;
|
float d0 = y2 - y3;
|
||||||
float d1 = x3 - x2;
|
float d1 = x3 - x2;
|
||||||
float d2 = x1 - x3;
|
float d2 = x1 - x3;
|
||||||
@ -450,8 +446,10 @@ public class SkeletonRenderer {
|
|||||||
float x = clipVertices[j];
|
float x = clipVertices[j];
|
||||||
float y = clipVertices[j + 1];
|
float y = clipVertices[j + 1];
|
||||||
|
|
||||||
float a = (d0 * (x - x3) + d1 * (y - y3)) * denom;
|
float c0 = x - x3;
|
||||||
float b = (d4 * (x - x3) + d2 * (y - y3)) * denom;
|
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 c = 1.0f - a - b;
|
||||||
|
|
||||||
float u = u1 * a + u2 * b + u3 * c;
|
float u = u1 * a + u2 * b + u3 * c;
|
||||||
@ -472,22 +470,22 @@ public class SkeletonRenderer {
|
|||||||
|
|
||||||
idx += clipOutput.size >> 1;
|
idx += clipOutput.size >> 1;
|
||||||
} else {
|
} else {
|
||||||
clippedVertices.add(clipInput[0]);
|
clippedVertices.add(x1);
|
||||||
clippedVertices.add(clipInput[1]);
|
clippedVertices.add(y1);
|
||||||
clippedVertices.add(light);
|
clippedVertices.add(light);
|
||||||
if (twoColor) clippedVertices.add(dark);
|
if (twoColor) clippedVertices.add(dark);
|
||||||
clippedVertices.add(u1);
|
clippedVertices.add(u1);
|
||||||
clippedVertices.add(v1);
|
clippedVertices.add(v1);
|
||||||
|
|
||||||
clippedVertices.add(clipInput[2]);
|
clippedVertices.add(x2);
|
||||||
clippedVertices.add(clipInput[3]);
|
clippedVertices.add(y2);
|
||||||
clippedVertices.add(light);
|
clippedVertices.add(light);
|
||||||
if (twoColor) clippedVertices.add(dark);
|
if (twoColor) clippedVertices.add(dark);
|
||||||
clippedVertices.add(u2);
|
clippedVertices.add(u2);
|
||||||
clippedVertices.add(v2);
|
clippedVertices.add(v2);
|
||||||
|
|
||||||
clippedVertices.add(clipInput[4]);
|
clippedVertices.add(x3);
|
||||||
clippedVertices.add(clipInput[5]);
|
clippedVertices.add(y3);
|
||||||
clippedVertices.add(light);
|
clippedVertices.add(light);
|
||||||
if (twoColor) clippedVertices.add(dark);
|
if (twoColor) clippedVertices.add(dark);
|
||||||
clippedVertices.add(u3);
|
clippedVertices.add(u3);
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
package com.esotericsoftware.spine.utils;
|
package com.esotericsoftware.spine.utils;
|
||||||
|
|
||||||
import com.badlogic.gdx.math.Intersector;
|
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.badlogic.gdx.utils.FloatArray;
|
import com.badlogic.gdx.utils.FloatArray;
|
||||||
|
|
||||||
@ -9,29 +8,50 @@ public class SutherlandHodgmanClipper {
|
|||||||
Vector2 tmp = new Vector2();
|
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
|
FloatArray output) {
|
||||||
* within the clipping area, false is returned.
|
|
||||||
*/
|
|
||||||
public boolean clip (float[] triangle, int offset, int length, int stride, FloatArray clippingArea, FloatArray output) {
|
|
||||||
boolean isClockwise = clockwise(clippingArea);
|
boolean isClockwise = clockwise(clippingArea);
|
||||||
|
return clip(x1, y1, x2, y2, x3, y3, clippingArea, output, isClockwise);
|
||||||
|
}
|
||||||
|
|
||||||
FloatArray originalOutput = output;
|
/**
|
||||||
|
* 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;
|
||||||
boolean clipped = false;
|
boolean clipped = false;
|
||||||
|
|
||||||
FloatArray input = scratch;
|
FloatArray input = null;
|
||||||
input.clear();
|
// avoid copy at the end
|
||||||
for (int i = offset; i < offset + length; i+= stride) {
|
if ((clippingArea.size / 2) % 2 != 0) {
|
||||||
input.add(triangle[i]);
|
input = output;
|
||||||
input.add(triangle[i + 1]);
|
output = scratch;
|
||||||
|
} else {
|
||||||
|
input = scratch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input.clear();
|
||||||
|
input.add(x1);
|
||||||
|
input.add(y1);
|
||||||
|
input.add(x2);
|
||||||
|
input.add(y2);
|
||||||
|
input.add(x3);
|
||||||
|
input.add(y3);
|
||||||
|
input.add(x1);
|
||||||
|
input.add(y1);
|
||||||
output.clear();
|
output.clear();
|
||||||
|
|
||||||
for (int i = 0; i < clippingArea.size; i += 2) {
|
final float[] clippingVertices = clippingArea.items;
|
||||||
float edgeX = clippingArea.items[i];
|
final int clippingVerticesLength = clippingArea.size - 2;
|
||||||
float edgeY = clippingArea.items[i + 1];
|
for (int i = 0; i < clippingVerticesLength; i += 2) {
|
||||||
float edgeX2 = clippingArea.items[(i + 2) % clippingArea.size];
|
float edgeX = clippingVertices[i];
|
||||||
float edgeY2 = clippingArea.items[(i + 3) % clippingArea.size];
|
float edgeY = clippingVertices[i + 1];
|
||||||
|
float edgeX2 = clippingVertices[i + 2];
|
||||||
|
float edgeY2 = clippingVertices[i + 3];
|
||||||
|
|
||||||
if (!isClockwise) {
|
if (!isClockwise) {
|
||||||
float tmp = edgeX;
|
float tmp = edgeX;
|
||||||
@ -43,14 +63,20 @@ public class SutherlandHodgmanClipper {
|
|||||||
edgeY2 = tmp;
|
edgeY2 = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < input.size; j += 2) {
|
final float deltaX = edgeX - edgeX2;
|
||||||
float inputX = input.items[j % input.size];
|
final float deltaY = edgeY - edgeY2;
|
||||||
float inputY = input.items[(j + 1) % input.size];
|
|
||||||
float inputX2 = input.items[(j + 2) % input.size];
|
|
||||||
float inputY2 = input.items[(j + 3) % input.size];
|
|
||||||
|
|
||||||
int side = pointLineSide(edgeX2, edgeY2, edgeX, edgeY, inputX, inputY);
|
final float[] inputVertices = input.items;
|
||||||
int side2 = pointLineSide(edgeX2, edgeY2, edgeX, edgeY, inputX2, inputY2);
|
final int inputVerticesLength = input.size - 2;
|
||||||
|
|
||||||
|
for (int j = 0; j < inputVerticesLength; j += 2) {
|
||||||
|
final float inputX = inputVertices[j];
|
||||||
|
final float inputY = inputVertices[j + 1];
|
||||||
|
final float inputX2 = inputVertices[j + 2];
|
||||||
|
final float inputY2 = inputVertices[j + 3];
|
||||||
|
|
||||||
|
final int side = pointLineSide(deltaX, deltaY, edgeX2, edgeY2, inputX, inputY);
|
||||||
|
final int side2 = pointLineSide(deltaX, deltaY, edgeX2, edgeY2, inputX2, inputY2);
|
||||||
|
|
||||||
// v1 inside, v2 inside
|
// v1 inside, v2 inside
|
||||||
if (side >= 0 && side2 >= 0) {
|
if (side >= 0 && side2 >= 0) {
|
||||||
@ -59,9 +85,7 @@ public class SutherlandHodgmanClipper {
|
|||||||
}
|
}
|
||||||
// v1 inside, v2 outside
|
// v1 inside, v2 outside
|
||||||
else if (side >= 0 && side2 < 0) {
|
else if (side >= 0 && side2 < 0) {
|
||||||
if (!Intersector.intersectLines(edgeX, edgeY, edgeX2, edgeY2, inputX, inputY, inputX2, inputY2, tmp)) {
|
intersectLines(edgeX, edgeY, edgeX2, edgeY2, inputX, inputY, inputX2, inputY2, tmp);
|
||||||
throw new RuntimeException("Lines should intersect, but didn't");
|
|
||||||
}
|
|
||||||
output.add(tmp.x);
|
output.add(tmp.x);
|
||||||
output.add(tmp.y);
|
output.add(tmp.y);
|
||||||
clipped = true;
|
clipped = true;
|
||||||
@ -73,9 +97,7 @@ public class SutherlandHodgmanClipper {
|
|||||||
}
|
}
|
||||||
// v1 outside, v2 inside
|
// v1 outside, v2 inside
|
||||||
else if (side < 0 && side2 >= 0) {
|
else if (side < 0 && side2 >= 0) {
|
||||||
if (!Intersector.intersectLines(edgeX, edgeY, edgeX2, edgeY2, inputX, inputY, inputX2, inputY2, tmp)) {
|
intersectLines(edgeX, edgeY, edgeX2, edgeY2, inputX, inputY, inputX2, inputY2, tmp);
|
||||||
throw new RuntimeException("Lines should intersect, but didn't");
|
|
||||||
}
|
|
||||||
output.add(tmp.x);
|
output.add(tmp.x);
|
||||||
output.add(tmp.y);
|
output.add(tmp.y);
|
||||||
output.add(inputX2);
|
output.add(inputX2);
|
||||||
@ -84,7 +106,10 @@ public class SutherlandHodgmanClipper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < clippingArea.size - 2) {
|
output.add(output.items[0]);
|
||||||
|
output.add(output.items[1]);
|
||||||
|
|
||||||
|
if (i < clippingVerticesLength - 2) {
|
||||||
FloatArray tmp = output;
|
FloatArray tmp = output;
|
||||||
output = input;
|
output = input;
|
||||||
output.clear();
|
output.clear();
|
||||||
@ -97,24 +122,26 @@ public class SutherlandHodgmanClipper {
|
|||||||
originalOutput.addAll(output.items, 0, output.size);
|
originalOutput.addAll(output.items, 0, output.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
originalOutput.setSize(originalOutput.size - 2);
|
||||||
|
|
||||||
return clipped;
|
return clipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int pointLineSide(float lineX, float lineY, float lineX2, float lineY2, float pointX, float pointY) {
|
private int pointLineSide(float deltaX, float deltaY, float lineX, float lineY, float pointX, float pointY) {
|
||||||
return (int)Math.signum((lineX2 - lineX) * (pointY - lineY) - (lineY2 - lineY) * (pointX - lineX));
|
return (int) Math.signum(deltaX * (pointY - lineY) - deltaY * (pointX - lineX));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean 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) {
|
Vector2 intersection) {
|
||||||
float d = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
|
float c0 = y4 - y3;
|
||||||
if (d == 0) return false;
|
float c1 = x2 - x1;
|
||||||
|
float c2 = x4 - x3;
|
||||||
|
float c3 = y2 - y1;
|
||||||
|
float d = c0 * c1 - c2 * c3;
|
||||||
|
|
||||||
if (intersection != null) {
|
float ua = (c2 * (y1 - y3) - c0 * (x1 - x3)) / d;
|
||||||
float ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / d;
|
|
||||||
intersection.set(x1 + (x2 - x1) * ua, y1 + (y2 - y1) * ua);
|
intersection.set(x1 + (x2 - x1) * ua, y1 + (y2 - y1) * ua);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean clockwise(FloatArray poly) {
|
public static boolean clockwise(FloatArray poly) {
|
||||||
return area(poly) < 0;
|
return area(poly) < 0;
|
||||||
@ -123,11 +150,13 @@ public class SutherlandHodgmanClipper {
|
|||||||
public static float area(FloatArray poly) {
|
public static float area(FloatArray poly) {
|
||||||
float area = 0;
|
float area = 0;
|
||||||
|
|
||||||
for (int i = 0; i < poly.size; i += 2) {
|
final float[] polyVertices = poly.items;
|
||||||
float x = poly.items[i];
|
final int polySize = poly.size;
|
||||||
float y = poly.items[i + 1];
|
for (int i = 0; i < polySize; i += 2) {
|
||||||
float x2 = poly.items[(i + 2) % poly.size];
|
float x = polyVertices[i];
|
||||||
float y2 = poly.items[(i + 3) % poly.size];
|
float y = polyVertices[i + 1];
|
||||||
|
float x2 = polyVertices[(i + 2) % poly.size];
|
||||||
|
float y2 = polyVertices[(i + 3) % poly.size];
|
||||||
|
|
||||||
area += x * y2 - y * x2;
|
area += x * y2 - y * x2;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user