From d44e8ada30d62149c5d4d4b8fdba7cc33f8c765b Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Thu, 3 Jul 2014 09:35:34 +0200
Subject: Bug 1021: Refine Stereo Rendering API and OculusVR implementing
 renderer

Refine API in regards to proper package names, interface
and high-level access to eye specific constant parameter
and variable eye movement.

+++

Commit 36327e24cf586b50bf18e87d7d13d53eb41cf1d9 introduced 'GLEventListener2'

Move javax.media.opengl.GLEventListener2
  -> com.jogamp.opengl.util.CustomRendererListener
    -> com.jogamp.opengl.util.stereo.StereoRendererListener

StereoRendererListener adds stereoscopic specific:

  public void reshapeEye(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height,
                         final EyeParameter eyeParam, final EyePose eyePose);

.. see below.

++

Add com.jogamp.opengl.util.stereo:
  - EyeParameter (Constant eye parameters, like IPD and FOV)
  - EyePose (Current eye position and orientation)

+++

Add com.jogamp.opengl.math.FovHVHalves to support
non-centered bi-directional FOV for lenses.

Add respective FloatUtil.makePerspective(.. FovHVHalves fovhv ) variant.

+++
---
 .../classes/com/jogamp/opengl/math/FloatUtil.java  | 98 ++++++++++++++++++----
 .../com/jogamp/opengl/math/FovHVHalves.java        | 90 ++++++++++++++++++++
 .../classes/com/jogamp/opengl/math/VectorUtil.java | 24 +++---
 3 files changed, 187 insertions(+), 25 deletions(-)
 create mode 100644 src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java

(limited to 'src/jogl/classes/com/jogamp/opengl/math')

diff --git a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
index f5200443c..eeedf531c 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java
@@ -548,7 +548,8 @@ public final class FloatUtil {
   }
 
   /**
-   * Make given matrix the perspective matrix based on given parameters.
+   * 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>
@@ -556,7 +557,7 @@ public final class FloatUtil {
    * @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 non-zero fields are set.
+   *              otherwise only the frustum fields are set.
    * @param fovy angle in radians
    * @param aspect
    * @param zNear
@@ -565,13 +566,80 @@ public final class FloatUtil {
    */
   public static float[] makePerspective(final float[] m, final int m_off, final boolean initM,
                                         final float fovy, final float aspect, final float zNear, final float zFar) {
-      float top=(float)Math.tan(fovy)*zNear;
-      float bottom=-1.0f*top;
-      float left=aspect*bottom;
-      float right=aspect*top;
+      final float top=(float)Math.tan(fovy)*zNear;
+      final float bottom=-1.0f*top;
+      final float left=aspect*bottom;
+      final float right=aspect*top;
       return makeFrustum(m, m_off, initM, left, right, bottom, top, zNear, zFar);
   }
 
+  /**
+   * 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 fovhv {@link FovHVHalves} field of view in both directions, may not be centered, either in radians or tangent
+   * @param zNear
+   * @param zFar
+   * @return given matrix for chaining
+   */
+  public static float[] makePerspective(final float[] m, final int m_offset, final boolean initM,
+                                        final FovHVHalves fovhv, final float zNear, final float zFar) {
+      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 projScaleX  = 2.0f / ( fovhv.left + fovhv.right  );
+      final float projScaleY  = 2.0f / ( fovhv.top  + fovhv.bottom );
+      final float projOffsetX =       ( fovhv.left - fovhv.right  ) * projScaleX * 0.5f;
+      final float projOffsetY = -1f * ( fovhv.top  - fovhv.bottom ) * projScaleY * 0.5f;
+
+      // Produces X result, mapping clip edges to [-w,+w]
+      m[m_offset+0+4*0] = projScaleX;
+      m[m_offset+0+4*2] = -1f * projOffsetX;
+
+      // Produces Y result, mapping clip edges to [-w,+w] (Y=up)
+      m[m_offset+1+4*1] = projScaleY;
+      m[m_offset+1+4*2] = -1f * projOffsetY;
+
+      // Custom Z-buffer result .. same as frustum matrix!
+      m[m_offset+2+4*2] = -1.0f*(zFar+zNear)/(zFar-zNear);
+      m[m_offset+2+4*3] = -2.0f*(zFar*zNear)/(zFar-zNear);
+      // alternative:
+      // m[m_offset+2+4*2] = -1.0f * zFar / (zNear - zFar);
+      // m[m_offset+2+4*3] = (zFar * zNear) / (zNear - zFar);
+
+      // Produces W result (= Z in)
+      m[m_offset+3+4*2] = -1.0f;
+      m[m_offset+3+4*3] = 0f;
+
+      return m;
+  }
+
   /**
    * Make given matrix the <i>look-at</i> matrix based on given parameters.
    * <p>
@@ -1034,7 +1102,7 @@ public final class FloatUtil {
                                           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, int win_pos_offset,
+                                          final float[] win_pos, final int win_pos_offset,
                                           final float[/*4*/] vec4Tmp1, final float[/*4*/] vec4Tmp2) {
       vec4Tmp1[0] = objx;
       vec4Tmp1[1] = objy;
@@ -1088,7 +1156,7 @@ public final class FloatUtil {
   public static boolean mapObjToWinCoords(final float objx, final float objy, final float objz,
                                           final float[/*16*/] mat4PMv,
                                           final int[] viewport, final int viewport_offset,
-                                          final float[] win_pos, int win_pos_offset,
+                                          final float[] win_pos, final int win_pos_offset,
                                           final float[/*4*/] vec4Tmp1, final float[/*4*/] vec4Tmp2) {
       vec4Tmp2[0] = objx;
       vec4Tmp2[1] = objy;
@@ -1338,11 +1406,11 @@ public final class FloatUtil {
    * @return true if successful, otherwise false (failed to invert matrix, or becomes infinity due to zero z)
    */
   public static boolean mapWinToObjCoords(final float winx, final float winy, final float winz, final float clipw,
-                                          float[] modelMatrix, int modelMatrix_offset,
-                                          float[] projMatrix, int projMatrix_offset,
-                                          int[] viewport, int viewport_offset,
-                                          float near, float far,
-                                          float[] obj_pos, int obj_pos_offset,
+                                          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);
@@ -1445,7 +1513,7 @@ public final class FloatUtil {
    * @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 int a_off, final float[] b, final int b_off, float[] d, final int d_off) {
+  public static float[] 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];
@@ -1509,7 +1577,7 @@ public final class FloatUtil {
    * @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, float[] d) {
+  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];
diff --git a/src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java b/src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java
new file mode 100644
index 000000000..18bba8c45
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java
@@ -0,0 +1,90 @@
+/**
+ * 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. */
+    public final float left;
+    /** Half horizontal FOV from center to right. */
+    public final float right;
+    /** Half vertical FOV from center to top. */
+    public final float top;
+    /** Half vertical FOV from center to bottom. */
+    public final float bottom;
+    /** If true, values are in tangent, otherwise radians.*/
+    public final boolean inTangents;
+
+    /**
+     * Constructor for one {@link FovHVHalves} instance.
+     *
+     * @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 tangents, using:
+     * <pre>
+        final float halfHorizFovTan = (float)Math.tan(horizontalFov/2f);
+        final float halfVertFovTan = (float)Math.tan(verticalFov/2f);
+     * </pre>
+     * @param horizontalFov whole horizontal FOV in radians
+     * @param verticalFov whole vertical FOV in radians
+     */
+    public static FovHVHalves createByRadians(final float horizontalFov, final float verticalFov) {
+        final float halfHorizFovTan = (float)Math.tan(horizontalFov/2f);
+        final float halfVertFovTan = (float)Math.tan(verticalFov/2f);
+        return new FovHVHalves(halfHorizFovTan, halfHorizFovTan, halfVertFovTan, halfVertFovTan, true);
+    }
+
+    /** Returns the full horizontal FOV, i.e. {@link #left} + {@link #right}. */
+    public final float horzFov() { return left+right; }
+
+    /** Returns the full vertical FOV, i.e. {@link #top} + {@link #bottom}. */
+    public final float vertFov() { return top+bottom; }
+
+    public final String toString() {
+        return "FovHVHalves["+(inTangents?"tangents":"radians")+": "+left+" l, "+right+" r, "+top+" t, "+bottom+" b]";
+    }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
index 607d8ef9d..c11c2bd2b 100644
--- a/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java
@@ -33,13 +33,17 @@ public final class VectorUtil {
 
     public static final float[] VEC3_ONE = { 1f, 1f, 1f };
     public static final float[] VEC3_ZERO = { 0f, 0f, 0f };
+    public static final float[] VEC3_UNIT_Y = { 0f, 1f, 0f };
+    public static final float[] VEC3_UNIT_Y_NEG = { 0f, -1f, 0f };
+    public static final float[] VEC3_UNIT_Z = { 0f, 0f, 1f };
+    public static final float[] VEC3_UNIT_Z_NEG = { 0f, 0f, -1f };
 
     public enum Winding {
         CW(-1), CCW(1);
 
         public final int dir;
 
-        Winding(int dir) {
+        Winding(final int dir) {
             this.dir = dir;
         }
     }
@@ -52,7 +56,7 @@ public final class VectorUtil {
      * @param srcOffset offset of src in array
      * @return copied output vector for chaining
      */
-    public static float[] copyVec2(final float[] dst, int dstOffset, final float[] src, int srcOffset)
+    public static float[] copyVec2(final float[] dst, final int dstOffset, final float[] src, final int srcOffset)
     {
         System.arraycopy(src, srcOffset, dst, dstOffset, 2);
         return dst;
@@ -66,7 +70,7 @@ public final class VectorUtil {
      * @param srcOffset offset of src in array
      * @return copied output vector for chaining
      */
-    public static float[] copyVec3(final float[] dst, int dstOffset, final float[] src, int srcOffset)
+    public static float[] copyVec3(final float[] dst, final int dstOffset, final float[] src, final int srcOffset)
     {
         System.arraycopy(src, srcOffset, dst, dstOffset, 3);
         return dst;
@@ -80,7 +84,7 @@ public final class VectorUtil {
      * @param srcOffset offset of src in array
      * @return copied output vector for chaining
      */
-    public static float[] copyVec4(final float[] dst, int dstOffset, final float[] src, int srcOffset)
+    public static float[] copyVec4(final float[] dst, final int dstOffset, final float[] src, final int srcOffset)
     {
         System.arraycopy(src, srcOffset, dst, dstOffset, 4);
         return dst;
@@ -92,7 +96,7 @@ public final class VectorUtil {
      * Implementation uses {@link FloatUtil#isEqual(float, float)}, see API doc for details.
      * </p>
      */
-    public static boolean isVec2Equal(final float[] vec1, int vec1Offset, final float[] vec2, int vec2Offset) {
+    public static boolean isVec2Equal(final float[] vec1, final int vec1Offset, final float[] vec2, final int vec2Offset) {
         return FloatUtil.isEqual(vec1[0+vec1Offset], vec2[0+vec2Offset]) &&
                FloatUtil.isEqual(vec1[1+vec1Offset], vec2[1+vec2Offset]) ;
     }
@@ -103,7 +107,7 @@ public final class VectorUtil {
      * Implementation uses {@link FloatUtil#isEqual(float, float)}, see API doc for details.
      * </p>
      */
-    public static boolean isVec3Equal(final float[] vec1, int vec1Offset, final float[] vec2, int vec2Offset) {
+    public static boolean isVec3Equal(final float[] vec1, final int vec1Offset, final float[] vec2, final int vec2Offset) {
         return FloatUtil.isEqual(vec1[0+vec1Offset], vec2[0+vec2Offset]) &&
                FloatUtil.isEqual(vec1[1+vec1Offset], vec2[1+vec2Offset]) &&
                FloatUtil.isEqual(vec1[2+vec1Offset], vec2[2+vec2Offset]) ;
@@ -115,7 +119,7 @@ public final class VectorUtil {
      * Implementation uses {@link FloatUtil#isEqual(float, float, float)}, see API doc for details.
      * </p>
      */
-    public static boolean isVec2Equal(final float[] vec1, int vec1Offset, final float[] vec2, int vec2Offset, final float epsilon) {
+    public static boolean isVec2Equal(final float[] vec1, final int vec1Offset, final float[] vec2, final int vec2Offset, final float epsilon) {
         return FloatUtil.isEqual(vec1[0+vec1Offset], vec2[0+vec2Offset], epsilon) &&
                FloatUtil.isEqual(vec1[1+vec1Offset], vec2[1+vec2Offset], epsilon) ;
     }
@@ -126,7 +130,7 @@ public final class VectorUtil {
      * Implementation uses {@link FloatUtil#isEqual(float, float, float)}, see API doc for details.
      * </p>
      */
-    public static boolean isVec3Equal(final float[] vec1, int vec1Offset, final float[] vec2, int vec2Offset, final float epsilon) {
+    public static boolean isVec3Equal(final float[] vec1, final int vec1Offset, final float[] vec2, final int vec2Offset, final float epsilon) {
         return FloatUtil.isEqual(vec1[0+vec1Offset], vec2[0+vec2Offset], epsilon) &&
                FloatUtil.isEqual(vec1[1+vec1Offset], vec2[1+vec2Offset], epsilon) &&
                FloatUtil.isEqual(vec1[2+vec1Offset], vec2[2+vec2Offset], epsilon) ;
@@ -250,7 +254,7 @@ public final class VectorUtil {
      */
     public static float normSquareVec2(final float[] vec, final int offset) {
         float v = vec[0+offset];
-        float r = v*v;
+        final float r = v*v;
         v = vec[1+offset];
         return r + v*v;
     }
@@ -956,7 +960,7 @@ public final class VectorUtil {
      * @param epsilon
      * @return resulting intersecting if exists, otherwise null
      */
-    public static float[] line2PlaneIntersection(final float[] result, final Ray ray, float[/*4*/] plane, final float epsilon) {
+    public static float[] line2PlaneIntersection(final float[] result, final Ray ray, final float[/*4*/] plane, final float epsilon) {
         final float tmp = dotVec3(ray.dir, plane) ;
 
         if ( Math.abs(tmp) < epsilon ) {
-- 
cgit v1.2.3