aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/com/jogamp/opengl/math/geom
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-04-09 08:31:41 +0200
committerSven Gothel <[email protected]>2014-04-09 08:31:41 +0200
commitbe8d0765317cdcb44bbe3016cc18273ecace9324 (patch)
tree912d5fe2c0b1851578890546ba0e05d6d1296b9a /src/jogl/classes/com/jogamp/opengl/math/geom
parent0234452455511713fcbfd5df1987c3958cca781b (diff)
Add AABBox.getRayIntersection(..), VectorUtil.line2PlaneIntersection(..) incl. getNormal*(..) and getPlane*(..)
AABBox.getRayIntersection(..) provides the intersecting coordinates, where the fast alternative AABBox.intersectsRay(..) does not.
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/math/geom')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java129
1 files changed, 129 insertions, 0 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java b/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java
index 8a0bf37a0..6f1384c28 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java
@@ -432,6 +432,135 @@ public class AABBox {
return true;
}
+ /**
+ * Return intersection of a {@link Ray} with this bounding box,
+ * or null if none exist.
+ * <p>
+ * <ul>
+ * <li>Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990 [2]</li>
+ * <li>Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500)</li>
+ * <li>Epsilon value added by Klaus Hartmann.</li>
+ * </ul>
+ * Method is based on the requirements:
+ * <ul>
+ * <li>the integer representation of 0.0f is 0x00000000</li>
+ * <li>the sign bit of the float is the most significant one</li>
+ * </ul>
+ * Report bugs: [email protected]
+ * </p>
+ * <pre>
+ * [1] http://www.codercorner.com/RayAABB.cpp
+ * [2] http://tog.acm.org/resources/GraphicsGems/gems/RayBox.c
+ * </pre>
+ * @param result vec3
+ * @param ray
+ * @param epsilon
+ * @param assumeIntersection if true, method assumes an intersection, i.e. by pre-checking via {@link #intersectsRay(Ray)}.
+ * In this case method will not validate a possible non-intersection and just computes
+ * coordinates.
+ * @param tmp1V3 temp vec3
+ * @param tmp2V3 temp vec3
+ * @param tmp3V3 temp vec3
+ * @return float[3] result of intersection coordinates, or null if none exists
+ */
+ public final float[] getRayIntersection(final float[] result, final Ray ray, final float epsilon,
+ final boolean assumeIntersection,
+ final float[] tmp1V3, final float[] tmp2V3, final float[] tmp3V3) {
+ final float[] maxT = { -1f, -1f, -1f };
+
+ final float[] origin = ray.orig;
+ final float[] dir = ray.dir;
+
+ boolean inside = true;
+
+ // Find candidate planes.
+ for(int i=0; i<3; i++) {
+ if(origin[i] < low[i]) {
+ result[i] = low[i];
+ inside = false;
+
+ // Calculate T distances to candidate planes
+ if( 0 != Float.floatToIntBits(dir[i]) ) {
+ maxT[i] = (low[i] - origin[i]) / dir[i];
+ }
+ } else if(origin[i] > high[i]) {
+ result[i] = high[i];
+ inside = false;
+
+ // Calculate T distances to candidate planes
+ if( 0 != Float.floatToIntBits(dir[i]) ) {
+ maxT[i] = (high[i] - origin[i]) / dir[i];
+ }
+ }
+ }
+
+ // Ray origin inside bounding box
+ if(inside) {
+ System.arraycopy(origin, 0, result, 0, 3);
+ return result;
+ }
+
+ // Get largest of the maxT's for final choice of intersection
+ int whichPlane = 0;
+ if(maxT[1] > maxT[whichPlane]) { whichPlane = 1; }
+ if(maxT[2] > maxT[whichPlane]) { whichPlane = 2; }
+
+ if( !assumeIntersection ) {
+ // Check final candidate actually inside box
+ if( 0 != ( Float.floatToIntBits(maxT[whichPlane]) & 0x80000000 ) ) {
+ return null;
+ }
+
+ /** Use unrolled version below ..
+ for(int i=0; i<3; i++) {
+ if( i!=whichPlane ) {
+ result[i] = origin[i] + maxT[whichPlane] * dir[i];
+ if(result[i] < minB[i] - epsilon || result[i] > maxB[i] + epsilon) { return null; }
+ // if(result[i] < minB[i] || result[i] > maxB[i] ) { return null; }
+ }
+ } */
+ switch( whichPlane ) {
+ case 0:
+ result[1] = origin[1] + maxT[whichPlane] * dir[1];
+ if(result[1] < low[1] - epsilon || result[1] > high[1] + epsilon) { return null; }
+ result[2] = origin[2] + maxT[whichPlane] * dir[2];
+ if(result[2] < low[2] - epsilon || result[2] > high[2] + epsilon) { return null; }
+ break;
+ case 1:
+ result[0] = origin[0] + maxT[whichPlane] * dir[0];
+ if(result[0] < low[0] - epsilon || result[0] > high[0] + epsilon) { return null; }
+ result[2] = origin[2] + maxT[whichPlane] * dir[2];
+ if(result[2] < low[2] - epsilon || result[2] > high[2] + epsilon) { return null; }
+ break;
+ case 2:
+ result[0] = origin[0] + maxT[whichPlane] * dir[0];
+ if(result[0] < low[0] - epsilon || result[0] > high[0] + epsilon) { return null; }
+ result[1] = origin[1] + maxT[whichPlane] * dir[1];
+ if(result[1] < low[1] - epsilon || result[1] > high[1] + epsilon) { return null; }
+ break;
+ default:
+ throw new InternalError("XXX");
+ }
+ } else {
+ switch( whichPlane ) {
+ case 0:
+ result[1] = origin[1] + maxT[whichPlane] * dir[1];
+ result[2] = origin[2] + maxT[whichPlane] * dir[2];
+ break;
+ case 1:
+ result[0] = origin[0] + maxT[whichPlane] * dir[0];
+ result[2] = origin[2] + maxT[whichPlane] * dir[2];
+ break;
+ case 2:
+ result[0] = origin[0] + maxT[whichPlane] * dir[0];
+ result[1] = origin[1] + maxT[whichPlane] * dir[1];
+ break;
+ default:
+ throw new InternalError("XXX");
+ }
+ }
+ return result; // ray hits box
+ }
/**
* Get the size of this AABBox where the size is represented by the