diff options
author | Sven Gothel <[email protected]> | 2023-04-05 09:42:28 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2023-04-05 09:42:28 +0200 |
commit | 15e60161787224e85172685f74dc0ac195969b51 (patch) | |
tree | 68f3b44be2b340cfb7903996cea4820512049463 /src/jogl/classes/com/jogamp/opengl/math/geom | |
parent | 603233b19373bfa157dd033132bff809af6a123f (diff) |
Math: Complete Matrix4f w/ Vec[234]f and adopt it throughout Quaternion, Ray, AABBox, Frustum, Stereo*, ... adding hook to PMVMatrix
Motivation was to simplify matrix + vector math usage, ease review and avoid usage bugs.
Matrix4f implementation uses dedicated float fields instead of an array.
Performance didn't increase much,
as JVM >= 11(?) has some optimizations to drop the array bounds check.
AMD64 + OpenJDK17
- Matrix4f.mul(a, b) got a roughly ~10% enhancement over FloatUtil.multMatrix(a, b, dest)
- Matrix4f.mul(b) roughly ~3% slower than FloatUtil.multMatrix(a, b, dest)
- FloatUtil.multMatrix(a, a_off, b, b_off, dest) is considerable slower than all
- Matrix4f.invert(..) roughly ~3% slower than FloatUtil.invertMatrix(..)
RaspberryPi 4b aarch64 + OpenJDK17
- Matrix4f.mul(a, b) got a roughly ~10% enhancement over FloatUtil.multMatrix(a, b, dest)
- Matrix4f.mul(b) roughly ~20% slower than FloatUtil.multMatrix(a, b)
- FloatUtil.multMatrix(a, a_off, b, b_off, dest) is considerable slower than all
- Matrix4f.invert(..) roughly ~4% slower than FloatUtil.invertMatrix(..)
Conclusion
- Matrix4f.mul(b) needs to be revised (esp for aarch64)
- Matrix4f.invert(..) should also not be slower ..
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/math/geom')
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java | 433 | ||||
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java | 121 |
2 files changed, 301 insertions, 253 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 f858b1c0d..9e8edfbf0 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java +++ b/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java @@ -1,5 +1,5 @@ /** - * Copyright 2010 JogAmp Community. All rights reserved. + * Copyright 2010-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -29,9 +29,11 @@ package com.jogamp.opengl.math.geom; import com.jogamp.graph.geom.plane.AffineTransform; import com.jogamp.opengl.math.FloatUtil; +import com.jogamp.opengl.math.Matrix4f; import com.jogamp.opengl.math.Quaternion; import com.jogamp.opengl.math.Ray; -import com.jogamp.opengl.math.VectorUtil; +import com.jogamp.opengl.math.Vec3f; +import com.jogamp.opengl.util.PMVMatrix; /** @@ -51,9 +53,9 @@ import com.jogamp.opengl.math.VectorUtil; */ public class AABBox { private static final boolean DEBUG = FloatUtil.DEBUG; - private final float[] low = new float[3]; - private final float[] high = new float[3]; - private final float[] center = new float[3]; + private final Vec3f low = new Vec3f(); + private final Vec3f high = new Vec3f(); + private final Vec3f center = new Vec3f(); /** * Create an Axis Aligned bounding box (AABBox) with the @@ -109,42 +111,34 @@ public class AABBox { public final AABBox reset() { setLow(Float.MAX_VALUE,Float.MAX_VALUE,Float.MAX_VALUE); setHigh(-1*Float.MAX_VALUE,-1*Float.MAX_VALUE,-1*Float.MAX_VALUE); - center[0] = 0f; - center[1] = 0f; - center[2] = 0f; + center.set( 0f, 0f, 0f); return this; } /** Get the max xyz-coordinates - * @return a float array containing the max xyz coordinates + * @return max xyz coordinates */ - public final float[] getHigh() { + public final Vec3f getHigh() { return high; } private final void setHigh(final float hx, final float hy, final float hz) { - this.high[0] = hx; - this.high[1] = hy; - this.high[2] = hz; + this.high.set(hx, hy, hz); } /** Get the min xyz-coordinates - * @return a float array containing the min xyz coordinates + * @return min xyz coordinates */ - public final float[] getLow() { + public final Vec3f getLow() { return low; } private final void setLow(final float lx, final float ly, final float lz) { - this.low[0] = lx; - this.low[1] = ly; - this.low[2] = lz; + this.low.set(lx, ly, lz); } private final void computeCenter() { - center[0] = (high[0] + low[0])/2f; - center[1] = (high[1] + low[1])/2f; - center[2] = (high[2] + low[2])/2f; + center.set(high).add(low).scale(1f/2f); } /** @@ -154,9 +148,9 @@ public class AABBox { * @return this AABBox for chaining */ public final AABBox copy(final AABBox src) { - System.arraycopy(src.low, 0, low, 0, 3); - System.arraycopy(src.high, 0, high, 0, 3); - System.arraycopy(src.center, 0, center, 0, 3); + low.set(src.low); + high.set(src.high); + center.set(src.center); return this; } @@ -186,12 +180,23 @@ public class AABBox { */ public final AABBox setSize(final float lx, final float ly, final float lz, final float hx, final float hy, final float hz) { - this.low[0] = lx; - this.low[1] = ly; - this.low[2] = lz; - this.high[0] = hx; - this.high[1] = hy; - this.high[2] = hz; + this.low.set(lx, ly, lz); + this.high.set(hx, hy, hz); + computeCenter(); + return this; + } + + /** + * Set size of the AABBox specifying the coordinates + * of the low and high. + * + * @param low min xyz-coordinates + * @param high max xyz-coordinates + * @return this AABBox for chaining + */ + public final AABBox setSize(final Vec3f low, final Vec3f high) { + this.low.set(low); + this.high.set(high); computeCenter(); return this; } @@ -202,25 +207,30 @@ public class AABBox { * @return this AABBox for chaining */ public final AABBox resize(final AABBox newBox) { - final float[] newLow = newBox.getLow(); - final float[] newHigh = newBox.getHigh(); + final Vec3f newLow = newBox.getLow(); + final Vec3f newHigh = newBox.getHigh(); /** test low */ - if (newLow[0] < low[0]) - low[0] = newLow[0]; - if (newLow[1] < low[1]) - low[1] = newLow[1]; - if (newLow[2] < low[2]) - low[2] = newLow[2]; + if (newLow.x() < low.x()) { + low.setX( newLow.x() ); + } + if (newLow.y() < low.y()) { + low.setY( newLow.y() ); + } + if (newLow.z() < low.z()) { + low.setZ( newLow.z() ); + } /** test high */ - if (newHigh[0] > high[0]) - high[0] = newHigh[0]; - if (newHigh[1] > high[1]) - high[1] = newHigh[1]; - if (newHigh[2] > high[2]) - high[2] = newHigh[2]; - + if (newHigh.x() > high.x()) { + high.setX( newHigh.x() ); + } + if (newHigh.y() > high.y()) { + high.setY( newHigh.y() ); + } + if (newHigh.z() > high.z()) { + high.setZ( newHigh.z() ); + } computeCenter(); return this; } @@ -229,34 +239,32 @@ public class AABBox { * Resize the AABBox to encapsulate another AABox, which will be <i>transformed</i> on the fly first. * @param newBox AABBox to be encapsulated in * @param t the {@link AffineTransform} applied on <i>newBox</i> on the fly - * @param tmpV3 temp float[3] storage + * @param tmpV3 temporary storage * @return this AABBox for chaining */ - public final AABBox resize(final AABBox newBox, final AffineTransform t, final float[] tmpV3) { + public final AABBox resize(final AABBox newBox, final AffineTransform t, final Vec3f tmpV3) { /** test low */ { - final float[] newBoxLow = newBox.getLow(); + final Vec3f newBoxLow = newBox.getLow(); t.transform(newBoxLow, tmpV3); - tmpV3[2] = newBoxLow[2]; - if (tmpV3[0] < low[0]) - low[0] = tmpV3[0]; - if (tmpV3[1] < low[1]) - low[1] = tmpV3[1]; - if (tmpV3[2] < low[2]) - low[2] = tmpV3[2]; + if (tmpV3.x() < low.x()) + low.setX( tmpV3.x() ); + if (tmpV3.y() < low.y()) + low.setY( tmpV3.y() ); + if (tmpV3.z() < low.z()) + low.setZ( tmpV3.z() ); } /** test high */ { - final float[] newBoxHigh = newBox.getHigh(); + final Vec3f newBoxHigh = newBox.getHigh(); t.transform(newBoxHigh, tmpV3); - tmpV3[2] = newBoxHigh[2]; - if (tmpV3[0] > high[0]) - high[0] = tmpV3[0]; - if (tmpV3[1] > high[1]) - high[1] = tmpV3[1]; - if (tmpV3[2] > high[2]) - high[2] = tmpV3[2]; + if (tmpV3.x() > high.x()) + high.setX( tmpV3.x() ); + if (tmpV3.y() > high.y()) + high.setY( tmpV3.y() ); + if (tmpV3.z() > high.z()) + high.setZ( tmpV3.z() ); } computeCenter(); @@ -273,25 +281,25 @@ public class AABBox { */ public final AABBox resize(final float x, final float y, final float z) { /** test low */ - if (x < low[0]) { - low[0] = x; + if (x < low.x()) { + low.setX( x ); } - if (y < low[1]) { - low[1] = y; + if (y < low.y()) { + low.setY( y ); } - if (z < low[2]) { - low[2] = z; + if (z < low.z()) { + low.setZ( z ); } /** test high */ - if (x > high[0]) { - high[0] = x; + if (x > high.x()) { + high.setX( x ); } - if (y > high[1]) { - high[1] = y; + if (y > high.y()) { + high.setY( y ); } - if (z > high[2]) { - high[2] = z; + if (z > high.z()) { + high.setZ( z ); } computeCenter(); @@ -320,6 +328,16 @@ public class AABBox { } /** + * Resize the AABBox to encapsulate the passed + * xyz-coordinates. + * @param xyz xyz-axis coordinate values + * @return this AABBox for chaining + */ + public final AABBox resize(final Vec3f xyz) { + return resize(xyz.x(), xyz.y(), xyz.z()); + } + + /** * Check if the x & y coordinates are bounded/contained * by this AABBox * @param x x-axis coordinate value @@ -328,10 +346,10 @@ public class AABBox { * y belong to (low.y, high.y) */ public final boolean contains(final float x, final float y) { - if(x<low[0] || x>high[0]){ + if(x<low.x() || x>high.x()){ return false; } - if(y<low[1]|| y>high[1]){ + if(y<low.y()|| y>high.y()){ return false; } return true; @@ -347,13 +365,13 @@ public class AABBox { * y belong to (low.y, high.y) and z belong to (low.z, high.z) */ public final boolean contains(final float x, final float y, final float z) { - if(x<low[0] || x>high[0]){ + if(x<low.x() || x>high.x()){ return false; } - if(y<low[1]|| y>high[1]){ + if(y<low.y()|| y>high.y()){ return false; } - if(z<low[2] || z>high[2]){ + if(z<low.z() || z>high.z()){ return false; } return true; @@ -390,13 +408,13 @@ public class AABBox { /** * Check if {@link Ray} intersects this bounding box. * <p> - * Versions uses the SAT[1], testing 6 axes. + * Versions uses the SAT.y(), testing 6 axes. * Original code for OBBs from MAGIC. - * Rewritten for AABBs and reorganized for early exits[2]. + * Rewritten for AABBs and reorganized for early exits.z(). * </p> * <pre> - * [1] SAT = Separating Axis Theorem - * [2] http://www.codercorner.com/RayAABB.cpp + * .y() SAT = Separating Axis Theorem + * .z() http://www.codercorner.com/RayAABB.cpp * </pre> * @param ray * @return @@ -405,19 +423,19 @@ public class AABBox { // diff[XYZ] -> VectorUtil.subVec3(diff, ray.orig, center); // ext[XYZ] -> extend VectorUtil.subVec3(ext, high, center); - final float dirX = ray.dir[0]; - final float diffX = ray.orig[0] - center[0]; - final float extX = high[0] - center[0]; + final float dirX = ray.dir.x(); + final float diffX = ray.orig.x() - center.x(); + final float extX = high.x() - center.x(); if( Math.abs(diffX) > extX && diffX*dirX >= 0f ) return false; - final float dirY = ray.dir[1]; - final float diffY = ray.orig[1] - center[1]; - final float extY = high[1] - center[1]; + final float dirY = ray.dir.y(); + final float diffY = ray.orig.y() - center.y(); + final float extY = high.y() - center.y(); if( Math.abs(diffY) > extY && diffY*dirY >= 0f ) return false; - final float dirZ = ray.dir[2]; - final float diffZ = ray.orig[2] - center[2]; - final float extZ = high[2] - center[2]; + final float dirZ = ray.dir.z(); + final float diffZ = ray.orig.z() - center.z(); + final float extZ = high.z() - center.z(); if( Math.abs(diffZ) > extZ && diffZ*dirZ >= 0f ) return false; final float absDirY = Math.abs(dirY); @@ -442,7 +460,7 @@ public class AABBox { * or null if none exist. * <p> * <ul> - * <li>Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990 [2]</li> + * <li>Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990 .z()</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> @@ -458,8 +476,8 @@ public class AABBox { * Report bugs: [email protected] (original author) * </p> * <pre> - * [1] http://www.codercorner.com/RayAABB.cpp - * [2] http://tog.acm.org/resources/GraphicsGems/gems/RayBox.c + * .y() http://www.codercorner.com/RayAABB.cpp + * .z() http://tog.acm.org/resources/GraphicsGems/gems/RayBox.c * </pre> * @param result vec3 * @param ray @@ -467,45 +485,45 @@ public class AABBox { * @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) { + public final Vec3f getRayIntersection(final Vec3f result, final Ray ray, final float epsilon, + final boolean assumeIntersection) { final float[] maxT = { -1f, -1f, -1f }; - final float[] origin = ray.orig; - final float[] dir = ray.dir; + final Vec3f origin = ray.orig; + final Vec3f 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]; + final float origin_i = origin.get(i); + final float dir_i = dir.get(i); + final float low_i = low.get(i); + final float high_i = high.get(i); + if(origin_i < low_i) { + result.set(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]; + if( 0 != Float.floatToIntBits(dir_i) ) { + maxT[i] = (low_i - origin_i) / dir_i; } - } else if(origin[i] > high[i]) { - result[i] = high[i]; + } else if(origin_i > high_i) { + result.set(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]; + 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); + result.set(origin); return result; } @@ -530,22 +548,22 @@ public class AABBox { } */ 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; } + result.setY( origin.y() + maxT[whichPlane] * dir.y() ); + if(result.y() < low.y() - epsilon || result.y() > high.y() + epsilon) { return null; } + result.setZ( origin.z() + maxT[whichPlane] * dir.z() ); + if(result.z() < low.z() - epsilon || result.z() > high.z() + 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; } + result.setX( origin.x() + maxT[whichPlane] * dir.x() ); + if(result.x() < low.x() - epsilon || result.x() > high.x() + epsilon) { return null; } + result.setZ( origin.z() + maxT[whichPlane] * dir.z() ); + if(result.z() < low.z() - epsilon || result.z() > high.z() + 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; } + result.setX( origin.x() + maxT[whichPlane] * dir.x() ); + if(result.x() < low.x() - epsilon || result.x() > high.x() + epsilon) { return null; } + result.setY( origin.y() + maxT[whichPlane] * dir.y() ); + if(result.y() < low.y() - epsilon || result.y() > high.y() + epsilon) { return null; } break; default: throw new InternalError("XXX"); @@ -553,16 +571,16 @@ public class AABBox { } else { switch( whichPlane ) { case 0: - result[1] = origin[1] + maxT[whichPlane] * dir[1]; - result[2] = origin[2] + maxT[whichPlane] * dir[2]; + result.setY( origin.y() + maxT[whichPlane] * dir.y() ); + result.setZ( origin.z() + maxT[whichPlane] * dir.z() ); break; case 1: - result[0] = origin[0] + maxT[whichPlane] * dir[0]; - result[2] = origin[2] + maxT[whichPlane] * dir[2]; + result.setX( origin.x() + maxT[whichPlane] * dir.x() ); + result.setZ( origin.z() + maxT[whichPlane] * dir.z() ); break; case 2: - result[0] = origin[0] + maxT[whichPlane] * dir[0]; - result[1] = origin[1] + maxT[whichPlane] * dir[1]; + result.setX( origin.x() + maxT[whichPlane] * dir.x() ); + result.setY( origin.y() + maxT[whichPlane] * dir.y() ); break; default: throw new InternalError("XXX"); @@ -577,14 +595,14 @@ public class AABBox { * @return a float representing the size of the AABBox */ public final float getSize() { - return VectorUtil.distVec3(low, high); + return low.dist(high); } /** * Get the Center of this AABBox * @return the xyz-coordinates of the center of the AABBox */ - public final float[] getCenter() { + public final Vec3f getCenter() { return center; } @@ -594,24 +612,17 @@ public class AABBox { * high and low is recomputed by scaling its distance to fixed center. * </p> * @param size a constant float value - * @param tmpV3 caller provided temporary 3-component vector * @return this AABBox for chaining * @see #scale2(float, float[]) */ - public final AABBox scale(final float size, final float[] tmpV3) { - tmpV3[0] = high[0] - center[0]; - tmpV3[1] = high[1] - center[1]; - tmpV3[2] = high[2] - center[2]; - - VectorUtil.scaleVec3(tmpV3, tmpV3, size); // in-place scale - VectorUtil.addVec3(high, center, tmpV3); + public final AABBox scale(final float size) { + final Vec3f tmp = new Vec3f(); + tmp.set(high).sub(center).scale(size); + high.set(center).add(tmp); - tmpV3[0] = low[0] - center[0]; - tmpV3[1] = low[1] - center[1]; - tmpV3[2] = low[2] - center[2]; + tmp.set(low).sub(center).scale(size); + low.set(center).add(tmp); - VectorUtil.scaleVec3(tmpV3, tmpV3, size); // in-place scale - VectorUtil.addVec3(low, center, tmpV3); return this; } @@ -621,13 +632,12 @@ public class AABBox { * high and low is scaled and center recomputed. * </p> * @param size a constant float value - * @param tmpV3 caller provided temporary 3-component vector * @return this AABBox for chaining * @see #scale(float, float[]) */ - public final AABBox scale2(final float size, final float[] tmpV3) { - VectorUtil.scaleVec3(high, high, size); // in-place scale - VectorUtil.scaleVec3(low, low, size); // in-place scale + public final AABBox scale2(final float size) { + high.scale(size); + low.scale(size); computeCenter(); return this; } @@ -637,9 +647,9 @@ public class AABBox { * @param t the float[3] translation vector * @return this AABBox for chaining */ - public final AABBox translate(final float[] t) { - VectorUtil.addVec3(low, low, t); // in-place translate - VectorUtil.addVec3(high, high, t); // in-place translate + public final AABBox translate(final Vec3f t) { + low.add(t); + high.add(t); computeCenter(); return this; } @@ -650,46 +660,46 @@ public class AABBox { * @return this AABBox for chaining */ public final AABBox rotate(final Quaternion quat) { - quat.rotateVector(low, 0, low, 0); - quat.rotateVector(high, 0, high, 0); + quat.rotateVector(low, low); + quat.rotateVector(high, high); computeCenter(); return this; } public final float getMinX() { - return low[0]; + return low.x(); } public final float getMinY() { - return low[1]; + return low.y(); } public final float getMinZ() { - return low[2]; + return low.z(); } public final float getMaxX() { - return high[0]; + return high.x(); } public final float getMaxY() { - return high[1]; + return high.y(); } public final float getMaxZ() { - return high[2]; + return high.z(); } public final float getWidth(){ - return high[0] - low[0]; + return high.x() - low.x(); } public final float getHeight() { - return high[1] - low[1]; + return high.y() - low.y(); } public final float getDepth() { - return high[2] - low[2]; + return high.z() - low.z(); } @Override @@ -701,29 +711,65 @@ public class AABBox { return false; } final AABBox other = (AABBox) obj; - return VectorUtil.isVec2Equal(low, 0, other.low, 0, FloatUtil.EPSILON) && - VectorUtil.isVec3Equal(high, 0, other.high, 0, FloatUtil.EPSILON) ; + return low.isEqual(other.low) && high.isEqual(other.high); } @Override public final int hashCode() { throw new InternalError("hashCode not designed"); } + public AABBox transform(final AABBox result, final float[/*16*/] mat4, final int mat4_off, + final float[] vec3Tmp0, final float[] vec3Tmp1) { + result.reset(); + FloatUtil.multMatrixVec3(mat4, mat4_off, low.get(vec3Tmp0), vec3Tmp1); + result.resize(vec3Tmp1); + + FloatUtil.multMatrixVec3(mat4, mat4_off, high.get(vec3Tmp0), vec3Tmp1); + result.resize(vec3Tmp1); + + result.computeCenter(); + return result; + } + + public AABBox transformMv(final AABBox result, final PMVMatrix pmv, + final float[] vec3Tmp0, final float[] vec3Tmp1) { + result.reset(); + pmv.multMvMatVec3f(low.get(vec3Tmp0), vec3Tmp1); + result.resize(vec3Tmp1); + + pmv.multMvMatVec3f(high.get(vec3Tmp0), vec3Tmp1); + result.resize(vec3Tmp1); + + result.computeCenter(); + return result; + } + + public AABBox transform(final AABBox result, final Matrix4f mat, + final Vec3f vec3Tmp) { + result.reset(); + result.resize( mat.mulVec3f(low, vec3Tmp) ); + + result.resize( mat.mulVec3f(high, vec3Tmp) ); + + result.computeCenter(); + return result; + } + /** * Assume this bounding box as being in object space and * compute the window bounding box. * <p> * If <code>useCenterZ</code> is <code>true</code>, - * only 4 {@link FloatUtil#mapObjToWinCoords(float, float, float, float[], int[], int, float[], int, float[], float[]) mapObjToWinCoords} + * only 4 {@link FloatUtil#mapObjToWin(float, float, float, float[], int[], float[], float[], float[]) mapObjToWinCoords} * operations are made on points [1..4] using {@link #getCenter()}'s z-value. - * Otherwise 8 {@link FloatUtil#mapObjToWinCoords(float, float, float, float[], int[], int, float[], int, float[], float[]) mapObjToWinCoords} + * Otherwise 8 {@link FloatUtil#mapObjToWin(float, float, float, float[], int[], float[], float[], float[]) mapObjToWinCoords} * operation on all 8 points are performed. * </p> * <pre> - * [2] ------ [4] + * .z() ------ [4] * | | * | | - * [1] ------ [3] + * .y() ------ [3] * </pre> * @param mat4PMv P x Mv matrix * @param view @@ -736,42 +782,42 @@ public class AABBox { public AABBox mapToWindow(final AABBox result, final float[/*16*/] mat4PMv, final int[] view, final boolean useCenterZ, final float[] vec3Tmp0, final float[] vec4Tmp1, final float[] vec4Tmp2) { { - // System.err.printf("AABBox.mapToWindow.0: view[%d, %d, %d, %d], this %s%n", view[0], view[1], view[2], view[3], toString()); - final float objZ = useCenterZ ? center[2] : getMinZ(); - FloatUtil.mapObjToWinCoords(getMinX(), getMinY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2); - // System.err.printf("AABBox.mapToWindow.p1: %f, %f, %f -> %f, %f, %f%n", getMinX(), getMinY(), objZ, vec3Tmp0[0], vec3Tmp0[1], vec3Tmp0[2]); + // System.err.printf("AABBox.mapToWindow.0: view[%d, %d, %d, %d], this %s%n", view.x(), view.y(), view.z(), view[3], toString()); + final float objZ = useCenterZ ? center.z() : getMinZ(); + FloatUtil.mapObjToWin(getMinX(), getMinY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); + // System.err.printf("AABBox.mapToWindow.p1: %f, %f, %f -> %f, %f, %f%n", getMinX(), getMinY(), objZ, vec3Tmp0.x(), vec3Tmp0.y(), vec3Tmp0.z()); // System.err.println("AABBox.mapToWindow.p1:"); // System.err.println(FloatUtil.matrixToString(null, " mat4PMv", "%10.5f", mat4PMv, 0, 4, 4, false /* rowMajorOrder */)); result.reset(); - result.resize(vec3Tmp0, 0); + result.resize(vec3Tmp0); - FloatUtil.mapObjToWinCoords(getMinX(), getMaxY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2); - // System.err.printf("AABBox.mapToWindow.p2: %f, %f, %f -> %f, %f, %f%n", getMinX(), getMaxY(), objZ, vec3Tmp0[0], vec3Tmp0[1], vec3Tmp0[2]); - result.resize(vec3Tmp0, 0); + FloatUtil.mapObjToWin(getMinX(), getMaxY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); + // System.err.printf("AABBox.mapToWindow.p2: %f, %f, %f -> %f, %f, %f%n", getMinX(), getMaxY(), objZ, vec3Tmp0.x(), vec3Tmp0.y(), vec3Tmp0.z()); + result.resize(vec3Tmp0); - FloatUtil.mapObjToWinCoords(getMaxX(), getMinY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2); - // System.err.printf("AABBox.mapToWindow.p3: %f, %f, %f -> %f, %f, %f%n", getMaxX(), getMinY(), objZ, vec3Tmp0[0], vec3Tmp0[1], vec3Tmp0[2]); - result.resize(vec3Tmp0, 0); + FloatUtil.mapObjToWin(getMaxX(), getMinY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); + // System.err.printf("AABBox.mapToWindow.p3: %f, %f, %f -> %f, %f, %f%n", getMaxX(), getMinY(), objZ, vec3Tmp0.x(), vec3Tmp0.y(), vec3Tmp0.z()); + result.resize(vec3Tmp0); - FloatUtil.mapObjToWinCoords(getMaxX(), getMaxY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2); - // System.err.printf("AABBox.mapToWindow.p4: %f, %f, %f -> %f, %f, %f%n", getMaxX(), getMaxY(), objZ, vec3Tmp0[0], vec3Tmp0[1], vec3Tmp0[2]); - result.resize(vec3Tmp0, 0); + FloatUtil.mapObjToWin(getMaxX(), getMaxY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); + // System.err.printf("AABBox.mapToWindow.p4: %f, %f, %f -> %f, %f, %f%n", getMaxX(), getMaxY(), objZ, vec3Tmp0.x(), vec3Tmp0.y(), vec3Tmp0.z()); + result.resize(vec3Tmp0); } if( !useCenterZ ) { final float objZ = getMaxZ(); - FloatUtil.mapObjToWinCoords(getMinX(), getMinY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2); - result.resize(vec3Tmp0, 0); + FloatUtil.mapObjToWin(getMinX(), getMinY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); + result.resize(vec3Tmp0); - FloatUtil.mapObjToWinCoords(getMinX(), getMaxY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2); - result.resize(vec3Tmp0, 0); + FloatUtil.mapObjToWin(getMinX(), getMaxY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); + result.resize(vec3Tmp0); - FloatUtil.mapObjToWinCoords(getMaxX(), getMinY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2); - result.resize(vec3Tmp0, 0); + FloatUtil.mapObjToWin(getMaxX(), getMinY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); + result.resize(vec3Tmp0); - FloatUtil.mapObjToWinCoords(getMaxX(), getMaxY(), objZ, mat4PMv, view, 0, vec3Tmp0, 0, vec4Tmp1, vec4Tmp2); - result.resize(vec3Tmp0, 0); + FloatUtil.mapObjToWin(getMaxX(), getMaxY(), objZ, mat4PMv, view, vec3Tmp0, vec4Tmp1, vec4Tmp2); + result.resize(vec3Tmp0); } if( DEBUG ) { System.err.printf("AABBox.mapToWindow: view[%d, %d], this %s -> %s%n", view[0], view[1], toString(), result.toString()); @@ -782,7 +828,6 @@ public class AABBox { @Override public final String toString() { return "[ dim "+getWidth()+" x "+getHeight()+" x "+getDepth()+ - ", box "+low[0]+" / "+low[1]+" / "+low[2]+" .. "+high[0]+" / "+high[1]+" / "+high[2]+ - ", ctr "+center[0]+" / "+center[1]+" / "+center[2]+" ]"; + ", box "+low+" .. "+high+", ctr "+center+" ]"; } } diff --git a/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java b/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java index 8b0fa559e..4d098cb72 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java +++ b/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java @@ -1,5 +1,5 @@ /** - * Copyright 2010 JogAmp Community. All rights reserved. + * Copyright 2010-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -29,9 +29,11 @@ package com.jogamp.opengl.math.geom; import jogamp.common.os.PlatformPropsImpl; -import com.jogamp.common.os.Platform; import com.jogamp.opengl.math.FloatUtil; import com.jogamp.opengl.math.FovHVHalves; +import com.jogamp.opengl.math.Matrix4f; +import com.jogamp.opengl.math.Vec3f; +import com.jogamp.opengl.math.geom.Frustum.FovDesc; /** * Providing frustum {@link #getPlanes() planes} derived by different inputs @@ -103,6 +105,7 @@ public class Frustum { this.zNear = zNear; this.zFar = zFar; } + @Override public final String toString() { return "FrustumFovDesc["+fovhv.toStringInDegrees()+", Z["+zNear+" - "+zFar+"]]"; } @@ -134,7 +137,7 @@ public class Frustum { */ public static class Plane { /** Normal of the plane */ - public final float[] n = new float[3]; + public final Vec3f n = new Vec3f(); /** Distance to origin */ public float d; @@ -155,17 +158,22 @@ public class Frustum { * </p> **/ public final float distanceTo(final float x, final float y, final float z) { - return n[0] * x + n[1] * y + n[2] * z + d; + return n.x() * x + n.y() * y + n.z() * z + d; } /** Return distance of plane to given point, see {@link #distanceTo(float, float, float)}. */ public final float distanceTo(final float[] p) { - return n[0] * p[0] + n[1] * p[1] + n[2] * p[2] + d; + return n.x() * p[0] + n.y() * p[1] + n.z() * p[2] + d; + } + + /** Return distance of plane to given point, see {@link #distanceTo(float, float, float)}. */ + public final float distanceTo(final Vec3f p) { + return n.x() * p.x() + n.y() * p.y() + n.z() * p.z() + d; } @Override public String toString() { - return "Plane[ [ " + n[0] + ", " + n[1] + ", " + n[2] + " ], " + d + "]"; + return "Plane[ [ " + n + " ], " + d + "]"; } } @@ -221,9 +229,9 @@ public class Frustum { * Operation Details: * <ul> * <li>The given {@link FovDesc} will be transformed - * into the given float[16] as a perspective matrix (column major order) first, - * see {@link FloatUtil#makePerspective(float[], int, boolean, FovHVHalves, float, float)}.</li> - * <li>Then the float[16] perspective matrix is used to {@link #updateByPMV(float[], int)} this instance.</li> + * into the given perspective matrix (column major order) first, + * see {@link Matrix4f#setToPerspective(FovHVHalves, float, float)}.</li> + * <li>Then the perspective matrix is used to {@link Matrix4f#updateFrustumPlanes(Frustum)} this instance.</li> * </ul> * </p> * <p> @@ -232,17 +240,15 @@ public class Frustum { * </p> * * @param m 4x4 matrix in column-major order (also result) - * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix - * @param initM if true, given matrix will be initialized w/ identity matrix, - * otherwise only the frustum fields are set. * @param fovDesc {@link Frustum} {@link FovDesc} * @return given matrix for chaining - * @see FloatUtil#makePerspective(float[], int, boolean, FovHVHalves, float, float) + * @see Matrix4f#setToPerspective(FovHVHalves, float, float) + * @see Matrix4f#updateFrustumPlanes(Frustum) + * @see Matrix4f#getFrustum(Frustum, FovDesc) */ - public float[] updateByFovDesc(final float[] m, final int m_offset, final boolean initM, - final FovDesc fovDesc) { - FloatUtil.makePerspective(m, m_offset, initM, fovDesc.fovhv, fovDesc.zNear, fovDesc.zFar); - updateByPMV(m, 0); + public Matrix4f updateByFovDesc(final Matrix4f m, final FovDesc fovDesc) { + m.setToPerspective(fovDesc.fovhv, fovDesc.zNear, fovDesc.zFar); + m.updateFrustumPlanes(this); return m; } @@ -259,10 +265,10 @@ public class Frustum { // Left: a = m30 + m00, b = m31 + m01, c = m32 + m02, d = m33 + m03 - [0..3] column-major { final Plane p = planes[LEFT]; - final float[] p_n = p.n; - p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 0 + 0 * 4 ]; - p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 0 + 1 * 4 ]; - p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 0 + 2 * 4 ]; + final Vec3f p_n = p.n; + p_n.set( pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 0 + 0 * 4 ], + pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 0 + 1 * 4 ], + pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 0 + 2 * 4 ] ); p.d = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 0 + 3 * 4 ]; } @@ -270,10 +276,10 @@ public class Frustum { // Right: a = m30 - m00, b = m31 - m01, c = m32 - m02, d = m33 - m03 - [0..3] column-major { final Plane p = planes[RIGHT]; - final float[] p_n = p.n; - p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 0 + 0 * 4 ]; - p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 0 + 1 * 4 ]; - p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 0 + 2 * 4 ]; + final Vec3f p_n = p.n; + p_n.set( pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 0 + 0 * 4 ], + pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 0 + 1 * 4 ], + pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 0 + 2 * 4 ] ); p.d = pmv[ pmv_off + 3 + 3 * 4 ] - pmv[ pmv_off + 0 + 3 * 4 ]; } @@ -281,10 +287,10 @@ public class Frustum { // Bottom: a = m30 + m10, b = m31 + m11, c = m32 + m12, d = m33 + m13 - [0..3] column-major { final Plane p = planes[BOTTOM]; - final float[] p_n = p.n; - p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 1 + 0 * 4 ]; - p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 1 + 1 * 4 ]; - p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 1 + 2 * 4 ]; + final Vec3f p_n = p.n; + p_n.set( pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 1 + 0 * 4 ], + pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 1 + 1 * 4 ], + pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 1 + 2 * 4 ] ); p.d = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 1 + 3 * 4 ]; } @@ -292,10 +298,10 @@ public class Frustum { // Top: a = m30 - m10, b = m31 - m11, c = m32 - m12, d = m33 - m13 - [0..3] column-major { final Plane p = planes[TOP]; - final float[] p_n = p.n; - p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 1 + 0 * 4 ]; - p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 1 + 1 * 4 ]; - p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 1 + 2 * 4 ]; + final Vec3f p_n = p.n; + p_n.set( pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 1 + 0 * 4 ], + pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 1 + 1 * 4 ], + pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 1 + 2 * 4 ] ); p.d = pmv[ pmv_off + 3 + 3 * 4 ] - pmv[ pmv_off + 1 + 3 * 4 ]; } @@ -303,10 +309,10 @@ public class Frustum { // Near: a = m30 + m20, b = m31 + m21, c = m32 + m22, d = m33 + m23 - [0..3] column-major { final Plane p = planes[NEAR]; - final float[] p_n = p.n; - p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 2 + 0 * 4 ]; - p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 2 + 1 * 4 ]; - p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 2 + 2 * 4 ]; + final Vec3f p_n = p.n; + p_n.set( pmv[ pmv_off + 3 + 0 * 4 ] + pmv[ pmv_off + 2 + 0 * 4 ], + pmv[ pmv_off + 3 + 1 * 4 ] + pmv[ pmv_off + 2 + 1 * 4 ], + pmv[ pmv_off + 3 + 2 * 4 ] + pmv[ pmv_off + 2 + 2 * 4 ] ); p.d = pmv[ pmv_off + 3 + 3 * 4 ] + pmv[ pmv_off + 2 + 3 * 4 ]; } @@ -314,38 +320,35 @@ public class Frustum { // Far: a = m30 - m20, b = m31 - m21, c = m32 + m22, d = m33 + m23 - [0..3] column-major { final Plane p = planes[FAR]; - final float[] p_n = p.n; - p_n[0] = pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 2 + 0 * 4 ]; - p_n[1] = pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 2 + 1 * 4 ]; - p_n[2] = pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 2 + 2 * 4 ]; + final Vec3f p_n = p.n; + p_n.set( pmv[ pmv_off + 3 + 0 * 4 ] - pmv[ pmv_off + 2 + 0 * 4 ], + pmv[ pmv_off + 3 + 1 * 4 ] - pmv[ pmv_off + 2 + 1 * 4 ], + pmv[ pmv_off + 3 + 2 * 4 ] - pmv[ pmv_off + 2 + 2 * 4 ] ); p.d = pmv[ pmv_off + 3 + 3 * 4 ] - pmv[ pmv_off + 2 + 3 * 4 ]; } // Normalize all planes for (int i = 0; i < 6; ++i) { final Plane p = planes[i]; - final float[] p_n = p.n; - final double invl = Math.sqrt(p_n[0] * p_n[0] + p_n[1] * p_n[1] + p_n[2] * p_n[2]); - - p_n[0] /= invl; - p_n[1] /= invl; - p_n[2] /= invl; - p.d /= invl; + final Vec3f p_n = p.n; + final float invLen = 1f / p_n.length(); + p_n.scale(invLen); + p.d *= invLen; } } private static final boolean isOutsideImpl(final Plane p, final AABBox box) { - final float[] low = box.getLow(); - final float[] high = box.getHigh(); - - if ( p.distanceTo(low[0], low[1], low[2]) > 0.0f || - p.distanceTo(high[0], low[1], low[2]) > 0.0f || - p.distanceTo(low[0], high[1], low[2]) > 0.0f || - p.distanceTo(high[0], high[1], low[2]) > 0.0f || - p.distanceTo(low[0], low[1], high[2]) > 0.0f || - p.distanceTo(high[0], low[1], high[2]) > 0.0f || - p.distanceTo(low[0], high[1], high[2]) > 0.0f || - p.distanceTo(high[0], high[1], high[2]) > 0.0f ) { + final Vec3f lo = box.getLow(); + final Vec3f hi = box.getHigh(); + + if ( p.distanceTo(lo.x(), lo.y(), lo.z()) > 0.0f || + p.distanceTo(hi.x(), lo.y(), lo.z()) > 0.0f || + p.distanceTo(lo.x(), hi.y(), lo.z()) > 0.0f || + p.distanceTo(hi.x(), hi.y(), lo.z()) > 0.0f || + p.distanceTo(lo.x(), lo.y(), hi.z()) > 0.0f || + p.distanceTo(hi.x(), lo.y(), hi.z()) > 0.0f || + p.distanceTo(lo.x(), hi.y(), hi.z()) > 0.0f || + p.distanceTo(hi.x(), hi.y(), hi.z()) > 0.0f ) { return false; } return true; |