diff --git a/.gitignore b/.gitignore index aa848af79..dc6d9aec8 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,4 @@ !/jme3-vr/src/main/resources/**/*.so.dbg !/jme3-vr/src/main/resources/**/*.dll !/jme3-vr/src/main/resources/**/*.pdb +/buildMaven.bat diff --git a/jme3-vr/src/main/java/com/jme3/app/VRAppState.java b/jme3-vr/src/main/java/com/jme3/app/VRAppState.java index 5b850c931..a468e71b9 100644 --- a/jme3-vr/src/main/java/com/jme3/app/VRAppState.java +++ b/jme3-vr/src/main/java/com/jme3/app/VRAppState.java @@ -241,7 +241,7 @@ public class VRAppState extends AbstractAppState { return application.getViewPort(); } - return environment.getVRViewManager().getLeftViewport(); + return environment.getVRViewManager().getLeftViewPort(); } /** @@ -253,7 +253,7 @@ public class VRAppState extends AbstractAppState { if( environment.getVRViewManager() == null ){ return application.getViewPort(); } - return environment.getVRViewManager().getRightViewport(); + return environment.getVRViewManager().getRightViewPort(); } /** @@ -263,12 +263,12 @@ public class VRAppState extends AbstractAppState { public void setBackgroundColors(ColorRGBA clr) { if( environment.getVRViewManager() == null ) { application.getViewPort().setBackgroundColor(clr); - } else if( environment.getVRViewManager().getLeftViewport() != null ) { + } else if( environment.getVRViewManager().getLeftViewPort() != null ) { - environment.getVRViewManager().getLeftViewport().setBackgroundColor(clr); + environment.getVRViewManager().getLeftViewPort().setBackgroundColor(clr); - if( environment.getVRViewManager().getRightViewport() != null ){ - environment.getVRViewManager().getRightViewport().setBackgroundColor(clr); + if( environment.getVRViewManager().getRightViewPort() != null ){ + environment.getVRViewManager().getRightViewPort().setBackgroundColor(clr); } } } diff --git a/jme3-vr/src/main/java/com/jme3/app/VRApplication.java b/jme3-vr/src/main/java/com/jme3/app/VRApplication.java index 698451248..9d502431d 100644 --- a/jme3-vr/src/main/java/com/jme3/app/VRApplication.java +++ b/jme3-vr/src/main/java/com/jme3/app/VRApplication.java @@ -254,7 +254,7 @@ public abstract class VRApplication implements Application, SystemListener { dummyCam = new Camera(); initStateManager(); - + // Create the GUI manager. guiManager = new VRGuiManager(null); @@ -1085,7 +1085,7 @@ public abstract class VRApplication implements Application, SystemListener { */ public ViewPort getLeftViewPort() { if( viewmanager == null ) return getViewPort(); - return viewmanager.getLeftViewport(); + return viewmanager.getLeftViewPort(); } /** @@ -1095,7 +1095,7 @@ public abstract class VRApplication implements Application, SystemListener { */ public ViewPort getRightViewPort() { if( viewmanager == null ) return getViewPort(); - return viewmanager.getRightViewport(); + return viewmanager.getRightViewPort(); } @@ -1106,9 +1106,9 @@ public abstract class VRApplication implements Application, SystemListener { public void setBackgroundColors(ColorRGBA clr) { if( viewmanager == null ) { getViewPort().setBackgroundColor(clr); - } else if( viewmanager.getLeftViewport() != null ) { - viewmanager.getLeftViewport().setBackgroundColor(clr); - if( viewmanager.getRightViewport() != null ) viewmanager.getRightViewport().setBackgroundColor(clr); + } else if( viewmanager.getLeftViewPort() != null ) { + viewmanager.getLeftViewPort().setBackgroundColor(clr); + if( viewmanager.getRightViewPort() != null ) viewmanager.getRightViewPort().setBackgroundColor(clr); } } diff --git a/jme3-vr/src/main/java/com/jme3/app/VREnvironment.java b/jme3-vr/src/main/java/com/jme3/app/VREnvironment.java index 5358ff42a..e0e9048dc 100644 --- a/jme3-vr/src/main/java/com/jme3/app/VREnvironment.java +++ b/jme3-vr/src/main/java/com/jme3/app/VREnvironment.java @@ -8,6 +8,7 @@ import com.jme3.app.state.AppState; import com.jme3.input.vr.OSVR; import com.jme3.input.vr.OpenVR; import com.jme3.input.vr.VRAPI; +import com.jme3.input.vr.VRBounds; import com.jme3.input.vr.VRInputAPI; import com.jme3.renderer.Camera; import com.jme3.scene.Spatial; @@ -28,6 +29,8 @@ public class VREnvironment { private VRMouseManager mouseManager = null; private VRViewManager viewmanager = null; + private VRBounds bounds = null; + /** * The underlying system VR API. By default set to {@link VRConstants#SETTING_VRAPI_OPENVR_VALUE}. */ @@ -65,7 +68,6 @@ public class VREnvironment { private boolean initialized = false; - private boolean attached = false; public VREnvironment(AppSettings settings){ @@ -73,7 +75,8 @@ public class VREnvironment { guiManager = new VRGuiManager(this); mouseManager = new VRMouseManager(this); -// dummyCam = new Camera(settings.getWidth(), settings.getHeight()); + + bounds = new VRBounds(); processSettings(); } @@ -86,6 +89,14 @@ public class VREnvironment { return hardware; } + /** + * Get the VR bounds. + * @return the VR bounds. + */ + public VRBounds getVRBounds(){ + return bounds; + } + /** * Get the VR dedicated input. * @return the VR dedicated input. @@ -347,7 +358,12 @@ public class VREnvironment { if (application.getCamera() != null){ dummyCam = application.getCamera().clone(); } else { - return new Camera(settings.getWidth(), settings.getHeight()); + + if ((settings != null) && (settings.getWidth() != 0) && (settings.getHeight() != 0)){ + dummyCam = new Camera(settings.getWidth(), settings.getHeight()); + } else { + dummyCam = new Camera(); + } } } else { throw new IllegalStateException("VR environment is not attached to any application."); diff --git a/jme3-vr/src/main/java/com/jme3/input/vr/OpenVR.java b/jme3-vr/src/main/java/com/jme3/input/vr/OpenVR.java index 8171bc48a..a9f3fdcfb 100644 --- a/jme3-vr/src/main/java/com/jme3/input/vr/OpenVR.java +++ b/jme3-vr/src/main/java/com/jme3/input/vr/OpenVR.java @@ -1,524 +1,525 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.jme3.input.vr; - -import com.jme3.app.VREnvironment; -import com.jme3.math.Matrix4f; -import com.jme3.math.Quaternion; -import com.jme3.math.Vector2f; -import com.jme3.math.Vector3f; -import com.jme3.renderer.Camera; -import com.jme3.system.jopenvr.HmdMatrix34_t; -import com.jme3.system.jopenvr.HmdMatrix44_t; -import com.jme3.system.jopenvr.JOpenVRLibrary; -import com.jme3.system.jopenvr.OpenVRUtil; -import com.jme3.system.jopenvr.TrackedDevicePose_t; -import com.jme3.system.jopenvr.VR_IVRCompositor_FnTable; -import com.jme3.system.jopenvr.VR_IVRSystem_FnTable; -import com.jme3.util.VRUtil; -import com.sun.jna.Memory; -import com.sun.jna.Pointer; -import com.sun.jna.ptr.FloatByReference; -import com.sun.jna.ptr.IntByReference; -import com.sun.jna.ptr.LongByReference; - -import java.nio.IntBuffer; -import java.util.Locale; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * A class that wraps an OpenVR system. - * @author reden - phr00t - https://github.com/phr00t - * @author Julien Seinturier - (c) 2016 - JOrigin project - http:/www.jorigin.org - */ -public class OpenVR implements VRAPI { - - private static final Logger logger = Logger.getLogger(OpenVR.class.getName()); - - private static VR_IVRCompositor_FnTable compositorFunctions; - private static VR_IVRSystem_FnTable vrsystemFunctions; - - private static boolean initSuccess = false; - private static boolean flipEyes = false; - - private static IntBuffer hmdDisplayFrequency; - private static TrackedDevicePose_t.ByReference hmdTrackedDevicePoseReference; - protected static TrackedDevicePose_t[] hmdTrackedDevicePoses; - - protected static IntByReference hmdErrorStore; - - private static final Quaternion rotStore = new Quaternion(); - private static final Vector3f posStore = new Vector3f(); - - private static FloatByReference tlastVsync; - - /** - * The actual frame count. - */ - public static LongByReference _tframeCount; - - // for debugging latency - private int frames = 0; - - protected static Matrix4f[] poseMatrices; - - private static final Matrix4f hmdPose = Matrix4f.IDENTITY.clone(); - private static Matrix4f hmdProjectionLeftEye; - private static Matrix4f hmdProjectionRightEye; - private static Matrix4f hmdPoseLeftEye; - private static Matrix4f hmdPoseRightEye; - - private static Vector3f hmdPoseLeftEyeVec, hmdPoseRightEyeVec, hmdSeatToStand; - - private static float vsyncToPhotons; - private static double timePerFrame, frameCountRun; - private static long frameCount; - private static OpenVRInput VRinput; - - private VREnvironment environment = null; - - /** - * Create a new OpenVR system - * attached to the given {@link VREnvironment VR environment}. - * @param environment the VR environment to which this API is attached. - */ - public OpenVR(VREnvironment environment){ - this.environment = environment; - } - - @Override - public OpenVRInput getVRinput() { - return VRinput; - } - - @Override - public VR_IVRSystem_FnTable getVRSystem() { - return vrsystemFunctions; - } - - @Override - public VR_IVRCompositor_FnTable getCompositor() { - return compositorFunctions; - } - - @Override - public String getName() { - return "OpenVR"; - } - - private static long latencyWaitTime = 0; - - @Override - public void setFlipEyes(boolean set) { - flipEyes = set; - } - - private boolean enableDebugLatency = false; - - @Override - public void printLatencyInfoToConsole(boolean set) { - enableDebugLatency = set; - } - - @Override - public int getDisplayFrequency() { - if( hmdDisplayFrequency == null ) return 0; - return hmdDisplayFrequency.get(0); - } - - @Override - public boolean initialize() { - - logger.config("Initializing OpenVR system..."); - - hmdErrorStore = new IntByReference(); - vrsystemFunctions = null; - JOpenVRLibrary.VR_InitInternal(hmdErrorStore, JOpenVRLibrary.EVRApplicationType.EVRApplicationType_VRApplication_Scene); - if( hmdErrorStore.getValue() == 0 ) { - vrsystemFunctions = new VR_IVRSystem_FnTable(JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVRSystem_Version, hmdErrorStore).getPointer()); - } - - if( vrsystemFunctions == null || hmdErrorStore.getValue() != 0 ) { - logger.severe("OpenVR Initialize Result: " + JOpenVRLibrary.VR_GetVRInitErrorAsEnglishDescription(hmdErrorStore.getValue()).getString(0)); - logger.severe("Initializing OpenVR system [FAILED]"); - return false; - } else { - logger.config("OpenVR initialized & VR connected."); - - vrsystemFunctions.setAutoSynch(false); - vrsystemFunctions.read(); - - tlastVsync = new FloatByReference(); - _tframeCount = new LongByReference(); - - hmdDisplayFrequency = IntBuffer.allocate(1); - hmdDisplayFrequency.put( (int) JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_DisplayFrequency_Float); - hmdTrackedDevicePoseReference = new TrackedDevicePose_t.ByReference(); - hmdTrackedDevicePoses = (TrackedDevicePose_t[])hmdTrackedDevicePoseReference.toArray(JOpenVRLibrary.k_unMaxTrackedDeviceCount); - poseMatrices = new Matrix4f[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; - for(int i=0;i 0 ) VRUtil.sleepNanos(latencyWaitTime); - - vrsystemFunctions.GetTimeSinceLastVsync.apply(tlastVsync, _tframeCount); - float fSecondsUntilPhotons = (float)timePerFrame - tlastVsync.getValue() + vsyncToPhotons; - - if( enableDebugLatency ) { - if( frames == 10 ) { - System.out.println("Waited (nanos): " + Long.toString(latencyWaitTime)); - System.out.println("Predict ahead time: " + Float.toString(fSecondsUntilPhotons)); - } - frames = (frames + 1) % 60; - } - - // handle skipping frame stuff - long nowCount = _tframeCount.getValue(); - if( nowCount - frameCount > 1 ) { - // skipped a frame! - if( enableDebugLatency ) System.out.println("Frame skipped!"); - frameCountRun = 0; - if( latencyWaitTime > 0 ) { - latencyWaitTime -= TimeUnit.MILLISECONDS.toNanos(1); - if( latencyWaitTime < 0 ) latencyWaitTime = 0; - } - } else if( latencyWaitTime < timePerFrame * 1000000000.0 ) { - // didn't skip a frame, lets try waiting longer to improve latency - frameCountRun++; - latencyWaitTime += Math.round(Math.pow(frameCountRun / 10.0, 2.0)); - } - - frameCount = nowCount; - - vrsystemFunctions.GetDeviceToAbsoluteTrackingPose.apply( - environment.isSeatedExperience()?JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated: - JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding, - fSecondsUntilPhotons, hmdTrackedDevicePoseReference, JOpenVRLibrary.k_unMaxTrackedDeviceCount); - } - - // deal with controllers being plugged in and out - // causing an invalid memory crash... skipping for now - /*boolean hasEvent = false; - while( JOpenVRLibrary.VR_IVRSystem_PollNextEvent(OpenVR.getVRSystemInstance(), tempEvent) != 0 ) { - // wait until the events are clear.. - hasEvent = true; - } - if( hasEvent ) { - // an event probably changed controller state - VRInput._updateConnectedControllers(); - }*/ - //update controllers pose information - environment.getVRinput().updateControllerStates(); - - // read pose data from native - for (int nDevice = 0; nDevice < JOpenVRLibrary.k_unMaxTrackedDeviceCount; ++nDevice ){ - hmdTrackedDevicePoses[nDevice].readField("bPoseIsValid"); - if( hmdTrackedDevicePoses[nDevice].bPoseIsValid != 0 ){ - hmdTrackedDevicePoses[nDevice].readField("mDeviceToAbsoluteTracking"); - VRUtil.convertSteamVRMatrix3ToMatrix4f(hmdTrackedDevicePoses[nDevice].mDeviceToAbsoluteTracking, poseMatrices[nDevice]); - } - } - - if ( hmdTrackedDevicePoses[JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd].bPoseIsValid != 0 ){ - hmdPose.set(poseMatrices[JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd]); - } else { - hmdPose.set(Matrix4f.IDENTITY); - } - } - - @Override - public Matrix4f getHMDMatrixProjectionLeftEye(Camera cam){ - if( hmdProjectionLeftEye != null ) { - return hmdProjectionLeftEye; - } else if(vrsystemFunctions == null){ - return cam.getProjectionMatrix(); - } else { - HmdMatrix44_t mat = vrsystemFunctions.GetProjectionMatrix.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Left, cam.getFrustumNear(), cam.getFrustumFar()); - hmdProjectionLeftEye = new Matrix4f(); - VRUtil.convertSteamVRMatrix4ToMatrix4f(mat, hmdProjectionLeftEye); - return hmdProjectionLeftEye; - } - } - - @Override - public Matrix4f getHMDMatrixProjectionRightEye(Camera cam){ - if( hmdProjectionRightEye != null ) { - return hmdProjectionRightEye; - } else if(vrsystemFunctions == null){ - return cam.getProjectionMatrix(); - } else { - HmdMatrix44_t mat = vrsystemFunctions.GetProjectionMatrix.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Right, cam.getFrustumNear(), cam.getFrustumFar()); - hmdProjectionRightEye = new Matrix4f(); - VRUtil.convertSteamVRMatrix4ToMatrix4f(mat, hmdProjectionRightEye); - return hmdProjectionRightEye; - } - } - - @Override - public Vector3f getHMDVectorPoseLeftEye() { - if( hmdPoseLeftEyeVec == null ) { - hmdPoseLeftEyeVec = getHMDMatrixPoseLeftEye().toTranslationVector(); - // set default IPD if none or broken - if( hmdPoseLeftEyeVec.x <= 0.080f * -0.5f || hmdPoseLeftEyeVec.x >= 0.040f * -0.5f ) { - hmdPoseLeftEyeVec.x = 0.065f * -0.5f; - } - if( flipEyes == false ) hmdPoseLeftEyeVec.x *= -1f; // it seems these need flipping - } - return hmdPoseLeftEyeVec; - } - - @Override - public Vector3f getHMDVectorPoseRightEye() { - if( hmdPoseRightEyeVec == null ) { - hmdPoseRightEyeVec = getHMDMatrixPoseRightEye().toTranslationVector(); - // set default IPD if none or broken - if( hmdPoseRightEyeVec.x >= 0.080f * 0.5f || hmdPoseRightEyeVec.x <= 0.040f * 0.5f ) { - hmdPoseRightEyeVec.x = 0.065f * 0.5f; - } - if( flipEyes == false ) hmdPoseRightEyeVec.x *= -1f; // it seems these need flipping - } - return hmdPoseRightEyeVec; - } - - @Override - public Vector3f getSeatedToAbsolutePosition() { - if( environment.isSeatedExperience() == false ) return Vector3f.ZERO; - if( hmdSeatToStand == null ) { - hmdSeatToStand = new Vector3f(); - HmdMatrix34_t mat = vrsystemFunctions.GetSeatedZeroPoseToStandingAbsoluteTrackingPose.apply(); - Matrix4f tempmat = new Matrix4f(); - VRUtil.convertSteamVRMatrix3ToMatrix4f(mat, tempmat); - tempmat.toTranslationVector(hmdSeatToStand); - } - return hmdSeatToStand; - } - - @Override - public Matrix4f getHMDMatrixPoseLeftEye(){ - if( hmdPoseLeftEye != null ) { - return hmdPoseLeftEye; - } else if(vrsystemFunctions == null) { - return Matrix4f.IDENTITY; - } else { - HmdMatrix34_t mat = vrsystemFunctions.GetEyeToHeadTransform.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Left); - hmdPoseLeftEye = new Matrix4f(); - return VRUtil.convertSteamVRMatrix3ToMatrix4f(mat, hmdPoseLeftEye); - } - } - - @Override - public HmdType getType() { - if( vrsystemFunctions != null ) { - Pointer str1 = new Memory(128); - Pointer str2 = new Memory(128); - String completeName = ""; - vrsystemFunctions.GetStringTrackedDeviceProperty.apply(JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd, - JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_ManufacturerName_String, - str1, 128, hmdErrorStore); - if( hmdErrorStore.getValue() == 0 ) completeName += str1.getString(0); - vrsystemFunctions.GetStringTrackedDeviceProperty.apply(JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd, - JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_ModelNumber_String, - str2, 128, hmdErrorStore); - if( hmdErrorStore.getValue() == 0 ) completeName += " " + str2.getString(0); - if( completeName.length() > 0 ) { - completeName = completeName.toLowerCase(Locale.ENGLISH).trim(); - if( completeName.contains("htc") || completeName.contains("vive") ) { - return HmdType.HTC_VIVE; - } else if( completeName.contains("osvr") ) { - return HmdType.OSVR; - } else if( completeName.contains("oculus") || completeName.contains("rift") || - completeName.contains("dk1") || completeName.contains("dk2") || completeName.contains("cv1") ) { - return HmdType.OCULUS_RIFT; - } else if( completeName.contains("fove") ) { - return HmdType.FOVE; - } else if( completeName.contains("game") && completeName.contains("face") ) { - return HmdType.GAMEFACE; - } else if( completeName.contains("morpheus") ) { - return HmdType.MORPHEUS; - } else if( completeName.contains("gear") ) { - return HmdType.GEARVR; - } else if( completeName.contains("star") ) { - return HmdType.STARVR; - } else if( completeName.contains("null") ) { - return HmdType.NULL; - } - } - } else return HmdType.NONE; - return HmdType.OTHER; - } - - @Override - public Matrix4f getHMDMatrixPoseRightEye(){ - if( hmdPoseRightEye != null ) { - return hmdPoseRightEye; - } else if(vrsystemFunctions == null) { - return Matrix4f.IDENTITY; - } else { - HmdMatrix34_t mat = vrsystemFunctions.GetEyeToHeadTransform.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Right); - hmdPoseRightEye = new Matrix4f(); - return VRUtil.convertSteamVRMatrix3ToMatrix4f(mat, hmdPoseRightEye); - } - } - -} +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.input.vr; + +import com.jme3.app.VREnvironment; +import com.jme3.math.Matrix4f; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; +import com.jme3.renderer.Camera; +import com.jme3.system.jopenvr.HmdMatrix34_t; +import com.jme3.system.jopenvr.HmdMatrix44_t; +import com.jme3.system.jopenvr.JOpenVRLibrary; +import com.jme3.system.jopenvr.OpenVRUtil; +import com.jme3.system.jopenvr.TrackedDevicePose_t; +import com.jme3.system.jopenvr.VR_IVRCompositor_FnTable; +import com.jme3.system.jopenvr.VR_IVRSystem_FnTable; +import com.jme3.util.VRUtil; +import com.sun.jna.Memory; +import com.sun.jna.Pointer; +import com.sun.jna.ptr.FloatByReference; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.LongByReference; + +import java.nio.IntBuffer; +import java.util.Locale; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * A class that wraps an OpenVR system. + * @author reden - phr00t - https://github.com/phr00t + * @author Julien Seinturier - (c) 2016 - JOrigin project - http:/www.jorigin.org + */ +public class OpenVR implements VRAPI { + + private static final Logger logger = Logger.getLogger(OpenVR.class.getName()); + + private static VR_IVRCompositor_FnTable compositorFunctions; + private static VR_IVRSystem_FnTable vrsystemFunctions; + + private static boolean initSuccess = false; + private static boolean flipEyes = false; + + private IntBuffer hmdDisplayFrequency; + private TrackedDevicePose_t.ByReference hmdTrackedDevicePoseReference; + protected TrackedDevicePose_t[] hmdTrackedDevicePoses; + + protected IntByReference hmdErrorStore; + + private final Quaternion rotStore = new Quaternion(); + private final Vector3f posStore = new Vector3f(); + + private static FloatByReference tlastVsync; + + /** + * The actual frame count. + */ + public static LongByReference _tframeCount; + + // for debugging latency + private int frames = 0; + + protected Matrix4f[] poseMatrices; + + private final Matrix4f hmdPose = Matrix4f.IDENTITY.clone(); + private Matrix4f hmdProjectionLeftEye; + private Matrix4f hmdProjectionRightEye; + private Matrix4f hmdPoseLeftEye; + private Matrix4f hmdPoseRightEye; + + private Vector3f hmdPoseLeftEyeVec, hmdPoseRightEyeVec, hmdSeatToStand; + + private float vsyncToPhotons; + private double timePerFrame, frameCountRun; + private long frameCount; + private OpenVRInput VRinput; + + + private VREnvironment environment = null; + + /** + * Create a new OpenVR system + * attached to the given {@link VREnvironment VR environment}. + * @param environment the VR environment to which this API is attached. + */ + public OpenVR(VREnvironment environment){ + this.environment = environment; + } + + @Override + public OpenVRInput getVRinput() { + return VRinput; + } + + @Override + public VR_IVRSystem_FnTable getVRSystem() { + return vrsystemFunctions; + } + + @Override + public VR_IVRCompositor_FnTable getCompositor() { + return compositorFunctions; + } + + @Override + public String getName() { + return "OpenVR"; + } + + private static long latencyWaitTime = 0; + + @Override + public void setFlipEyes(boolean set) { + flipEyes = set; + } + + private boolean enableDebugLatency = false; + + @Override + public void printLatencyInfoToConsole(boolean set) { + enableDebugLatency = set; + } + + @Override + public int getDisplayFrequency() { + if( hmdDisplayFrequency == null ) return 0; + return hmdDisplayFrequency.get(0); + } + + @Override + public boolean initialize() { + + logger.config("Initializing OpenVR system..."); + + hmdErrorStore = new IntByReference(); + vrsystemFunctions = null; + JOpenVRLibrary.VR_InitInternal(hmdErrorStore, JOpenVRLibrary.EVRApplicationType.EVRApplicationType_VRApplication_Scene); + if( hmdErrorStore.getValue() == 0 ) { + vrsystemFunctions = new VR_IVRSystem_FnTable(JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVRSystem_Version, hmdErrorStore).getPointer()); + } + + if( vrsystemFunctions == null || hmdErrorStore.getValue() != 0 ) { + logger.severe("OpenVR Initialize Result: " + JOpenVRLibrary.VR_GetVRInitErrorAsEnglishDescription(hmdErrorStore.getValue()).getString(0)); + logger.severe("Initializing OpenVR system [FAILED]"); + return false; + } else { + logger.config("OpenVR initialized & VR connected."); + + vrsystemFunctions.setAutoSynch(false); + vrsystemFunctions.read(); + + tlastVsync = new FloatByReference(); + _tframeCount = new LongByReference(); + + hmdDisplayFrequency = IntBuffer.allocate(1); + hmdDisplayFrequency.put( (int) JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_DisplayFrequency_Float); + hmdTrackedDevicePoseReference = new TrackedDevicePose_t.ByReference(); + hmdTrackedDevicePoses = (TrackedDevicePose_t[])hmdTrackedDevicePoseReference.toArray(JOpenVRLibrary.k_unMaxTrackedDeviceCount); + poseMatrices = new Matrix4f[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; + for(int i=0;i 0 ) VRUtil.sleepNanos(latencyWaitTime); + + vrsystemFunctions.GetTimeSinceLastVsync.apply(tlastVsync, _tframeCount); + float fSecondsUntilPhotons = (float)timePerFrame - tlastVsync.getValue() + vsyncToPhotons; + + if( enableDebugLatency ) { + if( frames == 10 ) { + System.out.println("Waited (nanos): " + Long.toString(latencyWaitTime)); + System.out.println("Predict ahead time: " + Float.toString(fSecondsUntilPhotons)); + } + frames = (frames + 1) % 60; + } + + // handle skipping frame stuff + long nowCount = _tframeCount.getValue(); + if( nowCount - frameCount > 1 ) { + // skipped a frame! + if( enableDebugLatency ) System.out.println("Frame skipped!"); + frameCountRun = 0; + if( latencyWaitTime > 0 ) { + latencyWaitTime -= TimeUnit.MILLISECONDS.toNanos(1); + if( latencyWaitTime < 0 ) latencyWaitTime = 0; + } + } else if( latencyWaitTime < timePerFrame * 1000000000.0 ) { + // didn't skip a frame, lets try waiting longer to improve latency + frameCountRun++; + latencyWaitTime += Math.round(Math.pow(frameCountRun / 10.0, 2.0)); + } + + frameCount = nowCount; + + vrsystemFunctions.GetDeviceToAbsoluteTrackingPose.apply( + environment.isSeatedExperience()?JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated: + JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding, + fSecondsUntilPhotons, hmdTrackedDevicePoseReference, JOpenVRLibrary.k_unMaxTrackedDeviceCount); + } + + // deal with controllers being plugged in and out + // causing an invalid memory crash... skipping for now + /*boolean hasEvent = false; + while( JOpenVRLibrary.VR_IVRSystem_PollNextEvent(OpenVR.getVRSystemInstance(), tempEvent) != 0 ) { + // wait until the events are clear.. + hasEvent = true; + } + if( hasEvent ) { + // an event probably changed controller state + VRInput._updateConnectedControllers(); + }*/ + //update controllers pose information + environment.getVRinput().updateControllerStates(); + + // read pose data from native + for (int nDevice = 0; nDevice < JOpenVRLibrary.k_unMaxTrackedDeviceCount; ++nDevice ){ + hmdTrackedDevicePoses[nDevice].readField("bPoseIsValid"); + if( hmdTrackedDevicePoses[nDevice].bPoseIsValid != 0 ){ + hmdTrackedDevicePoses[nDevice].readField("mDeviceToAbsoluteTracking"); + VRUtil.convertSteamVRMatrix3ToMatrix4f(hmdTrackedDevicePoses[nDevice].mDeviceToAbsoluteTracking, poseMatrices[nDevice]); + } + } + + if ( hmdTrackedDevicePoses[JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd].bPoseIsValid != 0 ){ + hmdPose.set(poseMatrices[JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd]); + } else { + hmdPose.set(Matrix4f.IDENTITY); + } + } + + @Override + public Matrix4f getHMDMatrixProjectionLeftEye(Camera cam){ + if( hmdProjectionLeftEye != null ) { + return hmdProjectionLeftEye; + } else if(vrsystemFunctions == null){ + return cam.getProjectionMatrix(); + } else { + HmdMatrix44_t mat = vrsystemFunctions.GetProjectionMatrix.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Left, cam.getFrustumNear(), cam.getFrustumFar()); + hmdProjectionLeftEye = new Matrix4f(); + VRUtil.convertSteamVRMatrix4ToMatrix4f(mat, hmdProjectionLeftEye); + return hmdProjectionLeftEye; + } + } + + @Override + public Matrix4f getHMDMatrixProjectionRightEye(Camera cam){ + if( hmdProjectionRightEye != null ) { + return hmdProjectionRightEye; + } else if(vrsystemFunctions == null){ + return cam.getProjectionMatrix(); + } else { + HmdMatrix44_t mat = vrsystemFunctions.GetProjectionMatrix.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Right, cam.getFrustumNear(), cam.getFrustumFar()); + hmdProjectionRightEye = new Matrix4f(); + VRUtil.convertSteamVRMatrix4ToMatrix4f(mat, hmdProjectionRightEye); + return hmdProjectionRightEye; + } + } + + @Override + public Vector3f getHMDVectorPoseLeftEye() { + if( hmdPoseLeftEyeVec == null ) { + hmdPoseLeftEyeVec = getHMDMatrixPoseLeftEye().toTranslationVector(); + // set default IPD if none or broken + if( hmdPoseLeftEyeVec.x <= 0.080f * -0.5f || hmdPoseLeftEyeVec.x >= 0.040f * -0.5f ) { + hmdPoseLeftEyeVec.x = 0.065f * -0.5f; + } + if( flipEyes == false ) hmdPoseLeftEyeVec.x *= -1f; // it seems these need flipping + } + return hmdPoseLeftEyeVec; + } + + @Override + public Vector3f getHMDVectorPoseRightEye() { + if( hmdPoseRightEyeVec == null ) { + hmdPoseRightEyeVec = getHMDMatrixPoseRightEye().toTranslationVector(); + // set default IPD if none or broken + if( hmdPoseRightEyeVec.x >= 0.080f * 0.5f || hmdPoseRightEyeVec.x <= 0.040f * 0.5f ) { + hmdPoseRightEyeVec.x = 0.065f * 0.5f; + } + if( flipEyes == false ) hmdPoseRightEyeVec.x *= -1f; // it seems these need flipping + } + return hmdPoseRightEyeVec; + } + + @Override + public Vector3f getSeatedToAbsolutePosition() { + if( environment.isSeatedExperience() == false ) return Vector3f.ZERO; + if( hmdSeatToStand == null ) { + hmdSeatToStand = new Vector3f(); + HmdMatrix34_t mat = vrsystemFunctions.GetSeatedZeroPoseToStandingAbsoluteTrackingPose.apply(); + Matrix4f tempmat = new Matrix4f(); + VRUtil.convertSteamVRMatrix3ToMatrix4f(mat, tempmat); + tempmat.toTranslationVector(hmdSeatToStand); + } + return hmdSeatToStand; + } + + @Override + public Matrix4f getHMDMatrixPoseLeftEye(){ + if( hmdPoseLeftEye != null ) { + return hmdPoseLeftEye; + } else if(vrsystemFunctions == null) { + return Matrix4f.IDENTITY; + } else { + HmdMatrix34_t mat = vrsystemFunctions.GetEyeToHeadTransform.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Left); + hmdPoseLeftEye = new Matrix4f(); + return VRUtil.convertSteamVRMatrix3ToMatrix4f(mat, hmdPoseLeftEye); + } + } + + @Override + public HmdType getType() { + if( vrsystemFunctions != null ) { + Pointer str1 = new Memory(128); + Pointer str2 = new Memory(128); + String completeName = ""; + vrsystemFunctions.GetStringTrackedDeviceProperty.apply(JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd, + JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_ManufacturerName_String, + str1, 128, hmdErrorStore); + if( hmdErrorStore.getValue() == 0 ) completeName += str1.getString(0); + vrsystemFunctions.GetStringTrackedDeviceProperty.apply(JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd, + JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_ModelNumber_String, + str2, 128, hmdErrorStore); + if( hmdErrorStore.getValue() == 0 ) completeName += " " + str2.getString(0); + if( completeName.length() > 0 ) { + completeName = completeName.toLowerCase(Locale.ENGLISH).trim(); + if( completeName.contains("htc") || completeName.contains("vive") ) { + return HmdType.HTC_VIVE; + } else if( completeName.contains("osvr") ) { + return HmdType.OSVR; + } else if( completeName.contains("oculus") || completeName.contains("rift") || + completeName.contains("dk1") || completeName.contains("dk2") || completeName.contains("cv1") ) { + return HmdType.OCULUS_RIFT; + } else if( completeName.contains("fove") ) { + return HmdType.FOVE; + } else if( completeName.contains("game") && completeName.contains("face") ) { + return HmdType.GAMEFACE; + } else if( completeName.contains("morpheus") ) { + return HmdType.MORPHEUS; + } else if( completeName.contains("gear") ) { + return HmdType.GEARVR; + } else if( completeName.contains("star") ) { + return HmdType.STARVR; + } else if( completeName.contains("null") ) { + return HmdType.NULL; + } + } + } else return HmdType.NONE; + return HmdType.OTHER; + } + + @Override + public Matrix4f getHMDMatrixPoseRightEye(){ + if( hmdPoseRightEye != null ) { + return hmdPoseRightEye; + } else if(vrsystemFunctions == null) { + return Matrix4f.IDENTITY; + } else { + HmdMatrix34_t mat = vrsystemFunctions.GetEyeToHeadTransform.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Right); + hmdPoseRightEye = new Matrix4f(); + return VRUtil.convertSteamVRMatrix3ToMatrix4f(mat, hmdPoseRightEye); + } + } + +} diff --git a/jme3-vr/src/main/java/com/jme3/input/vr/OpenVRInput.java b/jme3-vr/src/main/java/com/jme3/input/vr/OpenVRInput.java index b4b5cdce5..2f9b81e95 100644 --- a/jme3-vr/src/main/java/com/jme3/input/vr/OpenVRInput.java +++ b/jme3-vr/src/main/java/com/jme3/input/vr/OpenVRInput.java @@ -5,6 +5,7 @@ */ package com.jme3.input.vr; +import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -183,28 +184,50 @@ public class OpenVRInput implements VRInputAPI { @Override public Vector3f getVelocity(int controllerIndex) { - int index = OpenVRInput.controllerIndex[controllerIndex]; - if( needsNewVelocity[index] ) { - OpenVR.hmdTrackedDevicePoses[index].readField("vVelocity"); - needsNewVelocity[index] = false; - } - tempVel.x = OpenVR.hmdTrackedDevicePoses[index].vVelocity.v[0]; - tempVel.y = OpenVR.hmdTrackedDevicePoses[index].vVelocity.v[1]; - tempVel.z = OpenVR.hmdTrackedDevicePoses[index].vVelocity.v[2]; - return tempVel; + + if (environment != null){ + + if (environment.getVRHardware() instanceof OpenVR){ + int index = OpenVRInput.controllerIndex[controllerIndex]; + if( needsNewVelocity[index] ) { + ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].readField("vVelocity"); + needsNewVelocity[index] = false; + } + tempVel.x = ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].vVelocity.v[0]; + tempVel.y = ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].vVelocity.v[1]; + tempVel.z = ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].vVelocity.v[2]; + return tempVel; + } else { + throw new IllegalStateException("VR hardware "+environment.getVRHardware().getClass().getSimpleName()+" is not a subclass of "+OpenVR.class.getSimpleName()); + } + } else { + throw new IllegalStateException("VR input is not attached to a VR environment."); + } } @Override public Vector3f getAngularVelocity(int controllerIndex) { - int index = OpenVRInput.controllerIndex[controllerIndex]; - if( needsNewAngVelocity[index] ) { - OpenVR.hmdTrackedDevicePoses[index].readField("vAngularVelocity"); - needsNewAngVelocity[index] = false; - } - tempVel.x = OpenVR.hmdTrackedDevicePoses[index].vAngularVelocity.v[0]; - tempVel.y = OpenVR.hmdTrackedDevicePoses[index].vAngularVelocity.v[1]; - tempVel.z = OpenVR.hmdTrackedDevicePoses[index].vAngularVelocity.v[2]; - return tempVel; + + if (environment != null){ + + if (environment.getVRHardware() instanceof OpenVR){ + + int index = OpenVRInput.controllerIndex[controllerIndex]; + if( needsNewAngVelocity[index] ) { + ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].readField("vAngularVelocity"); + needsNewAngVelocity[index] = false; + } + tempVel.x = ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].vAngularVelocity.v[0]; + tempVel.y = ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].vAngularVelocity.v[1]; + tempVel.z = ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[index].vAngularVelocity.v[2]; + return tempVel; + } else { + throw new IllegalStateException("VR hardware "+environment.getVRHardware().getClass().getSimpleName()+" is not a subclass of "+OpenVR.class.getSimpleName()); + } + } else { + throw new IllegalStateException("VR input is not attached to a VR environment."); + } + } @Override @@ -309,7 +332,16 @@ public class OpenVRInput implements VRInputAPI { return false; } - return OpenVR.hmdTrackedDevicePoses[controllerIndex[index]].bPoseIsValid != 0; + if (environment != null){ + + if (environment.getVRHardware() instanceof OpenVR){ + return ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[controllerIndex[index]].bPoseIsValid != 0; + } else { + throw new IllegalStateException("VR hardware "+environment.getVRHardware().getClass().getSimpleName()+" is not a subclass of "+OpenVR.class.getSimpleName()); + } + } else { + throw new IllegalStateException("VR input is not attached to a VR environment."); + } } @Override @@ -317,9 +349,19 @@ public class OpenVRInput implements VRInputAPI { if( isInputDeviceTracking(index) == false ){ return null; } - index = controllerIndex[index]; - VRUtil.convertMatrix4toQuat(OpenVR.poseMatrices[index], rotStore[index]); - return rotStore[index]; + + if (environment != null){ + + if (environment.getVRHardware() instanceof OpenVR){ + index = controllerIndex[index]; + VRUtil.convertMatrix4toQuat(((OpenVR)environment.getVRHardware()).poseMatrices[index], rotStore[index]); + return rotStore[index]; + } else { + throw new IllegalStateException("VR hardware "+environment.getVRHardware().getClass().getSimpleName()+" is not a subclass of "+OpenVR.class.getSimpleName()); + } + } else { + throw new IllegalStateException("VR input is not attached to a VR environment."); + } } @Override @@ -328,12 +370,23 @@ public class OpenVRInput implements VRInputAPI { return null; } - // the hmdPose comes in rotated funny, fix that here - index = controllerIndex[index]; - OpenVR.poseMatrices[index].toTranslationVector(posStore[index]); - posStore[index].x = -posStore[index].x; - posStore[index].z = -posStore[index].z; - return posStore[index]; + if (environment != null){ + + if (environment.getVRHardware() instanceof OpenVR){ + // the hmdPose comes in rotated funny, fix that here + index = controllerIndex[index]; + ((OpenVR)environment.getVRHardware()).poseMatrices[index].toTranslationVector(posStore[index]); + posStore[index].x = -posStore[index].x; + posStore[index].z = -posStore[index].z; + return posStore[index]; + } else { + throw new IllegalStateException("VR hardware "+environment.getVRHardware().getClass().getSimpleName()+" is not a subclass of "+OpenVR.class.getSimpleName()); + } + } else { + throw new IllegalStateException("VR input is not attached to a VR environment."); + } + + } @Override @@ -411,9 +464,9 @@ public class OpenVRInput implements VRInputAPI { if (environment != null){ controllerCount = 0; for(int i=0;i(JOpenVRLibrary.k_unMaxTrackedDeviceCount); + } + trackedControllers.add(new OpenVRTrackedController(i, this, controllerName, manufacturerName, environment)); + // Send an Haptic pulse to the controller triggerHapticPulse(controllerCount, 1.0f); diff --git a/jme3-vr/src/main/java/com/jme3/input/vr/OpenVRTrackedController.java b/jme3-vr/src/main/java/com/jme3/input/vr/OpenVRTrackedController.java new file mode 100644 index 000000000..026830604 --- /dev/null +++ b/jme3-vr/src/main/java/com/jme3/input/vr/OpenVRTrackedController.java @@ -0,0 +1,93 @@ +package com.jme3.input.vr; + +import com.jme3.app.VREnvironment; +import com.jme3.math.Matrix4f; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; + +public class OpenVRTrackedController implements VRTrackedController{ + + /** + * The index of the controller within the unserlying VR API. + */ + private int controllerIndex = -1; + + /** + * The underlying VRAPI. + */ + private OpenVRInput hardware = null; + + /** + * The name of the controller. + */ + private String name; + + private VREnvironment environment; + + /** + * Wrap a new VR tracked controller on an OpenVR system. + * @param controllerIndex the index of the controller within the underlying VR system. + * @param hardware the underlying VR system. + * @param name the name of the controller. + * @param manufacturer the manufacturer of the controller. + * @param environment the VR environment. + */ + public OpenVRTrackedController(int controllerIndex, OpenVRInput hardware, String name, String manufacturer, VREnvironment environment){ + this.controllerIndex = controllerIndex; + this.hardware = hardware; + + this.name = name; + this.manufacturer = manufacturer; + + this.environment = environment; + } + + /** + * The manufacturer of the controller. + */ + private String manufacturer; + + @Override + public Vector3f getPosition() { + if (hardware != null){ + return hardware.getPosition(controllerIndex); + } else { + throw new IllegalStateException("No underlying VR API."); + } + } + + @Override + public Quaternion getOrientation() { + if (hardware != null){ + return hardware.getOrientation(controllerIndex); + } else { + throw new IllegalStateException("No underlying VR API."); + } + } + + @Override + public Matrix4f getPose(){ + + if (environment != null){ + if (hardware != null){ + return ((OpenVR)environment.getVRHardware()).poseMatrices[controllerIndex]; + } else { + throw new IllegalStateException("No underlying VR API."); + } + } else { + throw new IllegalStateException("VR tracked device is not attached to any environment."); + } + + + } + + @Override + public String getControllerName() { + return name; + } + + @Override + public String getControllerManufacturer() { + return manufacturer; + } +} diff --git a/jme3-vr/src/main/java/com/jme3/input/vr/VRBounds.java b/jme3-vr/src/main/java/com/jme3/input/vr/VRBounds.java index 15ce659ea..0f81b4105 100644 --- a/jme3-vr/src/main/java/com/jme3/input/vr/VRBounds.java +++ b/jme3-vr/src/main/java/com/jme3/input/vr/VRBounds.java @@ -16,19 +16,19 @@ public class VRBounds { private static Logger logger = Logger.getLogger(VRBounds.class.getName()); - private static VR_IVRChaperone_FnTable vrChaperone; - private static Vector2f playSize; + private VR_IVRChaperone_FnTable vrChaperone; + private Vector2f playSize; /** * Initialize the VR bounds. * @return true if the initialization is a success and false otherwise. */ - public static boolean init() { + public boolean init(OpenVR api) { logger.config("Initialize VR bounds..."); if( vrChaperone == null ) { - vrChaperone = new VR_IVRChaperone_FnTable(JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVRChaperone_Version, OpenVR.hmdErrorStore).getPointer()); + vrChaperone = new VR_IVRChaperone_FnTable(JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVRChaperone_Version, api.hmdErrorStore).getPointer()); if( vrChaperone != null ) { vrChaperone.setAutoSynch(false); vrChaperone.read(); @@ -53,7 +53,7 @@ public class VRBounds { * Get the size of the VR world. * @return the size of the VR world. */ - public static Vector2f getPlaySize() { + public Vector2f getPlaySize() { return playSize; } diff --git a/jme3-vr/src/main/java/com/jme3/input/vr/VRTrackedController.java b/jme3-vr/src/main/java/com/jme3/input/vr/VRTrackedController.java index 5fb2572a0..3ce20e5c0 100644 --- a/jme3-vr/src/main/java/com/jme3/input/vr/VRTrackedController.java +++ b/jme3-vr/src/main/java/com/jme3/input/vr/VRTrackedController.java @@ -1,5 +1,9 @@ package com.jme3.input.vr; +import com.jme3.math.Matrix4f; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; + /** * TODO * @author Julien Seinturier - (c) 2016 - JOrigin project - http:/www.jorigin.org @@ -7,4 +11,40 @@ package com.jme3.input.vr; */ public interface VRTrackedController { + /** + * Get the controller name. + * @return the controller name. + */ + public String getControllerName(); + + /** + * Get the controller manufacturer. + * @return the controller manufacturer. + */ + public String getControllerManufacturer(); + + /** + * Get the position of the tracked device. This value is the translation component of the device {@link #getPose() pose}. + * @return the position of the tracked device. + * @see #getOrientation() + * @see #getPose() + */ + public Vector3f getPosition(); + + /** + * Get the orientation of the tracked device. This value is the rotation component of the device {@link #getPose() pose}. + * @return the orientation of the tracked device. + * @see #getPosition() + * @see #getPose() + */ + public Quaternion getOrientation(); + + /** + * Get the pose of the tracked device. + * The pose is a 4x4 matrix than combine the {@link #getPosition() position} and the {@link #getOrientation() orientation} of the device. + * @return the pose of the tracked device. + * @see #getPosition() + * @see #getOrientation() + */ + public Matrix4f getPose(); } diff --git a/jme3-vr/src/main/java/com/jme3/util/AbstractVRViewManager.java b/jme3-vr/src/main/java/com/jme3/util/AbstractVRViewManager.java index 7a9b5ea56..f4f7e7f91 100644 --- a/jme3-vr/src/main/java/com/jme3/util/AbstractVRViewManager.java +++ b/jme3-vr/src/main/java/com/jme3/util/AbstractVRViewManager.java @@ -28,18 +28,20 @@ public abstract class AbstractVRViewManager implements VRViewManager { protected VREnvironment environment = null; protected Camera leftCamera; - protected ViewPort leftViewport; + protected ViewPort leftViewPort; protected FilterPostProcessor leftPostProcessor; protected Texture2D leftEyeTexture; protected Texture2D leftEyeDepth; protected Camera rightCamera; - protected ViewPort rightViewport; + protected ViewPort rightViewPort; protected FilterPostProcessor rightPostProcessor; protected Texture2D rightEyeTexture; protected Texture2D rightEyeDepth; - private float resMult = 1f; + protected ViewPort mirrorViewPort; + + private float resMult = 1f; private float heightAdjustment; @@ -54,15 +56,24 @@ public abstract class AbstractVRViewManager implements VRViewManager { } @Override - public ViewPort getLeftViewport() { - return leftViewport; + public ViewPort getLeftViewPort() { + return leftViewPort; } @Override - public ViewPort getRightViewport() { - return rightViewport; + public ViewPort getRightViewPort() { + return rightViewPort; } + /** + * Get the {@link ViewPort view port} attached to the mirror display. + * @return the view port attached to the mirror display. + */ + public ViewPort getMirrorViewPort() { + return mirrorViewPort; + } + + @Override public Texture2D getLeftTexture(){ return leftEyeTexture; @@ -124,7 +135,7 @@ public abstract class AbstractVRViewManager implements VRViewManager { public void moveScreenProcessingToEyes() { if (environment != null){ - if( getRightViewport() == null ){ + if( getRightViewPort() == null ){ return; } @@ -150,7 +161,7 @@ public abstract class AbstractVRViewManager implements VRViewManager { public void syncScreenProcessing(ViewPort sourceViewport) { if (environment != null){ - if( getRightViewport() == null ){ + if( getRightViewPort() == null ){ return; } @@ -163,13 +174,13 @@ public abstract class AbstractVRViewManager implements VRViewManager { // clear out all filters & processors, to start from scratch getRightPostProcessor().removeAllFilters(); getLeftPostProcessor().removeAllFilters(); - getLeftViewport().clearProcessors(); - getRightViewport().clearProcessors(); + getLeftViewPort().clearProcessors(); + getRightViewPort().clearProcessors(); // if we have no processors to sync, don't add the FilterPostProcessor if( sourceViewport.getProcessors().isEmpty() ) return; // add post processors we just made, which are empty - getLeftViewport().addProcessor(getLeftPostProcessor()); - getRightViewport().addProcessor(getRightPostProcessor()); + getLeftViewPort().addProcessor(getLeftPostProcessor()); + getRightViewPort().addProcessor(getRightPostProcessor()); // go through all of the filters in the processors list // add them to the left viewport processor & clone them to the right for(SceneProcessor sceneProcessor : sourceViewport.getProcessors()) { @@ -202,8 +213,8 @@ public abstract class AbstractVRViewManager implements VRViewManager { VRDirectionalLightShadowRenderer dlsr = (VRDirectionalLightShadowRenderer) sceneProcessor; VRDirectionalLightShadowRenderer dlsrRight = dlsr.clone(); dlsrRight.setLight(dlsr.getLight()); - getRightViewport().getProcessors().add(0, dlsrRight); - getLeftViewport().getProcessors().add(0, sceneProcessor); + getRightViewPort().getProcessors().add(0, dlsrRight); + getLeftViewPort().getProcessors().add(0, sceneProcessor); } } // make sure each has a translucent filter renderer diff --git a/jme3-vr/src/main/java/com/jme3/util/VRViewManager.java b/jme3-vr/src/main/java/com/jme3/util/VRViewManager.java index e2c503006..58a6c166e 100644 --- a/jme3-vr/src/main/java/com/jme3/util/VRViewManager.java +++ b/jme3-vr/src/main/java/com/jme3/util/VRViewManager.java @@ -42,17 +42,25 @@ public interface VRViewManager { /** * Get the {@link ViewPort viewport} attached to the left eye. * @return the {@link ViewPort viewport} attached to the left eye. - * @see #getRightViewport() + * @see #getRightViewPort() */ - public ViewPort getLeftViewport(); + public ViewPort getLeftViewPort(); /** * Get the {@link ViewPort viewport} attached to the right eye. * @return the {@link ViewPort viewport} attached to the right eye. - * @see #getLeftViewport() + * @see #getLeftViewPort() */ - public ViewPort getRightViewport(); + public ViewPort getRightViewPort(); + + /** + * Get the {@link ViewPort view port} attached to the mirror display. + * @return the view port attached to the mirror display. + * @see #getLeftViewPort() + * @see #getRightViewPort() + */ + public ViewPort getMirrorViewPort(); /** * Get the texture attached to the left eye. diff --git a/jme3-vr/src/main/java/com/jme3/util/VRViewManagerOSVR.java b/jme3-vr/src/main/java/com/jme3/util/VRViewManagerOSVR.java index 9b78396e5..e3d85406e 100644 --- a/jme3-vr/src/main/java/com/jme3/util/VRViewManagerOSVR.java +++ b/jme3-vr/src/main/java/com/jme3/util/VRViewManagerOSVR.java @@ -117,18 +117,18 @@ public class VRViewManagerOSVR extends AbstractVRViewManager{ /** * Get the {@link ViewPort viewport} attached to the left eye. * @return the {@link ViewPort viewport} attached to the left eye. - * @see #getRightViewport() + * @see #getRightViewPort() */ - public ViewPort getLeftViewport() { + public ViewPort getLeftViewPort() { return leftViewport; } /** * Get the {@link ViewPort viewport} attached to the right eye. * @return the {@link ViewPort viewport} attached to the right eye. - * @see #getLeftViewport() + * @see #getLeftViewPort() */ - public ViewPort getRightViewport() { + public ViewPort getRightViewPort() { return rightViewport; } diff --git a/jme3-vr/src/main/java/com/jme3/util/VRViewManagerOpenVR.java b/jme3-vr/src/main/java/com/jme3/util/VRViewManagerOpenVR.java index 49d08578b..545754a59 100644 --- a/jme3-vr/src/main/java/com/jme3/util/VRViewManagerOpenVR.java +++ b/jme3-vr/src/main/java/com/jme3/util/VRViewManagerOpenVR.java @@ -7,6 +7,7 @@ package com.jme3.util; import com.jme3.app.VREnvironment; import com.jme3.input.vr.OpenVR; import com.jme3.input.vr.VRAPI; +import com.jme3.input.vr.VRTrackedController; import com.jme3.material.Material; import com.jme3.math.ColorRGBA; import com.jme3.math.Quaternion; @@ -346,10 +347,10 @@ public class VRViewManagerOpenVR extends AbstractVRViewManager { return; } - leftEyeTexture = (Texture2D) getLeftViewport().getOutputFrameBuffer().getColorBuffer().getTexture(); - rightEyeTexture = (Texture2D)getRightViewport().getOutputFrameBuffer().getColorBuffer().getTexture(); - leftEyeDepth = (Texture2D) getLeftViewport().getOutputFrameBuffer().getDepthBuffer().getTexture(); - rightEyeDepth = (Texture2D)getRightViewport().getOutputFrameBuffer().getDepthBuffer().getTexture(); + leftEyeTexture = (Texture2D) getLeftViewPort().getOutputFrameBuffer().getColorBuffer().getTexture(); + rightEyeTexture = (Texture2D)getRightViewPort().getOutputFrameBuffer().getColorBuffer().getTexture(); + leftEyeDepth = (Texture2D) getLeftViewPort().getOutputFrameBuffer().getDepthBuffer().getTexture(); + rightEyeDepth = (Texture2D)getRightViewPort().getOutputFrameBuffer().getDepthBuffer().getTexture(); // main viewport is either going to be a distortion scene or nothing // mirroring is handled by copying framebuffers @@ -387,6 +388,7 @@ public class VRViewManagerOpenVR extends AbstractVRViewManager { if( environment.getApplication().getContext().getSettings().isSwapBuffers() ) { setupMirrorBuffers(environment.getCamera(), leftEyeTexture, false); + } } else { throw new IllegalStateException("This VR environment is not attached to any application."); @@ -414,9 +416,35 @@ public class VRViewManagerOpenVR extends AbstractVRViewManager { // grab the hardware handle VRAPI dev = environment.getVRHardware(); if( dev != null ) { + + // update the HMD's position & orientation dev.updatePose(); dev.getPositionAndOrientation(hmdPos, hmdRot); +/* + // TOREMOVE + Vector3f v = dev.getVRinput().getTrackedController(0).getPosition(); + Quaternion q = dev.getVRinput().getTrackedController(0).getOrientation(); + if ((v != null)&&(q != null)){ + hmdPos.set(v); + hmdRot.set(q); + } + + logger.severe("HMD controller "); + logger.severe(" Position "+hmdPos); + logger.severe(" Orientation "+hmdRot); + + VRTrackedController tc = null; + for(int i = 0; i < dev.getVRinput().getTrackedControllerCount(); i++){ + tc = dev.getVRinput().getTrackedController(i); + logger.severe("Tracked controller "+i+": "+tc.getControllerName()); + logger.severe(" Position "+tc.getPosition()); + logger.severe(" Orientation "+tc.getOrientation()); + logger.severe(""); + } +*/ + // TOREMOVE + if( obs != null ) { // update hmdPos based on obs rotation finalRotation.set(objRot); @@ -490,18 +518,18 @@ public class VRViewManagerOpenVR extends AbstractVRViewManager { //org.lwjgl.opengl.GL11.glEnable(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_SRGB); if( !environment.isInstanceRendering()) { - leftViewport = setupViewBuffers(getLeftCamera(), LEFT_VIEW_NAME); + leftViewPort = setupViewBuffers(getLeftCamera(), LEFT_VIEW_NAME); rightCamera = getLeftCamera().clone(); if( environment.getVRHardware() != null ){ getRightCamera().setProjectionMatrix(environment.getVRHardware().getHMDMatrixProjectionRightEye(getRightCamera())); } - rightViewport = setupViewBuffers(getRightCamera(), RIGHT_VIEW_NAME); + rightViewPort = setupViewBuffers(getRightCamera(), RIGHT_VIEW_NAME); } else { if (environment.getApplication() != null){ logger.severe("THIS CODE NEED CHANGES !!!"); - leftViewport = environment.getApplication().getViewPort(); + leftViewPort = environment.getApplication().getViewPort(); //leftViewport.attachScene(app.getRootNode()); rightCamera = getLeftCamera().clone(); if( environment.getVRHardware() != null ){ @@ -520,7 +548,7 @@ public class VRViewManagerOpenVR extends AbstractVRViewManager { } // setup gui - environment.getVRGUIManager().setupGui(getLeftCamera(), getRightCamera(), getLeftViewport(), getRightViewport()); + environment.getVRGUIManager().setupGui(getLeftCamera(), getRightCamera(), getLeftViewPort(), getRightViewPort()); if( environment.getVRHardware() != null ) { // call these to cache the results internally