Explorar o código

Merge pull request #641 from jseinturier/jme3-vr-dev

Jme3 vr dev
empirephoenix %!s(int64=8) %!d(string=hai) anos
pai
achega
d1166f40c1

+ 1 - 0
.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

+ 6 - 6
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);
             }
         }
     }

+ 6 - 6
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);
         }
     }
     

+ 19 - 3
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.");

+ 525 - 524
jme3-vr/src/main/java/com/jme3/input/vr/OpenVR.java

@@ -1,524 +1,525 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package com.jme3.input.vr;
-
-import com.jme3.app.VREnvironment;
-import com.jme3.math.Matrix4f;
-import com.jme3.math.Quaternion;
-import com.jme3.math.Vector2f;
-import com.jme3.math.Vector3f;
-import com.jme3.renderer.Camera;
-import com.jme3.system.jopenvr.HmdMatrix34_t;
-import com.jme3.system.jopenvr.HmdMatrix44_t;
-import com.jme3.system.jopenvr.JOpenVRLibrary;
-import com.jme3.system.jopenvr.OpenVRUtil;
-import com.jme3.system.jopenvr.TrackedDevicePose_t;
-import com.jme3.system.jopenvr.VR_IVRCompositor_FnTable;
-import com.jme3.system.jopenvr.VR_IVRSystem_FnTable;
-import com.jme3.util.VRUtil;
-import com.sun.jna.Memory;
-import com.sun.jna.Pointer;
-import com.sun.jna.ptr.FloatByReference;
-import com.sun.jna.ptr.IntByReference;
-import com.sun.jna.ptr.LongByReference;
-
-import java.nio.IntBuffer;
-import java.util.Locale;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * A class that wraps an <a href="https://github.com/ValveSoftware/openvr/wiki/API-Documentation">OpenVR</a> system. 
- * @author reden - phr00t - https://github.com/phr00t
- * @author Julien Seinturier - (c) 2016 - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a>
- */
-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 <a href="https://github.com/ValveSoftware/openvr/wiki/API-Documentation">OpenVR</a> 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<poseMatrices.length;i++) poseMatrices[i] = new Matrix4f();
-
-            timePerFrame = 1.0 / hmdDisplayFrequency.get(0);
-            
-            // disable all this stuff which kills performance
-            hmdTrackedDevicePoseReference.setAutoRead(false);
-            hmdTrackedDevicePoseReference.setAutoWrite(false);
-            hmdTrackedDevicePoseReference.setAutoSynch(false);
-            for(int i=0;i<JOpenVRLibrary.k_unMaxTrackedDeviceCount;i++) {
-                hmdTrackedDevicePoses[i].setAutoRead(false);
-                hmdTrackedDevicePoses[i].setAutoWrite(false);
-                hmdTrackedDevicePoses[i].setAutoSynch(false);
-            }
-            
-            // init controllers for the first time
-            VRinput = new OpenVRInput(environment);
-            VRinput.init();
-            VRinput.updateConnectedControllers();
-            
-            // init bounds & chaperone info
-            VRBounds.init();
-            
-            logger.config("Initializing OpenVR system [SUCCESS]");
-            initSuccess = true;
-            return true;
-        }
-    }
-    
-    @Override
-    public boolean initVRCompositor(boolean allowed) {
-        hmdErrorStore.setValue(0); // clear the error store
-        if( allowed && vrsystemFunctions != null ) {
-        	
-        	IntByReference intptr = JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVRCompositor_Version, hmdErrorStore);
-        	if (intptr != null){
-        	
-        		if (intptr.getPointer() != null){
-            		compositorFunctions = new VR_IVRCompositor_FnTable(intptr.getPointer());
-                    if(compositorFunctions != null && hmdErrorStore.getValue() == 0 ){          
-                        compositorFunctions.setAutoSynch(false);
-                        compositorFunctions.read();
-                        if( environment.isSeatedExperience() ) {                    
-                            compositorFunctions.SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated);
-                        } else {
-                            compositorFunctions.SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding);                
-                        }
-                        logger.config("OpenVR Compositor initialized");
-                    } else {
-                        logger.severe("OpenVR Compositor error: " + hmdErrorStore.getValue());
-                        compositorFunctions = null;
-                    }
-        		} else {
-        			logger.log(Level.SEVERE, "Cannot get valid pointer for generic interface \""+JOpenVRLibrary.IVRCompositor_Version+"\", "+OpenVRUtil.getEVRInitErrorString(hmdErrorStore.getValue())+" ("+hmdErrorStore.getValue()+")");
-        			compositorFunctions = null;
-        		}
-
-        	} else {
-        		logger.log(Level.SEVERE, "Cannot get generic interface for \""+JOpenVRLibrary.IVRCompositor_Version+"\", "+OpenVRUtil.getEVRInitErrorString(hmdErrorStore.getValue())+" ("+hmdErrorStore.getValue()+")");
-        		compositorFunctions = null;
-        	}
-        	
-            
-        }
-        if( compositorFunctions == null ) {
-            logger.severe("Skipping VR Compositor...");
-            if( vrsystemFunctions != null ) {
-                vsyncToPhotons = vrsystemFunctions.GetFloatTrackedDeviceProperty.apply(JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd, JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_SecondsFromVsyncToPhotons_Float, hmdErrorStore);
-            } else {
-                vsyncToPhotons = 0f;
-            }
-        }
-        return compositorFunctions != null;
-    }
-
-    @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");
-                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 <a href="https://github.com/ValveSoftware/openvr/wiki/API-Documentation">OpenVR</a> system. 
+ * @author reden - phr00t - https://github.com/phr00t
+ * @author Julien Seinturier - (c) 2016 - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a>
+ */
+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 <a href="https://github.com/ValveSoftware/openvr/wiki/API-Documentation">OpenVR</a> 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<poseMatrices.length;i++) poseMatrices[i] = new Matrix4f();
+
+            timePerFrame = 1.0 / hmdDisplayFrequency.get(0);
+            
+            // disable all this stuff which kills performance
+            hmdTrackedDevicePoseReference.setAutoRead(false);
+            hmdTrackedDevicePoseReference.setAutoWrite(false);
+            hmdTrackedDevicePoseReference.setAutoSynch(false);
+            for(int i=0;i<JOpenVRLibrary.k_unMaxTrackedDeviceCount;i++) {
+                hmdTrackedDevicePoses[i].setAutoRead(false);
+                hmdTrackedDevicePoses[i].setAutoWrite(false);
+                hmdTrackedDevicePoses[i].setAutoSynch(false);
+            }
+            
+            // init controllers for the first time
+            VRinput = new OpenVRInput(environment);
+            VRinput.init();
+            VRinput.updateConnectedControllers();
+            
+            // init bounds & chaperone info
+            environment.getVRBounds().init(this);
+            
+            logger.config("Initializing OpenVR system [SUCCESS]");
+            initSuccess = true;
+            return true;
+        }
+    }
+    
+    @Override
+    public boolean initVRCompositor(boolean allowed) {
+        hmdErrorStore.setValue(0); // clear the error store
+        if( allowed && vrsystemFunctions != null ) {
+        	
+        	IntByReference intptr = JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVRCompositor_Version, hmdErrorStore);
+        	if (intptr != null){
+        	
+        		if (intptr.getPointer() != null){
+            		compositorFunctions = new VR_IVRCompositor_FnTable(intptr.getPointer());
+                    if(compositorFunctions != null && hmdErrorStore.getValue() == 0 ){          
+                        compositorFunctions.setAutoSynch(false);
+                        compositorFunctions.read();
+                        if( environment.isSeatedExperience() ) {                    
+                            compositorFunctions.SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated);
+                        } else {
+                            compositorFunctions.SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding);                
+                        }
+                        logger.config("OpenVR Compositor initialized");
+                    } else {
+                        logger.severe("OpenVR Compositor error: " + hmdErrorStore.getValue());
+                        compositorFunctions = null;
+                    }
+        		} else {
+        			logger.log(Level.SEVERE, "Cannot get valid pointer for generic interface \""+JOpenVRLibrary.IVRCompositor_Version+"\", "+OpenVRUtil.getEVRInitErrorString(hmdErrorStore.getValue())+" ("+hmdErrorStore.getValue()+")");
+        			compositorFunctions = null;
+        		}
+
+        	} else {
+        		logger.log(Level.SEVERE, "Cannot get generic interface for \""+JOpenVRLibrary.IVRCompositor_Version+"\", "+OpenVRUtil.getEVRInitErrorString(hmdErrorStore.getValue())+" ("+hmdErrorStore.getValue()+")");
+        		compositorFunctions = null;
+        	}
+        	
+            
+        }
+        if( compositorFunctions == null ) {
+            logger.severe("Skipping VR Compositor...");
+            if( vrsystemFunctions != null ) {
+                vsyncToPhotons = vrsystemFunctions.GetFloatTrackedDeviceProperty.apply(JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd, JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_SecondsFromVsyncToPhotons_Float, hmdErrorStore);
+            } else {
+                vsyncToPhotons = 0f;
+            }
+        }
+        return compositorFunctions != null;
+    }
+
+    @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");
+                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);
+        }
+    }
+  
+}

+ 89 - 30
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;i++) {
-                    int classCallback = ((OpenVR)environment.getVRHardware()).getVRSystem().GetTrackedDeviceClass.apply(i);
+        		int classCallback = ((OpenVR)environment.getVRHardware()).getVRSystem().GetTrackedDeviceClass.apply(i);
         		if( classCallback == JOpenVRLibrary.ETrackedDeviceClass.ETrackedDeviceClass_TrackedDeviceClass_Controller || classCallback == JOpenVRLibrary.ETrackedDeviceClass.ETrackedDeviceClass_TrackedDeviceClass_GenericTracker) {
-        			
+	
         			String controllerName   = "Unknown";
     				String manufacturerName = "Unknown";
     				try {
@@ -425,6 +478,12 @@ public class OpenVRInput implements VRInputAPI {
         			
         			controllerIndex[controllerCount] = i;
         			
+        			// Adding tracked controller to control.
+        			if (trackedControllers == null){
+        				trackedControllers = new ArrayList<VRTrackedController>(JOpenVRLibrary.k_unMaxTrackedDeviceCount);
+        			}
+        			trackedControllers.add(new OpenVRTrackedController(i, this, controllerName, manufacturerName, environment));
+        			
         			// Send an Haptic pulse to the controller
         			triggerHapticPulse(controllerCount, 1.0f);
         			

+ 93 - 0
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;
+	}
+}

+ 5 - 5
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 <code>true</code> if the initialization is a success and <code>false</code> 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;
     }
     

+ 40 - 0
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 - <a href="http://www.jorigin.org">http:/www.jorigin.org</a>
@@ -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();
 }

+ 26 - 15
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

+ 12 - 4
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.

+ 4 - 4
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;
     }
     

+ 36 - 8
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