aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/com/jogamp/opengl/math
diff options
context:
space:
mode:
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/math')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Binary16.java569
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Binary32.java116
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Binary64.java116
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/FixedPoint.java61
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java1628
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java182
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java2153
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Quaternion.java1188
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Ray.java60
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Recti.java134
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Vec2f.java385
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Vec2i.java153
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Vec3f.java404
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Vec4f.java394
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java770
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Vert2fImmutable.java36
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Vert3fImmutable.java34
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/geom/AABBox.java923
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/geom/Frustum.java378
19 files changed, 0 insertions, 9684 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Binary16.java b/src/jogl/classes/com/jogamp/opengl/math/Binary16.java
deleted file mode 100644
index 8e4aa9176..000000000
--- a/src/jogl/classes/com/jogamp/opengl/math/Binary16.java
+++ /dev/null
@@ -1,569 +0,0 @@
-/**
- * Copyright 2013 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;
-
-/**
- * <p>
- * Functions to convert values to/from the <code>binary16</code> format
- * specified in <code>IEEE 754 2008</code>.
- * </p>
- */
-
-public final class Binary16
-{
- /**
- * The encoded form of negative infinity <code>-∞</code>.
- */
-
- public static final char NEGATIVE_INFINITY;
-
- /**
- * The encoded form of positive infinity <code>∞</code>.
- */
-
- public static final char POSITIVE_INFINITY;
-
- /**
- * The encoded form of positive zero <code>0</code>.
- */
-
- public static final char POSITIVE_ZERO;
-
- /**
- * The encoded form of negative zero <code>-0</code>.
- */
-
- public static final char NEGATIVE_ZERO;
-
- /**
- * The <i>bias</i> value used to offset the encoded exponent. A given
- * exponent <code>e</code> is encoded as <code>{@link #BIAS} + e</code>.
- */
-
- 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 <code>true</code> if the given packed <code>binary16</code> 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 <code>true</code> if the given packed <code>binary16</code> value
- * is not a number (<code>NaN</code>).
- */
-
- public static boolean isNaN(
- final char k)
- {
- final int e = Binary16.unpackGetExponentUnbiased(k);
- final int s = Binary16.unpackGetSignificand(k);
- return (e == 16) && (s > 0);
- }
-
- /**
- * <p>
- * Convert a double precision floating point value to a packed
- * <code>binary16</code> value.
- * </p>
- * <p>
- * For the following specific cases, the function returns:
- * </p>
- * <ul>
- * <li><code>NaN</code> iff <code>isNaN(k)</code></li>
- * <li>{@link #POSITIVE_INFINITY} iff
- * <code>k == {@link Double#POSITIVE_INFINITY}</code></li>
- * <li>{@link #NEGATIVE_INFINITY} iff
- * <code>k == {@link Double#NEGATIVE_INFINITY}</code></li>
- * <li>{@link #NEGATIVE_ZERO} iff <code>k == -0.0</code></li>
- * <li>{@link #POSITIVE_ZERO} iff <code>k == 0.0</code></li>
- * </ul>
- * <p>
- * Otherwise, the <code>binary16</code> value that most closely represents
- * <code>k</code> is returned. This may obviously be an infinite value as
- * the interval of double precision values is far larger than that of the
- * <code>binary16</code> type.
- * </p>
- *
- * @see #unpackDouble(char)
- */
-
- public static char packDouble(
- final double k)
- {
- if (Double.isNaN(k)) {
- return Binary16.exampleNaN();
- }
- if (k == Double.POSITIVE_INFINITY) {
- return Binary16.POSITIVE_INFINITY;
- }
- if (k == Double.NEGATIVE_INFINITY) {
- return Binary16.NEGATIVE_INFINITY;
- }
- if (Double.doubleToLongBits(k) == Binary64.NEGATIVE_ZERO_BITS) {
- return Binary16.NEGATIVE_ZERO;
- }
- if (k == 0.0) {
- return Binary16.POSITIVE_ZERO;
- }
-
- final long de = Binary64.unpackGetExponentUnbiased(k);
- final long ds = Binary64.unpackGetSign(k);
- final long dn = Binary64.unpackGetSignificand(k);
- final char rsr = Binary16.packSetSignUnchecked((int) ds);
-
- /**
- * Extract the 5 least-significant bits of the exponent.
- */
-
- final int rem = (int) (de & 0x001F);
- final char rer = Binary16.packSetExponentUnbiasedUnchecked(rem);
-
- /**
- * Extract the 10 most-significant bits of the significand.
- */
-
- final long rnm = dn & 0xFFC0000000000L;
- final long rns = rnm >> 42;
- final char rnr = Binary16.packSetSignificandUnchecked((int) rns);
-
- /**
- * Combine the results.
- */
-
- return (char) (rsr | rer | rnr);
- }
-
- /**
- * <p>
- * Convert a single precision floating point value to a packed
- * <code>binary16</code> value.
- * </p>
- * <p>
- * For the following specific cases, the function returns:
- * </p>
- * <ul>
- * <li><code>NaN</code> iff <code>isNaN(k)</code></li>
- * <li>{@link #POSITIVE_INFINITY} iff
- * <code>k == {@link Float#POSITIVE_INFINITY}</code></li>
- * <li>{@link #NEGATIVE_INFINITY} iff
- * <code>k == {@link Float#NEGATIVE_INFINITY}</code></li>
- * <li>{@link #NEGATIVE_ZERO} iff <code>k == -0.0</code></li>
- * <li>{@link #POSITIVE_ZERO} iff <code>k == 0.0</code></li>
- * </ul>
- * <p>
- * Otherwise, the <code>binary16</code> value that most closely represents
- * <code>k</code> is returned. This may obviously be an infinite value as
- * the interval of single precision values is far larger than that of the
- * <code>binary16</code> type.
- * </p>
- *
- * @see #unpackFloat(char)
- */
-
- public static char packFloat(
- final float k)
- {
- if (Float.isNaN(k)) {
- return Binary16.exampleNaN();
- }
- if (k == Float.POSITIVE_INFINITY) {
- return Binary16.POSITIVE_INFINITY;
- }
- if (k == Float.NEGATIVE_INFINITY) {
- return Binary16.NEGATIVE_INFINITY;
- }
- if (Float.floatToIntBits(k) == Binary32.NEGATIVE_ZERO_BITS) {
- return Binary16.NEGATIVE_ZERO;
- }
- if (k == 0.0) {
- return Binary16.POSITIVE_ZERO;
- }
-
- final long de = Binary32.unpackGetExponentUnbiased(k);
- final long ds = Binary32.unpackGetSign(k);
- final long dn = Binary32.unpackGetSignificand(k);
- final char rsr = Binary16.packSetSignUnchecked((int) ds);
-
- /**
- * Extract the 5 least-significant bits of the exponent.
- */
-
- final int rem = (int) (de & 0x001F);
- final char rer = Binary16.packSetExponentUnbiasedUnchecked(rem);
-
- /**
- * Extract the 10 most-significant bits of the significand.
- */
-
- final long rnm = dn & 0x7FE000L;
- final long rns = rnm >> 13;
- final char rnr = Binary16.packSetSignificandUnchecked((int) rns);
-
- /**
- * Combine the results.
- */
-
- return (char) (rsr | rer | rnr);
- }
-
- /**
- * <p>
- * Encode the unbiased exponent <code>e</code>. Values should be in the
- * range <code>[-15, 16]</code> - values outside of this range will be
- * truncated.
- * </p>
- *
- * @see #unpackGetExponentUnbiased(char)
- */
-
- public static char packSetExponentUnbiasedUnchecked(
- final int e)
- {
- final int eb = e + Binary16.BIAS;
- final int es = eb << 10;
- final int em = es & Binary16.MASK_EXPONENT;
- return (char) em;
- }
-
- /**
- * <p>
- * Encode the significand <code>s</code>. Values should be in the range
- * <code>[0, 1023]</code>. Values outside of this range will be truncated.
- * </p>
- *
- * @see #unpackGetSignificand(char)
- */
-
- public static char packSetSignificandUnchecked(
- final int s)
- {
- final int sm = s & Binary16.MASK_SIGNIFICAND;
- return (char) sm;
- }
-
- /**
- * <p>
- * Encode the sign bit <code>s</code>. Values should be in the range
- * <code>[0, 1]</code>, with <code>0</code> ironically denoting a positive
- * value. Values outside of this range will be truncated.
- * </p>
- *
- * @see #unpackGetSign(char)
- */
-
- public static char packSetSignUnchecked(
- final int s)
- {
- final int ss = s << 15;
- final int sm = ss & Binary16.MASK_SIGN;
- return (char) sm;
- }
-
- /**
- * Show the given raw packed <code>binary16</code> 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();
- }
-
- /**
- * <p>
- * Convert a packed <code>binary16</code> value <code>k</code> to a
- * double-precision floating point value.
- * </p>
- * <p>
- * The function returns:
- * </p>
- * <ul>
- * <li><code>NaN</code> iff <code>isNaN(k)</code></li>
- * <li>{@link Double#POSITIVE_INFINITY} iff
- * <code>k == {@link #POSITIVE_INFINITY}</code></li>
- * <li>{@link Double#NEGATIVE_INFINITY} iff
- * <code>k == {@link #NEGATIVE_INFINITY}</code></li>
- * <li><code>-0.0</code> iff <code>k == {@link #NEGATIVE_ZERO}</code></li>
- * <li><code>0.0</code> iff <code>k == {@link #POSITIVE_ZERO}</code></li>
- * <li><code>(-1.0 * n) * (2 ^ e) * 1.s</code>, for the decoded sign
- * <code>n</code> of <code>k</code>, the decoded exponent <code>e</code> of
- * <code>k</code>, and the decoded significand <code>s</code> of
- * <code>k</code>.</li>
- * </ul>
- *
- * @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);
- }
-
- /**
- * <p>
- * Convert a packed <code>binary16</code> value <code>k</code> to a
- * single-precision floating point value.
- * </p>
- * <p>
- * The function returns:
- * </p>
- * <ul>
- * <li><code>NaN</code> iff <code>isNaN(k)</code></li>
- * <li>{@link Float#POSITIVE_INFINITY} iff
- * <code>k == {@link #POSITIVE_INFINITY}</code></li>
- * <li>{@link Float#NEGATIVE_INFINITY} iff
- * <code>k == {@link #NEGATIVE_INFINITY}</code></li>
- * <li><code>-0.0</code> iff <code>k == {@link #NEGATIVE_ZERO}</code></li>
- * <li><code>0.0</code> iff <code>k == {@link #POSITIVE_ZERO}</code></li>
- * <li><code>(-1.0 * n) * (2 ^ e) * 1.s</code>, for the decoded sign
- * <code>n</code> of <code>k</code>, the decoded exponent <code>e</code> of
- * <code>k</code>, and the decoded significand <code>s</code> of
- * <code>k</code>.</li>
- * </ul>
- *
- * @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);
- }
-
- /**
- * <p>
- * Extract and unbias the exponent of the given packed <code>binary16</code>
- * value.
- * </p>
- * <p>
- * The exponent is encoded <i>biased</i> as a number in the range
- * <code>[0, 31]</code>, with <code>0</code> indicating that the number is
- * <i>subnormal</i> and <code>[1, 30]</code> denoting the actual exponent
- * plus {@link #BIAS}. Infinite and <code>NaN</code> values always have an
- * exponent of <code>31</code>.
- * </p>
- * <p>
- * This function will therefore return:
- * </p>
- * <ul>
- * <li>
- * <code>0 - {@link #BIAS} = -15</code> iff the input is a <i>subnormal</i>
- * number.</li>
- * <li>An integer in the range
- * <code>[1 - {@link #BIAS}, 30 - {@link #BIAS}] = [-14, 15]</code> iff the
- * input is a <i>normal</i> number.</li>
- * <li>
- * <code>16</code> iff the input is {@link #POSITIVE_INFINITY},
- * {@link #NEGATIVE_INFINITY}, or <code>NaN</code>.</li>
- * </ul>
- *
- * @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 <code>binary16</code> value, as
- * an integer in the range <code>[0, 1]</code>.
- *
- * @see Binary16#packSetSignUnchecked(int)
- */
-
- public static int unpackGetSign(
- final char k)
- {
- return (k & Binary16.MASK_SIGN) >> 15;
- }
-
- /**
- * <p>
- * Return the significand of the given packed <code>binary16</code> value as
- * an integer in the range <code>[0, 1023]</code>.
- * </p>
- *
- * @see Binary16#packSetSignificandUnchecked(int)
- */
-
- public static int unpackGetSignificand(
- final char k)
- {
- return k & Binary16.MASK_SIGNIFICAND;
- }
-
- private Binary16()
- {
- throw new AssertionError("Unreachable code, report this bug!");
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Binary32.java b/src/jogl/classes/com/jogamp/opengl/math/Binary32.java
deleted file mode 100644
index 599b1ff68..000000000
--- a/src/jogl/classes/com/jogamp/opengl/math/Binary32.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * Copyright 2013 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;
-
-/**
- * Functions for interrogating <code>binary32</code> (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;
- }
-
- /**
- * <p>
- * Extract and unbias the exponent of the given packed <code>float</code>
- * value.
- * </p>
- * <p>
- * The exponent is encoded <i>biased</i> as a number in the range
- * <code>[0, 255]</code>, with <code>0</code> indicating that the number is
- * <i>subnormal</i> and <code>[1, 254]</code> denoting the actual exponent
- * plus {@link #BIAS}. Infinite and <code>NaN</code> values always have a
- * biased exponent of <code>255</code>.
- * </p>
- * <p>
- * This function will therefore return:
- * </p>
- * <ul>
- * <li>
- * <code>0 - {@link #BIAS} = -127</code> iff the input is a <i>subnormal</i>
- * number.</li>
- * <li>An integer in the range
- * <code>[1 - {@link #BIAS}, 254 - {@link #BIAS}] = [-126, 127]</code> iff
- * the input is a <i>normal</i> number.</li>
- * <li>
- * <code>255 - {@link #BIAS} = 128</code> iff the input is
- * {@link #POSITIVE_INFINITY}, {@link #NEGATIVE_INFINITY}, or
- * <code>NaN</code>.</li>
- * </ul>
- *
- * @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;
- }
-
- /**
- * <p>
- * Return the sign of the given float value.
- * </p>
- */
-
- public static int unpackGetSign(
- final float d)
- {
- final int b = Float.floatToRawIntBits(d);
- return ((b & Binary32.MASK_SIGN) >> 31) & 1;
- }
-
- /**
- * <p>
- * Return the significand of the given float value.
- * </p>
- */
-
- public static int unpackGetSignificand(
- final float d)
- {
- final int b = Float.floatToRawIntBits(d);
- return b & Binary32.MASK_SIGNIFICAND;
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Binary64.java b/src/jogl/classes/com/jogamp/opengl/math/Binary64.java
deleted file mode 100644
index d4ec636a5..000000000
--- a/src/jogl/classes/com/jogamp/opengl/math/Binary64.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * Copyright 2013 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;
-
-/**
- * Functions for interrogating <code>binary64</code> (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;
- }
-
- /**
- * <p>
- * Extract and unbias the exponent of the given packed <code>double</code>
- * value.
- * </p>
- * <p>
- * The exponent is encoded <i>biased</i> as a number in the range
- * <code>[0, 2047]</code>, with <code>0</code> indicating that the number is
- * <i>subnormal</i> and <code>[1, 2046]</code> denoting the actual exponent
- * plus {@link #BIAS}. Infinite and <code>NaN</code> values always have a
- * biased exponent of <code>2047</code>.
- * </p>
- * <p>
- * This function will therefore return:
- * </p>
- * <ul>
- * <li>
- * <code>0 - {@link #BIAS} = -1023</code> iff the input is a
- * <i>subnormal</i> number.</li>
- * <li>An integer in the range
- * <code>[1 - {@link #BIAS}, 2046 - {@link #BIAS}] = [-1022, 1023]</code>
- * iff the input is a <i>normal</i> number.</li>
- * <li>
- * <code>2047 - {@link #BIAS} = 1024</code> iff the input is
- * {@link #POSITIVE_INFINITY}, {@link #NEGATIVE_INFINITY}, or
- * <code>NaN</code>.</li>
- * </ul>
- *
- * @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;
- }
-
- /**
- * <p>
- * Return the significand of the given double value.
- * </p>
- */
-
- public static long unpackGetSignificand(
- final double d)
- {
- final long b = Double.doubleToRawLongBits(d);
- return b & Binary64.MASK_SIGNIFICAND;
- }
-
- /**
- * <p>
- * Return the sign of the given double value.
- * </p>
- */
-
- public static long unpackGetSign(
- final double d)
- {
- final long b = Double.doubleToRawLongBits(d);
- return ((b & Binary64.MASK_SIGN) >> 63) & 1;
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/FixedPoint.java b/src/jogl/classes/com/jogamp/opengl/math/FixedPoint.java
deleted file mode 100644
index 31408b079..000000000
--- a/src/jogl/classes/com/jogamp/opengl/math/FixedPoint.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution 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.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- */
-
-package com.jogamp.opengl.math;
-
-public class FixedPoint {
- public static final int toFixed(int value) {
- if (value < -32768) value = -32768;
- if (value > 32767) value = 32767;
- return value * 65536;
- }
-
- public static final int toFixed(float value) {
- if (value < -32768) value = -32768;
- if (value > 32767) value = 32767;
- return (int)(value * 65536.0f);
- }
-
- public static final float toFloat(final int value) {
- return value/65536.0f;
- }
-
- public static final int mult(final int x1, final int x2) {
- return (int) ( ((long)x1*(long)x2)/65536 );
- }
-
- public static final int div(final int x1, final int x2) {
- return (int) ( (((long)x1)<<16)/x2 );
- }
-}
-
diff --git a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
deleted file mode 100644
index 25b5a8ad7..000000000
--- a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
+++ /dev/null
@@ -1,1628 +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;
-
-import java.nio.FloatBuffer;
-import java.util.Locale;
-
-import com.jogamp.opengl.GLException;
-
-import jogamp.opengl.Debug;
-
-import com.jogamp.common.os.Platform;
-
-/**
- * Basic Float math utility functions.
- * <p>
- * Implementation assumes linear matrix layout in column-major order
- * matching OpenGL's implementation, illustration:
- * <pre>
- 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;
-
- * </pre>
- * </p>
- * <p>
- * <ul>
- * <li><a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html">Matrix-FAQ</a></li>
- * <li><a href="https://en.wikipedia.org/wiki/Matrix_%28mathematics%29">Wikipedia-Matrix</a></li>
- * <li><a href="http://www.euclideanspace.com/maths/algebra/matrix/index.htm">euclideanspace.com-Matrix</a></li>
- * </ul>
- * </p>
- * <p>
- * Implementation utilizes unrolling of small vertices and matrices wherever possible
- * while trying to access memory in a linear fashion for performance reasons, see:
- * <ul>
- * <li><a href="https://lessthanoptimal.github.io/Java-Matrix-Benchmark/">java-matrix-benchmark</a></li>
- * <li><a href="https://github.com/lessthanoptimal/ejml">EJML Efficient Java Matrix Library</a></li>
- * </ul>
- * </p>
- */
-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
- * <pre>
- Translation matrix (Column Order):
- 1 0 0 0
- 0 1 0 0
- 0 0 1 0
- x y z 1
- * </pre>
- * <p>
- * All matrix fields are only set if <code>initM</code> is <code>true</code>.
- * </p>
- * @param m 4x4 matrix in column-major order (also result)
- * @param initM if true, given matrix will be initialized w/ identity matrix,
- * otherwise only the diagonal and last-row is set.
- * The latter can be utilized to share a once {@link #makeIdentity(float[], int) identity set} matrix
- * for {@link #makeScale(float[], int, boolean, float, float, float) scaling}
- * and {@link #makeTranslation(float[], int, boolean, float, float, float) translation},
- * while leaving the other fields untouched for performance reasons.
- * @return given matrix for chaining
- */
- public static float[] makeTranslation(final float[] m, final boolean initM, final float tx, final float ty, final float tz) {
- if( initM ) {
- makeIdentity(m);
- } else {
- m[0+4*0] = 1;
- m[1+4*1] = 1;
- m[2+4*2] = 1;
- m[3+4*3] = 1;
- }
- m[0+4*3] = tx;
- m[1+4*3] = ty;
- m[2+4*3] = tz;
- return m;
- }
-
- /**
- * Make a scale matrix in column-major order from the given axis factors
- * <pre>
- Scale matrix (Any Order):
- x 0 0 0
- 0 y 0 0
- 0 0 z 0
- 0 0 0 1
- * </pre>
- * <p>
- * All matrix fields are only set if <code>initM</code> is <code>true</code>.
- * </p>
- * @param m 4x4 matrix in column-major order (also result)
- * @param initM if true, given matrix will be initialized w/ identity matrix,
- * otherwise only the diagonal and last-row is set.
- * The latter can be utilized to share a once {@link #makeIdentity(float[], int) identity set} matrix
- * for {@link #makeScale(float[], int, boolean, float, float, float) scaling}
- * and {@link #makeTranslation(float[], int, boolean, float, float, float) translation},
- * while leaving the other fields untouched for performance reasons.
- * @return given matrix for chaining
- */
- public static float[] makeScale(final float[] m, final boolean initM, final float sx, final float sy, final float sz) {
- if( initM ) {
- makeIdentity(m);
- } else {
- m[0+4*3] = 0;
- m[1+4*3] = 0;
- m[2+4*3] = 0;
- m[3+4*3] = 1;
- }
- m[0+4*0] = sx;
- m[1+4*1] = sy;
- m[2+4*2] = sz;
- return m;
- }
-
- /**
- * Make given matrix the frustum matrix based on given parameters.
- * <pre>
- Frustum matrix (Column Order):
- 2*zNear/dx 0 0 0
- 0 2*zNear/dy 0 0
- A B C -1
- 0 0 D 0
- * </pre>
- * <p>
- * All matrix fields are only set if <code>initM</code> is <code>true</code>.
- * </p>
- *
- * @param m 4x4 matrix in column-major order (also result)
- * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix
- * @param initM if true, given matrix will be initialized w/ identity matrix,
- * otherwise only the frustum fields are set.
- * @param left
- * @param right
- * @param bottom
- * @param top
- * @param zNear
- * @param zFar
- * @return given matrix for chaining
- * @throws GLException if {@code zNear <= 0} or {@code zFar <= zNear}
- * or {@code left == right}, or {@code bottom == top}.
- */
- public static float[] makeFrustum(final float[] m, final int m_offset, final boolean initM,
- final float left, final float right,
- final float bottom, final float top,
- final float zNear, final float zFar) throws GLException {
- if( zNear <= 0.0f || zFar <= zNear ) {
- throw new GLException("Requirements zNear > 0 and zFar > zNear, but zNear "+zNear+", zFar "+zFar);
- }
- if( left == right || top == bottom) {
- throw new GLException("GL_INVALID_VALUE: top,bottom and left,right must not be equal");
- }
- if( initM ) {
- // m[m_offset+0+4*0] = 1f;
- m[m_offset+1+4*0] = 0f;
- m[m_offset+2+4*0] = 0f;
- m[m_offset+3+4*0] = 0f;
-
- m[m_offset+0+4*1] = 0f;
- // m[m_offset+1+4*1] = 1f;
- m[m_offset+2+4*1] = 0f;
- m[m_offset+3+4*1] = 0f;
-
- // m[m_offset+0+4*2] = 0f;
- // m[m_offset+1+4*2] = 0f;
- // m[m_offset+2+4*2] = 1f;
- // m[m_offset+3+4*2] = 0f;
-
- m[m_offset+0+4*3] = 0f;
- m[m_offset+1+4*3] = 0f;
- // m[m_offset+2+4*3] = 0f;
- // m[m_offset+3+4*3] = 1f;
- }
- 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;
-
- m[m_offset+0+4*0] = zNear2/dx;
-
- m[m_offset+1+4*1] = zNear2/dy;
-
- m[m_offset+0+4*2] = A;
- m[m_offset+1+4*2] = B;
- m[m_offset+2+4*2] = C;
- m[m_offset+3+4*2] = -1.0f;
-
- m[m_offset+2+4*3] = D;
- m[m_offset+3+4*3] = 0f;
-
- return m;
- }
-
- /**
- * Make given matrix the perspective {@link #makeFrustum(float[], int, boolean, float, float, float, float, float, float) frustum}
- * matrix based on given parameters.
- * <p>
- * All matrix fields are only set if <code>initM</code> is <code>true</code>.
- * </p>
- *
- * @param m 4x4 matrix in column-major order (also result)
- * @param m_offset offset in given array <i>m</i>, i.e. start of the 4x4 matrix
- * @param initM if true, given matrix will be initialized w/ identity matrix,
- * otherwise only the frustum fields are set.
- * @param fovy_rad angle in radians
- * @param aspect aspect ratio width / height
- * @param zNear
- * @param zFar
- * @return given matrix for chaining
- * @throws GLException if {@code zNear <= 0} or {@code zFar <= zNear}
- * @see #makeFrustum(float[], int, boolean, float, float, float, float, float, float)
- */
- public static float[] makePerspective(final float[] m, final int m_off, final boolean initM,
- final float fovy_rad, final float aspect, final float zNear, final float zFar) throws GLException {
- final float top = 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 makeFrustum(m, m_off, initM, left, right, bottom, top, zNear, zFar);
- }
-
- /**
- * Make given matrix the <i>look-at</i> matrix based on given parameters.
- * <p>
- * Consist out of two matrix multiplications:
- * <pre>
- * <b>R</b> = <b>L</b> x <b>T</b>,
- * with <b>L</b> for <i>look-at</i> matrix and
- * <b>T</b> for eye translation.
- *
- * Result <b>R</b> can be utilized for <i>modelview</i> multiplication, i.e.
- * <b>M</b> = <b>M</b> x <b>R</b>,
- * with <b>M</b> being the <i>modelview</i> matrix.
- * </pre>
- * </p>
- * <p>
- * All matrix fields are set.
- * </p>
- * @param m 4x4 matrix in column-major order, result only
- * @param m_offset offset in given array <i>m</i>, 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 matrix <code>m</code> 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 <i>pick</i> matrix based on given parameters.
- * <p>
- * Traditional <code>gluPickMatrix</code> implementation.
- * </p>
- * <p>
- * Consist out of two matrix multiplications:
- * <pre>
- * <b>R</b> = <b>T</b> x <b>S</b>,
- * with <b>T</b> for viewport translation matrix and
- * <b>S</b> for viewport scale matrix.
- *
- * Result <b>R</b> can be utilized for <i>projection</i> multiplication, i.e.
- * <b>P</b> = <b>P</b> x <b>R</b>,
- * with <b>P</b> being the <i>projection</i> matrix.
- * </pre>
- * </p>
- * <p>
- * 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.
- * </p>
- * <p>
- * All matrix fields are set.
- * </p>
- * @param m 4x4 matrix in column-major order, result only
- * @param m_offset offset in given array <i>m</i>, 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 matrix <code>m</code> for chaining or <code>null</code> 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 <i>mres</i> 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.
- * <p>
- * Returns <code>null</code> if inversion is not possible,
- * e.g. matrix is singular due to a bad matrix.
- * </p>
- *
- * @param msrc 4x4 matrix in column-major order, the source
- * @param mres 4x4 matrix in column-major order, the result - may be <code>msrc</code> (in-place)
- * @return given result matrix <i>mres</i> for chaining if successful, otherwise <code>null</code>. 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.
- * <p>
- * Traditional <code>gluProject</code> implementation.
- * </p>
- *
- * @param objx
- * @param objy
- * @param objz
- * @param modelMatrix 4x4 modelview matrix
- * @param modelMatrix_offset
- * @param projMatrix 4x4 projection matrix
- * @param projMatrix_offset
- * @param viewport 4 component viewport vector
- * @param viewport_offset
- * @param win_pos 3 component window coordinate, the result
- * @param win_pos_offset
- * @param vec4Tmp1 4 component vector for temp storage
- * @param vec4Tmp2 4 component vector for temp storage
- * @return true if successful, otherwise false (z is 1)
- */
- public static boolean mapObjToWin(final float objx, final float objy, final float objz,
- final float[] modelMatrix, final int modelMatrix_offset,
- final float[] projMatrix, final int projMatrix_offset,
- final int[] viewport, final int viewport_offset,
- final float[] win_pos, final int win_pos_offset,
- final float[/*4*/] vec4Tmp1, final float[/*4*/] vec4Tmp2) {
- vec4Tmp1[0] = objx;
- vec4Tmp1[1] = objy;
- vec4Tmp1[2] = objz;
- vec4Tmp1[3] = 1.0f;
-
- // vec4Tmp2 = Mv * o
- // vec4Tmp1 = P * vec4Tmp2
- // vec4Tmp1 = P * ( Mv * o )
- // vec4Tmp1 = P * Mv * o
- multMatrixVec(modelMatrix, modelMatrix_offset, vec4Tmp1, 0, vec4Tmp2, 0);
- multMatrixVec(projMatrix, projMatrix_offset, vec4Tmp2, 0, vec4Tmp1, 0);
-
- if (vec4Tmp1[3] == 0.0f) {
- return false;
- }
-
- vec4Tmp1[3] = (1.0f / vec4Tmp1[3]) * 0.5f;
-
- // Map x, y and z to range 0-1
- vec4Tmp1[0] = vec4Tmp1[0] * vec4Tmp1[3] + 0.5f;
- vec4Tmp1[1] = vec4Tmp1[1] * vec4Tmp1[3] + 0.5f;
- vec4Tmp1[2] = vec4Tmp1[2] * vec4Tmp1[3] + 0.5f;
-
- // Map x,y to viewport
- win_pos[0+win_pos_offset] = vec4Tmp1[0] * viewport[2+viewport_offset] + viewport[0+viewport_offset];
- win_pos[1+win_pos_offset] = vec4Tmp1[1] * viewport[3+viewport_offset] + viewport[1+viewport_offset];
- win_pos[2+win_pos_offset] = vec4Tmp1[2];
-
- return true;
- }
-
- /**
- * Map window coordinates to object coordinates.
- * <p>
- * Traditional <code>gluUnProject</code> implementation.
- * </p>
- *
- * @param winx
- * @param winy
- * @param winz
- * @param modelMatrix 4x4 modelview matrix
- * @param modelMatrix_offset
- * @param projMatrix 4x4 projection matrix
- * @param projMatrix_offset
- * @param viewport 4 component viewport vector
- * @param viewport_offset
- * @param obj_pos 3 component object coordinate, the result
- * @param obj_pos_offset
- * @param mat4Tmp1 16 component matrix for temp storage
- * @param mat4Tmp2 16 component matrix for temp storage
- * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
- */
- public static boolean mapWinToObj(final float winx, final float winy, final float winz,
- final float[] modelMatrix, final int modelMatrix_offset,
- final float[] projMatrix, final int projMatrix_offset,
- final int[] viewport, final int viewport_offset,
- final float[] obj_pos, final int obj_pos_offset,
- final float[/*16*/] mat4Tmp1, final float[/*16*/] mat4Tmp2) {
- // mat4Tmp1 = P x Mv
- multMatrix(projMatrix, projMatrix_offset, modelMatrix, modelMatrix_offset, mat4Tmp1, 0);
-
- // mat4Tmp1 = Inv(P x Mv)
- if ( null == invertMatrix(mat4Tmp1, mat4Tmp1) ) {
- return false;
- }
- mat4Tmp2[0] = winx;
- mat4Tmp2[1] = winy;
- mat4Tmp2[2] = winz;
- mat4Tmp2[3] = 1.0f;
-
- // Map x and y from window coordinates
- mat4Tmp2[0] = (mat4Tmp2[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset];
- mat4Tmp2[1] = (mat4Tmp2[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset];
-
- // Map to range -1 to 1
- mat4Tmp2[0] = mat4Tmp2[0] * 2 - 1;
- mat4Tmp2[1] = mat4Tmp2[1] * 2 - 1;
- mat4Tmp2[2] = mat4Tmp2[2] * 2 - 1;
-
- final int raw_off = 4;
- // object raw coords = Inv(P x Mv) * winPos -> mat4Tmp2
- multMatrixVec(mat4Tmp1, 0, mat4Tmp2, 0, mat4Tmp2, raw_off);
-
- if (mat4Tmp2[3+raw_off] == 0.0) {
- return false;
- }
-
- mat4Tmp2[3+raw_off] = 1.0f / mat4Tmp2[3+raw_off];
-
- obj_pos[0+obj_pos_offset] = mat4Tmp2[0+raw_off] * mat4Tmp2[3+raw_off];
- obj_pos[1+obj_pos_offset] = mat4Tmp2[1+raw_off] * mat4Tmp2[3+raw_off];
- obj_pos[2+obj_pos_offset] = mat4Tmp2[2+raw_off] * mat4Tmp2[3+raw_off];
-
- return true;
- }
-
- /**
- * Map window coordinates to object coordinates.
- * <p>
- * Traditional <code>gluUnProject4</code> implementation.
- * </p>
- *
- * @param winx
- * @param winy
- * @param winz
- * @param clipw
- * @param modelMatrix 4x4 modelview matrix
- * @param modelMatrix_offset
- * @param projMatrix 4x4 projection matrix
- * @param projMatrix_offset
- * @param viewport 4 component viewport vector
- * @param viewport_offset
- * @param near
- * @param far
- * @param obj_pos 4 component object coordinate, the result
- * @param obj_pos_offset
- * @param mat4Tmp1 16 component matrix for temp storage
- * @param mat4Tmp2 16 component matrix for temp storage
- * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
- */
- public static boolean mapWinToObj4(final float winx, final float winy, final float winz, final float clipw,
- final float[] modelMatrix, final int modelMatrix_offset,
- final float[] projMatrix, final int projMatrix_offset,
- final int[] viewport, final int viewport_offset,
- final float near, final float far,
- final float[] obj_pos, final int obj_pos_offset,
- final float[/*16*/] mat4Tmp1, final float[/*16*/] mat4Tmp2) {
- // mat4Tmp1 = P x Mv
- multMatrix(projMatrix, projMatrix_offset, modelMatrix, modelMatrix_offset, mat4Tmp1, 0);
-
- // mat4Tmp1 = Inv(P x Mv)
- if ( null == invertMatrix(mat4Tmp1, mat4Tmp1) ) {
- return false;
- }
-
- mat4Tmp2[0] = winx;
- mat4Tmp2[1] = winy;
- mat4Tmp2[2] = winz;
- mat4Tmp2[3] = clipw;
-
- // Map x and y from window coordinates
- mat4Tmp2[0] = (mat4Tmp2[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset];
- mat4Tmp2[1] = (mat4Tmp2[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset];
- mat4Tmp2[2] = (mat4Tmp2[2] - near) / (far - near);
-
- // Map to range -1 to 1
- mat4Tmp2[0] = mat4Tmp2[0] * 2 - 1;
- mat4Tmp2[1] = mat4Tmp2[1] * 2 - 1;
- mat4Tmp2[2] = mat4Tmp2[2] * 2 - 1;
-
- final int raw_off = 4;
- // object raw coords = Inv(P x Mv) * winPos -> mat4Tmp2
- multMatrixVec(mat4Tmp1, 0, mat4Tmp2, 0, mat4Tmp2, raw_off);
-
- if (mat4Tmp2[3+raw_off] == 0.0) {
- return false;
- }
-
- obj_pos[0+obj_pos_offset] = mat4Tmp2[0+raw_off];
- obj_pos[1+obj_pos_offset] = mat4Tmp2[1+raw_off];
- obj_pos[2+obj_pos_offset] = mat4Tmp2[2+raw_off];
- obj_pos[3+obj_pos_offset] = mat4Tmp2[3+raw_off];
-
- return true;
- }
-
- /**
- * Multiply matrix: [d] = [a] x [b]
- * @param a 4x4 matrix in column-major order
- * @param b 4x4 matrix in column-major order
- * @param d result a*b in column-major order
- */
- public static void multMatrix(final float[] a, final int a_off, final float[] b, final int b_off, final float[] d, final int d_off) {
- final float b00 = b[b_off+0+0*4];
- final float b10 = b[b_off+1+0*4];
- final float b20 = b[b_off+2+0*4];
- final float b30 = b[b_off+3+0*4];
- final float b01 = b[b_off+0+1*4];
- final float b11 = b[b_off+1+1*4];
- final float b21 = b[b_off+2+1*4];
- final float b31 = b[b_off+3+1*4];
- final float b02 = b[b_off+0+2*4];
- final float b12 = b[b_off+1+2*4];
- final float b22 = b[b_off+2+2*4];
- final float b32 = b[b_off+3+2*4];
- final float b03 = b[b_off+0+3*4];
- final float b13 = b[b_off+1+3*4];
- final float b23 = b[b_off+2+3*4];
- final float b33 = b[b_off+3+3*4];
-
- float ai0=a[a_off+ 0*4]; // row-0 of a
- float ai1=a[a_off+ 1*4];
- float ai2=a[a_off+ 2*4];
- float ai3=a[a_off+ 3*4];
- d[d_off+ 0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- d[d_off+ 1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- d[d_off+ 2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- d[d_off+ 3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
-
- ai0=a[a_off+1+0*4]; // row-1 of a
- ai1=a[a_off+1+1*4];
- ai2=a[a_off+1+2*4];
- ai3=a[a_off+1+3*4];
- d[d_off+1+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- d[d_off+1+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- d[d_off+1+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- d[d_off+1+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
-
- ai0=a[a_off+2+0*4]; // row-2 of a
- ai1=a[a_off+2+1*4];
- ai2=a[a_off+2+2*4];
- ai3=a[a_off+2+3*4];
- d[d_off+2+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- d[d_off+2+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- d[d_off+2+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- d[d_off+2+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
-
- ai0=a[a_off+3+0*4]; // row-3 of a
- ai1=a[a_off+3+1*4];
- ai2=a[a_off+3+2*4];
- ai3=a[a_off+3+3*4];
- d[d_off+3+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- d[d_off+3+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- d[d_off+3+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- d[d_off+3+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
- }
-
- /**
- * Multiply matrix: [d] = [a] x [b]
- * @param a 4x4 matrix in column-major order
- * @param b 4x4 matrix in column-major order
- * @param d result a*b in column-major order
- * @return given result matrix <i>d</i> for chaining
- */
- public static float[] multMatrix(final float[] a, final float[] b, final float[] d) {
- final float b00 = b[0+0*4];
- final float b10 = b[1+0*4];
- final float b20 = b[2+0*4];
- final float b30 = b[3+0*4];
- final float b01 = b[0+1*4];
- final float b11 = b[1+1*4];
- final float b21 = b[2+1*4];
- final float b31 = b[3+1*4];
- final float b02 = b[0+2*4];
- final float b12 = b[1+2*4];
- final float b22 = b[2+2*4];
- final float b32 = b[3+2*4];
- final float b03 = b[0+3*4];
- final float b13 = b[1+3*4];
- final float b23 = b[2+3*4];
- final float b33 = b[3+3*4];
-
- float ai0=a[ 0*4]; // row-0 of a
- float ai1=a[ 1*4];
- float ai2=a[ 2*4];
- float ai3=a[ 3*4];
- d[ 0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- d[ 1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- d[ 2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- d[ 3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
-
- ai0=a[1+0*4]; // row-1 of a
- ai1=a[1+1*4];
- ai2=a[1+2*4];
- ai3=a[1+3*4];
- d[1+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- d[1+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- d[1+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- d[1+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
-
- ai0=a[2+0*4]; // row-2 of a
- ai1=a[2+1*4];
- ai2=a[2+2*4];
- ai3=a[2+3*4];
- d[2+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- d[2+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- d[2+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- d[2+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
-
- ai0=a[3+0*4]; // row-3 of a
- ai1=a[3+1*4];
- ai2=a[3+2*4];
- ai3=a[3+3*4];
- d[3+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- d[3+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- d[3+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- d[3+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
-
- return d;
- }
-
- /**
- * Multiply matrix: [a] = [a] x [b]
- * @param a 4x4 matrix in column-major order (also result)
- * @param b 4x4 matrix in column-major order
- */
- public static void multMatrix(final float[] a, final int a_off, final float[] b, final int b_off) {
- final float b00 = b[b_off+0+0*4];
- final float b10 = b[b_off+1+0*4];
- final float b20 = b[b_off+2+0*4];
- final float b30 = b[b_off+3+0*4];
- final float b01 = b[b_off+0+1*4];
- final float b11 = b[b_off+1+1*4];
- final float b21 = b[b_off+2+1*4];
- final float b31 = b[b_off+3+1*4];
- final float b02 = b[b_off+0+2*4];
- final float b12 = b[b_off+1+2*4];
- final float b22 = b[b_off+2+2*4];
- final float b32 = b[b_off+3+2*4];
- final float b03 = b[b_off+0+3*4];
- final float b13 = b[b_off+1+3*4];
- final float b23 = b[b_off+2+3*4];
- final float b33 = b[b_off+3+3*4];
-
- float ai0=a[a_off+ 0*4]; // row-0 of a
- float ai1=a[a_off+ 1*4];
- float ai2=a[a_off+ 2*4];
- float ai3=a[a_off+ 3*4];
- a[a_off+ 0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- a[a_off+ 1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- a[a_off+ 2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- a[a_off+ 3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
-
- ai0=a[a_off+1+0*4]; // row-1 of a
- ai1=a[a_off+1+1*4];
- ai2=a[a_off+1+2*4];
- ai3=a[a_off+1+3*4];
- a[a_off+1+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- a[a_off+1+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- a[a_off+1+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- a[a_off+1+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
-
- ai0=a[a_off+2+0*4]; // row-2 of a
- ai1=a[a_off+2+1*4];
- ai2=a[a_off+2+2*4];
- ai3=a[a_off+2+3*4];
- a[a_off+2+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- a[a_off+2+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- a[a_off+2+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- a[a_off+2+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
-
- ai0=a[a_off+3+0*4]; // row-3 of a
- ai1=a[a_off+3+1*4];
- ai2=a[a_off+3+2*4];
- ai3=a[a_off+3+3*4];
- a[a_off+3+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- a[a_off+3+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- a[a_off+3+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- a[a_off+3+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
- }
-
- /**
- * Multiply matrix: [a] = [a] x [b]
- * @param a 4x4 matrix in column-major order (also result)
- * @param b 4x4 matrix in column-major order
- * @return given result matrix <i>a</i> for chaining
- */
- public static float[] multMatrix(final float[] a, final float[] b) {
- final float b00 = b[0+0*4];
- final float b10 = b[1+0*4];
- final float b20 = b[2+0*4];
- final float b30 = b[3+0*4];
- final float b01 = b[0+1*4];
- final float b11 = b[1+1*4];
- final float b21 = b[2+1*4];
- final float b31 = b[3+1*4];
- final float b02 = b[0+2*4];
- final float b12 = b[1+2*4];
- final float b22 = b[2+2*4];
- final float b32 = b[3+2*4];
- final float b03 = b[0+3*4];
- final float b13 = b[1+3*4];
- final float b23 = b[2+3*4];
- final float b33 = b[3+3*4];
-
- float ai0=a[ 0*4]; // row-0 of a
- float ai1=a[ 1*4];
- float ai2=a[ 2*4];
- float ai3=a[ 3*4];
- a[ 0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- a[ 1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- a[ 2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- a[ 3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
-
- ai0=a[1+0*4]; // row-1 of a
- ai1=a[1+1*4];
- ai2=a[1+2*4];
- ai3=a[1+3*4];
- a[1+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- a[1+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- a[1+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- a[1+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
-
- ai0=a[2+0*4]; // row-2 of a
- ai1=a[2+1*4];
- ai2=a[2+2*4];
- ai3=a[2+3*4];
- a[2+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- a[2+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- a[2+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- a[2+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
-
- ai0=a[3+0*4]; // row-3 of a
- ai1=a[3+1*4];
- ai2=a[3+2*4];
- ai3=a[3+3*4];
- a[3+0*4] = ai0 * b00 + ai1 * b10 + ai2 * b20 + ai3 * b30 ;
- a[3+1*4] = ai0 * b01 + ai1 * b11 + ai2 * b21 + ai3 * b31 ;
- a[3+2*4] = ai0 * b02 + ai1 * b12 + ai2 * b22 + ai3 * b32 ;
- a[3+3*4] = ai0 * b03 + ai1 * b13 + ai2 * b23 + ai3 * b33 ;
-
- return a;
- }
-
- /**
- * Multiply matrix: [d] = [a] x [b]
- * @param a 4x4 matrix in column-major order
- * @param b 4x4 matrix in column-major order
- * @param d result a*b in column-major order
- */
- public static void multMatrix(final FloatBuffer a, final FloatBuffer b, final float[] d) {
- final int a_off = a.position();
- final int b_off = b.position();
- for (int i = 0; i < 4; i++) {
- // one row in column-major order
- final int a_off_i = a_off+i;
- final float ai0=a.get(a_off_i+0*4), ai1=a.get(a_off_i+1*4), ai2=a.get(a_off_i+2*4), ai3=a.get(a_off_i+3*4); // row-i of a
- d[i+0*4] = ai0 * b.get(b_off+0+0*4) + ai1 * b.get(b_off+1+0*4) + ai2 * b.get(b_off+2+0*4) + ai3 * b.get(b_off+3+0*4) ;
- d[i+1*4] = ai0 * b.get(b_off+0+1*4) + ai1 * b.get(b_off+1+1*4) + ai2 * b.get(b_off+2+1*4) + ai3 * b.get(b_off+3+1*4) ;
- d[i+2*4] = ai0 * b.get(b_off+0+2*4) + ai1 * b.get(b_off+1+2*4) + ai2 * b.get(b_off+2+2*4) + ai3 * b.get(b_off+3+2*4) ;
- d[i+3*4] = ai0 * b.get(b_off+0+3*4) + ai1 * b.get(b_off+1+3*4) + ai2 * b.get(b_off+2+3*4) + ai3 * b.get(b_off+3+3*4) ;
- }
- }
-
- /**
- * Multiply matrix: [a] = [a] x [b]
- * @param a 4x4 matrix in column-major order (also result)
- * @param b 4x4 matrix in column-major order
- */
- public static void multMatrix(final FloatBuffer a, final FloatBuffer b) {
- final int a_off = a.position();
- final int b_off = b.position();
- for (int i = 0; i < 4; i++) {
- // one row in column-major order
- final int a_off_i = a_off+i;
- final float ai0=a.get(a_off_i+0*4), ai1=a.get(a_off_i+1*4), ai2=a.get(a_off_i+2*4), ai3=a.get(a_off_i+3*4); // row-i of a
- a.put(a_off_i+0*4 , ai0 * b.get(b_off+0+0*4) + ai1 * b.get(b_off+1+0*4) + ai2 * b.get(b_off+2+0*4) + ai3 * b.get(b_off+3+0*4) );
- a.put(a_off_i+1*4 , ai0 * b.get(b_off+0+1*4) + ai1 * b.get(b_off+1+1*4) + ai2 * b.get(b_off+2+1*4) + ai3 * b.get(b_off+3+1*4) );
- a.put(a_off_i+2*4 , ai0 * b.get(b_off+0+2*4) + ai1 * b.get(b_off+1+2*4) + ai2 * b.get(b_off+2+2*4) + ai3 * b.get(b_off+3+2*4) );
- a.put(a_off_i+3*4 , ai0 * b.get(b_off+0+3*4) + ai1 * b.get(b_off+1+3*4) + ai2 * b.get(b_off+2+3*4) + ai3 * b.get(b_off+3+3*4) );
- }
- }
-
- /**
- * @param m_in 4x4 matrix in column-major order
- * @param m_in_off
- * @param v_in 4-component column-vector
- * @param v_out m_in * v_in
- */
- public static void multMatrixVec(final float[] m_in, final int m_in_off,
- final float[] v_in, final int v_in_off,
- final float[] v_out, final int v_out_off) {
- // (one matrix row in column-major order) X (column vector)
- v_out[0 + v_out_off] = v_in[0+v_in_off] * m_in[0*4+m_in_off ] + v_in[1+v_in_off] * m_in[1*4+m_in_off ] +
- v_in[2+v_in_off] * m_in[2*4+m_in_off ] + v_in[3+v_in_off] * m_in[3*4+m_in_off ];
-
- final int m_in_off_1 = 1+m_in_off;
- v_out[1 + v_out_off] = v_in[0+v_in_off] * m_in[0*4+m_in_off_1] + v_in[1+v_in_off] * m_in[1*4+m_in_off_1] +
- v_in[2+v_in_off] * m_in[2*4+m_in_off_1] + v_in[3+v_in_off] * m_in[3*4+m_in_off_1];
-
- final int m_in_off_2 = 2+m_in_off;
- v_out[2 + v_out_off] = v_in[0+v_in_off] * m_in[0*4+m_in_off_2] + v_in[1+v_in_off] * m_in[1*4+m_in_off_2] +
- v_in[2+v_in_off] * m_in[2*4+m_in_off_2] + v_in[3+v_in_off] * m_in[3*4+m_in_off_2];
-
- final int m_in_off_3 = 3+m_in_off;
- v_out[3 + v_out_off] = v_in[0+v_in_off] * m_in[0*4+m_in_off_3] + v_in[1+v_in_off] * m_in[1*4+m_in_off_3] +
- v_in[2+v_in_off] * m_in[2*4+m_in_off_3] + v_in[3+v_in_off] * m_in[3*4+m_in_off_3];
- }
-
- /**
- * @param m_in 4x4 matrix in column-major order
- * @param m_in_off
- * @param v_in 4-component column-vector
- * @param v_out m_in * v_in
- */
- public static void multMatrixVec(final float[] m_in, final int m_in_off,
- final float[] v_in, final float[] v_out) {
- // (one matrix row in column-major order) X (column vector)
- v_out[0] = v_in[0] * m_in[0*4+m_in_off ] + v_in[1] * m_in[1*4+m_in_off ] +
- v_in[2] * m_in[2*4+m_in_off ] + v_in[3] * m_in[3*4+m_in_off ];
-
- final int m_in_off_1 = 1+m_in_off;
- v_out[1] = v_in[0] * m_in[0*4+m_in_off_1] + v_in[1] * m_in[1*4+m_in_off_1] +
- v_in[2] * m_in[2*4+m_in_off_1] + v_in[3] * m_in[3*4+m_in_off_1];
-
- final int m_in_off_2 = 2+m_in_off;
- v_out[2] = v_in[0] * m_in[0*4+m_in_off_2] + v_in[1] * m_in[1*4+m_in_off_2] +
- v_in[2] * m_in[2*4+m_in_off_2] + v_in[3] * m_in[3*4+m_in_off_2];
-
- final int m_in_off_3 = 3+m_in_off;
- v_out[3] = v_in[0] * m_in[0*4+m_in_off_3] + v_in[1] * m_in[1*4+m_in_off_3] +
- v_in[2] * m_in[2*4+m_in_off_3] + v_in[3] * m_in[3*4+m_in_off_3];
- }
-
- /**
- * @param m_in 4x4 matrix in column-major order
- * @param m_in_off
- * @param v_in 4-component column-vector
- * @param v_out m_in * v_in
- * @return given result vector <i>v_out</i> for chaining
- */
- public static float[] multMatrixVec(final float[] m_in, final float[] v_in, final float[] v_out) {
- // (one matrix row in column-major order) X (column vector)
- v_out[0] = v_in[0] * m_in[0*4 ] + v_in[1] * m_in[1*4 ] +
- v_in[2] * m_in[2*4 ] + v_in[3] * m_in[3*4 ];
-
- v_out[1] = v_in[0] * m_in[0*4+1] + v_in[1] * m_in[1*4+1] +
- v_in[2] * m_in[2*4+1] + v_in[3] * m_in[3*4+1];
-
- v_out[2] = v_in[0] * m_in[0*4+2] + v_in[1] * m_in[1*4+2] +
- v_in[2] * m_in[2*4+2] + v_in[3] * m_in[3*4+2];
-
- v_out[3] = v_in[0] * m_in[0*4+3] + v_in[1] * m_in[1*4+3] +
- v_in[2] * m_in[2*4+3] + v_in[3] * m_in[3*4+3];
-
- return v_out;
- }
-
- /**
- * @param m_in 4x4 matrix in column-major order
- * @param v_in 4-component column-vector
- * @param v_out m_in * v_in
- */
- public static void multMatrixVec(final FloatBuffer m_in, final float[] v_in, final float[] v_out) {
- final int m_in_off = m_in.position();
- for (int i = 0; i < 4; i++) {
- // (one matrix row in column-major order) X (column vector)
- final int i_m_in_off = i+m_in_off;
- v_out[i] =
- v_in[0] * m_in.get(0*4+i_m_in_off) +
- v_in[1] * m_in.get(1*4+i_m_in_off) +
- v_in[2] * m_in.get(2*4+i_m_in_off) +
- v_in[3] * m_in.get(3*4+i_m_in_off);
- }
- }
-
- /**
- * Affine 3f-vector transformation by 4x4 matrix
- *
- * 4x4 matrix multiplication with 3-component vector,
- * using {@code 1} for for {@code v_in[3]} and dropping {@code v_out[3]},
- * which shall be {@code 1}.
- *
- * @param m_in 4x4 matrix in column-major order
- * @param m_in_off
- * @param v_in 3-component column-vector
- * @param v_out m_in * v_in, 3-component column-vector
- * @return given result vector <i>v_out</i> for chaining
- */
- public static float[] multMatrixVec3(final float[] m_in, final float[] v_in, final float[] v_out) {
- // (one matrix row in column-major order) X (column vector)
- v_out[0] = v_in[0] * m_in[0*4 ] + v_in[1] * m_in[1*4 ] +
- v_in[2] * m_in[2*4 ] + 1f * m_in[3*4 ];
-
- v_out[1] = v_in[0] * m_in[0*4+1] + v_in[1] * m_in[1*4+1] +
- v_in[2] * m_in[2*4+1] + 1f * m_in[3*4+1];
-
- v_out[2] = v_in[0] * m_in[0*4+2] + v_in[1] * m_in[1*4+2] +
- v_in[2] * m_in[2*4+2] + 1f * m_in[3*4+2];
-
- return v_out;
- }
-
- /**
- * @param sb optional passed StringBuilder instance to be used
- * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
- * @param a mxn matrix (rows x columns)
- * @param aOffset offset to <code>a</code>'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<columns; c++) {
- sb.append( String.format((Locale)null, f+", ", a.get( a0 + row*columns + c ) ) );
- }
- } else {
- for(int r=0; r<columns; r++) {
- sb.append( String.format((Locale)null, f+", ", a.get( a0 + row + r*rows ) ) );
- }
- }
- return sb;
- }
-
- /**
- * @param sb optional passed StringBuilder instance to be used
- * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
- * @param a mxn matrix (rows x columns)
- * @param aOffset offset to <code>a</code>'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 float[] a, final int aOffset, final int rows, final int columns, final boolean rowMajorOrder, final int row) {
- if(null == sb) {
- sb = new StringBuilder();
- }
- if(rowMajorOrder) {
- for(int c=0; c<columns; c++) {
- sb.append( String.format((Locale)null, f+", ", a[ aOffset + row*columns + c ] ) );
- }
- } else {
- for(int r=0; r<columns; r++) {
- sb.append( String.format((Locale)null, f+", ", a[ aOffset + row + r*rows ] ) );
- }
- }
- return sb;
- }
-
- /**
- * @param sb optional passed StringBuilder instance to be used
- * @param rowPrefix optional prefix for each row
- * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
- * @param a mxn matrix (rows x columns)
- * @param aOffset offset to <code>a</code>'s current position
- * @param rows
- * @param columns
- * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL)
- * @return matrix string representation
- */
- public static StringBuilder matrixToString(StringBuilder sb, final String rowPrefix, final String f,
- final FloatBuffer a, final int aOffset, final int rows, final int columns, final boolean rowMajorOrder) {
- if(null == sb) {
- sb = new StringBuilder();
- }
- final String prefix = ( null == rowPrefix ) ? "" : rowPrefix;
- sb.append(prefix).append("{ ");
- for(int i=0; i<rows; i++) {
- if( 0 < i ) {
- sb.append(prefix).append(" ");
- }
- matrixRowToString(sb, f, a, aOffset, rows, columns, rowMajorOrder, i);
- sb.append(System.lineSeparator());
- }
- sb.append(prefix).append("}").append(System.lineSeparator());
- return sb;
- }
-
- /**
- * @param sb optional passed StringBuilder instance to be used
- * @param rowPrefix optional prefix for each row
- * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
- * @param a mxn matrix (rows x columns)
- * @param aOffset offset to <code>a</code>'s current position
- * @param rows
- * @param columns
- * @param rowMajorOrder if true floats are layed out in row-major-order, otherwise column-major-order (OpenGL)
- * @return matrix string representation
- */
- public static StringBuilder matrixToString(StringBuilder sb, final String rowPrefix, final String f,
- final float[] a, final int aOffset, final int rows, final int columns, final boolean rowMajorOrder) {
- if(null == sb) {
- sb = new StringBuilder();
- }
- final String prefix = ( null == rowPrefix ) ? "" : rowPrefix;
- sb.append(prefix).append("{ ");
- for(int i=0; i<rows; i++) {
- if( 0 < i ) {
- sb.append(prefix).append(" ");
- }
- matrixRowToString(sb, f, a, aOffset, rows, columns, rowMajorOrder, i);
- sb.append(System.lineSeparator());
- }
- sb.append(prefix).append("}").append(System.lineSeparator());
- return sb;
- }
-
- //
- // Scalar Ops
- //
-
- @SuppressWarnings("unused")
- private static void calculateMachineEpsilonFloat() {
- final long t0;
- if( DEBUG_EPSILON ) {
- t0 = Platform.currentTimeMillis();
- }
- float machEps = 1.0f;
- int i=0;
- do {
- machEps /= 2.0f;
- i++;
- } while (1.0f + (machEps / 2.0f) != 1.0f);
- machEpsilon = machEps;
- if( DEBUG_EPSILON ) {
- final long t1 = Platform.currentTimeMillis();
- System.err.println("MachineEpsilon: "+machEpsilon+", in "+i+" iterations within "+(t1-t0)+" ms");
- }
- }
- private static volatile boolean machEpsilonAvail = false;
- private static float machEpsilon = 0f;
- private static final boolean DEBUG_EPSILON = false;
-
- /**
- * Return computed machine Epsilon value.
- * <p>
- * The machine Epsilon value is computed once.
- * </p>
- * <p>
- * On a reference machine the result was {@link #EPSILON} in 23 iterations.
- * </p>
- * @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.
- * <p>
- * Definition of machine epsilon guarantees that:
- * <pre>
- * 1.0f + EPSILON != 1.0f
- * </pre>
- * In other words: <i>machEps</i> is the maximum relative error of the chosen rounding procedure.
- * </p>
- * <p>
- * A number can be considered zero if it is in the range (or in the set):
- * <pre>
- * <b>MaybeZeroSet</b> e ]-<i>machEps</i> .. <i>machEps</i>[ <i>(exclusive)</i>
- * </pre>
- * While comparing floating point values, <i>machEps</i> allows to clip the relative error:
- * <pre>
- * boolean isZero = afloat < EPSILON;
- * boolean isNotZero = afloat >= EPSILON;
- *
- * boolean isEqual = abs(bfloat - afloat) < EPSILON;
- * boolean isNotEqual = abs(bfloat - afloat) >= EPSILON;
- * </pre>
- * </p>
- * @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.
- * <p>
- * Using {@value}, which is ~100 times {@link FloatUtil#EPSILON}.
- * </p>
- */
- 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.
- * <p>
- * Implementation considers following corner cases:
- * <ul>
- * <li>NaN == NaN</li>
- * <li>+Inf == +Inf</li>
- * <li>-Inf == -Inf</li>
- * </ul>
- * </p>
- * @see #isEqual(float, float, float)
- */
- public static boolean isEqualRaw(final float a, final float b) {
- // Values are equal (Inf, Nan .. )
- return Float.floatToIntBits(a) == Float.floatToIntBits(b);
- }
-
- /**
- * Return true if both values are equal, i.e. their absolute delta < <code>epsilon</code>.
- * <p>
- * Implementation considers following corner cases:
- * <ul>
- * <li>NaN == NaN</li>
- * <li>+Inf == +Inf</li>
- * <li>-Inf == -Inf</li>
- * </ul>
- * </p>
- * @see #EPSILON
- */
- public static boolean isEqual(final float a, final float b, final float epsilon) {
- if ( Math.abs(a - b) < epsilon ) {
- return true;
- } else {
- // Values are equal (Inf, Nan .. )
- return Float.floatToIntBits(a) == Float.floatToIntBits(b);
- }
- }
-
- /**
- * Return true if both values are equal, i.e. their absolute delta < {@link #EPSILON}.
- * <p>
- * Implementation considers following corner cases:
- * <ul>
- * <li>NaN == NaN</li>
- * <li>+Inf == +Inf</li>
- * <li>-Inf == -Inf</li>
- * </ul>
- * </p>
- * @see #EPSILON
- */
- public static boolean isEqual(final float a, final float b) {
- if ( Math.abs(a - b) < EPSILON ) {
- return true;
- } else {
- // Values are equal (Inf, Nan .. )
- return Float.floatToIntBits(a) == Float.floatToIntBits(b);
- }
- }
-
- /**
- * Return true if both values are equal, i.e. their absolute delta < {@link #EPSILON}.
- * <p>
- * Implementation does not consider corner cases like {@link #isEqual(float, float, float)}.
- * </p>
- * @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.
- * <p>
- * Implementation considers following corner cases:
- * <ul>
- * <li>NaN == NaN</li>
- * <li>+Inf == +Inf</li>
- * <li>-Inf == -Inf</li>
- * <li>NaN > 0</li>
- * <li>+Inf > -Inf</li>
- * </ul>
- * </p>
- * @see #compare(float, float, float)
- */
- public static int compare(final float a, final float b) {
- if (a < b) {
- return -1; // Neither is NaN, a is smaller
- }
- if (a > b) {
- return 1; // Neither is NaN, a is larger
- }
- final int aBits = Float.floatToIntBits(a);
- final int bBits = Float.floatToIntBits(b);
- if( aBits == bBits ) {
- return 0; // Values are equal (Inf, Nan .. )
- } else if( aBits < bBits ) {
- return -1; // (-0.0, 0.0) or (!NaN, NaN)
- } else {
- return 1; // ( 0.0, -0.0) or ( NaN, !NaN)
- }
- }
-
- /**
- * Return true if both values are equal, i.e. their absolute delta < <code>epsilon</code>.
- * <p>
- * Implementation considers following corner cases:
- * <ul>
- * <li>NaN == NaN</li>
- * <li>+Inf == +Inf</li>
- * <li>-Inf == -Inf</li>
- * <li>NaN > 0</li>
- * <li>+Inf > -Inf</li>
- * </ul>
- * </p>
- * @see #EPSILON
- */
- public static int compare(final float a, final float b, final float epsilon) {
- if ( Math.abs(a - b) < epsilon ) {
- return 0;
- } else {
- return compare(a, b);
- }
- }
-
- /**
- * Return true if value is zero, i.e. it's absolute value < <code>epsilon</code>.
- * @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 <a href="http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html">Love Your Z-Buffer</a>.
- * <pre>
- * return z * z / ( zNear * (1&lt;&lt;zBits) - z )
- * </pre>
- * Examples:
- * <pre>
- * 1.5256461E-4 = 16 zBits, -0.2 zDist, 0.1 zNear
- * 6.1033297E-6 = 16 zBits, -1.0 zDist, 0.1 zNear
- * </pre>
- * @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 <a href="http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html">Love Your Z-Buffer</a>.
- * <pre>
- * float a = zFar / ( zFar - zNear )
- * float b = zFar * zNear / ( zNear - zFar )
- * return (int) ( (1&lt;&lt;zBits) * ( a + b / z ) )
- * </pre>
- * @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<<zBits) * ( a + b / z ) );
- }
-
- /**
- * Returns orthogonal distance
- * (1f/zNear-1f/orthoZ) / (1f/zNear-1f/zFar);
- */
- public static float getOrthoWinZ(final float orthoZ, final float zNear, final float zFar) {
- return (1f/zNear-1f/orthoZ) / (1f/zNear-1f/zFar);
- }
-
-} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java b/src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java
deleted file mode 100644
index 5d7907f2f..000000000
--- a/src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/**
- * Copyright 2014 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;
-
-/**
- * Horizontal and vertical field of view (FOV) halves,
- * allowing a non-centered projection.
- * <p>
- * The values might be either in tangent or radians.
- * </p>
- */
-public final class FovHVHalves {
- /** Half horizontal FOV from center to left, either in {@link #inTangents} or radians. */
- public final float left;
- /** Half horizontal FOV from center to right, either in {@link #inTangents} or radians. */
- public final float right;
- /** Half vertical FOV from center to top, either in {@link #inTangents} or radians. */
- public final float top;
- /** Half vertical FOV from center to bottom, either in {@link #inTangents} or radians. */
- public final float bottom;
- /** If true, values are in tangent, otherwise radians.*/
- public final boolean inTangents;
-
- /**
- * Constructor for one {@link FovHVHalves} instance.
- * <p>
- * 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.
- * </p>
- * @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:
- * <pre>
- halfHorizFovTan = tan( horizontalFov / 2f );
- halfVertFovTan = tan( verticalFov / 2f );
- * </pre>
- * @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:
- * <pre>
- top = bottom = tan( verticalFov / 2f );
- left = right = aspect * top;
- * </pre>
- *
- * @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:
- * <pre>
- left = tan( horizontalFov * horizCenterFromLeft )
- right = tan( horizontalFov * ( 1f - horizCenterFromLeft ) )
- top = tan( verticalFov * vertCenterFromTop )
- bottom = tan( verticalFov * (1f - vertCenterFromTop ) )
- * </pre>
- * @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 <code>horizontalFov</code> using:
- * <pre>
- halfVertFovTan = tan( verticalFov / 2f );
- halfHorizFovTan = aspect * halfVertFovTan;
- horizontalFov = atan( halfHorizFovTan ) * 2f;
- return {@link #byRadians(float, float, float, float) byRadians}(horizontalFov, horizCenterFromLeft, verticalFov, vertCenterFromTop)
- * </pre>
- * @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 <i>in tangent</i> values.
- * <p>
- * If this instance is {@link #inTangents} already, method returns this instance,
- * otherwise a newly created instance w/ converted values to tangent.
- * </p>
- */
- 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).
- * <p>
- * Implementation covers {@link FloatUtil} matrix functionality, exposed in an object oriented manner.
- * </p>
- * <p>
- * 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.
- * </p>
- * <p>
- * For array operations the layout is expected in column-major order
- * matching OpenGL's implementation, illustration:
- * <pre>
- 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;
-
- * </pre>
- * </p>
- * <p>
- * <ul>
- * <li><a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html">Matrix-FAQ</a></li>
- * <li><a href="https://en.wikipedia.org/wiki/Matrix_%28mathematics%29">Wikipedia-Matrix</a></li>
- * <li><a href="http://www.euclideanspace.com/maths/algebra/matrix/index.htm">euclideanspace.com-Matrix</a></li>
- * </ul>
- * </p>
- * <p>
- * Implementation utilizes unrolling of small vertices and matrices wherever possible
- * while trying to access memory in a linear fashion for performance reasons, see:
- * <ul>
- * <li><a href="https://lessthanoptimal.github.io/Java-Matrix-Benchmark/">java-matrix-benchmark</a></li>
- * <li><a href="https://github.com/lessthanoptimal/ejml">EJML Efficient Java Matrix Library</a></li>
- * </ul>
- * </p>
- * @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.
- * <pre>
- Translation matrix (Column Order):
- 1 0 0 0
- 0 1 0 0
- 0 0 1 0
- 0 0 0 1
- * </pre>
- * @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.
- * <p>
- * Implementation uses relative {@link FloatBuffer#get()},
- * hence caller may want to issue {@link FloatBuffer#reset()} thereafter.
- * </p>
- * @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 <i>v_out</i> 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 <i>v_out</i> 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 <i>v_out</i> 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 <i>v_out</i> 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.
- * <p>
- * Implementation uses relative {@link FloatBuffer#put(float)},
- * hence caller may want to issue {@link FloatBuffer#reset()} thereafter.
- * </p>
- *
- * @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.
- * <pre>
- Translation matrix (Column Order):
- 1 0 0 0
- 0 1 0 0
- 0 0 1 0
- x y z 1
- * </pre>
- * @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.
- * <pre>
- Translation matrix (Column Order):
- 1 0 0 0
- 0 1 0 0
- 0 0 1 0
- x y z 1
- * </pre>
- * @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.
- * <pre>
- Scale matrix (Any Order):
- x 0 0 0
- 0 y 0 0
- 0 0 z 0
- 0 0 0 1
- * </pre>
- * @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.
- * <pre>
- Scale matrix (Any Order):
- x 0 0 0
- 0 y 0 0
- 0 0 z 0
- 0 0 0 1
- * </pre>
- * @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.
- * <pre>
- 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
- * </pre>
- * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a>
- * @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.
- * <pre>
- 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
- * </pre>
- * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a>
- * @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.
- * <p>
- * The rotations are applied in the given order:
- * <ul>
- * <li>y - heading</li>
- * <li>z - attitude</li>
- * <li>x - bank</li>
- * </ul>
- * </p>
- * @param bankX the Euler pitch angle in radians. (rotation about the X axis)
- * @param headingY the Euler yaw angle in radians. (rotation about the Y axis)
- * @param attitudeZ the Euler roll angle in radians. (rotation about the Z axis)
- * @return this matrix for chaining
- * <p>
- * Implementation does not use Quaternion and hence is exposed to
- * <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q34">Gimbal-Lock</a>,
- * consider using {@link #setToRotation(Quaternion)}.
- * </p>
- * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q36">Matrix-FAQ Q36</a>
- * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm">euclideanspace.com-eulerToMatrix</a>
- * @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.
- * <p>
- * The rotations are applied in the given order:
- * <ul>
- * <li>y - heading</li>
- * <li>z - attitude</li>
- * <li>x - bank</li>
- * </ul>
- * </p>
- * @param angradXYZ euler angle vector in radians holding x-bank, y-heading and z-attitude
- * @return this quaternion for chaining.
- * <p>
- * Implementation does not use Quaternion and hence is exposed to
- * <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q34">Gimbal-Lock</a>,
- * consider using {@link #setToRotation(Quaternion)}.
- * </p>
- * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q36">Matrix-FAQ Q36</a>
- * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm">euclideanspace.com-eulerToMatrix</a>
- * @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.
- * <p>
- * Implementation Details:
- * <ul>
- * <li> makes identity matrix if {@link #magnitudeSquared()} is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
- * <li> The fields [m00 .. m22] define the rotation</li>
- * </ul>
- * </p>
- *
- * @param q the Quaternion representing the rotation
- * @return this matrix for chaining
- * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54">Matrix-FAQ Q54</a>
- * @see Quaternion#toMatrix(float[])
- * @see #getRotation()
- */
- public final Matrix4f setToRotation(final Quaternion q) {
- // pre-multiply scaled-reciprocal-magnitude to reduce multiplications
- final float norm = q.magnitudeSquared();
- if ( FloatUtil.isZero(norm) ) {
- // identity matrix -> srecip = 0f
- loadIdentity();
- return this;
- }
- final float srecip;
- if ( FloatUtil.isEqual(1f, norm) ) {
- srecip = 2f;
- } else {
- srecip = 2.0f / norm;
- }
-
- final float x = q.x();
- final float y = q.y();
- final float z = q.z();
- final float w = q.w();
-
- final float xs = srecip * x;
- final float ys = srecip * y;
- final float zs = srecip * z;
-
- final float xx = x * xs;
- final float xy = x * ys;
- final float xz = x * zs;
- final float xw = xs * w;
- final float yy = y * ys;
- final float yz = y * zs;
- final float yw = ys * w;
- final float zz = z * zs;
- final float zw = zs * w;
-
- m00 = 1f - ( yy + zz );
- m01 = ( xy - zw );
- m02 = ( xz + yw );
- m03 = 0f;
-
- m10 = ( xy + zw );
- m11 = 1f - ( xx + zz );
- m12 = ( yz - xw );
- m13 = 0f;
-
- m20 = ( xz - yw );
- m21 = ( yz + xw );
- m22 = 1f - ( xx + yy );
- m23 = 0f;
-
- m30 = m31 = m32 = 0f;
- m33 = 1f;
- return this;
- }
-
- /**
- * Returns the rotation [m00 .. m22] fields converted to a Quaternion.
- * @param res resulting Quaternion
- * @return the resulting Quaternion for chaining.
- * @see Quaternion#setFromMatrix(float, float, float, float, float, float, float, float, float)
- * @see #setToRotation(Quaternion)
- */
- public final Quaternion getRotation(final Quaternion res) {
- res.setFromMatrix(m00, m01, m02, m10, m11, m12, m20, m21, m22);
- return res;
- }
-
- /**
- * Set this matrix to orthogonal projection.
- * <pre>
- Ortho matrix (Column Order):
- 2/dx 0 0 0
- 0 2/dy 0 0
- 0 0 2/dz 0
- tx ty tz 1
- * </pre>
- * @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.
- * <pre>
- Frustum matrix (Column Order):
- 2*zNear/dx 0 0 0
- 0 2*zNear/dy 0 0
- A B C -1
- 0 0 D 0
- * </pre>
- * @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.
- * <p>
- * Frustum plane's normals will point to the inside of the viewing frustum,
- * as required by this class.
- * </p>
- * <p>
- * Usually called by {@link Frustum#updateFrustumPlanes(Matrix4f)}.
- * </p>
- */
- 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 <i>look-at</i> matrix based on given parameters.
- * <p>
- * Consist out of two matrix multiplications:
- * <pre>
- * <b>R</b> = <b>L</b> x <b>T</b>,
- * with <b>L</b> for <i>look-at</i> matrix and
- * <b>T</b> for eye translation.
- *
- * Result <b>R</b> can be utilized for <i>projection or modelview</i> multiplication, i.e.
- * <b>M</b> = <b>M</b> x <b>R</b>,
- * with <b>M</b> being the <i>projection or modelview</i> matrix.
- * </pre>
- * </p>
- * @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 <i>pick</i> matrix based on given parameters.
- * <p>
- * Traditional <code>gluPickMatrix</code> implementation.
- * </p>
- * <p>
- * Consist out of two matrix multiplications:
- * <pre>
- * <b>R</b> = <b>T</b> x <b>S</b>,
- * with <b>T</b> for viewport translation matrix and
- * <b>S</b> for viewport scale matrix.
- *
- * Result <b>R</b> can be utilized for <i>projection</i> multiplication, i.e.
- * <b>P</b> = <b>P</b> x <b>R</b>,
- * with <b>P</b> being the <i>projection</i> matrix.
- * </pre>
- * </p>
- * <p>
- * 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.
- * </p>
- * @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 <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a>
- * @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 <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q38">Matrix-FAQ Q38</a>
- * @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)}.
- * <p>
- * Implementation considers following corner cases:
- * <ul>
- * <li>NaN == NaN</li>
- * <li>+Inf == +Inf</li>
- * <li>-Inf == -Inf</li>
- * </ul>
- * @param o comparison value
- * @param epsilon consider using {@link FloatUtil#EPSILON}
- * @return true if all components differ less than {@code epsilon}, otherwise false.
- */
- public boolean isEqual(final Matrix4f o, final float epsilon) {
- if( this == o ) {
- return true;
- } else {
- return FloatUtil.isEqual(m00, o.m00, epsilon) &&
- FloatUtil.isEqual(m01, o.m01, epsilon) &&
- FloatUtil.isEqual(m02, o.m02, epsilon) &&
- FloatUtil.isEqual(m03, o.m03, epsilon) &&
- FloatUtil.isEqual(m10, o.m10, epsilon) &&
- FloatUtil.isEqual(m11, o.m11, epsilon) &&
- FloatUtil.isEqual(m12, o.m12, epsilon) &&
- FloatUtil.isEqual(m13, o.m13, epsilon) &&
- FloatUtil.isEqual(m20, o.m20, epsilon) &&
- FloatUtil.isEqual(m21, o.m21, epsilon) &&
- FloatUtil.isEqual(m22, o.m22, epsilon) &&
- FloatUtil.isEqual(m23, o.m23, epsilon) &&
- FloatUtil.isEqual(m30, o.m30, epsilon) &&
- FloatUtil.isEqual(m31, o.m31, epsilon) &&
- FloatUtil.isEqual(m32, o.m32, epsilon) &&
- FloatUtil.isEqual(m33, o.m33, epsilon);
- }
- }
-
- /**
- * Equals check using {@link FloatUtil#EPSILON} value and {@link FloatUtil#isEqual(float, float, float)}.
- * <p>
- * Implementation considers following corner cases:
- * <ul>
- * <li>NaN == NaN</li>
- * <li>+Inf == +Inf</li>
- * <li>-Inf == -Inf</li>
- * </ul>
- * @param o comparison value
- * @return true if all components differ less than {@link FloatUtil#EPSILON}, otherwise false.
- */
- public boolean isEqual(final Matrix4f o) {
- return isEqual(o, FloatUtil.EPSILON);
- }
-
- @Override
- public boolean equals(final Object o) {
- if( o instanceof Matrix4f ) {
- return isEqual((Matrix4f)o, FloatUtil.EPSILON);
- } else {
- return false;
- }
- }
-
- //
- // Static multi Matrix ops
- //
-
- /**
- * Map object coordinates to window coordinates.
- * <p>
- * Traditional <code>gluProject</code> implementation.
- * </p>
- *
- * @param obj object position, 3 component vector
- * @param mMv modelview matrix
- * @param mP projection matrix
- * @param viewport Rect4i viewport
- * @param winPos 3 component window coordinate, the result
- * @return true if successful, otherwise false (z is 1)
- */
- public static boolean mapObjToWin(final Vec3f obj, final Matrix4f mMv, final Matrix4f mP,
- final Recti viewport, final Vec3f winPos)
- {
- final Vec4f vec4Tmp1 = new Vec4f(obj, 1f);
-
- // vec4Tmp2 = Mv * o
- // rawWinPos = P * vec4Tmp2
- // rawWinPos = P * ( Mv * o )
- // rawWinPos = P * Mv * o
- final Vec4f vec4Tmp2 = mMv.mulVec4f(vec4Tmp1, new Vec4f());
- final Vec4f rawWinPos = mP.mulVec4f(vec4Tmp2, vec4Tmp1);
-
- if (rawWinPos.w() == 0.0f) {
- return false;
- }
-
- final float s = ( 1.0f / rawWinPos.w() ) * 0.5f;
-
- // Map x, y and z to range 0-1 (w is ignored)
- rawWinPos.scale(s).add(0.5f, 0.5f, 0.5f, 0f);
-
- // Map x,y to viewport
- winPos.set( rawWinPos.x() * viewport.width() + viewport.x(),
- rawWinPos.y() * viewport.height() + viewport.y(),
- rawWinPos.z() );
-
- return true;
- }
-
- /**
- * Map object coordinates to window coordinates.
- * <p>
- * Traditional <code>gluProject</code> implementation.
- * </p>
- *
- * @param obj object position, 3 component vector
- * @param mPMv [projection] x [modelview] matrix, i.e. P x Mv
- * @param viewport Rect4i viewport
- * @param winPos 3 component window coordinate, the result
- * @return true if successful, otherwise false (z is 1)
- */
- public static boolean mapObjToWin(final Vec3f obj, final Matrix4f mPMv,
- final Recti viewport, final Vec3f winPos)
- {
- final Vec4f vec4Tmp2 = new Vec4f(obj, 1f);
-
- // rawWinPos = P * Mv * o
- final Vec4f rawWinPos = mPMv.mulVec4f(vec4Tmp2, new Vec4f());
-
- if (rawWinPos.w() == 0.0f) {
- return false;
- }
-
- final float s = ( 1.0f / rawWinPos.w() ) * 0.5f;
-
- // Map x, y and z to range 0-1 (w is ignored)
- rawWinPos.scale(s).add(0.5f, 0.5f, 0.5f, 0f);
-
- // Map x,y to viewport
- winPos.set( rawWinPos.x() * viewport.width() + viewport.x(),
- rawWinPos.y() * viewport.height() + viewport.y(),
- rawWinPos.z() );
-
- return true;
- }
-
- /**
- * Map window coordinates to object coordinates.
- * <p>
- * Traditional <code>gluUnProject</code> implementation.
- * </p>
- *
- * @param winx
- * @param winy
- * @param winz
- * @param mMv 4x4 modelview matrix
- * @param mP 4x4 projection matrix
- * @param viewport Rect4i viewport
- * @param objPos 3 component object coordinate, the result
- * @param mat4Tmp 16 component matrix for temp storage
- * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
- */
- public static boolean mapWinToObj(final float winx, final float winy, final float winz,
- final Matrix4f mMv, final Matrix4f mP,
- final Recti viewport,
- final Vec3f objPos,
- final Matrix4f mat4Tmp)
- {
- // invPMv = Inv(P x Mv)
- final Matrix4f invPMv = mat4Tmp.mul(mP, mMv);
- if( !invPMv.invert() ) {
- return false;
- }
-
- final Vec4f winPos = new Vec4f(winx, winy, winz, 1f);
-
- // Map x and y from window coordinates
- winPos.add(-viewport.x(), -viewport.y(), 0f, 0f).scale(1f/viewport.width(), 1f/viewport.height(), 1f, 1f);
-
- // Map to range -1 to 1
- winPos.scale(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f);
-
- // rawObjPos = Inv(P x Mv) * winPos
- final Vec4f rawObjPos = invPMv.mulVec4f(winPos, new Vec4f());
-
- if ( rawObjPos.w() == 0.0f ) {
- return false;
- }
- objPos.set( rawObjPos.scale( 1f / rawObjPos.w() ) );
-
- return true;
- }
-
- /**
- * Map window coordinates to object coordinates.
- * <p>
- * Traditional <code>gluUnProject</code> implementation.
- * </p>
- *
- * @param winx
- * @param winy
- * @param winz
- * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv), if null method returns false
- * @param viewport Rect4i viewport
- * @param objPos 3 component object coordinate, the result
- * @return true if successful, otherwise false (null invert matrix, or becomes infinity due to zero z)
- */
- public static boolean mapWinToObj(final float winx, final float winy, final float winz,
- final Matrix4f invPMv,
- final Recti viewport,
- final Vec3f objPos)
- {
- if( null == invPMv ) {
- return false;
- }
- final Vec4f winPos = new Vec4f(winx, winy, winz, 1f);
-
- // Map x and y from window coordinates
- winPos.add(-viewport.x(), -viewport.y(), 0f, 0f).scale(1f/viewport.width(), 1f/viewport.height(), 1f, 1f);
-
- // Map to range -1 to 1
- winPos.scale(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f);
-
- // rawObjPos = Inv(P x Mv) * winPos
- final Vec4f rawObjPos = invPMv.mulVec4f(winPos, new Vec4f());
-
- if ( rawObjPos.w() == 0.0f ) {
- return false;
- }
- objPos.set( rawObjPos.scale( 1f / rawObjPos.w() ) );
-
- return true;
- }
-
- /**
- * Map two window coordinates to two object coordinates,
- * distinguished by their z component.
- * <p>
- * Traditional <code>gluUnProject</code> implementation.
- * </p>
- *
- * @param winx
- * @param winy
- * @param winz1
- * @param winz2
- * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv), if null method returns false
- * @param viewport Rect4i viewport vector
- * @param objPos1 3 component object coordinate, the result
- * @return true if successful, otherwise false (null invert matrix, or becomes infinity due to zero z)
- */
- public static boolean mapWinToObj(final float winx, final float winy, final float winz1, final float winz2,
- final Matrix4f invPMv,
- final Recti viewport,
- final Vec3f objPos1, final Vec3f objPos2)
- {
- if( null == invPMv ) {
- return false;
- }
- final Vec4f winPos = new Vec4f(winx, winy, winz1, 1f);
-
- // Map x and y from window coordinates
- winPos.add(-viewport.x(), -viewport.y(), 0f, 0f).scale(1f/viewport.width(), 1f/viewport.height(), 1f, 1f);
-
- // Map to range -1 to 1
- winPos.scale(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f);
-
- // rawObjPos = Inv(P x Mv) * winPos1
- final Vec4f rawObjPos = invPMv.mulVec4f(winPos, new Vec4f());
-
- if ( rawObjPos.w() == 0.0f ) {
- return false;
- }
- objPos1.set( rawObjPos.scale( 1f / rawObjPos.w() ) );
-
- //
- // winz2
- //
- // Map Z to range -1 to 1
- winPos.setZ( winz2 * 2f - 1f );
-
- // rawObjPos = Inv(P x Mv) * winPos2
- invPMv.mulVec4f(winPos, rawObjPos);
-
- if ( rawObjPos.w() == 0.0f ) {
- return false;
- }
- objPos2.set( rawObjPos.scale( 1f / rawObjPos.w() ) );
-
- return true;
- }
-
- /**
- * Map window coordinates to object coordinates.
- * <p>
- * Traditional <code>gluUnProject4</code> implementation.
- * </p>
- *
- * @param winx
- * @param winy
- * @param winz
- * @param clipw
- * @param mMv 4x4 modelview matrix
- * @param mP 4x4 projection matrix
- * @param viewport Rect4i viewport vector
- * @param near
- * @param far
- * @param obj_pos 4 component object coordinate, the result
- * @param mat4Tmp 16 component matrix for temp storage
- * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
- */
- public static boolean mapWinToObj4(final float winx, final float winy, final float winz, final float clipw,
- final Matrix4f mMv, final Matrix4f mP,
- final Recti viewport,
- final float near, final float far,
- final Vec4f objPos,
- final Matrix4f mat4Tmp)
- {
- // invPMv = Inv(P x Mv)
- final Matrix4f invPMv = mat4Tmp.mul(mP, mMv);
- if( !invPMv.invert() ) {
- return false;
- }
-
- final Vec4f winPos = new Vec4f(winx, winy, winz, clipw);
-
- // Map x and y from window coordinates
- winPos.add(-viewport.x(), -viewport.y(), -near, 0f).scale(1f/viewport.width(), 1f/viewport.height(), 1f/(far-near), 1f);
-
- // Map to range -1 to 1
- winPos.scale(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f);
-
- // objPos = Inv(P x Mv) * winPos
- invPMv.mulVec4f(winPos, objPos);
-
- if ( objPos.w() == 0.0f ) {
- return false;
- }
- return true;
- }
-
- /**
- * Map window coordinates to object coordinates.
- * <p>
- * Traditional <code>gluUnProject4</code> implementation.
- * </p>
- *
- * @param winx
- * @param winy
- * @param winz
- * @param clipw
- * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv), if null method returns false
- * @param viewport Rect4i viewport vector
- * @param near
- * @param far
- * @param obj_pos 4 component object coordinate, the result
- * @return true if successful, otherwise false (null invert matrix, or becomes infinity due to zero z)
- */
- public static boolean mapWinToObj4(final float winx, final float winy, final float winz, final float clipw,
- final Matrix4f invPMv,
- final Recti viewport,
- final float near, final float far,
- final Vec4f objPos)
- {
- if( null == invPMv ) {
- return false;
- }
- final Vec4f winPos = new Vec4f(winx, winy, winz, clipw);
-
- // Map x and y from window coordinates
- winPos.add(-viewport.x(), -viewport.y(), -near, 0f).scale(1f/viewport.width(), 1f/viewport.height(), 1f/(far-near), 1f);
-
- // Map to range -1 to 1
- winPos.scale(2f, 2f, 2f, 1f).add(-1f, -1f, -1f, 0f);
-
- // objPos = Inv(P x Mv) * winPos
- invPMv.mulVec4f(winPos, objPos);
-
- if ( objPos.w() == 0.0f ) {
- return false;
- }
- return true;
- }
-
- /**
- * Map two window coordinates w/ shared X/Y and distinctive Z
- * to a {@link Ray}. The resulting {@link Ray} maybe used for <i>picking</i>
- * using a {@link AABBox#getRayIntersection(Vec3f, Ray, float, boolean)}.
- * <p>
- * Notes for picking <i>winz0</i> and <i>winz1</i>:
- * <ul>
- * <li>see {@link FloatUtil#getZBufferEpsilon(int, float, float)}</li>
- * <li>see {@link FloatUtil#getZBufferValue(int, float, float, float)}</li>
- * <li>see {@link FloatUtil#getOrthoWinZ(float, float, float)}</li>
- * </ul>
- * </p>
- * @param winx
- * @param winy
- * @param winz0
- * @param winz1
- * @param mMv 4x4 modelview matrix
- * @param mP 4x4 projection matrix
- * @param viewport Rect4i viewport
- * @param ray storage for the resulting {@link Ray}
- * @param mat4Tmp1 16 component matrix for temp storage
- * @param mat4Tmp2 16 component matrix for temp storage
- * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity)
- */
- public static boolean mapWinToRay(final float winx, final float winy, final float winz0, final float winz1,
- final Matrix4f mMv, final Matrix4f mP,
- final Recti viewport,
- final Ray ray,
- final Matrix4f mat4Tmp1, final Matrix4f mat4Tmp2) {
- // invPMv = Inv(P x Mv)
- final Matrix4f invPMv = mat4Tmp1.mul(mP, mMv);
- if( !invPMv.invert() ) {
- return false;
- }
-
- if( mapWinToObj(winx, winy, winz0, winz1, invPMv, viewport, ray.orig, ray.dir) ) {
- ray.dir.sub(ray.orig).normalize();
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Map two window coordinates w/ shared X/Y and distinctive Z
- * to a {@link Ray}. The resulting {@link Ray} maybe used for <i>picking</i>
- * using a {@link AABBox#getRayIntersection(Vec3f, Ray, float, boolean)}.
- * <p>
- * Notes for picking <i>winz0</i> and <i>winz1</i>:
- * <ul>
- * <li>see {@link FloatUtil#getZBufferEpsilon(int, float, float)}</li>
- * <li>see {@link FloatUtil#getZBufferValue(int, float, float, float)}</li>
- * <li>see {@link FloatUtil#getOrthoWinZ(float, float, float)}</li>
- * </ul>
- * </p>
- * @param winx
- * @param winy
- * @param winz0
- * @param winz1
- * @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv), if null method returns false
- * @param viewport Rect4i viewport
- * @param ray storage for the resulting {@link Ray}
- * @return true if successful, otherwise false (null invert matrix, or becomes z is infinity)
- */
- public static boolean mapWinToRay(final float winx, final float winy, final float winz0, final float winz1,
- final Matrix4f invPMv,
- final Recti viewport,
- final Ray ray) {
- if( mapWinToObj(winx, winy, winz0, winz1, invPMv, viewport, ray.orig, ray.dir) ) {
- ray.dir.sub(ray.orig).normalize();
- return true;
- } else {
- return false;
- }
- }
-
- //
- // String and internals
- //
-
- /**
- * @param sb optional passed StringBuilder instance to be used
- * @param rowPrefix optional prefix for each row
- * @param f the format string of one floating point, i.e. "%10.5f", see {@link java.util.Formatter}
- * @return matrix string representation
- */
- public StringBuilder toString(final StringBuilder sb, final String rowPrefix, final String f) {
- final float[] tmp = new float[16];
- this.get(tmp);
- return FloatUtil.matrixToString(sb, rowPrefix, f,tmp, 0, 4, 4, false /* rowMajorOrder */);
- }
-
- @Override
- public String toString() {
- return toString(null, null, "%10.5f").toString();
- }
-
- private float m00, m10, m20, m30;
- private float m01, m11, m21, m31;
- private float m02, m12, m22, m32;
- private float m03, m13, m23, m33;
-
- final Stack stack = new Stack(0, 16*16); // start w/ zero size, growSize is half GL-min size (32)
-
- private static class Stack {
- private int position;
- private float[] buffer;
- private final int growSize;
-
- /**
- * @param initialSize initial size
- * @param growSize grow size if {@link #position()} is reached, maybe <code>0</code>
- * 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
- * <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q34">Gimbal-Lock</a> free rotations.
- * <p>
- * All matrix operation provided are in column-major order,
- * as specified in the OpenGL fixed function pipeline, i.e. compatibility profile.
- * See {@link FloatUtil}.
- * </p>
- * <p>
- * See <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html">Matrix-FAQ</a>
- * </p>
- * <p>
- * See <a href="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/index.htm">euclideanspace.com-Quaternion</a>
- * </p>
- */
-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.
- * <p>
- * Using {@value}, which is ~10 times {@link FloatUtil#EPSILON}.
- * </p>
- */
- 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()})
- * <p>
- * A magnitude of zero shall equal {@link #isIdentity() identity},
- * as performed by {@link #normalize()}.
- * </p>
- * <p>
- * Implementation Details:
- * <ul>
- * <li> returns 0f if {@link #magnitudeSquared()} is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
- * <li> returns 1f if {@link #magnitudeSquared()} is {@link FloatUtil#isEqual(float, float, float) equals 1f} using {@link FloatUtil#EPSILON epsilon}</li>
- * </ul>
- * </p>
- */
- public final float magnitude() {
- final float magnitudeSQ = magnitudeSquared();
- if ( FloatUtil.isZero(magnitudeSQ) ) {
- return 0f;
- }
- if ( FloatUtil.isEqual(1f, magnitudeSQ) ) {
- return 1f;
- }
- return FloatUtil.sqrt(magnitudeSQ);
- }
-
- public final float w() {
- return w;
- }
-
- public final void setW(final float w) {
- this.w = w;
- }
-
- public final float x() {
- return x;
- }
-
- public final void setX(final float x) {
- this.x = x;
- }
-
- public final float y() {
- return y;
- }
-
- public final void setY(final float y) {
- this.y = y;
- }
-
- public final float z() {
- return z;
- }
-
- public final void setZ(final float z) {
- this.z = z;
- }
-
- /**
- * Returns the dot product of this quaternion with the given x,y,z and w components.
- */
- public final float dot(final float x, final float y, final float z, final float w) {
- return this.x * x + this.y * y + this.z * z + this.w * w;
- }
-
- /**
- * Returns the dot product of this quaternion with the given quaternion
- */
- public final float dot(final Quaternion quat) {
- return dot(quat.x(), quat.y(), quat.z(), quat.w());
- }
-
- /**
- * Returns <code>true</code> if this quaternion has identity.
- * <p>
- * 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}.
- * </p>
- */
- 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.
- * <p>
- * Implementation Details:
- * <ul>
- * <li> {@link #setIdentity()} if {@link #magnitude()} is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
- * </ul>
- * </p>
- * @return this quaternion for chaining.
- */
- public final Quaternion normalize() {
- final float norm = magnitude();
- if ( FloatUtil.isZero(norm, FloatUtil.EPSILON) ) {
- setIdentity();
- } else {
- final float invNorm = 1f/norm;
- w *= invNorm;
- x *= invNorm;
- y *= invNorm;
- z *= invNorm;
- }
- return this;
- }
-
- /**
- * Conjugates this quaternion <code>[-x, -y, -z, w]</code>.
- * @return this quaternion for chaining.
- * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q49">Matrix-FAQ Q49</a>
- */
- public Quaternion conjugate() {
- x = -x;
- y = -y;
- z = -z;
- return this;
- }
-
- /**
- * Invert the quaternion If rotational, will produce a the inverse rotation
- * <p>
- * Implementation Details:
- * <ul>
- * <li> {@link #conjugate() conjugates} if {@link #magnitudeSquared()} is is {@link FloatUtil#isEqual(float, float, float) equals 1f} using {@link FloatUtil#EPSILON epsilon}</li>
- * </ul>
- * </p>
- * @return this quaternion for chaining.
- * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q50">Matrix-FAQ Q50</a>
- */
- public final Quaternion invert() {
- final float magnitudeSQ = magnitudeSquared();
- if ( FloatUtil.isEqual(1.0f, magnitudeSQ) ) {
- conjugate();
- } else {
- final float invmsq = 1f/magnitudeSQ;
- w *= invmsq;
- x = -x * invmsq;
- y = -y * invmsq;
- z = -z * invmsq;
- }
- return this;
- }
-
- /**
- * Set all values of this quaternion using the given src.
- * @return this quaternion for chaining.
- */
- public final Quaternion set(final Quaternion src) {
- this.x = src.x;
- this.y = src.y;
- this.z = src.z;
- this.w = src.w;
- return this;
- }
-
- /**
- * Set all values of this quaternion using the given components.
- * @return this quaternion for chaining.
- */
- public final Quaternion set(final float x, final float y, final float z, final float w) {
- this.x = x;
- this.y = y;
- this.z = z;
- this.w = w;
- return this;
- }
-
- /**
- * Add a quaternion
- *
- * @param q quaternion
- * @return this quaternion for chaining.
- * @see <a href="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm#add">euclideanspace.com-QuaternionAdd</a>
- */
- public final Quaternion add(final Quaternion q) {
- x += q.x;
- y += q.y;
- z += q.z;
- w += q.w;
- return this;
- }
-
- /**
- * Subtract a quaternion
- *
- * @param q quaternion
- * @return this quaternion for chaining.
- * @see <a href="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm#add">euclideanspace.com-QuaternionAdd</a>
- */
- public final Quaternion subtract(final Quaternion q) {
- x -= q.x;
- y -= q.y;
- z -= q.z;
- w -= q.w;
- return this;
- }
-
- /**
- * Multiply this quaternion by the param quaternion
- *
- * @param q a quaternion to multiply with
- * @return this quaternion for chaining.
- * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q53">Matrix-FAQ Q53</a>
- * @see <a href="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm#mul">euclideanspace.com-QuaternionMul</a>
- */
- public final Quaternion mult(final Quaternion q) {
- return set( w * q.x + x * q.w + y * q.z - z * q.y,
- w * q.y - x * q.z + y * q.w + z * q.x,
- w * q.z + x * q.y - y * q.x + z * q.w,
- w * q.w - x * q.x - y * q.y - z * q.z );
- }
-
- /**
- * Scale this quaternion by a constant
- *
- * @param n a float constant
- * @return this quaternion for chaining.
- * @see <a href="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm#scale">euclideanspace.com-QuaternionScale</a>
- */
- public final Quaternion scale(final float n) {
- x *= n;
- y *= n;
- z *= n;
- w *= n;
- return this;
- }
-
- /**
- * Rotate this quaternion by the given angle and axis.
- * <p>
- * The axis must be a normalized vector.
- * </p>
- * <p>
- * A rotational quaternion is made from the given angle and axis.
- * </p>
- *
- * @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.
- * <p>
- * The axis must be a normalized vector.
- * </p>
- * <p>
- * A rotational quaternion is made from the given angle and axis.
- * </p>
- *
- * @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 array <code>angradXYZ</code> in radians.
- * <p>
- * The <code>angradXYZ</code> array is laid out in natural order:
- * <ul>
- * <li>x - bank</li>
- * <li>y - heading</li>
- * <li>z - attitude</li>
- * </ul>
- * </p>
- * For details see {@link #rotateByEuler(float, float, float)}.
- * @param angradXYZ euler angle array in radians
- * @return this quaternion for chaining.
- * @see #rotateByEuler(float, float, float)
- */
- public final Quaternion rotateByEuler(final Vec3f angradXYZ) {
- return rotateByEuler(angradXYZ.x(), angradXYZ.y(), angradXYZ.z());
- }
-
- /**
- * Rotates this quaternion from the given Euler rotation angles in radians.
- * <p>
- * The rotations are applied in the given order and using chained rotation per axis:
- * <ul>
- * <li>y - heading - {@link #rotateByAngleY(float)}</li>
- * <li>z - attitude - {@link #rotateByAngleZ(float)}</li>
- * <li>x - bank - {@link #rotateByAngleX(float)}</li>
- * </ul>
- * </p>
- * <p>
- * Implementation Details:
- * <ul>
- * <li> NOP if all angles are {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
- * <li> result is {@link #normalize()}ed</li>
- * </ul>
- * </p>
- * @param bankX the Euler pitch angle in radians. (rotation about the X axis)
- * @param headingY the Euler yaw angle in radians. (rotation about the Y axis)
- * @param attitudeZ the Euler roll angle in radians. (rotation about the Z axis)
- * @return this quaternion for chaining.
- * @see #rotateByAngleY(float)
- * @see #rotateByAngleZ(float)
- * @see #rotateByAngleX(float)
- * @see #setFromEuler(float, float, float)
- */
- public final Quaternion rotateByEuler(final float bankX, final float headingY, final float attitudeZ) {
- if ( VectorUtil.isZero(bankX, headingY, attitudeZ, FloatUtil.EPSILON) ) {
- return this;
- } else {
- // setFromEuler muls: ( 8 + 4 ) , + quat muls 24 = 36
- // this: 8 + 8 + 8 + 4 = 28 muls
- return rotateByAngleY(headingY).rotateByAngleZ(attitudeZ).rotateByAngleX(bankX).normalize();
- }
- }
-
- /***
- * Rotate the given vector by this quaternion
- * @param vecIn vector to be rotated
- * @param vecOut result storage for rotated vector, maybe equal to vecIn for in-place rotation
- *
- * @return the given vecOut store for chaining
- * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q63">Matrix-FAQ Q63</a>
- */
- public final Vec3f rotateVector(final Vec3f vecIn, final Vec3f vecOut) {
- if( vecIn.isZero() ) {
- vecOut.set(0, 0, 0);
- } else {
- final float vecX = vecIn.x();
- final float vecY = vecIn.y();
- final float vecZ = vecIn.z();
- final float x_x = x*x;
- final float y_y = y*y;
- final float z_z = z*z;
- final float w_w = w*w;
-
- vecOut.setX( w_w * vecX
- + x_x * vecX
- - z_z * vecX
- - y_y * vecX
- + 2f * ( y*w*vecZ - z*w*vecY + y*x*vecY + z*x*vecZ ) );
- ;
-
- vecOut.setY( y_y * vecY
- - z_z * vecY
- + w_w * vecY
- - x_x * vecY
- + 2f * ( x*y*vecX + z*y*vecZ + w*z*vecX - x*w*vecZ ) );;
-
- vecOut.setZ( z_z * vecZ
- - y_y * vecZ
- - x_x * vecZ
- + w_w * vecZ
- + 2f * ( x*z*vecX + y*z*vecY - w*y*vecX + w*x*vecY ) );
- }
- return vecOut;
- }
-
- /**
- * Set this quaternion to a spherical linear interpolation
- * between the given start and end quaternions by the given change amount.
- * <p>
- * Note: Method <i>does not</i> normalize this quaternion!
- * </p>
- *
- * @param a start quaternion
- * @param b end quaternion
- * @param changeAmnt float between 0 and 1 representing interpolation.
- * @return this quaternion for chaining.
- * @see <a href="http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/">euclideanspace.com-QuaternionSlerp</a>
- */
- 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 <i>direction</i> and the y-axis to <i>up</i>.
- * <p>
- * Implementation generates a 3x3 matrix
- * and is equal with ProjectFloat's lookAt(..).<br/>
- * </p>
- * Implementation Details:
- * <ul>
- * <li> result is {@link #normalize()}ed</li>
- * </ul>
- * </p>
- * @param directionIn where to <i>look</i> at
- * @param upIn a vector indicating the local <i>up</i> direction.
- * @param xAxisOut vector storing the <i>orthogonal</i> x-axis of the coordinate system.
- * @param yAxisOut vector storing the <i>orthogonal</i> y-axis of the coordinate system.
- * @param zAxisOut vector storing the <i>orthogonal</i> z-axis of the coordinate system.
- * @return this quaternion for chaining.
- * @see <a href="http://www.euclideanspace.com/maths/algebra/vectors/lookat/index.htm">euclideanspace.com-LookUp</a>
- */
- public Quaternion setLookAt(final Vec3f directionIn, final Vec3f upIn,
- final Vec3f xAxisOut, final Vec3f yAxisOut, final Vec3f zAxisOut) {
- // Z = norm(dir)
- zAxisOut.set(directionIn).normalize();
-
- // X = upIn x Z
- // (borrow yAxisOut for upNorm)
- yAxisOut.set(upIn).normalize();
- xAxisOut.cross(yAxisOut, zAxisOut).normalize();
-
- // Y = Z x X
- //
- yAxisOut.cross(zAxisOut, xAxisOut).normalize();
-
- /**
- final float m00 = xAxisOut[0];
- final float m01 = yAxisOut[0];
- final float m02 = zAxisOut[0];
- final float m10 = xAxisOut[1];
- final float m11 = yAxisOut[1];
- final float m12 = zAxisOut[1];
- final float m20 = xAxisOut[2];
- final float m21 = yAxisOut[2];
- final float m22 = zAxisOut[2];
- */
- return setFromAxes(xAxisOut, yAxisOut, zAxisOut).normalize();
- }
-
- //
- // Conversions
- //
-
- /**
- * Initialize this quaternion from two vectors
- * <pre>
- * q = (s,v) = (v1•v2 , v1 × v2),
- * angle = angle(v1, v2) = v1•v2
- * axis = normal(v1 x v2)
- * </pre>
- * <p>
- * Implementation Details:
- * <ul>
- * <li> {@link #setIdentity()} if square vector-length is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
- * </ul>
- * </p>
- * @param v1 not normalized
- * @param v2 not normalized
- * @param tmpPivotVec temp storage for cross product
- * @param tmpNormalVec temp storage to normalize vector
- * @return this quaternion for chaining.
- */
- public final Quaternion setFromVectors(final Vec3f v1, final Vec3f v2, final Vec3f tmpPivotVec, final Vec3f tmpNormalVec) {
- final float factor = v1.length() * v2.length();
- if ( FloatUtil.isZero(factor, FloatUtil.EPSILON ) ) {
- return setIdentity();
- } else {
- final float dot = v1.dot(v2) / factor; // normalize
- final float theta = FloatUtil.acos(Math.max(-1.0f, Math.min(dot, 1.0f))); // clipping [-1..1]
-
- tmpPivotVec.cross(v1, v2);
-
- if ( dot < 0.0f && FloatUtil.isZero( tmpPivotVec.length(), FloatUtil.EPSILON ) ) {
- // Vectors parallel and opposite direction, therefore a rotation of 180 degrees about any vector
- // perpendicular to this vector will rotate vector a onto vector b.
- //
- // The following guarantees the dot-product will be 0.0.
- int dominantIndex;
- if (Math.abs(v1.x()) > Math.abs(v1.y())) {
- if (Math.abs(v1.x()) > Math.abs(v1.z())) {
- dominantIndex = 0;
- } else {
- dominantIndex = 2;
- }
- } else {
- if (Math.abs(v1.y()) > Math.abs(v1.z())) {
- dominantIndex = 1;
- } else {
- dominantIndex = 2;
- }
- }
- tmpPivotVec.set( dominantIndex, -v1.get( (dominantIndex + 1) % 3 ) );
- tmpPivotVec.set( (dominantIndex + 1) % 3, v1.get( dominantIndex ) );
- tmpPivotVec.set( (dominantIndex + 2) % 3, 0f );
- }
- return setFromAngleAxis(theta, tmpPivotVec, tmpNormalVec);
- }
- }
-
- /**
- * Initialize this quaternion from two normalized vectors
- * <pre>
- * q = (s,v) = (v1•v2 , v1 × v2),
- * angle = angle(v1, v2) = v1•v2
- * axis = v1 x v2
- * </pre>
- * <p>
- * Implementation Details:
- * <ul>
- * <li> {@link #setIdentity()} if square vector-length is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
- * </ul>
- * </p>
- * @param v1 normalized
- * @param v2 normalized
- * @param tmpPivotVec temp storage for cross product
- * @return this quaternion for chaining.
- */
- public final Quaternion setFromNormalVectors(final Vec3f v1, final Vec3f v2, final Vec3f tmpPivotVec) {
- final float factor = v1.length() * v2.length();
- if ( FloatUtil.isZero(factor, FloatUtil.EPSILON ) ) {
- return setIdentity();
- } else {
- final float dot = v1.dot(v2) / factor; // normalize
- final float theta = FloatUtil.acos(Math.max(-1.0f, Math.min(dot, 1.0f))); // clipping [-1..1]
-
- tmpPivotVec.cross(v1, v2);
-
- if ( dot < 0.0f && FloatUtil.isZero( tmpPivotVec.length(), FloatUtil.EPSILON ) ) {
- // Vectors parallel and opposite direction, therefore a rotation of 180 degrees about any vector
- // perpendicular to this vector will rotate vector a onto vector b.
- //
- // The following guarantees the dot-product will be 0.0.
- int dominantIndex;
- if (Math.abs(v1.x()) > Math.abs(v1.y())) {
- if (Math.abs(v1.x()) > Math.abs(v1.z())) {
- dominantIndex = 0;
- } else {
- dominantIndex = 2;
- }
- } else {
- if (Math.abs(v1.y()) > Math.abs(v1.z())) {
- dominantIndex = 1;
- } else {
- dominantIndex = 2;
- }
- }
- tmpPivotVec.set( dominantIndex, -v1.get( (dominantIndex + 1) % 3 ) );
- tmpPivotVec.set( (dominantIndex + 1) % 3, v1.get( dominantIndex ) );
- tmpPivotVec.set( (dominantIndex + 2) % 3, 0f );
- }
- return setFromAngleNormalAxis(theta, tmpPivotVec);
- }
- }
-
- /***
- * Initialize this quaternion with given non-normalized axis vector and rotation angle
- * <p>
- * Implementation Details:
- * <ul>
- * <li> {@link #setIdentity()} if axis is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
- * </ul>
- * </p>
- * @param angle rotation angle (rads)
- * @param vector axis vector not normalized
- * @param tmpV3f temp storage to normalize vector
- * @return this quaternion for chaining.
- *
- * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56">Matrix-FAQ Q56</a>
- * @see #toAngleAxis(Vec3f)
- */
- public final Quaternion setFromAngleAxis(final float angle, final Vec3f vector, final Vec3f tmpV3f) {
- tmpV3f.set(vector).normalize();
- return setFromAngleNormalAxis(angle, tmpV3f);
- }
-
- /***
- * Initialize this quaternion with given normalized axis vector and rotation angle
- * <p>
- * Implementation Details:
- * <ul>
- * <li> {@link #setIdentity()} if axis is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
- * </ul>
- * </p>
- * @param angle rotation angle (rads)
- * @param vector axis vector normalized
- * @return this quaternion for chaining.
- *
- * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56">Matrix-FAQ Q56</a>
- * @see #toAngleAxis(Vec3f)
- */
- public final Quaternion setFromAngleNormalAxis(final float angle, final Vec3f vector) {
- if( vector.isZero() ) {
- setIdentity();
- } else {
- final float halfangle = angle * 0.5f;
- final float sin = FloatUtil.sin(halfangle);
- x = vector.x() * sin;
- y = vector.y() * sin;
- z = vector.z() * sin;
- w = FloatUtil.cos(halfangle);
- }
- return this;
- }
-
- /**
- * Transform the rotational quaternion to axis based rotation angles
- *
- * @param axis storage for computed axis
- * @return the rotation angle in radians
- * @see #setFromAngleAxis(float, Vec3f, Vec3f)
- */
- public final float toAngleAxis(final Vec3f axis) {
- final float sqrLength = x*x + y*y + z*z;
- float angle;
- if ( FloatUtil.isZero(sqrLength, FloatUtil.EPSILON) ) { // length is ~0
- angle = 0.0f;
- axis.set( 1.0f, 0.0f, 0.0f );
- } else {
- angle = FloatUtil.acos(w) * 2.0f;
- final float invLength = 1.0f / FloatUtil.sqrt(sqrLength);
- axis.set( x * invLength,
- y * invLength,
- z * invLength );
- }
- return angle;
- }
-
- /**
- * Initializes this quaternion from the given Euler rotation array <code>angradXYZ</code> in radians.
- * <p>
- * The <code>angradXYZ</code> vector is laid out in natural order:
- * <ul>
- * <li>x - bank</li>
- * <li>y - heading</li>
- * <li>z - attitude</li>
- * </ul>
- * </p>
- * For details see {@link #setFromEuler(float, float, float)}.
- * @param angradXYZ euler angle vector in radians holding x-bank, y-heading and z-attitude
- * @return this quaternion for chaining.
- * @see #setFromEuler(float, float, float)
- */
- public final Quaternion setFromEuler(final Vec3f angradXYZ) {
- return setFromEuler(angradXYZ.x(), angradXYZ.y(), angradXYZ.z());
- }
-
- /**
- * Initializes this quaternion from the given Euler rotation angles in radians.
- * <p>
- * The rotations are applied in the given order:
- * <ul>
- * <li>y - heading</li>
- * <li>z - attitude</li>
- * <li>x - bank</li>
- * </ul>
- * </p>
- * <p>
- * Implementation Details:
- * <ul>
- * <li> {@link #setIdentity()} if all angles are {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
- * <li> result is {@link #normalize()}ed</li>
- * </ul>
- * </p>
- * @param bankX the Euler pitch angle in radians. (rotation about the X axis)
- * @param headingY the Euler yaw angle in radians. (rotation about the Y axis)
- * @param attitudeZ the Euler roll angle in radians. (rotation about the Z axis)
- * @return this quaternion for chaining.
- *
- * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q60">Matrix-FAQ Q60</a>
- * @see <a href="http://vered.rose.utoronto.ca/people/david_dir/GEMS/GEMS.html">Gems</a>
- * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/index.htm">euclideanspace.com-eulerToQuaternion</a>
- * @see #toEuler(Vec3f)
- */
- public final Quaternion setFromEuler(final float bankX, final float headingY, final float attitudeZ) {
- if ( VectorUtil.isZero(bankX, headingY, attitudeZ, FloatUtil.EPSILON) ) {
- return setIdentity();
- } else {
- float angle = headingY * 0.5f;
- final float sinHeadingY = FloatUtil.sin(angle);
- final float cosHeadingY = FloatUtil.cos(angle);
- angle = attitudeZ * 0.5f;
- final float sinAttitudeZ = FloatUtil.sin(angle);
- final float cosAttitudeZ = FloatUtil.cos(angle);
- angle = bankX * 0.5f;
- final float sinBankX = FloatUtil.sin(angle);
- final float cosBankX = FloatUtil.cos(angle);
-
- // variables used to reduce multiplication calls.
- final float cosHeadingXcosAttitude = cosHeadingY * cosAttitudeZ;
- final float sinHeadingXsinAttitude = sinHeadingY * sinAttitudeZ;
- final float cosHeadingXsinAttitude = cosHeadingY * sinAttitudeZ;
- final float sinHeadingXcosAttitude = sinHeadingY * cosAttitudeZ;
-
- w = cosHeadingXcosAttitude * cosBankX - sinHeadingXsinAttitude * sinBankX;
- x = cosHeadingXcosAttitude * sinBankX + sinHeadingXsinAttitude * cosBankX;
- y = sinHeadingXcosAttitude * cosBankX + cosHeadingXsinAttitude * sinBankX;
- z = cosHeadingXsinAttitude * cosBankX - sinHeadingXcosAttitude * sinBankX;
- return normalize();
- }
- }
-
- /**
- * Transform this quaternion to Euler rotation angles in radians (pitchX, yawY and rollZ).
- * <p>
- * The <code>result</code> array is laid out in natural order:
- * <ul>
- * <li>x - bank</li>
- * <li>y - heading</li>
- * <li>z - attitude</li>
- * </ul>
- * </p>
- *
- * @param result euler angle result vector for radians x-bank, y-heading and z-attitude
- * @return the Vec3f `result` filled with x-bank, y-heading and z-attitude
- * @see <a href="http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm">euclideanspace.com-quaternionToEuler</a>
- * @see #setFromEuler(float, float, float)
- */
- public Vec3f toEuler(final Vec3f result) {
- final float sqw = w*w;
- final float sqx = x*x;
- final float sqy = y*y;
- final float sqz = z*z;
- final float unit = sqx + sqy + sqz + sqw; // if normalized is one, otherwise, is correction factor
- final float test = x*y + z*w;
-
- if (test > 0.499f * unit) { // singularity at north pole
- result.set( 0f, // x-bank
- 2f * FloatUtil.atan2(x, w), // y-heading
- FloatUtil.HALF_PI ); // z-attitude
- } else if (test < -0.499f * unit) { // singularity at south pole
- result.set( 0f, // x-bank
- -2 * FloatUtil.atan2(x, w), // y-heading
- -FloatUtil.HALF_PI ); // z-attitude
- } else {
- result.set( FloatUtil.atan2(2f * x * w - 2 * y * z, -sqx + sqy - sqz + sqw), // x-bank
- FloatUtil.atan2(2f * y * w - 2 * x * z, sqx - sqy - sqz + sqw), // y-heading
- FloatUtil.asin( 2f * test / unit) ); // z-attitude
- }
- return result;
- }
-
- /**
- * Compute the quaternion from a 3x3 column rotation matrix
- * <p>
- * See <a href="ftp://ftp.cis.upenn.edu/pub/graphics/shoemake/quatut.ps.Z">Graphics Gems Code</a>,<br/>
- * <a href="http://mathworld.wolfram.com/MatrixTrace.html">MatrixTrace</a>.
- * </p>
- * <p>
- * Buggy <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q55">Matrix-FAQ Q55</a>
- * </p>
- *
- * @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
- * <p>
- * See <a href="ftp://ftp.cis.upenn.edu/pub/graphics/shoemake/quatut.ps.Z">Graphics Gems Code</a>,<br/>
- * <a href="http://mathworld.wolfram.com/MatrixTrace.html">MatrixTrace</a>.
- * </p>
- * <p>
- * Buggy <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q55">Matrix-FAQ Q55</a>
- * </p>
- *
- * @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.
- * <p>
- * Implementation Details:
- * <ul>
- * <li> makes identity matrix if {@link #magnitudeSquared()} is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
- * </ul>
- * </p>
- *
- * @param matrix float[16] store for the resulting normalized column matrix 4x4
- * @return the given matrix store
- * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54">Matrix-FAQ Q54</a>
- * @see #setFromMatrix(Matrix4f)
- * @see #setFromMatrix(float, float, float, float, float, float, float, float, float)
- */
- public final float[] toMatrix(final float[] matrix) {
- // pre-multiply scaled-reciprocal-magnitude to reduce multiplications
- final float norm = magnitudeSquared();
- if ( FloatUtil.isZero(norm) ) {
- // identity matrix -> srecip = 0f
- return FloatUtil.makeIdentity(matrix);
- }
- final float srecip;
- if ( FloatUtil.isEqual(1f, norm) ) {
- srecip = 2f;
- } else {
- srecip = 2.0f / norm;
- }
-
- final float xs = srecip * x;
- final float ys = srecip * y;
- final float zs = srecip * z;
-
- final float xx = x * xs;
- final float xy = x * ys;
- final float xz = x * zs;
- final float xw = xs * w;
- final float yy = y * ys;
- final float yz = y * zs;
- final float yw = ys * w;
- final float zz = z * zs;
- final float zw = zs * w;
-
- matrix[0+0*4] = 1f - ( yy + zz );
- matrix[0+1*4] = ( xy - zw );
- matrix[0+2*4] = ( xz + yw );
- matrix[0+3*4] = 0f;
-
- matrix[1+0*4] = ( xy + zw );
- matrix[1+1*4] = 1f - ( xx + zz );
- matrix[1+2*4] = ( yz - xw );
- matrix[1+3*4] = 0f;
-
- matrix[2+0*4] = ( xz - yw );
- matrix[2+1*4] = ( yz + xw );
- matrix[2+2*4] = 1f - ( xx + yy );
- matrix[2+3*4] = 0f;
-
- matrix[3+0*4] = 0f;
- matrix[3+1*4] = 0f;
- matrix[3+2*4] = 0f;
- matrix[3+3*4] = 1f;
- return matrix;
- }
-
- /**
- * Transform this quaternion to a normalized 4x4 column matrix representing the rotation.
- * <p>
- * Implementation Details:
- * <ul>
- * <li> makes identity matrix if {@link #magnitudeSquared()} is {@link FloatUtil#isZero(float, float) is zero} using {@link FloatUtil#EPSILON epsilon}</li>
- * </ul>
- * </p>
- *
- * @param matrix store for the resulting normalized column matrix 4x4
- * @return the given matrix store
- * @see <a href="http://web.archive.org/web/20041029003853/http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54">Matrix-FAQ Q54</a>
- * @see #setFromMatrix(float, float, float, float, float, float, float, float, float)
- * @see Matrix4f#setToRotation(Quaternion)
- */
- public final Matrix4f toMatrix(final Matrix4f matrix) {
- return matrix.setToRotation(this);
- }
-
- /**
- * Initializes this quaternion to represent a rotation formed by the given three <i>orthogonal</i> axes.
- * <p>
- * No validation whether the axes are <i>orthogonal</i> is performed.
- * </p>
- *
- * @param xAxis vector representing the <i>orthogonal</i> x-axis of the coordinate system.
- * @param yAxis vector representing the <i>orthogonal</i> y-axis of the coordinate system.
- * @param zAxis vector representing the <i>orthogonal</i> 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 <i>orthogonal</i> rotation axes.
- *
- * @param xAxis vector representing the <i>orthogonal</i> x-axis of the coordinate system.
- * @param yAxis vector representing the <i>orthogonal</i> y-axis of the coordinate system.
- * @param zAxis vector representing the <i>orthogonal</i> 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.
- * <p>
- * A ray, also known as a half line, consists out of it's <i>origin</i>
- * and <i>direction</i>. Hence it is bound to only the <i>origin</i> side,
- * where the other end is +infinitive.
- * <pre>
- * R(t) = R0 + Rd * t with R0 origin, Rd direction and t > 0.0
- * </pre>
- * </p>
- * <p>
- * A {@link Ray} maybe used for <i>picking</i>
- * 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}.
- * </p>
- */
-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 <i>norm</i> or <i>magnitude</i>
- */
- public float length() {
- return (float) Math.sqrt(lengthSq());
- }
-
- /**
- * Return the squared length of this vector, a.k.a the squared <i>norm</i> or squared <i>magnitude</i>
- */
- 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.
- * <p>
- * When comparing the relative distance between two points it is usually sufficient to compare the squared
- * distances, thus avoiding an expensive square root operation.
- * </p>
- */
- 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)}.
- * <p>
- * Implementation considers following corner cases:
- * <ul>
- * <li>NaN == NaN</li>
- * <li>+Inf == +Inf</li>
- * <li>-Inf == -Inf</li>
- * </ul>
- * @param o comparison value
- * @param epsilon consider using {@link FloatUtil#EPSILON}
- * @return true if all components differ less than {@code epsilon}, otherwise false.
- */
- public boolean isEqual(final Vec2f o, final float epsilon) {
- if( this == o ) {
- return true;
- } else {
- return FloatUtil.isEqual(x, o.x, epsilon) &&
- FloatUtil.isEqual(y, o.y, epsilon);
- }
- }
-
- /**
- * Equals check using {@link FloatUtil#EPSILON} in {@link FloatUtil#isEqual(float, float)}.
- * <p>
- * Implementation considers following corner cases:
- * <ul>
- * <li>NaN == NaN</li>
- * <li>+Inf == +Inf</li>
- * <li>-Inf == -Inf</li>
- * </ul>
- * @param o comparison value
- * @return true if all components differ less than {@link FloatUtil#EPSILON}, otherwise false.
- */
- public boolean isEqual(final Vec2f o) {
- if( this == o ) {
- return true;
- } else {
- return FloatUtil.isEqual(x, o.x) &&
- FloatUtil.isEqual(y, o.y);
- }
- }
-
- @Override
- public boolean equals(final Object o) {
- if( o instanceof Vec2f ) {
- return isEqual((Vec2f)o);
- } else {
- return false;
- }
- }
-
- @Override
- public String toString() {
- return x + " / " + y;
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Vec2i.java b/src/jogl/classes/com/jogamp/opengl/math/Vec2i.java
deleted file mode 100644
index 9e70a502f..000000000
--- a/src/jogl/classes/com/jogamp/opengl/math/Vec2i.java
+++ /dev/null
@@ -1,153 +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 integer components.
- */
-public final class Vec2i {
- private int x;
- private int y;
-
- public Vec2i() {}
-
- public Vec2i(final Vec2i o) {
- set(o);
- }
-
- public Vec2i copy() {
- return new Vec2i(this);
- }
-
- public Vec2i(final int[/*2*/] xy) {
- set(xy);
- }
-
- public Vec2i(final int x, final int y) {
- set(x, y);
- }
-
- /** this = o, returns this. */
- public void set(final Vec2i o) {
- this.x = o.x;
- this.y = o.y;
- }
-
- /** this = { x, y }, returns this. */
- public void set(final int x, final int y) {
- this.x = x;
- this.y = y;
- }
-
- /** this = xy, returns this. */
- public Vec2i set(final int[/*2*/] xy) {
- this.x = xy[0];
- this.y = xy[1];
- return this;
- }
-
- /** xy = this, returns xy. */
- public int[] get(final int[/*2*/] xy) {
- xy[0] = this.x;
- xy[1] = this.y;
- return xy;
- }
-
- public int x() { return x; }
- public int y() { return y; }
-
- public void setX(final int x) { this.x = x; }
- public void setY(final int y) { this.y = y; }
-
- /** Return true if all components are zero. */
- public boolean isZero() {
- return 0 == x && 0 == y;
- }
-
- /**
- * Return the length of this vector, a.k.a the <i>norm</i> or <i>magnitude</i>
- */
- public int length() {
- return (int) Math.sqrt(lengthSq());
- }
-
- /**
- * Return the squared length of this vector, a.k.a the squared <i>norm</i> or squared <i>magnitude</i>
- */
- public int lengthSq() {
- return x*x + y*y;
- }
-
- /**
- * Return the squared distance between this vector and the given one.
- * <p>
- * When comparing the relative distance between two points it is usually sufficient to compare the squared
- * distances, thus avoiding an expensive square root operation.
- * </p>
- */
- 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 <i>norm</i> or <i>magnitude</i>
- */
- public float length() {
- return (float) Math.sqrt(lengthSq());
- }
-
- /**
- * Return the squared length of this vector, a.k.a the squared <i>norm</i> or squared <i>magnitude</i>
- */
- 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.
- * <p>
- * When comparing the relative distance between two points it is usually sufficient to compare the squared
- * distances, thus avoiding an expensive square root operation.
- * </p>
- */
- 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)}.
- * <p>
- * Implementation considers following corner cases:
- * <ul>
- * <li>NaN == NaN</li>
- * <li>+Inf == +Inf</li>
- * <li>-Inf == -Inf</li>
- * </ul>
- * @param o comparison value
- * @param epsilon consider using {@link FloatUtil#EPSILON}
- * @return true if all components differ less than {@code epsilon}, otherwise false.
- */
- public boolean isEqual(final Vec3f o, final float epsilon) {
- if( this == o ) {
- return true;
- } else {
- return FloatUtil.isEqual(x, o.x, epsilon) &&
- FloatUtil.isEqual(y, o.y, epsilon) &&
- FloatUtil.isEqual(z, o.z, epsilon);
- }
- }
-
- /**
- * Equals check using {@link FloatUtil#EPSILON} in {@link FloatUtil#isEqual(float, float)}.
- * <p>
- * Implementation considers following corner cases:
- * <ul>
- * <li>NaN == NaN</li>
- * <li>+Inf == +Inf</li>
- * <li>-Inf == -Inf</li>
- * </ul>
- * @param o comparison value
- * @return true if all components differ less than {@link FloatUtil#EPSILON}, otherwise false.
- */
- public boolean isEqual(final Vec3f o) {
- if( this == o ) {
- return true;
- } else {
- return FloatUtil.isEqual(x, o.x) &&
- FloatUtil.isEqual(y, o.y) &&
- FloatUtil.isEqual(z, o.z);
- }
- }
-
- @Override
- public boolean equals(final Object o) {
- if( o instanceof Vec3f ) {
- return isEqual((Vec3f)o);
- } else {
- return false;
- }
- }
-
- @Override
- public String toString() {
- return x + " / " + y + " / " + z;
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Vec4f.java b/src/jogl/classes/com/jogamp/opengl/math/Vec4f.java
deleted file mode 100644
index 914450bf1..000000000
--- a/src/jogl/classes/com/jogamp/opengl/math/Vec4f.java
+++ /dev/null
@@ -1,394 +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;
-
-/**
- * 4D Vector based upon four 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 Vec4f {
- private float x;
- private float y;
- private float z;
- private float w;
-
- public Vec4f() {}
-
- public Vec4f(final Vec4f o) {
- set(o);
- }
-
- /** Creating new Vec4f using { o, w }. */
- public Vec4f(final Vec3f o, final float w) {
- set(o, w);
- }
-
- public Vec4f copy() {
- return new Vec4f(this);
- }
-
- public Vec4f(final float[/*4*/] xyzw) {
- set(xyzw);
- }
-
- public Vec4f(final float x, final float y, final float z, final float w) {
- set(x, y, z, w);
- }
-
- /** this = o, returns this. */
- public Vec4f set(final Vec4f o) {
- this.x = o.x;
- this.y = o.y;
- this.z = o.z;
- this.w = o.w;
- return this;
- }
-
- /** this = { o, w }, returns this. */
- public Vec4f set(final Vec3f o, final float w) {
- this.x = o.x();
- this.y = o.y();
- this.z = o.z();
- this.w = w;
- return this;
- }
-
- /** this = { x, y, z, w }, returns this. */
- public Vec4f set(final float x, final float y, final float z, final float w) {
- this.x = x;
- this.y = y;
- this.z = z;
- this.w = w;
- return this;
- }
-
- /** this = xyzw, returns this. */
- public Vec4f set(final float[/*4*/] xyzw) {
- this.x = xyzw[0];
- this.y = xyzw[1];
- this.z = xyzw[2];
- this.w = xyzw[3];
- return this;
- }
-
- /** Sets the ith component, 0 <= i < 4 */
- 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;
- case 3: w = val; break;
- default: throw new IndexOutOfBoundsException();
- }
- }
-
- /** xyzw = this, returns xyzw. */
- public float[] get(final float[/*4*/] xyzw) {
- xyzw[0] = this.x;
- xyzw[1] = this.y;
- xyzw[2] = this.z;
- xyzw[3] = this.w;
- return xyzw;
- }
-
- /** Gets the ith component, 0 <= i < 4 */
- public float get(final int i) {
- switch (i) {
- case 0: return x;
- case 1: return y;
- case 2: return z;
- case 3: return w;
- default: throw new IndexOutOfBoundsException();
- }
- }
-
- public float x() { return x; }
- public float y() { return y; }
- public float z() { return z; }
- public float w() { return w; }
-
- 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; }
- public void setW(final float w) { this.w = w; }
-
- /** this = max(this, m), returns this. */
- public Vec4f max(final Vec4f 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);
- this.w = Math.max(this.w, m.w);
- return this;
- }
- /** this = min(this, m), returns this. */
- public Vec4f min(final Vec4f 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);
- this.w = Math.min(this.w, m.w);
- return this;
- }
-
- /** Returns this * val; creates new vector */
- public Vec4f mul(final float val) {
- return new Vec4f(this).scale(val);
- }
-
- /** this = a * b, returns this. */
- public Vec4f mul(final Vec4f a, final Vec4f b) {
- x = a.x * b.x;
- y = a.y * b.y;
- z = a.z * b.z;
- w = a.w * b.w;
- return this;
- }
-
- /** this = this * s, returns this. */
- public Vec4f scale(final float s) {
- x *= s;
- y *= s;
- z *= s;
- w *= s;
- return this;
- }
-
- /** this = this * { sx, sy, sz, sw }, returns this. */
- public Vec4f scale(final float sx, final float sy, final float sz, final float sw) {
- x *= sx;
- y *= sy;
- z *= sz;
- w *= sw;
- return this;
- }
-
- /** this = this * { s.x, s.y, s.z, s.w }, returns this. */
- public Vec4f scale(final Vec4f s) { return scale(s.x, s.y, s.z, s.w); }
-
- /** Returns this + arg; creates new vector */
- public Vec4f plus(final Vec4f arg) {
- return new Vec4f(this).add(arg);
- }
-
- /** this = a + b, returns this. */
- public Vec4f plus(final Vec4f a, final Vec4f b) {
- x = a.x + b.x;
- y = a.y + b.y;
- z = a.z + b.z;
- w = a.w + b.w;
- return this;
- }
-
- /** this = this + { dx, dy, dz, dw }, returns this. */
- public Vec4f add(final float dx, final float dy, final float dz, final float dw) {
- x += dx;
- y += dy;
- z += dz;
- w += dw;
- return this;
- }
-
- /** this = this + b, returns this. */
- public Vec4f add(final Vec4f b) {
- x += b.x;
- y += b.y;
- z += b.z;
- w += b.w;
- return this;
- }
-
- /** Returns this - arg; creates new vector */
- public Vec4f minus(final Vec4f arg) {
- return new Vec4f(this).sub(arg);
- }
-
- /** this = a - b, returns this. */
- public Vec4f minus(final Vec4f a, final Vec4f b) {
- x = a.x - b.x;
- y = a.y - b.y;
- z = a.z - b.z;
- w = a.w - b.w;
- return this;
- }
-
- /** this = this - b, returns this. */
- public Vec4f sub(final Vec4f b) {
- x -= b.x;
- y -= b.y;
- z -= b.z;
- w -= b.w;
- 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) && FloatUtil.isZero(w);
- }
-
- /**
- * Return the length of this vector, a.k.a the <i>norm</i> or <i>magnitude</i>
- */
- public float length() {
- return (float) Math.sqrt(lengthSq());
- }
-
- /**
- * Return the squared length of this vector, a.k.a the squared <i>norm</i> or squared <i>magnitude</i>
- */
- public float lengthSq() {
- return x*x + y*y + z*z + w*w;
- }
-
- /**
- * Normalize this vector in place
- */
- public Vec4f normalize() {
- final float lengthSq = lengthSq();
- if ( FloatUtil.isZero( lengthSq ) ) {
- x = 0.0f;
- y = 0.0f;
- z = 0.0f;
- w = 0.0f;
- } else {
- final float invSqr = 1.0f / (float)Math.sqrt(lengthSq);
- x *= invSqr;
- y *= invSqr;
- z *= invSqr;
- w *= invSqr;
- }
- return this;
- }
-
- /**
- * Return the squared distance between this vector and the given one.
- * <p>
- * When comparing the relative distance between two points it is usually sufficient to compare the squared
- * distances, thus avoiding an expensive square root operation.
- * </p>
- */
- 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)}.
- * <p>
- * Implementation considers following corner cases:
- * <ul>
- * <li>NaN == NaN</li>
- * <li>+Inf == +Inf</li>
- * <li>-Inf == -Inf</li>
- * </ul>
- * @param o comparison value
- * @param epsilon consider using {@link FloatUtil#EPSILON}
- * @return true if all components differ less than {@code epsilon}, otherwise false.
- */
- public boolean isEqual(final Vec4f o, final float epsilon) {
- if( this == o ) {
- return true;
- } else {
- return FloatUtil.isEqual(x, o.x, epsilon) &&
- FloatUtil.isEqual(y, o.y, epsilon) &&
- FloatUtil.isEqual(z, o.z, epsilon) &&
- FloatUtil.isEqual(w, o.w, epsilon);
- }
- }
-
- /**
- * Equals check using {@link FloatUtil#EPSILON} in {@link FloatUtil#isEqual(float, float)}.
- * <p>
- * Implementation considers following corner cases:
- * <ul>
- * <li>NaN == NaN</li>
- * <li>+Inf == +Inf</li>
- * <li>-Inf == -Inf</li>
- * </ul>
- * @param o comparison value
- * @return true if all components differ less than {@link FloatUtil#EPSILON}, otherwise false.
- */
- public boolean isEqual(final Vec4f o) {
- if( this == o ) {
- return true;
- } else {
- return FloatUtil.isEqual(x, o.x) &&
- FloatUtil.isEqual(y, o.y) &&
- FloatUtil.isEqual(z, o.z) &&
- FloatUtil.isEqual(w, o.w);
- }
- }
-
- @Override
- public boolean equals(final Object o) {
- if( o instanceof Vec4f ) {
- return isEqual((Vec4f)o);
- } else {
- return false;
- }
- }
-
- @Override
- public String toString() {
- return x + " / " + y + " / " + z + " / " + w;
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
deleted file mode 100644
index e38501c73..000000000
--- a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
+++ /dev/null
@@ -1,770 +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;
-
-import java.util.ArrayList;
-
-import com.jogamp.graph.geom.plane.Winding;
-
-public final class VectorUtil {
- /**
- * Return true if 2D vector components are zero, no {@link FloatUtil#EPSILON} is taken into consideration.
- */
- public static boolean isVec2Zero(final Vec3f vec) {
- return 0f == vec.x() && 0f == vec.y();
- }
-
- /**
- * Return true if all three vector components are zero, i.e. it's their absolute value < <code>epsilon</code>.
- * <p>
- * Implementation uses {@link FloatUtil#isZero(float, float)}, see API doc for details.
- * </p>
- */
- 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}.
- * <p>
- * Implementation uses {@link FloatUtil#isZero(float)}, see API doc for details.
- * </p>
- */
- 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.
- * <p>
- * When comparing the relative distance between two points it is usually sufficient to compare the squared
- * distances, thus avoiding an expensive square root operation.
- * </p>
- */
- 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 <i>norm</i> or squared <i>magnitude</i>
- */
- 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 <i>norm</i> or squared <i>magnitude</i>
- */
- 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 <i>norm</i> or squared <i>magnitude</i>
- */
- 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 <i>norm</i> or <i>magnitude</i>
- */
- 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
- * <p>
- * Consider using {@link #getWinding(ArrayList)} using the {@link #area(ArrayList)} function over all points
- * on complex shapes for a reliable result!
- * </p>
- * @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.
- * <p>
- * This method is utilized e.g. to reliably compute the {@link Winding} of complex shapes.
- * </p>
- * @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.
- * <p>
- * Uses the {@link #area(ArrayList)} function over all points
- * on complex shapes for a reliable result!
- * </p>
- * @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.
- * <p>
- * Thanks to <i>Norman Vine -- [email protected] (with hacks by Steve)</i>
- * </p>
- *
- * @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.
- * <p>
- * A few references for collision detection, intersections:
- * <pre>
- * 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
- * </pre>
- * </p>
- *
- */
-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.
- * <p>
- * The dimension, i.e. {@link #getWidth()} abd {@link #getHeight()} is {@link Float#isInfinite()} thereafter.
- * </p>
- * @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.
- * <p>
- * The dimension, i.e. {@link #getWidth()} abd {@link #getHeight()} is {@link Float#isInfinite()} thereafter.
- * </p>
- * @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 <i>transformed</i> on the fly first.
- * @param newBox AABBox to be encapsulated in
- * @param t the {@link AffineTransform} applied on <i>newBox</i> on the fly
- * @param tmpV3 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<low.x() || x>high.x()){
- return false;
- }
- if(y<low.y()|| y>high.y()){
- return false;
- }
- return true;
- }
-
- /**
- * Check if the xyz coordinates are bounded/contained
- * by this AABBox.
- * @param x x-axis coordinate value
- * @param y y-axis coordinate value
- * @param z z-axis coordinate value
- * @return true if x belong to (low.x, high.x) and
- * y belong to (low.y, high.y) and z belong to (low.z, high.z)
- */
- public final boolean contains(final float x, final float y, final float z) {
- if(x<low.x() || x>high.x()){
- return false;
- }
- if(y<low.y()|| y>high.y()){
- return false;
- }
- if(z<low.z() || z>high.z()){
- return false;
- }
- return true;
- }
-
- /**
- * Check if there is a common region between this AABBox and the passed
- * 2D region irrespective of z range
- * @param x lower left x-coord
- * @param y lower left y-coord
- * @param w width
- * @param h hight
- * @return true if this AABBox might have a common region with this 2D region
- */
- public final boolean intersects2DRegion(final float x, final float y, final float w, final float h) {
- if (w <= 0 || h <= 0) {
- return false;
- }
-
- final float _w = getWidth();
- final float _h = getHeight();
- if (_w <= 0 || _h <= 0) {
- return false;
- }
-
- final float x0 = getMinX();
- final float y0 = getMinY();
- return (x >= x0 &&
- y >= y0 &&
- x + w <= x0 + _w &&
- y + h <= y0 + _h);
- }
-
- /**
- * Check if {@link Ray} intersects this bounding box.
- * <p>
- * Versions uses the SAT[1], testing 6 axes.
- * Original code for OBBs from MAGIC.
- * Rewritten for AABBs and reorganized for early exits[2].
- * </p>
- * <pre>
- * [1] SAT = Separating Axis Theorem
- * [2] http://www.codercorner.com/RayAABB.cpp
- * </pre>
- * @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.
- * <p>
- * <ul>
- * <li>Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990 [2]</li>
- * <li>Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500)</li>
- * <li>Epsilon value added by Klaus Hartmann.</li>
- * </ul>
- * </p>
- * <p>
- * Method is based on the requirements:
- * <ul>
- * <li>the integer representation of 0.0f is 0x00000000</li>
- * <li>the sign bit of the float is the most significant one</li>
- * </ul>
- * </p>
- * <p>
- * Report bugs: [email protected] (original author)
- * </p>
- * <pre>
- * [1] http://www.codercorner.com/RayAABB.cpp
- * [2] http://tog.acm.org/resources/GraphicsGems/gems/RayBox.c
- * </pre>
- * @param result vec3
- * @param ray
- * @param epsilon
- * @param assumeIntersection if true, method assumes an intersection, i.e. by pre-checking via {@link #intersectsRay(Ray)}.
- * In this case method will not validate a possible non-intersection and just computes
- * coordinates.
- * @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
- * <p>
- * high and low is recomputed by scaling its distance to fixed center.
- * </p>
- * @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
- * <p>
- * high and low is scaled and center recomputed.
- * </p>
- * @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.
- * <p>
- * If <code>useCenterZ</code> is <code>true</code>,
- * 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.
- * </p>
- * <pre>
- * .z() ------ [4]
- * | |
- * | |
- * .y() ------ [3]
- * </pre>
- * @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
- * <ul>
- * <li> {@link #classifyPoint(float[]) point} </li>
- * <li> {@link #classifySphere(float[], float) sphere} </li>
- * </ul>
- * and to test whether they are outside
- * <ul>
- * <li> {@link #isPointOutside(float[]) point} </li>
- * <li> {@link #isSphereOutside(float[], float) sphere} </li>
- * <li> {@link #isAABBoxOutside(AABBox) bounding-box} </li>
- * </ul>
- *
- * <p>
- * Extracting the world-frustum planes from the P*Mv:
- * <pre>
- * Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix
- * Gil Gribb <[email protected]>
- * Klaus Hartmann <[email protected]>
- * http://graphics.cs.ucf.edu/cap4720/fall2008/plane_extraction.pdf
- * </pre>
- * Classifying Point, Sphere and AABBox:
- * <pre>
- * Efficient View Frustum Culling
- * Daniel Sýkora <[email protected]>
- * Josef Jelínek <[email protected]>
- * http://www.cg.tuwien.ac.at/hostings/cescg/CESCG-2002/DSykoraJJelinek/index.html
- * </pre>
- * <pre>
- * Lighthouse3d.com
- * http://www.lighthouse3d.com/tutorials/view-frustum-culling/
- * </pre>
- *
- * Fundamentals about Planes, Half-Spaces and Frustum-Culling:<br/>
- * <pre>
- * Planes and Half-Spaces, Max Wagner <[email protected]>
- * http://www.emeyex.com/site/tuts/PlanesHalfSpaces.pdf
- * </pre>
- * <pre>
- * Frustum Culling, Max Wagner <[email protected]>
- * http://www.emeyex.com/site/tuts/FrustumCulling.pdf
- * </pre>
- * </p>
- */
-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.
- * <p>
- * Use one of the <code>update(..)</code> methods to set the {@link #getPlanes() planes}.
- * </p>
- * @see #updateByPlanes(Plane[])
- * @see #updateFrustumPlanes(float[], int)
- */
- public Frustum() {
- for (int i = 0; i < 6; ++i) {
- planes[i] = new Plane();
- }
- }
-
- /**
- * Plane equation := dot(n, x - p) = 0 -> ax + bc + cx + d == 0
- * <p>
- * In order to work w/ {@link Frustum#isOutside(AABBox) isOutside(..)} methods,
- * the normals have to point to the inside of the frustum.
- * </p>
- */
- 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.
- * <ul>
- * <li>If dist &lt; 0 , then the point p lies in the negative halfspace.</li>
- * <li>If dist = 0 , then the point p lies in the plane.</li>
- * <li>If dist &gt; 0 , then the point p lies in the positive halfspace.</li>
- * </ul>
- * A plane cuts 3D space into 2 half spaces.
- * <p>
- * Positive halfspace is where the plane’s normals vector points into.
- * </p>
- * <p>
- * Negative halfspace is the <i>other side</i> of the plane, i.e. *-1
- * </p>
- **/
- 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:
- * <ul>
- * <li>{@link #LEFT}</li>
- * <li>{@link #RIGHT}</li>
- * <li>{@link #BOTTOM}</li>
- * <li>{@link #TOP}</li>
- * <li>{@link #NEAR}</li>
- * <li>{@link #FAR}</li>
- * </ul>
- * <p>
- * {@link Plane}'s normals are pointing to the inside of the frustum
- * in order to work w/ {@link #isOutside(AABBox) isOutside(..)} methods.
- * </p>
- *
- * @return array of normalized {@link Plane}s, order see above.
- */
- public final Plane[] getPlanes() { return planes; }
-
- /**
- * Copy the given <code>src</code> 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}.
- * <p>
- * Operation Details:
- * <ul>
- * <li>The given {@link FovDesc} will be transformed
- * into the given perspective matrix (column major order) first,
- * see {@link Matrix4f#setToPerspective(FovHVHalves, float, float)}.</li>
- * <li>Then the perspective matrix is used to {@link Matrix4f#updateFrustumPlanes(Frustum)} this instance.</li>
- * </ul>
- * </p>
- * <p>
- * Frustum plane's normals will point to the inside of the viewing frustum,
- * as required by this class.
- * </p>
- *
- * @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.
- * <p>
- * Frustum plane's normals will point to the inside of the viewing frustum,
- * as required by this class.
- * </p>
- */
- 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.
- * <p>
- * Note: If method returns false, the box may only be partially inside.
- * </p>
- */
- 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();
- }
-}