diff --git a/jme3-vr/build.gradle b/jme3-vr/build.gradle
index 7a9ea7d34..aac0a3a04 100644
--- a/jme3-vr/build.gradle
+++ b/jme3-vr/build.gradle
@@ -2,7 +2,7 @@ if (!hasProperty('mainClass')) {
ext.mainClass = ''
}
-def lwjglVersion = '3.2.0'
+def lwjglVersion = '3.2.1'
sourceCompatibility = '1.8'
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 485a563ce..3ed87b696 100644
--- a/jme3-vr/src/main/java/com/jme3/app/VREnvironment.java
+++ b/jme3-vr/src/main/java/com/jme3/app/VREnvironment.java
@@ -1,550 +1,555 @@
-package com.jme3.app;
-
-import java.util.Locale;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.jme3.app.state.AppState;
-import com.jme3.input.vr.VRAPI;
-import com.jme3.input.vr.VRBounds;
-import com.jme3.input.vr.VRInputAPI;
-import com.jme3.input.vr.VRMouseManager;
-import com.jme3.input.vr.VRViewManager;
-import com.jme3.input.vr.lwjgl_openvr.LWJGLOpenVR;
-import com.jme3.input.vr.lwjgl_openvr.LWJGLOpenVRMouseManager;
-import com.jme3.input.vr.lwjgl_openvr.LWJGLOpenVRViewManager;
-import com.jme3.input.vr.oculus.OculusMouseManager;
-import com.jme3.input.vr.oculus.OculusVR;
-import com.jme3.input.vr.oculus.OculusViewManager;
-import com.jme3.input.vr.openvr.OpenVR;
-import com.jme3.input.vr.openvr.OpenVRMouseManager;
-import com.jme3.input.vr.openvr.OpenVRViewManager;
-import com.jme3.input.vr.osvr.OSVR;
-import com.jme3.input.vr.osvr.OSVRViewManager;
-import com.jme3.renderer.Camera;
-import com.jme3.scene.Spatial;
-import com.jme3.system.AppSettings;
-import com.jme3.system.jopenvr.JOpenVRLibrary;
-import com.jme3.util.VRGuiManager;
-
-/**
- *
- * @author Julien Seinturier - COMEX SA - http://www.seinturier.fr
- *
- */
-public class VREnvironment {
-
- private static final Logger logger = Logger.getLogger(VREnvironment.class.getName());
-
- private VRAPI hardware = null;
- 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}.
- */
- public int vrBinding = VRConstants.SETTING_VRAPI_OPENVR_VALUE;
-
- private boolean seated = false;
-
- private Spatial observer = null;
-
- private boolean forceVR = false;
-
- private boolean vrSupportedOS = false;
-
- private boolean nogui = false;
-
- private boolean compositorOS;
-
- private boolean useCompositor = true;
-
- private boolean instanceRendering = false;
-
- private boolean disableSwapBuffers = true;
-
- private float defaultFOV = 108f;
-
- private float defaultAspect = 1f;
-
- private AppSettings settings = null;
-
- private Application application = null;
-
- private Camera dummyCam = null;
-
- private AppState app = null;
-
- private boolean initialized = false;
-
-
- public VREnvironment(AppSettings settings){
-
- this.settings = settings;
-
- bounds = null;
-
- processSettings();
- }
-
- /**
- * Get the VR underlying hardware.
- * @return the VR underlying hardware.
- */
- public VRAPI getVRHardware() {
- return hardware;
- }
-
- /**
- * Set the VR bounds.
- * @see #getVRBounds()
- */
- public void setVRBounds(VRBounds bounds){
- this.bounds = bounds;
- }
-
- /**
- * Get the VR bounds.
- * @return the VR bounds.
- * @see #setVRBounds(VRBounds)
- */
- public VRBounds getVRBounds(){
- return bounds;
- }
-
- /**
- * Get the VR dedicated input.
- * @return the VR dedicated input.
- */
- public VRInputAPI getVRinput() {
- if( hardware == null ){
- return null;
- }
-
- return hardware.getVRinput();
- }
-
- /**
- * Get the VR view manager.
- * @return the VR view manager.
- */
- public VRViewManager getVRViewManager() {
- return viewmanager;
- }
-
- /**
- * Get the GUI manager attached to this environment.
- * @return the GUI manager attached to this environment.
- */
- public VRGuiManager getVRGUIManager(){
- return guiManager;
- }
-
- /**
- * Get the VR mouse manager attached to this environment.
- * @return the VR mouse manager attached to this environment.
- */
- public VRMouseManager getVRMouseManager(){
- return mouseManager;
- }
-
- /**
- * Can be used to change seated experience during runtime.
- * @param isSeated true
if designed for sitting, false
for standing/roomscale
- * @see #isSeatedExperience()
- */
- public void setSeatedExperience(boolean isSeated) {
- seated = isSeated;
- if( hardware instanceof OpenVR ) {
- if( hardware.getCompositor() == null ) {
- return;
- }
-
- if( seated ) {
- ((OpenVR)hardware).getCompositor().SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated);
- } else {
- ((OpenVR)hardware).getCompositor().SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding);
- }
- } else if (hardware instanceof LWJGLOpenVR) {
- if( ((LWJGLOpenVR)hardware).isInitialized() ) {
- ((LWJGLOpenVR)hardware).setTrackingSpace(seated);
- }
- }
- }
-
- /**
- * Check if the application is configured as a seated experience.
- * @return true
if the application is configured as a seated experience and false
otherwise.
- * @see #setSeatedExperience(boolean)
- */
- public boolean isSeatedExperience() {
- return seated;
- }
-
- /**
- * Set the VR headset height from the ground.
- * @param amount the VR headset height from the ground.
- * @see #getVRHeightAdjustment()
- */
- public void setVRHeightAdjustment(float amount) {
- if( viewmanager != null ){
- viewmanager.setHeightAdjustment(amount);
- }
- }
-
- /**
- * Get the VR headset height from the ground.
- * @return the VR headset height from the ground.
- * @see #setVRHeightAdjustment(float)
- */
- public float getVRHeightAdjustment() {
- if( viewmanager != null ){
- return viewmanager.getHeightAdjustment();
- }
- return 0f;
- }
-
- /**
- * Get the scene observer. If no observer has been set, this method return the application {@link #getCamera() camera}.
- * @return the scene observer.
- * @see #setObserver(Spatial)
- */
- public Object getObserver() {
- if( observer == null ) {
-
- if (application != null){
- return application.getCamera();
- } else {
- throw new IllegalStateException("VR environment is not attached to any application.");
- }
- }
- return observer;
- }
-
- /**
- * Set the scene observer. The VR headset will be linked to it. If no observer is set, the VR headset is linked to the application {@link #getCamera() camera}.
- * @param observer the scene observer.
- */
- public void setObserver(Spatial observer) {
- this.observer = observer;
- }
-
- /**
- * Get the default Field Of View (FOV) value.
- * @return the default Field Of View (FOV) value.
- * @see #setDefaultFOV(float)
- */
- public float getDefaultFOV() {
- return defaultFOV;
- }
-
- /**
- * Set the default Field Of View (FOV) value.
- * @param defaultFOV the default Field Of View (FOV) value.
- * @see #getDefaultFOV()
- */
- public void setDefaultFOV(float defaultFOV) {
- this.defaultFOV = defaultFOV;
- }
-
- /**
- * Get the default aspect ratio.
- * @return the default aspect ratio.
- * @see #setDefaultAspect(float)
- */
- public float getDefaultAspect() {
- return defaultAspect;
- }
-
- /**
- * Set the default aspect ratio.
- * @param defaultAspect the default aspect ratio.
- * @see #getDefaultAspect()
- */
- public void setDefaultAspect(float defaultAspect) {
- this.defaultAspect = defaultAspect;
- }
-
- /**
- * Get the {@link AppSettings settings} attached to this environment.
- * @return the {@link AppSettings settings} attached to this environment.
- * @see #setSettings(AppSettings)
- */
- public AppSettings getSettings(){
- return settings;
- }
-
- /**
- * Set the {@link AppSettings settings} attached to this environment.
- * @param settings the {@link AppSettings settings} attached to this environment.
- * @see #getSettings()
- */
- public void setSettings(AppSettings settings){
- this.settings = settings;
- processSettings();
- }
-
- /**
- * Get if the system currently support VR.
- * @return true
if the system currently support VR and false
otherwise.
- */
- public boolean isVRSupported() {
- return vrSupportedOS;
- }
-
- /**
- * Check if the VR mode is enabled.
- * @return true
if the VR mode is enabled and false
otherwise.
- */
- public boolean isInVR() {
- return (forceVR || vrSupportedOS && hardware != null && hardware.isInitialized() && isInitialized());
- }
-
- /**
- * Check if the rendering is instanced (see Geometry instancing).
- * @return true
if the rendering is instanced and false
otherwise.
- */
- public boolean isInstanceRendering() {
- return instanceRendering;
- }
-
- public boolean isSwapBuffers(){
- return disableSwapBuffers;
- }
-
- /**
- * Check if the application has a GUI overlay attached.
- * @return true
if the application has a GUI overlay attached and false
otherwise.
- */
- public boolean hasTraditionalGUIOverlay() {
- return !nogui;
- }
-
- /**
- * Check if the VR environment is initialized. A call to the {@link #initialize() initialize()} method should set this value to true
- * @return true
if the VR environment is initialized and false
otherwise.
- */
- public boolean isInitialized(){
- return initialized;
- }
-
- /**
- * Is the VR compositor is active.
- * @return true
if the VR compositor is active and false
otherwise.
- */
- public boolean compositorAllowed() {
- return useCompositor && compositorOS;
- }
-
- /**
- * Reset headset pose if seating experience.
- */
- public void resetSeatedPose(){
- if( vrSupportedOS == false || isSeatedExperience() == false ){
- return;
- }
- getVRHardware().reset();
- }
-
- public AppState getAppState(){
- return app;
- }
-
- public Application getApplication(){
- return application;
- }
-
- /**
- * Get the {@link Camera camera} used for rendering.
- * If the VR mode is {@link #isInVR() active}, this method return a dummy camera, otherwise,
- * this method return the camera of the attached application.
- * @return the camera attached used for rendering.
- */
- public Camera getCamera() {
- if( isInVR() && getVRViewManager() != null && getVRViewManager().getLeftCamera() != null ) {
- return getDummyCamera();
- }
-
- return application.getCamera();
- }
-
- public Camera getDummyCamera(){
-
- if (dummyCam == null){
-
- if (application != null){
-
- if (application.getCamera() != null){
- dummyCam = application.getCamera().clone();
- } else {
-
- 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.");
- }
- }
- return dummyCam;
- }
-
- /**
- * Attach the VR environment to the given app state and application.
- * This method should be called within the {@link AppState#stateAttached(com.jme3.app.state.AppStateManager) stateAttached(com.jme3.app.state.AppStateManager)} method
- * from the app state.
- * @param appState the app state to attach.
- * @param application the application to attach.
- */
- public void atttach(AppState appState, Application application){
- this.application = application;
- this.app = appState;
-
- // Instanciate view manager
- if (vrBinding == VRConstants.SETTING_VRAPI_OPENVR_VALUE){
- viewmanager = new OpenVRViewManager(this);
- } else if (vrBinding == VRConstants.SETTING_VRAPI_OSVR_VALUE){
- viewmanager = new OSVRViewManager(this);
- } else if (vrBinding == VRConstants.SETTING_VRAPI_OCULUSVR_VALUE) {
- viewmanager = new OculusViewManager(this);
- } else if (vrBinding == VRConstants.SETTING_VRAPI_OPENVR_LWJGL_VALUE) {
- viewmanager = new LWJGLOpenVRViewManager(this);
- } else {
- logger.severe("Cannot instanciate view manager, unknown VRAPI type: "+vrBinding);
- }
- }
-
- /**
- * Initialize this VR environment. This method enable the system bindings and configure all the VR system modules.
- * A call to this method has to be made before any use of VR capabilities.
- * @return true
if the VR environment is successfully initialized and false
otherwise.
- */
- public boolean initialize(){
-
- logger.config("Initializing VR environment.");
-
- initialized = false;
-
- // we are going to use OpenVR now, not the Oculus Rift
- // OpenVR does support the Rift
- String OS = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH);
- vrSupportedOS = !OS.contains("nux") && System.getProperty("sun.arch.data.model").equalsIgnoreCase("64"); //for the moment, linux/unix causes crashes, 64-bit only
- compositorOS = OS.contains("indows");
-
- if( vrSupportedOS) {
- if( vrBinding == VRConstants.SETTING_VRAPI_OSVR_VALUE ) {
-
- guiManager = new VRGuiManager(this);
- mouseManager = new OpenVRMouseManager(this);
-
- hardware = new OSVR(this);
- initialized = true;
- logger.config("Creating OSVR wrapper [SUCCESS]");
- } else if( vrBinding == VRConstants.SETTING_VRAPI_OPENVR_VALUE ) {
-
- guiManager = new VRGuiManager(this);
- mouseManager = new OpenVRMouseManager(this);
-
- hardware = new OpenVR(this);
- initialized = true;
- logger.config("Creating OpenVR wrapper [SUCCESS]");
- } else if (vrBinding == VRConstants.SETTING_VRAPI_OCULUSVR_VALUE) {
-
- guiManager = new VRGuiManager(this);
- mouseManager = new OculusMouseManager(this);
-
- hardware = new OculusVR(this);
- initialized = true;
- logger.config("Creating Occulus Rift wrapper [SUCCESS]");
- } else if (vrBinding == VRConstants.SETTING_VRAPI_OPENVR_LWJGL_VALUE) {
-
- guiManager = new VRGuiManager(this);
- mouseManager = new LWJGLOpenVRMouseManager(this);
-
- hardware = new LWJGLOpenVR(this);
- initialized = true;
- logger.config("Creating OpenVR/LWJGL wrapper [SUCCESS]");
- } else {
- logger.config("Cannot create VR binding: "+vrBinding+" [FAILED]");
- logger.log(Level.SEVERE, "Cannot initialize VR environment [FAILED]");
- }
-
- if( hardware.initialize() ) {
- initialized &= true;
- logger.config("VR native wrapper initialized [SUCCESS]");
- } else {
- initialized &= false;
- logger.warning("VR native wrapper initialized [FAILED]");
- logger.log(Level.SEVERE, "Cannot initialize VR environment [FAILED]");
- }
- } else {
- logger.log(Level.SEVERE, "System does not support VR capabilities.");
- logger.log(Level.SEVERE, "Cannot initialize VR environment [FAILED]");
- }
-
- return initialized;
- }
-
- private void processSettings(){
- if (settings != null){
-
- if (settings.get(VRConstants.SETTING_USE_COMPOSITOR) != null){
- useCompositor = settings.getBoolean(VRConstants.SETTING_USE_COMPOSITOR);
- if( useCompositor == false ){
- disableSwapBuffers = false;
- }
- }
-
- if (settings.get(VRConstants.SETTING_ENABLE_MIRROR_WINDOW) != null){
- if( useCompositor == false ) {
- disableSwapBuffers = false;
- } else {
- disableSwapBuffers = !settings.getBoolean(VRConstants.SETTING_ENABLE_MIRROR_WINDOW);
- }
- }
-
- if (settings.get(VRConstants.SETTING_GUI_OVERDRAW) != null){
- getVRGUIManager().setGuiOverdraw(settings.getBoolean(VRConstants.SETTING_GUI_OVERDRAW));
- }
-
- if (settings.get(VRConstants.SETTING_GUI_CURVED_SURFACE) != null){
- getVRGUIManager().setCurvedSurface(settings.getBoolean(VRConstants.SETTING_GUI_CURVED_SURFACE));
- }
-
- if (settings.get(VRConstants.SETTING_NO_GUI) != null){
- nogui = settings.getBoolean(VRConstants.SETTING_NO_GUI);
- }
-
- if (settings.get(VRConstants.SETTING_VRAPI) != null){
- vrBinding = settings.getInteger(VRConstants.SETTING_VRAPI);
- }
-
- if (settings.get(VRConstants.SETTING_SEATED_EXPERIENCE) != null){
- seated = settings.getBoolean(VRConstants.SETTING_SEATED_EXPERIENCE);
- }
-
- if (settings.get(VRConstants.SETTING_INSTANCE_RENDERING) != null){
- instanceRendering = settings.getBoolean(VRConstants.SETTING_INSTANCE_RENDERING);
- }
-
- if (settings.get(VRConstants.SETTING_DEFAULT_FOV) != null){
- defaultFOV = settings.getFloat(VRConstants.SETTING_DEFAULT_FOV);
- }
-
- if (settings.get(VRConstants.SETTING_DEFAULT_ASPECT_RATIO) != null){
- defaultAspect = settings.getFloat(VRConstants.SETTING_DEFAULT_ASPECT_RATIO);
- }
-
- if (settings.get(VRConstants.SETTING_FLIP_EYES) != null){
- if( getVRHardware() != null ){
- getVRHardware().setFlipEyes(settings.getBoolean(VRConstants.SETTING_FLIP_EYES));
- }
- }
- }
- }
-}
+package com.jme3.app;
+
+import java.util.Locale;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.app.state.AppState;
+import com.jme3.input.vr.VRAPI;
+import com.jme3.input.vr.VRBounds;
+import com.jme3.input.vr.VRInputAPI;
+import com.jme3.input.vr.VRMouseManager;
+import com.jme3.input.vr.VRViewManager;
+import com.jme3.input.vr.lwjgl_openvr.LWJGLOpenVR;
+import com.jme3.input.vr.lwjgl_openvr.LWJGLOpenVRMouseManager;
+import com.jme3.input.vr.lwjgl_openvr.LWJGLOpenVRViewManager;
+import com.jme3.input.vr.oculus.OculusMouseManager;
+import com.jme3.input.vr.oculus.OculusVR;
+import com.jme3.input.vr.oculus.OculusViewManager;
+import com.jme3.input.vr.openvr.OpenVR;
+import com.jme3.input.vr.openvr.OpenVRMouseManager;
+import com.jme3.input.vr.openvr.OpenVRViewManager;
+import com.jme3.input.vr.osvr.OSVR;
+import com.jme3.input.vr.osvr.OSVRViewManager;
+import com.jme3.renderer.Camera;
+import com.jme3.scene.Spatial;
+import com.jme3.system.AppSettings;
+import com.jme3.system.jopenvr.JOpenVRLibrary;
+import com.jme3.util.VRGuiManager;
+
+/**
+ *
+ * @author Julien Seinturier - COMEX SA - http://www.seinturier.fr
+ *
+ */
+public class VREnvironment {
+
+ private static final Logger logger = Logger.getLogger(VREnvironment.class.getName());
+
+ private VRAPI hardware = null;
+ 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}.
+ */
+ public int vrBinding = VRConstants.SETTING_VRAPI_OPENVR_VALUE;
+
+ private boolean seated = false;
+
+ private Spatial observer = null;
+
+ private boolean forceVR = false;
+
+ private boolean vrSupportedOS = false;
+
+ private boolean nogui = false;
+
+ private boolean compositorOS;
+
+ private boolean useCompositor = true;
+
+ private boolean instanceRendering = false;
+
+ private boolean disableSwapBuffers = true;
+
+ private float defaultFOV = 108f;
+
+ private float defaultAspect = 1f;
+
+ private AppSettings settings = null;
+
+ private Application application = null;
+
+ private Camera dummyCam = null;
+
+ private AppState app = null;
+
+ private boolean initialized = false;
+
+
+ public VREnvironment(AppSettings settings){
+
+ this.settings = settings;
+
+ bounds = null;
+
+ processSettings();
+ }
+
+ /**
+ * Get the VR underlying hardware.
+ * @return the VR underlying hardware.
+ */
+ public VRAPI getVRHardware() {
+ return hardware;
+ }
+
+ /**
+ * Set the VR bounds.
+ * @see #getVRBounds()
+ */
+ public void setVRBounds(VRBounds bounds){
+ this.bounds = bounds;
+ }
+
+ /**
+ * Get the VR bounds.
+ * @return the VR bounds.
+ * @see #setVRBounds(VRBounds)
+ */
+ public VRBounds getVRBounds(){
+ return bounds;
+ }
+
+ /**
+ * Get the VR dedicated input.
+ * @return the VR dedicated input.
+ */
+ public VRInputAPI getVRinput() {
+ if( hardware == null ){
+ return null;
+ }
+
+ return hardware.getVRinput();
+ }
+
+ /**
+ * Get the VR view manager.
+ * @return the VR view manager.
+ */
+ public VRViewManager getVRViewManager() {
+ return viewmanager;
+ }
+
+ /**
+ * Get the GUI manager attached to this environment.
+ * @return the GUI manager attached to this environment.
+ */
+ public VRGuiManager getVRGUIManager(){
+ return guiManager;
+ }
+
+ /**
+ * Get the VR mouse manager attached to this environment.
+ * @return the VR mouse manager attached to this environment.
+ */
+ public VRMouseManager getVRMouseManager(){
+ return mouseManager;
+ }
+
+ /**
+ * Can be used to change seated experience during runtime.
+ * @param isSeated true
if designed for sitting, false
for standing/roomscale
+ * @see #isSeatedExperience()
+ */
+ public void setSeatedExperience(boolean isSeated) {
+ seated = isSeated;
+ if( hardware instanceof OpenVR ) {
+ if( hardware.getCompositor() == null ) {
+ return;
+ }
+
+ if( seated ) {
+ ((OpenVR)hardware).getCompositor().SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated);
+ } else {
+ ((OpenVR)hardware).getCompositor().SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding);
+ }
+ } else if (hardware instanceof LWJGLOpenVR) {
+ if( ((LWJGLOpenVR)hardware).isInitialized() ) {
+ ((LWJGLOpenVR)hardware).setTrackingSpace(seated);
+ }
+ }
+ }
+
+ /**
+ * Check if the application is configured as a seated experience.
+ * @return true
if the application is configured as a seated experience and false
otherwise.
+ * @see #setSeatedExperience(boolean)
+ */
+ public boolean isSeatedExperience() {
+ return seated;
+ }
+
+ /**
+ * Set the VR headset height from the ground.
+ * @param amount the VR headset height from the ground.
+ * @see #getVRHeightAdjustment()
+ */
+ public void setVRHeightAdjustment(float amount) {
+ if( viewmanager != null ){
+ viewmanager.setHeightAdjustment(amount);
+ }
+ }
+
+ /**
+ * Get the VR headset height from the ground.
+ * @return the VR headset height from the ground.
+ * @see #setVRHeightAdjustment(float)
+ */
+ public float getVRHeightAdjustment() {
+ if( viewmanager != null ){
+ return viewmanager.getHeightAdjustment();
+ }
+ return 0f;
+ }
+
+ /**
+ * Get the scene observer. If no observer has been set, this method return the application {@link #getCamera() camera}.
+ * @return the scene observer.
+ * @see #setObserver(Spatial)
+ */
+ public Object getObserver() {
+ if( observer == null ) {
+
+ if (application != null){
+ return application.getCamera();
+ } else {
+ throw new IllegalStateException("VR environment is not attached to any application.");
+ }
+ }
+ return observer;
+ }
+
+ /**
+ * Set the scene observer. The VR headset will be linked to it. If no observer is set, the VR headset is linked to the application {@link #getCamera() camera}.
+ * @param observer the scene observer.
+ */
+ public void setObserver(Spatial observer) {
+ this.observer = observer;
+ }
+
+ /**
+ * Get the default Field Of View (FOV) value.
+ * @return the default Field Of View (FOV) value.
+ * @see #setDefaultFOV(float)
+ */
+ public float getDefaultFOV() {
+ return defaultFOV;
+ }
+
+ /**
+ * Set the default Field Of View (FOV) value.
+ * @param defaultFOV the default Field Of View (FOV) value.
+ * @see #getDefaultFOV()
+ */
+ public void setDefaultFOV(float defaultFOV) {
+ this.defaultFOV = defaultFOV;
+ }
+
+ /**
+ * Get the default aspect ratio.
+ * @return the default aspect ratio.
+ * @see #setDefaultAspect(float)
+ */
+ public float getDefaultAspect() {
+ return defaultAspect;
+ }
+
+ /**
+ * Set the default aspect ratio.
+ * @param defaultAspect the default aspect ratio.
+ * @see #getDefaultAspect()
+ */
+ public void setDefaultAspect(float defaultAspect) {
+ this.defaultAspect = defaultAspect;
+ }
+
+ /**
+ * Get the {@link AppSettings settings} attached to this environment.
+ * @return the {@link AppSettings settings} attached to this environment.
+ * @see #setSettings(AppSettings)
+ */
+ public AppSettings getSettings(){
+ return settings;
+ }
+
+ /**
+ * Set the {@link AppSettings settings} attached to this environment.
+ * @param settings the {@link AppSettings settings} attached to this environment.
+ * @see #getSettings()
+ */
+ public void setSettings(AppSettings settings){
+ this.settings = settings;
+ processSettings();
+ }
+
+ /**
+ * Get if the system currently support VR.
+ * @return true
if the system currently support VR and false
otherwise.
+ */
+ public boolean isVRSupported() {
+ return vrSupportedOS;
+ }
+
+ /**
+ * Check if the VR mode is enabled.
+ * @return true
if the VR mode is enabled and false
otherwise.
+ */
+ public boolean isInVR() {
+ return (forceVR || vrSupportedOS && hardware != null && hardware.isInitialized() && isInitialized());
+ }
+
+ /**
+ * Check if the rendering is instanced (see Geometry instancing).
+ * @return true
if the rendering is instanced and false
otherwise.
+ */
+ public boolean isInstanceRendering() {
+ return instanceRendering;
+ }
+
+ public boolean isSwapBuffers(){
+ return disableSwapBuffers;
+ }
+
+ /**
+ * Check if the application has a GUI overlay attached.
+ * @return true
if the application has a GUI overlay attached and false
otherwise.
+ */
+ public boolean hasTraditionalGUIOverlay() {
+ return !nogui;
+ }
+
+ /**
+ * Check if the VR environment is initialized. A call to the {@link #initialize() initialize()} method should set this value to true
+ * @return true
if the VR environment is initialized and false
otherwise.
+ */
+ public boolean isInitialized(){
+ return initialized;
+ }
+
+ /**
+ * Is the VR compositor is active.
+ * @return true
if the VR compositor is active and false
otherwise.
+ */
+ public boolean compositorAllowed() {
+ return useCompositor && compositorOS;
+ }
+
+ /**
+ * Reset headset pose if seating experience.
+ */
+ public void resetSeatedPose(){
+ if( vrSupportedOS == false || isSeatedExperience() == false ){
+ return;
+ }
+ getVRHardware().reset();
+ }
+
+ public AppState getAppState(){
+ return app;
+ }
+
+ public Application getApplication(){
+ return application;
+ }
+
+ /**
+ * Get the {@link Camera camera} used for rendering.
+ * If the VR mode is {@link #isInVR() active}, this method return a dummy camera, otherwise,
+ * this method return the camera of the attached application.
+ * @return the camera attached used for rendering.
+ */
+ public Camera getCamera() {
+ if( isInVR() && getVRViewManager() != null && getVRViewManager().getLeftCamera() != null ) {
+ return getDummyCamera();
+ }
+
+ return application.getCamera();
+ }
+
+ public Camera getDummyCamera(){
+
+ if (dummyCam == null){
+
+ if (application != null){
+
+ if (application.getCamera() != null){
+ dummyCam = application.getCamera().clone();
+ } else {
+
+ 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.");
+ }
+ }
+ return dummyCam;
+ }
+
+ /**
+ * Attach the VR environment to the given app state and application.
+ * This method should be called within the {@link AppState#stateAttached(com.jme3.app.state.AppStateManager) stateAttached(com.jme3.app.state.AppStateManager)} method
+ * from the app state.
+ * @param appState the app state to attach.
+ * @param application the application to attach.
+ */
+ public void atttach(AppState appState, Application application){
+ this.application = application;
+ this.app = appState;
+
+ // Instanciate view manager
+ if (vrBinding == VRConstants.SETTING_VRAPI_OPENVR_VALUE){
+ viewmanager = new OpenVRViewManager(this);
+ } else if (vrBinding == VRConstants.SETTING_VRAPI_OSVR_VALUE){
+ viewmanager = new OSVRViewManager(this);
+ } else if (vrBinding == VRConstants.SETTING_VRAPI_OCULUSVR_VALUE) {
+ viewmanager = new OculusViewManager(this);
+ } else if (vrBinding == VRConstants.SETTING_VRAPI_OPENVR_LWJGL_VALUE) {
+ viewmanager = new LWJGLOpenVRViewManager(this);
+ } else {
+ logger.severe("Cannot instanciate view manager, unknown VRAPI type: "+vrBinding);
+ }
+ }
+
+ /**
+ * Initialize this VR environment. This method enable the system bindings and configure all the VR system modules.
+ * A call to this method has to be made before any use of VR capabilities.
+ * @return true
if the VR environment is successfully initialized and false
otherwise.
+ */
+ public boolean initialize(){
+
+ logger.config("Initializing VR environment.");
+
+ initialized = false;
+
+ // we are going to use OpenVR now, not the Oculus Rift
+ // OpenVR does support the Rift
+ String OS = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH);
+ vrSupportedOS = System.getProperty("sun.arch.data.model").equalsIgnoreCase("64"); //64-bit only
+ compositorOS = OS.contains("indows") || OS.contains("nux");
+
+ if (OS.contains("nux") && vrBinding != VRConstants.SETTING_VRAPI_OPENVR_LWJGL_VALUE){
+ logger.severe("Only LWJGL VR backend is currently (partially) supported on Linux.");
+ vrSupportedOS = false;
+ }
+
+ if( vrSupportedOS) {
+ if( vrBinding == VRConstants.SETTING_VRAPI_OSVR_VALUE ) {
+
+ guiManager = new VRGuiManager(this);
+ mouseManager = new OpenVRMouseManager(this);
+
+ hardware = new OSVR(this);
+ initialized = true;
+ logger.config("Creating OSVR wrapper [SUCCESS]");
+ } else if( vrBinding == VRConstants.SETTING_VRAPI_OPENVR_VALUE ) {
+
+ guiManager = new VRGuiManager(this);
+ mouseManager = new OpenVRMouseManager(this);
+
+ hardware = new OpenVR(this);
+ initialized = true;
+ logger.config("Creating OpenVR wrapper [SUCCESS]");
+ } else if (vrBinding == VRConstants.SETTING_VRAPI_OCULUSVR_VALUE) {
+
+ guiManager = new VRGuiManager(this);
+ mouseManager = new OculusMouseManager(this);
+
+ hardware = new OculusVR(this);
+ initialized = true;
+ logger.config("Creating Occulus Rift wrapper [SUCCESS]");
+ } else if (vrBinding == VRConstants.SETTING_VRAPI_OPENVR_LWJGL_VALUE) {
+
+ guiManager = new VRGuiManager(this);
+ mouseManager = new LWJGLOpenVRMouseManager(this);
+
+ hardware = new LWJGLOpenVR(this);
+ initialized = true;
+ logger.config("Creating OpenVR/LWJGL wrapper [SUCCESS]");
+ } else {
+ logger.config("Cannot create VR binding: "+vrBinding+" [FAILED]");
+ logger.log(Level.SEVERE, "Cannot initialize VR environment [FAILED]");
+ }
+
+ if( hardware.initialize() ) {
+ initialized &= true;
+ logger.config("VR native wrapper initialized [SUCCESS]");
+ } else {
+ initialized &= false;
+ logger.warning("VR native wrapper initialized [FAILED]");
+ logger.log(Level.SEVERE, "Cannot initialize VR environment [FAILED]");
+ }
+ } else {
+ logger.log(Level.SEVERE, "System does not support VR capabilities.");
+ logger.log(Level.SEVERE, "Cannot initialize VR environment [FAILED]");
+ }
+
+ return initialized;
+ }
+
+ private void processSettings(){
+ if (settings != null){
+
+ if (settings.get(VRConstants.SETTING_USE_COMPOSITOR) != null){
+ useCompositor = settings.getBoolean(VRConstants.SETTING_USE_COMPOSITOR);
+ if( useCompositor == false ){
+ disableSwapBuffers = false;
+ }
+ }
+
+ if (settings.get(VRConstants.SETTING_ENABLE_MIRROR_WINDOW) != null){
+ if( useCompositor == false ) {
+ disableSwapBuffers = false;
+ } else {
+ disableSwapBuffers = !settings.getBoolean(VRConstants.SETTING_ENABLE_MIRROR_WINDOW);
+ }
+ }
+
+ if (settings.get(VRConstants.SETTING_GUI_OVERDRAW) != null){
+ getVRGUIManager().setGuiOverdraw(settings.getBoolean(VRConstants.SETTING_GUI_OVERDRAW));
+ }
+
+ if (settings.get(VRConstants.SETTING_GUI_CURVED_SURFACE) != null){
+ getVRGUIManager().setCurvedSurface(settings.getBoolean(VRConstants.SETTING_GUI_CURVED_SURFACE));
+ }
+
+ if (settings.get(VRConstants.SETTING_NO_GUI) != null){
+ nogui = settings.getBoolean(VRConstants.SETTING_NO_GUI);
+ }
+
+ if (settings.get(VRConstants.SETTING_VRAPI) != null){
+ vrBinding = settings.getInteger(VRConstants.SETTING_VRAPI);
+ }
+
+ if (settings.get(VRConstants.SETTING_SEATED_EXPERIENCE) != null){
+ seated = settings.getBoolean(VRConstants.SETTING_SEATED_EXPERIENCE);
+ }
+
+ if (settings.get(VRConstants.SETTING_INSTANCE_RENDERING) != null){
+ instanceRendering = settings.getBoolean(VRConstants.SETTING_INSTANCE_RENDERING);
+ }
+
+ if (settings.get(VRConstants.SETTING_DEFAULT_FOV) != null){
+ defaultFOV = settings.getFloat(VRConstants.SETTING_DEFAULT_FOV);
+ }
+
+ if (settings.get(VRConstants.SETTING_DEFAULT_ASPECT_RATIO) != null){
+ defaultAspect = settings.getFloat(VRConstants.SETTING_DEFAULT_ASPECT_RATIO);
+ }
+
+ if (settings.get(VRConstants.SETTING_FLIP_EYES) != null){
+ if( getVRHardware() != null ){
+ getVRHardware().setFlipEyes(settings.getBoolean(VRConstants.SETTING_FLIP_EYES));
+ }
+ }
+ }
+ }
+}
diff --git a/jme3-vr/src/main/java/com/jme3/input/vr/HmdType.java b/jme3-vr/src/main/java/com/jme3/input/vr/HmdType.java
index 5ad535d72..cffc1b35d 100644
--- a/jme3-vr/src/main/java/com/jme3/input/vr/HmdType.java
+++ b/jme3-vr/src/main/java/com/jme3/input/vr/HmdType.java
@@ -1,64 +1,69 @@
-package com.jme3.input.vr;
-
-/**
- * The type of VR Head Mounted Device (HMD)
- * @author reden - phr00t - https://github.com/phr00t
- * @author Julien Seinturier - COMEX SA - http://www.seinturier.fr
- */
-public enum HmdType {
-
- /**
- * HTC vive Head Mounted Device (HMD).
- */
- HTC_VIVE,
-
- /**
- * Occulus Rift Head Mounted Device (HMD).
- */
- OCULUS_RIFT,
-
- /**
- * OSVR generic Head Mounted Device (HMD).
- */
- OSVR,
-
- /**
- * FOVE Head Mounted Device (HMD).
- */
- FOVE,
-
- /**
- * STARVR Head Mounted Device (HMD).
- */
- STARVR,
-
- /**
- * GameFace Head Mounted Device (HMD).
- */
- GAMEFACE,
-
- /**
- * PlayStation VR (formely Morpheus) Head Mounted Device (HMD).
- */
- MORPHEUS,
-
- /**
- * Samsung GearVR Head Mounted Device (HMD).
- */
- GEARVR,
-
- /**
- * a null Head Mounted Device (HMD).
- */
- NULL,
-
- /**
- * a none Head Mounted Device (HMD).
- */
- NONE,
-
- /**
- * a not referenced Head Mounted Device (HMD).
- */
- OTHER
+package com.jme3.input.vr;
+
+/**
+ * The type of VR Head Mounted Device (HMD)
+ * @author reden - phr00t - https://github.com/phr00t
+ * @author Julien Seinturier - COMEX SA - http://www.seinturier.fr
+ */
+public enum HmdType {
+
+ /**
+ * HTC vive Head Mounted Device (HMD).
+ */
+ HTC_VIVE,
+
+ /**
+ * Valve Index Head Mounted Device (HMD).
+ */
+ VALVE_INDEX,
+
+ /**
+ * Occulus Rift Head Mounted Device (HMD).
+ */
+ OCULUS_RIFT,
+
+ /**
+ * OSVR generic Head Mounted Device (HMD).
+ */
+ OSVR,
+
+ /**
+ * FOVE Head Mounted Device (HMD).
+ */
+ FOVE,
+
+ /**
+ * STARVR Head Mounted Device (HMD).
+ */
+ STARVR,
+
+ /**
+ * GameFace Head Mounted Device (HMD).
+ */
+ GAMEFACE,
+
+ /**
+ * PlayStation VR (formely Morpheus) Head Mounted Device (HMD).
+ */
+ MORPHEUS,
+
+ /**
+ * Samsung GearVR Head Mounted Device (HMD).
+ */
+ GEARVR,
+
+ /**
+ * a null Head Mounted Device (HMD).
+ */
+ NULL,
+
+ /**
+ * a none Head Mounted Device (HMD).
+ */
+ NONE,
+
+ /**
+ * a not referenced Head Mounted Device (HMD).
+ */
+ OTHER
}
\ No newline at end of file
diff --git a/jme3-vr/src/main/java/com/jme3/input/vr/lwjgl_openvr/LWJGLOpenVR.java b/jme3-vr/src/main/java/com/jme3/input/vr/lwjgl_openvr/LWJGLOpenVR.java
index 3e7c22cd3..7615ae844 100644
--- a/jme3-vr/src/main/java/com/jme3/input/vr/lwjgl_openvr/LWJGLOpenVR.java
+++ b/jme3-vr/src/main/java/com/jme3/input/vr/lwjgl_openvr/LWJGLOpenVR.java
@@ -421,6 +421,8 @@ public class LWJGLOpenVR implements VRAPI {
completeName = completeName.toLowerCase(Locale.ENGLISH).trim();
if( completeName.contains("htc") || completeName.contains("vive") ) {
return HmdType.HTC_VIVE;
+ } else if ( completeName.contains("index") ) {
+ return HmdType.VALVE_INDEX;
} else if( completeName.contains("osvr") ) {
return HmdType.OSVR;
} else if( completeName.contains("oculus") || completeName.contains("rift") ||
diff --git a/jme3-vr/src/main/java/com/jme3/input/vr/openvr/OpenVR.java b/jme3-vr/src/main/java/com/jme3/input/vr/openvr/OpenVR.java
index ef70bccbc..a4d76018b 100644
--- a/jme3-vr/src/main/java/com/jme3/input/vr/openvr/OpenVR.java
+++ b/jme3-vr/src/main/java/com/jme3/input/vr/openvr/OpenVR.java
@@ -1,595 +1,597 @@
-/*
- * 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.openvr;
-
-import com.jme3.app.VREnvironment;
-import com.jme3.input.vr.HmdType;
-import com.jme3.input.vr.VRAPI;
-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.system.jopenvr.VR_IVRTrackedCamera_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 - COMEX SA - http://www.seinturier.fr
- */
-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 VR_IVRTrackedCamera_FnTable cameraFunctions;
-
- 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;
-
- /**
- * Convert specific OpenVR {@link com.jme3.system.jopenvr.HmdMatrix34_t HmdMatrix34_t} into JME {@link Matrix4f Matrix4f}
- * @param hmdMatrix the input matrix
- * @param mat the converted matrix
- * @return the converted matrix
- */
- public static Matrix4f convertSteamVRMatrix3ToMatrix4f(com.jme3.system.jopenvr.HmdMatrix34_t hmdMatrix, Matrix4f mat){
- mat.set(hmdMatrix.m[0], hmdMatrix.m[1], hmdMatrix.m[2], hmdMatrix.m[3],
- hmdMatrix.m[4], hmdMatrix.m[5], hmdMatrix.m[6], hmdMatrix.m[7],
- hmdMatrix.m[8], hmdMatrix.m[9], hmdMatrix.m[10], hmdMatrix.m[11],
- 0f, 0f, 0f, 1f);
- return mat;
- }
-
- /**
- * Convert specific OpenVR {@link com.jme3.system.jopenvr.HmdMatrix44_t HmdMatrix34_t} into JME {@link Matrix4f Matrix4f}
- * @param hmdMatrix the input matrix
- * @param mat the converted matrix
- * @return the converted matrix
- */
- public static Matrix4f convertSteamVRMatrix4ToMatrix4f(com.jme3.system.jopenvr.HmdMatrix44_t hmdMatrix, Matrix4f mat){
- mat.set(hmdMatrix.m[0], hmdMatrix.m[1], hmdMatrix.m[2], hmdMatrix.m[3],
- hmdMatrix.m[4], hmdMatrix.m[5], hmdMatrix.m[6], hmdMatrix.m[7],
- hmdMatrix.m[8], hmdMatrix.m[9], hmdMatrix.m[10], hmdMatrix.m[11],
- hmdMatrix.m[12], hmdMatrix.m[13], hmdMatrix.m[14], hmdMatrix.m[15]);
- return mat;
- }
-
-
- /**
- * 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;
- }
-
- public VR_IVRTrackedCamera_FnTable getTrackedCamera(){
- return cameraFunctions;
- }
-
- @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;
-
- // Init the native linking to the OpenVR library.
- try{
- JOpenVRLibrary.init();
- } catch(Throwable t){
- logger.log(Level.SEVERE, "Cannot link to OpenVR system library: "+t.getMessage(), t);
- return false;
- }
-
- 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;itrue is the use of the headset camera is allowed and false
otherwise.
- */
- public void initCamera(boolean allowed) {
- hmdErrorStore.setValue(0); // clear the error store
-
- if( allowed && vrsystemFunctions != null ) {
- IntByReference intptr = JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVRTrackedCamera_Version, hmdErrorStore);
- if (intptr != null){
- cameraFunctions = new VR_IVRTrackedCamera_FnTable(intptr.getPointer());
- if(cameraFunctions != null && hmdErrorStore.getValue() == 0 ){
- cameraFunctions.setAutoSynch(false);
- cameraFunctions.read();
- logger.config("OpenVR Camera initialized");
- }
- }
- }
- }
-
- @Override
- public void destroy() {
- JOpenVRLibrary.VR_ShutdownInternal();
- }
-
- @Override
- public boolean isInitialized() {
- return initSuccess;
- }
-
- @Override
- public void reset() {
- if( vrsystemFunctions == null ) return;
- vrsystemFunctions.ResetSeatedZeroPose.apply();
- hmdSeatToStand = null;
- }
-
- @Override
- public void getRenderSize(Vector2f store) {
- if( vrsystemFunctions == null ) {
- // 1344x1512
- store.x = 1344f;
- store.y = 1512f;
- } else {
- IntByReference x = new IntByReference();
- IntByReference y = new IntByReference();
- vrsystemFunctions.GetRecommendedRenderTargetSize.apply(x, y);
- store.x = x.getValue();
- store.y = y.getValue();
- }
- }
- /*
- @Override
- public float getFOV(int dir) {
- float val = 0f;
- if( vrsystemFunctions != null ) {
- val = vrsystemFunctions.GetFloatTrackedDeviceProperty.apply(JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd, dir, hmdErrorStore);
- }
- // verification of number
- if( val == 0f ) {
- return 55f;
- } else if( val <= 10f ) {
- // most likely a radian number
- return val * 57.2957795f;
- }
- return val;
- }
- */
-
- @Override
- public float getInterpupillaryDistance() {
- if( vrsystemFunctions == null ) return 0.065f;
- return vrsystemFunctions.GetFloatTrackedDeviceProperty.apply(JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd, JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_UserIpdMeters_Float, hmdErrorStore);
- }
-
- @Override
- public Quaternion getOrientation() {
- VRUtil.convertMatrix4toQuat(hmdPose, rotStore);
- return rotStore;
- }
-
- @Override
- public Vector3f getPosition() {
- // the hmdPose comes in rotated funny, fix that here
- hmdPose.toTranslationVector(posStore);
- posStore.x = -posStore.x;
- posStore.z = -posStore.z;
- return posStore;
- }
-
- @Override
- public void getPositionAndOrientation(Vector3f storePos, Quaternion storeRot) {
- hmdPose.toTranslationVector(storePos);
- storePos.x = -storePos.x;
- storePos.z = -storePos.z;
- storeRot.set(getOrientation());
- }
-
- @Override
- public void updatePose(){
- if(vrsystemFunctions == null) return;
- if(compositorFunctions != null) {
- compositorFunctions.WaitGetPoses.apply(hmdTrackedDevicePoseReference, JOpenVRLibrary.k_unMaxTrackedDeviceCount, null, 0);
- } else {
- // wait
- if( latencyWaitTime > 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");
- 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();
- 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();
- 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();
- 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 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 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.openvr;
+
+import com.jme3.app.VREnvironment;
+import com.jme3.input.vr.HmdType;
+import com.jme3.input.vr.VRAPI;
+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.system.jopenvr.VR_IVRTrackedCamera_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 - COMEX SA - http://www.seinturier.fr
+ */
+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 VR_IVRTrackedCamera_FnTable cameraFunctions;
+
+ 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;
+
+ /**
+ * Convert specific OpenVR {@link com.jme3.system.jopenvr.HmdMatrix34_t HmdMatrix34_t} into JME {@link Matrix4f Matrix4f}
+ * @param hmdMatrix the input matrix
+ * @param mat the converted matrix
+ * @return the converted matrix
+ */
+ public static Matrix4f convertSteamVRMatrix3ToMatrix4f(com.jme3.system.jopenvr.HmdMatrix34_t hmdMatrix, Matrix4f mat){
+ mat.set(hmdMatrix.m[0], hmdMatrix.m[1], hmdMatrix.m[2], hmdMatrix.m[3],
+ hmdMatrix.m[4], hmdMatrix.m[5], hmdMatrix.m[6], hmdMatrix.m[7],
+ hmdMatrix.m[8], hmdMatrix.m[9], hmdMatrix.m[10], hmdMatrix.m[11],
+ 0f, 0f, 0f, 1f);
+ return mat;
+ }
+
+ /**
+ * Convert specific OpenVR {@link com.jme3.system.jopenvr.HmdMatrix44_t HmdMatrix34_t} into JME {@link Matrix4f Matrix4f}
+ * @param hmdMatrix the input matrix
+ * @param mat the converted matrix
+ * @return the converted matrix
+ */
+ public static Matrix4f convertSteamVRMatrix4ToMatrix4f(com.jme3.system.jopenvr.HmdMatrix44_t hmdMatrix, Matrix4f mat){
+ mat.set(hmdMatrix.m[0], hmdMatrix.m[1], hmdMatrix.m[2], hmdMatrix.m[3],
+ hmdMatrix.m[4], hmdMatrix.m[5], hmdMatrix.m[6], hmdMatrix.m[7],
+ hmdMatrix.m[8], hmdMatrix.m[9], hmdMatrix.m[10], hmdMatrix.m[11],
+ hmdMatrix.m[12], hmdMatrix.m[13], hmdMatrix.m[14], hmdMatrix.m[15]);
+ return mat;
+ }
+
+
+ /**
+ * 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;
+ }
+
+ public VR_IVRTrackedCamera_FnTable getTrackedCamera(){
+ return cameraFunctions;
+ }
+
+ @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;
+
+ // Init the native linking to the OpenVR library.
+ try{
+ JOpenVRLibrary.init();
+ } catch(Throwable t){
+ logger.log(Level.SEVERE, "Cannot link to OpenVR system library: "+t.getMessage(), t);
+ return false;
+ }
+
+ 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;itrue is the use of the headset camera is allowed and false
otherwise.
+ */
+ public void initCamera(boolean allowed) {
+ hmdErrorStore.setValue(0); // clear the error store
+
+ if( allowed && vrsystemFunctions != null ) {
+ IntByReference intptr = JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVRTrackedCamera_Version, hmdErrorStore);
+ if (intptr != null){
+ cameraFunctions = new VR_IVRTrackedCamera_FnTable(intptr.getPointer());
+ if(cameraFunctions != null && hmdErrorStore.getValue() == 0 ){
+ cameraFunctions.setAutoSynch(false);
+ cameraFunctions.read();
+ logger.config("OpenVR Camera initialized");
+ }
+ }
+ }
+ }
+
+ @Override
+ public void destroy() {
+ JOpenVRLibrary.VR_ShutdownInternal();
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return initSuccess;
+ }
+
+ @Override
+ public void reset() {
+ if( vrsystemFunctions == null ) return;
+ vrsystemFunctions.ResetSeatedZeroPose.apply();
+ hmdSeatToStand = null;
+ }
+
+ @Override
+ public void getRenderSize(Vector2f store) {
+ if( vrsystemFunctions == null ) {
+ // 1344x1512
+ store.x = 1344f;
+ store.y = 1512f;
+ } else {
+ IntByReference x = new IntByReference();
+ IntByReference y = new IntByReference();
+ vrsystemFunctions.GetRecommendedRenderTargetSize.apply(x, y);
+ store.x = x.getValue();
+ store.y = y.getValue();
+ }
+ }
+ /*
+ @Override
+ public float getFOV(int dir) {
+ float val = 0f;
+ if( vrsystemFunctions != null ) {
+ val = vrsystemFunctions.GetFloatTrackedDeviceProperty.apply(JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd, dir, hmdErrorStore);
+ }
+ // verification of number
+ if( val == 0f ) {
+ return 55f;
+ } else if( val <= 10f ) {
+ // most likely a radian number
+ return val * 57.2957795f;
+ }
+ return val;
+ }
+ */
+
+ @Override
+ public float getInterpupillaryDistance() {
+ if( vrsystemFunctions == null ) return 0.065f;
+ return vrsystemFunctions.GetFloatTrackedDeviceProperty.apply(JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd, JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_UserIpdMeters_Float, hmdErrorStore);
+ }
+
+ @Override
+ public Quaternion getOrientation() {
+ VRUtil.convertMatrix4toQuat(hmdPose, rotStore);
+ return rotStore;
+ }
+
+ @Override
+ public Vector3f getPosition() {
+ // the hmdPose comes in rotated funny, fix that here
+ hmdPose.toTranslationVector(posStore);
+ posStore.x = -posStore.x;
+ posStore.z = -posStore.z;
+ return posStore;
+ }
+
+ @Override
+ public void getPositionAndOrientation(Vector3f storePos, Quaternion storeRot) {
+ hmdPose.toTranslationVector(storePos);
+ storePos.x = -storePos.x;
+ storePos.z = -storePos.z;
+ storeRot.set(getOrientation());
+ }
+
+ @Override
+ public void updatePose(){
+ if(vrsystemFunctions == null) return;
+ if(compositorFunctions != null) {
+ compositorFunctions.WaitGetPoses.apply(hmdTrackedDevicePoseReference, JOpenVRLibrary.k_unMaxTrackedDeviceCount, null, 0);
+ } else {
+ // wait
+ if( latencyWaitTime > 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");
+ 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();
+ 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();
+ 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();
+ 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 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("index") ) {
+ return HmdType.VALVE_INDEX;
+ } 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 convertSteamVRMatrix3ToMatrix4f(mat, hmdPoseRightEye);
+ }
+ }
+
+}