OBB2D optimizaitons
This commit is contained in:
parent
77e2a6607c
commit
44fc754b6f
@ -24,7 +24,7 @@ import org.oscim.theme.styles.Line;
|
|||||||
|
|
||||||
class Debug {
|
class Debug {
|
||||||
|
|
||||||
private final static float[] mDebugPoints = new float[4];
|
private final static float[] mDebugPoints = new float[8];
|
||||||
|
|
||||||
static void addDebugBox(ElementLayers dbg, Label l, TextItem ti, int overlaps, boolean prev,
|
static void addDebugBox(ElementLayers dbg, Label l, TextItem ti, int overlaps, boolean prev,
|
||||||
float scale) {
|
float scale) {
|
||||||
@ -57,8 +57,9 @@ class Debug {
|
|||||||
points[3] = (l.y + height * scale);
|
points[3] = (l.y + height * scale);
|
||||||
ll.addLine(points, 4, false);
|
ll.addLine(points, 4, false);
|
||||||
|
|
||||||
|
System.arraycopy(l.bbox.vec, 2, points, 0, 8);
|
||||||
if (l.bbox != null && overlaps != 3) {
|
if (l.bbox != null && overlaps != 3) {
|
||||||
ll.addLine(l.bbox.corner, 8, true);
|
ll.addLine(points, 8, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,115 +17,129 @@
|
|||||||
package org.oscim.utils;
|
package org.oscim.utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* from http://www.flipcode.com/archives/2D_OBB_Intersection.shtml
|
* ported from http://www.flipcode.com/archives/2D_OBB_Intersection.shtml
|
||||||
*
|
|
||||||
* @author Morgan McGuire morgan@cs.brown.edu
|
|
||||||
* @author Hannes Janetzek
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class OBB2D {
|
public class OBB2D {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vector math for one array
|
||||||
|
*/
|
||||||
public static class Vec2 {
|
public static class Vec2 {
|
||||||
|
|
||||||
public static void set(float[] v, int pos, float x, float y) {
|
public static void set(float[] v, int pos, float x, float y) {
|
||||||
v[(pos << 1) + 0] = x;
|
v[pos + 0] = x;
|
||||||
v[(pos << 1) + 1] = y;
|
v[pos + 1] = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float dot(float[] a, int apos, float[] b, int bpos) {
|
public static float dot(float[] v, int a, int b) {
|
||||||
return a[apos << 1] * b[bpos << 1] + a[(apos << 1) + 1] * b[(bpos << 1) + 1];
|
return v[a] * v[b] + v[a + 1] * v[b + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static float lengthSquared(float[] v, int pos) {
|
public final static float lengthSquared(float[] v, int pos) {
|
||||||
float x = v[(pos << 1) + 0];
|
float x = v[pos + 0];
|
||||||
float y = v[(pos << 1) + 1];
|
float y = v[pos + 1];
|
||||||
|
|
||||||
return x * x + y * y;
|
return x * x + y * y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static void normalizeSquared(float[] v, int pos) {
|
public final static void normalizeSquared(float[] v, int pos) {
|
||||||
float x = v[(pos << 1) + 0];
|
float x = v[pos + 0];
|
||||||
float y = v[(pos << 1) + 1];
|
float y = v[pos + 1];
|
||||||
|
|
||||||
float length = x * x + y * y;
|
float length = x * x + y * y;
|
||||||
|
|
||||||
v[(pos << 1) + 0] = x / length;
|
v[pos + 0] = x / length;
|
||||||
v[(pos << 1) + 1] = y / length;
|
v[pos + 1] = y / length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static void normalize(float[] v, int pos) {
|
public final static void normalize(float[] v, int pos) {
|
||||||
float x = v[(pos << 1) + 0];
|
float x = v[pos + 0];
|
||||||
float y = v[(pos << 1) + 1];
|
float y = v[pos + 1];
|
||||||
|
|
||||||
double length = Math.sqrt(x * x + y * y);
|
double length = Math.sqrt(x * x + y * y);
|
||||||
|
|
||||||
v[(pos << 1) + 0] = (float) (x / length);
|
v[pos + 0] = (float) (x / length);
|
||||||
v[(pos << 1) + 1] = (float) (y / length);
|
v[pos + 1] = (float) (y / length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static float length(float[] v, int pos) {
|
public final static float length(float[] v, int pos) {
|
||||||
float x = v[(pos << 1) + 0];
|
float x = v[pos + 0];
|
||||||
float y = v[(pos << 1) + 1];
|
float y = v[pos + 1];
|
||||||
|
|
||||||
return (float) Math.sqrt(x * x + y * y);
|
return (float) Math.sqrt(x * x + y * y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static void add(float[] result, int rpos, float[] a, int apos, float[] b,
|
public final static void add(float[] v, int r, int a, int b) {
|
||||||
int bpos) {
|
v[r + 0] = v[a + 0] + v[b + 0];
|
||||||
result[(rpos << 1) + 0] = a[(apos << 1) + 0] + b[(bpos << 1) + 0];
|
v[r + 1] = v[a + 1] + v[b + 1];
|
||||||
result[(rpos << 1) + 1] = a[(apos << 1) + 1] + b[(bpos << 1) + 1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static void sub(float[] result, int rpos, float[] a, int apos, float[] b,
|
public final static void sub(float[] v, int r, int a, int b) {
|
||||||
int bpos) {
|
v[r + 0] = v[a + 0] - v[b + 0];
|
||||||
result[(rpos << 1) + 0] = a[(apos << 1) + 0] - b[(bpos << 1) + 0];
|
v[r + 1] = v[a + 1] - v[b + 1];
|
||||||
result[(rpos << 1) + 1] = a[(apos << 1) + 1] - b[(bpos << 1) + 1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static void mul(float[] v, int pos, float a) {
|
public final static void mul(float[] v, int pos, float a) {
|
||||||
v[(pos << 1) + 0] *= a;
|
v[pos + 0] *= a;
|
||||||
v[(pos << 1) + 1] *= a;
|
v[pos + 1] *= a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float originX;
|
||||||
|
float originY;
|
||||||
|
|
||||||
|
public final float[] vec = new float[4 * 2 + 2 * 2];
|
||||||
|
|
||||||
// Corners of the box, where 0 is the lower left.
|
// Corners of the box, where 0 is the lower left.
|
||||||
public final float[] corner = new float[4 * 2];
|
//public final float[] corner = new float[ 4 * 2];
|
||||||
|
private final static int CORNER_X = 0;
|
||||||
|
private final static int CORNER_Y = CORNER_X + 1;
|
||||||
|
private final static int CORNER_0 = CORNER_X;
|
||||||
|
private final static int CORNER_1 = CORNER_X + 2;
|
||||||
|
//private final static int CORNER_2 = CORNER_X + 4;
|
||||||
|
private final static int CORNER_3 = CORNER_X + 6;
|
||||||
|
|
||||||
// Two edges of the box extended away from corner[0].
|
// Two edges of the box extended away from origin[CORNER_X + 0].
|
||||||
public final float[] axis = new float[2 * 2];
|
//public final float[] axis = new float[2 * 2];
|
||||||
|
private final static int AXIS_X = 2 * 4;
|
||||||
|
private final static int AXIS_Y = AXIS_X + 1;
|
||||||
|
|
||||||
// origin[a] = corner[0].dot(axis[a]);
|
private final static int AXIS_1 = AXIS_X;
|
||||||
public final float[] origin = new float[2];
|
private final static int AXIS_2 = AXIS_X + 2;
|
||||||
|
|
||||||
// Returns true if other overlaps one dimension of this.
|
// Returns true if other overlaps one dimension of this.
|
||||||
private boolean overlaps1Way(OBB2D other) {
|
private boolean overlaps1Way(OBB2D other) {
|
||||||
for (int a = 0; a < 2; a++) {
|
for (int a = 0; a <= 2; a += 2) {
|
||||||
float ax = axis[a * 2];
|
float ax = vec[AXIS_X + a];
|
||||||
float ay = axis[a * 2 + 1];
|
float ay = vec[AXIS_Y + a];
|
||||||
|
|
||||||
// dot product
|
// dot product
|
||||||
float t = ax * other.corner[0] + ay * other.corner[1];
|
float t = ax * other.vec[CORNER_X] + ay * other.vec[CORNER_Y];
|
||||||
|
|
||||||
// Find the extent of box 2 on axis a
|
// Find the extent of box 2 on axis a
|
||||||
float tMin = t;
|
float tMin = t;
|
||||||
float tMax = t;
|
float tMax = t;
|
||||||
|
|
||||||
for (int c = 2; c < 8; c += 2) {
|
for (int c = CORNER_X + 2; c < 8; c += 2) {
|
||||||
t = ax * other.corner[c] + ay * other.corner[c + 1];
|
t = ax * other.vec[c] + ay * other.vec[c + 1];
|
||||||
|
|
||||||
if (t < tMin) {
|
if (t < tMin)
|
||||||
tMin = t;
|
tMin = t;
|
||||||
} else if (t > tMax) {
|
else if (t > tMax)
|
||||||
tMax = t;
|
tMax = t;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// We have to subtract off the origin
|
// We have to subtract off the origin
|
||||||
// See if [tMin, tMax] intersects [0, 1]
|
// See if [tMin, tMax] intersects [0, 1]
|
||||||
if ((tMin > 1 + origin[a]) || (tMax < origin[a])) {
|
if (a == 0) {
|
||||||
|
if ((tMin > 1 + originX) || (tMax < originX))
|
||||||
// There was no intersection along this dimension;
|
// There was no intersection along this dimension;
|
||||||
// the boxes cannot possibly overlap.
|
// the boxes cannot possibly overlap.
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
if ((tMin > 1 + originY) || (tMax < originY))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,42 +151,42 @@ public class OBB2D {
|
|||||||
// Updates the axes after the corners move. Assumes the
|
// Updates the axes after the corners move. Assumes the
|
||||||
// corners actually form a rectangle.
|
// corners actually form a rectangle.
|
||||||
private void computeAxes() {
|
private void computeAxes() {
|
||||||
Vec2.sub(axis, 0, corner, 1, corner, 0);
|
Vec2.sub(vec, AXIS_1, CORNER_1, CORNER_0);
|
||||||
Vec2.sub(axis, 1, corner, 3, corner, 0);
|
Vec2.sub(vec, AXIS_2, CORNER_3, CORNER_0);
|
||||||
|
|
||||||
// Make the length of each axis 1/edge length so we know any
|
// Make the length of each axis 1/edge length so we know any
|
||||||
// dot product must be less than 1 to fall within the edge.
|
// dot product must be less than 1 to fall within the edge.
|
||||||
Vec2.normalizeSquared(axis, 0);
|
Vec2.normalizeSquared(vec, AXIS_1);
|
||||||
origin[0] = Vec2.dot(corner, 0, axis, 0);
|
originX = Vec2.dot(vec, CORNER_0, AXIS_1);
|
||||||
|
|
||||||
Vec2.normalizeSquared(axis, 1);
|
Vec2.normalizeSquared(vec, AXIS_2);
|
||||||
origin[1] = Vec2.dot(corner, 0, axis, 1);
|
originY = Vec2.dot(vec, CORNER_0, AXIS_2);
|
||||||
}
|
|
||||||
|
|
||||||
public OBB2D(float cx, float cy, float w, float h, float angle) {
|
|
||||||
float rcos = (float) Math.cos(angle);
|
|
||||||
float rsin = (float) Math.sin(angle);
|
|
||||||
|
|
||||||
float[] tmp = new float[4 * 2];
|
|
||||||
Vec2.set(tmp, 0, rcos, rsin);
|
|
||||||
Vec2.set(tmp, 1, -rsin, rcos);
|
|
||||||
|
|
||||||
Vec2.mul(tmp, 0, w / 2);
|
|
||||||
Vec2.mul(tmp, 1, h / 2);
|
|
||||||
|
|
||||||
Vec2.add(tmp, 2, tmp, 0, tmp, 1);
|
|
||||||
Vec2.sub(tmp, 3, tmp, 0, tmp, 1);
|
|
||||||
|
|
||||||
Vec2.set(tmp, 0, cx, cy);
|
|
||||||
|
|
||||||
Vec2.sub(corner, 0, tmp, 0, tmp, 3);
|
|
||||||
Vec2.add(corner, 1, tmp, 0, tmp, 3);
|
|
||||||
Vec2.add(corner, 2, tmp, 0, tmp, 2);
|
|
||||||
Vec2.sub(corner, 3, tmp, 0, tmp, 2);
|
|
||||||
|
|
||||||
computeAxes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public OBB2D(float cx, float cy, float w, float h, float angle) {
|
||||||
|
// float rcos = (float) Math.cos(angle);
|
||||||
|
// float rsin = (float) Math.sin(angle);
|
||||||
|
//
|
||||||
|
// float[] tmp = new float[4 * 2];
|
||||||
|
// Vec2.set(tmp, 0, rcos, rsin);
|
||||||
|
// Vec2.set(tmp, 1, -rsin, rcos);
|
||||||
|
//
|
||||||
|
// Vec2.mul(tmp, 0, w / 2);
|
||||||
|
// Vec2.mul(tmp, 1, h / 2);
|
||||||
|
//
|
||||||
|
// Vec2.add(tmp, 2, tmp, 0, tmp, 1);
|
||||||
|
// Vec2.sub(tmp, 3, tmp, 0, tmp, 1);
|
||||||
|
//
|
||||||
|
// Vec2.set(tmp, 0, cx, cy);
|
||||||
|
//
|
||||||
|
// Vec2.sub(origin, CORNER_X + 0, tmp, 0, tmp, 3);
|
||||||
|
// Vec2.add(origin, CORNER_X + 2, tmp, 0, tmp, 3);
|
||||||
|
// Vec2.add(origin, CORNER_X + 4, tmp, 0, tmp, 2);
|
||||||
|
// Vec2.sub(origin, CORNER_X + 6, tmp, 0, tmp, 2);
|
||||||
|
//
|
||||||
|
// computeAxes();
|
||||||
|
// }
|
||||||
|
//
|
||||||
public OBB2D() {
|
public OBB2D() {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -185,17 +199,17 @@ public class OBB2D {
|
|||||||
float ux = (float) -asin * height / 2;
|
float ux = (float) -asin * height / 2;
|
||||||
float uy = (float) acos * height / 2;
|
float uy = (float) acos * height / 2;
|
||||||
|
|
||||||
corner[0] = cx + (vx - ux);
|
vec[CORNER_X] = cx + (vx - ux);
|
||||||
corner[1] = cy + (vy - uy);
|
vec[CORNER_Y] = cy + (vy - uy);
|
||||||
|
|
||||||
corner[2] = cx + (-vx - ux);
|
vec[CORNER_X + 2] = cx + (-vx - ux);
|
||||||
corner[3] = cy + (-vy - uy);
|
vec[CORNER_Y + 2] = cy + (-vy - uy);
|
||||||
|
|
||||||
corner[4] = cx + (-vx + ux);
|
vec[CORNER_X + 4] = cx + (-vx + ux);
|
||||||
corner[5] = cy + (-vy + uy);
|
vec[CORNER_Y + 4] = cy + (-vy + uy);
|
||||||
|
|
||||||
corner[6] = cx + (vx + ux);
|
vec[CORNER_X + 6] = cx + (vx + ux);
|
||||||
corner[7] = cy + (vy + uy);
|
vec[CORNER_Y + 6] = cy + (vy + uy);
|
||||||
|
|
||||||
computeAxes();
|
computeAxes();
|
||||||
}
|
}
|
||||||
@ -219,17 +233,17 @@ public class OBB2D {
|
|||||||
ux *= hh;
|
ux *= hh;
|
||||||
uy *= hh;
|
uy *= hh;
|
||||||
|
|
||||||
corner[0] = cx - (vx - ux);
|
vec[CORNER_X] = cx - (vx - ux);
|
||||||
corner[1] = cy - (vy - uy);
|
vec[CORNER_Y] = cy - (vy - uy);
|
||||||
|
|
||||||
corner[2] = cx + (vx - ux);
|
vec[CORNER_X + 2] = cx + (vx - ux);
|
||||||
corner[3] = cy + (vy - uy);
|
vec[CORNER_Y + 2] = cy + (vy - uy);
|
||||||
|
|
||||||
corner[4] = cx + (vx + ux);
|
vec[CORNER_X + 4] = cx + (vx + ux);
|
||||||
corner[5] = cy + (vy + uy);
|
vec[CORNER_Y + 4] = cy + (vy + uy);
|
||||||
|
|
||||||
corner[6] = cx - (vx + ux);
|
vec[CORNER_X + 6] = cx - (vx + ux);
|
||||||
corner[7] = cy - (vy + uy);
|
vec[CORNER_Y + 6] = cy - (vy + uy);
|
||||||
|
|
||||||
computeAxes();
|
computeAxes();
|
||||||
}
|
}
|
||||||
@ -251,17 +265,17 @@ public class OBB2D {
|
|||||||
vx *= hw;
|
vx *= hw;
|
||||||
vy *= hw;
|
vy *= hw;
|
||||||
|
|
||||||
corner[0] = cx - vx - ux;
|
vec[CORNER_X] = cx - vx - ux;
|
||||||
corner[1] = cy - vy - uy;
|
vec[CORNER_Y] = cy - vy - uy;
|
||||||
|
|
||||||
corner[2] = cx + vx - ux;
|
vec[CORNER_X + 2] = cx + vx - ux;
|
||||||
corner[3] = cy + vy - uy;
|
vec[CORNER_Y + 2] = cy + vy - uy;
|
||||||
|
|
||||||
corner[4] = cx + vx + ux;
|
vec[CORNER_X + 4] = cx + vx + ux;
|
||||||
corner[5] = cy + vy + uy;
|
vec[CORNER_Y + 4] = cy + vy + uy;
|
||||||
|
|
||||||
corner[6] = cx - vx + ux;
|
vec[CORNER_X + 6] = cx - vx + ux;
|
||||||
corner[7] = cy - vy + uy;
|
vec[CORNER_Y + 6] = cy - vy + uy;
|
||||||
|
|
||||||
computeAxes();
|
computeAxes();
|
||||||
}
|
}
|
||||||
@ -284,17 +298,17 @@ public class OBB2D {
|
|||||||
vx *= hw;
|
vx *= hw;
|
||||||
vy *= hw;
|
vy *= hw;
|
||||||
|
|
||||||
corner[0] = cx - vx - ux;
|
vec[CORNER_X + 0] = cx - vx - ux;
|
||||||
corner[1] = cy - vy - uy;
|
vec[CORNER_Y + 0] = cy - vy - uy;
|
||||||
|
|
||||||
corner[2] = cx + vx - ux;
|
vec[CORNER_X + 2] = cx + vx - ux;
|
||||||
corner[3] = cy + vy - uy;
|
vec[CORNER_Y + 2] = cy + vy - uy;
|
||||||
|
|
||||||
corner[4] = cx + vx + ux;
|
vec[CORNER_X + 4] = cx + vx + ux;
|
||||||
corner[5] = cy + vy + uy;
|
vec[CORNER_Y + 4] = cy + vy + uy;
|
||||||
|
|
||||||
corner[6] = cx - vx + ux;
|
vec[CORNER_X + 6] = cx - vx + ux;
|
||||||
corner[7] = cy - vy + uy;
|
vec[CORNER_Y + 6] = cy - vy + uy;
|
||||||
|
|
||||||
computeAxes();
|
computeAxes();
|
||||||
}
|
}
|
||||||
@ -305,26 +319,26 @@ public class OBB2D {
|
|||||||
float hw = width / 2;
|
float hw = width / 2;
|
||||||
float hh = height / 2;
|
float hh = height / 2;
|
||||||
|
|
||||||
corner[0] = cx - hw;
|
vec[CORNER_X] = cx - hw;
|
||||||
corner[1] = cy - hh;
|
vec[CORNER_Y] = cy - hh;
|
||||||
|
|
||||||
corner[2] = cx - hw;
|
vec[CORNER_X + 2] = cx - hw;
|
||||||
corner[3] = cy + hh;
|
vec[CORNER_Y + 2] = cy + hh;
|
||||||
|
|
||||||
corner[4] = cx + hw;
|
vec[CORNER_X + 4] = cx + hw;
|
||||||
corner[5] = cy + hh;
|
vec[CORNER_Y + 4] = cy + hh;
|
||||||
|
|
||||||
corner[6] = cx + hw;
|
vec[CORNER_X + 6] = cx + hw;
|
||||||
corner[7] = cy - hh;
|
vec[CORNER_Y + 6] = cy - hh;
|
||||||
|
|
||||||
axis[0] = 0;
|
vec[AXIS_X + 0] = 0;
|
||||||
axis[1] = 1 / height;
|
vec[AXIS_X + 1] = 1 / height;
|
||||||
|
|
||||||
axis[2] = 1 / width;
|
vec[AXIS_X + 2] = 1 / width;
|
||||||
axis[3] = 0;
|
vec[AXIS_X + 3] = 0;
|
||||||
|
|
||||||
origin[0] = corner[1] * axis[1];
|
vec[0] = vec[CORNER_Y] * vec[AXIS_Y];
|
||||||
origin[1] = corner[2] * axis[2];
|
vec[1] = vec[CORNER_X + 2] * vec[AXIS_X + 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the intersection of the boxes is non-empty.
|
// Returns true if the intersection of the boxes is non-empty.
|
||||||
@ -334,12 +348,12 @@ public class OBB2D {
|
|||||||
|
|
||||||
// // For testing purposes.
|
// // For testing purposes.
|
||||||
// void moveTo(Vec2 center) {
|
// void moveTo(Vec2 center) {
|
||||||
// Vec2 centroid = (corner[0] + corner[1] + corner[2] + corner[3]) / 4;
|
// Vec2 centroid = (origin[CORNER_X + 0] + origin[CORNER_X + 1] + origin[CORNER_X + 2] + origin[CORNER_X + 3]) / 4;
|
||||||
//
|
//
|
||||||
// Vec2 translation = center - centroid;
|
// Vec2 translation = center - centroid;
|
||||||
//
|
//
|
||||||
// for (int c = 0; c < 4; ++c) {
|
// for (int c = 0; c < 4; ++c) {
|
||||||
// corner[c] += translation;
|
// origin[CORNER_X + c] += translation;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// computeAxes();
|
// computeAxes();
|
||||||
@ -348,7 +362,7 @@ public class OBB2D {
|
|||||||
// void render() {
|
// void render() {
|
||||||
// glBegin(GL_LINES);
|
// glBegin(GL_LINES);
|
||||||
// for (int c = 0; c < 5; ++c) {
|
// for (int c = 0; c < 5; ++c) {
|
||||||
// glVertex2fv(corner[c & 3]);
|
// glVertex2fv(origin[CORNER_X + c & 3]);
|
||||||
// }
|
// }
|
||||||
// glEnd();
|
// glEnd();
|
||||||
// }
|
// }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user