aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
-rw-r--r--src/oculusvr/classes/com/jogamp/opengl/oculusvr/OVRSBSRendererDualFBO.java40
-rw-r--r--src/oculusvr/classes/com/jogamp/opengl/oculusvr/OVRSBSRendererSingleFBO.java38
-rw-r--r--src/oculusvr/classes/jogamp/opengl/oculusvr/OVRDistortion.java152
-rw-r--r--src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java9
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java57
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/stereo/ovr/OVRDemo01.java13
13 files changed, 584 insertions, 168 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);
+
+
+}
diff --git a/src/oculusvr/classes/com/jogamp/opengl/oculusvr/OVRSBSRendererDualFBO.java b/src/oculusvr/classes/com/jogamp/opengl/oculusvr/OVRSBSRendererDualFBO.java
index b10a58842..ab53862cd 100644
--- a/src/oculusvr/classes/com/jogamp/opengl/oculusvr/OVRSBSRendererDualFBO.java
+++ b/src/oculusvr/classes/com/jogamp/opengl/oculusvr/OVRSBSRendererDualFBO.java
@@ -31,7 +31,6 @@ import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLEventListener2;
import jogamp.opengl.oculusvr.OVRDistortion;
@@ -40,35 +39,27 @@ import com.jogamp.oculusvr.ovrFrameTiming;
import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.FBObject.TextureAttachment;
import com.jogamp.opengl.FBObject.Attachment.Type;
-import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.util.CustomRendererListener;
+import com.jogamp.opengl.util.stereo.StereoRendererListener;
/**
* OculusVR (OVR) <i>Side By Side</i> Distortion Renderer utilizing {@link OVRDistortion}
* implementing {@link GLEventListener} for convenience.
* <p>
- * Implementation renders an {@link GLEventListener2} instance
+ * Implementation renders an {@link StereoRendererListener} instance
* side-by-side using two {@link FBObject}s according to {@link OVRDistortion}.
* </p>
*/
public class OVRSBSRendererDualFBO implements GLEventListener {
-
- private final float[] mat4Projection = new float[16];
- private final float[] mat4Modelview = new float[16];
private final OVRDistortion dist;
private final boolean ownsDist;
- private final GLEventListener2 upstream;
+ private final StereoRendererListener upstream;
private final FBObject[] fbos;
- // final float[] eyePos = { 0.0f, 1.6f, -5.0f };
- private final float[] eyePos = { 0.0f, 0.0f, -20.0f };
- // EyePos.y = ovrHmd_GetFloat(HMD, OVR_KEY_EYE_HEIGHT, EyePos.y);
- private float eyeYaw = FloatUtil.PI; // 180 degrees in radians
- private float frustumNear = 0.1f;
- private float frustumFar = 7000f;
private int numSamples;
private final TextureAttachment[] fboTexs;
- public OVRSBSRendererDualFBO(final OVRDistortion dist, final boolean ownsDist, final GLEventListener2 upstream, final int numSamples) {
+ public OVRSBSRendererDualFBO(final OVRDistortion dist, final boolean ownsDist, final StereoRendererListener upstream, final int numSamples) {
this.dist = dist;
this.ownsDist = ownsDist;
this.upstream = upstream;
@@ -79,20 +70,6 @@ public class OVRSBSRendererDualFBO implements GLEventListener {
fboTexs = new TextureAttachment[2];
}
- /**
- *
- * @param eyePos
- * @param eyeYaw
- * @param frustumNear
- * @param frustumFar
- */
- public void setUpstreamPMVParams(final float[] eyePos, final float eyeYaw, final float frustumNear, final float frustumFar) {
- System.arraycopy(eyePos, 0, this.eyePos, 0, 3);
- this.eyeYaw = eyeYaw;
- this.frustumNear = frustumNear;
- this.frustumFar = frustumFar;
- }
-
private void initFBOs(final GL gl, final int width, final int height) {
// remove all texture attachments, since MSAA uses just color-render-buffer
// and non-MSAA uses texture2d-buffer
@@ -191,9 +168,10 @@ public class OVRSBSRendererDualFBO implements GLEventListener {
final int[] viewport = eyeDist.viewport;
gl.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
- dist.getSBSUpstreamPMV(eyeNum, eyePos, eyeYaw, frustumNear, frustumFar, mat4Projection, mat4Modelview);
- upstream.setProjectionModelview(drawable, mat4Projection, mat4Modelview);
- upstream.display(drawable, eyeNum > 0 ? GLEventListener2.DISPLAY_REPEAT : 0);
+ dist.updateEyePose(eyeNum);
+ upstream.reshapeEye(drawable, viewport[0], viewport[1], viewport[2], viewport[3],
+ dist.getEyeParam(eyeNum), dist.updateEyePose(eyeNum));
+ upstream.display(drawable, eyeNum > 0 ? CustomRendererListener.DISPLAY_REPEAT : 0);
fbos[eyeNum].unbind(gl);
}
gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
diff --git a/src/oculusvr/classes/com/jogamp/opengl/oculusvr/OVRSBSRendererSingleFBO.java b/src/oculusvr/classes/com/jogamp/opengl/oculusvr/OVRSBSRendererSingleFBO.java
index 22b8b37ce..c9d307665 100644
--- a/src/oculusvr/classes/com/jogamp/opengl/oculusvr/OVRSBSRendererSingleFBO.java
+++ b/src/oculusvr/classes/com/jogamp/opengl/oculusvr/OVRSBSRendererSingleFBO.java
@@ -31,7 +31,6 @@ import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLEventListener2;
import jogamp.opengl.oculusvr.OVRDistortion;
@@ -40,35 +39,28 @@ import com.jogamp.oculusvr.ovrFrameTiming;
import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.FBObject.TextureAttachment;
import com.jogamp.opengl.FBObject.Attachment.Type;
-import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.util.CustomRendererListener;
+import com.jogamp.opengl.util.stereo.StereoRendererListener;
/**
* OculusVR (OVR) <i>Side By Side</i> Distortion Renderer utilizing {@link OVRDistortion}
* implementing {@link GLEventListener} for convenience.
* <p>
- * Implementation renders an {@link GLEventListener2} instance
+ * Implementation renders an {@link StereoRendererListener} instance
* side-by-side within one {@link FBObject} according to {@link OVRDistortion}.
* </p>
*/
public class OVRSBSRendererSingleFBO implements GLEventListener {
- private final float[] mat4Projection = new float[16];
- private final float[] mat4Modelview = new float[16];
private final OVRDistortion dist;
private final boolean ownsDist;
- private final GLEventListener2 upstream;
+ private final StereoRendererListener upstream;
private final FBObject fbo0;
- // final float[] eyePos = { 0.0f, 1.6f, -5.0f };
- private final float[] eyePos = { 0.0f, 0.0f, -20.0f };
- // EyePos.y = ovrHmd_GetFloat(HMD, OVR_KEY_EYE_HEIGHT, EyePos.y);
- private float eyeYaw = FloatUtil.PI; // 180 degrees in radians
- private float frustumNear = 0.1f;
- private float frustumFar = 7000f;
private int numSamples;
private TextureAttachment fbo0Tex;
- public OVRSBSRendererSingleFBO(final OVRDistortion dist, final boolean ownsDist, final GLEventListener2 upstream, final int numSamples) {
+ public OVRSBSRendererSingleFBO(final OVRDistortion dist, final boolean ownsDist, final StereoRendererListener upstream, final int numSamples) {
this.dist = dist;
this.ownsDist = ownsDist;
this.upstream = upstream;
@@ -76,20 +68,6 @@ public class OVRSBSRendererSingleFBO implements GLEventListener {
fbo0 = new FBObject();
}
- /**
- *
- * @param eyePos
- * @param eyeYaw
- * @param frustumNear
- * @param frustumFar
- */
- public void setUpstreamPMVParams(final float[] eyePos, final float eyeYaw, final float frustumNear, final float frustumFar) {
- System.arraycopy(eyePos, 0, this.eyePos, 0, 3);
- this.eyeYaw = eyeYaw;
- this.frustumNear = frustumNear;
- this.frustumFar = frustumFar;
- }
-
private void initFBOs(final GL gl, final int width, final int height) {
// remove all texture attachments, since MSAA uses just color-render-buffer
// and non-MSAA uses texture2d-buffer
@@ -170,9 +148,9 @@ public class OVRSBSRendererSingleFBO implements GLEventListener {
final int[] viewport = eyeDist.viewport;
gl.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
- dist.getSBSUpstreamPMV(eyeNum, eyePos, eyeYaw, frustumNear, frustumFar, mat4Projection, mat4Modelview);
- upstream.setProjectionModelview(drawable, mat4Projection, mat4Modelview);
- upstream.display(drawable, eyeNum > 0 ? GLEventListener2.DISPLAY_REPEAT | GLEventListener2.DISPLAY_DONTCLEAR : 0);
+ upstream.reshapeEye(drawable, viewport[0], viewport[1], viewport[2], viewport[3],
+ dist.getEyeParam(eyeNum), dist.updateEyePose(eyeNum));
+ upstream.display(drawable, eyeNum > 0 ? CustomRendererListener.DISPLAY_REPEAT | CustomRendererListener.DISPLAY_DONTCLEAR : 0);
}
fbo0.unbind(gl);
gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRDistortion.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRDistortion.java
index 590b0e834..7a9def985 100644
--- a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRDistortion.java
+++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRDistortion.java
@@ -33,6 +33,7 @@ import java.nio.ShortBuffer;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLArrayData;
+import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.GLUniformData;
@@ -50,13 +51,17 @@ import com.jogamp.oculusvr.ovrPosef;
import com.jogamp.oculusvr.ovrRecti;
import com.jogamp.oculusvr.ovrSizei;
import com.jogamp.oculusvr.ovrVector2f;
+import com.jogamp.oculusvr.ovrVector3f;
import com.jogamp.opengl.JoglVersion;
import com.jogamp.opengl.math.FloatUtil;
import com.jogamp.opengl.math.Quaternion;
import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.util.CustomRendererListener;
import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.stereo.EyeParameter;
+import com.jogamp.opengl.util.stereo.EyePose;
/**
* OculusVR Distortion Data and OpenGL Renderer Utility
@@ -80,7 +85,6 @@ public class OVRDistortion {
public final int vertexCount;
public final int indexCount;
public final int[/*4*/] viewport;
- public final float[/*3*/] viewAdjust;
public final GLUniformData eyeToSourceUVScale;
public final GLUniformData eyeToSourceUVOffset;
@@ -92,23 +96,23 @@ public class OVRDistortion {
public final GLArrayData vboPos, vboParams, vboTexCoordsR, vboTexCoordsG, vboTexCoordsB;
public final GLArrayDataServer indices;
- public final ovrEyeRenderDesc eyeRenderDesc;
- public final ovrFovPort eyeRenderFov;
+ public final ovrEyeRenderDesc ovrEyeDesc;
+ public final ovrFovPort ovrEyeFov;
+ public final EyeParameter eyeParameter;
- public ovrPosef eyeRenderPose;
- public final Quaternion eyeRenderPoseOrientation;
- public final float[] eyeRenderPosePosition;
+ public ovrPosef ovrEyePose;
+ public EyePose eyePose;
public final boolean useTimewarp() { return OVRDistortion.useTimewarp(distortionCaps); }
public final boolean useChromatic() { return OVRDistortion.useChromatic(distortionCaps); }
public final boolean useVignette() { return OVRDistortion.useVignette(distortionCaps); }
private EyeData(final OvrHmdContext hmdCtx, final int distortionCaps,
- final ovrEyeRenderDesc eyeRenderDesc, final ovrSizei ovrTextureSize, final int[] eyeRenderViewport) {
- this.eyeName = eyeRenderDesc.getEye();
+ final float[] eyePositionOffset, final ovrEyeRenderDesc eyeDesc,
+ final ovrSizei ovrTextureSize, final int[] eyeRenderViewport) {
+ this.eyeName = eyeDesc.getEye();
this.distortionCaps = distortionCaps;
viewport = new int[4];
- viewAdjust = new float[3];
System.arraycopy(eyeRenderViewport, 0, viewport, 0, 4);
final FloatBuffer fstash = Buffers.newDirectFloatBuffer(2+2+16+26);
@@ -124,15 +128,19 @@ public class OVRDistortion {
eyeRotationEnd = null;
}
- this.eyeRenderDesc = eyeRenderDesc;
- this.eyeRenderFov = eyeRenderDesc.getFov();
+ this.ovrEyeDesc = eyeDesc;
+ this.ovrEyeFov = eyeDesc.getFov();
- this.eyeRenderPoseOrientation = new Quaternion();
- this.eyeRenderPosePosition = new float[3];
+ final ovrVector3f eyeViewAdjust = eyeDesc.getViewAdjust();
+ this.eyeParameter = new EyeParameter(eyeName, eyePositionOffset, OVRUtil.getFovHV(ovrEyeFov),
+ eyeViewAdjust.getX(), eyeViewAdjust.getY(), eyeViewAdjust.getZ());
+ this.eyePose = new EyePose(eyeName);
+
+ updateEyePose(hmdCtx);
final ovrDistortionMesh meshData = ovrDistortionMesh.create();
- final ovrFovPort fov = eyeRenderDesc.getFov();
+ final ovrFovPort fov = eyeDesc.getFov();
if( !OVR.ovrHmd_CreateDistortionMesh(hmdCtx, eyeName, fov, distortionCaps, meshData) ) {
throw new OVRException("Failed to create meshData for eye "+eyeName+" and "+OVRUtil.toString(fov));
@@ -156,7 +164,6 @@ public class OVRDistortion {
vboTexCoordsB = null;
}
indices = GLArrayDataServer.createData(1, GL2ES2.GL_SHORT, indexCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER);
- OVRUtil.copyVec3fToFloat(eyeRenderDesc.getViewAdjust(), viewAdjust);
// Setup: eyeToSourceUVScale, eyeToSourceUVOffset
{
@@ -309,24 +316,26 @@ public class OVRDistortion {
}
/**
- * Updates {@link #eyeRenderPose} and it's extracted
+ * Updates {@link #ovrEyePose} and it's extracted
* {@link #eyeRenderPoseOrientation} and {@link #eyeRenderPosePosition}.
- * @param hmdCtx used get the {@link #eyeRenderPose} via {@link OVR#ovrHmd_GetEyePose(OvrHmdContext, int)}
+ * @param hmdCtx used get the {@link #ovrEyePose} via {@link OVR#ovrHmd_GetEyePose(OvrHmdContext, int)}
*/
- public void updateEyePose(final OvrHmdContext hmdCtx) {
- eyeRenderPose = OVR.ovrHmd_GetEyePose(hmdCtx, eyeName);
- OVRUtil.copyToQuaternion(eyeRenderPose.getOrientation(), eyeRenderPoseOrientation);
- OVRUtil.copyVec3fToFloat(eyeRenderPose.getPosition(), eyeRenderPosePosition);
+ public EyePose updateEyePose(final OvrHmdContext hmdCtx) {
+ ovrEyePose = OVR.ovrHmd_GetEyePose(hmdCtx, eyeName);
+ final ovrVector3f pos = ovrEyePose.getPosition();
+ eyePose.setPosition(pos.getX(), pos.getY(), pos.getZ());
+ OVRUtil.copyToQuaternion(ovrEyePose.getOrientation(), eyePose.orientation);
+ return eyePose;
}
@Override
public String toString() {
return "Eye["+eyeName+", viewport "+viewport[0]+"/"+viewport[1]+" "+viewport[2]+"x"+viewport[3]+
- " viewAdjust["+viewAdjust[0]+", "+viewAdjust[1]+", "+viewAdjust[2]+
- "], vertices "+vertexCount+", indices "+indexCount+
+ ", "+eyeParameter+
+ ", vertices "+vertexCount+", indices "+indexCount+
", uvScale["+eyeToSourceUVScale.floatBufferValue().get(0)+", "+eyeToSourceUVScale.floatBufferValue().get(1)+
"], uvOffset["+eyeToSourceUVOffset.floatBufferValue().get(0)+", "+eyeToSourceUVOffset.floatBufferValue().get(1)+
- "], desc"+OVRUtil.toString(eyeRenderDesc)+"]";
+ "], desc"+OVRUtil.toString(ovrEyeDesc)+", "+eyePose+"]";
}
}
@@ -339,9 +348,6 @@ public class OVRDistortion {
private final float[] mat4Tmp1 = new float[16];
private final float[] mat4Tmp2 = new float[16];
- private final float[] vec3Tmp1 = new float[3];
- private final float[] vec3Tmp2 = new float[3];
- private final float[] vec3Tmp3 = new float[3];
private ShaderProgram sp;
@@ -354,7 +360,8 @@ public class OVRDistortion {
}
public static OVRDistortion create(final OvrHmdContext hmdCtx, final boolean sbsSingleTexture,
- final ovrFovPort[] eyeFov, final float pixelsPerDisplayPixel, final int distortionCaps) {
+ final float[] eyePositionOffset, final ovrFovPort[] eyeFov,
+ final float pixelsPerDisplayPixel, final int distortionCaps) {
final ovrEyeRenderDesc[] eyeRenderDesc = new ovrEyeRenderDesc[2];
eyeRenderDesc[0] = OVR.ovrHmd_GetRenderDesc(hmdCtx, OVR.ovrEye_Left, eyeFov[0]);
eyeRenderDesc[1] = OVR.ovrHmd_GetRenderDesc(hmdCtx, OVR.ovrEye_Right, eyeFov[1]);
@@ -400,10 +407,11 @@ public class OVRDistortion {
eyeRenderViewports[1][2] = textureSize[0];
eyeRenderViewports[1][3] = textureSize[1];
}
- return new OVRDistortion(hmdCtx, sbsSingleTexture, eyeRenderDesc, textureSize, eyeRenderViewports, distortionCaps, 0);
+ return new OVRDistortion(hmdCtx, sbsSingleTexture, eyePositionOffset, eyeRenderDesc, textureSize, eyeRenderViewports, distortionCaps, 0);
}
- public OVRDistortion(final OvrHmdContext hmdCtx, final boolean sbsSingleTexture, final ovrEyeRenderDesc[] eyeRenderDescs,
+ public OVRDistortion(final OvrHmdContext hmdCtx, final boolean sbsSingleTexture,
+ final float[] eyePositionOffset, final ovrEyeRenderDesc[] eyeRenderDescs,
final int[] textureSize, final int[][] eyeRenderViewports,
final int distortionCaps, final int textureUnit) {
this.hmdCtx = hmdCtx;
@@ -416,8 +424,8 @@ public class OVRDistortion {
usesDistMesh = true;
final ovrSizei ovrTextureSize = OVRUtil.createOVRSizei(textureSize);
- eyes[0] = new EyeData(hmdCtx, distortionCaps, eyeRenderDescs[0], ovrTextureSize, eyeRenderViewports[0]);
- eyes[1] = new EyeData(hmdCtx, distortionCaps, eyeRenderDescs[1], ovrTextureSize, eyeRenderViewports[1]);
+ eyes[0] = new EyeData(hmdCtx, distortionCaps, eyePositionOffset, eyeRenderDescs[0], ovrTextureSize, eyeRenderViewports[0]);
+ eyes[1] = new EyeData(hmdCtx, distortionCaps, eyePositionOffset, eyeRenderDescs[1], ovrTextureSize, eyeRenderViewports[1]);
sp = null;
}
@@ -440,14 +448,6 @@ public class OVRDistortion {
eyes[eyeNum].enableVBO(gl, enable);
}
- public void updateUniforms(final GL2ES2 gl, final int eyeNum) {
- if( null == sp ) {
- throw new IllegalStateException("Not initialized");
- }
- gl.glUniform(texUnit0);
- eyes[eyeNum].updateUniform(gl, sp);
- }
-
public final ShaderProgram getShaderProgram() { return sp; }
public void init(final GL2ES2 gl) {
@@ -511,6 +511,35 @@ public class OVRDistortion {
sp.destroy(gl);
}
+ public EyeParameter getEyeParam(final int eyeNum) {
+ return eyes[eyeNum].eyeParameter;
+ }
+
+ /**
+ * Updates the {@link EyeData#ovrEyePose} via {@link EyeData#updateEyePose(OvrHmdContext)}
+ * for the denoted eye.
+ */
+ public EyePose updateEyePose(final int eyeNum) {
+ return eyes[eyeNum].updateEyePose(hmdCtx);
+ }
+
+ public void updateUniforms(final GL2ES2 gl, final int eyeNum) {
+ if( null == sp ) {
+ throw new IllegalStateException("Not initialized");
+ }
+ gl.glUniform(texUnit0);
+ eyes[eyeNum].updateUniform(gl, sp);
+ }
+
+ /**
+ * <p>
+ * {@link #updateEyePose(int)} must be called upfront
+ * when rendering upstream {@link GLEventListener}.
+ * </p>
+ *
+ * @param gl
+ * @param timewarpPointSeconds
+ */
public void display(final GL2ES2 gl, final double timewarpPointSeconds) {
if( null == sp ) {
throw new IllegalStateException("Not initialized");
@@ -533,7 +562,7 @@ public class OVRDistortion {
for(int eyeNum=0; eyeNum<2; eyeNum++) {
final EyeData eye = eyes[eyeNum];
if( useTimewarp() ) {
- eye.updateTimewarp(hmdCtx, eye.eyeRenderPose, mat4Tmp1, mat4Tmp2);
+ eye.updateTimewarp(hmdCtx, eye.ovrEyePose, mat4Tmp1, mat4Tmp2);
}
eye.updateUniform(gl, sp);
eye.enableVBO(gl, true);
@@ -548,6 +577,11 @@ public class OVRDistortion {
sp.useProgram(gl, false);
}
+ /**
+ *
+ * @param gl
+ * @param timewarpPointSeconds
+ */
public void displayOneEyePre(final GL2ES2 gl, final double timewarpPointSeconds) {
if( null == sp ) {
throw new IllegalStateException("Not initialized");
@@ -568,13 +602,22 @@ public class OVRDistortion {
gl.glUniform(texUnit0);
}
+ /**
+ * <p>
+ * {@link #updateEyePose(int)} must be called upfront
+ * when rendering upstream {@link GLEventListener}.
+ * </p>
+ *
+ * @param gl
+ * @param eyeNum
+ */
public void displayOneEye(final GL2ES2 gl, final int eyeNum) {
if( null == sp ) {
throw new IllegalStateException("Not initialized");
}
final EyeData eye = eyes[eyeNum];
if( useTimewarp() ) {
- eye.updateTimewarp(hmdCtx, eye.eyeRenderPose, mat4Tmp1, mat4Tmp2);
+ eye.updateTimewarp(hmdCtx, eye.ovrEyePose, mat4Tmp1, mat4Tmp2);
}
eye.updateUniform(gl, sp);
eye.enableVBO(gl, true);
@@ -593,7 +636,12 @@ public class OVRDistortion {
/**
* Calculates the <i>Side By Side</i>, SBS, projection- and modelview matrix for one eye.
* <p>
- * Method also issues {@link EyeData#updateEyePose(OvrHmdContext)}.
+ * {@link #updateEyePose(int)} must be called upfront.
+ * </p>
+ * <p>
+ * This method merely exist as an example implementation to compute the matrices,
+ * which shall be adopted by the
+ * {@link CustomRendererListener#reshape(javax.media.opengl.GLAutoDrawable, int, int, int, int, EyeParameter, EyePose) upstream client code}.
* </p>
* @param eyeNum eye denominator
* @param eyePos float[3] eye postion vector
@@ -602,17 +650,20 @@ public class OVRDistortion {
* @param far frustum far value
* @param mat4Projection float[16] projection matrix result
* @param mat4Modelview float[16] modelview matrix result
+ * @deprecated Only an example implementation, which should be adopted by the {@link CustomRendererListener#reshape(javax.media.opengl.GLAutoDrawable, int, int, int, int, EyeParameter, EyePose) upstream client code}.
*/
public void getSBSUpstreamPMV(final int eyeNum, final float[] eyePos, final float eyeYaw, final float near, final float far,
final float[] mat4Projection, final float[] mat4Modelview) {
final EyeData eyeDist = eyes[eyeNum];
- eyeDist.updateEyePose(hmdCtx);
+ final float[] vec3Tmp1 = new float[3];
+ final float[] vec3Tmp2 = new float[3];
+ final float[] vec3Tmp3 = new float[3];
//
// Projection
//
- final ovrMatrix4f pm = OVR.ovrMatrix4f_Projection(eyeDist.eyeRenderFov, near, far, true /* rightHanded*/);
+ final ovrMatrix4f pm = OVR.ovrMatrix4f_Projection(eyeDist.ovrEyeFov, near, far, true /* rightHanded*/);
/* final float[] mat4Projection = */ FloatUtil.transposeMatrix(pm.getM(0, mat4Tmp1), mat4Projection);
//
@@ -620,19 +671,20 @@ public class OVRDistortion {
//
final Quaternion rollPitchYaw = new Quaternion();
rollPitchYaw.rotateByAngleY(eyeYaw);
- final float[] shiftedEyePos = rollPitchYaw.rotateVector(vec3Tmp1, 0, eyeDist.eyeRenderPosePosition, 0);
+ final float[] shiftedEyePos = rollPitchYaw.rotateVector(vec3Tmp1, 0, eyeDist.eyePose.position, 0);
VectorUtil.addVec3(shiftedEyePos, shiftedEyePos, eyePos);
- rollPitchYaw.mult(eyeDist.eyeRenderPoseOrientation);
+ rollPitchYaw.mult(eyeDist.eyePose.orientation);
final float[] up = rollPitchYaw.rotateVector(vec3Tmp2, 0, VEC3_UP, 0);
final float[] forward = rollPitchYaw.rotateVector(vec3Tmp3, 0, VEC3_FORWARD, 0);
final float[] center = VectorUtil.addVec3(forward, shiftedEyePos, forward);
final float[] mLookAt = FloatUtil.makeLookAt(mat4Tmp2, 0, shiftedEyePos, 0, center, 0, up, 0, mat4Tmp1);
- final float[] mViewAdjust = FloatUtil.makeTranslation(mat4Modelview, true, eyeDist.viewAdjust[0], eyeDist.viewAdjust[1], eyeDist.viewAdjust[2]);
+ final float[] mViewAdjust = FloatUtil.makeTranslation(mat4Modelview, true,
+ eyeDist.eyeParameter.distNoseToPupilX,
+ eyeDist.eyeParameter.distMiddleToPupilY,
+ eyeDist.eyeParameter.eyeReliefZ);
/* mat4Modelview = */ FloatUtil.multMatrix(mViewAdjust, mLookAt);
}
-
-
}
diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java
index e28a50203..6c1cdc015 100644
--- a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java
+++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java
@@ -37,6 +37,7 @@ import com.jogamp.oculusvr.ovrSizei;
import com.jogamp.oculusvr.ovrVector2f;
import com.jogamp.oculusvr.ovrVector2i;
import com.jogamp.oculusvr.ovrVector3f;
+import com.jogamp.opengl.math.FovHVHalves;
import com.jogamp.opengl.math.Quaternion;
/**
@@ -83,6 +84,12 @@ public class OVRUtil {
res[2] = v.getZ();
}
+ public static FovHVHalves getFovHV(final ovrFovPort tanHalfFov) {
+ return new FovHVHalves(tanHalfFov.getLeftTan(), tanHalfFov.getRightTan(),
+ tanHalfFov.getUpTan(), tanHalfFov.getDownTan(),
+ true);
+ }
+
public static String toString(final ovrFovPort fov) {
return "["+fov.getLeftTan()+" l, "+fov.getRightTan()+" r, "+
fov.getUpTan()+" u, "+fov.getDownTan()+" d]";
@@ -100,12 +107,10 @@ public class OVRUtil {
public static String toString(final ovrVector3f v3) {
return "["+v3.getX()+", "+v3.getY()+", "+v3.getZ()+"]";
}
-
public static String toString(final ovrEyeRenderDesc desc) {
return "["+desc.getEye()+", fov"+toString(desc.getFov())+
", viewport"+toString(desc.getDistortedViewport())+
", pptCtr"+toString(desc.getPixelsPerTanAngleAtCenter())+
", view-adjust"+toString(desc.getViewAdjust())+"]";
}
-
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
index 177b573dd..d1a5f888e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
@@ -31,12 +31,19 @@ import com.jogamp.newt.event.MouseListener;
import com.jogamp.newt.event.PinchToZoomGesture;
import com.jogamp.newt.event.GestureHandler.GestureEvent;
import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.Quaternion;
+import com.jogamp.opengl.math.VectorUtil;
import com.jogamp.opengl.test.junit.jogl.demos.GearsObject;
+import com.jogamp.opengl.util.CustomRendererListener;
import com.jogamp.opengl.util.PMVMatrix;
import com.jogamp.opengl.util.TileRendererBase;
import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.glsl.ShaderProgram;
import com.jogamp.opengl.util.glsl.ShaderState;
+import com.jogamp.opengl.util.stereo.EyeParameter;
+import com.jogamp.opengl.util.stereo.EyePose;
+import com.jogamp.opengl.util.stereo.StereoRendererListener;
import java.nio.FloatBuffer;
@@ -45,7 +52,6 @@ import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLEventListener2;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLUniformData;
@@ -53,7 +59,7 @@ import javax.media.opengl.GLUniformData;
* GearsES2.java <BR>
* @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel) <P>
*/
-public class GearsES2 implements GLEventListener2, TileRendererBase.TileRendererListener {
+public class GearsES2 implements StereoRendererListener, TileRendererBase.TileRendererListener {
private final FloatBuffer lightPos = Buffers.newDirectFloatBuffer( new float[] { 5.0f, 5.0f, 10.0f } );
private ShaderState st = null;
@@ -62,6 +68,7 @@ public class GearsES2 implements GLEventListener2, TileRendererBase.TileRenderer
private GLUniformData colorU = null;
private float view_rotx = 20.0f, view_roty = 30.0f;
private boolean flipVerticalInGLOrientation = false;
+ private final boolean customRendering = false;
private final float view_rotz = 0.0f;
private float panX = 0.0f, panY = 0.0f, panZ=0.0f;
@@ -344,6 +351,10 @@ public class GearsES2 implements GLEventListener2, TileRendererBase.TileRenderer
reshapeImpl(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight);
}
+ private final float zNear = 2f;
+ private final float zFar = 10000f;
+ private final float zViewDist = 20.0f;
+
void reshapeImpl(final GL2ES2 gl, final int tileX, final int tileY, final int tileWidth, final int tileHeight, final int imageWidth, final int imageHeight) {
final boolean msaa = gl.getContext().getGLDrawable().getChosenGLCapabilities().getSampleBuffers();
if(verbose) {
@@ -389,21 +400,29 @@ public class GearsES2 implements GLEventListener2, TileRendererBase.TileRenderer
if( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) {
pmvMatrix.glScalef(1f, -1f, 1f);
}
- pmvMatrix.glFrustumf(l, r, b, t, 5.0f, 200.0f);
+ pmvMatrix.glFrustumf(l, r, b, t, zNear, zFar);
pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
pmvMatrix.glLoadIdentity();
- pmvMatrix.glTranslatef(0.0f, 0.0f, -40.0f);
+ pmvMatrix.glTranslatef(0.0f, 0.0f, -zViewDist);
st.useProgram(gl, true);
st.uniform(gl, pmvMatrixUniform);
st.useProgram(gl, false);
}
// private boolean useAndroidDebug = false;
+ private final float[] mat4Tmp1 = new float[16];
+ private final float[] mat4Tmp2 = new float[16];
+ private final float[] vec3Tmp1 = new float[3];
+ private final float[] vec3Tmp2 = new float[3];
+ private final float[] vec3Tmp3 = new float[3];
+
@Override
- public void setProjectionModelview(final GLAutoDrawable drawable, final float[] mat4Projection, final float[] mat4Modelview) {
+ public void reshapeEye(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height,
+ final EyeParameter eyeParam, final EyePose eyePose) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION);
+ final float[] mat4Projection = FloatUtil.makePerspective(mat4Tmp1, 0, true, eyeParam.fovhv, zNear, zFar);
if( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) {
pmvMatrix.glLoadIdentity();
pmvMatrix.glScalef(1f, -1f, 1f);
@@ -411,8 +430,26 @@ public class GearsES2 implements GLEventListener2, TileRendererBase.TileRenderer
} else {
pmvMatrix.glLoadMatrixf(mat4Projection, 0);
}
+
pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW);
+
+ final Quaternion rollPitchYaw = new Quaternion();
+ // private final float eyeYaw = FloatUtil.PI; // 180 degrees in radians
+ // rollPitchYaw.rotateByAngleY(eyeYaw);
+ final float[] shiftedEyePos = rollPitchYaw.rotateVector(vec3Tmp1, 0, eyePose.position, 0);
+ VectorUtil.addVec3(shiftedEyePos, shiftedEyePos, eyeParam.positionOffset);
+
+ rollPitchYaw.mult(eyePose.orientation);
+ final float[] up = rollPitchYaw.rotateVector(vec3Tmp2, 0, VectorUtil.VEC3_UNIT_Y, 0);
+ final float[] forward = rollPitchYaw.rotateVector(vec3Tmp3, 0, VectorUtil.VEC3_UNIT_Z_NEG, 0);
+ final float[] center = VectorUtil.addVec3(forward, shiftedEyePos, forward);
+
+ final float[] mLookAt = FloatUtil.makeLookAt(mat4Tmp1, 0, shiftedEyePos, 0, center, 0, up, 0, mat4Tmp2);
+ final float[] mViewAdjust = FloatUtil.makeTranslation(mat4Tmp2, true, eyeParam.distNoseToPupilX, eyeParam.distMiddleToPupilY, eyeParam.eyeReliefZ);
+ final float[] mat4Modelview = FloatUtil.multMatrix(mViewAdjust, mLookAt);
+
pmvMatrix.glLoadMatrixf(mat4Modelview, 0);
+ pmvMatrix.glTranslatef(0.0f, 0.0f, -zViewDist);
st.useProgram(gl, true);
st.uniform(gl, pmvMatrixUniform);
st.useProgram(gl, false);
@@ -469,8 +506,8 @@ public class GearsES2 implements GLEventListener2, TileRendererBase.TileRenderer
System.err.println(Thread.currentThread()+" GearsES2.display "+sid()+" "+drawable.getSurfaceWidth()+"x"+drawable.getSurfaceHeight()+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(drawable.getHandle()));
}
- final boolean repeatedFrame = 0 != ( GLEventListener2.DISPLAY_REPEAT & flags );
- final boolean dontClear = 0 != ( GLEventListener2.DISPLAY_DONTCLEAR & flags );
+ final boolean repeatedFrame = 0 != ( CustomRendererListener.DISPLAY_REPEAT & flags );
+ final boolean dontClear = 0 != ( CustomRendererListener.DISPLAY_DONTCLEAR & flags );
// Turn the gears' teeth
if( doRotate && !repeatedFrame ) {
@@ -533,15 +570,15 @@ public class GearsES2 implements GLEventListener2, TileRendererBase.TileRenderer
public void setGLStates(final GL2ES2 gl, final boolean enable) {
// Culling only possible if we do not flip the projection matrix
- final boolean enableCullFace = ! ( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() );
+ final boolean useCullFace = ! ( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() || customRendering );
if( enable ) {
gl.glEnable(GL.GL_DEPTH_TEST);
- if( enableCullFace ) {
+ if( useCullFace ) {
gl.glEnable(GL.GL_CULL_FACE);
}
} else {
gl.glDisable(GL.GL_DEPTH_TEST);
- if( enableCullFace ) {
+ if( useCullFace ) {
gl.glDisable(GL.GL_CULL_FACE);
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/stereo/ovr/OVRDemo01.java b/src/test/com/jogamp/opengl/test/junit/jogl/stereo/ovr/OVRDemo01.java
index c20af1389..cb5fa932c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/stereo/ovr/OVRDemo01.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/stereo/ovr/OVRDemo01.java
@@ -133,9 +133,11 @@ public class OVRDemo01 {
System.err.println(OVRVersion.getAvailableCapabilitiesInfo(hmdDesc, ovrHmdIndex, null).toString());
// Start the sensor which provides the Rift’s pose and motion.
- final int requiredSensorCaps = OVR.ovrSensorCap_Orientation;
- final int supportedSensorCaps = requiredSensorCaps | OVR.ovrSensorCap_YawCorrection | OVR.ovrSensorCap_Position;
- OVR.ovrHmd_StartSensor(hmdCtx, supportedSensorCaps, requiredSensorCaps);
+ final int requiredSensorCaps = 0;
+ final int supportedSensorCaps = requiredSensorCaps | OVR.ovrSensorCap_Orientation | OVR.ovrSensorCap_YawCorrection | OVR.ovrSensorCap_Position;
+ if( !OVR.ovrHmd_StartSensor(hmdCtx, supportedSensorCaps, requiredSensorCaps) ) {
+ throw new OVRException("OVR HMD #"+ovrHmdIndex+" required sensors not available");
+ }
//
//
@@ -161,12 +163,15 @@ public class OVRDemo01 {
//
// Oculus Rift setup
//
+ final float[] eyePositionOffset = { 0.0f, 1.6f, -5.0f };
+ // EyePos.y = ovrHmd_GetFloat(HMD, OVR_KEY_EYE_HEIGHT, EyePos.y);
+
final ovrFovPort[] defaultEyeFov = hmdDesc.getDefaultEyeFov(0, new ovrFovPort[2]);
final int distortionCaps = ( useVignette ? OVR.ovrDistortionCap_Vignette : 0 ) |
( useChromatic ? OVR.ovrDistortionCap_Chromatic : 0 ) |
( useTimewarp ? OVR.ovrDistortionCap_TimeWarp : 0 );
final float pixelsPerDisplayPixel = 1f;
- final OVRDistortion dist = OVRDistortion.create(hmdCtx, useSingleFBO, defaultEyeFov, pixelsPerDisplayPixel, distortionCaps);
+ final OVRDistortion dist = OVRDistortion.create(hmdCtx, useSingleFBO, eyePositionOffset, defaultEyeFov, pixelsPerDisplayPixel, distortionCaps);
System.err.println("OVRDistortion: "+dist);
final GearsES2 upstream = new GearsES2(0);