diff options
author | Sven Gothel <[email protected]> | 2014-07-03 09:35:34 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-07-03 09:35:34 +0200 |
commit | d44e8ada30d62149c5d4d4b8fdba7cc33f8c765b (patch) | |
tree | b05fbfb142497d7d62760d8d908236c5f7280fe5 /src/test | |
parent | 36327e24cf586b50bf18e87d7d13d53eb41cf1d9 (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/test')
-rw-r--r-- | src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java | 57 | ||||
-rw-r--r-- | src/test/com/jogamp/opengl/test/junit/jogl/stereo/ovr/OVRDemo01.java | 13 |
2 files changed, 56 insertions, 14 deletions
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); |