aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-07-03 09:35:34 +0200
committerSven Gothel <[email protected]>2014-07-03 09:35:34 +0200
commitd44e8ada30d62149c5d4d4b8fdba7cc33f8c765b (patch)
treeb05fbfb142497d7d62760d8d908236c5f7280fe5 /src/jogl
parent36327e24cf586b50bf18e87d7d13d53eb41cf1d9 (diff)
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. +++
Diffstat (limited to 'src/jogl')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java98
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java90
-rw-r--r--src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java24
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/CustomRendererListener.java (renamed from src/jogl/classes/javax/media/opengl/GLEventListener2.java)21
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/EyeParameter.java68
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/EyePose.java69
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/stereo/StereoRendererListener.java73
7 files changed, 402 insertions, 41 deletions
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,14 +566,81 @@ 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>
* Consist out of two matrix multiplications:
@@ -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 ) {
diff --git a/src/jogl/classes/javax/media/opengl/GLEventListener2.java b/src/jogl/classes/com/jogamp/opengl/util/CustomRendererListener.java
index d4e8e84a4..0e6de5178 100644
--- a/src/jogl/classes/javax/media/opengl/GLEventListener2.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/CustomRendererListener.java
@@ -25,13 +25,16 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
-package javax.media.opengl;
+package com.jogamp.opengl.util;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
/**
* Extended {@link GLEventListener} interface
* supporting more fine grained control over the implementation.
*/
-public interface GLEventListener2 extends GLEventListener {
+public interface CustomRendererListener extends GLEventListener {
/**
* {@link #display(GLAutoDrawable, int) display flag}: Repeat last produced image.
* <p>
@@ -57,18 +60,4 @@ public interface GLEventListener2 extends GLEventListener {
* @param flags
*/
public void display(final GLAutoDrawable drawable, final int flags);
-
- /**
- * Might be called instead of {@link #reshape(GLAutoDrawable, int, int, int, int) reshape}
- * to specify a custom projection and modelview matrix determined by the caller.
- * <p>
- * Method is usually called by a custom rendering loop,
- * e.g. for manual stereo rendering or the like.
- * </p>
- *
- * @param drawable the triggering {@link GLAutoDrawable}
- * @param mat4Projection float[16] projection matrix
- * @param mat4Modelview float[16] modelview matrix
- */
- public void setProjectionModelview(final GLAutoDrawable drawable, final float[] mat4Projection, final float[] mat4Modelview);
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/EyeParameter.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/EyeParameter.java
new file mode 100644
index 000000000..7774d67e2
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/EyeParameter.java
@@ -0,0 +1,68 @@
+/**
+ * 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.util.stereo;
+
+import com.jogamp.opengl.math.FovHVHalves;
+
+/**
+ * Constant parameter for one eye.
+ */
+public final class EyeParameter {
+ /** Eye number, <code>0</code> for the left eye and <code>1</code> for the right eye. */
+ public final int number;
+
+ /** float[3] eye position vector used to define eye height in meter relative to <i>actor</i>. */
+ public final float[] positionOffset;
+
+ /** Field of view in both directions, may not be centered, either in radians or tangent. */
+ public final FovHVHalves fovhv;
+
+ /** IPD related horizontal distance from nose to pupil in meter. */
+ public final float distNoseToPupilX;
+
+ /** Vertical distance from middle-line to pupil in meter. */
+ public final float distMiddleToPupilY;
+
+ /** Z-axis eye relief in meter. */
+ public final float eyeReliefZ;
+
+ public EyeParameter(final int number, final float[] 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.fovhv = fovhv;
+ this.distNoseToPupilX = distNoseToPupil;
+ this.distMiddleToPupilY = verticalDelta;
+ this.eyeReliefZ = eyeRelief;
+ }
+ public final String toString() {
+ return "EyeParam[num"+number+", posOff["+positionOffset[0]+", "+positionOffset[1]+", "+positionOffset[2]+"], "+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/EyePose.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/EyePose.java
new file mode 100644
index 000000000..2690097f1
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/EyePose.java
@@ -0,0 +1,69 @@
+/**
+ * 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.util.stereo;
+
+import com.jogamp.opengl.math.Quaternion;
+
+/**
+ * Position and orientation of one eye.
+ */
+public final class EyePose {
+ /** Eye number, <code>0</code> for the left eye and <code>1</code> for the right eye. */
+ public final int number;
+
+ /** float[3] eye position vector. */
+ public final float[] position;
+
+ /** Eye orientation */
+ public final Quaternion orientation;
+
+ public EyePose(final int number) {
+ this.number = number;
+ this.position = new float[3];
+ this.orientation = new Quaternion();
+ }
+ public EyePose(final int number, final float[] position, final Quaternion orientation) {
+ this(number);
+ set(position, orientation);
+ }
+
+ /** Set position and orientation of this instance. */
+ public final void set(final float[] position, final Quaternion orientation) {
+ System.arraycopy(position, 0, this.position, 0, 3);
+ this.orientation.set(orientation);
+ }
+ /** Set position and orientation of this instance. */
+ public final void setPosition(final float posX, final float posY, final float posZ) {
+ position[0] = posX;
+ position[1] = posY;
+ position[2] = posZ;
+ }
+ public final String toString() {
+ return "EyePose[num"+number+", pos["+position[0]+", "+position[1]+", "+position[2]+"], "+orientation+"]";
+ }
+} \ No newline at end of file
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoRendererListener.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoRendererListener.java
new file mode 100644
index 000000000..5e6e40a08
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoRendererListener.java
@@ -0,0 +1,73 @@
+/**
+ * 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.util.stereo;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLEventListener;
+
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.util.CustomRendererListener;
+
+/**
+ * Extended {@link GLEventListener} and {@link CustomRendererListener} interface
+ * supporting stereoscopic client rendering.
+ */
+public interface StereoRendererListener extends CustomRendererListener {
+ /**
+ * Stereo capable specialization of {@link #reshape(GLAutoDrawable, int, int, int, int)}.
+ * <p>
+ * Called by the stereo renderer before each {@link #display(GLAutoDrawable)}
+ * or {@link #display(GLAutoDrawable, int)} call.
+ * </p>
+ * <p>
+ * The client can update it's viewport associated data
+ * and view volume of the window appropriately.
+ * </p>
+ * <p>
+ * The client shall also update it's projection- and modelview matrices according
+ * to the given {@link EyeParameter} and {@link EyePose}.
+ * </p>
+ * <p>
+ * For efficiency the GL viewport has already been updated
+ * via <code>glViewport(x, y, width, height)</code> when this method is called.
+ * </p>
+ *
+ * @param drawable the triggering {@link GLAutoDrawable}
+ * @param x viewport x-coord in pixel units
+ * @param y viewport y-coord in pixel units
+ * @param width viewport width in pixel units
+ * @param height viewport height in pixel units
+ * @param eyeParam constant eye parameter, i.e. FOV and IPD
+ * @param eyePose current eye position and orientation
+ * @see FloatUtil#makePerspective(float[], int, boolean, com.jogamp.opengl.math.FloatUtil.FovHVHalves, float, float)
+ */
+ public void reshapeEye(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height,
+ final EyeParameter eyeParam, final EyePose eyePose);
+
+
+}