From 651e77953a63e6ef3de91b6197da8ae8e6cbd8c2 Mon Sep 17 00:00:00 2001 From: seint Date: Thu, 13 Apr 2017 08:40:34 +0200 Subject: [PATCH 1/6] VR controller clean integration --- .../main/java/com/jme3/app/VRAppState.java | 12 +- .../main/java/com/jme3/app/VRApplication.java | 12 +- .../main/java/com/jme3/app/VREnvironment.java | 14 +++ .../main/java/com/jme3/input/vr/OpenVR.java | 37 +++--- .../java/com/jme3/input/vr/OpenVRInput.java | 115 +++++++++++++----- .../input/vr/OpenVRTrackedController.java | 93 ++++++++++++++ .../main/java/com/jme3/input/vr/VRBounds.java | 10 +- .../jme3/input/vr/VRTrackedController.java | 40 ++++++ .../com/jme3/util/AbstractVRViewManager.java | 41 ++++--- .../java/com/jme3/util/VRViewManager.java | 16 ++- .../java/com/jme3/util/VRViewManagerOSVR.java | 8 +- .../com/jme3/util/VRViewManagerOpenVR.java | 44 +++++-- 12 files changed, 348 insertions(+), 94 deletions(-) create mode 100644 jme3-vr/src/main/java/com/jme3/input/vr/OpenVRTrackedController.java 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 e9e6d0aac..006400604 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; @@ -27,6 +28,8 @@ public class VREnvironment { private VRGuiManager guiManager = null; 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}. @@ -73,6 +76,9 @@ public class VREnvironment { guiManager = new VRGuiManager(this); mouseManager = new VRMouseManager(this); + + bounds = new VRBounds(); + dummyCam = new Camera(); processSettings(); @@ -86,6 +92,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. 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..509e84987 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 @@ -46,14 +46,14 @@ public class OpenVR implements VRAPI { 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; + private IntBuffer hmdDisplayFrequency; + private TrackedDevicePose_t.ByReference hmdTrackedDevicePoseReference; + protected TrackedDevicePose_t[] hmdTrackedDevicePoses; - protected static IntByReference hmdErrorStore; + protected IntByReference hmdErrorStore; - private static final Quaternion rotStore = new Quaternion(); - private static final Vector3f posStore = new Vector3f(); + private final Quaternion rotStore = new Quaternion(); + private final Vector3f posStore = new Vector3f(); private static FloatByReference tlastVsync; @@ -65,20 +65,21 @@ public class OpenVR implements VRAPI { // for debugging latency private int frames = 0; - protected static Matrix4f[] poseMatrices; + protected 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 final Matrix4f hmdPose = Matrix4f.IDENTITY.clone(); + private Matrix4f hmdProjectionLeftEye; + private Matrix4f hmdProjectionRightEye; + private Matrix4f hmdPoseLeftEye; + private Matrix4f hmdPoseRightEye; - private static Vector3f hmdPoseLeftEyeVec, hmdPoseRightEyeVec, hmdSeatToStand; + private Vector3f hmdPoseLeftEyeVec, hmdPoseRightEyeVec, hmdSeatToStand; + + private float vsyncToPhotons; + private double timePerFrame, frameCountRun; + private long frameCount; + private OpenVRInput VRinput; - private static float vsyncToPhotons; - private static double timePerFrame, frameCountRun; - private static long frameCount; - private static OpenVRInput VRinput; private VREnvironment environment = null; @@ -181,7 +182,7 @@ public class OpenVR implements VRAPI { VRinput.updateConnectedControllers(); // init bounds & chaperone info - VRBounds.init(); + environment.getVRBounds().init(this); logger.config("Initializing OpenVR system [SUCCESS]"); initSuccess = true; 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 0c565d0a1..6336cb4d9 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 @@ -424,6 +477,12 @@ public class OpenVRInput implements VRInputAPI { controllerIndex[controllerCount] = i; + // Adding tracked controller to control. + if (trackedControllers == null){ + trackedControllers = new ArrayList(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 From 888b66892de7b8af2db4511da8352dcfcf4f6d27 Mon Sep 17 00:00:00 2001 From: seint Date: Thu, 13 Apr 2017 08:43:34 +0200 Subject: [PATCH 2/6] Ignoring .gitignore files --- .gitignore | 1 + 1 file changed, 1 insertion(+) 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 From 9e945462f74ffaff89c3416ae869d252043a7837 Mon Sep 17 00:00:00 2001 From: jseinturier Date: Thu, 13 Apr 2017 10:00:11 +0200 Subject: [PATCH 3/6] Conforming to last master branch --- .../main/java/com/jme3/app/VREnvironment.java | 21 +-- .../java/com/jme3/input/vr/OpenVRInput.java | 120 +++++------------- 2 files changed, 34 insertions(+), 107 deletions(-) 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 006400604..5358ff42a 100644 --- a/jme3-vr/src/main/java/com/jme3/app/VREnvironment.java +++ b/jme3-vr/src/main/java/com/jme3/app/VREnvironment.java @@ -8,7 +8,6 @@ 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,8 +27,6 @@ public class VREnvironment { private VRGuiManager guiManager = null; 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}. @@ -76,10 +73,7 @@ public class VREnvironment { guiManager = new VRGuiManager(this); mouseManager = new VRMouseManager(this); - - bounds = new VRBounds(); - - dummyCam = new Camera(); +// dummyCam = new Camera(settings.getWidth(), settings.getHeight()); processSettings(); } @@ -92,14 +86,6 @@ 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. @@ -346,7 +332,7 @@ public class VREnvironment { */ public Camera getCamera() { if( isInVR() && getVRViewManager() != null && getVRViewManager().getLeftCamera() != null ) { - return dummyCam; + return getDummyCamera(); } return application.getCamera(); @@ -361,13 +347,12 @@ public class VREnvironment { if (application.getCamera() != null){ dummyCam = application.getCamera().clone(); } else { - return new Camera(); + return new Camera(settings.getWidth(), settings.getHeight()); } } else { throw new IllegalStateException("VR environment is not attached to any application."); } } - return dummyCam; } 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 6336cb4d9..b5514afcc 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,7 +5,6 @@ */ package com.jme3.input.vr; -import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -184,50 +183,28 @@ public class OpenVRInput implements VRInputAPI { @Override public Vector3f getVelocity(int controllerIndex) { - - 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."); - } + 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; } @Override public Vector3f getAngularVelocity(int controllerIndex) { - - 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."); - } - + 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; } @Override @@ -332,16 +309,7 @@ public class OpenVRInput implements VRInputAPI { return false; } - 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."); - } + return OpenVR.hmdTrackedDevicePoses[controllerIndex[index]].bPoseIsValid != 0; } @Override @@ -349,19 +317,9 @@ public class OpenVRInput implements VRInputAPI { if( isInputDeviceTracking(index) == false ){ return null; } - - 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."); - } + index = controllerIndex[index]; + VRUtil.convertMatrix4toQuat(OpenVR.poseMatrices[index], rotStore[index]); + return rotStore[index]; } @Override @@ -370,23 +328,12 @@ public class OpenVRInput implements VRInputAPI { return null; } - 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."); - } - - + // 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]; } @Override @@ -464,7 +411,8 @@ 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); @@ -503,7 +445,7 @@ public class OpenVRInput implements VRInputAPI { if (environment != null){ for(int i=0;i Date: Thu, 13 Apr 2017 11:12:11 +0200 Subject: [PATCH 4/6] Conform to master... boring.... --- .../main/java/com/jme3/input/vr/OpenVR.java | 1049 ++++++++--------- 1 file changed, 524 insertions(+), 525 deletions(-) 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 509e84987..cb2042885 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,525 +1,524 @@ -/* - * 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); - } - } - -} +/* + * 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); + } + } + +} From 2cacf16f69c1a63616753fd2cf15115431b82192 Mon Sep 17 00:00:00 2001 From: jseinturier Date: Thu, 13 Apr 2017 11:13:52 +0200 Subject: [PATCH 5/6] Conform to... Oh you know what i mean... --- .../java/com/jme3/input/vr/OpenVRInput.java | 920 +++++++++--------- 1 file changed, 460 insertions(+), 460 deletions(-) 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 b5514afcc..b4b5cdce5 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 @@ -1,460 +1,460 @@ -/* - * 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 java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.jme3.app.VREnvironment; -import com.jme3.math.Quaternion; -import com.jme3.math.Vector2f; -import com.jme3.math.Vector3f; -import com.jme3.renderer.Camera; -import com.jme3.scene.Spatial; -import com.jme3.system.jopenvr.JOpenVRLibrary; -import com.jme3.system.jopenvr.OpenVRUtil; -import com.jme3.system.jopenvr.VRControllerState_t; -import com.jme3.system.jopenvr.VR_IVRSystem_FnTable; -import com.jme3.util.VRUtil; -import com.jme3.util.VRViewManagerOpenVR; - -/* -make helper functions to pull the following easily from raw data (DONE) - -trigger: -Controller#1, Axis#0 X: 0.0, Y: 0.0 -Controller#1, Axis#1 X: 1.0, Y: 0.0 -Controller#1, Axis#2 X: 0.0, Y: 0.0 -Controller#1, Axis#3 X: 0.0, Y: 0.0 -Controller#1, Axis#4 X: 0.0, Y: 0.0 -Button press: 8589934592 (when full), touch: 8589934592 - -touchpad (upper left): -Controller#1, Axis#0 X: -0.6059755, Y: 0.2301706 -Controller#1, Axis#1 X: 0.0, Y: 0.0 -Controller#1, Axis#2 X: 0.0, Y: 0.0 -Controller#1, Axis#3 X: 0.0, Y: 0.0 -Controller#1, Axis#4 X: 0.0, Y: 0.0 -Button press: 4294967296 (when pressed in), touch: 4294967296 - -grip: -Controller#1, Axis#0 X: 0.0, Y: 0.0 -Controller#1, Axis#1 X: 0.0, Y: 0.0 -Controller#1, Axis#2 X: 0.0, Y: 0.0 -Controller#1, Axis#3 X: 0.0, Y: 0.0 -Controller#1, Axis#4 X: 0.0, Y: 0.0 -Button press: 4, touch: 4 - -thumb: -Controller#1, Axis#0 X: 0.0, Y: 0.0 -Controller#1, Axis#1 X: 0.0, Y: 0.0 -Controller#1, Axis#2 X: 0.0, Y: 0.0 -Controller#1, Axis#3 X: 0.0, Y: 0.0 -Controller#1, Axis#4 X: 0.0, Y: 0.0 -Button press: 2, touch: 2 - -*/ - -/** - * A class that wraps an OpenVR input.
- * null values will be returned if no valid pose exists, or that input device isn't available - * user code should check for null values. - * @author reden - phr00t - https://github.com/phr00t - * @author Julien Seinturier - (c) 2016 - JOrigin project - http:/www.jorigin.org - */ -public class OpenVRInput implements VRInputAPI { - - private static final Logger logger = Logger.getLogger(OpenVRInput.class.getName()); - - private final VRControllerState_t[] cStates = new VRControllerState_t[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; - - private final Quaternion[] rotStore = new Quaternion[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; - - private final Vector3f[] posStore = new Vector3f[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; - - private static final int[] controllerIndex = new int[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; - - private int controllerCount = 0; - - private final Vector2f tempAxis = new Vector2f(), temp2Axis = new Vector2f(); - - private final Vector2f lastCallAxis[] = new Vector2f[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; - - private final boolean needsNewVelocity[] = new boolean[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; - - private final boolean needsNewAngVelocity[] = new boolean[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; - - private final boolean buttonDown[][] = new boolean[JOpenVRLibrary.k_unMaxTrackedDeviceCount][16]; - - private float axisMultiplier = 1f; - - private final Vector3f tempVel = new Vector3f(); - - private final Quaternion tempq = new Quaternion(); - - private VREnvironment environment; - - private List trackedControllers = null; - - /** - * Create a new OpenVR input attached to the given VR environment. - * @param environment the VR environment to which the input is attached. - */ - public OpenVRInput(VREnvironment environment){ - this.environment = environment; - } - - @Override - public float getAxisMultiplier() { - return axisMultiplier; - } - - @Override - public void setAxisMultiplier(float set) { - axisMultiplier = set; - } - - @Override - public void swapHands() { - if( controllerCount != 2 ) return; - int temp = controllerIndex[0]; - controllerIndex[0] = controllerIndex[1]; - controllerIndex[1] = temp; - } - - @Override - public boolean isButtonDown(int controllerIndex, VRInputType checkButton) { - VRControllerState_t cs = cStates[OpenVRInput.controllerIndex[controllerIndex]]; - switch( checkButton ) { - default: - return false; - case ViveGripButton: - return (cs.ulButtonPressed & 4) != 0; - case ViveMenuButton: - return (cs.ulButtonPressed & 2) != 0; - case ViveTrackpadAxis: - return (cs.ulButtonPressed & 4294967296l) != 0; - case ViveTriggerAxis: - return (cs.ulButtonPressed & 8589934592l) != 0; - } - } - - @Override - public boolean wasButtonPressedSinceLastCall(int controllerIndex, VRInputType checkButton) { - boolean buttonDownNow = isButtonDown(controllerIndex, checkButton); - int checkButtonValue = checkButton.getValue(); - int cIndex = OpenVRInput.controllerIndex[controllerIndex]; - boolean retval = buttonDownNow == true && buttonDown[cIndex][checkButtonValue] == false; - buttonDown[cIndex][checkButtonValue] = buttonDownNow; - return retval; - } - - @Override - public void resetInputSinceLastCall() { - for(int i=0;i 0) && (index < trackedControllers.size())){ - return trackedControllers.get(index); - } - } - - return null; - } - - @Override - public int getTrackedControllerCount() { - return controllerCount; - } - - @Override - public VRControllerState_t getRawControllerState(int index) { - if( isInputDeviceTracking(index) == false ) return null; - return cStates[controllerIndex[index]]; - } - - //public Matrix4f getPoseForInputDevice(int index) { - // if( isInputDeviceTracking(index) == false ) return null; - // return OpenVR.poseMatrices[controllerIndex[index]]; - //} - - @Override - public boolean isInputFocused() { - - if (environment != null){ - return ((VR_IVRSystem_FnTable)environment.getVRHardware().getVRSystem()).IsInputFocusCapturedByAnotherProcess.apply() == 0; - } else { - throw new IllegalStateException("VR input is not attached to a VR environment."); - } - } - - @Override - public boolean isInputDeviceTracking(int index) { - if( index < 0 || index >= controllerCount ){ - return false; - } - - return OpenVR.hmdTrackedDevicePoses[controllerIndex[index]].bPoseIsValid != 0; - } - - @Override - public Quaternion getOrientation(int index) { - if( isInputDeviceTracking(index) == false ){ - return null; - } - index = controllerIndex[index]; - VRUtil.convertMatrix4toQuat(OpenVR.poseMatrices[index], rotStore[index]); - return rotStore[index]; - } - - @Override - public Vector3f getPosition(int index) { - if( isInputDeviceTracking(index) == false ){ - 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]; - } - - @Override - public Quaternion getFinalObserverRotation(int index) { - - if (environment != null){ - VRViewManagerOpenVR vrvm = (VRViewManagerOpenVR)environment.getVRViewManager(); - - if (vrvm != null){ - if(isInputDeviceTracking(index) == false ){ - return null; - } - - Object obs = environment.getObserver(); - if( obs instanceof Camera ) { - tempq.set(((Camera)obs).getRotation()); - } else { - tempq.set(((Spatial)obs).getWorldRotation()); - } - - return tempq.multLocal(getOrientation(index)); - } else { - throw new IllegalStateException("VR environment has no valid view manager."); - } - - - } else { - throw new IllegalStateException("VR input is not attached to a VR environment."); - } - } - - @Override - public Vector3f getFinalObserverPosition(int index) { - - if (environment != null){ - VRViewManagerOpenVR vrvm = (VRViewManagerOpenVR)environment.getVRViewManager(); - - if (vrvm != null){ - if(isInputDeviceTracking(index) == false ){ - return null; - } - Object obs = environment.getObserver(); - Vector3f pos = getPosition(index); - if( obs instanceof Camera ) { - ((Camera)obs).getRotation().mult(pos, pos); - return pos.addLocal(((Camera)obs).getLocation()); - } else { - ((Spatial)obs).getWorldRotation().mult(pos, pos); - return pos.addLocal(((Spatial)obs).getWorldTranslation()); - } - } else { - throw new IllegalStateException("VR environment has no valid view manager."); - } - - } else { - throw new IllegalStateException("VR input is not attached to a VR environment."); - } - } - - @Override - public void triggerHapticPulse(int controllerIndex, float seconds) { - if( environment.isInVR() == false || isInputDeviceTracking(controllerIndex) == false ){ - return; - } - - // apparently only axis ID of 0 works - ((VR_IVRSystem_FnTable)environment.getVRHardware().getVRSystem()).TriggerHapticPulse.apply(OpenVRInput.controllerIndex[controllerIndex], - 0, (short)Math.round(3f * seconds / 1e-3f)); - } - - @Override - public void updateConnectedControllers() { - logger.config("Updating connected controllers."); - - if (environment != null){ - controllerCount = 0; - for(int i=0;iOpenVR input.
+ * null values will be returned if no valid pose exists, or that input device isn't available + * user code should check for null values. + * @author reden - phr00t - https://github.com/phr00t + * @author Julien Seinturier - (c) 2016 - JOrigin project - http:/www.jorigin.org + */ +public class OpenVRInput implements VRInputAPI { + + private static final Logger logger = Logger.getLogger(OpenVRInput.class.getName()); + + private final VRControllerState_t[] cStates = new VRControllerState_t[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; + + private final Quaternion[] rotStore = new Quaternion[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; + + private final Vector3f[] posStore = new Vector3f[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; + + private static final int[] controllerIndex = new int[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; + + private int controllerCount = 0; + + private final Vector2f tempAxis = new Vector2f(), temp2Axis = new Vector2f(); + + private final Vector2f lastCallAxis[] = new Vector2f[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; + + private final boolean needsNewVelocity[] = new boolean[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; + + private final boolean needsNewAngVelocity[] = new boolean[JOpenVRLibrary.k_unMaxTrackedDeviceCount]; + + private final boolean buttonDown[][] = new boolean[JOpenVRLibrary.k_unMaxTrackedDeviceCount][16]; + + private float axisMultiplier = 1f; + + private final Vector3f tempVel = new Vector3f(); + + private final Quaternion tempq = new Quaternion(); + + private VREnvironment environment; + + private List trackedControllers = null; + + /** + * Create a new OpenVR input attached to the given VR environment. + * @param environment the VR environment to which the input is attached. + */ + public OpenVRInput(VREnvironment environment){ + this.environment = environment; + } + + @Override + public float getAxisMultiplier() { + return axisMultiplier; + } + + @Override + public void setAxisMultiplier(float set) { + axisMultiplier = set; + } + + @Override + public void swapHands() { + if( controllerCount != 2 ) return; + int temp = controllerIndex[0]; + controllerIndex[0] = controllerIndex[1]; + controllerIndex[1] = temp; + } + + @Override + public boolean isButtonDown(int controllerIndex, VRInputType checkButton) { + VRControllerState_t cs = cStates[OpenVRInput.controllerIndex[controllerIndex]]; + switch( checkButton ) { + default: + return false; + case ViveGripButton: + return (cs.ulButtonPressed & 4) != 0; + case ViveMenuButton: + return (cs.ulButtonPressed & 2) != 0; + case ViveTrackpadAxis: + return (cs.ulButtonPressed & 4294967296l) != 0; + case ViveTriggerAxis: + return (cs.ulButtonPressed & 8589934592l) != 0; + } + } + + @Override + public boolean wasButtonPressedSinceLastCall(int controllerIndex, VRInputType checkButton) { + boolean buttonDownNow = isButtonDown(controllerIndex, checkButton); + int checkButtonValue = checkButton.getValue(); + int cIndex = OpenVRInput.controllerIndex[controllerIndex]; + boolean retval = buttonDownNow == true && buttonDown[cIndex][checkButtonValue] == false; + buttonDown[cIndex][checkButtonValue] = buttonDownNow; + return retval; + } + + @Override + public void resetInputSinceLastCall() { + for(int i=0;i 0) && (index < trackedControllers.size())){ + return trackedControllers.get(index); + } + } + + return null; + } + + @Override + public int getTrackedControllerCount() { + return controllerCount; + } + + @Override + public VRControllerState_t getRawControllerState(int index) { + if( isInputDeviceTracking(index) == false ) return null; + return cStates[controllerIndex[index]]; + } + + //public Matrix4f getPoseForInputDevice(int index) { + // if( isInputDeviceTracking(index) == false ) return null; + // return OpenVR.poseMatrices[controllerIndex[index]]; + //} + + @Override + public boolean isInputFocused() { + + if (environment != null){ + return ((VR_IVRSystem_FnTable)environment.getVRHardware().getVRSystem()).IsInputFocusCapturedByAnotherProcess.apply() == 0; + } else { + throw new IllegalStateException("VR input is not attached to a VR environment."); + } + } + + @Override + public boolean isInputDeviceTracking(int index) { + if( index < 0 || index >= controllerCount ){ + return false; + } + + return OpenVR.hmdTrackedDevicePoses[controllerIndex[index]].bPoseIsValid != 0; + } + + @Override + public Quaternion getOrientation(int index) { + if( isInputDeviceTracking(index) == false ){ + return null; + } + index = controllerIndex[index]; + VRUtil.convertMatrix4toQuat(OpenVR.poseMatrices[index], rotStore[index]); + return rotStore[index]; + } + + @Override + public Vector3f getPosition(int index) { + if( isInputDeviceTracking(index) == false ){ + 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]; + } + + @Override + public Quaternion getFinalObserverRotation(int index) { + + if (environment != null){ + VRViewManagerOpenVR vrvm = (VRViewManagerOpenVR)environment.getVRViewManager(); + + if (vrvm != null){ + if(isInputDeviceTracking(index) == false ){ + return null; + } + + Object obs = environment.getObserver(); + if( obs instanceof Camera ) { + tempq.set(((Camera)obs).getRotation()); + } else { + tempq.set(((Spatial)obs).getWorldRotation()); + } + + return tempq.multLocal(getOrientation(index)); + } else { + throw new IllegalStateException("VR environment has no valid view manager."); + } + + + } else { + throw new IllegalStateException("VR input is not attached to a VR environment."); + } + } + + @Override + public Vector3f getFinalObserverPosition(int index) { + + if (environment != null){ + VRViewManagerOpenVR vrvm = (VRViewManagerOpenVR)environment.getVRViewManager(); + + if (vrvm != null){ + if(isInputDeviceTracking(index) == false ){ + return null; + } + Object obs = environment.getObserver(); + Vector3f pos = getPosition(index); + if( obs instanceof Camera ) { + ((Camera)obs).getRotation().mult(pos, pos); + return pos.addLocal(((Camera)obs).getLocation()); + } else { + ((Spatial)obs).getWorldRotation().mult(pos, pos); + return pos.addLocal(((Spatial)obs).getWorldTranslation()); + } + } else { + throw new IllegalStateException("VR environment has no valid view manager."); + } + + } else { + throw new IllegalStateException("VR input is not attached to a VR environment."); + } + } + + @Override + public void triggerHapticPulse(int controllerIndex, float seconds) { + if( environment.isInVR() == false || isInputDeviceTracking(controllerIndex) == false ){ + return; + } + + // apparently only axis ID of 0 works + ((VR_IVRSystem_FnTable)environment.getVRHardware().getVRSystem()).TriggerHapticPulse.apply(OpenVRInput.controllerIndex[controllerIndex], + 0, (short)Math.round(3f * seconds / 1e-3f)); + } + + @Override + public void updateConnectedControllers() { + logger.config("Updating connected controllers."); + + if (environment != null){ + controllerCount = 0; + for(int i=0;i Date: Thu, 13 Apr 2017 11:37:36 +0200 Subject: [PATCH 6/6] Removing more static references. --- .../main/java/com/jme3/app/VREnvironment.java | 22 +++- .../main/java/com/jme3/input/vr/OpenVR.java | 37 +++--- .../java/com/jme3/input/vr/OpenVRInput.java | 119 +++++++++++++----- 3 files changed, 127 insertions(+), 51 deletions(-) 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 cb2042885..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 @@ -46,14 +46,14 @@ public class OpenVR implements VRAPI { 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; + private IntBuffer hmdDisplayFrequency; + private TrackedDevicePose_t.ByReference hmdTrackedDevicePoseReference; + protected TrackedDevicePose_t[] hmdTrackedDevicePoses; - protected static IntByReference hmdErrorStore; + protected IntByReference hmdErrorStore; - private static final Quaternion rotStore = new Quaternion(); - private static final Vector3f posStore = new Vector3f(); + private final Quaternion rotStore = new Quaternion(); + private final Vector3f posStore = new Vector3f(); private static FloatByReference tlastVsync; @@ -65,20 +65,21 @@ public class OpenVR implements VRAPI { // for debugging latency private int frames = 0; - protected static Matrix4f[] poseMatrices; + protected 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 final Matrix4f hmdPose = Matrix4f.IDENTITY.clone(); + private Matrix4f hmdProjectionLeftEye; + private Matrix4f hmdProjectionRightEye; + private Matrix4f hmdPoseLeftEye; + private Matrix4f hmdPoseRightEye; - private static Vector3f hmdPoseLeftEyeVec, hmdPoseRightEyeVec, hmdSeatToStand; + private Vector3f hmdPoseLeftEyeVec, hmdPoseRightEyeVec, hmdSeatToStand; + + private float vsyncToPhotons; + private double timePerFrame, frameCountRun; + private long frameCount; + private OpenVRInput VRinput; - private static float vsyncToPhotons; - private static double timePerFrame, frameCountRun; - private static long frameCount; - private static OpenVRInput VRinput; private VREnvironment environment = null; @@ -181,7 +182,7 @@ public class OpenVR implements VRAPI { VRinput.updateConnectedControllers(); // init bounds & chaperone info - VRBounds.init(); + environment.getVRBounds().init(this); logger.config("Initializing OpenVR system [SUCCESS]"); initSuccess = true; 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);