diff options
author | Sven Gothel <[email protected]> | 2014-07-07 23:46:19 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-07-07 23:46:19 +0200 |
commit | 38e51e4a5f6f35c658df10f6d48a33e3ffaea2f3 (patch) | |
tree | 259024b16429986ab48fd49a9bd2667dad2b85eb /src/oculusvr | |
parent | 06fc570f70dc5ccfad7399d8426bdf224c239a5a (diff) |
Bug 1021: Add GenericStereoDevice* Supporting custom configurations; Hook-in oculusvr-sdk java distortion-mesh calculation if available
StereoDeviceFactory support new GenericStereoDeviceFactory, with it's GenericStereoDevice and GenericStereoDeviceRenderer.
GenericStereoDevice maintains different configurations, triggered either by passing a GenericStereoDevice.Config
instance directly or by the device-index parameter:
- 0: monoscopi device: No post-processing
- 1: stereoscopic device SBS: No post-processing
- 2: stereoscopic device SBS + Lenses: Distortion post-processing
(only available w/ oculusvr-sdk sub-module)
Producing a 'GenericStereoDevice.Config' instance is self containing
and may extend if supporting more device types like top-bottom, interlaced etc.
StereoDemo01 handles all use-cases and may be used as a test-bed
to add and experiment with stereoscopy, devices and settings.
Diffstat (limited to 'src/oculusvr')
4 files changed, 152 insertions, 68 deletions
diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDevice.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDevice.java index 09a348c46..2832012e4 100644 --- a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDevice.java +++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDevice.java @@ -42,19 +42,50 @@ import com.jogamp.oculusvr.ovrSizei; import com.jogamp.opengl.math.FovHVHalves; import com.jogamp.opengl.util.stereo.StereoDevice; import com.jogamp.opengl.util.stereo.StereoDeviceRenderer; +import com.jogamp.opengl.util.stereo.StereoUtil; public class OVRStereoDevice implements StereoDevice { + /** 1.6 up, 5 forward */ + private static final float[] DEFAULT_EYE_POSITION_OFFSET = { 0.0f, 1.6f, -5.0f }; + public final OvrHmdContext handle; public final int deviceIndex; public final ovrHmdDesc hmdDesc; + private final FovHVHalves[] defaultEyeFov; private boolean sensorsStarted = false; + private final int[] eyeRenderOrder; + private final int supportedDistortionBits, recommendedDistortionBits, minimumDistortionBits; public OVRStereoDevice(final OvrHmdContext nativeContext, final int deviceIndex) { this.handle = nativeContext; this.deviceIndex = deviceIndex; this.hmdDesc = ovrHmdDesc.create(); OVR.ovrHmd_GetDesc(handle, hmdDesc); + final ovrFovPort[] defaultOVREyeFov = hmdDesc.getDefaultEyeFov(0, new ovrFovPort[hmdDesc.getEyeRenderOrderArrayLength()]); + defaultEyeFov = new FovHVHalves[defaultOVREyeFov.length]; + for(int i=0; i<defaultEyeFov.length; i++) { + defaultEyeFov[i] = OVRUtil.getFovHV(defaultOVREyeFov[i]); + } + eyeRenderOrder = new int[hmdDesc.getEyeRenderOrderArrayLength()]; + hmdDesc.getEyeRenderOrder(0, eyeRenderOrder); + supportedDistortionBits = OVRUtil.ovrDistCaps2DistBits(hmdDesc.getDistortionCaps()); + recommendedDistortionBits = supportedDistortionBits & ~StereoDeviceRenderer.DISTORTION_TIMEWARP; + minimumDistortionBits = StereoDeviceRenderer.DISTORTION_BARREL; + } + + @Override + public final String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("OVRStereoDevice[product "+hmdDesc.getProductNameAsString()); + sb.append(", vendor "+hmdDesc.getManufacturerAsString()); + sb.append(", device "+hmdDesc.getDisplayDeviceNameAsString()); + sb.append(", surfaceSize "+getSurfaceSize()); + sb.append(", surfacePos "+getPosition()); + sb.append(", distortionBits[supported ["+StereoUtil.distortionBitsToString(getSupportedDistortionBits())+ + "], recommended ["+StereoUtil.distortionBitsToString(getRecommendedDistortionBits())+ + "], minimum ["+StereoUtil.distortionBitsToString(getMinimumDistortionBits())+"]]]"); + return sb.toString(); } @Override @@ -73,12 +104,13 @@ public class OVRStereoDevice implements StereoDevice { } @Override + public float[] getDefaultEyePositionOffset() { + return DEFAULT_EYE_POSITION_OFFSET; + } + + @Override public final FovHVHalves[] getDefaultFOV() { - final ovrFovPort[] defaultEyeFov = hmdDesc.getDefaultEyeFov(0, new ovrFovPort[2]); - final FovHVHalves[] eyeFov = new FovHVHalves[2]; - eyeFov[0] = OVRUtil.getFovHV(defaultEyeFov[0]); - eyeFov[1] = OVRUtil.getFovHV(defaultEyeFov[1]); - return eyeFov; + return defaultEyeFov; } @Override @@ -104,7 +136,27 @@ public class OVRStereoDevice implements StereoDevice { } } @Override - public boolean getSensorsStarted() { return sensorsStarted; } + public final boolean getSensorsStarted() { return sensorsStarted; } + + @Override + public final int[] getEyeRenderOrder() { + return eyeRenderOrder; + } + + @Override + public final int getSupportedDistortionBits() { + return supportedDistortionBits; + }; + + @Override + public final int getRecommendedDistortionBits() { + return recommendedDistortionBits; + } + + @Override + public final int getMinimumDistortionBits() { + return minimumDistortionBits; + } @Override public final StereoDeviceRenderer createRenderer(final int distortionBits, diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceFactory.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceFactory.java index 06454e443..ebd3699e1 100644 --- a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceFactory.java +++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceFactory.java @@ -31,6 +31,7 @@ import com.jogamp.oculusvr.OVR; import com.jogamp.oculusvr.OVRVersion; import com.jogamp.oculusvr.OvrHmdContext; import com.jogamp.opengl.util.stereo.StereoDevice; +import com.jogamp.opengl.util.stereo.StereoDevice.Config; import com.jogamp.opengl.util.stereo.StereoDeviceFactory; public class OVRStereoDeviceFactory extends StereoDeviceFactory { @@ -40,7 +41,7 @@ public class OVRStereoDeviceFactory extends StereoDeviceFactory { } @Override - public final StereoDevice createDevice(final int deviceIndex, final boolean verbose) { + public final StereoDevice createDevice(final int deviceIndex, Config config, final boolean verbose) { final OvrHmdContext hmdCtx = OVR.ovrHmd_Create(deviceIndex); final OVRStereoDevice ctx = new OVRStereoDevice(hmdCtx, deviceIndex); if( verbose ) { diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceRenderer.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceRenderer.java index 012ad183d..39736217c 100644 --- a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceRenderer.java +++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceRenderer.java @@ -67,7 +67,7 @@ import com.jogamp.opengl.util.stereo.StereoDeviceRenderer; import com.jogamp.opengl.util.stereo.StereoUtil; /** - * OculusVR Distortion Data and OpenGL Renderer Utility + * OculusVR Stereo Device Distortion and OpenGL Renderer Utility */ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { private static final String shaderPrefix01 = "dist01"; @@ -140,12 +140,34 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { updateEyePose(hmdCtx); // 1st init + // Setup: eyeToSourceUVScale, eyeToSourceUVOffset + { + final ovrVector2f[] uvScaleOffsetOut = new ovrVector2f[2]; + uvScaleOffsetOut[0] = ovrVector2f.create(); // FIXME: remove ctor / double check + uvScaleOffsetOut[1] = ovrVector2f.create(); + + final ovrRecti ovrEyeRenderViewport = OVRUtil.createOVRRecti(eyeViewport); + OVR.ovrHmd_GetRenderScaleAndOffset(ovrEyeFov, ovrTextureSize, ovrEyeRenderViewport, uvScaleOffsetOut); + if( StereoDevice.DEBUG ) { + System.err.println("XXX."+eyeName+": eyeParam "+eyeParameter); + System.err.println("XXX."+eyeName+": uvScale "+OVRUtil.toString(uvScaleOffsetOut[0])); + System.err.println("XXX."+eyeName+": uvOffset "+OVRUtil.toString(uvScaleOffsetOut[1])); + System.err.println("XXX."+eyeName+": textureSize "+OVRUtil.toString(ovrTextureSize)); + System.err.println("XXX."+eyeName+": viewport "+OVRUtil.toString(ovrEyeRenderViewport)); + } + final FloatBuffer eyeToSourceUVScaleFB = eyeToSourceUVScale.floatBufferValue(); + eyeToSourceUVScaleFB.put(0, uvScaleOffsetOut[0].getX()); + eyeToSourceUVScaleFB.put(1, uvScaleOffsetOut[0].getY()); + final FloatBuffer eyeToSourceUVOffsetFB = eyeToSourceUVOffset.floatBufferValue(); + eyeToSourceUVOffsetFB.put(0, uvScaleOffsetOut[1].getX()); + eyeToSourceUVOffsetFB.put(1, uvScaleOffsetOut[1].getY()); + } + final ovrDistortionMesh meshData = ovrDistortionMesh.create(); - final ovrFovPort fov = eyeDesc.getFov(); final int ovrDistortionCaps = distBits2OVRDistCaps(distortionBits); - if( !OVR.ovrHmd_CreateDistortionMesh(hmdCtx, eyeName, fov, ovrDistortionCaps, meshData) ) { - throw new OVRException("Failed to create meshData for eye "+eyeName+", "+OVRUtil.toString(fov)+" and "+StereoUtil.distortionBitsToString(distortionBits)); + if( !OVR.ovrHmd_CreateDistortionMesh(hmdCtx, eyeName, ovrEyeFov, ovrDistortionCaps, meshData) ) { + throw new OVRException("Failed to create meshData for eye "+eyeName+", "+OVRUtil.toString(ovrEyeFov)+" and "+StereoUtil.distortionBitsToString(distortionBits)); } vertexCount = meshData.getVertexCount(); indexCount = meshData.getIndexCount(); @@ -168,29 +190,6 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { } indices = GLArrayDataServer.createData(1, GL.GL_SHORT, indexCount, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER); - // Setup: eyeToSourceUVScale, eyeToSourceUVOffset - { - final ovrVector2f[] uvScaleOffsetOut = new ovrVector2f[2]; - uvScaleOffsetOut[0] = ovrVector2f.create(); // FIXME: remove ctor / double check - uvScaleOffsetOut[1] = ovrVector2f.create(); - - final ovrRecti ovrEyeRenderViewport = OVRUtil.createOVRRecti(eyeViewport); - OVR.ovrHmd_GetRenderScaleAndOffset(fov, ovrTextureSize, ovrEyeRenderViewport, uvScaleOffsetOut); - if( StereoDevice.DEBUG ) { - System.err.println("XXX."+eyeName+": fov "+OVRUtil.toString(fov)); - System.err.println("XXX."+eyeName+": uvScale "+OVRUtil.toString(uvScaleOffsetOut[0])); - System.err.println("XXX."+eyeName+": uvOffset "+OVRUtil.toString(uvScaleOffsetOut[1])); - System.err.println("XXX."+eyeName+": textureSize "+OVRUtil.toString(ovrTextureSize)); - System.err.println("XXX."+eyeName+": viewport "+OVRUtil.toString(ovrEyeRenderViewport)); - } - final FloatBuffer eyeToSourceUVScaleFB = eyeToSourceUVScale.floatBufferValue(); - eyeToSourceUVScaleFB.put(0, uvScaleOffsetOut[0].getX()); - eyeToSourceUVScaleFB.put(1, uvScaleOffsetOut[0].getY()); - final FloatBuffer eyeToSourceUVOffsetFB = eyeToSourceUVOffset.floatBufferValue(); - eyeToSourceUVOffsetFB.put(0, uvScaleOffsetOut[1].getX()); - eyeToSourceUVOffsetFB.put(1, uvScaleOffsetOut[1].getY()); - } - /** 2+2+2+2+2: { vec2 position, vec2 color, vec2 texCoordR, vec2 texCoordG, vec2 texCoordB } */ final FloatBuffer iVBOFB = (FloatBuffer)iVBO.getBuffer(); final ovrDistortionVertex[] ovRes = new ovrDistortionVertex[1]; @@ -200,46 +199,76 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { final ovrDistortionVertex ov = meshData.getPVertexData(vertNum, ovRes)[0]; ovrVector2f v; + if( StereoDevice.DUMP_DATA ) { + System.err.println("XXX."+eyeName+": START VERTEX "+vertNum+" / "+vertexCount); + } // pos v = ov.getPos(); + if( StereoDevice.DUMP_DATA ) { + System.err.println("XXX."+eyeName+": pos "+OVRUtil.toString(v)); + } iVBOFB.put(v.getX()); iVBOFB.put(v.getY()); // params if( useVignette ) { + if( StereoDevice.DUMP_DATA ) { + System.err.println("XXX."+eyeName+": vignette "+ov.getVignetteFactor()); + } iVBOFB.put(ov.getVignetteFactor()); } else { iVBOFB.put(1.0f); } + if( StereoDevice.DUMP_DATA ) { + System.err.println("XXX."+eyeName+": timewarp "+ov.getTimeWarpFactor()); + } iVBOFB.put(ov.getTimeWarpFactor()); // texCoordR v = ov.getTexR(); + if( StereoDevice.DUMP_DATA ) { + System.err.println("XXX."+eyeName+": texR "+OVRUtil.toString(v)); + } iVBOFB.put(v.getX()); iVBOFB.put(v.getY()); if( useChromatic ) { // texCoordG v = ov.getTexG(); + if( StereoDevice.DUMP_DATA ) { + System.err.println("XXX."+eyeName+": texG "+OVRUtil.toString(v)); + } iVBOFB.put(v.getX()); iVBOFB.put(v.getY()); // texCoordB v = ov.getTexB(); + if( StereoDevice.DUMP_DATA ) { + System.err.println("XXX."+eyeName+": texB "+OVRUtil.toString(v)); + } iVBOFB.put(v.getX()); iVBOFB.put(v.getY()); } } - if( StereoDevice.DEBUG ) { + if( StereoDevice.DUMP_DATA ) { System.err.println("XXX."+eyeName+": iVBO "+iVBO); } { final ShortBuffer in = meshData.getPIndexData(); + if( StereoDevice.DUMP_DATA ) { + System.err.println("XXX."+eyeName+": idx "+indices+", count "+indexCount); + for(int i=0; i< indexCount; i++) { + if( 0 == i % 16 ) { + System.err.printf("%n%5d: ", i); + } + System.err.printf("%5d, ", (int)in.get(i)); + } + System.err.println(); + } final ShortBuffer out = (ShortBuffer) indices.getBuffer(); out.put(in); } if( StereoDevice.DEBUG ) { - System.err.println("XXX."+eyeName+": idx "+indices); System.err.println("XXX."+eyeName+": "+this); } OVR.ovrHmd_DestroyDistortionMesh(meshData); @@ -247,34 +276,34 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { private void linkData(final GL2ES2 gl, final ShaderProgram sp) { if( 0 > vboPos.setLocation(gl, sp.program()) ) { - throw new OVRException("Couldn't locate "+vboPos); + throw new GLException("Couldn't locate "+vboPos); } if( 0 > vboParams.setLocation(gl, sp.program()) ) { - throw new OVRException("Couldn't locate "+vboParams); + throw new GLException("Couldn't locate "+vboParams); } if( 0 > vboTexCoordsR.setLocation(gl, sp.program()) ) { - throw new OVRException("Couldn't locate "+vboTexCoordsR); + throw new GLException("Couldn't locate "+vboTexCoordsR); } if( StereoUtil.usesChromaticDistortion(distortionBits) ) { if( 0 > vboTexCoordsG.setLocation(gl, sp.program()) ) { - throw new OVRException("Couldn't locate "+vboTexCoordsG); + throw new GLException("Couldn't locate "+vboTexCoordsG); } if( 0 > vboTexCoordsB.setLocation(gl, sp.program()) ) { - throw new OVRException("Couldn't locate "+vboTexCoordsB); + throw new GLException("Couldn't locate "+vboTexCoordsB); } } if( 0 > eyeToSourceUVScale.setLocation(gl, sp.program()) ) { - throw new OVRException("Couldn't locate "+eyeToSourceUVScale); + throw new GLException("Couldn't locate "+eyeToSourceUVScale); } if( 0 > eyeToSourceUVOffset.setLocation(gl, sp.program()) ) { - throw new OVRException("Couldn't locate "+eyeToSourceUVOffset); + throw new GLException("Couldn't locate "+eyeToSourceUVOffset); } if( StereoUtil.usesTimewarpDistortion(distortionBits) ) { if( 0 > eyeRotationStart.setLocation(gl, sp.program()) ) { - throw new OVRException("Couldn't locate "+eyeRotationStart); + throw new GLException("Couldn't locate "+eyeRotationStart); } if( 0 > eyeRotationEnd.setLocation(gl, sp.program()) ) { - throw new OVRException("Couldn't locate "+eyeRotationEnd); + throw new GLException("Couldn't locate "+eyeRotationEnd); } } iVBO.seal(gl, true); @@ -368,17 +397,17 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { private static int distBits2OVRDistCaps(final int distortionBits) { - int bits = 0; + int caps = 0; if( StereoUtil.usesTimewarpDistortion(distortionBits) ) { - bits |= OVR.ovrDistortionCap_TimeWarp; + caps |= OVR.ovrDistortionCap_TimeWarp; } if( StereoUtil.usesChromaticDistortion(distortionBits) ) { - bits |= OVR.ovrDistortionCap_Chromatic; + caps |= OVR.ovrDistortionCap_Chromatic; } if( StereoUtil.usesVignetteDistortion(distortionBits) ) { - bits |= OVR.ovrDistortionCap_Vignette; + caps |= OVR.ovrDistortionCap_Vignette; } - return bits; + return caps; } /* pp */ OVRStereoDeviceRenderer(final OVRStereoDevice context, final int distortionBits, @@ -390,7 +419,7 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { } this.context = context; this.eyes = new OVREye[2]; - this.distortionBits = distortionBits | StereoDeviceRenderer.DISTORTION_BARREL /* always */; + this.distortionBits = ( distortionBits | context.getMinimumDistortionBits() ) & context.getSupportedDistortionBits(); this.textureCount = textureCount; this.singleTextureSize = singleTextureSize; this.totalTextureSize = totalTextureSize; @@ -428,7 +457,7 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { public final int getTextureUnit() { return texUnit0.intValue(); } @Override - public final boolean ppRequired() { return true; } + public final boolean ppAvailable() { return 0 != distortionBits; } @Override public final void init(final GL gl) { @@ -555,21 +584,6 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { } @Override - public final void ppBothEyes(final GL gl) { - final GL2ES2 gl2es2 = gl.getGL2ES2(); - for(int eyeNum=0; eyeNum<2; eyeNum++) { - final OVREye eye = eyes[eyeNum]; - if( StereoUtil.usesTimewarpDistortion(distortionBits) ) { - eye.updateTimewarp(context.handle, eye.ovrEyePose, mat4Tmp1, mat4Tmp2); - } - eye.updateUniform(gl2es2, sp); - eye.enableVBO(gl2es2, true); - gl2es2.glDrawElements(GL.GL_TRIANGLES, eye.indexCount, GL.GL_UNSIGNED_SHORT, 0); - eyes[eyeNum].enableVBO(gl2es2, false); - } - } - - @Override public final void ppOneEye(final GL gl, final int eyeNum) { final OVREye eye = eyes[eyeNum]; if( StereoUtil.usesTimewarpDistortion(distortionBits) ) { diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java index 48222ea97..44ec728fc 100644 --- a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java +++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java @@ -33,6 +33,7 @@ import javax.media.nativewindow.util.Point; import javax.media.nativewindow.util.PointImmutable; import javax.media.nativewindow.util.RectangleImmutable; +import com.jogamp.oculusvr.OVR; import com.jogamp.oculusvr.ovrEyeRenderDesc; import com.jogamp.oculusvr.ovrFovPort; import com.jogamp.oculusvr.ovrQuatf; @@ -43,6 +44,7 @@ import com.jogamp.oculusvr.ovrVector2i; import com.jogamp.oculusvr.ovrVector3f; import com.jogamp.opengl.math.FovHVHalves; import com.jogamp.opengl.math.Quaternion; +import com.jogamp.opengl.util.stereo.StereoDeviceRenderer; /** * OculusVR Data Conversion Helper Functions @@ -122,7 +124,7 @@ public class OVRUtil { } public static ovrFovPort getOVRFovPort(final FovHVHalves fovHVHalves) { final ovrFovPort tanHalfFov = ovrFovPort.create(); - final FovHVHalves fovHVHalvesTan = fovHVHalves.getInTangents(); + final FovHVHalves fovHVHalvesTan = fovHVHalves.toTangents(); tanHalfFov.setLeftTan(fovHVHalvesTan.left); tanHalfFov.setRightTan(fovHVHalvesTan.right); tanHalfFov.setUpTan(fovHVHalvesTan.top); @@ -130,6 +132,21 @@ public class OVRUtil { return tanHalfFov; } + public static int ovrDistCaps2DistBits(final int ovrDistortionCaps) { + int bits = StereoDeviceRenderer.DISTORTION_BARREL; + if( 0 != ( OVR.ovrDistortionCap_TimeWarp & ovrDistortionCaps ) ) { + bits |= StereoDeviceRenderer.DISTORTION_TIMEWARP; + } + if( 0 != ( OVR.ovrDistortionCap_Chromatic & ovrDistortionCaps ) ) { + bits |= StereoDeviceRenderer.DISTORTION_CHROMATIC; + } + if( 0 != ( OVR.ovrDistortionCap_Vignette & ovrDistortionCaps ) ) { + bits |= StereoDeviceRenderer.DISTORTION_VIGNETTE; + } + return bits; + } + + public static String toString(final ovrFovPort fov) { return "["+fov.getLeftTan()+" l, "+fov.getRightTan()+" r, "+ fov.getUpTan()+" u, "+fov.getDownTan()+" d]"; |