aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-04-07 08:46:18 +0200
committerSven Gothel <[email protected]>2023-04-07 08:46:18 +0200
commit84a6d63205ec49ddfb36b57fe2888425ecda3a5a (patch)
tree354cec2ac14a8932a01122c5234926e774ef874e /src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java
parent10b60e10ece3cbc3e0b8a68ac73229371530e0ba (diff)
PMVMatrix rewrite using Matrix4f, providing SyncMatrix4f* for GLUniformData; Utilize Vec3f, Recti, .. throughout API (Matrix4f, AABBox, .. Graph*)
Big Easter Cleanup - Net -214 lines of code, despite new classes. - GLUniformData buffer can be synced w/ underlying data via SyncAction/SyncBuffer, e.g. SyncMatrix4f + SyncMatrices4f - PMVMatrix rewrite using Matrix4f and providing SyncMatrix4f/Matrices4f to sync w/ GLUniformData - Additional SyncMatrix4f16 + SyncMatrices4f16 covering Matrix4f sync w/ GLUniformData w/o PMVMatrix - Utilize Vec3f, Recti, .. throughout API (Matrix4f, AABBox, .. Graph*) - Moved FloatUtil -> Matrix4f, kept a few basic matrix ops for ProjectFloat - Most, if not all, float[] and int[] should have been moved to proper classes - int[] -> Recti for viewport rectangle - Matrix4f and PMVMatrix is covered by math unit tests (as was FloatUtil before) -> save Passed all unit tests on AMD64 GNU/Linux
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java232
1 files changed, 155 insertions, 77 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java b/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java
index 6f4b2f38d..a06d5cefc 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/Matrix4f.java
@@ -121,10 +121,44 @@ public class Matrix4f {
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 load(..)
+ // 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>
@@ -242,7 +276,7 @@ public class Matrix4f {
// Read out Matrix via get(..)
//
- /** Gets the ith component, 0 <= i < 16 */
+ /** Gets the {@code i}th component, 0 <= i < 16 */
public float get(final int i) {
switch (i) {
case 0+4*0: return m00;
@@ -686,10 +720,6 @@ public class Matrix4f {
/**
* Multiply matrix: [this] = [this] x [b]
- * <p>
- * Roughly 15% slower than {@link #mul(Matrix4f, Matrix4f)}
- * Roughly 3% slower than {@link FloatUtil#multMatrix(float[], float[])}
- * </p>
* @param b 4x4 matrix
* @return this matrix for chaining
* @see #mul(Matrix4f, Matrix4f)
@@ -736,10 +766,6 @@ public class Matrix4f {
/**
* Multiply matrix: [this] = [a] x [b]
- * <p>
- * Roughly 13% faster than {@link #mul(Matrix4f)}
- * Roughly 11% faster than {@link FloatUtil#multMatrix(float[], float[])}
- * </p>
* @param a 4x4 matrix, can't be this matrix
* @param b 4x4 matrix, can't be this matrix
* @return this matrix for chaining
@@ -778,21 +804,6 @@ public class Matrix4f {
* @param v_out this * v_in
* @returns v_out for chaining
*/
- public final float[] mulVec4f(final float[/*4*/] v_in, final float[/*4*/] v_out) {
- // (one matrix row in column-major order) X (column vector)
- final float x = v_in[0], y = v_in[1], z = v_in[2], w = v_in[3];
- v_out[0] = x * m00 + y * m01 + z * m02 + w * m03;
- v_out[1] = x * m10 + y * m11 + z * m12 + w * m13;
- v_out[2] = x * m20 + y * m21 + z * m22 + w * m23;
- v_out[3] = x * m30 + y * m31 + z * m32 + w * m33;
- return v_out;
- }
-
- /**
- * @param v_in 4-component column-vector
- * @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();
@@ -807,26 +818,6 @@ public class Matrix4f {
* 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 v_in 3-component column-vector
- * @param v_out m_in * v_in, 3-component column-vector
- * @returns v_out for chaining
- */
- public final float[] mulVec3f(final float[/*3*/] v_in, final float[/*3*/] v_out) {
- // (one matrix row in column-major order) X (column vector)
- final float x = v_in[0], y = v_in[1], z = v_in[2];
- v_out[0] = x * m00 + y * m01 + z * m02 + 1f * m03;
- v_out[1] = x * m10 + y * m11 + z * m12 + 1f * m13;
- v_out[2] = 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_in.w()} and dropping {@code v_out.w()},
* which shall be {@code 1}.
*
@@ -916,6 +907,22 @@ public class Matrix4f {
}
/**
+ * 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):
@@ -936,9 +943,8 @@ public class Matrix4f {
final float ic= 1.0f - c;
final float s = FloatUtil.sin(ang_rad);
- final float[] tmpVec3f = { x, y, z };
- VectorUtil.normalizeVec3(tmpVec3f);
- x = tmpVec3f[0]; y = tmpVec3f[1]; z = tmpVec3f[2];
+ 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;
@@ -1043,6 +1049,31 @@ public class Matrix4f {
}
/**
+ * 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:
@@ -1055,7 +1086,7 @@ public class Matrix4f {
* @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[], int)
+ * @see Quaternion#toMatrix(float[])
* @see #getRotation()
*/
public final Matrix4f setToRotation(final Quaternion q) {
@@ -1255,7 +1286,7 @@ public class Matrix4f {
* @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(float[], int, boolean, Frustum.FovDesc)
+ * @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 !
@@ -1268,11 +1299,14 @@ public class Matrix4f {
/**
* Calculate the frustum planes in world coordinates
- * using the passed float[16] as premultiplied P*MV (column major order).
+ * 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
@@ -1352,7 +1386,7 @@ public class Matrix4f {
}
/**
- * Make given matrix the <i>look-at</i> matrix based on given parameters.
+ * Set this matrix to the <i>look-at</i> matrix based on given parameters.
* <p>
* Consist out of two matrix multiplications:
* <pre>
@@ -1406,6 +1440,50 @@ public class Matrix4f {
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..()
//
@@ -1587,12 +1665,12 @@ public class Matrix4f {
* @param obj object position, 3 component vector
* @param mMv modelview matrix
* @param mP projection matrix
- * @param viewport 4 component viewport vector
+ * @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 int[] viewport, final float[] winPos)
+ final Recti viewport, final Vec3f winPos)
{
final Vec4f vec4Tmp1 = new Vec4f(obj, 1f);
@@ -1613,9 +1691,9 @@ public class Matrix4f {
rawWinPos.scale(s).add(0.5f, 0.5f, 0.5f, 0f);
// Map x,y to viewport
- winPos[0] = rawWinPos.x() * viewport[2] + viewport[0];
- winPos[1] = rawWinPos.y() * viewport[3] + viewport[1];
- winPos[2] = rawWinPos.z();
+ winPos.set( rawWinPos.x() * viewport.width() + viewport.x(),
+ rawWinPos.y() * viewport.height() + viewport.y(),
+ rawWinPos.z() );
return true;
}
@@ -1628,12 +1706,12 @@ public class Matrix4f {
*
* @param obj object position, 3 component vector
* @param mPMv [projection] x [modelview] matrix, i.e. P x Mv
- * @param viewport 4 component viewport vector
+ * @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 int[] viewport, final float[] winPos)
+ final Recti viewport, final Vec3f winPos)
{
final Vec4f vec4Tmp2 = new Vec4f(obj, 1f);
@@ -1650,9 +1728,9 @@ public class Matrix4f {
rawWinPos.scale(s).add(0.5f, 0.5f, 0.5f, 0f);
// Map x,y to viewport
- winPos[0] = rawWinPos.x() * viewport[2] + viewport[0];
- winPos[1] = rawWinPos.y() * viewport[3] + viewport[1];
- winPos[2] = rawWinPos.z();
+ winPos.set( rawWinPos.x() * viewport.width() + viewport.x(),
+ rawWinPos.y() * viewport.height() + viewport.y(),
+ rawWinPos.z() );
return true;
}
@@ -1668,14 +1746,14 @@ public class Matrix4f {
* @param winz
* @param mMv 4x4 modelview matrix
* @param mP 4x4 projection matrix
- * @param viewport 4 component viewport vector
+ * @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 int[] viewport,
+ final Recti viewport,
final Vec3f objPos,
final Matrix4f mat4Tmp)
{
@@ -1688,7 +1766,7 @@ public class Matrix4f {
final Vec4f winPos = new Vec4f(winx, winy, winz, 1f);
// Map x and y from window coordinates
- winPos.add(-viewport[0], -viewport[1], 0f, 0f).scale(1f/viewport[2], 1f/viewport[3], 1f, 1f);
+ 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);
@@ -1714,21 +1792,21 @@ public class Matrix4f {
* @param winy
* @param winz
* @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv)
- * @param viewport 4 component viewport vector
+ * @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 invPMv,
- final int[] viewport,
+ final Recti viewport,
final Vec3f objPos,
final Matrix4f mat4Tmp)
{
final Vec4f winPos = new Vec4f(winx, winy, winz, 1f);
// Map x and y from window coordinates
- winPos.add(-viewport[0], -viewport[1], 0f, 0f).scale(1f/viewport[2], 1f/viewport[3], 1f, 1f);
+ 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);
@@ -1756,21 +1834,21 @@ public class Matrix4f {
* @param winz1
* @param winz2
* @param invPMv inverse [projection] x [modelview] matrix, i.e. Inv(P x Mv)
- * @param viewport 4 component viewport vector
+ * @param viewport Rect4i viewport vector
* @param objPos1 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 winz1, final float winz2,
final Matrix4f invPMv,
- final int[] viewport,
+ final Recti viewport,
final Vec3f objPos1, final Vec3f objPos2,
final Matrix4f mat4Tmp)
{
final Vec4f winPos = new Vec4f(winx, winy, winz1, 1f);
// Map x and y from window coordinates
- winPos.add(-viewport[0], -viewport[1], 0f, 0f).scale(1f/viewport[2], 1f/viewport[3], 1f, 1f);
+ 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);
@@ -1812,7 +1890,7 @@ public class Matrix4f {
* @param clipw
* @param mMv 4x4 modelview matrix
* @param mP 4x4 projection matrix
- * @param viewport 4 component viewport vector
+ * @param viewport Rect4i viewport vector
* @param near
* @param far
* @param obj_pos 4 component object coordinate, the result
@@ -1821,7 +1899,7 @@ public class Matrix4f {
*/
public static boolean mapWinToObj4(final float winx, final float winy, final float winz, final float clipw,
final Matrix4f mMv, final Matrix4f mP,
- final int[] viewport,
+ final Recti viewport,
final float near, final float far,
final Vec4f objPos,
final Matrix4f mat4Tmp)
@@ -1835,7 +1913,7 @@ public class Matrix4f {
final Vec4f winPos = new Vec4f(winx, winy, winz, clipw);
// Map x and y from window coordinates
- winPos.add(-viewport[0], -viewport[1], -near, 0f).scale(1f/viewport[2], 1f/viewport[3], 1f/(far-near), 1f);
+ 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);
@@ -1852,7 +1930,7 @@ public class Matrix4f {
/**
* 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(Ray, float[]) bounding box}.
+ * using a {@link AABBox#getRayIntersection(Vec3f, Ray, float, boolean)}.
* <p>
* Notes for picking <i>winz0</i> and <i>winz1</i>:
* <ul>
@@ -1867,7 +1945,7 @@ public class Matrix4f {
* @param winz1
* @param mMv 4x4 modelview matrix
* @param mP 4x4 projection matrix
- * @param viewport 4 component viewport vector
+ * @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
@@ -1876,7 +1954,7 @@ public class Matrix4f {
public static boolean mapWinToRay(final float winx, final float winy, final float winz0, final float winz1,
final Matrix4f mMv,
final Matrix4f mP,
- final int[] viewport,
+ final Recti viewport,
final Ray ray,
final Matrix4f mat4Tmp1, final Matrix4f mat4Tmp2) {
// invPMv = Inv(P x Mv)