diff options
Diffstat (limited to 'src/oculusvr')
5 files changed, 241 insertions, 77 deletions
diff --git a/src/oculusvr/classes/com/jogamp/oculusvr/OVRVersion.java b/src/oculusvr/classes/com/jogamp/oculusvr/OVRVersion.java index 50e0efd30..6269ce4e9 100644 --- a/src/oculusvr/classes/com/jogamp/oculusvr/OVRVersion.java +++ b/src/oculusvr/classes/com/jogamp/oculusvr/OVRVersion.java @@ -41,6 +41,16 @@ import java.util.jar.Manifest; public class OVRVersion extends JogampVersion { + /** + * Default init-params for {@link OVR#ovr_Initialize(ovrInitParams)}, + * w/ flags {@link OVR#ovrInit_ServerOptional}. + */ + public static final ovrInitParams defaultInitParams; + static { + defaultInitParams = ovrInitParams.create(); + defaultInitParams.setFlags(OVR.ovrInit_ServerOptional); + } + protected static volatile OVRVersion jogampCommonVersionInfo; protected OVRVersion(final String packageName, final Manifest mf) { @@ -64,7 +74,7 @@ public class OVRVersion extends JogampVersion { if(null==sb) { sb = new StringBuilder(); } - if( !OVR.ovr_Initialize() ) { // recursive .. + if( !OVR.ovr_Initialize(defaultInitParams) ) { // recursive .. sb.append("\tOVR not available").append(Platform.getNewline()); } else { final ovrHmdDesc hmdDesc = OVR.ovrHmd_Create(ovrHmdIndex); @@ -97,20 +107,23 @@ public class OVRVersion extends JogampVersion { if(null==sb) { sb = new StringBuilder(); } - sb.append("\thmd."+ovrHmdIndex+".productName:\t"+hmdDesc.getProductNameAsString()).append(Platform.getNewline()); - sb.append("\thmd."+ovrHmdIndex+".vendorName:\t"+hmdDesc.getManufacturerAsString()).append(Platform.getNewline()); - sb.append("\thmd."+ovrHmdIndex+".deviceName:\t"+hmdDesc.getDisplayDeviceNameAsString()).append(Platform.getNewline()); - sb.append("\thmd."+ovrHmdIndex+".productId:\t0x"+Integer.toHexString(hmdDesc.getProductId())).append(Platform.getNewline()); - sb.append("\thmd."+ovrHmdIndex+".vendorId:\t0x"+Integer.toHexString(hmdDesc.getVendorId())).append(Platform.getNewline()); - sb.append("\thmd."+ovrHmdIndex+".serial:\t"+hmdDesc.getSerialNumberAsString()).append(Platform.getNewline()); - sb.append("\thmd."+ovrHmdIndex+".type:\t"+hmdDesc.getType()).append(Platform.getNewline()); - sb.append("\thmd."+ovrHmdIndex+".hmdCaps:\t"+toHexString(hmdDesc.getHmdCaps())).append(Platform.getNewline()); - sb.append("\thmd."+ovrHmdIndex+".distorCaps:\t"+toHexString(hmdDesc.getDistortionCaps())).append(Platform.getNewline()); - sb.append("\thmd."+ovrHmdIndex+".sensorCaps:\t"+toHexString(hmdDesc.getTrackingCaps())).append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".productName: "+hmdDesc.getProductNameAsString()).append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".vendorName: "+hmdDesc.getManufacturerAsString()).append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".deviceName: "+hmdDesc.getDisplayDeviceNameAsString()).append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".productId: 0x"+Integer.toHexString(hmdDesc.getProductId())).append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".vendorId: 0x"+Integer.toHexString(hmdDesc.getVendorId())).append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".serial: "+hmdDesc.getSerialNumberAsString()).append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".firmware: "+hmdDesc.getFirmwareMajor()+"."+hmdDesc.getFirmwareMinor()).append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".type: "+hmdDesc.getType()).append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".hmdCaps: "+toHexString(hmdDesc.getHmdCaps())).append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".distorCaps: "+toHexString(hmdDesc.getDistortionCaps())).append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".sensorCaps: "+toHexString(hmdDesc.getTrackingCaps())).append(Platform.getNewline()); final ovrSizei resolution = hmdDesc.getResolution(); - sb.append("\thmd."+ovrHmdIndex+".resolution:\t"+resolution.getW()+"x"+resolution.getH()).append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".resolution: "+resolution.getW()+"x"+resolution.getH()).append(Platform.getNewline()); final ovrVector2i winPos = hmdDesc.getWindowsPos(); - sb.append("\thmd."+ovrHmdIndex+".winPos:\t"+winPos.getX()+" / "+winPos.getY()).append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".winPos: "+winPos.getX()+" / "+winPos.getY()).append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".cameraFrustum.Z: "+hmdDesc.getCameraFrustumNearZInMeters()+" - "+hmdDesc.getCameraFrustumFarZInMeters()+" meter").append(Platform.getNewline()); + sb.append("\thmd."+ovrHmdIndex+".cameraFrustum.Fov: H "+hmdDesc.getCameraFrustumHFovInRadians()+" rad, V "+hmdDesc.getCameraFrustumVFovInRadians()+" rad").append(Platform.getNewline()); return sb; } private static String toHexString(final int v) { return "0x"+Integer.toHexString(v); } diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDevice.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDevice.java index 3abea5839..5025e80c5 100644 --- a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDevice.java +++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDevice.java @@ -38,7 +38,10 @@ import com.jogamp.oculusvr.ovrEyeRenderDesc; import com.jogamp.oculusvr.ovrFovPort; import com.jogamp.oculusvr.ovrHmdDesc; import com.jogamp.oculusvr.ovrSizei; +import com.jogamp.oculusvr.ovrTrackingState; import com.jogamp.opengl.math.FovHVHalves; +import com.jogamp.opengl.math.geom.Frustum; +import com.jogamp.opengl.util.stereo.LocationSensorParameter; import com.jogamp.opengl.util.stereo.StereoDevice; import com.jogamp.opengl.util.stereo.StereoDeviceFactory; import com.jogamp.opengl.util.stereo.StereoDeviceRenderer; @@ -54,7 +57,11 @@ public class OVRStereoDevice implements StereoDevice { public ovrHmdDesc hmdDesc; public OvrHmdContext handle; + + private final int supportedSensorBits; + private int usedSensorBits; private boolean sensorsStarted = false; + private final int[] eyeRenderOrder; private final int supportedDistortionBits, recommendedDistortionBits, minimumDistortionBits; @@ -64,6 +71,8 @@ public class OVRStereoDevice implements StereoDevice { private final PointImmutable position; private final int dkVersion; + private final LocationSensorParameter locationSensorParams; + public OVRStereoDevice(final StereoDeviceFactory factory, final ovrHmdDesc hmdDesc, final int deviceIndex) { if( null == hmdDesc ) { throw new IllegalArgumentException("Passed null hmdDesc"); @@ -76,6 +85,7 @@ public class OVRStereoDevice implements StereoDevice { this.handle = nativeContext; this.deviceIndex = deviceIndex; this.hmdDesc = hmdDesc; + final ovrFovPort[] defaultOVREyeFov = hmdDesc.getDefaultEyeFov(0, new ovrFovPort[ovrHmdDesc.getEyeRenderOrderArrayLength()]); defaultEyeFov = new FovHVHalves[defaultOVREyeFov.length]; for(int i=0; i<defaultEyeFov.length; i++) { @@ -84,9 +94,27 @@ public class OVRStereoDevice implements StereoDevice { eyeRenderOrder = new int[ovrHmdDesc.getEyeRenderOrderArrayLength()]; hmdDesc.getEyeRenderOrder(0, eyeRenderOrder); supportedDistortionBits = OVRUtil.ovrDistCaps2DistBits(hmdDesc.getDistortionCaps()); - recommendedDistortionBits = supportedDistortionBits & ~StereoDeviceRenderer.DISTORTION_TIMEWARP; + recommendedDistortionBits = supportedDistortionBits; // & ~StereoDeviceRenderer.DISTORTION_TIMEWARP; minimumDistortionBits = StereoDeviceRenderer.DISTORTION_BARREL; + usedSensorBits = 0; + supportedSensorBits = OVRUtil.ovrTrackingCaps2SensorBits(hmdDesc.getTrackingCaps()); + + LocationSensorParameter _locationSensorParams = null; + if( StereoUtil.usesPositionSensor(supportedSensorBits)) { + try { + final FovHVHalves posFov = FovHVHalves.byRadians(hmdDesc.getCameraFrustumHFovInRadians(), + hmdDesc.getCameraFrustumVFovInRadians()); + final float posZNear = hmdDesc.getCameraFrustumNearZInMeters(); + final float posZFar = hmdDesc.getCameraFrustumFarZInMeters(); + _locationSensorParams = new LocationSensorParameter(new Frustum.FovDesc(posFov, posZNear, posZFar)); + } catch (final IllegalArgumentException iae) { + // probably zNear/zFar issue .. + System.err.println(iae.getMessage()); + } + } + locationSensorParams = _locationSensorParams; + // DK1 delivers unrotated resolution in target orientation // DK2 delivers rotated resolution in target orientation, monitor screen is rotated 90deg clockwise deviceName = hmdDesc.getDisplayDeviceNameAsString(); @@ -122,13 +150,17 @@ public class OVRStereoDevice implements StereoDevice { sb.append(", surfacePos "+getPosition()); sb.append(", distortionBits[supported ["+StereoUtil.distortionBitsToString(getSupportedDistortionBits())+ "], recommended ["+StereoUtil.distortionBitsToString(getRecommendedDistortionBits())+ - "], minimum ["+StereoUtil.distortionBitsToString(getMinimumDistortionBits())+"]]]"); + "], minimum ["+StereoUtil.distortionBitsToString(getMinimumDistortionBits())+"]]"); + sb.append(", sensorBits[supported ["+StereoUtil.sensorBitsToString(getSupportedSensorBits())+ + "], enabled ["+StereoUtil.sensorBitsToString(getEnabledSensorBits())+"]]"); + sb.append(", "+locationSensorParams+"]"); return sb.toString(); } @Override public final void dispose() { if( isValid() ) { + stopSensors(); OVR.ovrHmd_Destroy(hmdDesc); hmdDesc = null; handle = null; @@ -149,34 +181,84 @@ public class OVRStereoDevice implements StereoDevice { public int getRequiredRotation() { return requiredRotation; } @Override - public float[] getDefaultEyePositionOffset() { - return DEFAULT_EYE_POSITION_OFFSET; - } + public float[] getDefaultEyePositionOffset() { return DEFAULT_EYE_POSITION_OFFSET; } + + @Override + public final FovHVHalves[] getDefaultFOV() { return defaultEyeFov; } + + @Override + public final LocationSensorParameter getLocationSensorParams() { return locationSensorParams; } @Override - public final FovHVHalves[] getDefaultFOV() { - return defaultEyeFov; + public final void resetLocationSensorOrigin() { + if( isValid() && sensorsStarted && StereoUtil.usesPositionSensor(supportedSensorBits)) { + OVR.ovrHmd_RecenterPose(hmdDesc); + } + } + + /* pp */ void updateUsedSensorBits(final ovrTrackingState trackingState) { + final int pre = usedSensorBits; + if( sensorsStarted && null != trackingState ) { + usedSensorBits = StereoDevice.SENSOR_ORIENTATION | + OVRUtil.ovrTrackingStats2SensorBits(trackingState.getStatusFlags()); + } else { + usedSensorBits = 0; + } + if( StereoDevice.DEBUG ) { + if( pre != usedSensorBits ) { + System.err.println("XXX: Sensor Change: "+ + ": pre["+StereoUtil.sensorBitsToString(pre)+"]"+ + " -> now["+StereoUtil.sensorBitsToString(usedSensorBits)+"]"); + } + } } @Override - public final boolean startSensors(final boolean start) { - if( start && !sensorsStarted ) { + public final boolean startSensors(final int desiredSensorBits, final int requiredSensorBits) { + if( isValid() && !sensorsStarted ) { + if( requiredSensorBits != ( supportedSensorBits & requiredSensorBits ) ) { + // required sensors not available + if( StereoDevice.DEBUG ) { + System.err.println("XXX: startSensors failed: n/a required sensors ["+StereoUtil.sensorBitsToString(requiredSensorBits)+"]"); + } + return false; + } + if( 0 == ( supportedSensorBits & ( requiredSensorBits | desiredSensorBits ) ) ) { + // no sensors available + if( StereoDevice.DEBUG ) { + System.err.println("XXX: startSensors failed: n/a any sensors"); + } + return false; + } // Start the sensor which provides the Rift’s pose and motion. - final int requiredTrackingCaps = 0; - final int supportedTrackingCaps = requiredTrackingCaps | - OVR.ovrTrackingCap_Orientation | - OVR.ovrTrackingCap_MagYawCorrection | - OVR.ovrTrackingCap_Position; - if( OVR.ovrHmd_ConfigureTracking(hmdDesc, supportedTrackingCaps, requiredTrackingCaps) ) { + final int requiredTrackingCaps = OVRUtil.sensorBits2TrackingCaps(requiredSensorBits); + final int desiredTrackingCaps = requiredTrackingCaps | OVRUtil.sensorBits2TrackingCaps(desiredSensorBits); + final boolean res; + if( OVR.ovrHmd_ConfigureTracking(hmdDesc, desiredTrackingCaps, requiredTrackingCaps) ) { sensorsStarted = true; - return true; + updateUsedSensorBits(OVR.ovrHmd_GetTrackingState(hmdDesc, 0.0)); + res = true; } else { - sensorsStarted = false; - return false; + res = false; + } + if( StereoDevice.DEBUG ) { + System.err.println("XXX: startSensors: "+res+", started "+sensorsStarted+ + ": required["+StereoUtil.sensorBitsToString(requiredSensorBits)+"]"+ + ", desired["+StereoUtil.sensorBitsToString(desiredSensorBits)+"]"+ + ", enabled["+StereoUtil.sensorBitsToString(usedSensorBits)+"]"); } - } else if( sensorsStarted ) { + return res; + } else { + // No state change -> Success + return true; + } + } + @Override + public final boolean stopSensors() { + if( isValid() && sensorsStarted ) { OVR.ovrHmd_ConfigureTracking(hmdDesc, 0, 0); // STOP sensorsStarted = false; + usedSensorBits = 0; return true; } else { // No state change -> Success @@ -187,6 +269,16 @@ public class OVRStereoDevice implements StereoDevice { public final boolean getSensorsStarted() { return sensorsStarted; } @Override + public final int getSupportedSensorBits() { + return supportedSensorBits; + } + + @Override + public final int getEnabledSensorBits() { + return usedSensorBits; + } + + @Override public final int[] getEyeRenderOrder() { return eyeRenderOrder; } diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceFactory.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceFactory.java index 772891115..a0836b5a3 100644 --- a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceFactory.java +++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceFactory.java @@ -36,12 +36,13 @@ import com.jogamp.opengl.util.stereo.StereoDevice; import com.jogamp.opengl.util.stereo.StereoDeviceFactory; public class OVRStereoDeviceFactory extends StereoDeviceFactory { - public static boolean isAvailable() { - if( OVR.ovr_Initialize() ) { // recursive .. + if( OVR.ovr_Initialize(OVRVersion.defaultInitParams) ) { // recursive .. boolean res = false; final int count = OVR.ovrHmd_Detect(); - System.err.println("Detect.0: ovrHmd_Detect() -> "+count); + if( StereoDevice.DEBUG ) { + System.err.println("Detect.0: ovrHmd_Detect() -> "+count); + } if( 0 < count ) { res = true; } else { @@ -54,6 +55,10 @@ public class OVRStereoDeviceFactory extends StereoDeviceFactory { System.err.println("Detect.1: hmdDesc: "+hmdDesc.getProductNameAsString()); } OVR.ovrHmd_Destroy(hmdDesc); + } else { + if( StereoDevice.DEBUG ) { + System.err.println("Detect.1: hmdDesc: null"); + } } } return res; diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceRenderer.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceRenderer.java index 60fb8301e..95565dd0f 100644 --- a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceRenderer.java +++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRStereoDeviceRenderer.java @@ -54,6 +54,7 @@ import com.jogamp.oculusvr.ovrMatrix4f; import com.jogamp.oculusvr.ovrPosef; import com.jogamp.oculusvr.ovrRecti; import com.jogamp.oculusvr.ovrSizei; +import com.jogamp.oculusvr.ovrTrackingState; import com.jogamp.oculusvr.ovrVector2f; import com.jogamp.oculusvr.ovrVector3f; import com.jogamp.opengl.JoglVersion; @@ -62,7 +63,7 @@ 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; +import com.jogamp.opengl.util.stereo.ViewerPose; import com.jogamp.opengl.util.stereo.StereoDevice; import com.jogamp.opengl.util.stereo.StereoDeviceRenderer; import com.jogamp.opengl.util.stereo.StereoUtil; @@ -93,12 +94,11 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { private final GLArrayData vboPos, vboParams, vboTexCoordsR, vboTexCoordsG, vboTexCoordsB; private final GLArrayDataServer indices; - private final ovrEyeRenderDesc ovrEyeDesc; + /* pp */ final ovrEyeRenderDesc ovrEyeDesc; private final ovrFovPort ovrEyeFov; private final EyeParameter eyeParameter; - private ovrPosef ovrEyePose; - private final EyePose eyePose; + private final ovrMatrix4f[] timeWarpMatrices; @Override public final RectangleImmutable getViewport() { return viewport; } @@ -106,12 +106,9 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { @Override public final EyeParameter getEyeParameter() { return eyeParameter; } - @Override - public final EyePose getLastEyePose() { return eyePose; } - - private OVREye(final ovrHmdDesc hmdDesc, final int distortionBits, - final float[] eyePositionOffset, final ovrEyeRenderDesc eyeDesc, - final ovrSizei ovrTextureSize, final RectangleImmutable eyeViewport) { + /* pp */ OVREye(final ovrHmdDesc hmdDesc, final int distortionBits, + final float[] eyePositionOffset, final ovrEyeRenderDesc eyeDesc, + final ovrSizei ovrTextureSize, final RectangleImmutable eyeViewport) { this.eyeName = eyeDesc.getEye(); this.distortionBits = distortionBits; this.viewport = eyeViewport; @@ -125,9 +122,13 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { if( usesTimewarp ) { eyeRotationStart = new GLUniformData("ovr_EyeRotationStart", 4, 4, Buffers.slice2Float(fstash, 4, 16)); eyeRotationEnd = new GLUniformData("ovr_EyeRotationEnd", 4, 4, Buffers.slice2Float(fstash, 20, 16)); + timeWarpMatrices = new ovrMatrix4f[2]; + timeWarpMatrices[0] = ovrMatrix4f.create(); + timeWarpMatrices[1] = ovrMatrix4f.create(); } else { eyeRotationStart = null; eyeRotationEnd = null; + timeWarpMatrices = null; } this.ovrEyeDesc = eyeDesc; @@ -137,14 +138,10 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { this.eyeParameter = new EyeParameter(eyeName, eyePositionOffset, OVRUtil.getFovHV(ovrEyeFov), eyeViewAdjust.getX(), eyeViewAdjust.getY(), eyeViewAdjust.getZ()); - this.eyePose = new EyePose(eyeName); - - updateEyePose(hmdDesc); // 1st init - // Setup: eyeToSourceUVScale, eyeToSourceUVOffset { final ovrVector2f[] uvScaleOffsetOut = new ovrVector2f[2]; - uvScaleOffsetOut[0] = ovrVector2f.create(); // FIXME: remove ctor / double check + uvScaleOffsetOut[0] = ovrVector2f.create(); uvScaleOffsetOut[1] = ovrVector2f.create(); final ovrRecti ovrEyeRenderViewport = OVRUtil.createOVRRecti(eyeViewport); @@ -194,7 +191,7 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { /** 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]; - ovRes[0] = ovrDistortionVertex.create(); // FIXME: remove ctor / double check + ovRes[0] = ovrDistortionVertex.create(); for ( int vertNum = 0; vertNum < vertexCount; vertNum++ ) { final ovrDistortionVertex ov = meshData.getPVertexData(vertNum, ovRes)[0]; @@ -275,7 +272,7 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { OVR.ovrHmd_DestroyDistortionMesh(meshData); } - private void linkData(final GL2ES2 gl, final ShaderProgram sp) { + /* pp */ void linkData(final GL2ES2 gl, final ShaderProgram sp) { if( 0 > vboPos.setLocation(gl, sp.program()) ) { throw new GLException("Couldn't locate "+vboPos); } @@ -313,16 +310,16 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { indices.enableBuffer(gl, false); } - private void dispose(final GL2ES2 gl) { + /* pp */ void dispose(final GL2ES2 gl) { iVBO.destroy(gl); indices.destroy(gl); } - private void enableVBO(final GL2ES2 gl, final boolean enable) { + /* pp */ void enableVBO(final GL2ES2 gl, final boolean enable) { iVBO.enableBuffer(gl, enable); indices.bindBuffer(gl, enable); // keeps VBO binding if enable:=true } - private void updateUniform(final GL2ES2 gl, final ShaderProgram sp) { + /* pp */ void updateUniform(final GL2ES2 gl, final ShaderProgram sp) { gl.glUniform(eyeToSourceUVScale); gl.glUniform(eyeToSourceUVOffset); if( StereoUtil.usesTimewarpDistortion(distortionBits) ) { @@ -331,10 +328,7 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { } } - private void updateTimewarp(final ovrHmdDesc hmdDesc, final ovrPosef eyeRenderPose, final float[] mat4Tmp1, final float[] mat4Tmp2) { - final ovrMatrix4f[] timeWarpMatrices = new ovrMatrix4f[2]; - timeWarpMatrices[0] = ovrMatrix4f.create(); // FIXME: remove ctor / double check - timeWarpMatrices[1] = ovrMatrix4f.create(); + /* pp */ void updateTimewarp(final ovrHmdDesc hmdDesc, final ovrPosef eyeRenderPose, final float[] mat4Tmp1, final float[] mat4Tmp2) { OVR.ovrHmd_GetEyeTimewarpMatrices(hmdDesc, eyeName, eyeRenderPose, timeWarpMatrices); final float[] eyeRotationStartM = FloatUtil.transposeMatrix(timeWarpMatrices[0].getM(0, mat4Tmp1), mat4Tmp2); @@ -348,19 +342,6 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { eyeRotationEndU.rewind(); } - /** - * Updates {@link #ovrEyePose} and it's extracted - * {@link #eyeRenderPoseOrientation} and {@link #eyeRenderPosePosition}. - * @param hmdCtx used get the {@link #ovrEyePose} via {@link OVR#ovrHmd_GetHmdPosePerEye(ovrHmdDesc, int)} - */ - private EyePose updateEyePose(final ovrHmdDesc hmdDesc) { - ovrEyePose = OVR.ovrHmd_GetHmdPosePerEye(hmdDesc, 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+ @@ -368,12 +349,16 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { ", 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(ovrEyeDesc)+", "+eyePose+"]"; + "], desc"+OVRUtil.toString(ovrEyeDesc)+"]"; } } private final OVRStereoDevice context; private final OVREye[] eyes; + private final ovrPosef[] ovrEyePoses; + private final ovrVector3f[] hmdToEyeViewOffset; + private final ViewerPose viewerPose; + private final ovrTrackingState trackingState; private final int distortionBits; private final int textureCount; private final DimensionImmutable[] eyeTextureSizes; @@ -439,6 +424,16 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { } eyes[0] = new OVREye(context.hmdDesc, this.distortionBits, eyePositionOffset, eyeRenderDescs[0], ovrTexture0Size, eyeViewports[0]); eyes[1] = new OVREye(context.hmdDesc, this.distortionBits, eyePositionOffset, eyeRenderDescs[1], ovrTexture1Size, eyeViewports[1]); + + ovrEyePoses = new ovrPosef[2]; + ovrEyePoses[0] = ovrPosef.create(); + ovrEyePoses[1] = ovrPosef.create(); + hmdToEyeViewOffset = new ovrVector3f[2]; + hmdToEyeViewOffset[0] = eyes[0].ovrEyeDesc.getHmdToEyeViewOffset(); + hmdToEyeViewOffset[1] = eyes[1].ovrEyeDesc.getHmdToEyeViewOffset(); + viewerPose = new ViewerPose(); + trackingState = ovrTrackingState.create(); + sp = null; frameTiming = null; frameCount = 0; @@ -546,13 +541,33 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { } @Override - public final EyePose updateEyePose(final int eyeNum) { - return eyes[eyeNum].updateEyePose(context.hmdDesc); + public final ViewerPose updateViewerPose() { + final ovrTrackingState trackingState; + trackingState = this.trackingState; + OVR.ovrHmd_GetEyePoses(context.hmdDesc, frameCount, hmdToEyeViewOffset, ovrEyePoses, trackingState); + context.updateUsedSensorBits(trackingState); + + // Use headPose of tracking state, since it points to the viewer + // where ovrEyePoses already have hmdToEyeViewOffset applied (IPD .. etc). + final ovrPosef pose = trackingState.getHeadPose().getThePose(); + final ovrVector3f pos = pose.getPosition(); + viewerPose.setPosition(pos.getX(), pos.getY(), pos.getZ()); + OVRUtil.copyToQuaternion(pose.getOrientation(), viewerPose.orientation); + + // System.err.println("Viewer: "+OVRUtil.toString(pos)); + // System.err.println("Camera: "+OVRUtil.toString(trackingState.getCameraPose().getPosition())); + // System.err.println("Leveld: "+OVRUtil.toString(trackingState.getLeveledCameraPose().getPosition())); + return viewerPose; + } + + @Override + public final ViewerPose getLastViewerPose() { + return viewerPose; } @Override public final void beginFrame(final GL gl) { - frameTiming = OVR.ovrHmd_BeginFrameTiming(context.hmdDesc, 0); // ovrHmd_GetFrameTiming not used, otherwise: frameCount); + frameTiming = OVR.ovrHmd_BeginFrameTiming(context.hmdDesc, frameCount); // ovrHmd_GetFrameTiming not used, otherwise: frameCount); } @Override @@ -574,7 +589,9 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { throw new IllegalStateException("beginFrame not called"); } if( StereoUtil.usesTimewarpDistortion(distortionBits) ) { + // minimize latency OVR.ovr_WaitTillTime(frameTiming.getTimewarpPointSeconds()); + // {@link OVREye#updateTimewarp(ovrHmdDesc, ovrPosef, float[], float[])} will be called in {@link #ppOneEye} } final GL2ES2 gl2es2 = gl.getGL2ES2(); @@ -599,7 +616,7 @@ public class OVRStereoDeviceRenderer implements StereoDeviceRenderer { public final void ppOneEye(final GL gl, final int eyeNum) { final OVREye eye = eyes[eyeNum]; if( StereoUtil.usesTimewarpDistortion(distortionBits) ) { - eye.updateTimewarp(context.hmdDesc, eye.ovrEyePose, mat4Tmp1, mat4Tmp2); + eye.updateTimewarp(context.hmdDesc, ovrEyePoses[eyeNum], mat4Tmp1, mat4Tmp2); } final GL2ES2 gl2es2 = gl.getGL2ES2(); diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java index c1d01fea2..e54bd61e8 100644 --- a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java +++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java @@ -44,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.StereoDevice; import com.jogamp.opengl.util.stereo.StereoDeviceRenderer; /** @@ -146,6 +147,42 @@ public class OVRUtil { return bits; } + public static int ovrTrackingCaps2SensorBits(final int ovrTrackingCaps) { + int bits = 0; + if( 0 != ( OVR.ovrTrackingCap_Orientation & ovrTrackingCaps ) ) { + bits |= StereoDevice.SENSOR_ORIENTATION; + } + if( 0 != ( OVR.ovrTrackingCap_MagYawCorrection & ovrTrackingCaps ) ) { + bits |= StereoDevice.SENSOR_YAW_CORRECTION; + } + if( 0 != ( OVR.ovrTrackingCap_Position & ovrTrackingCaps ) ) { + bits |= StereoDevice.SENSOR_POSITION; + } + return bits; + } + public static int ovrTrackingStats2SensorBits(final int ovrTrackingCaps) { + int bits = 0; + if( 0 != ( OVR.ovrStatus_OrientationTracked & ovrTrackingCaps ) ) { + bits |= StereoDevice.SENSOR_ORIENTATION; + } + if( 0 != ( OVR.ovrStatus_PositionTracked & ovrTrackingCaps ) ) { + bits |= StereoDevice.SENSOR_POSITION; + } + return bits; + } + public static int sensorBits2TrackingCaps(final int sensorBits) { + int caps = 0; + if( 0 != ( StereoDevice.SENSOR_ORIENTATION & sensorBits ) ) { + caps |= OVR.ovrTrackingCap_Orientation; + } + if( 0 != ( StereoDevice.SENSOR_YAW_CORRECTION & sensorBits ) ) { + caps |= OVR.ovrTrackingCap_MagYawCorrection; + } + if( 0 != ( StereoDevice.SENSOR_POSITION & sensorBits ) ) { + caps |= OVR.ovrTrackingCap_Position; + } + return caps; + } public static String toString(final ovrFovPort fov) { return "["+fov.getLeftTan()+" l, "+fov.getRightTan()+" r, "+ |