From 5d6e8a367c03644740187e500c6de5d3ac039d5e Mon Sep 17 00:00:00 2001
From: Sven Gothel
- * Functions to convert values to/from the
- * Convert a double precision floating point value to a packed
- *
- * For the following specific cases, the function returns:
- *
- * Otherwise, the
- * Convert a single precision floating point value to a packed
- *
- * For the following specific cases, the function returns:
- *
- * Otherwise, the
- * Encode the unbiased exponent
- * Encode the significand
- * Encode the sign bit
- * Convert a packed
- * The function returns:
- *
- * Convert a packed
- * The function returns:
- *
- * Extract and unbias the exponent of the given packed
- * The exponent is encoded biased as a number in the range
- *
- * This function will therefore return:
- *
- * Return the significand of the given packed
- * Extract and unbias the exponent of the given packed
- * The exponent is encoded biased as a number in the range
- *
- * This function will therefore return:
- *
- * Return the sign of the given float value.
- *
- * Return the significand of the given float value.
- *
- * Extract and unbias the exponent of the given packed
- * The exponent is encoded biased as a number in the range
- *
- * This function will therefore return:
- *
- * Return the significand of the given double value.
- *
- * Return the sign of the given double value.
- *
- * Implementation assumes linear matrix layout in column-major order
- * matching OpenGL's implementation, illustration:
- * binary16
format
- * specified in IEEE 754 2008
.
- * -∞
.
- */
-
- public static final char NEGATIVE_INFINITY;
-
- /**
- * The encoded form of positive infinity ∞
.
- */
-
- public static final char POSITIVE_INFINITY;
-
- /**
- * The encoded form of positive zero 0
.
- */
-
- public static final char POSITIVE_ZERO;
-
- /**
- * The encoded form of negative zero -0
.
- */
-
- public static final char NEGATIVE_ZERO;
-
- /**
- * The bias value used to offset the encoded exponent. A given
- * exponent e
is encoded as {@link #BIAS} + e
.
- */
-
- public static final int BIAS;
-
- static {
- NEGATIVE_INFINITY = 0xFC00;
- POSITIVE_INFINITY = 0x7C00;
- POSITIVE_ZERO = 0x0000;
- NEGATIVE_ZERO = 0x8000;
- BIAS = 15;
- }
-
- private static final int MASK_SIGN;
- private static final int MASK_EXPONENT;
- private static final int MASK_SIGNIFICAND;
-
- static {
- MASK_SIGN = 0x8000;
- MASK_EXPONENT = 0x7C00;
- MASK_SIGNIFICAND = 0x03FF;
- }
-
- /**
- * One possible not-a-number value.
- */
-
- public static char exampleNaN()
- {
- final int n =
- Binary16.packSetExponentUnbiasedUnchecked(16)
- | Binary16.packSetSignificandUnchecked(1);
- final char c = (char) n;
- return c;
- }
-
- /**
- * Return true
if the given packed binary16
value
- * is infinite.
- */
-
- public static boolean isInfinite(
- final char k)
- {
- if (Binary16.unpackGetExponentUnbiased(k) == 16) {
- if (Binary16.unpackGetSignificand(k) == 0) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Return true
if the given packed binary16
value
- * is not a number (NaN
).
- */
-
- public static boolean isNaN(
- final char k)
- {
- final int e = Binary16.unpackGetExponentUnbiased(k);
- final int s = Binary16.unpackGetSignificand(k);
- return (e == 16) && (s > 0);
- }
-
- /**
- * binary16
value.
- *
- *
- * NaN
iff isNaN(k)
k == {@link Double#POSITIVE_INFINITY}
k == {@link Double#NEGATIVE_INFINITY}
k == -0.0
k == 0.0
binary16
value that most closely represents
- * k
is returned. This may obviously be an infinite value as
- * the interval of double precision values is far larger than that of the
- * binary16
type.
- * binary16
value.
- *
- *
- * NaN
iff isNaN(k)
k == {@link Float#POSITIVE_INFINITY}
k == {@link Float#NEGATIVE_INFINITY}
k == -0.0
k == 0.0
binary16
value that most closely represents
- * k
is returned. This may obviously be an infinite value as
- * the interval of single precision values is far larger than that of the
- * binary16
type.
- * e
. Values should be in the
- * range [-15, 16]
- values outside of this range will be
- * truncated.
- * s
. Values should be in the range
- * [0, 1023]
. Values outside of this range will be truncated.
- * s
. Values should be in the range
- * [0, 1]
, with 0
ironically denoting a positive
- * value. Values outside of this range will be truncated.
- * binary16
value as a string of
- * binary digits.
- */
-
- public static String toRawBinaryString(
- final char k)
- {
- final StringBuilder b = new StringBuilder();
- int z = k;
- for (int i = 0; i < 16; ++i) {
- if ((z & 1) == 1) {
- b.insert(0, "1");
- } else {
- b.insert(0, "0");
- }
- z >>= 1;
- }
- return b.toString();
- }
-
- /**
- * binary16
value k
to a
- * double-precision floating point value.
- *
- *
- *
- * @see #packDouble(double)
- */
-
- public static double unpackDouble(
- final char k)
- {
- if (Binary16.isNaN(k)) {
- return Double.NaN;
- }
- if (k == Binary16.POSITIVE_INFINITY) {
- return Double.POSITIVE_INFINITY;
- }
- if (k == Binary16.NEGATIVE_INFINITY) {
- return Double.NEGATIVE_INFINITY;
- }
- if (k == Binary16.NEGATIVE_ZERO) {
- return -0.0;
- }
- if (k == Binary16.POSITIVE_ZERO) {
- return 0.0;
- }
-
- final long e = Binary16.unpackGetExponentUnbiased(k);
- final long s = Binary16.unpackGetSign(k);
- final long n = Binary16.unpackGetSignificand(k);
-
- /**
- * Shift the sign bit to the position at which it will appear in the
- * resulting value.
- */
-
- final long rsr = s << 63;
-
- /**
- * 1. Bias the exponent.
- *
- * 2. Shift the result left to the position at which it will appear in the
- * resulting value.
- */
-
- final long reb = (e + Binary64.BIAS);
- final long rer = reb << 52;
-
- /**
- * Shift the significand left to the position at which it will appear in
- * the resulting value.
- */
-
- final long rnr = n << 42;
- return Double.longBitsToDouble(rsr | rer | rnr);
- }
-
- /**
- * NaN
iff isNaN(k)
k == {@link #POSITIVE_INFINITY}
k == {@link #NEGATIVE_INFINITY}
-0.0
iff k == {@link #NEGATIVE_ZERO}
0.0
iff k == {@link #POSITIVE_ZERO}
(-1.0 * n) * (2 ^ e) * 1.s
, for the decoded sign
- * n
of k
, the decoded exponent e
of
- * k
, and the decoded significand s
of
- * k
.binary16
value k
to a
- * single-precision floating point value.
- *
- *
- *
- * @see #packFloat(float)
- */
-
- public static float unpackFloat(
- final char k)
- {
- if (Binary16.isNaN(k)) {
- return Float.NaN;
- }
- if (k == Binary16.POSITIVE_INFINITY) {
- return Float.POSITIVE_INFINITY;
- }
- if (k == Binary16.NEGATIVE_INFINITY) {
- return Float.NEGATIVE_INFINITY;
- }
- if (k == Binary16.NEGATIVE_ZERO) {
- return -0.0f;
- }
- if (k == Binary16.POSITIVE_ZERO) {
- return 0.0f;
- }
-
- final int e = Binary16.unpackGetExponentUnbiased(k);
- final int s = Binary16.unpackGetSign(k);
- final int n = Binary16.unpackGetSignificand(k);
-
- /**
- * Shift the sign bit to the position at which it will appear in the
- * resulting value.
- */
-
- final int rsr = s << 31;
-
- /**
- * 1. Bias the exponent.
- *
- * 2. Shift the result left to the position at which it will appear in the
- * resulting value.
- */
-
- final int reb = (e + Binary32.BIAS);
- final int rer = reb << 23;
-
- /**
- * Shift the significand left to the position at which it will appear in
- * the resulting value.
- */
-
- final int rnr = n << 13;
- return Float.intBitsToFloat(rsr | rer | rnr);
- }
-
- /**
- * NaN
iff isNaN(k)
k == {@link #POSITIVE_INFINITY}
k == {@link #NEGATIVE_INFINITY}
-0.0
iff k == {@link #NEGATIVE_ZERO}
0.0
iff k == {@link #POSITIVE_ZERO}
(-1.0 * n) * (2 ^ e) * 1.s
, for the decoded sign
- * n
of k
, the decoded exponent e
of
- * k
, and the decoded significand s
of
- * k
.binary16
- * value.
- * [0, 31]
, with 0
indicating that the number is
- * subnormal and [1, 30]
denoting the actual exponent
- * plus {@link #BIAS}. Infinite and NaN
values always have an
- * exponent of 31
.
- *
- *
- *
- * @see #packSetExponentUnbiasedUnchecked(int)
- */
-
- public static int unpackGetExponentUnbiased(
- final char k)
- {
- final int em = k & Binary16.MASK_EXPONENT;
- final int es = em >> 10;
- return es - Binary16.BIAS;
- }
-
- /**
- * Retrieve the sign bit of the given packed 0 - {@link #BIAS} = -15
iff the input is a subnormal
- * number.[1 - {@link #BIAS}, 30 - {@link #BIAS}] = [-14, 15]
iff the
- * input is a normal number.16
iff the input is {@link #POSITIVE_INFINITY},
- * {@link #NEGATIVE_INFINITY}, or NaN
.binary16
value, as
- * an integer in the range [0, 1]
.
- *
- * @see Binary16#packSetSignUnchecked(int)
- */
-
- public static int unpackGetSign(
- final char k)
- {
- return (k & Binary16.MASK_SIGN) >> 15;
- }
-
- /**
- * binary16
value as
- * an integer in the range [0, 1023]
.
- * binary32
(float) values.
- */
-
-public final class Binary32
-{
- static final int NEGATIVE_ZERO_BITS;
- static final int MASK_SIGN;
- static final int MASK_EXPONENT;
- static final int MASK_SIGNIFICAND;
- static final int BIAS;
-
- static {
- NEGATIVE_ZERO_BITS = 0x80000000;
- MASK_SIGN = 0x80000000;
- MASK_EXPONENT = 0x7ff00000;
- MASK_SIGNIFICAND = 0x7fffff;
- BIAS = 127;
- }
-
- /**
- * float
- * value.
- * [0, 255]
, with 0
indicating that the number is
- * subnormal and [1, 254]
denoting the actual exponent
- * plus {@link #BIAS}. Infinite and NaN
values always have a
- * biased exponent of 255
.
- *
- *
- *
- * @see #packSetExponentUnbiasedUnchecked(int)
- */
-
- public static int unpackGetExponentUnbiased(
- final float d)
- {
- final int b = Float.floatToRawIntBits(d);
- final int em = b & Binary32.MASK_EXPONENT;
- final int es = em >> 23;
- return es - Binary32.BIAS;
- }
-
- /**
- * 0 - {@link #BIAS} = -127
iff the input is a subnormal
- * number.[1 - {@link #BIAS}, 254 - {@link #BIAS}] = [-126, 127]
iff
- * the input is a normal number.255 - {@link #BIAS} = 128
iff the input is
- * {@link #POSITIVE_INFINITY}, {@link #NEGATIVE_INFINITY}, or
- * NaN
.binary64
(double) values.
- */
-
-public final class Binary64
-{
- static final long NEGATIVE_ZERO_BITS;
- static final long MASK_SIGN;
- static final long MASK_EXPONENT;
- static final long MASK_SIGNIFICAND;
- static final long BIAS;
-
- static {
- NEGATIVE_ZERO_BITS = 0x8000000000000000L;
- MASK_SIGN = 0x8000000000000000L;
- MASK_EXPONENT = 0x7ff0000000000000L;
- MASK_SIGNIFICAND = 0x000fffffffffffffL;
- BIAS = 1023;
- }
-
- /**
- * double
- * value.
- * [0, 2047]
, with 0
indicating that the number is
- * subnormal and [1, 2046]
denoting the actual exponent
- * plus {@link #BIAS}. Infinite and NaN
values always have a
- * biased exponent of 2047
.
- *
- *
- *
- * @see #packSetExponentUnbiasedUnchecked(int)
- */
-
- public static long unpackGetExponentUnbiased(
- final double d)
- {
- final long b = Double.doubleToRawLongBits(d);
- final long em = b & Binary64.MASK_EXPONENT;
- final long es = em >> 52;
- return es - Binary64.BIAS;
- }
-
- /**
- * 0 - {@link #BIAS} = -1023
iff the input is a
- * subnormal number.[1 - {@link #BIAS}, 2046 - {@link #BIAS}] = [-1022, 1023]
- * iff the input is a normal number.2047 - {@link #BIAS} = 1024
iff the input is
- * {@link #POSITIVE_INFINITY}, {@link #NEGATIVE_INFINITY}, or
- * NaN
.
- Row-Major Column-Major (OpenGL):
-
- | 0 1 2 tx |
- | |
- | 4 5 6 ty |
- M = | |
- | 8 9 10 tz |
- | |
- | 12 13 14 15 |
-
- R C R C
- m[0*4+3] = tx; m[0+4*3] = tx;
- m[1*4+3] = ty; m[1+4*3] = ty;
- m[2*4+3] = tz; m[2+4*3] = tz;
-
- RC (std subscript order) RC (std subscript order)
- m03 = tx; m03 = tx;
- m13 = ty; m13 = ty;
- m23 = tz; m23 = tz;
-
- *
- *
- *
- * Implementation utilizes unrolling of small vertices and matrices wherever possible - * while trying to access memory in a linear fashion for performance reasons, see: - *
- * - */ -public final class FloatUtil { - public static final boolean DEBUG = Debug.debugExplicit("Math"); - - // - // Matrix Ops - // Only a subset will remain here, try using Matrix4f and perhaps PMVMatrix, SyncMatrix4f16 or SyncMatrices4f16 - // - - /** - * Make matrix an identity matrix - * @param m 4x4 matrix in column-major order (also result) - * @return given matrix for chaining - */ - public static float[] makeIdentity(final float[] m) { - m[0+4*0] = 1f; - m[1+4*0] = 0f; - m[2+4*0] = 0f; - m[3+4*0] = 0f; - - m[0+4*1] = 0f; - m[1+4*1] = 1f; - m[2+4*1] = 0f; - m[3+4*1] = 0f; - - m[0+4*2] = 0f; - m[1+4*2] = 0f; - m[2+4*2] = 1f; - m[3+4*2] = 0f; - - m[0+4*3] = 0f; - m[1+4*3] = 0f; - m[2+4*3] = 0f; - m[3+4*3] = 1f; - return m; - } - - /** - * Make a translation matrix in column-major order from the given axis deltas - *- Translation matrix (Column Order): - 1 0 0 0 - 0 1 0 0 - 0 0 1 0 - x y z 1 - *- *
- * All matrix fields are only set if initM
is true
.
- *
- Scale matrix (Any Order): - x 0 0 0 - 0 y 0 0 - 0 0 z 0 - 0 0 0 1 - *- *
- * All matrix fields are only set if initM
is true
.
- *
- Frustum matrix (Column Order): - 2*zNear/dx 0 0 0 - 0 2*zNear/dy 0 0 - A B C -1 - 0 0 D 0 - *- *
- * All matrix fields are only set if initM
is true
.
- *
- * All matrix fields are only set if initM
is true
.
- *
- * Consist out of two matrix multiplications: - *
- * R = L x T, - * with L for look-at matrix and - * T for eye translation. - * - * Result R can be utilized for modelview multiplication, i.e. - * M = M x R, - * with M being the modelview matrix. - *- * - *
- * All matrix fields are set. - *
- * @param m 4x4 matrix in column-major order, result only - * @param m_offset offset in given array m, i.e. start of the 4x4 matrix - * @param eye 3 component eye vector - * @param eye_offset - * @param center 3 component center vector - * @param center_offset - * @param up 3 component up vector - * @param up_offset - * @param mat4Tmp temp float[16] storage - * @return given matrixm
for chaining
- */
- public static float[] makeLookAt(final float[] m, final int m_offset,
- final float[] eye, final int eye_offset,
- final float[] center, final int center_offset,
- final float[] up, final int up_offset,
- final float[] mat4Tmp) {
- final int forward_off = 0;
- final int side_off = 3;
- final int up2_off = 6;
-
- // forward!
- mat4Tmp[0] = center[0+center_offset] - eye[0+eye_offset];
- mat4Tmp[1] = center[1+center_offset] - eye[1+eye_offset];
- mat4Tmp[2] = center[2+center_offset] - eye[2+eye_offset];
-
- VectorUtil.normalizeVec3(mat4Tmp); // normalize forward
-
- /* Side = forward x up */
- VectorUtil.crossVec3(mat4Tmp, side_off, mat4Tmp, forward_off, up, up_offset);
- VectorUtil.normalizeVec3(mat4Tmp, side_off); // normalize side
-
- /* Recompute up as: up = side x forward */
- VectorUtil.crossVec3(mat4Tmp, up2_off, mat4Tmp, side_off, mat4Tmp, forward_off);
-
- m[m_offset + 0 * 4 + 0] = mat4Tmp[0+side_off]; // side
- m[m_offset + 0 * 4 + 1] = mat4Tmp[0+up2_off]; // up2
- m[m_offset + 0 * 4 + 2] = -mat4Tmp[0]; // forward
- m[m_offset + 0 * 4 + 3] = 0;
-
- m[m_offset + 1 * 4 + 0] = mat4Tmp[1+side_off]; // side
- m[m_offset + 1 * 4 + 1] = mat4Tmp[1+up2_off]; // up2
- m[m_offset + 1 * 4 + 2] = -mat4Tmp[1]; // forward
- m[m_offset + 1 * 4 + 3] = 0;
-
- m[m_offset + 2 * 4 + 0] = mat4Tmp[2+side_off]; // side
- m[m_offset + 2 * 4 + 1] = mat4Tmp[2+up2_off]; // up2
- m[m_offset + 2 * 4 + 2] = -mat4Tmp[2]; // forward
- m[m_offset + 2 * 4 + 3] = 0;
-
- m[m_offset + 3 * 4 + 0] = 0;
- m[m_offset + 3 * 4 + 1] = 0;
- m[m_offset + 3 * 4 + 2] = 0;
- m[m_offset + 3 * 4 + 3] = 1;
-
- makeTranslation(mat4Tmp, true, -eye[0+eye_offset], -eye[1+eye_offset], -eye[2+eye_offset]);
- multMatrix(m, m_offset, mat4Tmp, 0);
-
- return m;
- }
-
- /**
- * Make given matrix the pick matrix based on given parameters.
- *
- * Traditional gluPickMatrix
implementation.
- *
- * Consist out of two matrix multiplications: - *
- * R = T x S, - * with T for viewport translation matrix and - * S for viewport scale matrix. - * - * Result R can be utilized for projection multiplication, i.e. - * P = P x R, - * with P being the projection matrix. - *- * - *
- * To effectively use the generated pick matrix for picking, - * call {@link #makePick(float[], int, float, float, float, float, int[], int, float[]) makePick} - * and multiply a {@link #makePerspective(float[], int, boolean, float, float, float, float) custom perspective matrix} - * by this pick matrix. Then you may load the result onto the perspective matrix stack. - *
- *- * All matrix fields are set. - *
- * @param m 4x4 matrix in column-major order, result only - * @param m_offset offset in given array m, i.e. start of the 4x4 matrix - * @param x the center x-component of a picking region in window coordinates - * @param y the center y-component of a picking region in window coordinates - * @param deltaX the width of the picking region in window coordinates. - * @param deltaY the height of the picking region in window coordinates. - * @param viewport 4 component viewport vector - * @param viewport_offset - * @param mat4Tmp temp float[16] storage - * @return given matrixm
for chaining or null
if either delta value is <= zero.
- */
- public static float[] makePick(final float[] m,
- final float x, final float y,
- final float deltaX, final float deltaY,
- final int[] viewport, final int viewport_offset,
- final float[] mat4Tmp) {
- if (deltaX <= 0 || deltaY <= 0) {
- return null;
- }
-
- /* Translate and scale the picked region to the entire window */
- makeTranslation(m, true,
- (viewport[2+viewport_offset] - 2 * (x - viewport[0+viewport_offset])) / deltaX,
- (viewport[3+viewport_offset] - 2 * (y - viewport[1+viewport_offset])) / deltaY,
- 0);
- makeScale(mat4Tmp, true,
- viewport[2+viewport_offset] / deltaX, viewport[3+viewport_offset] / deltaY, 1.0f);
- multMatrix(m, mat4Tmp);
- return m;
- }
-
- /**
- * Transpose the given matrix.
- *
- * @param msrc 4x4 matrix in column-major order, the source
- * @param mres 4x4 matrix in column-major order, the result
- * @return given result matrix mres for chaining
- */
- public static float[] transposeMatrix(final float[] msrc, final float[] mres) {
- mres[0] = msrc[0*4];
- mres[1] = msrc[1*4];
- mres[2] = msrc[2*4];
- mres[3] = msrc[3*4];
-
- final int i4_1 = 1*4;
- mres[0+i4_1] = msrc[1+0*4];
- mres[1+i4_1] = msrc[1+1*4];
- mres[2+i4_1] = msrc[1+2*4];
- mres[3+i4_1] = msrc[1+3*4];
-
- final int i4_2 = 2*4;
- mres[0+i4_2] = msrc[2+0*4];
- mres[1+i4_2] = msrc[2+1*4];
- mres[2+i4_2] = msrc[2+2*4];
- mres[3+i4_2] = msrc[2+3*4];
-
- final int i4_3 = 3*4;
- mres[0+i4_3] = msrc[3+0*4];
- mres[1+i4_3] = msrc[3+1*4];
- mres[2+i4_3] = msrc[3+2*4];
- mres[3+i4_3] = msrc[3+3*4];
-
- return mres;
- }
-
- /**
- * Returns the determinant of the given matrix
- * @param m 4x4 matrix in column-major order, the source
- * @return the matrix determinant
- */
- public static float matrixDeterminant(final float[] m) {
- float a11 = m[ 1+4*1 ];
- float a21 = m[ 2+4*1 ];
- float a31 = m[ 3+4*1 ];
- float a12 = m[ 1+4*2 ];
- float a22 = m[ 2+4*2 ];
- float a32 = m[ 3+4*2 ];
- float a13 = m[ 1+4*3 ];
- float a23 = m[ 2+4*3 ];
- float a33 = m[ 3+4*3 ];
-
- float ret = 0;
- ret += m[ 0 ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31));
- a11 = m[ 1+4*0 ];
- a21 = m[ 2+4*0 ];
- a31 = m[ 3+4*0 ];
- ret -= m[ 0+4*1 ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31));
- a12 = m[ 1+4*1 ];
- a22 = m[ 2+4*1 ];
- a32 = m[ 3+4*1 ];
- ret += m[ 0+4*2 ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31));
- a13 = m[ 1+4*2 ];
- a23 = m[ 2+4*2 ];
- a33 = m[ 3+4*2 ];
- ret -= m[ 0+4*3 ] * ( + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31));
- return ret;
- }
- /**
- * Invert the given matrix.
- *
- * Returns null
if inversion is not possible,
- * e.g. matrix is singular due to a bad matrix.
- *
msrc
(in-place)
- * @return given result matrix mres for chaining if successful, otherwise null
. See above.
- */
- public static float[] invertMatrix(final float[] msrc, final float[] mres) {
- final float scale;
- {
- float max = Math.abs(msrc[0]);
-
- for( int i = 1; i < 16; i++ ) {
- final float a = Math.abs(msrc[i]);
- if( a > max ) max = a;
- }
- if( 0 == max ) {
- return null;
- }
- scale = 1.0f/max;
- }
-
- final float a11 = msrc[0+4*0]*scale;
- final float a21 = msrc[1+4*0]*scale;
- final float a31 = msrc[2+4*0]*scale;
- final float a41 = msrc[3+4*0]*scale;
- final float a12 = msrc[0+4*1]*scale;
- final float a22 = msrc[1+4*1]*scale;
- final float a32 = msrc[2+4*1]*scale;
- final float a42 = msrc[3+4*1]*scale;
- final float a13 = msrc[0+4*2]*scale;
- final float a23 = msrc[1+4*2]*scale;
- final float a33 = msrc[2+4*2]*scale;
- final float a43 = msrc[3+4*2]*scale;
- final float a14 = msrc[0+4*3]*scale;
- final float a24 = msrc[1+4*3]*scale;
- final float a34 = msrc[2+4*3]*scale;
- final float a44 = msrc[3+4*3]*scale;
-
- final float m11 = + a22*(a33*a44 - a34*a43) - a23*(a32*a44 - a34*a42) + a24*(a32*a43 - a33*a42);
- final float m12 = -( + a21*(a33*a44 - a34*a43) - a23*(a31*a44 - a34*a41) + a24*(a31*a43 - a33*a41));
- final float m13 = + a21*(a32*a44 - a34*a42) - a22*(a31*a44 - a34*a41) + a24*(a31*a42 - a32*a41);
- final float m14 = -( + a21*(a32*a43 - a33*a42) - a22*(a31*a43 - a33*a41) + a23*(a31*a42 - a32*a41));
- final float m21 = -( + a12*(a33*a44 - a34*a43) - a13*(a32*a44 - a34*a42) + a14*(a32*a43 - a33*a42));
- final float m22 = + a11*(a33*a44 - a34*a43) - a13*(a31*a44 - a34*a41) + a14*(a31*a43 - a33*a41);
- final float m23 = -( + a11*(a32*a44 - a34*a42) - a12*(a31*a44 - a34*a41) + a14*(a31*a42 - a32*a41));
- final float m24 = + a11*(a32*a43 - a33*a42) - a12*(a31*a43 - a33*a41) + a13*(a31*a42 - a32*a41);
- final float m31 = + a12*(a23*a44 - a24*a43) - a13*(a22*a44 - a24*a42) + a14*(a22*a43 - a23*a42);
- final float m32 = -( + a11*(a23*a44 - a24*a43) - a13*(a21*a44 - a24*a41) + a14*(a21*a43 - a23*a41));
- final float m33 = + a11*(a22*a44 - a24*a42) - a12*(a21*a44 - a24*a41) + a14*(a21*a42 - a22*a41);
- final float m34 = -( + a11*(a22*a43 - a23*a42) - a12*(a21*a43 - a23*a41) + a13*(a21*a42 - a22*a41));
- final float m41 = -( + a12*(a23*a34 - a24*a33) - a13*(a22*a34 - a24*a32) + a14*(a22*a33 - a23*a32));
- final float m42 = + a11*(a23*a34 - a24*a33) - a13*(a21*a34 - a24*a31) + a14*(a21*a33 - a23*a31);
- final float m43 = -( + a11*(a22*a34 - a24*a32) - a12*(a21*a34 - a24*a31) + a14*(a21*a32 - a22*a31));
- final float m44 = + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31);
-
- final float det = (a11*m11 + a12*m12 + a13*m13 + a14*m14)/scale;
- if( 0 == det ) {
- return null;
- }
- final float invdet = 1.0f / det;
-
- mres[0+4*0] = m11 * invdet;
- mres[1+4*0] = m12 * invdet;
- mres[2+4*0] = m13 * invdet;
- mres[3+4*0] = m14 * invdet;
- mres[0+4*1] = m21 * invdet;
- mres[1+4*1] = m22 * invdet;
- mres[2+4*1] = m23 * invdet;
- mres[3+4*1] = m24 * invdet;
- mres[0+4*2] = m31 * invdet;
- mres[1+4*2] = m32 * invdet;
- mres[2+4*2] = m33 * invdet;
- mres[3+4*2] = m34 * invdet;
- mres[0+4*3] = m41 * invdet;
- mres[1+4*3] = m42 * invdet;
- mres[2+4*3] = m43 * invdet;
- mres[3+4*3] = m44 * invdet;
- return mres;
- }
-
- /**
- * Map object coordinates to window coordinates.
- *
- * Traditional gluProject
implementation.
- *
- * Traditional gluUnProject
implementation.
- *
- * Traditional gluUnProject4
implementation.
- *
a
's current position
- * @param rows
- * @param columns
- * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL)
- * @param row row number to print
- * @return matrix row string representation
- */
- public static StringBuilder matrixRowToString(StringBuilder sb, final String f,
- final FloatBuffer a, final int aOffset,
- final int rows, final int columns, final boolean rowMajorOrder, final int row) {
- if(null == sb) {
- sb = new StringBuilder();
- }
- final int a0 = aOffset + a.position();
- if(rowMajorOrder) {
- for(int c=0; c- * On a reference machine the result was {@link #EPSILON} in 23 iterations. - *
- * @see #EPSILON - */ - public static float getMachineEpsilon() { - if( !machEpsilonAvail ) { - synchronized(FloatUtil.class) { - if( !machEpsilonAvail ) { - machEpsilonAvail = true; - calculateMachineEpsilonFloat(); - } - } - } - return machEpsilon; - } - - public static final float E = 2.7182818284590452354f; - - /** The value PI, i.e. 180 degrees in radians. */ - public static final float PI = 3.14159265358979323846f; - - /** The value 2PI, i.e. 360 degrees in radians. */ - public static final float TWO_PI = 2f * PI; - - /** The value PI/2, i.e. 90 degrees in radians. */ - public static final float HALF_PI = PI / 2f; - - /** The value PI/4, i.e. 45 degrees in radians. */ - public static final float QUARTER_PI = PI / 4f; - - /** The value PI^2. */ - public final static float SQUARED_PI = PI * PI; - - /** Converts arc-degree to radians */ - public static float adegToRad(final float arc_degree) { - return arc_degree * PI / 180.0f; - } - - /** Converts radians to arc-degree */ - public static float radToADeg(final float rad) { - return rad * 180.0f / PI; - } - - /** - * Epsilon for floating point {@value}, as once computed via {@link #getMachineEpsilon()} on an AMD-64 CPU. - *- * Definition of machine epsilon guarantees that: - *
- * 1.0f + EPSILON != 1.0f - *- * In other words: machEps is the maximum relative error of the chosen rounding procedure. - * - *
- * A number can be considered zero if it is in the range (or in the set): - *
- * MaybeZeroSet e ]-machEps .. machEps[ (exclusive) - *- * While comparing floating point values, machEps allows to clip the relative error: - *
- * boolean isZero = afloat < EPSILON; - * boolean isNotZero = afloat >= EPSILON; - * - * boolean isEqual = abs(bfloat - afloat) < EPSILON; - * boolean isNotEqual = abs(bfloat - afloat) >= EPSILON; - *- * - * @see #isEqual(float, float, float) - * @see #isZero(float, float) - */ - public static final float EPSILON = 1.1920929E-7f; // Float.MIN_VALUE == 1.4e-45f ; double EPSILON 2.220446049250313E-16d - - /** - * Inversion Epsilon, used with equals method to determine if two inverted matrices are close enough to be considered equal. - *
- * Using {@value}, which is ~100 times {@link FloatUtil#EPSILON}. - *
- */ - public static final float INV_DEVIANCE = 1.0E-5f; // FloatUtil.EPSILON == 1.1920929E-7f; double ALLOWED_DEVIANCE: 1.0E-8f - - /** - * Return true if both values are equal w/o regarding an epsilon. - *- * Implementation considers following corner cases: - *
epsilon
.
- * - * Implementation considers following corner cases: - *
- * Implementation considers following corner cases: - *
- * Implementation does not consider corner cases like {@link #isEqual(float, float, float)}. - *
- * @see #EPSILON - */ - public static boolean isEqual2(final float a, final float b) { - return Math.abs(a - b) < EPSILON; - } - - /** - * Return true if both values are equal w/o regarding an epsilon. - *- * Implementation considers following corner cases: - *
epsilon
.
- * - * Implementation considers following corner cases: - *
epsilon
.
- * @see #EPSILON
- */
- public static boolean isZero(final float a, final float epsilon) {
- return Math.abs(a) < epsilon;
- }
-
- /**
- * Return true if value is zero, i.e. it's absolute value < {@link #EPSILON}.
- * @see #EPSILON
- */
- public static boolean isZero(final float a) {
- return Math.abs(a) < FloatUtil.EPSILON;
- }
-
- /**
- * Invokes {@link Math#abs(float)}
- * @param a float to process
- * @return absolute value of {@code a}
- * @deprecated use {@link Math#abs(float)} directly
- */
- @Deprecated
- public static float abs(final float a) { return java.lang.Math.abs(a); }
-
- public static float pow(final float a, final float b) { return (float) java.lang.Math.pow(a, b); }
-
- public static float sin(final float a) { return (float) java.lang.Math.sin(a); }
-
- public static float asin(final float a) { return (float) java.lang.Math.asin(a); }
-
- public static float cos(final float a) { return (float) java.lang.Math.cos(a); }
-
- public static float acos(final float a) { return (float) java.lang.Math.acos(a); }
-
- public static float tan(final float a) { return (float) java.lang.Math.tan(a); }
-
- public static float atan(final float a) { return (float) java.lang.Math.atan(a); }
-
- public static float atan2(final float y, final float x) { return (float) java.lang.Math.atan2(y, x); }
-
- public static float sqrt(final float a) { return (float) java.lang.Math.sqrt(a); }
-
- /**
- * Returns resolution of Z buffer of given parameter,
- * see Love Your Z-Buffer.
- * - * return z * z / ( zNear * (1<<zBits) - z ) - *- * Examples: - *
- * 1.5256461E-4 = 16 zBits, -0.2 zDist, 0.1 zNear - * 6.1033297E-6 = 16 zBits, -1.0 zDist, 0.1 zNear - *- * @param zBits number of bits of Z precision, i.e. z-buffer depth - * @param z distance from the eye to the object - * @param zNear distance from eye to near clip plane - * @return smallest resolvable Z separation at this range. - */ - public static float getZBufferEpsilon(final int zBits, final float z, final float zNear) { - return z * z / ( zNear * ( 1 << zBits ) - z ); - } - - /** - * Returns Z buffer value of given parameter, - * see Love Your Z-Buffer. - *
- * float a = zFar / ( zFar - zNear ) - * float b = zFar * zNear / ( zNear - zFar ) - * return (int) ( (1<<zBits) * ( a + b / z ) ) - *- * @param zBits number of bits of Z precision, i.e. z-buffer depth - * @param z distance from the eye to the object - * @param zNear distance from eye to near clip plane - * @param zFar distance from eye to far clip plane - * @return z buffer value - */ - public static int getZBufferValue(final int zBits, final float z, final float zNear, final float zFar) { - final float a = zFar / ( zFar - zNear ); - final float b = zFar * zNear / ( zNear - zFar ); - return (int) ( (1<
- * It is recommended to pass and store values in tangent - * if used for perspective FOV calculations, since it will avoid conversion to tangent later on. - *
- * @param left half horizontal FOV, left side, in tangent or radians - * @param right half horizontal FOV, right side, in tangent or radians - * @param top half vertical FOV, top side, in tangent or radians - * @param bottom half vertical FOV, bottom side, in tangent or radians - * @param inTangents if true, values are in tangent, otherwise radians - */ - public FovHVHalves(final float left, final float right, final float top, final float bottom, final boolean inTangents) { - this.left = left; - this.right = right; - this.top = top; - this.bottom = bottom; - this.inTangents = inTangents; - } - - /** - * Returns a symmetrical centered {@link FovHVHalves} instance in {@link #inTangents}, using: - *- halfHorizFovTan = tan( horizontalFov / 2f ); - halfVertFovTan = tan( verticalFov / 2f ); - *- * @param horizontalFov whole horizontal FOV in radians - * @param verticalFov whole vertical FOV in radians - */ - public static FovHVHalves byRadians(final float horizontalFov, final float verticalFov) { - final float halfHorizFovTan = FloatUtil.tan(horizontalFov/2f); - final float halfVertFovTan = FloatUtil.tan(verticalFov/2f); - return new FovHVHalves(halfHorizFovTan, halfHorizFovTan, halfVertFovTan, halfVertFovTan, true); - } - - /** - * Returns a symmetrical centered {@link FovHVHalves} instance in {@link #inTangents}, using: - *
- top = bottom = tan( verticalFov / 2f ); - left = right = aspect * top; - *- * - * @param verticalFov vertical FOV in radians - * @param aspect aspect ration width / height - */ - public static FovHVHalves byFovyRadianAndAspect(final float verticalFov, final float aspect) { - final float halfVertFovTan = FloatUtil.tan(verticalFov/2f); - final float halfHorizFovTan = aspect * halfVertFovTan; - return new FovHVHalves(halfHorizFovTan, halfHorizFovTan, - halfVertFovTan, halfVertFovTan, true); - } - - /** - * Returns a custom symmetry {@link FovHVHalves} instance {@link #inTangents}, using: - *
- left = tan( horizontalFov * horizCenterFromLeft ) - right = tan( horizontalFov * ( 1f - horizCenterFromLeft ) ) - top = tan( verticalFov * vertCenterFromTop ) - bottom = tan( verticalFov * (1f - vertCenterFromTop ) ) - *- * @param horizontalFov whole horizontal FOV in radians - * @param horizCenterFromLeft horizontal center from left in [0..1] - * @param verticalFov whole vertical FOV in radians - * @param vertCenterFromTop vertical center from top in [0..1] - */ - public static FovHVHalves byRadians(final float horizontalFov, final float horizCenterFromLeft, - final float verticalFov, final float vertCenterFromTop) { - return new FovHVHalves(FloatUtil.tan(horizontalFov * horizCenterFromLeft), - FloatUtil.tan(horizontalFov * ( 1f - horizCenterFromLeft )), - FloatUtil.tan(verticalFov * vertCenterFromTop), - FloatUtil.tan(verticalFov * (1f - vertCenterFromTop )), - true); - } - - /** - * Returns a custom symmetry {@link FovHVHalves} instance {@link #inTangents}, - * via computing the
horizontalFov
using:
- * - halfVertFovTan = tan( verticalFov / 2f ); - halfHorizFovTan = aspect * halfVertFovTan; - horizontalFov = atan( halfHorizFovTan ) * 2f; - return {@link #byRadians(float, float, float, float) byRadians}(horizontalFov, horizCenterFromLeft, verticalFov, vertCenterFromTop) - *- * @param verticalFov whole vertical FOV in radians - * @param vertCenterFromTop vertical center from top in [0..1] - * @param aspect aspect ration width / height - * @param horizCenterFromLeft horizontal center from left in [0..1] - */ - public static FovHVHalves byFovyRadianAndAspect(final float verticalFov, final float vertCenterFromTop, - final float aspect, final float horizCenterFromLeft) { - final float halfVertFovTan = FloatUtil.tan(verticalFov/2f); - final float halfHorizFovTan = aspect * halfVertFovTan; - final float horizontalFov = FloatUtil.atan(halfHorizFovTan) * 2f; - return byRadians(horizontalFov, horizCenterFromLeft, verticalFov, vertCenterFromTop); - } - - /** - * Returns this instance in tangent values. - *
- * If this instance is {@link #inTangents} already, method returns this instance, - * otherwise a newly created instance w/ converted values to tangent. - *
- */ - public final FovHVHalves toTangents() { - if( inTangents ) { - return this; - } else { - return new FovHVHalves(FloatUtil.tan(left), FloatUtil.tan(right), FloatUtil.tan(top), FloatUtil.tan(bottom), true); - } - } - - /** Returns the full horizontal FOV, i.e. {@link #left} + {@link #right}, either in {@link #inTangents} or radians. */ - public final float horzFov() { return left+right; } - - /** Returns the full vertical FOV, i.e. {@link #top} + {@link #bottom}, either in {@link #inTangents} or radians. */ - public final float vertFov() { return top+bottom; } - - public final String toString() { - return "FovHVH["+(inTangents?"tangents":"radians")+": "+left+" l, "+right+" r, "+top+" t, "+bottom+" b]"; - } - public final String toStringInDegrees() { - final float f = 180.0f / FloatUtil.PI; - final String storedAs = inTangents?"tangents":"radians"; - if( inTangents ) { - final float aleft = FloatUtil.atan(left); - final float aright = FloatUtil.atan(right); - final float atop = FloatUtil.atan(top); - final float abottom = FloatUtil.atan(bottom); - return "FovHVH[degrees: "+aleft*f+" l, "+aright*f+" r, "+atop*f+" t, "+abottom*f+" b, stored-as: "+storedAs+"]"; - } else { - return "FovHVH[degrees: "+left*f+" l, "+right*f+" r, "+top*f+" t, "+bottom*f+" b, stored-as: "+storedAs+"]"; - } - } -} diff --git a/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java b/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java deleted file mode 100644 index 5d1d8e968..000000000 --- a/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java +++ /dev/null @@ -1,2153 +0,0 @@ -/** - * Copyright 2014-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: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.math; - -import java.nio.FloatBuffer; - -import com.jogamp.opengl.math.geom.AABBox; -import com.jogamp.opengl.math.geom.Frustum; -import com.jogamp.opengl.math.geom.Frustum.Plane; - -/** - * Basic 4x4 float matrix implementation using fields for intensive use-cases (host operations). - *- * Implementation covers {@link FloatUtil} matrix functionality, exposed in an object oriented manner. - *
- *- * Unlike {@link com.jogamp.opengl.util.PMVMatrix PMVMatrix}, this class only represents one single matrix - * without a complete {@link com.jogamp.opengl.fixedfunc.GLMatrixFunc GLMatrixFunc} implementation. - *
- *- * For array operations the layout is expected in column-major order - * matching OpenGL's implementation, illustration: - *
- Row-Major Column-Major (OpenGL): - - | 0 1 2 tx | - | | - | 4 5 6 ty | - M = | | - | 8 9 10 tz | - | | - | 12 13 14 15 | - - R C R C - m[0*4+3] = tx; m[0+4*3] = tx; - m[1*4+3] = ty; m[1+4*3] = ty; - m[2*4+3] = tz; m[2+4*3] = tz; - - RC (std subscript order) RC (std subscript order) - m03 = tx; m03 = tx; - m13 = ty; m13 = ty; - m23 = tz; m23 = tz; - - *- * - *
- *
- * Implementation utilizes unrolling of small vertices and matrices wherever possible - * while trying to access memory in a linear fashion for performance reasons, see: - *
- * - * @see com.jogamp.opengl.util.PMVMatrix - * @see FloatUtil - */ -public class Matrix4f { - - /** - * Creates a new identity matrix. - */ - public Matrix4f() { - m00 = m11 = m22 = m33 = 1.0f; - // remaining fields have default init to zero - } - - /** - * Creates a new matrix copying the values of the given {@code src} matrix. - */ - public Matrix4f(final Matrix4f src) { - load(src); - } - - /** - * Creates a new matrix based on given float[4*4] column major order. - * @param m 4x4 matrix in column-major order - */ - public Matrix4f(final float[] m) { - load(m); - } - - /** - * Creates a new matrix based on given float[4*4] column major order. - * @param m 4x4 matrix in column-major order - * @param m_off offset for matrix {@code m} - */ - public Matrix4f(final float[] m, final int m_off) { - load(m, m_off); - } - - /** - * Creates a new matrix based on given {@link FloatBuffer} 4x4 column major order. - * @param m 4x4 matrix in column-major order - */ - public Matrix4f(final FloatBuffer m) { - load(m); - } - - // - // Write to Matrix via set(..) or load(..) - // - - /** Sets the {@code i}th component with float {@code v} 0 <= i < 16 */ - public void set(final int i, final float v) { - switch (i) { - case 0+4*0: m00 = v; break; - case 1+4*0: m10 = v; break; - case 2+4*0: m20 = v; break; - case 3+4*0: m30 = v; break; - - case 0+4*1: m01 = v; break; - case 1+4*1: m11 = v; break; - case 2+4*1: m21 = v; break; - case 3+4*1: m31 = v; break; - - case 0+4*2: m02 = v; break; - case 1+4*2: m12 = v; break; - case 2+4*2: m22 = v; break; - case 3+4*2: m32 = v; break; - - case 0+4*3: m03 = v; break; - case 1+4*3: m13 = v; break; - case 2+4*3: m23 = v; break; - case 3+4*3: m33 = v; break; - default: throw new IndexOutOfBoundsException(); - } - } - - /** - * Set this matrix to identity. - *- Translation matrix (Column Order): - 1 0 0 0 - 0 1 0 0 - 0 0 1 0 - 0 0 0 1 - *- * @return this matrix for chaining - */ - public final Matrix4f loadIdentity() { - m00 = m11 = m22 = m33 = 1.0f; - m01 = m02 = m03 = - m10 = m12 = m13 = - m20 = m21 = m23 = - m30 = m31 = m32 = 0.0f; - return this; - } - - /** - * Load the values of the given matrix {@code b} to this matrix. - * @param src the source values - * @return this matrix for chaining - */ - public Matrix4f load(final Matrix4f src) { - m00 = src.m00; m10 = src.m10; m20 = src.m20; m30 = src.m30; - m01 = src.m01; m11 = src.m11; m21 = src.m21; m31 = src.m31; - m02 = src.m02; m12 = src.m12; m22 = src.m22; m32 = src.m32; - m03 = src.m03; m13 = src.m13; m23 = src.m23; m33 = src.m33; - return this; - } - - /** - * Load the values of the given matrix {@code src} to this matrix. - * @param src 4x4 matrix float[16] in column-major order - * @return this matrix for chaining - */ - public Matrix4f load(final float[] src) { - m00 = src[0+0*4]; // column 0 - m10 = src[1+0*4]; - m20 = src[2+0*4]; - m30 = src[3+0*4]; - m01 = src[0+1*4]; // column 1 - m11 = src[1+1*4]; - m21 = src[2+1*4]; - m31 = src[3+1*4]; - m02 = src[0+2*4]; // column 2 - m12 = src[1+2*4]; - m22 = src[2+2*4]; - m32 = src[3+2*4]; - m03 = src[0+3*4]; // column 3 - m13 = src[1+3*4]; - m23 = src[2+3*4]; - m33 = src[3+3*4]; - return this; - } - - /** - * Load the values of the given matrix {@code src} to this matrix. - * @param src 4x4 matrix float[16] in column-major order - * @param src_off offset for matrix {@code src} - * @return this matrix for chaining - */ - public Matrix4f load(final float[] src, final int src_off) { - m00 = src[src_off+0+0*4]; - m10 = src[src_off+1+0*4]; - m20 = src[src_off+2+0*4]; - m30 = src[src_off+3+0*4]; - m01 = src[src_off+0+1*4]; - m11 = src[src_off+1+1*4]; - m21 = src[src_off+2+1*4]; - m31 = src[src_off+3+1*4]; - m02 = src[src_off+0+2*4]; - m12 = src[src_off+1+2*4]; - m22 = src[src_off+2+2*4]; - m32 = src[src_off+3+2*4]; - m03 = src[src_off+0+3*4]; - m13 = src[src_off+1+3*4]; - m23 = src[src_off+2+3*4]; - m33 = src[src_off+3+3*4]; - return this; - } - - /** - * Load the values of the given matrix {@code src} to this matrix. - *
- * Implementation uses relative {@link FloatBuffer#get()}, - * hence caller may want to issue {@link FloatBuffer#reset()} thereafter. - *
- * @param src 4x4 matrix {@link FloatBuffer} in column-major order - * @return this matrix for chaining - */ - public Matrix4f load(final FloatBuffer src) { - m00 = src.get(); - m10 = src.get(); - m20 = src.get(); - m30 = src.get(); - m01 = src.get(); - m11 = src.get(); - m21 = src.get(); - m31 = src.get(); - m02 = src.get(); - m12 = src.get(); - m22 = src.get(); - m32 = src.get(); - m03 = src.get(); - m13 = src.get(); - m23 = src.get(); - m33 = src.get(); - return this; - } - - // - // Read out Matrix via get(..) - // - - /** Gets the {@code i}th component, 0 <= i < 16 */ - public float get(final int i) { - switch (i) { - case 0+4*0: return m00; - case 1+4*0: return m10; - case 2+4*0: return m20; - case 3+4*0: return m30; - - case 0+4*1: return m01; - case 1+4*1: return m11; - case 2+4*1: return m21; - case 3+4*1: return m31; - - case 0+4*2: return m02; - case 1+4*2: return m12; - case 2+4*2: return m22; - case 3+4*2: return m32; - - case 0+4*3: return m03; - case 1+4*3: return m13; - case 2+4*3: return m23; - case 3+4*3: return m33; - - default: throw new IndexOutOfBoundsException(); - } - } - - /** - * Get the named column of the given column-major matrix to v_out. - * @param column named column to copy - * @param v_out the column-vector storage - * @return given result vector v_out for chaining - */ - public Vec4f getColumn(final int column, final Vec4f v_out) { - v_out.set( get(0+column*4), - get(1+column*4), - get(2+column*4), - get(3+column*4) ); - return v_out; - } - - /** - * Get the named column of the given column-major matrix to v_out. - * @param column named column to copy - * @param v_out the column-vector storage - * @return given result vector v_out for chaining - */ - public Vec3f getColumn(final int column, final Vec3f v_out) { - v_out.set( get(0+column*4), - get(1+column*4), - get(2+column*4) ); - return v_out; - } - - /** - * Get the named row of the given column-major matrix to v_out. - * @param row named row to copy - * @param v_out the row-vector storage - * @return given result vector v_out for chaining - */ - public Vec4f getRow(final int row, final Vec4f v_out) { - v_out.set( get(row+0*4), - get(row+1*4), - get(row+2*4), - get(row+3*4) ); - return v_out; - } - - /** - * Get the named row of the given column-major matrix to v_out. - * @param row named row to copy - * @param v_out the row-vector storage - * @return given result vector v_out for chaining - */ - public Vec3f getRow(final int row, final Vec3f v_out) { - v_out.set( get(row+0*4), - get(row+1*4), - get(row+2*4) ); - return v_out; - } - - /** - * Get this matrix into the given float[16] array at {@code dst_off} in column major order. - * - * @param dst float[16] array storage in column major order - * @param dst_off offset - * @return {@code dst} for chaining - */ - public float[] get(final float[] dst, final int dst_off) { - dst[dst_off+0+0*4] = m00; - dst[dst_off+1+0*4] = m10; - dst[dst_off+2+0*4] = m20; - dst[dst_off+3+0*4] = m30; - dst[dst_off+0+1*4] = m01; - dst[dst_off+1+1*4] = m11; - dst[dst_off+2+1*4] = m21; - dst[dst_off+3+1*4] = m31; - dst[dst_off+0+2*4] = m02; - dst[dst_off+1+2*4] = m12; - dst[dst_off+2+2*4] = m22; - dst[dst_off+3+2*4] = m32; - dst[dst_off+0+3*4] = m03; - dst[dst_off+1+3*4] = m13; - dst[dst_off+2+3*4] = m23; - dst[dst_off+3+3*4] = m33; - return dst; - } - - /** - * Get this matrix into the given float[16] array in column major order. - * - * @param dst float[16] array storage in column major order - * @return {@code dst} for chaining - */ - public float[] get(final float[] dst) { - dst[0+0*4] = m00; - dst[1+0*4] = m10; - dst[2+0*4] = m20; - dst[3+0*4] = m30; - dst[0+1*4] = m01; - dst[1+1*4] = m11; - dst[2+1*4] = m21; - dst[3+1*4] = m31; - dst[0+2*4] = m02; - dst[1+2*4] = m12; - dst[2+2*4] = m22; - dst[3+2*4] = m32; - dst[0+3*4] = m03; - dst[1+3*4] = m13; - dst[2+3*4] = m23; - dst[3+3*4] = m33; - return dst; - } - - /** - * Get this matrix into the given {@link FloatBuffer} in column major order. - *- * Implementation uses relative {@link FloatBuffer#put(float)}, - * hence caller may want to issue {@link FloatBuffer#reset()} thereafter. - *
- * - * @param dst {@link FloatBuffer} array storage in column major order - * @return {@code dst} for chaining - */ - public FloatBuffer get(final FloatBuffer dst) { - dst.put( m00 ); - dst.put( m10 ); - dst.put( m20 ); - dst.put( m30 ); - dst.put( m01 ); - dst.put( m11 ); - dst.put( m21 ); - dst.put( m31 ); - dst.put( m02 ); - dst.put( m12 ); - dst.put( m22 ); - dst.put( m32 ); - dst.put( m03 ); - dst.put( m13 ); - dst.put( m23 ); - dst.put( m33 ); - return dst; - } - - // - // Basic matrix operations - // - - /** - * Returns the determinant of this matrix - * @return the matrix determinant - */ - public float determinant() { - float ret = 0; - ret += m00 * ( + m11*(m22*m33 - m23*m32) - m12*(m21*m33 - m23*m31) + m13*(m21*m32 - m22*m31)); - ret -= m01 * ( + m10*(m22*m33 - m23*m32) - m12*(m20*m33 - m23*m30) + m13*(m20*m32 - m22*m30)); - ret += m02 * ( + m10*(m21*m33 - m23*m31) - m11*(m20*m33 - m23*m30) + m13*(m20*m31 - m21*m30)); - ret -= m03 * ( + m10*(m21*m32 - m22*m31) - m11*(m20*m32 - m22*m30) + m12*(m20*m31 - m21*m30)); - return ret; - } - - /** - * Transpose this matrix. - * - * @return this matrix for chaining - */ - public final Matrix4f transpose() { - float tmp; - - tmp = m10; - m10 = m01; - m01 = tmp; - - tmp = m20; - m20 = m02; - m02 = tmp; - - tmp = m30; - m30 = m03; - m03 = tmp; - - tmp = m21; - m21 = m12; - m12 = tmp; - - tmp = m31; - m31 = m13; - m13 = tmp; - - tmp = m32; - m32 = m23; - m23 = tmp; - - return this; - } - - /** - * Transpose the given {@code src} matrix into this matrix. - * - * @param src source 4x4 matrix - * @return this matrix (result) for chaining - */ - public final Matrix4f transpose(final Matrix4f src) { - if( src == this ) { - return transpose(); - } - m00 = src.m00; - m10 = src.m01; - m20 = src.m02; - m30 = src.m03; - - m01 = src.m10; - m11 = src.m11; - m21 = src.m12; - m31 = src.m13; - - m02 = src.m20; - m12 = src.m21; - m22 = src.m22; - m32 = src.m23; - - m03 = src.m30; - m13 = src.m31; - m23 = src.m32; - m33 = src.m33; - return this; - } - - /** - * Invert this matrix. - * @return false if this matrix is singular and inversion not possible, otherwise true - */ - public boolean invert() { - final float scale; - try { - scale = mulScale(); - } catch(final ArithmeticException aex) { - return false; // max was 0 - } - final float a00 = m00*scale; - final float a10 = m10*scale; - final float a20 = m20*scale; - final float a30 = m30*scale; - - final float a01 = m01*scale; - final float a11 = m11*scale; - final float a21 = m21*scale; - final float a31 = m31*scale; - - final float a02 = m02*scale; - final float a12 = m12*scale; - final float a22 = m22*scale; - final float a32 = m32*scale; - - final float a03 = m03*scale; - final float a13 = m13*scale; - final float a23 = m23*scale; - final float a33 = m33*scale; - - final float b00 = + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31); - final float b01 = -( + a10*(a22*a33 - a23*a32) - a12*(a20*a33 - a23*a30) + a13*(a20*a32 - a22*a30)); - final float b02 = + a10*(a21*a33 - a23*a31) - a11*(a20*a33 - a23*a30) + a13*(a20*a31 - a21*a30); - final float b03 = -( + a10*(a21*a32 - a22*a31) - a11*(a20*a32 - a22*a30) + a12*(a20*a31 - a21*a30)); - - final float b10 = -( + a01*(a22*a33 - a23*a32) - a02*(a21*a33 - a23*a31) + a03*(a21*a32 - a22*a31)); - final float b11 = + a00*(a22*a33 - a23*a32) - a02*(a20*a33 - a23*a30) + a03*(a20*a32 - a22*a30); - final float b12 = -( + a00*(a21*a33 - a23*a31) - a01*(a20*a33 - a23*a30) + a03*(a20*a31 - a21*a30)); - final float b13 = + a00*(a21*a32 - a22*a31) - a01*(a20*a32 - a22*a30) + a02*(a20*a31 - a21*a30); - - final float b20 = + a01*(a12*a33 - a13*a32) - a02*(a11*a33 - a13*a31) + a03*(a11*a32 - a12*a31); - final float b21 = -( + a00*(a12*a33 - a13*a32) - a02*(a10*a33 - a13*a30) + a03*(a10*a32 - a12*a30)); - final float b22 = + a00*(a11*a33 - a13*a31) - a01*(a10*a33 - a13*a30) + a03*(a10*a31 - a11*a30); - final float b23 = -( + a00*(a11*a32 - a12*a31) - a01*(a10*a32 - a12*a30) + a02*(a10*a31 - a11*a30)); - - final float b30 = -( + a01*(a12*a23 - a13*a22) - a02*(a11*a23 - a13*a21) + a03*(a11*a22 - a12*a21)); - final float b31 = + a00*(a12*a23 - a13*a22) - a02*(a10*a23 - a13*a20) + a03*(a10*a22 - a12*a20); - final float b32 = -( + a00*(a11*a23 - a13*a21) - a01*(a10*a23 - a13*a20) + a03*(a10*a21 - a11*a20)); - final float b33 = + a00*(a11*a22 - a12*a21) - a01*(a10*a22 - a12*a20) + a02*(a10*a21 - a11*a20); - - final float det = (a00*b00 + a01*b01 + a02*b02 + a03*b03) / scale; - if( 0 == det ) { - return false; - } - final float invdet = 1.0f / det; - - m00 = b00 * invdet; - m10 = b01 * invdet; - m20 = b02 * invdet; - m30 = b03 * invdet; - - m01 = b10 * invdet; - m11 = b11 * invdet; - m21 = b12 * invdet; - m31 = b13 * invdet; - - m02 = b20 * invdet; - m12 = b21 * invdet; - m22 = b22 * invdet; - m32 = b23 * invdet; - - m03 = b30 * invdet; - m13 = b31 * invdet; - m23 = b32 * invdet; - m33 = b33 * invdet; - return true; - } - - /** - * Invert the {@code src} matrix values into this matrix - * @param src the source matrix, which values are to be inverted - * @return false if {@code src} matrix is singular and inversion not possible, otherwise true - */ - public boolean invert(final Matrix4f src) { - final float scale; - try { - scale = src.mulScale(); - } catch(final ArithmeticException aex) { - return false; // max was 0 - } - final float a00 = src.m00*scale; - final float a10 = src.m10*scale; - final float a20 = src.m20*scale; - final float a30 = src.m30*scale; - - final float a01 = src.m01*scale; - final float a11 = src.m11*scale; - final float a21 = src.m21*scale; - final float a31 = src.m31*scale; - - final float a02 = src.m02*scale; - final float a12 = src.m12*scale; - final float a22 = src.m22*scale; - final float a32 = src.m32*scale; - - final float a03 = src.m03*scale; - final float a13 = src.m13*scale; - final float a23 = src.m23*scale; - final float a33 = src.m33*scale; - - final float b00 = + a11*(a22*a33 - a23*a32) - a12*(a21*a33 - a23*a31) + a13*(a21*a32 - a22*a31); - final float b01 = -( + a10*(a22*a33 - a23*a32) - a12*(a20*a33 - a23*a30) + a13*(a20*a32 - a22*a30)); - final float b02 = + a10*(a21*a33 - a23*a31) - a11*(a20*a33 - a23*a30) + a13*(a20*a31 - a21*a30); - final float b03 = -( + a10*(a21*a32 - a22*a31) - a11*(a20*a32 - a22*a30) + a12*(a20*a31 - a21*a30)); - - final float b10 = -( + a01*(a22*a33 - a23*a32) - a02*(a21*a33 - a23*a31) + a03*(a21*a32 - a22*a31)); - final float b11 = + a00*(a22*a33 - a23*a32) - a02*(a20*a33 - a23*a30) + a03*(a20*a32 - a22*a30); - final float b12 = -( + a00*(a21*a33 - a23*a31) - a01*(a20*a33 - a23*a30) + a03*(a20*a31 - a21*a30)); - final float b13 = + a00*(a21*a32 - a22*a31) - a01*(a20*a32 - a22*a30) + a02*(a20*a31 - a21*a30); - - final float b20 = + a01*(a12*a33 - a13*a32) - a02*(a11*a33 - a13*a31) + a03*(a11*a32 - a12*a31); - final float b21 = -( + a00*(a12*a33 - a13*a32) - a02*(a10*a33 - a13*a30) + a03*(a10*a32 - a12*a30)); - final float b22 = + a00*(a11*a33 - a13*a31) - a01*(a10*a33 - a13*a30) + a03*(a10*a31 - a11*a30); - final float b23 = -( + a00*(a11*a32 - a12*a31) - a01*(a10*a32 - a12*a30) + a02*(a10*a31 - a11*a30)); - - final float b30 = -( + a01*(a12*a23 - a13*a22) - a02*(a11*a23 - a13*a21) + a03*(a11*a22 - a12*a21)); - final float b31 = + a00*(a12*a23 - a13*a22) - a02*(a10*a23 - a13*a20) + a03*(a10*a22 - a12*a20); - final float b32 = -( + a00*(a11*a23 - a13*a21) - a01*(a10*a23 - a13*a20) + a03*(a10*a21 - a11*a20)); - final float b33 = + a00*(a11*a22 - a12*a21) - a01*(a10*a22 - a12*a20) + a02*(a10*a21 - a11*a20); - - final float det = (a00*b00 + a01*b01 + a02*b02 + a03*b03) / scale; - - if( 0 == det ) { - return false; - } - final float invdet = 1.0f / det; - - m00 = b00 * invdet; - m10 = b01 * invdet; - m20 = b02 * invdet; - m30 = b03 * invdet; - - m01 = b10 * invdet; - m11 = b11 * invdet; - m21 = b12 * invdet; - m31 = b13 * invdet; - - m02 = b20 * invdet; - m12 = b21 * invdet; - m22 = b22 * invdet; - m32 = b23 * invdet; - - m03 = b30 * invdet; - m13 = b31 * invdet; - m23 = b32 * invdet; - m33 = b33 * invdet; - return true; - } - - private final float mulScale() { - /** - // No Hotspot intrinsic Math.* optimization for at least Math.max(), - // hence this chunk is slower. - float max = Math.abs(m00); - - max = Math.max(max, Math.abs(m01)); - max = Math.max(max, Math.abs(m02)); - ... etc - */ - float a = Math.abs(m00); - float max = a; - a = Math.abs(m01); if( a > max ) max = a; - a = Math.abs(m02); if( a > max ) max = a; - a = Math.abs(m03); if( a > max ) max = a; - - a = Math.abs(m10); if( a > max ) max = a; - a = Math.abs(m11); if( a > max ) max = a; - a = Math.abs(m12); if( a > max ) max = a; - a = Math.abs(m13); if( a > max ) max = a; - - a = Math.abs(m20); if( a > max ) max = a; - a = Math.abs(m21); if( a > max ) max = a; - a = Math.abs(m22); if( a > max ) max = a; - a = Math.abs(m23); if( a > max ) max = a; - - a = Math.abs(m30); if( a > max ) max = a; - a = Math.abs(m31); if( a > max ) max = a; - a = Math.abs(m32); if( a > max ) max = a; - a = Math.abs(m33); if( a > max ) max = a; - - return 1.0f/max; - } - - /** - * Multiply matrix: [this] = [this] x [b] - * @param b 4x4 matrix - * @return this matrix for chaining - * @see #mul(Matrix4f, Matrix4f) - */ - public final Matrix4f mul(final Matrix4f b) { - // return mul(new Matrix4f(this), b); // <- roughly half speed - float ai0=m00; // row-0, m[0+0*4] - float ai1=m01; - float ai2=m02; - float ai3=m03; - m00 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ; - m01 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ; - m02 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ; - m03 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ; - - ai0=m10; //row-1, m[1+0*4] - ai1=m11; - ai2=m12; - ai3=m13; - m10 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ; - m11 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ; - m12 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ; - m13 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ; - - ai0=m20; // row-2, m[2+0*4] - ai1=m21; - ai2=m22; - ai3=m23; - m20 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ; - m21 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ; - m22 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ; - m23 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ; - - ai0=m30; // row-3, m[3+0*4] - ai1=m31; - ai2=m32; - ai3=m33; - m30 = ai0 * b.m00 + ai1 * b.m10 + ai2 * b.m20 + ai3 * b.m30 ; - m31 = ai0 * b.m01 + ai1 * b.m11 + ai2 * b.m21 + ai3 * b.m31 ; - m32 = ai0 * b.m02 + ai1 * b.m12 + ai2 * b.m22 + ai3 * b.m32 ; - m33 = ai0 * b.m03 + ai1 * b.m13 + ai2 * b.m23 + ai3 * b.m33 ; - return this; - } - - /** - * Multiply matrix: [this] = [a] x [b] - * @param a 4x4 matrix, can't be this matrix - * @param b 4x4 matrix, can't be this matrix - * @return this matrix for chaining - * @see #mul(Matrix4f) - */ - public final Matrix4f mul(final Matrix4f a, final Matrix4f b) { - // row-0, m[0+0*4] - m00 = a.m00 * b.m00 + a.m01 * b.m10 + a.m02 * b.m20 + a.m03 * b.m30 ; - m01 = a.m00 * b.m01 + a.m01 * b.m11 + a.m02 * b.m21 + a.m03 * b.m31 ; - m02 = a.m00 * b.m02 + a.m01 * b.m12 + a.m02 * b.m22 + a.m03 * b.m32 ; - m03 = a.m00 * b.m03 + a.m01 * b.m13 + a.m02 * b.m23 + a.m03 * b.m33 ; - - //row-1, m[1+0*4] - m10 = a.m10 * b.m00 + a.m11 * b.m10 + a.m12 * b.m20 + a.m13 * b.m30 ; - m11 = a.m10 * b.m01 + a.m11 * b.m11 + a.m12 * b.m21 + a.m13 * b.m31 ; - m12 = a.m10 * b.m02 + a.m11 * b.m12 + a.m12 * b.m22 + a.m13 * b.m32 ; - m13 = a.m10 * b.m03 + a.m11 * b.m13 + a.m12 * b.m23 + a.m13 * b.m33 ; - - // row-2, m[2+0*4] - m20 = a.m20 * b.m00 + a.m21 * b.m10 + a.m22 * b.m20 + a.m23 * b.m30 ; - m21 = a.m20 * b.m01 + a.m21 * b.m11 + a.m22 * b.m21 + a.m23 * b.m31 ; - m22 = a.m20 * b.m02 + a.m21 * b.m12 + a.m22 * b.m22 + a.m23 * b.m32 ; - m23 = a.m20 * b.m03 + a.m21 * b.m13 + a.m22 * b.m23 + a.m23 * b.m33 ; - - // row-3, m[3+0*4] - m30 = a.m30 * b.m00 + a.m31 * b.m10 + a.m32 * b.m20 + a.m33 * b.m30 ; - m31 = a.m30 * b.m01 + a.m31 * b.m11 + a.m32 * b.m21 + a.m33 * b.m31 ; - m32 = a.m30 * b.m02 + a.m31 * b.m12 + a.m32 * b.m22 + a.m33 * b.m32 ; - m33 = a.m30 * b.m03 + a.m31 * b.m13 + a.m32 * b.m23 + a.m33 * b.m33 ; - - return this; - } - - /** - * @param v_in 4-component column-vector, can be v_out for in-place transformation - * @param v_out this * v_in - * @returns v_out for chaining - */ - public final Vec4f mulVec4f(final Vec4f v_in, final Vec4f v_out) { - // (one matrix row in column-major order) X (column vector) - final float x = v_in.x(), y = v_in.y(), z = v_in.z(), w = v_in.w(); - v_out.set( x * m00 + y * m01 + z * m02 + w * m03, - x * m10 + y * m11 + z * m12 + w * m13, - x * m20 + y * m21 + z * m22 + w * m23, - x * m30 + y * m31 + z * m32 + w * m33 ); - return v_out; - } - - /** - * @param v_inout 4-component column-vector input and output, i.e. in-place transformation - * @returns v_inout for chaining - */ - public final Vec4f mulVec4f(final Vec4f v_inout) { - // (one matrix row in column-major order) X (column vector) - final float x = v_inout.x(), y = v_inout.y(), z = v_inout.z(), w = v_inout.w(); - v_inout.set( x * m00 + y * m01 + z * m02 + w * m03, - x * m10 + y * m11 + z * m12 + w * m13, - x * m20 + y * m21 + z * m22 + w * m23, - x * m30 + y * m31 + z * m32 + w * m33 ); - return v_inout; - } - - /** - * Affine 3f-vector transformation by 4x4 matrix - * - * 4x4 matrix multiplication with 3-component vector, - * using {@code 1} for for {@code v_in.w()} and dropping {@code v_out.w()}, - * which shall be {@code 1}. - * - * @param v_in 3-component column-vector {@link Vec3f}, can be v_out for in-place transformation - * @param v_out m_in * v_in, 3-component column-vector {@link Vec3f} - * @returns v_out for chaining - */ - public final Vec3f mulVec3f(final Vec3f v_in, final Vec3f v_out) { - // (one matrix row in column-major order) X (column vector) - final float x = v_in.x(), y = v_in.y(), z = v_in.z(); - v_out.set( x * m00 + y * m01 + z * m02 + 1f * m03, - x * m10 + y * m11 + z * m12 + 1f * m13, - x * m20 + y * m21 + z * m22 + 1f * m23 ); - return v_out; - } - - /** - * Affine 3f-vector transformation by 4x4 matrix - * - * 4x4 matrix multiplication with 3-component vector, - * using {@code 1} for for {@code v_inout.w()} and dropping {@code v_inout.w()}, - * which shall be {@code 1}. - * - * @param v_inout 3-component column-vector {@link Vec3f} input and output, i.e. in-place transformation - * @returns v_inout for chaining - */ - public final Vec3f mulVec3f(final Vec3f v_inout) { - // (one matrix row in column-major order) X (column vector) - final float x = v_inout.x(), y = v_inout.y(), z = v_inout.z(); - v_inout.set( x * m00 + y * m01 + z * m02 + 1f * m03, - x * m10 + y * m11 + z * m12 + 1f * m13, - x * m20 + y * m21 + z * m22 + 1f * m23 ); - return v_inout; - } - - // - // Matrix setTo...(), affine + basic - // - - /** - * Set this matrix to translation. - *- Translation matrix (Column Order): - 1 0 0 0 - 0 1 0 0 - 0 0 1 0 - x y z 1 - *- * @param x x-axis translate - * @param y y-axis translate - * @param z z-axis translate - * @return this matrix for chaining - */ - public final Matrix4f setToTranslation(final float x, final float y, final float z) { - m00 = m11 = m22 = m33 = 1.0f; - m03 = x; - m13 = y; - m23 = z; - m01 = m02 = - m10 = m12 = - m20 = m21 = - m30 = m31 = m32 = 0.0f; - return this; - } - - /** - * Set this matrix to translation. - *
- Translation matrix (Column Order): - 1 0 0 0 - 0 1 0 0 - 0 0 1 0 - x y z 1 - *- * @param t translate Vec3f - * @return this matrix for chaining - */ - public final Matrix4f setToTranslation(final Vec3f t) { - return setToTranslation(t.x(), t.y(), t.z()); - } - - /** - * Set this matrix to scale. - *
- Scale matrix (Any Order): - x 0 0 0 - 0 y 0 0 - 0 0 z 0 - 0 0 0 1 - *- * @param x x-axis scale - * @param y y-axis scale - * @param z z-axis scale - * @return this matrix for chaining - */ - public final Matrix4f setToScale(final float x, final float y, final float z) { - m33 = 1.0f; - m00 = x; - m11 = y; - m22 = z; - m01 = m02 = m03 = - m10 = m12 = m13 = - m20 = m21 = m23 = - m30 = m31 = m32 = 0.0f; - return this; - } - - /** - * Set this matrix to scale. - *
- Scale matrix (Any Order): - x 0 0 0 - 0 y 0 0 - 0 0 z 0 - 0 0 0 1 - *- * @param s scale Vec3f - * @return this matrix for chaining - */ - public final Matrix4f setToScale(final Vec3f s) { - return setToScale(s.x(), s.y(), s.z()); - } - - /** - * Set this matrix to rotation from the given axis and angle in radians. - *
- Rotation matrix (Column Order): - xx(1-c)+c xy(1-c)+zs xz(1-c)-ys 0 - xy(1-c)-zs yy(1-c)+c yz(1-c)+xs 0 - xz(1-c)+ys yz(1-c)-xs zz(1-c)+c 0 - 0 0 0 1 - *- * @see Matrix-FAQ Q38 - * @param ang_rad angle in radians - * @param x x of rotation axis - * @param y y of rotation axis - * @param z z of rotation axis - * @return this matrix for chaining - */ - public final Matrix4f setToRotationAxis(final float ang_rad, float x, float y, float z) { - final float c = FloatUtil.cos(ang_rad); - final float ic= 1.0f - c; - final float s = FloatUtil.sin(ang_rad); - - final Vec3f tmp = new Vec3f(x, y, z).normalize(); - x = tmp.x(); y = tmp.y(); z = tmp.z(); - - final float xy = x*y; - final float xz = x*z; - final float xs = x*s; - final float ys = y*s; - final float yz = y*z; - final float zs = z*s; - m00 = x*x*ic+c; - m10 = xy*ic+zs; - m20 = xz*ic-ys; - m30 = 0; - - m01 = xy*ic-zs; - m11 = y*y*ic+c; - m21 = yz*ic+xs; - m31 = 0; - - m02 = xz*ic+ys; - m12 = yz*ic-xs; - m22 = z*z*ic+c; - m32 = 0; - - m03 = 0f; - m13 = 0f; - m23 = 0f; - m33 = 1f; - - return this; - } - - /** - * Set this matrix to rotation from the given axis and angle in radians. - *
- Rotation matrix (Column Order): - xx(1-c)+c xy(1-c)+zs xz(1-c)-ys 0 - xy(1-c)-zs yy(1-c)+c yz(1-c)+xs 0 - xz(1-c)+ys yz(1-c)-xs zz(1-c)+c 0 - 0 0 0 1 - *- * @see Matrix-FAQ Q38 - * @param ang_rad angle in radians - * @param axis rotation axis - * @return this matrix for chaining - */ - public final Matrix4f setToRotationAxis(final float ang_rad, final Vec3f axis) { - return setToRotationAxis(ang_rad, axis.x(), axis.y(), axis.z()); - } - - /** - * Set this matrix to rotation from the given Euler rotation angles in radians. - *
- * The rotations are applied in the given order: - *
- * Implementation does not use Quaternion and hence is exposed to - * Gimbal-Lock, - * consider using {@link #setToRotation(Quaternion)}. - *
- * @see Matrix-FAQ Q36 - * @see euclideanspace.com-eulerToMatrix - * @see #setToRotation(Quaternion) - */ - public Matrix4f setToRotationEuler(final float bankX, final float headingY, final float attitudeZ) { - // Assuming the angles are in radians. - final float ch = FloatUtil.cos(headingY); - final float sh = FloatUtil.sin(headingY); - final float ca = FloatUtil.cos(attitudeZ); - final float sa = FloatUtil.sin(attitudeZ); - final float cb = FloatUtil.cos(bankX); - final float sb = FloatUtil.sin(bankX); - - m00 = ch*ca; - m10 = sa; - m20 = -sh*ca; - m30 = 0; - - m01 = sh*sb - ch*sa*cb; - m11 = ca*cb; - m21 = sh*sa*cb + ch*sb; - m31 = 0; - - m02 = ch*sa*sb + sh*cb; - m12 = -ca*sb; - m22 = -sh*sa*sb + ch*cb; - m32 = 0; - - m03 = 0; - m13 = 0; - m23 = 0; - m33 = 1; - - return this; - } - - /** - * Set this matrix to rotation from the given Euler rotation angles in radians. - *- * The rotations are applied in the given order: - *
- * Implementation does not use Quaternion and hence is exposed to - * Gimbal-Lock, - * consider using {@link #setToRotation(Quaternion)}. - *
- * @see Matrix-FAQ Q36 - * @see euclideanspace.com-eulerToMatrix - * @see #setToRotation(Quaternion) - */ - public Matrix4f setToRotationEuler(final Vec3f angradXYZ) { - return setToRotationEuler(angradXYZ.x(), angradXYZ.y(), angradXYZ.z()); - } - - /** - * Set this matrix to rotation using the given Quaternion. - *- * Implementation Details: - *
- Ortho matrix (Column Order): - 2/dx 0 0 0 - 0 2/dy 0 0 - 0 0 2/dz 0 - tx ty tz 1 - *- * @param left - * @param right - * @param bottom - * @param top - * @param zNear - * @param zFar - * @return this matrix for chaining - */ - public Matrix4f setToOrtho(final float left, final float right, - final float bottom, final float top, - final float zNear, final float zFar) { - { - // m00 = m11 = m22 = m33 = 1f; - m10 = m20 = m30 = 0f; - m01 = m21 = m31 = 0f; - m02 = m12 = m32 = 0f; - // m03 = m13 = m23 = 0f; - } - final float dx=right-left; - final float dy=top-bottom; - final float dz=zFar-zNear; - final float tx=-1.0f*(right+left)/dx; - final float ty=-1.0f*(top+bottom)/dy; - final float tz=-1.0f*(zFar+zNear)/dz; - - m00 = 2.0f/dx; - m11 = 2.0f/dy; - m22 = -2.0f/dz; - - m03 = tx; - m13 = ty; - m23 = tz; - m33 = 1f; - - return this; - } - - /** - * Set this matrix to frustum. - *
- Frustum matrix (Column Order): - 2*zNear/dx 0 0 0 - 0 2*zNear/dy 0 0 - A B C -1 - 0 0 D 0 - *- * @param left - * @param right - * @param bottom - * @param top - * @param zNear - * @param zFar - * @return this matrix for chaining - * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear} - * or {@code left == right}, or {@code bottom == top}. - */ - public Matrix4f setToFrustum(final float left, final float right, - final float bottom, final float top, - final float zNear, final float zFar) throws IllegalArgumentException { - if( zNear <= 0.0f || zFar <= zNear ) { - throw new IllegalArgumentException("Requirements zNear > 0 and zFar > zNear, but zNear "+zNear+", zFar "+zFar); - } - if( left == right || top == bottom) { - throw new IllegalArgumentException("GL_INVALID_VALUE: top,bottom and left,right must not be equal"); - } - { - // m00 = m11 = m22 = m33 = 1f; - m10 = m20 = m30 = 0f; - m01 = m21 = m31 = 0f; - m03 = m13 = 0f; - } - final float zNear2 = 2.0f*zNear; - final float dx=right-left; - final float dy=top-bottom; - final float dz=zFar-zNear; - final float A=(right+left)/dx; - final float B=(top+bottom)/dy; - final float C=-1.0f*(zFar+zNear)/dz; - final float D=-2.0f*(zFar*zNear)/dz; - - m00 = zNear2/dx; - m11 = zNear2/dy; - - m02 = A; - m12 = B; - m22 = C; - m32 = -1.0f; - - m23 = D; - m33 = 0f; - - return this; - } - - /** - * Set this matrix to perspective {@link #setToFrustum(float, float, float, float, float, float) frustum} projection. - * - * @param fovy_rad angle in radians - * @param aspect aspect ratio width / height - * @param zNear - * @param zFar - * @return this matrix for chaining - * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear} - * @see #setToFrustum(float, float, float, float, float, float) - */ - public Matrix4f setToPerspective(final float fovy_rad, final float aspect, final float zNear, final float zFar) throws IllegalArgumentException { - final float top = FloatUtil.tan(fovy_rad/2f) * zNear; // use tangent of half-fov ! - final float bottom = -1.0f * top; // -1f * fovhvTan.top * zNear - final float left = aspect * bottom; // aspect * -1f * fovhvTan.top * zNear - final float right = aspect * top; // aspect * fovhvTan.top * zNear - return setToFrustum(left, right, bottom, top, zNear, zFar); - } - - /** - * Set this matrix to perspective {@link #setToFrustum(float, float, float, float, float, float) frustum} projection. - * - * @param fovhv {@link FovHVHalves} field of view in both directions, may not be centered, either in radians or tangent - * @param zNear - * @param zFar - * @return this matrix for chaining - * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear} - * @see #setToFrustum(float, float, float, float, float, float) - * @see Frustum#updateByFovDesc(Matrix4f, com.jogamp.opengl.math.geom.Frustum.FovDesc) - */ - public Matrix4f setToPerspective(final FovHVHalves fovhv, final float zNear, final float zFar) throws IllegalArgumentException { - final FovHVHalves fovhvTan = fovhv.toTangents(); // use tangent of half-fov ! - final float top = fovhvTan.top * zNear; - final float bottom = -1.0f * fovhvTan.bottom * zNear; - final float left = -1.0f * fovhvTan.left * zNear; - final float right = fovhvTan.right * zNear; - return setToFrustum(left, right, bottom, top, zNear, zFar); - } - - /** - * Calculate the frustum planes in world coordinates - * using this premultiplied P*MV (column major order) matrix. - *
- * Frustum plane's normals will point to the inside of the viewing frustum, - * as required by this class. - *
- *- * Usually called by {@link Frustum#updateFrustumPlanes(Matrix4f)}. - *
- */ - public void updateFrustumPlanes(final Frustum frustum) { - // Left: a = m41 + m11, b = m42 + m12, c = m43 + m13, d = m44 + m14 - [1..4] column-major - // Left: a = m30 + m00, b = m31 + m01, c = m32 + m02, d = m33 + m03 - [0..3] column-major - { - final Frustum.Plane p = frustum.getPlanes()[Frustum.LEFT]; - final Vec3f p_n = p.n; - p_n.set( m30 + m00, - m31 + m01, - m32 + m02 ); - p.d = m33 + m03; - } - - // Right: a = m41 - m11, b = m42 - m12, c = m43 - m13, d = m44 - m14 - [1..4] column-major - // Right: a = m30 - m00, b = m31 - m01, c = m32 - m02, d = m33 - m03 - [0..3] column-major - { - final Frustum.Plane p = frustum.getPlanes()[Frustum.RIGHT]; - final Vec3f p_n = p.n; - p_n.set( m30 - m00, - m31 - m01, - m32 - m02 ); - p.d = m33 - m03; - } - - // Bottom: a = m41m21, b = m42m22, c = m43m23, d = m44m24 - [1..4] column-major - // Bottom: a = m30m10, b = m31m11, c = m32m12, d = m33m13 - [0..3] column-major - { - final Frustum.Plane p = frustum.getPlanes()[Frustum.BOTTOM]; - final Vec3f p_n = p.n; - p_n.set( m30 + m10, - m31 + m11, - m32 + m12 ); - p.d = m33 + m13; - } - - // Top: a = m41 - m21, b = m42 - m22, c = m43 - m23, d = m44 - m24 - [1..4] column-major - // Top: a = m30 - m10, b = m31 - m11, c = m32 - m12, d = m33 - m13 - [0..3] column-major - { - final Frustum.Plane p = frustum.getPlanes()[Frustum.TOP]; - final Vec3f p_n = p.n; - p_n.set( m30 - m10, - m31 - m11, - m32 - m12 ); - p.d = m33 - m13; - } - - // Near: a = m41m31, b = m42m32, c = m43m33, d = m44m34 - [1..4] column-major - // Near: a = m30m20, b = m31m21, c = m32m22, d = m33m23 - [0..3] column-major - { - final Frustum.Plane p = frustum.getPlanes()[Frustum.NEAR]; - final Vec3f p_n = p.n; - p_n.set( m30 + m20, - m31 + m21, - m32 + m22 ); - p.d = m33 + m23; - } - - // Far: a = m41 - m31, b = m42 - m32, c = m43 - m33, d = m44 - m34 - [1..4] column-major - // Far: a = m30 - m20, b = m31 - m21, c = m32m22, d = m33m23 - [0..3] column-major - { - final Frustum.Plane p = frustum.getPlanes()[Frustum.FAR]; - final Vec3f p_n = p.n; - p_n.set( m30 - m20, - m31 - m21, - m32 - m22 ); - p.d = m33 - m23; - } - - // Normalize all planes - for (int i = 0; i < 6; ++i) { - final Plane p = frustum.getPlanes()[i]; - final Vec3f p_n = p.n; - final float invLen = 1f / p_n.length(); - p_n.scale(invLen); - p.d *= invLen; - } - } - - /** - * Set this matrix to the look-at matrix based on given parameters. - *- * Consist out of two matrix multiplications: - *
- * R = L x T, - * with L for look-at matrix and - * T for eye translation. - * - * Result R can be utilized for projection or modelview multiplication, i.e. - * M = M x R, - * with M being the projection or modelview matrix. - *- * - * @param eye 3 component eye vector - * @param center 3 component center vector - * @param up 3 component up vector - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public Matrix4f setToLookAt(final Vec3f eye, final Vec3f center, final Vec3f up, final Matrix4f tmp) { - // normalized forward! - final Vec3f fwd = new Vec3f( center.x() - eye.x(), - center.y() - eye.y(), - center.z() - eye.z() ).normalize(); - - /* Side = forward x up, normalized */ - final Vec3f side = fwd.cross(up).normalize(); - - /* Recompute up as: up = side x forward */ - final Vec3f up2 = side.cross(fwd); - - m00 = side.x(); - m10 = up2.x(); - m20 = -fwd.x(); - m30 = 0; - - m01 = side.y(); - m11 = up2.y(); - m21 = -fwd.y(); - m31 = 0; - - m02 = side.z(); - m12 = up2.z(); - m22 = -fwd.z(); - m32 = 0; - - m03 = 0; - m13 = 0; - m23 = 0; - m33 = 1; - - return mul( tmp.setToTranslation( -eye.x(), -eye.y(), -eye.z() ) ); - } - - /** - * Set this matrix to the pick matrix based on given parameters. - *
- * Traditional gluPickMatrix
implementation.
- *
- * Consist out of two matrix multiplications: - *
- * R = T x S, - * with T for viewport translation matrix and - * S for viewport scale matrix. - * - * Result R can be utilized for projection multiplication, i.e. - * P = P x R, - * with P being the projection matrix. - *- * - *
- * To effectively use the generated pick matrix for picking, - * call {@link #setToPick(float, float, float, float, Recti, Matrix4f) setToPick(..)} - * and multiply a {@link #setToPerspective(float, float, float, float) custom perspective matrix} - * by this pick matrix. Then you may load the result onto the perspective matrix stack. - *
- * @param x the center x-component of a picking region in window coordinates - * @param y the center y-component of a picking region in window coordinates - * @param deltaX the width of the picking region in window coordinates. - * @param deltaY the height of the picking region in window coordinates. - * @param viewport Rect4i viewport - * @param mat4Tmp temp storage - * @return this matrix for chaining or {@code null} if either delta value is <= zero. - */ - public Matrix4f setToPick(final float x, final float y, final float deltaX, final float deltaY, - final Recti viewport, final Matrix4f mat4Tmp) { - if (deltaX <= 0 || deltaY <= 0) { - return null; - } - /* Translate and scale the picked region to the entire window */ - setToTranslation( ( viewport.width() - 2 * ( x - viewport.x() ) ) / deltaX, - ( viewport.height() - 2 * ( y - viewport.y() ) ) / deltaY, - 0); - mat4Tmp.setToScale( viewport.width() / deltaX, viewport.height() / deltaY, 1.0f ); - return mul(mat4Tmp); - } - - // - // Matrix affine operations using setTo..() - // - - /** - * Rotate this matrix about give axis and angle in radians, i.e. multiply by {@link #setToRotationAxis(float, float, float, float) axis-rotation matrix}. - * @see Matrix-FAQ Q38 - * @param angrad angle in radians - * @param x x of rotation axis - * @param y y of rotation axis - * @param z z of rotation axis - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public final Matrix4f rotate(final float ang_rad, final float x, final float y, final float z, final Matrix4f tmp) { - return mul( tmp.setToRotationAxis(ang_rad, x, y, z) ); - } - - /** - * Rotate this matrix about give axis and angle in radians, i.e. multiply by {@link #setToRotationAxis(float, Vec3f) axis-rotation matrix}. - * @see Matrix-FAQ Q38 - * @param angrad angle in radians - * @param axis rotation axis - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public final Matrix4f rotate(final float ang_rad, final Vec3f axis, final Matrix4f tmp) { - return mul( tmp.setToRotationAxis(ang_rad, axis) ); - } - - /** - * Rotate this matrix with the given {@link Quaternion}, i.e. multiply by {@link #setToRotation(Quaternion) Quaternion's rotation matrix}. - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public final Matrix4f rotate(final Quaternion quat, final Matrix4f tmp) { - return mul( tmp.setToRotation(quat) ); - } - - /** - * Translate this matrix, i.e. multiply by {@link #setToTranslation(float, float, float) translation matrix}. - * @param x x translation - * @param y y translation - * @param z z translation - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public final Matrix4f translate(final float x, final float y, final float z, final Matrix4f tmp) { - return mul( tmp.setToTranslation(x, y, z) ); - } - - /** - * Translate this matrix, i.e. multiply by {@link #setToTranslation(Vec3f) translation matrix}. - * @param t translation Vec3f - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public final Matrix4f translate(final Vec3f t, final Matrix4f tmp) { - return mul( tmp.setToTranslation(t) ); - } - - /** - * Scale this matrix, i.e. multiply by {@link #setToScale(float, float, float) scale matrix}. - * @param x x scale - * @param y y scale - * @param z z scale - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public final Matrix4f scale(final float x, final float y, final float z, final Matrix4f tmp) { - return mul( tmp.setToScale(x, y, z) ); - } - - /** - * Scale this matrix, i.e. multiply by {@link #setToScale(float, float, float) scale matrix}. - * @param s scale for x-, y- and z-axis - * @param tmp temporary Matrix4f used for multiplication - * @return this matrix for chaining - */ - public final Matrix4f scale(final float s, final Matrix4f tmp) { - return mul( tmp.setToScale(s, s, s) ); - } - - // - // Matrix Stack - // - - /** - * Push the matrix to it's stack, while preserving this matrix values. - * @see #pop() - */ - public final void push() { - stack.push(this); - } - - /** - * Pop the current matrix from it's stack, replacing this matrix values. - * @see #push() - */ - public final void pop() { - stack.pop(this); - } - - // - // equals - // - - /** - * Equals check using a given {@link FloatUtil#EPSILON} value and {@link FloatUtil#isEqual(float, float, float)}. - *- * Implementation considers following corner cases: - *
- * Implementation considers following corner cases: - *
- * Traditional gluProject
implementation.
- *
- * Traditional gluProject
implementation.
- *
- * Traditional gluUnProject
implementation.
- *
- * Traditional gluUnProject
implementation.
- *
- * Traditional gluUnProject
implementation.
- *
- * Traditional gluUnProject4
implementation.
- *
- * Traditional gluUnProject4
implementation.
- *
- * Notes for picking winz0 and winz1: - *
- * Notes for picking winz0 and winz1: - *
0
- * in which case an {@link IndexOutOfBoundsException} is thrown.
- */
- public Stack(final int initialSize, final int growSize) {
- this.position = 0;
- this.growSize = growSize;
- this.buffer = new float[initialSize];
- }
-
- private final void growIfNecessary(final int length) throws IndexOutOfBoundsException {
- if( position + length > buffer.length ) {
- if( 0 >= growSize ) {
- throw new IndexOutOfBoundsException("Out of fixed stack size: "+this);
- }
- final float[] newBuffer =
- new float[buffer.length + growSize];
- System.arraycopy(buffer, 0, newBuffer, 0, position);
- buffer = newBuffer;
- }
- }
-
- public final Matrix4f push(final Matrix4f src) throws IndexOutOfBoundsException {
- growIfNecessary(16);
- src.get(buffer, position);
- position += 16;
- return src;
- }
-
- public final Matrix4f pop(final Matrix4f dest) throws IndexOutOfBoundsException {
- position -= 16;
- dest.load(buffer, position);
- return dest;
- }
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java b/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java
deleted file mode 100644
index 0d04c69cc..000000000
--- a/src/jogl/classes/com/jogamp/opengl/math/Quaternion.java
+++ /dev/null
@@ -1,1188 +0,0 @@
-/**
- * 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:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-package com.jogamp.opengl.math;
-
-/**
- * Quaternion implementation supporting
- * Gimbal-Lock free rotations.
- * - * All matrix operation provided are in column-major order, - * as specified in the OpenGL fixed function pipeline, i.e. compatibility profile. - * See {@link FloatUtil}. - *
- *- * See Matrix-FAQ - *
- *- * See euclideanspace.com-Quaternion - *
- */ -public class Quaternion { - private float x, y, z, w; - - /** - * Quaternion Epsilon, used with equals method to determine if two Quaternions are close enough to be considered equal. - *- * Using {@value}, which is ~10 times {@link FloatUtil#EPSILON}. - *
- */ - public static final float ALLOWED_DEVIANCE = 1.0E-6f; // FloatUtil.EPSILON == 1.1920929E-7f; double ALLOWED_DEVIANCE: 1.0E-8f - - public Quaternion() { - x = y = z = 0; w = 1; - } - - public Quaternion(final Quaternion q) { - set(q); - } - - public Quaternion(final float x, final float y, final float z, final float w) { - set(x, y, z, w); - } - - /** - * See {@link #magnitude()} for special handling of {@link FloatUtil#EPSILON epsilon}, - * which is not applied here. - * @return the squared magnitude of this quaternion. - */ - public final float magnitudeSquared() { - return w*w + x*x + y*y + z*z; - } - - /** - * Return the magnitude of this quaternion, i.e. sqrt({@link #magnitudeSquared()}) - *- * A magnitude of zero shall equal {@link #isIdentity() identity}, - * as performed by {@link #normalize()}. - *
- *- * Implementation Details: - *
true
if this quaternion has identity.
- * - * Implementation uses {@link FloatUtil#EPSILON epsilon} to compare - * {@link #w() W} {@link FloatUtil#isEqual(float, float) against 1f} and - * {@link #x() X}, {@link #y() Y} and {@link #z() Z} - * {@link FloatUtil#isZero(float) against zero}. - *
- */ - public final boolean isIdentity() { - return FloatUtil.isEqual(1f, w) && VectorUtil.isZero(x, y, z); - // return w == 1f && x == 0f && y == 0f && z == 0f; - } - - /*** - * Set this quaternion to identity (x=0,y=0,z=0,w=1) - * @return this quaternion for chaining. - */ - public final Quaternion setIdentity() { - x = y = z = 0f; w = 1f; - return this; - } - - /** - * Normalize a quaternion required if to be used as a rotational quaternion. - *- * Implementation Details: - *
[-x, -y, -z, w]
.
- * @return this quaternion for chaining.
- * @see Matrix-FAQ Q49
- */
- public Quaternion conjugate() {
- x = -x;
- y = -y;
- z = -z;
- return this;
- }
-
- /**
- * Invert the quaternion If rotational, will produce a the inverse rotation
- * - * Implementation Details: - *
- * The axis must be a normalized vector. - *
- *- * A rotational quaternion is made from the given angle and axis. - *
- * - * @param angle in radians - * @param axisX x-coord of rotation axis - * @param axisY y-coord of rotation axis - * @param axisZ z-coord of rotation axis - * @return this quaternion for chaining. - */ - public Quaternion rotateByAngleNormalAxis(final float angle, final float axisX, final float axisY, final float axisZ) { - if( VectorUtil.isZero(axisX, axisY, axisZ, FloatUtil.EPSILON) ) { - // no change - return this; - } - final float halfAngle = 0.5f * angle; - final float sin = FloatUtil.sin(halfAngle); - final float qw = FloatUtil.cos(halfAngle); - final float qx = sin * axisX; - final float qy = sin * axisY; - final float qz = sin * axisZ; - return set( x * qw + y * qz - z * qy + w * qx, - -x * qz + y * qw + z * qx + w * qy, - x * qy - y * qx + z * qw + w * qz, - -x * qx - y * qy - z * qz + w * qw); - } - - /** - * Rotate this quaternion by the given angle and axis. - *- * The axis must be a normalized vector. - *
- *- * A rotational quaternion is made from the given angle and axis. - *
- * - * @param angle in radians - * @param axis Vec3f coord of rotation axis - * @return this quaternion for chaining. - */ - public Quaternion rotateByAngleNormalAxis(final float angle, final Vec3f axis) { - return rotateByAngleNormalAxis(angle, axis.x(), axis.y(), axis.z()); - } - - /** - * Rotate this quaternion around X axis with the given angle in radians - * - * @param angle in radians - * @return this quaternion for chaining. - */ - public Quaternion rotateByAngleX(final float angle) { - final float halfAngle = 0.5f * angle; - final float sin = FloatUtil.sin(halfAngle); - final float cos = FloatUtil.cos(halfAngle); - return set( x * cos + w * sin, - y * cos + z * sin, - -y * sin + z * cos, - -x * sin + w * cos); - } - - /** - * Rotate this quaternion around Y axis with the given angle in radians - * - * @param angle in radians - * @return this quaternion for chaining. - */ - public Quaternion rotateByAngleY(final float angle) { - final float halfAngle = 0.5f * angle; - final float sin = FloatUtil.sin(halfAngle); - final float cos = FloatUtil.cos(halfAngle); - return set( x * cos - z * sin, - y * cos + w * sin, - x * sin + z * cos, - -y * sin + w * cos); - } - - /** - * Rotate this quaternion around Z axis with the given angle in radians - * - * @param angle in radians - * @return this quaternion for chaining. - */ - public Quaternion rotateByAngleZ(final float angle) { - final float halfAngle = 0.5f * angle; - final float sin = FloatUtil.sin(halfAngle); - final float cos = FloatUtil.cos(halfAngle); - return set( x * cos + y * sin, - -x * sin + y * cos, - z * cos + w * sin, - -z * sin + w * cos); - } - - /** - * Rotates this quaternion from the given Euler rotation arrayangradXYZ
in radians.
- *
- * The angradXYZ
array is laid out in natural order:
- *
- * The rotations are applied in the given order and using chained rotation per axis: - *
- * Implementation Details: - *
- * Note: Method does not normalize this quaternion! - *
- * - * @param a start quaternion - * @param b end quaternion - * @param changeAmnt float between 0 and 1 representing interpolation. - * @return this quaternion for chaining. - * @see euclideanspace.com-QuaternionSlerp - */ - public final Quaternion setSlerp(final Quaternion a, final Quaternion b, final float changeAmnt) { - // System.err.println("Slerp.0: A "+a+", B "+b+", t "+changeAmnt); - if (changeAmnt == 0.0f) { - set(a); - } else if (changeAmnt == 1.0f) { - set(b); - } else { - float bx = b.x; - float by = b.y; - float bz = b.z; - float bw = b.w; - - // Calculate angle between them (quat dot product) - float cosHalfTheta = a.x * bx + a.y * by + a.z * bz + a.w * bw; - - final float scale0, scale1; - - if( cosHalfTheta >= 0.95f ) { - // quaternions are close, just use linear interpolation - scale0 = 1.0f - changeAmnt; - scale1 = changeAmnt; - // System.err.println("Slerp.1: Linear Interpol; cosHalfTheta "+cosHalfTheta); - } else if ( cosHalfTheta <= -0.99f ) { - // the quaternions are nearly opposite, - // we can pick any axis normal to a,b to do the rotation - scale0 = 0.5f; - scale1 = 0.5f; - // System.err.println("Slerp.2: Any; cosHalfTheta "+cosHalfTheta); - } else { - // System.err.println("Slerp.3: cosHalfTheta "+cosHalfTheta); - if( cosHalfTheta <= -FloatUtil.EPSILON ) { // FIXME: .. or shall we use the upper bound 'cosHalfTheta < FloatUtil.EPSILON' ? - // Negate the second quaternion and the result of the dot product (Inversion) - bx *= -1f; - by *= -1f; - bz *= -1f; - bw *= -1f; - cosHalfTheta *= -1f; - // System.err.println("Slerp.4: Inverted cosHalfTheta "+cosHalfTheta); - } - final float halfTheta = FloatUtil.acos(cosHalfTheta); - final float sinHalfTheta = FloatUtil.sqrt(1.0f - cosHalfTheta*cosHalfTheta); - // if theta = 180 degrees then result is not fully defined - // we could rotate around any axis normal to qa or qb - if ( Math.abs(sinHalfTheta) < 0.001f ){ // fabs is floating point absolute - scale0 = 0.5f; - scale1 = 0.5f; - // throw new InternalError("XXX"); // FIXME should not be reached due to above inversion ? - } else { - // Calculate the scale for q1 and q2, according to the angle and - // it's sine value - scale0 = FloatUtil.sin((1f - changeAmnt) * halfTheta) / sinHalfTheta; - scale1 = FloatUtil.sin(changeAmnt * halfTheta) / sinHalfTheta; - } - } - - x = a.x * scale0 + bx * scale1; - y = a.y * scale0 + by * scale1; - z = a.z * scale0 + bz * scale1; - w = a.w * scale0 + bw * scale1; - } - // System.err.println("Slerp.X: Result "+this); - return this; - } - - /** - * Set this quaternion to equal the rotation required - * to point the z-axis at direction and the y-axis to up. - *
- * Implementation generates a 3x3 matrix
- * and is equal with ProjectFloat's lookAt(..).
- *
- * q = (s,v) = (v1•v2 , v1 × v2), - * angle = angle(v1, v2) = v1•v2 - * axis = normal(v1 x v2) - *- *
- * Implementation Details: - *
- * q = (s,v) = (v1•v2 , v1 × v2), - * angle = angle(v1, v2) = v1•v2 - * axis = v1 x v2 - *- *
- * Implementation Details: - *
- * Implementation Details: - *
- * Implementation Details: - *
angradXYZ
in radians.
- *
- * The angradXYZ
vector is laid out in natural order:
- *
- * The rotations are applied in the given order: - *
- * Implementation Details: - *
- * The result
array is laid out in natural order:
- *
- * See Graphics Gems Code,
- * MatrixTrace.
- *
- * Buggy Matrix-FAQ Q55 - *
- * - * @return this quaternion for chaining. - * @see #setFromMatrix(Matrix4f) - */ - public Quaternion setFromMatrix(final float m00, final float m01, final float m02, - final float m10, final float m11, final float m12, - final float m20, final float m21, final float m22) { - // Note: Other implementations uses 'T' w/o '+1f' and compares 'T >= 0' while adding missing 1f in sqrt expr. - // However .. this causes setLookAt(..) to fail and actually violates the 'trace definition'. - - // The trace T is the sum of the diagonal elements; see - // http://mathworld.wolfram.com/MatrixTrace.html - final float T = m00 + m11 + m22 + 1f; - // System.err.println("setFromMatrix.0 T "+T+", m00 "+m00+", m11 "+m11+", m22 "+m22); - if ( T > 0f ) { - // System.err.println("setFromMatrix.1"); - final float S = 0.5f / FloatUtil.sqrt(T); // S = 1 / ( 2 t ) - w = 0.25f / S; // w = 1 / ( 4 S ) = t / 2 - x = ( m21 - m12 ) * S; - y = ( m02 - m20 ) * S; - z = ( m10 - m01 ) * S; - } else if ( m00 > m11 && m00 > m22) { - // System.err.println("setFromMatrix.2"); - final float S = 0.5f / FloatUtil.sqrt(1.0f + m00 - m11 - m22); // S=4*qx - w = ( m21 - m12 ) * S; - x = 0.25f / S; - y = ( m10 + m01 ) * S; - z = ( m02 + m20 ) * S; - } else if ( m11 > m22 ) { - // System.err.println("setFromMatrix.3"); - final float S = 0.5f / FloatUtil.sqrt(1.0f + m11 - m00 - m22); // S=4*qy - w = ( m02 - m20 ) * S; - x = ( m20 + m01 ) * S; - y = 0.25f / S; - z = ( m21 + m12 ) * S; - } else { - // System.err.println("setFromMatrix.3"); - final float S = 0.5f / FloatUtil.sqrt(1.0f + m22 - m00 - m11); // S=4*qz - w = ( m10 - m01 ) * S; - x = ( m02 + m20 ) * S; - y = ( m21 + m12 ) * S; - z = 0.25f / S; - } - return this; - } - - /** - * Compute the quaternion from a 3x3 column rotation matrix - *
- * See Graphics Gems Code,
- * MatrixTrace.
- *
- * Buggy Matrix-FAQ Q55 - *
- * - * @return this quaternion for chaining. - * @see Matrix4f#getRotation(Quaternion) - * @see #setFromMatrix(float, float, float, float, float, float, float, float, float) - */ - public Quaternion setFromMatrix(final Matrix4f m) { - return m.getRotation(this); - } - - /** - * Transform this quaternion to a normalized 4x4 column matrix representing the rotation. - *- * Implementation Details: - *
- * Implementation Details: - *
- * No validation whether the axes are orthogonal is performed. - *
- * - * @param xAxis vector representing the orthogonal x-axis of the coordinate system. - * @param yAxis vector representing the orthogonal y-axis of the coordinate system. - * @param zAxis vector representing the orthogonal z-axis of the coordinate system. - * @return this quaternion for chaining. - */ - public final Quaternion setFromAxes(final Vec3f xAxis, final Vec3f yAxis, final Vec3f zAxis) { - return setFromMatrix(xAxis.x(), yAxis.x(), zAxis.x(), - xAxis.y(), yAxis.y(), zAxis.y(), - xAxis.z(), yAxis.z(), zAxis.z()); - } - - /** - * Extracts this quaternion's orthogonal rotation axes. - * - * @param xAxis vector representing the orthogonal x-axis of the coordinate system. - * @param yAxis vector representing the orthogonal y-axis of the coordinate system. - * @param zAxis vector representing the orthogonal z-axis of the coordinate system. - * @param tmpMat4 temporary float[4] matrix, used to transform this quaternion to a matrix. - */ - public void toAxes(final Vec3f xAxis, final Vec3f yAxis, final Vec3f zAxis, final Matrix4f tmpMat4) { - tmpMat4.setToRotation(this); - tmpMat4.getColumn(2, zAxis); - tmpMat4.getColumn(1, yAxis); - tmpMat4.getColumn(0, xAxis); - } - - /** - * Check if the the 3x3 matrix (param) is in fact an affine rotational - * matrix - * - * @param m 3x3 column matrix - * @return true if representing a rotational matrix, false otherwise - */ - @Deprecated - public final boolean isRotationMatrix3f(final float[] m) { - final float epsilon = 0.01f; // margin to allow for rounding errors - if (Math.abs(m[0] * m[3] + m[3] * m[4] + m[6] * m[7]) > epsilon) - return false; - if (Math.abs(m[0] * m[2] + m[3] * m[5] + m[6] * m[8]) > epsilon) - return false; - if (Math.abs(m[1] * m[2] + m[4] * m[5] + m[7] * m[8]) > epsilon) - return false; - if (Math.abs(m[0] * m[0] + m[3] * m[3] + m[6] * m[6] - 1) > epsilon) - return false; - if (Math.abs(m[1] * m[1] + m[4] * m[4] + m[7] * m[7] - 1) > epsilon) - return false; - if (Math.abs(m[2] * m[2] + m[5] * m[5] + m[8] * m[8] - 1) > epsilon) - return false; - return (Math.abs(determinant3f(m) - 1) < epsilon); - } - - @Deprecated - private final float determinant3f(final float[] m) { - return m[0] * m[4] * m[8] + m[3] * m[7] * m[2] + m[6] * m[1] * m[5] - - m[0] * m[7] * m[5] - m[3] * m[1] * m[8] - m[6] * m[4] * m[2]; - } - - // - // std java overrides - // - - /** - * @param o the object to compare for equality - * @return true if this quaternion and the provided quaternion have roughly the same x, y, z and w values. - */ - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Quaternion)) { - return false; - } - final Quaternion comp = (Quaternion) o; - return Math.abs(x - comp.x()) <= ALLOWED_DEVIANCE && - Math.abs(y - comp.y()) <= ALLOWED_DEVIANCE && - Math.abs(z - comp.z()) <= ALLOWED_DEVIANCE && - Math.abs(w - comp.w()) <= ALLOWED_DEVIANCE; - } - @Override - public final int hashCode() { - throw new InternalError("hashCode not designed"); - } - - @Override - public String toString() { - return "Quat[x "+x+", y "+y+", z "+z+", w "+w+"]"; - } -} diff --git a/src/jogl/classes/com/jogamp/opengl/math/Ray.java b/src/jogl/classes/com/jogamp/opengl/math/Ray.java deleted file mode 100644 index 25a7d9a70..000000000 --- a/src/jogl/classes/com/jogamp/opengl/math/Ray.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright 2014-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: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.opengl.math; - -import com.jogamp.opengl.math.geom.AABBox; - -/** - * Simple compound denoting a ray. - *- * A ray, also known as a half line, consists out of it's origin - * and direction. Hence it is bound to only the origin side, - * where the other end is +infinitive. - *
- * R(t) = R0 + Rd * t with R0 origin, Rd direction and t > 0.0 - *- * - *
- * A {@link Ray} maybe used for picking - * using a {@link AABBox bounding box} via - * {@link AABBox#intersectsRay(Ray) fast probe} or - * {@link AABBox#getRayIntersection(float[], Ray, float, boolean, float[], float[], float[]) returning the intersection}. - *
- */ -public class Ray { - /** Origin of Ray. */ - public final Vec3f orig = new Vec3f(); - - /** Normalized direction vector of ray. */ - public final Vec3f dir = new Vec3f(); - - @Override - public String toString() { - return "Ray[orig["+orig+"], dir["+dir+"]]"; - } -} \ No newline at end of file diff --git a/src/jogl/classes/com/jogamp/opengl/math/Recti.java b/src/jogl/classes/com/jogamp/opengl/math/Recti.java deleted file mode 100644 index 58f5e5e77..000000000 --- a/src/jogl/classes/com/jogamp/opengl/math/Recti.java +++ /dev/null @@ -1,134 +0,0 @@ -/** - * Copyright 2022-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: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.math; - -/** - * Rectangle with x, y, width and height integer components. - */ -public final class Recti { - private int x; - private int y; - private int width; - private int height; - - public Recti() {} - - public Recti(final Recti o) { - set(o); - } - - public Recti copy() { - return new Recti(this); - } - - public Recti(final int[/*4*/] xywh) { - set(xywh); - } - - public Recti(final int x, final int y, final int width, final int height) { - set(x, y, width, height); - } - - /** this = o, returns this. */ - public void set(final Recti o) { - this.x = o.x; - this.y = o.y; - this.width = o.width; - this.height= o.height; - } - - /** this = { x, y, width, height }, returns this. */ - public void set(final int x, final int y, final int width, final int height) { - this.x = x; - this.y = y; - this.width = width; - this.height= height; - } - - /** this = xywh, returns this. */ - public Recti set(final int[/*2*/] xywh) { - this.x = xywh[0]; - this.y = xywh[1]; - this.width = xywh[2]; - this.height= xywh[3]; - return this; - } - - /** xywh = this, returns xy. */ - public int[] get(final int[/*4*/] xywh) { - xywh[0] = this.x; - xywh[1] = this.y; - xywh[2] = this.width; - xywh[3] = this.height; - return xywh; - } - - public int x() { return x; } - public int y() { return y; } - public int width() { return width; } - public int height() { return height; } - - public void setX(final int x) { this.x = x; } - public void setY(final int y) { this.y = y; } - public void setWidth(final int width) { this.width = width; } - public void setHeight(final int height) { this.height = height; } - - /** Return true if all components are zero. */ - public boolean isZero() { - return 0 == x && 0 == y; - } - - /** - * Equals check. - * @param o comparison value - * @return true if all components are equal - */ - public boolean isEqual(final Recti o) { - if( this == o ) { - return true; - } else { - return x == o.x && y == o.y && - width == o.width && height == o.height; - } - } - - @Override - public boolean equals(final Object o) { - if( o instanceof Recti ) { - return isEqual((Recti)o); - } else { - return false; - } - } - - @Override - public String toString() { - return x + " / " + y + " " + width + " x " + height; - } -} diff --git a/src/jogl/classes/com/jogamp/opengl/math/Vec2f.java b/src/jogl/classes/com/jogamp/opengl/math/Vec2f.java deleted file mode 100644 index f504b960b..000000000 --- a/src/jogl/classes/com/jogamp/opengl/math/Vec2f.java +++ /dev/null @@ -1,385 +0,0 @@ -/** - * Copyright 2022-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: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.math; - -/** - * 2D Vector based upon two float components. - * - * Implementation borrowed from [gfxbox2](https://jausoft.com/cgit/cs_class/gfxbox2.git/tree/include/pixel/pixel2f.hpp#n29) - * and its data layout from JOAL's Vec3f. - */ -public final class Vec2f { - private float x; - private float y; - - public static Vec2f from_length_angle(final float magnitude, final float radians) { - return new Vec2f((float)(magnitude * Math.cos(radians)), (float)(magnitude * Math.sin(radians))); - } - - public Vec2f() {} - - public Vec2f(final Vec2f o) { - set(o); - } - - /** Creating new Vec2f using Vec3f, dropping z. */ - public Vec2f(final Vec3f o) { - set(o); - } - - public Vec2f copy() { - return new Vec2f(this); - } - - public Vec2f(final float[/*2*/] xy) { - set(xy); - } - - public Vec2f(final float x, final float y) { - set(x, y); - } - - /** this = o, returns this. */ - public void set(final Vec2f o) { - this.x = o.x; - this.y = o.y; - } - - /** this = o while dropping z, returns this. */ - public void set(final Vec3f o) { - this.x = o.x(); - this.y = o.y(); - } - - /** this = { x, y }, returns this. */ - public void set(final float x, final float y) { - this.x = x; - this.y = y; - } - - /** this = xy, returns this. */ - public Vec2f set(final float[/*2*/] xy) { - this.x = xy[0]; - this.y = xy[1]; - return this; - } - - /** Sets the ith component, 0 <= i < 2 */ - public void set(final int i, final float val) { - switch (i) { - case 0: x = val; break; - case 1: y = val; break; - default: throw new IndexOutOfBoundsException(); - } - } - - /** xy = this, returns xy. */ - public float[] get(final float[/*2*/] xy) { - xy[0] = this.x; - xy[1] = this.y; - return xy; - } - - /** Gets the ith component, 0 <= i < 2 */ - public float get(final int i) { - switch (i) { - case 0: return x; - case 1: return y; - default: throw new IndexOutOfBoundsException(); - } - } - - public float x() { return x; } - public float y() { return y; } - - public void setX(final float x) { this.x = x; } - public void setY(final float y) { this.y = y; } - - /** this = max(this, m), returns this. */ - public Vec2f max(final Vec2f m) { - this.x = Math.max(this.x, m.x); - this.y = Math.max(this.y, m.y); - return this; - } - /** this = min(this, m), returns this. */ - public Vec2f min(final Vec2f m) { - this.x = Math.min(this.x, m.x); - this.y = Math.min(this.y, m.y); - return this; - } - - /** Returns this * val; creates new vector */ - public Vec2f mul(final float val) { - return new Vec2f(this).scale(val); - } - - /** this = a * b, returns this. */ - public Vec2f mul(final Vec2f a, final Vec2f b) { - x = a.x * b.x; - y = a.y * b.y; - return this; - } - - /** this = this * s, returns this. */ - public Vec2f scale(final float s) { - x *= s; - y *= s; - return this; - } - - /** this = this * { sx, sy }, returns this. */ - public Vec2f scale(final float sx, final float sy) { - x *= sx; - y *= sy; - return this; - } - - /** this = this * { s.x, s.y }, returns this. */ - public Vec2f scale(final Vec2f s) { return scale(s.x, s.y); } - - /** Returns this + arg; creates new vector */ - public Vec2f plus(final Vec2f arg) { - return new Vec2f(this).add(arg); - } - - /** this = a + b, returns this. */ - public Vec2f plus(final Vec2f a, final Vec2f b) { - x = a.x + b.x; - y = a.y + b.y; - return this; - } - - /** this = this + { dx, dy }, returns this. */ - public Vec2f add(final float dx, final float dy) { - x += dx; - y += dy; - return this; - } - - /** this = this + b, returns this. */ - public Vec2f add(final Vec2f b) { - x += b.x; - y += b.y; - return this; - } - - /** Returns this - arg; creates new vector */ - public Vec2f minus(final Vec2f arg) { - return new Vec2f(this).sub(arg); - } - - /** this = a - b, returns this. */ - public Vec2f minus(final Vec2f a, final Vec2f b) { - x = a.x - b.x; - y = a.y - b.y; - return this; - } - - /** this = this - b, returns this. */ - public Vec2f sub(final Vec2f b) { - x -= b.x; - y -= b.y; - return this; - } - - /** Return true if all components are zero, i.e. it's absolute value < {@link #EPSILON}. */ - public boolean isZero() { - return FloatUtil.isZero(x) && FloatUtil.isZero(y); - } - - public void rotate(final float radians, final Vec2f ctr) { - final float cos = (float)Math.cos(radians); - final float sin = (float)Math.sin(radians); - rotate(sin, cos, ctr); - } - - public void rotate(final float sin, final float cos, final Vec2f ctr) { - final float x0 = x - ctr.x; - final float y0 = y - ctr.y; - final float tmp = x0 * cos - y0 * sin + ctr.x; - y = x0 * sin + y0 * cos + ctr.y; - x = tmp; - } - - /** - * Return the length of this vector, a.k.a the norm or magnitude - */ - public float length() { - return (float) Math.sqrt(lengthSq()); - } - - /** - * Return the squared length of this vector, a.k.a the squared norm or squared magnitude - */ - public float lengthSq() { - return x*x + y*y; - } - - /** - * Return the direction angle of this vector in radians - */ - public float angle() { - // Utilize atan2 taking y=sin(a) and x=cos(a), resulting in proper direction angle for all quadrants. - return (float) Math.atan2(y, x); - } - - /** - * Normalize this vector in place - */ - public Vec2f normalize() { - final float lengthSq = lengthSq(); - if ( FloatUtil.isZero( lengthSq ) ) { - x = 0.0f; - y = 0.0f; - } else { - final float invSqr = 1.0f / (float)Math.sqrt(lengthSq); - x *= invSqr; - y *= invSqr; - } - return this; - } - - /** - * Return the squared distance between this vector and the given one. - *- * When comparing the relative distance between two points it is usually sufficient to compare the squared - * distances, thus avoiding an expensive square root operation. - *
- */ - public float distSq(final Vec2f o) { - final float dx = x - o.x; - final float dy = y - o.y; - return dx*dx + dy*dy; - } - - /** - * Return the distance between this vector and the given one. - */ - public float dist(final Vec2f o) { - return (float)Math.sqrt(distSq(o)); - } - - - /** - * Return the dot product of this vector and the given one - * @return the dot product as float - */ - public float dot(final Vec2f arg) { - return x * arg.x + y * arg.y; - } - - /** - * Returns cross product of this vectors and the given one, i.e. *this x o. - * - * The 2D cross product is identical with the 2D perp dot product. - * - * @return the resulting scalar - */ - public float cross(final Vec2f o) { - return x * o.y - y * o.x; - } - - /** - * Return the cosines of the angle between two vectors - */ - public float cosAngle(final Vec2f o) { - return dot(o) / ( length() * o.length() ) ; - } - - /** - * Return the angle between two vectors in radians - */ - public float angle(final Vec2f o) { - return (float) Math.acos( cosAngle(o) ); - } - - /** - * Return the counter-clock-wise (CCW) normal of this vector, i.e. perp(endicular) vector - */ - public Vec2f normal_ccw() { - return new Vec2f(-y, x); - } - - /** - * Equals check using a given {@link FloatUtil#EPSILON} value and {@link FloatUtil#isEqual(float, float, float)}. - *- * Implementation considers following corner cases: - *
- * Implementation considers following corner cases: - *
- * When comparing the relative distance between two points it is usually sufficient to compare the squared - * distances, thus avoiding an expensive square root operation. - *
- */ - public int distSq(final Vec2i o) { - final int dx = x - o.x; - final int dy = y - o.y; - return dx*dx + dy*dy; - } - - /** - * Return the distance between this vector and the given one. - */ - public int dist(final Vec2i o) { - return (int)Math.sqrt(distSq(o)); - } - - /** - * Equals check. - * @param o comparison value - * @return true if all components are equal - */ - public boolean isEqual(final Vec2i o) { - if( this == o ) { - return true; - } else { - return x == o.x && y == o.y; - } - } - - @Override - public boolean equals(final Object o) { - if( o instanceof Vec2i ) { - return isEqual((Vec2i)o); - } else { - return false; - } - } - - @Override - public String toString() { - return x + " / " + y; - } -} diff --git a/src/jogl/classes/com/jogamp/opengl/math/Vec3f.java b/src/jogl/classes/com/jogamp/opengl/math/Vec3f.java deleted file mode 100644 index 7012edd74..000000000 --- a/src/jogl/classes/com/jogamp/opengl/math/Vec3f.java +++ /dev/null @@ -1,404 +0,0 @@ -/** - * Copyright 2022-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: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.math; - -/** - * 3D Vector based upon three float components. - * - * Implementation borrowed from [gfxbox2](https://jausoft.com/cgit/cs_class/gfxbox2.git/tree/include/pixel/pixel3f.hpp#n29) - * and its data layout from JOAL's Vec3f. - */ -public final class Vec3f { - public static final Vec3f ONE = new Vec3f(1f, 1f, 1f); - public static final Vec3f UNIT_X = new Vec3f(1f, 0f, 0f); - public static final Vec3f UNIT_X_NEG = new Vec3f(-1f, 0f, 0f); - public static final Vec3f UNIT_Y = new Vec3f(0f, 1f, 0f); - public static final Vec3f UNIT_Y_NEG = new Vec3f(0f, -1f, 0f); - public static final Vec3f UNIT_Z = new Vec3f(0f, 0f, 1f); - public static final Vec3f UNIT_Z_NEG = new Vec3f(0f, 0f, -1f); - - private float x; - private float y; - private float z; - - public Vec3f() {} - - public Vec3f(final Vec3f o) { - set(o); - } - - /** Creating new Vec3f using Vec4f, dropping w. */ - public Vec3f(final Vec4f o) { - set(o); - } - - /** Creating new Vec3f using { Vec2f, z}. */ - public Vec3f(final Vec2f o, final float z) { - set(o, z); - } - - public Vec3f copy() { - return new Vec3f(this); - } - - public Vec3f(final float[/*3*/] xyz) { - set(xyz); - } - - public Vec3f(final float x, final float y, final float z) { - set(x, y, z); - } - - /** this = o, returns this. */ - public Vec3f set(final Vec3f o) { - this.x = o.x; - this.y = o.y; - this.z = o.z; - return this; - } - - /** this = { o, z }, returns this. */ - public Vec3f set(final Vec2f o, final float z) { - this.x = o.x(); - this.y = o.y(); - this.z = z; - return this; - } - - /** this = o while dropping w, returns this. */ - public Vec3f set(final Vec4f o) { - this.x = o.x(); - this.y = o.y(); - this.z = o.z(); - return this; - } - - /** this = { x, y, z }, returns this. */ - public Vec3f set(final float x, final float y, final float z) { - this.x = x; - this.y = y; - this.z = z; - return this; - } - - /** this = xyz, returns this. */ - public Vec3f set(final float[/*3*/] xyz) { - this.x = xyz[0]; - this.y = xyz[1]; - this.z = xyz[2]; - return this; - } - - /** Sets the ith component, 0 <= i < 3 */ - public void set(final int i, final float val) { - switch (i) { - case 0: x = val; break; - case 1: y = val; break; - case 2: z = val; break; - default: throw new IndexOutOfBoundsException(); - } - } - - /** xyz = this, returns xyz. */ - public float[] get(final float[/*3*/] xyz) { - xyz[0] = this.x; - xyz[1] = this.y; - xyz[2] = this.z; - return xyz; - } - - /** Gets the ith component, 0 <= i < 3 */ - public float get(final int i) { - switch (i) { - case 0: return x; - case 1: return y; - case 2: return z; - default: throw new IndexOutOfBoundsException(); - } - } - - public float x() { return x; } - public float y() { return y; } - public float z() { return z; } - - public void setX(final float x) { this.x = x; } - public void setY(final float y) { this.y = y; } - public void setZ(final float z) { this.z = z; } - - /** this = max(this, m), returns this. */ - public Vec3f max(final Vec3f m) { - this.x = Math.max(this.x, m.x); - this.y = Math.max(this.y, m.y); - this.z = Math.max(this.z, m.z); - return this; - } - /** this = min(this, m), returns this. */ - public Vec3f min(final Vec3f m) { - this.x = Math.min(this.x, m.x); - this.y = Math.min(this.y, m.y); - this.z = Math.min(this.z, m.z); - return this; - } - - /** Returns this * val; creates new vector */ - public Vec3f mul(final float val) { - return new Vec3f(this).scale(val); - } - - /** this = a * b, returns this. */ - public Vec3f mul(final Vec3f a, final Vec3f b) { - x = a.x * b.x; - y = a.y * b.y; - z = a.z * b.z; - return this; - } - - /** this = this * s, returns this. */ - public Vec3f scale(final float s) { - x *= s; - y *= s; - z *= s; - return this; - } - - /** this = this * { sx, sy, sz }, returns this. */ - public Vec3f scale(final float sx, final float sy, final float sz) { - x *= sx; - y *= sy; - z *= sz; - return this; - } - - /** this = this * { s.x, s.y, s.z }, returns this. */ - public Vec3f scale(final Vec3f s) { return scale(s.x, s.y, s.z); } - - /** Returns this + arg; creates new vector */ - public Vec3f plus(final Vec3f arg) { - return new Vec3f(this).add(arg); - } - - /** this = a + b, returns this. */ - public Vec3f plus(final Vec3f a, final Vec3f b) { - x = a.x + b.x; - y = a.y + b.y; - z = a.z + b.z; - return this; - } - - /** this = this + { dx, dy, dz }, returns this. */ - public Vec3f add(final float dx, final float dy, final float dz) { - x += dx; - y += dy; - z += dz; - return this; - } - - /** this = this + b, returns this. */ - public Vec3f add(final Vec3f b) { - x += b.x; - y += b.y; - z += b.z; - return this; - } - - /** Returns this - arg; creates new vector */ - public Vec3f minus(final Vec3f arg) { - return new Vec3f(this).sub(arg); - } - - /** this = a - b, returns this. */ - public Vec3f minus(final Vec3f a, final Vec3f b) { - x = a.x - b.x; - y = a.y - b.y; - z = a.z - b.z; - return this; - } - - /** this = this - b, returns this. */ - public Vec3f sub(final Vec3f b) { - x -= b.x; - y -= b.y; - z -= b.z; - return this; - } - - /** Return true if all components are zero, i.e. it's absolute value < {@link #EPSILON}. */ - public boolean isZero() { - return FloatUtil.isZero(x) && FloatUtil.isZero(y) && FloatUtil.isZero(z); - } - - /** - * Return the length of this vector, a.k.a the norm or magnitude - */ - public float length() { - return (float) Math.sqrt(lengthSq()); - } - - /** - * Return the squared length of this vector, a.k.a the squared norm or squared magnitude - */ - public float lengthSq() { - return x*x + y*y + z*z; - } - - /** - * Normalize this vector in place - */ - public Vec3f normalize() { - final float lengthSq = lengthSq(); - if ( FloatUtil.isZero( lengthSq ) ) { - x = 0.0f; - y = 0.0f; - z = 0.0f; - } else { - final float invSqr = 1.0f / (float)Math.sqrt(lengthSq); - x *= invSqr; - y *= invSqr; - z *= invSqr; - } - return this; - } - - /** - * Return the squared distance between this vector and the given one. - *- * When comparing the relative distance between two points it is usually sufficient to compare the squared - * distances, thus avoiding an expensive square root operation. - *
- */ - public float distSq(final Vec3f o) { - final float dx = x - o.x; - final float dy = y - o.y; - final float dz = z - o.z; - return dx*dx + dy*dy + dz*dz; - } - - /** - * Return the distance between this vector and the given one. - */ - public float dist(final Vec3f o) { - return (float)Math.sqrt(distSq(o)); - } - - - /** - * Return the dot product of this vector and the given one - * @return the dot product as float - */ - public float dot(final Vec3f o) { - return x*o.x + y*o.y + z*o.z; - } - - /** Returns this cross arg; creates new vector */ - public Vec3f cross(final Vec3f arg) { - return new Vec3f().cross(this, arg); - } - - /** this = a cross b. NOTE: "this" must be a different vector than - both a and b. */ - public Vec3f cross(final Vec3f a, final Vec3f b) { - x = a.y * b.z - a.z * b.y; - y = a.z * b.x - a.x * b.z; - z = a.x * b.y - a.y * b.x; - return this; - } - - /** - * Return the cosine of the angle between two vectors using {@link #dot(Vec3f)} - */ - public float cosAngle(final Vec3f o) { - return dot(o) / ( length() * o.length() ) ; - } - - /** - * Return the angle between two vectors in radians using {@link Math#acos(double)} on {@link #cosAngle(Vec3f)}. - */ - public float angle(final Vec3f o) { - return (float) Math.acos( cosAngle(o) ); - } - - /** - * Equals check using a given {@link FloatUtil#EPSILON} value and {@link FloatUtil#isEqual(float, float, float)}. - *- * Implementation considers following corner cases: - *
- * Implementation considers following corner cases: - *
- * When comparing the relative distance between two points it is usually sufficient to compare the squared - * distances, thus avoiding an expensive square root operation. - *
- */ - public float distSq(final Vec4f o) { - final float dx = x - o.x; - final float dy = y - o.y; - final float dz = z - o.z; - final float dw = w - o.w; - return dx*dx + dy*dy + dz*dz + dw*dw; - } - - /** - * Return the distance between this vector and the given one. - */ - public float dist(final Vec4f o) { - return (float)Math.sqrt(distSq(o)); - } - - - /** - * Return the dot product of this vector and the given one - * @return the dot product as float - */ - public float dot(final Vec4f o) { - return x*o.x + y*o.y + z*o.z + w*o.w; - } - - /** - * Return the cosines of the angle between two vectors - */ - public float cosAngle(final Vec4f o) { - return dot(o) / ( length() * o.length() ) ; - } - - /** - * Return the angle between two vectors in radians - */ - public float angle(final Vec4f o) { - return (float) Math.acos( cosAngle(o) ); - } - - /** - * Equals check using a given {@link FloatUtil#EPSILON} value and {@link FloatUtil#isEqual(float, float, float)}. - *- * Implementation considers following corner cases: - *
- * Implementation considers following corner cases: - *
epsilon
.
- * - * Implementation uses {@link FloatUtil#isZero(float, float)}, see API doc for details. - *
- */ - public static boolean isZero(final float x, final float y, final float z, final float epsilon) { - return FloatUtil.isZero(x, epsilon) && - FloatUtil.isZero(y, epsilon) && - FloatUtil.isZero(z, epsilon) ; - } - - /** - * Return true if all three vector components are zero, i.e. it's their absolute value < {@link FloatUtil#EPSILON}. - *- * Implementation uses {@link FloatUtil#isZero(float)}, see API doc for details. - *
- */ - public static boolean isZero(final float x, final float y, final float z) { - return FloatUtil.isZero(x) && - FloatUtil.isZero(y) && - FloatUtil.isZero(z) ; - } - - /** - * Return the squared distance between the given two points described vector v1 and v2. - *- * When comparing the relative distance between two points it is usually sufficient to compare the squared - * distances, thus avoiding an expensive square root operation. - *
- */ - public static float distSquareVec3(final float[] v1, final float[] v2) { - final float dx = v1[0] - v2[0]; - final float dy = v1[1] - v2[1]; - final float dz = v1[2] - v2[2]; - return dx * dx + dy * dy + dz * dz; - } - - /** - * Return the distance between the given two points described vector v1 and v2. - */ - public static float distVec3(final float[] v1, final float[] v2) { - return FloatUtil.sqrt(distSquareVec3(v1, v2)); - } - - /** - * Return the squared length of a vector, a.k.a the squared norm or squared magnitude - */ - public static float normSquareVec2(final float[] vec) { - return vec[0]*vec[0] + vec[1]*vec[1]; - } - - /** - * Return the squared length of a vector, a.k.a the squared norm or squared magnitude - */ - public static float normSquareVec3(final float[] vec) { - return vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]; - } - - /** - * Return the squared length of a vector, a.k.a the squared norm or squared magnitude - */ - public static float normSquareVec3(final float[] vec, final int offset) { - float v = vec[0+offset]; - float r = v*v; - v = vec[1+offset]; - r += v*v; - v = vec[2+offset]; - return r + v*v; - } - - /** - * Return the length of a vector, a.k.a the norm or magnitude - */ - public static float normVec2(final float[] vec) { - return FloatUtil.sqrt(normSquareVec2(vec)); - } - - /** - * Normalize a vector in place - * @param vector input vector - * @return normalized output vector - */ - public static float[] normalizeVec3(final float[] vector) { - final float lengthSq = normSquareVec3(vector); - if ( FloatUtil.isZero(lengthSq, FloatUtil.EPSILON) ) { - vector[0] = 0f; - vector[1] = 0f; - vector[2] = 0f; - } else { - final float invSqr = 1f / FloatUtil.sqrt(lengthSq); - vector[0] *= invSqr; - vector[1] *= invSqr; - vector[2] *= invSqr; - } - return vector; - } - - /** - * Normalize a vector in place - * @param vector input vector - * @return normalized output vector - */ - public static float[] normalizeVec3(final float[] vector, final int offset) { - final float lengthSq = normSquareVec3(vector, offset); - if ( FloatUtil.isZero(lengthSq, FloatUtil.EPSILON) ) { - vector[0+offset] = 0f; - vector[1+offset] = 0f; - vector[2+offset] = 0f; - } else { - final float invSqr = 1f / FloatUtil.sqrt(lengthSq); - vector[0+offset] *= invSqr; - vector[1+offset] *= invSqr; - vector[2+offset] *= invSqr; - } - return vector; - } - - /** - * Scales a vector by param using given result float[], result = vector * scale - * @param result vector for the result, may be vector (in-place) - * @param vector input vector - * @param scale single scale constant for all vector components - * @return result vector for chaining - */ - public static float[] scaleVec2(final float[] result, final float[] vector, final float scale) { - result[0] = vector[0] * scale; - result[1] = vector[1] * scale; - return result; - } - - /** - * Scales a vector by param using given result float[], result = vector * scale - * @param result vector for the result, may be vector (in-place) - * @param vector input vector - * @param scale 2 component scale constant for each vector component - * @return result vector for chaining - */ - public static float[] scaleVec2(final float[] result, final float[] vector, final float[] scale) - { - result[0] = vector[0] * scale[0]; - result[1] = vector[1] * scale[1]; - return result; - } - - /** - * Divides a vector by param using given result float[], result = vector / scale - * @param result vector for the result, may be vector (in-place) - * @param vector input vector - * @param scale single scale constant for all vector components - * @return result vector for chaining - */ - public static float[] divVec2(final float[] result, final float[] vector, final float scale) { - result[0] = vector[0] / scale; - result[1] = vector[1] / scale; - return result; - } - - /** - * Divides a vector by param using given result float[], result = vector / scale - * @param result vector for the result, may be vector (in-place) - * @param vector input vector - * @param scale 2 component scale constant for each vector component - * @return result vector for chaining - */ - public static float[] divVec2(final float[] result, final float[] vector, final float[] scale) - { - result[0] = vector[0] / scale[0]; - result[1] = vector[1] / scale[1]; - return result; - } - - /** - * Adds two vectors, result = v1 + v2 - * @param result float[2] result vector, may be either v1 or v2 (in-place) - * @param v1 vector 1 - * @param v2 vector 2 - * @return result vector for chaining - */ - public static float[] addVec2(final float[] result, final float[] v1, final float[] v2) { - result[0] = v1[0] + v2[0]; - result[1] = v1[1] + v2[1]; - return result; - } - - /** - * Subtracts two vectors, result = v1 - v2 - * @param result float[2] result vector, may be either v1 or v2 (in-place) - * @param v1 vector 1 - * @param v2 vector 2 - * @return result vector for chaining - */ - public static float[] subVec2(final float[] result, final float[] v1, final float[] v2) { - result[0] = v1[0] - v2[0]; - result[1] = v1[1] - v2[1]; - return result; - } - - /** - * cross product vec1 x vec2 - * @param v1 vector 1 - * @param v2 vector 2 - * @return the resulting vector - */ - public static float[] crossVec3(final float[] r, final int r_offset, final float[] v1, final int v1_offset, final float[] v2, final int v2_offset) - { - r[0+r_offset] = v1[1+v1_offset] * v2[2+v2_offset] - v1[2+v1_offset] * v2[1+v2_offset]; - r[1+r_offset] = v1[2+v1_offset] * v2[0+v2_offset] - v1[0+v1_offset] * v2[2+v2_offset]; - r[2+r_offset] = v1[0+v1_offset] * v2[1+v2_offset] - v1[1+v1_offset] * v2[0+v2_offset]; - return r; - } - - /** - * Calculate the midpoint of two points - * @param p1 first point vector - * @param p2 second point vector - * @return midpoint - */ - public static Vec3f midVec3(final Vec3f result, final Vec3f p1, final Vec3f p2) { - result.set( (p1.x() + p2.x())*0.5f, - (p1.y() + p2.y())*0.5f, - (p1.z() + p2.z())*0.5f ); - return result; - } - - /** - * Return the determinant of 3 vectors - * @param a vector 1 - * @param b vector 2 - * @param c vector 3 - * @return the determinant value - */ - public static float determinantVec3(final Vec3f a, final Vec3f b, final Vec3f c) { - return a.x()*b.y()*c.z() + a.y()*b.z()*c.x() + a.z()*b.x()*c.y() - a.x()*b.z()*c.y() - a.y()*b.x()*c.z() - a.z()*b.y()*c.x(); - } - - /** - * Check if three vertices are colliniear - * @param v1 vertex 1 - * @param v2 vertex 2 - * @param v3 vertex 3 - * @return true if collinear, false otherwise - */ - public static boolean isCollinearVec3(final Vec3f v1, final Vec3f v2, final Vec3f v3) { - return FloatUtil.isZero( determinantVec3(v1, v2, v3), FloatUtil.EPSILON ); - } - - /** - * Check if vertices in triangle circumcircle - * @param a triangle vertex 1 - * @param b triangle vertex 2 - * @param c triangle vertex 3 - * @param d vertex in question - * @return true if the vertex d is inside the circle defined by the - * vertices a, b, c. from paper by Guibas and Stolfi (1985). - */ - public static boolean isInCircleVec2(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c, final Vert2fImmutable d) { - return (a.x() * a.x() + a.y() * a.y()) * triAreaVec2(b, c, d) - - (b.x() * b.x() + b.y() * b.y()) * triAreaVec2(a, c, d) + - (c.x() * c.x() + c.y() * c.y()) * triAreaVec2(a, b, d) - - (d.x() * d.x() + d.y() * d.y()) * triAreaVec2(a, b, c) > 0; - } - - /** - * Computes oriented area of a triangle - * @param a first vertex - * @param b second vertex - * @param c third vertex - * @return compute twice the area of the oriented triangle (a,b,c), the area - * is positive if the triangle is oriented counterclockwise. - */ - public static float triAreaVec2(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c){ - return (b.x() - a.x()) * (c.y() - a.y()) - (b.y() - a.y()) * (c.x() - a.x()); - } - - /** - * Check if a vertex is in triangle using barycentric coordinates computation. - * @param a first triangle vertex - * @param b second triangle vertex - * @param c third triangle vertex - * @param p the vertex in question - * @param ac temporary storage - * @param ab temporary storage - * @param ap temporary storage - * @return true if p is in triangle (a, b, c), false otherwise. - */ - public static boolean isInTriangleVec3(final Vec3f a, final Vec3f b, final Vec3f c, - final Vec3f p, - final Vec3f ac, final Vec3f ab, final Vec3f ap){ - // Compute vectors - ac.minus( c, a); // v0 - ab.minus( b, a); // v1 - ap.minus( p, a); // v2 - - // Compute dot products - final float dotAC_AC = ac.dot(ac); - final float dotAC_AB = ac.dot(ab); - final float dotAB_AB = ab.dot(ab); - final float dotAC_AP = ac.dot(ap); - final float dotAB_AP = ab.dot(ap); - - // Compute barycentric coordinates - final float invDenom = 1 / (dotAC_AC * dotAB_AB - dotAC_AB * dotAC_AB); - final float u = (dotAB_AB * dotAC_AP - dotAC_AB * dotAB_AP) * invDenom; - final float v = (dotAC_AC * dotAB_AP - dotAC_AB * dotAC_AP) * invDenom; - - // Check if point is in triangle - return (u >= 0) && (v >= 0) && (u + v < 1); - } - - /** - * Check if one of three vertices are in triangle using barycentric coordinates computation. - * @param a first triangle vertex - * @param b second triangle vertex - * @param c third triangle vertex - * @param p1 the vertex in question - * @param p2 the vertex in question - * @param p3 the vertex in question - * @param ac temporary storage - * @param ab temporary storage - * @param ap temporary storage - * @return true if p1 or p2 or p3 is in triangle (a, b, c), false otherwise. - */ - public static boolean isVec3InTriangle3(final Vec3f a, final Vec3f b, final Vec3f c, - final Vec3f p1, final Vec3f p2, final Vec3f p3, - final Vec3f ac, final Vec3f ab, final Vec3f ap){ - // Compute vectors - ac.minus(c, a); // v0 - ab.minus(b, a); // v1 - - // Compute dot products - final float dotAC_AC = ac.dot(ac); - final float dotAC_AB = ac.dot(ab); - final float dotAB_AB = ab.dot(ab); - - // Compute barycentric coordinates - final float invDenom = 1 / (dotAC_AC * dotAB_AB - dotAC_AB * dotAC_AB); - { - ap.minus(p1, a); // v2 - final float dotAC_AP1 = ac.dot(ap); - final float dotAB_AP1 = ab.dot(ap); - final float u = (dotAB_AB * dotAC_AP1 - dotAC_AB * dotAB_AP1) * invDenom; - final float v = (dotAC_AC * dotAB_AP1 - dotAC_AB * dotAC_AP1) * invDenom; - - // Check if point is in triangle - if ( (u >= 0) && (v >= 0) && (u + v < 1) ) { - return true; - } - } - - { - ap.minus(p2, a); // v2 - final float dotAC_AP2 = ac.dot(ap); - final float dotAB_AP2 = ab.dot(ap); - final float u = (dotAB_AB * dotAC_AP2 - dotAC_AB * dotAB_AP2) * invDenom; - final float v = (dotAC_AC * dotAB_AP2 - dotAC_AB * dotAC_AP2) * invDenom; - - // Check if point is in triangle - if ( (u >= 0) && (v >= 0) && (u + v < 1) ) { - return true; - } - } - - { - ap.minus(p3, a); // v3 - final float dotAC_AP3 = ac.dot(ap); - final float dotAB_AP3 = ab.dot(ap); - final float u = (dotAB_AB * dotAC_AP3 - dotAC_AB * dotAB_AP3) * invDenom; - final float v = (dotAC_AC * dotAB_AP3 - dotAC_AB * dotAC_AP3) * invDenom; - - // Check if point is in triangle - if ( (u >= 0) && (v >= 0) && (u + v < 1) ) { - return true; - } - } - return false; - } - /** - * Check if one of three vertices are in triangle using - * barycentric coordinates computation, using given epsilon for comparison. - * @param a first triangle vertex - * @param b second triangle vertex - * @param c third triangle vertex - * @param p1 the vertex in question - * @param p2 the vertex in question - * @param p3 the vertex in question - * @param tmpAC - * @param tmpAB - * @param tmpAP - * @return true if p1 or p2 or p3 is in triangle (a, b, c), false otherwise. - */ - public static boolean isVec3InTriangle3(final Vec3f a, final Vec3f b, final Vec3f c, - final Vec3f p1, final Vec3f p2, final Vec3f p3, - final Vec3f ac, final Vec3f ab, final Vec3f ap, - final float epsilon) { - // Compute vectors - ac.minus(c, a); // v0 - ab.minus(b, a); // v1 - - // Compute dot products - final float dotAC_AC = ac.dot(ac); - final float dotAC_AB = ac.dot(ab); - final float dotAB_AB = ab.dot(ab); - - // Compute barycentric coordinates - final float invDenom = 1 / (dotAC_AC * dotAB_AB - dotAC_AB * dotAC_AB); - { - ap.minus(p1, a); // v2 - final float dotAC_AP1 = ac.dot(ap); - final float dotAB_AP1 = ab.dot(ap); - final float u = (dotAB_AB * dotAC_AP1 - dotAC_AB * dotAB_AP1) * invDenom; - final float v = (dotAC_AC * dotAB_AP1 - dotAC_AB * dotAC_AP1) * invDenom; - - // Check if point is in triangle - if( FloatUtil.compare(u, 0.0f, epsilon) >= 0 && - FloatUtil.compare(v, 0.0f, epsilon) >= 0 && - FloatUtil.compare(u+v, 1.0f, epsilon) < 0 ) { - return true; - } - } - - { - ap.minus(p2, a); // v3 - final float dotAC_AP2 = ac.dot(ap); - final float dotAB_AP2 = ab.dot(ap); - final float u = (dotAB_AB * dotAC_AP2 - dotAC_AB * dotAB_AP2) * invDenom; - final float v = (dotAC_AC * dotAB_AP2 - dotAC_AB * dotAC_AP2) * invDenom; - - // Check if point is in triangle - if( FloatUtil.compare(u, 0.0f, epsilon) >= 0 && - FloatUtil.compare(v, 0.0f, epsilon) >= 0 && - FloatUtil.compare(u+v, 1.0f, epsilon) < 0 ) { - return true; - } - } - - { - ap.minus(p3, a); // v4 - final float dotAC_AP3 = ac.dot(ap); - final float dotAB_AP3 = ab.dot(ap); - final float u = (dotAB_AB * dotAC_AP3 - dotAC_AB * dotAB_AP3) * invDenom; - final float v = (dotAC_AC * dotAB_AP3 - dotAC_AB * dotAC_AP3) * invDenom; - - // Check if point is in triangle - if( FloatUtil.compare(u, 0.0f, epsilon) >= 0 && - FloatUtil.compare(v, 0.0f, epsilon) >= 0 && - FloatUtil.compare(u+v, 1.0f, epsilon) < 0 ) { - return true; - } - } - return false; - } - - /** - * Check if points are in ccw order - * @param a first vertex - * @param b second vertex - * @param c third vertex - * @return true if the points a,b,c are in a ccw order - */ - public static boolean isCCW(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c){ - return triAreaVec2(a,b,c) > 0; - } - - /** - * Compute the winding of the 3 given points - *- * Consider using {@link #getWinding(ArrayList)} using the {@link #area(ArrayList)} function over all points - * on complex shapes for a reliable result! - *
- * @param a first vertex - * @param b second vertex - * @param c third vertex - * @return {@link Winding#CCW} or {@link Winding#CW} - * @see #getWinding(ArrayList) - */ - public static Winding getWinding(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c) { - return triAreaVec2(a,b,c) > 0 ? Winding.CCW : Winding.CW ; - } - - /** - * Computes the area of a list of vertices. - *- * This method is utilized e.g. to reliably compute the {@link Winding} of complex shapes. - *
- * @param vertices - * @return positive area if ccw else negative area value - * @see #getWinding(ArrayList) - */ - public static float area(final ArrayList extends Vert2fImmutable> vertices) { - final int n = vertices.size(); - float area = 0.0f; - for (int p = n - 1, q = 0; q < n; p = q++) { - final Vert2fImmutable pCoord = vertices.get(p); - final Vert2fImmutable qCoord = vertices.get(q); - area += pCoord.x() * qCoord.y() - qCoord.x() * pCoord.y(); - } - return area; - } - - /** - * Compute the winding using the {@link #area(ArrayList)} function over all vertices for complex shapes. - *- * Uses the {@link #area(ArrayList)} function over all points - * on complex shapes for a reliable result! - *
- * @param vertices array of Vertices - * @return {@link Winding#CCW} or {@link Winding#CW} - * @see #area(ArrayList) - */ - public static Winding getWinding(final ArrayList extends Vert2fImmutable> vertices) { - return area(vertices) >= 0 ? Winding.CCW : Winding.CW ; - } - - /** - * Finds the plane equation of a plane given its normal and a point on the plane. - * - * @param resultV4 vec4 plane equation - * @param normalVec3 - * @param pVec3 - * @return result for chaining - */ - public static Vec4f getPlaneVec3(final Vec4f resultV4, final Vec3f normalVec3, final Vec3f pVec3) { - /** - Ax + By + Cz + D == 0 ; - D = - ( Ax + By + Cz ) - = - ( A*a[0] + B*a[1] + C*a[2] ) - = - vec3Dot ( normal, a ) ; - */ - resultV4.set(normalVec3, -normalVec3.dot(pVec3)); - return resultV4; - } - - /** - * This finds the plane equation of a triangle given three vertices. - * - * @param resultVec4 vec4 plane equation - * @param v1 vec3 - * @param v2 vec3 - * @param v3 vec3 - * @param temp1V3 - * @param temp2V3 - * @return result for chaining - */ - public static Vec4f getPlaneVec3(final Vec4f resultVec4, final Vec3f v1, final Vec3f v2, final Vec3f v3, - final Vec3f temp1V3, final Vec3f temp2V3, final Vec3f temp3V3) { - /** - Ax + By + Cz + D == 0 ; - D = - ( Ax + By + Cz ) - = - ( A*a[0] + B*a[1] + C*a[2] ) - = - vec3Dot ( normal, a ) ; - */ - temp3V3.cross(temp1V3.minus(v2, v1), temp2V3.minus(v3, v1)).normalize(); - resultVec4.set(temp3V3, -temp3V3.dot(v1)); - return resultVec4; - } - - /** - * Return intersection of an infinite line with a plane if exists, otherwise null. - *- * Thanks to Norman Vine -- nhv@yahoo.com (with hacks by Steve) - *
- * - * @param result vec3 result buffer for intersecting coords - * @param ray here representing an infinite line, origin and direction. - * @param plane vec4 plane equation - * @param epsilon - * @return resulting intersecting if exists, otherwise null - */ - public static Vec3f line2PlaneIntersection(final Vec3f result, final Ray ray, final Vec4f plane, final float epsilon) { - final Vec3f plane3 = new Vec3f(plane); - final float tmp = ray.dir.dot(plane3); - - if ( Math.abs(tmp) < epsilon ) { - return null; // ray is parallel to plane - } - result.set( ray.dir ); - return result.scale( -( ray.orig.dot(plane3) + plane.w() ) / tmp ).add(ray.orig); - } - - /** Compute intersection between two segments - * @param a vertex 1 of first segment - * @param b vertex 2 of first segment - * @param c vertex 1 of second segment - * @param d vertex 2 of second segment - * @return the intersection coordinates if the segments intersect, otherwise returns null - */ - public static Vec3f seg2SegIntersection(final Vec3f result, final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c, final Vert2fImmutable d) { - final float determinant = (a.x()-b.x())*(c.y()-d.y()) - (a.y()-b.y())*(c.x()-d.x()); - - if (determinant == 0) - return null; - - final float alpha = (a.x()*b.y()-a.y()*b.x()); - final float beta = (c.x()*d.y()-c.y()*d.y()); - final float xi = ((c.x()-d.x())*alpha-(a.x()-b.x())*beta)/determinant; - final float yi = ((c.y()-d.y())*alpha-(a.y()-b.y())*beta)/determinant; - - final float gamma = (xi - a.x())/(b.x() - a.x()); - final float gamma1 = (xi - c.x())/(d.x() - c.x()); - if(gamma <= 0 || gamma >= 1) return null; - if(gamma1 <= 0 || gamma1 >= 1) return null; - - return result.set(xi, yi, 0); - } - - /** - * Compute intersection between two segments - * @param a vertex 1 of first segment - * @param b vertex 2 of first segment - * @param c vertex 1 of second segment - * @param d vertex 2 of second segment - * @return true if the segments intersect, otherwise returns false - */ - public static boolean testSeg2SegIntersection(final Vert2fImmutable a, final Vert2fImmutable b, - final Vert2fImmutable c, final Vert2fImmutable d) { - final float determinant = (a.x()-b.x())*(c.y()-d.y()) - (a.y()-b.y())*(c.x()-d.x()); - - if (determinant == 0) { - return false; - } - - final float alpha = (a.x()*b.y()-a.y()*b.x()); - final float beta = (c.x()*d.y()-c.y()*d.y()); - final float xi = ((c.x()-d.x())*alpha-(a.x()-b.x())*beta)/determinant; - - final float gamma0 = (xi - a.x())/(b.x() - a.x()); - final float gamma1 = (xi - c.x())/(d.x() - c.x()); - if(gamma0 <= 0 || gamma0 >= 1 || gamma1 <= 0 || gamma1 >= 1) { - return false; - } - - return true; - } - /** - * Compute intersection between two segments, using given epsilon for comparison. - * @param a vertex 1 of first segment - * @param b vertex 2 of first segment - * @param c vertex 1 of second segment - * @param d vertex 2 of second segment - * @return true if the segments intersect, otherwise returns false - */ - public static boolean testSeg2SegIntersection(final Vert2fImmutable a, final Vert2fImmutable b, - final Vert2fImmutable c, final Vert2fImmutable d, - final float epsilon) { - final float determinant = (a.x()-b.x())*(c.y()-d.y()) - (a.y()-b.y())*(c.x()-d.x()); - - if ( FloatUtil.isZero(determinant, epsilon) ) { - return false; - } - - final float alpha = (a.x()*b.y()-a.y()*b.x()); - final float beta = (c.x()*d.y()-c.y()*d.y()); - final float xi = ((c.x()-d.x())*alpha-(a.x()-b.x())*beta)/determinant; - - final float gamma0 = (xi - a.x())/(b.x() - a.x()); - final float gamma1 = (xi - c.x())/(d.x() - c.x()); - - if( FloatUtil.compare(gamma0, 0.0f, epsilon) <= 0 || - FloatUtil.compare(gamma0, 1.0f, epsilon) >= 0 || - FloatUtil.compare(gamma1, 0.0f, epsilon) <= 0 || - FloatUtil.compare(gamma1, 1.0f, epsilon) >= 0 ) { - return false; - } - - if(gamma0 <= 0 || gamma0 >= 1 || gamma1 <= 0 || gamma1 >= 1) { - return false; - } - - return true; - } - - /** - * Compute intersection between two lines - * @param a vertex 1 of first line - * @param b vertex 2 of first line - * @param c vertex 1 of second line - * @param d vertex 2 of second line - * @return the intersection coordinates if the lines intersect, otherwise - * returns null - */ - public static Vec3f line2lineIntersection(final Vec3f result, - final Vert2fImmutable a, final Vert2fImmutable b, - final Vert2fImmutable c, final Vert2fImmutable d) { - final float determinant = (a.x()-b.x())*(c.y()-d.y()) - (a.y()-b.y())*(c.x()-d.x()); - - if (determinant == 0) - return null; - - final float alpha = (a.x()*b.y()-a.y()*b.x()); - final float beta = (c.x()*d.y()-c.y()*d.y()); - final float xi = ((c.x()-d.x())*alpha-(a.x()-b.x())*beta)/determinant; - final float yi = ((c.y()-d.y())*alpha-(a.y()-b.y())*beta)/determinant; - - return result.set(xi, yi, 0); - } - - /** - * Check if a segment intersects with a triangle - * @param a vertex 1 of the triangle - * @param b vertex 2 of the triangle - * @param c vertex 3 of the triangle - * @param d vertex 1 of first segment - * @param e vertex 2 of first segment - * @return true if the segment intersects at least one segment of the triangle, false otherwise - */ - public static boolean testTri2SegIntersection(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c, - final Vert2fImmutable d, final Vert2fImmutable e){ - return testSeg2SegIntersection(a, b, d, e) || - testSeg2SegIntersection(b, c, d, e) || - testSeg2SegIntersection(a, c, d, e) ; - } - /** - * Check if a segment intersects with a triangle, using given epsilon for comparison. - * @param a vertex 1 of the triangle - * @param b vertex 2 of the triangle - * @param c vertex 3 of the triangle - * @param d vertex 1 of first segment - * @param e vertex 2 of first segment - * @return true if the segment intersects at least one segment of the triangle, false otherwise - */ - public static boolean testTri2SegIntersection(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c, - final Vert2fImmutable d, final Vert2fImmutable e, - final float epsilon){ - return testSeg2SegIntersection(a, b, d, e, epsilon) || - testSeg2SegIntersection(b, c, d, e, epsilon) || - testSeg2SegIntersection(a, c, d, e, epsilon) ; - } -} diff --git a/src/jogl/classes/com/jogamp/opengl/math/Vert2fImmutable.java b/src/jogl/classes/com/jogamp/opengl/math/Vert2fImmutable.java deleted file mode 100644 index 66bf078f3..000000000 --- a/src/jogl/classes/com/jogamp/opengl/math/Vert2fImmutable.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright 2012 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: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.opengl.math; - -public interface Vert2fImmutable { - float x(); - - float y(); - - int getCoordCount(); -} diff --git a/src/jogl/classes/com/jogamp/opengl/math/Vert3fImmutable.java b/src/jogl/classes/com/jogamp/opengl/math/Vert3fImmutable.java deleted file mode 100644 index 6f63a746c..000000000 --- a/src/jogl/classes/com/jogamp/opengl/math/Vert3fImmutable.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright 2012 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: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.opengl.math; - -public interface Vert3fImmutable extends Vert2fImmutable { - float z(); - - Vec3f getCoord(); -} diff --git a/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java b/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java deleted file mode 100644 index 1720caf0e..000000000 --- a/src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java +++ /dev/null @@ -1,923 +0,0 @@ -/** - * 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: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -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.Recti; -import com.jogamp.opengl.math.Vec3f; -import com.jogamp.opengl.util.PMVMatrix; - - -/** - * Axis Aligned Bounding Box. Defined by two 3D coordinates (low and high) - * The low being the the lower left corner of the box, and the high being the upper - * right corner of the box. - *- * A few references for collision detection, intersections: - *
- * http://www.realtimerendering.com/intersections.html - * http://www.codercorner.com/RayAABB.cpp - * http://www.siggraph.org/education/materials/HyperGraph/raytrace/rtinter0.htm - * http://realtimecollisiondetection.net/files/levine_swept_sat.txt - *- * - * - */ -public class AABBox { - private static final boolean DEBUG = FloatUtil.DEBUG; - 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 - * inverse low/high, allowing the next {@link #resize(float, float, float)} command to hit. - *
- * The dimension, i.e. {@link #getWidth()} abd {@link #getHeight()} is {@link Float#isInfinite()} thereafter. - *
- * @see #reset() - */ - public AABBox() { - reset(); - } - - /** - * Create an AABBox copying all values from the given one - * @param src the box value to be used for the new instance - */ - public AABBox(final AABBox src) { - copy(src); - } - - /** - * Create an AABBox specifying the coordinates - * of the low and high - * @param lx min x-coordinate - * @param ly min y-coordnate - * @param lz min z-coordinate - * @param hx max x-coordinate - * @param hy max y-coordinate - * @param hz max z-coordinate - */ - public AABBox(final float lx, final float ly, final float lz, - final float hx, final float hy, final float hz) { - setSize(lx, ly, lz, hx, hy, hz); - } - - /** - * Create a AABBox defining the low and high - * @param low min xyz-coordinates - * @param high max xyz-coordinates - */ - public AABBox(final float[] low, final float[] high) { - setSize(low, high); - } - - /** - * Create a AABBox defining the low and high - * @param low min xyz-coordinates - * @param high max xyz-coordinates - */ - public AABBox(final Vec3f low, final Vec3f high) { - setSize(low, high); - } - - /** - * Resets this box to the inverse low/high, allowing the next {@link #resize(float, float, float)} command to hit. - *- * The dimension, i.e. {@link #getWidth()} abd {@link #getHeight()} is {@link Float#isInfinite()} thereafter. - *
- * @return this AABBox for chaining - */ - 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.set( 0f, 0f, 0f); - return this; - } - - /** Get the max xyz-coordinates - * @return max xyz coordinates - */ - public final Vec3f getHigh() { - return high; - } - - private final void setHigh(final float hx, final float hy, final float hz) { - this.high.set(hx, hy, hz); - } - - /** Get the min xyz-coordinates - * @return min xyz coordinates - */ - public final Vec3f getLow() { - return low; - } - - private final void setLow(final float lx, final float ly, final float lz) { - this.low.set(lx, ly, lz); - } - - private final void computeCenter() { - center.set(high).add(low).scale(1f/2f); - } - - /** - * Copy given AABBox 'src' values to this AABBox. - * - * @param src source AABBox - * @return this AABBox for chaining - */ - public final AABBox copy(final AABBox src) { - low.set(src.low); - high.set(src.high); - center.set(src.center); - 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 float[] low, final float[] high) { - return setSize(low[0],low[1],low[2], high[0],high[1],high[2]); - } - - /** - * Set size of the AABBox specifying the coordinates - * of the low and high. - * - * @param lx min x-coordinate - * @param ly min y-coordnate - * @param lz min z-coordinate - * @param hx max x-coordinate - * @param hy max y-coordinate - * @param hz max z-coordinate - * @return this AABBox for chaining - */ - public final AABBox setSize(final float lx, final float ly, final float lz, - final float hx, final float hy, final float 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; - } - - /** - * Resize width of this AABBox with explicit left- and right delta values - * @param deltaLeft positive value will shrink width, otherwise expand width - * @param deltaRight positive value will expand width, otherwise shrink width - * @return this AABBox for chaining - */ - public final AABBox resizeWidth(final float deltaLeft, final float deltaRight) { - boolean mod = false; - if( !FloatUtil.isZero(deltaLeft) ) { - low.setX( low.x() + deltaLeft ); - mod = true; - } - if( !FloatUtil.isZero(deltaRight) ) { - high.setX( high.x() + deltaRight ); - mod = true; - } - if( mod ) { - computeCenter(); - } - return this; - } - - /** - * Resize height of this AABBox with explicit bottom- and top delta values - * @param deltaBottom positive value will shrink height, otherwise expand height - * @param deltaTop positive value will expand height, otherwise shrink height - * @return this AABBox for chaining - */ - public final AABBox resizeHeight(final float deltaBottom, final float deltaTop) { - boolean mod = false; - if( !FloatUtil.isZero(deltaBottom) ) { - low.setY( low.y() + deltaBottom ); - mod = true; - } - if( !FloatUtil.isZero(deltaTop) ) { - high.setY( high.y() + deltaTop ); - mod = true; - } - if( mod ) { - computeCenter(); - } - return this; - } - - /** - * Assign values of given AABBox to this instance. - * - * @param o source AABBox - * @return this AABBox for chaining - */ - public final AABBox set(final AABBox o) { - this.low.set(o.low); - this.high.set(o.high); - this.center.set(o.center); - return this; - } - - /** - * Resize the AABBox to encapsulate another AABox - * @param newBox AABBox to be encapsulated in - * @return this AABBox for chaining - */ - public final AABBox resize(final AABBox newBox) { - final Vec3f newLow = newBox.getLow(); - final Vec3f newHigh = newBox.getHigh(); - - /** test low */ - 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.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; - } - - /** - * Resize the AABBox to encapsulate another AABox, which will be transformed on the fly first. - * @param newBox AABBox to be encapsulated in - * @param t the {@link AffineTransform} applied on newBox on the fly - * @param tmpV3 temporary storage - * @return this AABBox for chaining - */ - public final AABBox resize(final AABBox newBox, final AffineTransform t, final Vec3f tmpV3) { - /** test low */ - { - final Vec3f newBoxLow = newBox.getLow(); - t.transform(newBoxLow, tmpV3); - 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 Vec3f newBoxHigh = newBox.getHigh(); - t.transform(newBoxHigh, tmpV3); - 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(); - return this; - } - - /** - * Resize the AABBox to encapsulate the passed - * xyz-coordinates. - * @param x x-axis coordinate value - * @param y y-axis coordinate value - * @param z z-axis coordinate value - * @return this AABBox for chaining - */ - public final AABBox resize(final float x, final float y, final float z) { - /** test low */ - if (x < low.x()) { - low.setX( x ); - } - if (y < low.y()) { - low.setY( y ); - } - if (z < low.z()) { - low.setZ( z ); - } - - /** test high */ - if (x > high.x()) { - high.setX( x ); - } - if (y > high.y()) { - high.setY( y ); - } - if (z > high.z()) { - high.setZ( z ); - } - - computeCenter(); - return this; - } - - /** - * Resize the AABBox to encapsulate the passed - * xyz-coordinates. - * @param xyz xyz-axis coordinate values - * @param offset of the array - * @return this AABBox for chaining - */ - public final AABBox resize(final float[] xyz, final int offset) { - return resize(xyz[0+offset], xyz[1+offset], xyz[2+offset]); - } - - /** - * 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 float[] xyz) { - return resize(xyz[0], xyz[1], xyz[2]); - } - - /** - * 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 - * @param y y-axis coordinate value - * @return true if x belong to (low.x, high.x) and - * y belong to (low.y, high.y) - */ - public final boolean contains(final float x, final float y) { - if(x- * Versions uses the SAT[1], testing 6 axes. - * Original code for OBBs from MAGIC. - * Rewritten for AABBs and reorganized for early exits[2]. - *
- *- * [1] SAT = Separating Axis Theorem - * [2] http://www.codercorner.com/RayAABB.cpp - *- * @param ray - * @return - */ - public final boolean intersectsRay(final Ray ray) { - // diff[XYZ] -> VectorUtil.subVec3(diff, ray.orig, center); - // ext[XYZ] -> extend VectorUtil.subVec3(ext, high, center); - - 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.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.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); - final float absDirZ = Math.abs(dirZ); - - float f = dirY * diffZ - dirZ * diffY; - if( Math.abs(f) > extY*absDirZ + extZ*absDirY ) return false; - - final float absDirX = Math.abs(dirX); - - f = dirZ * diffX - dirX * diffZ; - if( Math.abs(f) > extX*absDirZ + extZ*absDirX ) return false; - - f = dirX * diffY - dirY * diffX; - if( Math.abs(f) > extX*absDirY + extY*absDirX ) return false; - - return true; - } - - /** - * Return intersection of a {@link Ray} with this bounding box, - * or null if none exist. - *
- *
- * Method is based on the requirements: - *
- * Report bugs: p.terdiman@codercorner.com (original author) - *
- *- * [1] http://www.codercorner.com/RayAABB.cpp - * [2] http://tog.acm.org/resources/GraphicsGems/gems/RayBox.c - *- * @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. - * @return float[3] result of intersection coordinates, or null if none exists - */ - public final Vec3f getRayIntersection(final Vec3f result, final Ray ray, final float epsilon, - final boolean assumeIntersection) { - final float[] maxT = { -1f, -1f, -1f }; - - final Vec3f origin = ray.orig; - final Vec3f dir = ray.dir; - - boolean inside = true; - - // Find candidate planes. - for(int i=0; i<3; 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; - } - } 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; - } - } - } - - // Ray origin inside bounding box - if(inside) { - result.set(origin); - 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.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.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.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"); - } - } else { - switch( whichPlane ) { - case 0: - result.setY( origin.y() + maxT[whichPlane] * dir.y() ); - result.setZ( origin.z() + maxT[whichPlane] * dir.z() ); - break; - case 1: - result.setX( origin.x() + maxT[whichPlane] * dir.x() ); - result.setZ( origin.z() + maxT[whichPlane] * dir.z() ); - break; - case 2: - result.setX( origin.x() + maxT[whichPlane] * dir.x() ); - result.setY( origin.y() + maxT[whichPlane] * dir.y() ); - break; - default: - throw new InternalError("XXX"); - } - } - return result; // ray hits box - } - - /** - * Get the size of this AABBox where the size is represented by the - * length of the vector between low and high. - * @return a float representing the size of the AABBox - */ - public final float getSize() { - return low.dist(high); - } - - /** - * Get the Center of this AABBox - * @return the xyz-coordinates of the center of the AABBox - */ - public final Vec3f getCenter() { - return center; - } - - /** - * Scale this AABBox by a constant around fixed center - *
- * high and low is recomputed by scaling its distance to fixed center. - *
- * @param size a constant float value - * @return this AABBox for chaining - * @see #scale2(float, float[]) - */ - public final AABBox scale(final float size) { - final Vec3f tmp = new Vec3f(); - tmp.set(high).sub(center).scale(size); - high.set(center).add(tmp); - - tmp.set(low).sub(center).scale(size); - low.set(center).add(tmp); - - return this; - } - - /** - * Scale this AABBox by a constant, recomputing center - *- * high and low is scaled and center recomputed. - *
- * @param size a constant float value - * @return this AABBox for chaining - * @see #scale(float, float[]) - */ - public final AABBox scale2(final float size) { - high.scale(size); - low.scale(size); - computeCenter(); - return this; - } - - /** - * Translate this AABBox by a float[3] vector - * @param dx the translation x-component - * @param dy the translation y-component - * @param dz the translation z-component - * @param t the float[3] translation vector - * @return this AABBox for chaining - */ - public final AABBox translate(final float dx, final float dy, final float dz) { - low.add(dx, dy, dz); - high.add(dx, dy, dz); - computeCenter(); - return this; - } - - /** - * Translate this AABBox by a float[3] vector - * @param t the float[3] translation vector - * @return this AABBox for chaining - */ - public final AABBox translate(final Vec3f t) { - low.add(t); - high.add(t); - computeCenter(); - return this; - } - - /** - * Rotate this AABBox by a float[3] vector - * @param quat the {@link Quaternion} used for rotation - * @return this AABBox for chaining - */ - public final AABBox rotate(final Quaternion quat) { - quat.rotateVector(low, low); - quat.rotateVector(high, high); - computeCenter(); - return this; - } - - public final float getMinX() { - return low.x(); - } - - public final float getMinY() { - return low.y(); - } - - public final float getMinZ() { - return low.z(); - } - - public final float getMaxX() { - return high.x(); - } - - public final float getMaxY() { - return high.y(); - } - - public final float getMaxZ() { - return high.z(); - } - - public final float getWidth(){ - return high.x() - low.x(); - } - - public final float getHeight() { - return high.y() - low.y(); - } - - public final float getDepth() { - return high.z() - low.z(); - } - - /** Returns the volume, i.e. width * height * depth */ - public final float getVolume() { - return getWidth() * getHeight() * getDepth(); - } - - /** Return true if {@link #getVolume()} is {@link FloatUtil#isZero(float)}, considering epsilon. */ - public final boolean hasZeroVolume() { - return FloatUtil.isZero(getVolume()); - } - - /** Returns the assumed 2D area, i.e. width * height while assuming low and high lies on same plane. */ - public final float get2DArea() { - return getWidth() * getHeight(); - } - - /** Return true if {@link #get2DArea()} is {@link FloatUtil#isZero(float)}, considering epsilon. */ - public final boolean hasZero2DArea() { - return FloatUtil.isZero(get2DArea()); - } - - @Override - public final boolean equals(final Object obj) { - if( obj == this ) { - return true; - } - if( null == obj || !(obj instanceof AABBox) ) { - return false; - } - final AABBox other = (AABBox) obj; - return low.isEqual(other.low) && high.isEqual(other.high); - } - @Override - public final int hashCode() { - throw new InternalError("hashCode not designed"); - } - - /** - * Transform this box using the given {@link Matrix4f} into {@code out} - * @param mat transformation {@link Matrix4f} - * @param out the resulting {@link AABBox} - * @return the resulting {@link AABBox} for chaining - */ - public AABBox transform(final Matrix4f mat, final AABBox out) { - final Vec3f tmp = new Vec3f(); - out.reset(); - out.resize( mat.mulVec3f(low, tmp) ); - out.resize( mat.mulVec3f(high, tmp) ); - out.computeCenter(); - return out; - } - - /** - * Transform this box using the {@link PMVMatrix#getMvMat() modelview} of the given {@link PMVMatrix} into {@code out} - * @param pmv transformation {@link PMVMatrix} - * @param out the resulting {@link AABBox} - * @return the resulting {@link AABBox} for chaining - */ - public AABBox transformMv(final PMVMatrix pmv, final AABBox out) { - final Vec3f tmp = new Vec3f(); - out.reset(); - out.resize( pmv.mulMvMatVec3f(low, tmp) ); - out.resize( pmv.mulMvMatVec3f(high, tmp) ); - out.computeCenter(); - return out; - } - - /** - * Assume this bounding box as being in object space and - * compute the window bounding box. - *
- * If useCenterZ
is true
,
- * 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#mapObjToWin(float, float, float, float[], int[], float[], float[], float[]) mapObjToWinCoords}
- * operation on all 8 points are performed.
- *
- * .z() ------ [4] - * | | - * | | - * .y() ------ [3] - *- * @param mat4PMv [projection] x [modelview] matrix, i.e. P x Mv - * @param viewport viewport rectangle - * @param useCenterZ - * @param vec3Tmp0 3 component vector for temp storage - * @param vec4Tmp1 4 component vector for temp storage - * @param vec4Tmp2 4 component vector for temp storage - * @return - */ - public AABBox mapToWindow(final AABBox result, final Matrix4f mat4PMv, final Recti viewport, final boolean useCenterZ) { - final Vec3f tmp = new Vec3f(); - final Vec3f winPos = new Vec3f(); - { - final float objZ = useCenterZ ? center.z() : getMinZ(); - result.reset(); - - Matrix4f.mapObjToWin(tmp.set(getMinX(), getMinY(), objZ), mat4PMv, viewport, winPos); - result.resize(winPos); - - Matrix4f.mapObjToWin(tmp.set(getMinX(), getMaxY(), objZ), mat4PMv, viewport, winPos); - result.resize(winPos); - - Matrix4f.mapObjToWin(tmp.set(getMaxX(), getMaxY(), objZ), mat4PMv, viewport, winPos); - result.resize(winPos); - - Matrix4f.mapObjToWin(tmp.set(getMaxX(), getMinY(), objZ), mat4PMv, viewport, winPos); - result.resize(winPos); - } - - if( !useCenterZ ) { - final float objZ = getMaxZ(); - - Matrix4f.mapObjToWin(tmp.set(getMinX(), getMinY(), objZ), mat4PMv, viewport, winPos); - result.resize(winPos); - - Matrix4f.mapObjToWin(tmp.set(getMinX(), getMaxY(), objZ), mat4PMv, viewport, winPos); - result.resize(winPos); - - Matrix4f.mapObjToWin(tmp.set(getMaxX(), getMaxY(), objZ), mat4PMv, viewport, winPos); - result.resize(winPos); - - Matrix4f.mapObjToWin(tmp.set(getMaxX(), getMinY(), objZ), mat4PMv, viewport, winPos); - result.resize(winPos); - } - if( DEBUG ) { - System.err.printf("AABBox.mapToWindow: view[%s], this %s -> %s%n", viewport, toString(), result.toString()); - } - return result; - } - - @Override - public final String toString() { - return "[dim "+getWidth()+" x "+getHeight()+" x "+getDepth()+ - ", 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 deleted file mode 100644 index 73079959b..000000000 --- a/src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java +++ /dev/null @@ -1,378 +0,0 @@ -/** - * 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: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.opengl.math.geom; - -import com.jogamp.opengl.math.FovHVHalves; -import com.jogamp.opengl.math.Matrix4f; -import com.jogamp.opengl.math.Vec3f; - -/** - * Providing frustum {@link #getPlanes() planes} derived by different inputs - * ({@link #updateFrustumPlanes(float[], int) P*MV}, ..) used to classify objects - *
- * Extracting the world-frustum planes from the P*Mv: - *
- * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix - * Gil Gribb- * Classifying Point, Sphere and AABBox: - *- * Klaus Hartmann - * http://graphics.cs.ucf.edu/cap4720/fall2008/plane_extraction.pdf - *
- * Efficient View Frustum Culling - * Daniel Sýkora- *- * Josef Jelínek - * http://www.cg.tuwien.ac.at/hostings/cescg/CESCG-2002/DSykoraJJelinek/index.html - *
- * Lighthouse3d.com - * http://www.lighthouse3d.com/tutorials/view-frustum-culling/ - *- * - * Fundamentals about Planes, Half-Spaces and Frustum-Culling:
- * Planes and Half-Spaces, Max Wagner- *- * http://www.emeyex.com/site/tuts/PlanesHalfSpaces.pdf - *
- * Frustum Culling, Max Wagner- * - */ -public class Frustum { - /** - * {@link Frustum} description by {@link #fovhv} and {@link #zNear}, {@link #zFar}. - */ - public static class FovDesc { - /** Field of view in both directions, may not be centered, either {@link FovHVHalves#inTangents} or radians. */ - public final FovHVHalves fovhv; - /** Near Z */ - public final float zNear; - /** Far Z */ - public final float zFar; - /** - * @param fovhv field of view in both directions, may not be centered, either {@link FovHVHalves#inTangents} or radians - * @param zNear - * @param zFar - * @throws IllegalArgumentException if {@code zNear <= 0} or {@code zFar <= zNear}. - */ - public FovDesc(final FovHVHalves fovhv, final float zNear, final float zFar) throws IllegalArgumentException { - if( zNear <= 0.0f || zFar <= zNear ) { - throw new IllegalArgumentException("Requirements zNear > 0 and zFar > zNear, but zNear "+zNear+", zFar "+zFar); - } - this.fovhv = fovhv; - this.zNear = zNear; - this.zFar = zFar; - } - @Override - public final String toString() { - return "FrustumFovDesc["+fovhv.toStringInDegrees()+", Z["+zNear+" - "+zFar+"]]"; - } - } - - /** Normalized planes[l, r, b, t, n, f] */ - protected final Plane[] planes = new Plane[6]; - - /** - * Creates an undefined instance w/o calculating the frustum. - *- * http://www.emeyex.com/site/tuts/FrustumCulling.pdf - *
- * Use one of the update(..)
methods to set the {@link #getPlanes() planes}.
- *
- * In order to work w/ {@link Frustum#isOutside(AABBox) isOutside(..)} methods, - * the normals have to point to the inside of the frustum. - *
- */ - public static class Plane { - /** Normal of the plane */ - public final Vec3f n = new Vec3f(); - - /** Distance to origin */ - public float d; - - /** - * Return signed distance of plane to given point. - *- * Positive halfspace is where the plane’s normals vector points into. - *
- *- * Negative halfspace is the other side of the plane, i.e. *-1 - *
- **/ - public final float distanceTo(final float x, final float y, final float z) { - 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 Vec3f p) { - return n.x() * p.x() + n.y() * p.y() + n.z() * p.z() + d; - } - - @Override - public String toString() { - return "Plane[ [ " + n + " ], " + d + "]"; - } - } - - /** Index for left plane: {@value} */ - public static final int LEFT = 0; - /** Index for right plane: {@value} */ - public static final int RIGHT = 1; - /** Index for bottom plane: {@value} */ - public static final int BOTTOM = 2; - /** Index for top plane: {@value} */ - public static final int TOP = 3; - /** Index for near plane: {@value} */ - public static final int NEAR = 4; - /** Index for far plane: {@value} */ - public static final int FAR = 5; - - /** - * {@link Plane}s are ordered in the returned array as follows: - *- * {@link Plane}'s normals are pointing to the inside of the frustum - * in order to work w/ {@link #isOutside(AABBox) isOutside(..)} methods. - *
- * - * @return array of normalized {@link Plane}s, order see above. - */ - public final Plane[] getPlanes() { return planes; } - - /** - * Copy the givensrc
planes into this this instance's planes.
- * @param src the 6 source planes
- */
- public final void updateByPlanes(final Plane[] src) {
- for (int i = 0; i < 6; ++i) {
- final Plane pD = planes[i];
- final Plane pS = src[i];
- pD.d = pS.d;
- System.arraycopy(pS.n, 0, pD.n, 0, 3);
- }
- }
-
- /**
- * Calculate the frustum planes in world coordinates
- * using the passed {@link FovDesc}.
- * - * Operation Details: - *
- * Frustum plane's normals will point to the inside of the viewing frustum, - * as required by this class. - *
- * - * @param m 4x4 matrix in column-major order (also result) - * @param fovDesc {@link Frustum} {@link FovDesc} - * @return given matrix for chaining - * @see Matrix4f#setToPerspective(FovHVHalves, float, float) - * @see Matrix4f#updateFrustumPlanes(Frustum) - * @see Matrix4f#getFrustum(Frustum, FovDesc) - */ - public Matrix4f updateByFovDesc(final Matrix4f m, final FovDesc fovDesc) { - m.setToPerspective(fovDesc.fovhv, fovDesc.zNear, fovDesc.zFar); - m.updateFrustumPlanes(this); - return m; - } - - /** - * Calculate the frustum planes in world coordinates - * using the passed premultiplied P*MV (column major order) matrix. - *- * Frustum plane's normals will point to the inside of the viewing frustum, - * as required by this class. - *
- */ - public void updateFrustumPlanes(final Matrix4f pmv) { - pmv.updateFrustumPlanes(this); - } - - private static final boolean isOutsideImpl(final Plane p, final AABBox box) { - 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; - } - - /** - * Check to see if an axis aligned bounding box is completely outside of the frustum. - *- * Note: If method returns false, the box may only be partially inside. - *
- */ - public final boolean isAABBoxOutside(final AABBox box) { - for (int i = 0; i < 6; ++i) { - if ( isOutsideImpl(planes[i], box) ) { - // fully outside - return true; - } - } - // We make no attempt to determine whether it's fully inside or not. - return false; - } - - - public static enum Location { OUTSIDE, INSIDE, INTERSECT }; - - /** - * Check to see if a point is outside, inside or on a plane of the frustum. - * - * @param p the point - * @return {@link Location} of point related to frustum planes - */ - public final Location classifyPoint(final Vec3f p) { - Location res = Location.INSIDE; - - for (int i = 0; i < 6; ++i) { - final float d = planes[i].distanceTo(p); - if ( d < 0.0f ) { - return Location.OUTSIDE; - } else if ( d == 0.0f ) { - res = Location.INTERSECT; - } - } - return res; - } - - /** - * Check to see if a point is outside of the frustum. - * - * @param p the point - * @return true if outside of the frustum, otherwise inside or on a plane - */ - public final boolean isPointOutside(final Vec3f p) { - return Location.OUTSIDE == classifyPoint(p); - } - - /** - * Check to see if a sphere is outside, intersecting or inside of the frustum. - * - * @param p center of the sphere - * @param radius radius of the sphere - * @return {@link Location} of point related to frustum planes - */ - public final Location classifySphere(final Vec3f p, final float radius) { - Location res = Location.INSIDE; // fully inside - - for (int i = 0; i < 6; ++i) { - final float d = planes[i].distanceTo(p); - if ( d < -radius ) { - // fully outside - return Location.OUTSIDE; - } else if (d < radius ) { - // intersecting - res = Location.INTERSECT; - } - } - return res; - } - - /** - * Check to see if a sphere is outside of the frustum. - * - * @param p center of the sphere - * @param radius radius of the sphere - * @return true if outside of the frustum, otherwise inside or intersecting - */ - public final boolean isSphereOutside(final Vec3f p, final float radius) { - return Location.OUTSIDE == classifySphere(p, radius); - } - - public StringBuilder toString(StringBuilder sb) { - if( null == sb ) { - sb = new StringBuilder(); - } - sb.append("Frustum[Planes[").append(System.lineSeparator()) - .append(" L: ").append(planes[0]).append(", ").append(System.lineSeparator()) - .append(" R: ").append(planes[1]).append(", ").append(System.lineSeparator()) - .append(" B: ").append(planes[2]).append(", ").append(System.lineSeparator()) - .append(" T: ").append(planes[3]).append(", ").append(System.lineSeparator()) - .append(" N: ").append(planes[4]).append(", ").append(System.lineSeparator()) - .append(" F: ").append(planes[5]).append("], ").append(System.lineSeparator()) - .append("]"); - return sb; - } - - @Override - public String toString() { - return toString(null).toString(); - } -} -- cgit v1.2.3