From 15e60161787224e85172685f74dc0ac195969b51 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 5 Apr 2023 09:42:28 +0200 Subject: Math: Complete Matrix4f w/ Vec[234]f and adopt it throughout Quaternion, Ray, AABBox, Frustum, Stereo*, ... adding hook to PMVMatrix Motivation was to simplify matrix + vector math usage, ease review and avoid usage bugs. Matrix4f implementation uses dedicated float fields instead of an array. Performance didn't increase much, as JVM >= 11(?) has some optimizations to drop the array bounds check. AMD64 + OpenJDK17 - Matrix4f.mul(a, b) got a roughly ~10% enhancement over FloatUtil.multMatrix(a, b, dest) - Matrix4f.mul(b) roughly ~3% slower than FloatUtil.multMatrix(a, b, dest) - FloatUtil.multMatrix(a, a_off, b, b_off, dest) is considerable slower than all - Matrix4f.invert(..) roughly ~3% slower than FloatUtil.invertMatrix(..) RaspberryPi 4b aarch64 + OpenJDK17 - Matrix4f.mul(a, b) got a roughly ~10% enhancement over FloatUtil.multMatrix(a, b, dest) - Matrix4f.mul(b) roughly ~20% slower than FloatUtil.multMatrix(a, b) - FloatUtil.multMatrix(a, a_off, b, b_off, dest) is considerable slower than all - Matrix4f.invert(..) roughly ~4% slower than FloatUtil.invertMatrix(..) Conclusion - Matrix4f.mul(b) needs to be revised (esp for aarch64) - Matrix4f.invert(..) should also not be slower .. --- .../classes/com/jogamp/opengl/util/PMVMatrix.java | 128 ++++++++++++++++++--- .../jogamp/opengl/util/stereo/EyeParameter.java | 17 +-- .../util/stereo/LocationSensorParameter.java | 9 +- .../jogamp/opengl/util/stereo/StereoDevice.java | 15 +-- .../com/jogamp/opengl/util/stereo/StereoUtil.java | 44 ++++--- .../com/jogamp/opengl/util/stereo/ViewerPose.java | 20 ++-- .../stereo/generic/GenericStereoDeviceFactory.java | 7 +- 7 files changed, 173 insertions(+), 67 deletions(-) (limited to 'src/jogl/classes/com/jogamp/opengl/util') diff --git a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java index f8f1d3930..1aa305c2e 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java +++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java @@ -46,6 +46,7 @@ import jogamp.common.os.PlatformPropsImpl; import com.jogamp.common.nio.Buffers; import com.jogamp.common.util.FloatStack; 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.geom.AABBox; @@ -208,9 +209,9 @@ public final class PMVMatrix implements GLMatrixFunc { // Mvit Modelview-Inverse-Transpose matrixArray = new float[5*16]; - mP_offset = 0*16; - mMv_offset = 1*16; - mTex_offset = 4*16; + // mP_offset = 0*16; + // mMv_offset = 1*16; + // mTex_offset = 4*16; matrixPMvMvit = Buffers.slice2Float(matrixArray, 0*16, 4*16); // P + Mv + Mvi + Mvit matrixPMvMvi = Buffers.slice2Float(matrixArray, 0*16, 3*16); // P + Mv + Mvi @@ -241,6 +242,8 @@ public final class PMVMatrix implements GLMatrixFunc { * Issues {@link #glLoadIdentity()} on all matrices, * i.e. {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW}, {@link GLMatrixFunc#GL_PROJECTION GL_PROJECTION} or {@link GL#GL_TEXTURE GL_TEXTURE} * and resets all internal states. + * + * Leaves {@link GLMatrixFunc#GL_MODELVIEW GL_MODELVIEW} the active matrix mode. */ public final void reset() { FloatUtil.makeIdentity(matrixArray, mMv_offset); @@ -403,7 +406,6 @@ public final class PMVMatrix implements GLMatrixFunc { } } - /** * Multiplies the {@link #glGetPMatrixf() P} and {@link #glGetMvMatrixf() Mv} matrix, i.e. *
@@ -432,6 +434,71 @@ public final class PMVMatrix implements GLMatrixFunc {
         return mat4MvP;
     }
 
+    /**
+     * v_out = Mv * v_in
+     * @param v_in float[4] input vector
+     * @param v_out float[4] output vector
+     */
+    public final void multMvMatVec4f(final float[/*4*/] v_in, final float[/*4*/] v_out) {
+        FloatUtil.multMatrixVec(matrixArray, mMv_offset, v_in, v_out);
+    }
+
+    /**
+     * v_out = Mv * v_in
+     *
+     * Affine 3f-vector transformation by 4x4 matrix, see {@link FloatUtil#multMatrixVec3(float[], int, float[], float[])}.
+     *
+     * @param v_in float[3] input vector
+     * @param v_out float[3] output vector
+     */
+    public final void multMvMatVec3f(final float[/*3*/] v_in, final float[/*3*/] v_out) {
+        FloatUtil.multMatrixVec3(matrixArray, mMv_offset, v_in, v_out);
+    }
+
+    /**
+     * v_out = P * v_in
+     * @param v_in float[4] input vector
+     * @param v_out float[4] output vector
+     */
+    public final void multPMatVec4f(final float[/*4*/] v_in, final float[/*4*/] v_out) {
+        FloatUtil.multMatrixVec(matrixArray, v_in, v_out); // mP_offset := 0
+    }
+
+    /**
+     * v_out = P * v_in
+     *
+     * Affine 3f-vector transformation by 4x4 matrix, see {@link FloatUtil#multMatrixVec3(float[], int, float[], float[])}.
+     *
+     * @param v_in float[3] input vector
+     * @param v_out float[3] output vector
+     */
+    public final void multPMatVec3f(final float[/*3*/] v_in, final float[/*3*/] v_out) {
+        FloatUtil.multMatrixVec3(matrixArray, v_in, v_out); // mP_offset := 0
+    }
+
+    /**
+     * v_out = P * Mv * v_in
+     * @param v_in float[4] input vector
+     * @param v_out float[4] output vector
+     */
+    public final void multPMvMatVec4f(final float[/*4*/] v_in, final float[/*4*/] v_out) {
+        FloatUtil.multMatrixVec(matrixArray, mMv_offset, v_in, mat4Tmp1);
+        FloatUtil.multMatrixVec(matrixArray, mat4Tmp1, v_out); // mP_offset := 0
+    }
+
+    /**
+     * v_out = P * Mv * v_in
+     *
+     * Affine 3f-vector transformation by 4x4 matrix, see {@link FloatUtil#multMatrixVec3(float[], int, float[], float[])}.
+     *
+     * @param v_in float[3] input vector
+     * @param v_out float[3] output vector
+     */
+    public final void multPMvMatVec3f(final float[/*3*/] v_in, final float[/*3*/] v_out) {
+        FloatUtil.multMatrixVec3(matrixArray, mMv_offset, v_in, mat4Tmp1);
+        FloatUtil.multMatrixVec3(matrixArray, mat4Tmp1, v_out); // mP_offset := 0
+    }
+
     //
     // GLMatrixFunc implementation
     //
@@ -533,6 +600,24 @@ public final class PMVMatrix implements GLMatrixFunc {
         m.position(spos);
     }
 
+    /**
+     * Load the current matrix with the values of the given {@link Matrix4f}.
+     */
+    public final void glLoadMatrixf(final Matrix4f m) {
+        if(matrixMode==GL_MODELVIEW) {
+            m.get(matrixArray, mMv_offset);
+            dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+            modifiedBits |= MODIFIED_MODELVIEW;
+        } else if(matrixMode==GL_PROJECTION) {
+            m.get(matrixArray, mP_offset);
+            dirtyBits |= DIRTY_FRUSTUM ;
+            modifiedBits |= MODIFIED_PROJECTION;
+        } else if(matrixMode==GL.GL_TEXTURE) {
+            m.get(matrixArray, mTex_offset);
+            modifiedBits |= MODIFIED_TEXTURE;
+        }
+    }
+
     /**
      * Load the current matrix with the values of the given {@link Quaternion}'s rotation {@link Quaternion#toMatrix(float[], int) matrix representation}.
      */
@@ -633,6 +718,21 @@ public final class PMVMatrix implements GLMatrixFunc {
         }
     }
 
+    public final void glMultMatrixf(final Matrix4f m) {
+        if(matrixMode==GL_MODELVIEW) {
+            new Matrix4f(matrixArray, mMv_offset).mul(m).get(matrixArray, mMv_offset);
+            dirtyBits |= DIRTY_INVERSE_MODELVIEW | DIRTY_INVERSE_TRANSPOSED_MODELVIEW | DIRTY_FRUSTUM ;
+            modifiedBits |= MODIFIED_MODELVIEW;
+        } else if(matrixMode==GL_PROJECTION) {
+            new Matrix4f(matrixArray, mP_offset).mul(m).get(matrixArray, mP_offset);
+            dirtyBits |= DIRTY_FRUSTUM ;
+            modifiedBits |= MODIFIED_PROJECTION;
+        } else if(matrixMode==GL.GL_TEXTURE) {
+            new Matrix4f(matrixArray, mTex_offset).mul(m).get(matrixArray, mTex_offset);
+            modifiedBits |= MODIFIED_TEXTURE;
+        }
+    }
+
     @Override
     public final void glTranslatef(final float x, final float y, final float z) {
         glMultMatrixf(FloatUtil.makeTranslation(matrixTxSx, false, x, y, z), 0);
@@ -645,7 +745,7 @@ public final class PMVMatrix implements GLMatrixFunc {
 
     @Override
     public final void glRotatef(final float ang_deg, final float x, final float y, final float z) {
-        glMultMatrixf(FloatUtil.makeRotationAxis(mat4Tmp1, 0, ang_deg * FloatUtil.PI / 180.0f, x, y, z, mat4Tmp2), 0);
+        glMultMatrixf(FloatUtil.makeRotationAxis(mat4Tmp1, 0, FloatUtil.adegToRad(ang_deg), x, y, z, mat4Tmp2), 0);
     }
 
     /**
@@ -728,7 +828,7 @@ public final class PMVMatrix implements GLMatrixFunc {
     public final boolean gluProject(final float objx, final float objy, final float objz,
                                     final int[] viewport, final int viewport_offset,
                                     final float[] win_pos, final int win_pos_offset ) {
-        return FloatUtil.mapObjToWinCoords(objx, objy, objz,
+        return FloatUtil.mapObjToWin(objx, objy, objz,
                           matrixArray, mMv_offset,
                           matrixArray, mP_offset,
                           viewport, viewport_offset,
@@ -754,7 +854,7 @@ public final class PMVMatrix implements GLMatrixFunc {
     public final boolean gluUnProject(final float winx, final float winy, final float winz,
                                       final int[] viewport, final int viewport_offset,
                                       final float[] obj_pos, final int obj_pos_offset) {
-        return FloatUtil.mapWinToObjCoords(winx, winy, winz,
+        return FloatUtil.mapWinToObj(winx, winy, winz,
                                            matrixArray, mMv_offset,
                                            matrixArray, mP_offset,
                                            viewport, viewport_offset,
@@ -788,7 +888,7 @@ public final class PMVMatrix implements GLMatrixFunc {
                                  final int[] viewport, final int viewport_offset,
                                  final float near, final float far,
                                  final float[] obj_pos, final int obj_pos_offset ) {
-        return FloatUtil.mapWinToObjCoords(winx, winy, winz, clipw,
+        return FloatUtil.mapWinToObj4(winx, winy, winz, clipw,
                 matrixArray, mMv_offset,
                 matrixArray, mP_offset,
                 viewport, viewport_offset,
@@ -842,14 +942,12 @@ public final class PMVMatrix implements GLMatrixFunc {
      * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity)
      */
     public final boolean gluUnProjectRay(final float winx, final float winy, final float winz0, final float winz1,
-                                         final int[] viewport, final int viewport_offset,
+                                         final int[] viewport,
                                          final Ray ray) {
         return FloatUtil.mapWinToRay(winx, winy, winz0, winz1,
                 matrixArray, mMv_offset,
-                matrixArray, mP_offset,
-                viewport, viewport_offset,
-                ray,
-                mat4Tmp1, mat4Tmp2, mat4Tmp3);
+                matrixArray, mP_offset, viewport,
+                ray, mat4Tmp1, mat4Tmp2, mat4Tmp3);
     }
 
     public StringBuilder toString(StringBuilder sb, final String f) {
@@ -1066,8 +1164,10 @@ public final class PMVMatrix implements GLMatrixFunc {
         return res;
     }
 
+    private static final int mP_offset   = 0*16;
+    private static final int mMv_offset  = 1*16;
+    private static final int mTex_offset = 4*16;
     private final float[] matrixArray;
-    private final int mP_offset, mMv_offset, mTex_offset;
     private final FloatBuffer matrixPMvMvit, matrixPMvMvi, matrixPMv, matrixP, matrixTex, matrixMv, matrixMvi, matrixMvit;
     private final float[] matrixTxSx;
     private final float[] mat4Tmp1, mat4Tmp2, mat4Tmp3;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/EyeParameter.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/EyeParameter.java
index 43a6cfc58..e0f465da7 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/stereo/EyeParameter.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/EyeParameter.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2014 JogAmp Community. All rights reserved.
+ * 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:
@@ -28,6 +28,7 @@
 package com.jogamp.opengl.util.stereo;
 
 import com.jogamp.opengl.math.FovHVHalves;
+import com.jogamp.opengl.math.Vec3f;
 
 /**
  * Constant single eye parameter of the viewer, relative to its {@link ViewerPose}.
@@ -36,8 +37,8 @@ public final class EyeParameter {
     /** Eye number, 0 for the left eye and 1 for the right eye. */
     public final int number;
 
-    /** float[3] eye position vector used to define eye height in meter relative to actor. */
-    public final float[] positionOffset;
+    /** eye position vector used to define eye height in meter relative to actor. */
+    public final Vec3f positionOffset;
 
     /** Field of view in both directions, may not be centered, either {@link FovHVHalves#inTangents} or radians. */
     public final FovHVHalves fovhv;
@@ -51,18 +52,18 @@ public final class EyeParameter {
     /** Z-axis eye relief in meter. */
     public final float eyeReliefZ;
 
-    public EyeParameter(final int number, final float[] positionOffset, final FovHVHalves fovhv,
+    public EyeParameter(final int number, final Vec3f positionOffset, final FovHVHalves fovhv,
                         final float distNoseToPupil, final float verticalDelta, final float eyeRelief) {
         this.number = number;
-        this.positionOffset = new float[3];
-        System.arraycopy(positionOffset, 0, this.positionOffset, 0, 3);
+        this.positionOffset = new Vec3f(positionOffset);
         this.fovhv = fovhv;
         this.distNoseToPupilX = distNoseToPupil;
         this.distMiddleToPupilY = verticalDelta;
         this.eyeReliefZ = eyeRelief;
     }
+    @Override
     public final String toString() {
-        return "EyeParam[num "+number+", posOff["+positionOffset[0]+", "+positionOffset[1]+", "+positionOffset[2]+"], "+fovhv+
-                      ", distPupil[noseX "+distNoseToPupilX+", middleY "+distMiddleToPupilY+", reliefZ "+eyeReliefZ+"]]";
+        return "EyeParam[num "+number+", posOff["+positionOffset+"], "+fovhv+
+               ", distPupil[noseX "+distNoseToPupilX+", middleY "+distMiddleToPupilY+", reliefZ "+eyeReliefZ+"]]";
     }
 }
\ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/LocationSensorParameter.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/LocationSensorParameter.java
index b795927cd..6294adee1 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/stereo/LocationSensorParameter.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/LocationSensorParameter.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2015 JogAmp Community. All rights reserved.
+ * Copyright 2015-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:
@@ -27,6 +27,7 @@
  */
 package com.jogamp.opengl.util.stereo;
 
+import com.jogamp.opengl.math.Matrix4f;
 import com.jogamp.opengl.math.geom.Frustum;
 
 /**
@@ -38,13 +39,15 @@ public final class LocationSensorParameter {
     /** The {@link Frustum}'s {@link Frustum.FovDesc} description of the location sensor. */
     public final Frustum.FovDesc frustumDesc;
     /** The {@link Frustum}'s float[16] projection matrix of the location sensor. */
-    public final float[] frustumProjMat;
+    public final Matrix4f frustumProjMat;
 
     public LocationSensorParameter(final Frustum.FovDesc fovDesc) {
         this.frustumDesc = fovDesc;
         this.frustum = new Frustum();
-        this.frustumProjMat = frustum.updateByFovDesc(new float[16], 0, true, fovDesc);
+        this.frustumProjMat = frustum.updateByFovDesc(new Matrix4f(), fovDesc);
     }
+
+    @Override
     public final String toString() {
         return "LocationSensor["+frustumDesc+"]";
     }
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDevice.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDevice.java
index b6112650a..85e752302 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDevice.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoDevice.java
@@ -1,5 +1,5 @@
 /**
- * Copyright 2014 JogAmp Community. All rights reserved.
+ * 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:
@@ -33,6 +33,7 @@ import com.jogamp.nativewindow.util.PointImmutable;
 import jogamp.opengl.Debug;
 
 import com.jogamp.opengl.math.FovHVHalves;
+import com.jogamp.opengl.math.Vec3f;
 
 /**
  * Interface describing a native stereoscopic device
@@ -94,7 +95,7 @@ public interface StereoDevice {
     public int getRequiredRotation();
 
     /**
-     * Return the device default eye position offset for {@link #createRenderer(int, int, float[], FovHVHalves[], float)}.
+     * Return the device default eye position offset for {@link #createRenderer(int, int, Vec3f, FovHVHalves[], float)}.
      * 

* Result is an array of float values for *