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

Deprecated VRApplication. Now VRAppState should be used.
fix-456
empirephoenix 8 years ago committed by GitHub
commit ed4e614722
  1. 526
      jme3-vr/src/main/java/com/jme3/app/VRAppState.java
  2. 35
      jme3-vr/src/main/java/com/jme3/app/VRApplication.java
  3. 485
      jme3-vr/src/main/java/com/jme3/app/VREnvironment.java
  4. 53
      jme3-vr/src/main/java/com/jme3/input/vr/OSVR.java
  5. 47
      jme3-vr/src/main/java/com/jme3/input/vr/OSVRInput.java
  6. 35
      jme3-vr/src/main/java/com/jme3/input/vr/OpenVR.java
  7. 107
      jme3-vr/src/main/java/com/jme3/input/vr/OpenVRInput.java
  8. 11
      jme3-vr/src/main/java/com/jme3/input/vr/VRAPI.java
  9. 7
      jme3-vr/src/main/java/com/jme3/input/vr/VRInputAPI.java
  10. 2
      jme3-vr/src/main/java/com/jme3/post/FilterUtil.java
  11. 2
      jme3-vr/src/main/java/com/jme3/scene/CenterQuad.java
  12. 8
      jme3-vr/src/main/java/com/jme3/shadow/AbstractShadowRendererVR.java
  13. 8
      jme3-vr/src/main/java/com/jme3/shadow/DirectionalLightShadowRendererVR.java
  14. 39
      jme3-vr/src/main/java/com/jme3/shadow/InstancedDirectionalShadowFilter.java
  15. 2
      jme3-vr/src/main/java/com/jme3/system/lwjgl/LwjglWindowVR.java
  16. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientkit/OsvrClientKitLibrary.java
  17. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_AccelerationReport.java
  18. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_AccelerationState.java
  19. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_AnalogReport.java
  20. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_AngularAccelerationReport.java
  21. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_AngularVelocityReport.java
  22. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_ButtonReport.java
  23. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_DirectionReport.java
  24. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_EyeTracker2DReport.java
  25. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_EyeTracker3DReport.java
  26. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_EyeTracker3DState.java
  27. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_EyeTrackerBlinkReport.java
  28. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_IncrementalQuaternion.java
  29. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_LinearAccelerationReport.java
  30. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_LinearVelocityReport.java
  31. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_Location2DReport.java
  32. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_NaviPositionReport.java
  33. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_NaviVelocityReport.java
  34. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_OrientationReport.java
  35. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_Pose3.java
  36. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_PoseReport.java
  37. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_PositionReport.java
  38. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_Quaternion.java
  39. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_Vec2.java
  40. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_Vec3.java
  41. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_VelocityReport.java
  42. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OSVR_VelocityState.java
  43. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrclientreporttypes/OsvrClientReportTypesLibrary.java
  44. 5
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrdisplay/OsvrDisplayLibrary.java
  45. 8
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrinterface/OsvrInterfaceLibrary.java
  46. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrmatrixconventions/OSVR_Pose3.java
  47. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrmatrixconventions/OSVR_Quaternion.java
  48. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrmatrixconventions/OSVR_Vec3.java
  49. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrmatrixconventions/OsvrMatrixConventionsLibrary.java
  50. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanager/OSVR_ProjectionMatrix.java
  51. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanager/OSVR_RGB.java
  52. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanager/OSVR_RenderParams.java
  53. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanager/OSVR_ViewportDescription.java
  54. 22
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanager/OsvrRenderManagerLibrary.java
  55. 6
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanageropengl/OSVR_GraphicsLibraryOpenGL.java
  56. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanageropengl/OSVR_OpenGLContextParams.java
  57. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanageropengl/OSVR_OpenGLToolkitFunctions.java
  58. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanageropengl/OSVR_OpenResultsOpenGL.java
  59. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanageropengl/OSVR_ProjectionMatrix.java
  60. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanageropengl/OSVR_RGB.java
  61. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanageropengl/OSVR_RenderBufferOpenGL.java
  62. 4
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanageropengl/OSVR_RenderInfoOpenGL.java
  63. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanageropengl/OSVR_RenderParams.java
  64. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanageropengl/OSVR_ViewportDescription.java
  65. 34
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrrendermanageropengl/OsvrRenderManagerOpenGLLibrary.java
  66. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrtimevalue/OSVR_TimeValue.java
  67. 2
      jme3-vr/src/main/java/com/jme3/system/osvr/osvrtimevalue/OsvrTimeValueLibrary.java
  68. 223
      jme3-vr/src/main/java/com/jme3/util/AbstractVRViewManager.java
  69. 15
      jme3-vr/src/main/java/com/jme3/util/VRGUIPositioningMode.java
  70. 474
      jme3-vr/src/main/java/com/jme3/util/VRGuiManager.java
  71. 334
      jme3-vr/src/main/java/com/jme3/util/VRMouseManager.java
  72. 7
      jme3-vr/src/main/java/com/jme3/util/VRUtil.java
  73. 156
      jme3-vr/src/main/java/com/jme3/util/VRViewManager.java
  74. 957
      jme3-vr/src/main/java/com/jme3/util/VRViewManagerOSVR.java
  75. 732
      jme3-vr/src/main/java/com/jme3/util/VRViewManagerOpenVR.java
  76. 107
      jme3-vr/src/main/java/jmevr/util/MeshUtil.java
  77. 334
      jme3-vr/src/main/java/jmevr/util/VRGuiManager.java
  78. 234
      jme3-vr/src/main/java/jmevr/util/VRMouseManager.java
  79. 863
      jme3-vr/src/main/java/jmevr/util/VRViewManager.java

@ -1,23 +1,53 @@
package com.jme3.app; package com.jme3.app;
/*
* Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import com.jme3.app.Application; import com.jme3.app.Application;
import com.jme3.app.state.AbstractAppState; import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager; import com.jme3.app.state.AppStateManager;
import com.jme3.input.vr.OSVR;
import com.jme3.input.vr.OpenVR;
import com.jme3.input.vr.VRAPI; import com.jme3.input.vr.VRAPI;
import com.jme3.input.vr.VRInputAPI; import com.jme3.input.vr.VRInputAPI;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.post.PreNormalCaching; import com.jme3.post.PreNormalCaching;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort; import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.system.AppSettings; import com.jme3.system.AppSettings;
import com.jme3.system.jopenvr.JOpenVRLibrary; import com.jme3.util.VRGUIPositioningMode;
import com.jme3.util.VRGuiManager;
import com.jme3.util.VRMouseManager;
import com.jme3.util.VRViewManager;
import java.awt.GraphicsDevice; import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment; import java.awt.GraphicsEnvironment;
@ -30,11 +60,6 @@ import java.util.Locale;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import jmevr.util.VRGuiManager;
import jmevr.util.VRMouseManager;
import jmevr.util.VRViewManager;
import jmevr.util.VRGuiManager.POSITIONING_MODE;
/** /**
* A JMonkey app state dedicated to Virtual Reality. * A JMonkey app state dedicated to Virtual Reality.
* An application that want to use VR devices (HTC vive, ...) has to use this app state.<br> * An application that want to use VR devices (HTC vive, ...) has to use this app state.<br>
@ -53,38 +78,11 @@ public class VRAppState extends AbstractAppState {
private static final Logger logger = Logger.getLogger(VRAppState.class.getName()); private static final Logger logger = Logger.getLogger(VRAppState.class.getName());
/**
* The underlying system VR API. By default set to {@link VRConstants#SETTING_VRAPI_OPENVR_VALUE}.
*/
public int vrBinding = VRConstants.SETTING_VRAPI_OPENVR_VALUE;
/** /**
* Is the application has not to start within VR mode (default is <code>false</code>). * Is the application has not to start within VR mode (default is <code>false</code>).
*/ */
public boolean DISABLE_VR = false; public boolean DISABLE_VR = false;
private VRAPI VRhardware = null;
private VRGuiManager guiManager = null;
private VRMouseManager mouseManager = null;
private VRViewManager viewmanager = null;
private String OS;
private Camera dummyCam;
private Spatial observer = null;
private boolean VRSupportedOS;
private boolean forceVR = false;;
private boolean disableSwapBuffers = true;
private boolean disableVR = false;
private boolean seated;
private boolean nogui;
private boolean instanceVR = false;
private float defaultFOV = 108f;
private float defaultAspect = 1f;
private float fFar = 1000f; private float fFar = 1000f;
@ -94,9 +92,6 @@ public class VRAppState extends AbstractAppState {
private float resMult = 1f; private float resMult = 1f;
private boolean useCompositor = true;
private boolean compositorOS;
/* /*
where is the headset pointing, after all rotations are combined? where is the headset pointing, after all rotations are combined?
depends on observer rotation, if any depends on observer rotation, if any
@ -107,32 +102,27 @@ public class VRAppState extends AbstractAppState {
private AppStateManager stateManager = null; private AppStateManager stateManager = null;
private AppSettings settings = null; private AppSettings settings = null;
private VREnvironment environment = null;
/** /**
* Create a new default VR app state. * Create a new default VR app state that relies on the given {@link VREnvironment VR environment}.
* @param environment the {@link VREnvironment VR environment} that this app state is using.
*/ */
public VRAppState() { public VRAppState(VREnvironment environment) {
super(); super();
dummyCam = new Camera(); this.environment = environment;
// Create the GUI manager.
guiManager = new VRGuiManager();
// Create a new view manager.
viewmanager = new VRViewManager();
// Create a new mouse manager.
mouseManager = new VRMouseManager();
this.setSettings(environment.getSettings());
} }
/** /**
* Create a new VR app state with given settings. * Create a new VR app state with given settings. The app state relies on the the given {@link VREnvironment VR environment}.
* @param settings the settings to use. * @param settings the settings to use.
* @param environment the {@link VREnvironment VR environment} that this app state is using.
*/ */
public VRAppState(AppSettings settings){ public VRAppState(AppSettings settings, VREnvironment environment){
this(); this(environment);
this.settings = settings; this.settings = settings;
processSettings(settings); processSettings(settings);
} }
@ -152,7 +142,7 @@ public class VRAppState extends AbstractAppState {
* @param renderManager the {@link RenderManager render manager}. * @param renderManager the {@link RenderManager render manager}.
*/ */
public void simpleRender(RenderManager renderManager) { public void simpleRender(RenderManager renderManager) {
PreNormalCaching.resetCache(isInVR()); PreNormalCaching.resetCache(environment.isInVR());
} }
/** /**
@ -181,163 +171,18 @@ public class VRAppState extends AbstractAppState {
*/ */
public void setResolutionMultiplier(float val) { public void setResolutionMultiplier(float val) {
resMult = val; resMult = val;
if( viewmanager != null ){ if( environment.getVRViewManager() != null ){
viewmanager.setResolutionMultiplier(resMult); environment.getVRViewManager().setResolutionMultiplier(resMult);
}
}
/**
* Is the VR compositor is active.
* @return <code>true</code> if the VR compositor is active and <code>false</code> otherwise.
*/
public boolean compositorAllowed() {
return useCompositor && compositorOS;
}
/**
* Get if the system currently support VR.
* @return <code>true</code> if the system currently support VR and <code>false</Code> otherwise.
*/
public boolean isVRSupported() {
return VRSupportedOS;
}
/**
* Get the {@link Camera camera} attached to this application state.
* 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 to this application state.
*/
public Camera getCamera() {
if( isInVR() && viewmanager != null && viewmanager.getLeftCamera() != null ) {
return dummyCam;
}
return application.getCamera();
}
/**
* Can be used to change seated experience during runtime.
* @param isSeated <code>true</code> if designed for sitting, <code>false</code> for standing/roomscale
* @see #isSeatedExperience()
*/
public void setSeatedExperience(boolean isSeated) {
seated = isSeated;
if( VRhardware instanceof OpenVR ) {
if( VRhardware.getCompositor() == null ) return;
if( seated ) {
((OpenVR)VRhardware).getCompositor().SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated);
} else {
((OpenVR)VRhardware).getCompositor().SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding);
}
}
}
/**
* Check if the application is configured as a seated experience.
* @return <code>true</code> if the application is configured as a seated experience and <code>false</code> otherwise.
* @see #setSeatedExperience(boolean)
*/
public boolean isSeatedExperience() {
return seated;
}
/**
* Reset headset pose if seating experience.
*/
public void resetSeatedPose(){
if( VRSupportedOS == false || isSeatedExperience() == false ) return;
VRhardware.reset();
}
/**
* Check if the rendering is instanced (see <a href="https://en.wikipedia.org/wiki/Geometry_instancing">Geometry instancing</a>).
* @return <code>true</code> if the rendering is instanced and <code>false</code> otherwise.
*/
public boolean isInstanceVRRendering() {
return instanceVR && isInVR();
}
/**
* Check if the VR mode is enabled.
* @return <code>true</code> if the VR mode is enabled and <code>false</code> otherwise.
*/
public boolean isInVR() {
return DISABLE_VR == false && (forceVR || VRSupportedOS && VRhardware != null && VRhardware.isInitialized());
}
/**
* 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;
}
/** /**
* Move filters from the main scene into the eye's. * Move filters from the main scene into the eye's.
* This removes filters from the main scene. * This removes filters from the main scene.
*/ */
public void moveScreenProcessingToVR() { public void moveScreenProcessingToVR() {
if( isInVR() ) { environment.getVRViewManager().moveScreenProcessingToEyes();
viewmanager.moveScreenProcessingToEyes();
}
}
/**
* Check if the application has a GUI overlay attached.
* @return <code>true</code> if the application has a GUI overlay attached and <code>false</code> otherwise.
*/
public boolean hasTraditionalGUIOverlay() {
return !nogui;
}
/**
* 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 ) {
return getCamera();
}
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 the application {@link #getCamera() camera}.
* @param observer the scene observer.
*/
public void setObserver(Spatial observer) {
this.observer = observer;
} }
/** /**
@ -346,17 +191,20 @@ public class VRAppState extends AbstractAppState {
* @see #getFinalObserverPosition() * @see #getFinalObserverPosition()
*/ */
public Quaternion getFinalObserverRotation() { public Quaternion getFinalObserverRotation() {
if( viewmanager == null ) { if( environment.getVRViewManager() == null ) {
if( observer == null ) { if( environment.getObserver() == null ) {
return getCamera().getRotation(); return environment.getCamera().getRotation();
} else return observer.getWorldRotation(); } else {
return ((Spatial)environment.getObserver()).getWorldRotation();
} }
if( observer == null ) { }
tempq.set(dummyCam.getRotation());
if( environment.getObserver() == null ) {
tempq.set(environment.getDummyCamera().getRotation());
} else { } else {
tempq.set(observer.getWorldRotation()); tempq.set(((Spatial)environment.getObserver()).getWorldRotation());
} }
return tempq.multLocal(VRhardware.getOrientation()); return tempq.multLocal(environment.getVRHardware().getOrientation());
} }
/** /**
@ -365,40 +213,22 @@ public class VRAppState extends AbstractAppState {
* @see #getFinalObserverRotation() * @see #getFinalObserverRotation()
*/ */
public Vector3f getFinalObserverPosition() { public Vector3f getFinalObserverPosition() {
if( viewmanager == null ) { if( environment.getVRViewManager() == null ) {
if( observer == null ) { if( environment.getObserver() == null ) {
return getCamera().getLocation(); return environment.getCamera().getLocation();
} else return observer.getWorldTranslation();
}
Vector3f pos = VRhardware.getPosition();
if( observer == null ) {
dummyCam.getRotation().mult(pos, pos);
return pos.addLocal(dummyCam.getLocation());
} else{ } else{
observer.getWorldRotation().mult(pos, pos); return ((Spatial)environment.getObserver()).getWorldTranslation();
return pos.addLocal(observer.getWorldTranslation());
} }
} }
/** Vector3f pos = environment.getVRHardware().getPosition();
* Set the VR headset height from the ground. if( environment.getObserver() == null ) {
* @param amount the VR headset height from the ground. environment.getDummyCamera().getRotation().mult(pos, pos);
* @see #getVRHeightAdjustment() return pos.addLocal(environment.getDummyCamera().getLocation());
*/ } else {
public void setVRHeightAdjustment(float amount) { ((Spatial)environment.getObserver()).getWorldRotation().mult(pos, pos);
if( viewmanager != null ) viewmanager.setHeightAdjustment(amount); return pos.addLocal(((Spatial)environment.getObserver()).getWorldTranslation());
}
/**
* 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;
} }
/** /**
@ -407,8 +237,11 @@ public class VRAppState extends AbstractAppState {
* @see #getRightViewPort() * @see #getRightViewPort()
*/ */
public ViewPort getLeftViewPort() { public ViewPort getLeftViewPort() {
if( viewmanager == null ) return application.getViewPort(); if( environment.getVRViewManager() == null ){
return viewmanager.getLeftViewport(); return application.getViewPort();
}
return environment.getVRViewManager().getLeftViewport();
} }
/** /**
@ -417,8 +250,10 @@ public class VRAppState extends AbstractAppState {
* @see #getLeftViewPort() * @see #getLeftViewPort()
*/ */
public ViewPort getRightViewPort() { public ViewPort getRightViewPort() {
if( viewmanager == null ) return application.getViewPort(); if( environment.getVRViewManager() == null ){
return viewmanager.getRightViewport(); return application.getViewPort();
}
return environment.getVRViewManager().getRightViewport();
} }
/** /**
@ -426,11 +261,15 @@ public class VRAppState extends AbstractAppState {
* @param clr the background color. * @param clr the background color.
*/ */
public void setBackgroundColors(ColorRGBA clr) { public void setBackgroundColors(ColorRGBA clr) {
if( viewmanager == null ) { if( environment.getVRViewManager() == null ) {
application.getViewPort().setBackgroundColor(clr); application.getViewPort().setBackgroundColor(clr);
} else if( viewmanager.getLeftViewport() != null ) { } else if( environment.getVRViewManager().getLeftViewport() != null ) {
viewmanager.getLeftViewport().setBackgroundColor(clr);
if( viewmanager.getRightViewport() != null ) viewmanager.getRightViewport().setBackgroundColor(clr); environment.getVRViewManager().getLeftViewport().setBackgroundColor(clr);
if( environment.getVRViewManager().getRightViewport() != null ){
environment.getVRViewManager().getRightViewport().setBackgroundColor(clr);
}
} }
} }
@ -452,12 +291,45 @@ public class VRAppState extends AbstractAppState {
return stateManager; return stateManager;
} }
/**
* 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() {
return environment.getObserver();
}
/**
* Set the scene observer. The VR headset will be linked to it. If no observer is set, the VR headset is linked to the the application {@link #getCamera() camera}.
* @param observer the scene observer.
*/
public void setObserver(Spatial observer) {
environment.setObserver(observer);
}
/**
* Check if the rendering is instanced (see <a href="https://en.wikipedia.org/wiki/Geometry_instancing">Geometry instancing</a>).
* @return <code>true</code> if the rendering is instanced and <code>false</code> otherwise.
*/
public boolean isInstanceRendering() {
return environment.isInstanceRendering();
}
/**
* Return the {@link VREnvironment VR environment} on which this app state relies.
* @return the {@link VREnvironment VR environment} on which this app state relies.
*/
public VREnvironment getVREnvironment(){
return environment;
}
/** /**
* Get the VR underlying hardware. * Get the VR underlying hardware.
* @return the VR underlying hardware. * @return the VR underlying hardware.
*/ */
public VRAPI getVRHardware() { public VRAPI getVRHardware() {
return VRhardware; return getVREnvironment().getVRHardware();
} }
/** /**
@ -465,11 +337,11 @@ public class VRAppState extends AbstractAppState {
* @return the VR dedicated input. * @return the VR dedicated input.
*/ */
public VRInputAPI getVRinput() { public VRInputAPI getVRinput() {
if( VRhardware == null ){ if( getVREnvironment().getVRHardware() == null ){
return null; return null;
} }
return VRhardware.getVRinput(); return getVREnvironment().getVRHardware().getVRinput();
} }
/** /**
@ -477,23 +349,23 @@ public class VRAppState extends AbstractAppState {
* @return the VR view manager. * @return the VR view manager.
*/ */
public VRViewManager getVRViewManager() { public VRViewManager getVRViewManager() {
return viewmanager; return getVREnvironment().getVRViewManager();
} }
/** /**
* Get the GUI manager attached to this application. * Get the GUI manager attached to this app state.
* @return the GUI manager attached to this application. * @return the GUI manager attached to this app state.
*/ */
public VRGuiManager getVRGUIManager(){ public VRGuiManager getVRGUIManager(){
return guiManager; return getVREnvironment().getVRGUIManager();
} }
/** /**
* Get the VR mouse manager attached to this application. * Get the VR mouse manager attached to this app state.
* @return the VR mouse manager attached to this application. * @return the VR mouse manager attached to this application.
*/ */
public VRMouseManager getVRMouseManager(){ public VRMouseManager getVRMouseManager(){
return mouseManager; return getVREnvironment().getVRMouseManager();
} }
/** /**
@ -519,10 +391,10 @@ public class VRAppState extends AbstractAppState {
public void update(float tpf) { public void update(float tpf) {
// update VR pose & cameras // update VR pose & cameras
if( viewmanager != null ) { if( environment.getVRViewManager() != null ) {
viewmanager.update(tpf); environment.getVRViewManager().update(tpf);
} else if( observer != null ) { } else if( environment.getObserver() != null ) {
getCamera().setFrame(observer.getWorldTranslation(), observer.getWorldRotation()); environment.getCamera().setFrame(((Spatial)environment.getObserver()).getWorldTranslation(), ((Spatial)environment.getObserver()).getWorldRotation());
} }
//FIXME: check if this code is necessary. //FIXME: check if this code is necessary.
@ -535,7 +407,7 @@ public class VRAppState extends AbstractAppState {
spatial.updateGeometricState(); spatial.updateGeometricState();
} }
if( isInVR() == false || guiManager.getPositioningMode() == POSITIONING_MODE.MANUAL ) { if( environment.isInVR() == false || environment.getVRGUIManager().getPositioningMode() == VRGUIPositioningMode.MANUAL ) {
// only update geometric state here if GUI is in manual mode, or not in VR // only update geometric state here if GUI is in manual mode, or not in VR
// it will get updated automatically in the viewmanager update otherwise // it will get updated automatically in the viewmanager update otherwise
spatialIter = application.getGuiViewPort().getScenes().iterator(); spatialIter = application.getGuiViewPort().getScenes().iterator();
@ -546,17 +418,17 @@ public class VRAppState extends AbstractAppState {
} }
} }
// use the analog control on the first tracked controller to push around the mouse // use the analog control on the first tracked controller to push around the mouse
getVRMouseManager().updateAnalogAsMouse(0, null, null, null, tpf); environment.getVRMouseManager().updateAnalogAsMouse(0, null, null, null, tpf);
} }
@Override @Override
public void postRender() { public void postRender() {
super.postRender(); super.postRender();
// update compositor?
if( viewmanager != null ) { // update compositor
viewmanager.sendTextures(); if( environment.getVRViewManager() != null ) {
environment.getVRViewManager().postRender();
} }
} }
@ -571,27 +443,21 @@ public class VRAppState extends AbstractAppState {
// for late GUI placement for VR purposes // for late GUI placement for VR purposes
Logger.getLogger("com.jme3").setLevel(Level.SEVERE); Logger.getLogger("com.jme3").setLevel(Level.SEVERE);
// VR module attch
guiManager.attach(this, app);
viewmanager.attach(this, app);
mouseManager.attach(this, app);
app.getCamera().setFrustumFar(fFar); app.getCamera().setFrustumFar(fFar);
app.getCamera().setFrustumNear(fNear); app.getCamera().setFrustumNear(fNear);
dummyCam = app.getCamera().clone();
if( isInVR() ) { if( environment.isInVR() ) {
logger.config("VR mode enabled."); logger.config("VR mode enabled.");
if( VRhardware != null ) { if( environment.getVRHardware() != null ) {
VRhardware.initVRCompositor(compositorAllowed()); environment.getVRHardware().initVRCompositor(environment.compositorAllowed());
} else { } else {
logger.warning("No VR system found."); logger.warning("No VR system found.");
} }
viewmanager.setResolutionMultiplier(resMult); environment.getVRViewManager().setResolutionMultiplier(resMult);
//inputManager.addMapping(RESET_HMD, new KeyTrigger(KeyInput.KEY_F9)); //inputManager.addMapping(RESET_HMD, new KeyTrigger(KeyInput.KEY_F9));
//setLostFocusBehavior(LostFocusBehavior.Disabled); //setLostFocusBehavior(LostFocusBehavior.Disabled);
} else { } else {
@ -600,8 +466,8 @@ public class VRAppState extends AbstractAppState {
//guiViewPort.attachScene(guiNode); //guiViewPort.attachScene(guiNode);
} }
if( viewmanager != null ) { if( environment.getVRViewManager() != null ) {
viewmanager.initialize(); environment.getVRViewManager().initialize();
} }
} }
@ -616,33 +482,20 @@ public class VRAppState extends AbstractAppState {
logger.config("Using given settings."); logger.config("Using given settings.");
} }
// we are going to use OpenVR now, not the Oculus Rift // Attach VR environment to the application
// OpenVR does support the Rift if (!environment.isInitialized()){
OS = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH); environment.initialize();
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 && disableVR == false ) {
if( vrBinding == VRConstants.SETTING_VRAPI_OSVR_VALUE ) {
VRhardware = new OSVR(this);
logger.config("Creating OSVR wrapper [SUCCESS]");
} else if( vrBinding == VRConstants.SETTING_VRAPI_OPENVR_VALUE ) {
VRhardware = new OpenVR(this);
logger.config("Creating OpenVR wrapper [SUCCESS]");
} else {
logger.config("Cannot create VR binding: "+vrBinding+" [FAILED]");
} }
if( VRhardware.initialize() ) { if (environment.isInitialized()){
logger.config("VR native wrapper initialized [SUCCESS]"); environment.atttach(this, stateManager.getApplication());
} else { } else {
logger.warning("VR native wrapper initialized [FAILED]"); logger.severe("Cannot attach VR environment to the VR app state as its not initialized.");
}
} }
GraphicsDevice defDev = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); GraphicsDevice defDev = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
if( isInVR() && !compositorAllowed() ) { if( environment.isInVR() && !environment.compositorAllowed() ) {
// "easy extended" mode // "easy extended" mode
// setup experimental JFrame on external device // setup experimental JFrame on external device
// first, find the VR device // first, find the VR device
@ -694,14 +547,14 @@ public class VRAppState extends AbstractAppState {
logger.config("Cannot access to external screen."); logger.config("Cannot access to external screen.");
} }
} else { } else {
if (!isInVR()){ if (!environment.isInVR()){
logger.config("Cannot switch to VR mode (VR disabled by user)."); logger.config("Cannot switch to VR mode (VR disabled by user).");
} else if (!compositorAllowed()){ } else if (!environment.compositorAllowed()){
logger.warning("Cannot switch to VR mode (VR not supported)."); logger.warning("Cannot switch to VR mode (VR not supported).");
} }
} }
if( !isInVR() ) { if( !environment.isInVR() ) {
//FIXME: Handling GLFW workaround on MacOS //FIXME: Handling GLFW workaround on MacOS
boolean macOs = false; boolean macOs = false;
@ -742,10 +595,10 @@ public class VRAppState extends AbstractAppState {
settings.setHeight(yWin); settings.setHeight(yWin);
settings.setBitsPerPixel(32); settings.setBitsPerPixel(32);
settings.setFrameRate(0); settings.setFrameRate(0);
settings.setFrequency(VRhardware.getDisplayFrequency()); settings.setFrequency(environment.getVRHardware().getDisplayFrequency());
settings.setFullscreen(false); settings.setFullscreen(false);
settings.setVSync(false); // stop vsyncing on primary monitor! settings.setVSync(false); // stop vsyncing on primary monitor!
settings.setSwapBuffers(disableSwapBuffers); settings.setSwapBuffers(environment.isSwapBuffers());
} }
// Updating application settings // Updating application settings
@ -756,11 +609,9 @@ public class VRAppState extends AbstractAppState {
@Override @Override
public void cleanup() { public void cleanup() {
if( VRhardware != null ) { if( environment.getVRHardware() != null ) {
VRhardware.destroy(); environment.getVRHardware().destroy();
VRhardware = null;
} }
disableVR = true;
this.application = null; this.application = null;
this.stateManager = null; this.stateManager = null;
@ -777,67 +628,10 @@ public class VRAppState extends AbstractAppState {
*/ */
protected void processSettings(AppSettings settings){ protected void processSettings(AppSettings settings){
if (settings != null){ 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_VR_FORCE) != null){
forceVR = settings.getBoolean(VRConstants.SETTING_VR_FORCE);
}
if (settings.get(VRConstants.SETTING_FLIP_EYES) != null){
if( VRhardware != null ){
VRhardware._setFlipEyes(settings.getBoolean(VRConstants.SETTING_FLIP_EYES));
}
}
if (settings.get(VRConstants.SETTING_GUI_OVERDRAW) != null){
guiManager._enableGuiOverdraw(settings.getBoolean(VRConstants.SETTING_GUI_OVERDRAW));
}
if (settings.get(VRConstants.SETTING_GUI_CURVED_SURFACE) != null){
guiManager._enableCurvedSuface(settings.getBoolean(VRConstants.SETTING_GUI_CURVED_SURFACE));
}
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_DISABLE_VR) != null){ if (settings.get(VRConstants.SETTING_DISABLE_VR) != null){
DISABLE_VR = settings.getBoolean(VRConstants.SETTING_DISABLE_VR); DISABLE_VR = settings.getBoolean(VRConstants.SETTING_DISABLE_VR);
} }
if (settings.get(VRConstants.SETTING_SEATED_EXPERIENCE) != null){
seated = settings.getBoolean(VRConstants.SETTING_SEATED_EXPERIENCE);
}
if (settings.get(VRConstants.SETTING_NO_GUI) != null){
nogui = settings.getBoolean(VRConstants.SETTING_NO_GUI);
}
if (settings.get(VRConstants.SETTING_INSTANCE_RENDERING) != null){
instanceVR = 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_VRAPI) != null){
vrBinding = settings.getInteger(VRConstants.SETTING_VRAPI);
}
} }
} }
} }

@ -45,10 +45,13 @@ import com.jme3.system.SystemListener;
import com.jme3.system.Timer; import com.jme3.system.Timer;
import com.jme3.system.lwjgl.LwjglDisplayVR; import com.jme3.system.lwjgl.LwjglDisplayVR;
import com.jme3.system.lwjgl.LwjglOffscreenBufferVR; import com.jme3.system.lwjgl.LwjglOffscreenBufferVR;
import com.jme3.util.VRGUIPositioningMode;
import com.jme3.util.VRGuiManager;
import com.jme3.util.VRMouseManager;
import com.jme3.util.VRViewManagerOpenVR;
import java.awt.GraphicsDevice; import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment; import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
@ -61,18 +64,16 @@ import java.util.concurrent.Future;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import jmevr.util.VRViewManager;
import jmevr.util.VRGuiManager;
import jmevr.util.VRGuiManager.POSITIONING_MODE;
import jmevr.util.VRMouseManager;
import org.lwjgl.system.Platform; import org.lwjgl.system.Platform;
/** /**
* A JMonkey application dedicated to Virtual Reality. An application that use VR devices (HTC vive, ...) has to extends this one.<br> * A JMonkey application dedicated to Virtual Reality. An application that use VR devices (HTC vive, ...) has to extends this one.<br>
* <p>
* <b>This class is no more functional and is deprecated. Please use {@link VRAppState VRAppState} instead.</b>
* @author reden - phr00t - https://github.com/phr00t * @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> * @author Julien Seinturier - (c) 2016 - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a>
* @deprecated use {@link VRAppState VRAppState} instead.
*/ */
public abstract class VRApplication implements Application, SystemListener { public abstract class VRApplication implements Application, SystemListener {
@ -171,7 +172,7 @@ public abstract class VRApplication implements Application, SystemListener {
private VRAPI VRhardware = null; private VRAPI VRhardware = null;
private VRGuiManager guiManager = null; private VRGuiManager guiManager = null;
private VRMouseManager mouseManager = null; private VRMouseManager mouseManager = null;
private VRViewManager viewmanager = null; private VRViewManagerOpenVR viewmanager = null;
private String OS; private String OS;
@ -255,13 +256,13 @@ public abstract class VRApplication implements Application, SystemListener {
initStateManager(); initStateManager();
// Create the GUI manager. // Create the GUI manager.
guiManager = new VRGuiManager(); guiManager = new VRGuiManager(null);
// Create a new view manager. // Create a new view manager.
viewmanager = new VRViewManager(); viewmanager = new VRViewManagerOpenVR(null);
// Create a new mouse manager. // Create a new mouse manager.
mouseManager = new VRMouseManager(); mouseManager = new VRMouseManager(null);
// we are going to use OpenVR now, not the Oculus Rift // we are going to use OpenVR now, not the Oculus Rift
// OpenVR does support the Rift // OpenVR does support the Rift
@ -310,7 +311,7 @@ public abstract class VRApplication implements Application, SystemListener {
* Get the VR view manager. * Get the VR view manager.
* @return the VR view manager. * @return the VR view manager.
*/ */
public VRViewManager getVRViewManager() { public VRViewManagerOpenVR getVRViewManager() {
return viewmanager; return viewmanager;
} }
@ -841,10 +842,10 @@ public abstract class VRApplication implements Application, SystemListener {
public void preconfigureVRApp(PreconfigParameter parm, boolean value) { public void preconfigureVRApp(PreconfigParameter parm, boolean value) {
switch( parm ) { switch( parm ) {
case SET_GUI_OVERDRAW: case SET_GUI_OVERDRAW:
guiManager._enableGuiOverdraw(value); guiManager.setGuiOverdraw(value);
break; break;
case SET_GUI_CURVED_SURFACE: case SET_GUI_CURVED_SURFACE:
guiManager._enableCurvedSuface(value); guiManager.setCurvedSurface(value);
break; break;
case FORCE_VR_MODE: case FORCE_VR_MODE:
forceVR = value; forceVR = value;
@ -858,7 +859,7 @@ public abstract class VRApplication implements Application, SystemListener {
break; break;
case FLIP_EYES: case FLIP_EYES:
if( VRhardware == null ) return; if( VRhardware == null ) return;
VRhardware._setFlipEyes(value); VRhardware.setFlipEyes(value);
break; break;
case INSTANCE_VR_RENDERING: case INSTANCE_VR_RENDERING:
instanceVR = value; instanceVR = value;
@ -1179,7 +1180,7 @@ public abstract class VRApplication implements Application, SystemListener {
rootNode.updateGeometricState(); rootNode.updateGeometricState();
if( isInVR() == false || guiManager.getPositioningMode() == POSITIONING_MODE.MANUAL ) { if( isInVR() == false || guiManager.getPositioningMode() == VRGUIPositioningMode.MANUAL ) {
// only update geometric state here if GUI is in manual mode, or not in VR // only update geometric state here if GUI is in manual mode, or not in VR
// it will get updated automatically in the viewmanager update otherwise // it will get updated automatically in the viewmanager update otherwise
guiNode.updateGeometricState(); guiNode.updateGeometricState();
@ -1191,7 +1192,7 @@ public abstract class VRApplication implements Application, SystemListener {
// update compositor? // update compositor?
if( viewmanager != null ) { if( viewmanager != null ) {
viewmanager.sendTextures(); viewmanager.postRender();
} }
} }
@ -1358,7 +1359,7 @@ public abstract class VRApplication implements Application, SystemListener {
} }
//FIXME: WARNING !! //FIXME: WARNING !!
viewmanager = new VRViewManager(); viewmanager = new VRViewManagerOpenVR(null);
viewmanager.setResolutionMultiplier(resMult); viewmanager.setResolutionMultiplier(resMult);
inputManager.addMapping(RESET_HMD, new KeyTrigger(KeyInput.KEY_F9)); inputManager.addMapping(RESET_HMD, new KeyTrigger(KeyInput.KEY_F9));
setLostFocusBehavior(LostFocusBehavior.Disabled); setLostFocusBehavior(LostFocusBehavior.Disabled);

@ -0,0 +1,485 @@
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.OSVR;
import com.jme3.input.vr.OpenVR;
import com.jme3.input.vr.VRAPI;
import com.jme3.input.vr.VRInputAPI;
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;
import com.jme3.util.VRMouseManager;
import com.jme3.util.VRViewManager;
import com.jme3.util.VRViewManagerOSVR;
import com.jme3.util.VRViewManagerOpenVR;
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;
/**
* 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;
private boolean attached = false;
public VREnvironment(AppSettings settings){
this.settings = settings;
guiManager = new VRGuiManager(this);
mouseManager = new VRMouseManager(this);
dummyCam = new Camera();
processSettings();
}
/**
* Get the VR underlying hardware.
* @return the VR underlying hardware.
*/
public VRAPI getVRHardware() {
return hardware;
}
/**
* 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 <code>true</code> if designed for sitting, <code>false</code> 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);
}
}
}
/**
* Check if the application is configured as a seated experience.
* @return <code>true</code> if the application is configured as a seated experience and <code>false</code> 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 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 <code>true</code> if the system currently support VR and <code>false</Code> otherwise.
*/
public boolean isVRSupported() {
return vrSupportedOS;
}
/**
* Check if the VR mode is enabled.
* @return <code>true</code> if the VR mode is enabled and <code>false</code> otherwise.
*/
public boolean isInVR() {
return (forceVR || vrSupportedOS && hardware != null && hardware.isInitialized() && isInitialized());
}
/**
* Check if the rendering is instanced (see <a href="https://en.wikipedia.org/wiki/Geometry_instancing">Geometry instancing</a>).
* @return <code>true</code> if the rendering is instanced and <code>false</code> otherwise.
*/
public boolean isInstanceRendering() {
return instanceRendering;
}
public boolean isSwapBuffers(){
return disableSwapBuffers;
}
/**
* Check if the application has a GUI overlay attached.
* @return <code>true</code> if the application has a GUI overlay attached and <code>false</code> 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 <code>true</code>
* @return <code>true</code> if the VR environment is initialized and <code>false</code> otherwise.
*/
public boolean isInitialized(){
return initialized;
}
/**
* Is the VR compositor is active.
* @return <code>true</code> if the VR compositor is active and <code>false</code> 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 dummyCam;
}
return application.getCamera();
}
public Camera getDummyCamera(){
if (dummyCam == null){
if (application != null){
if (application.getCamera() != null){
dummyCam = application.getCamera().clone();
} else {
return 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 VRViewManagerOpenVR(this);
} else if (vrBinding == VRConstants.SETTING_VRAPI_OSVR_VALUE){
viewmanager = new VRViewManagerOSVR(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 <code>true</code> if the VR environment is successfully initialized and <code>false</code> 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 ) {
hardware = new OSVR(this);
initialized = true;
logger.config("Creating OSVR wrapper [SUCCESS]");
} else if( vrBinding == VRConstants.SETTING_VRAPI_OPENVR_VALUE ) {
hardware = new OpenVR(this);
initialized = true;
logger.config("Creating OpenVR 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));
}
}
}
}
}

@ -9,13 +9,22 @@ https://github.com/sensics/OSVR-RenderManager/blob/master/examples/RenderManager
*/ */
package com.jme3.input.vr; package com.jme3.input.vr;
import com.jme3.app.VRAppState; import com.jme3.app.VREnvironment;
import com.jme3.app.VRApplication;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
import com.jme3.system.osvr.osvrclientkit.OsvrClientKitLibrary;
import com.jme3.system.osvr.osvrdisplay.OsvrDisplayLibrary;
import com.jme3.system.osvr.osvrdisplay.OsvrDisplayLibrary.OSVR_DisplayConfig;
import com.jme3.system.osvr.osvrmatrixconventions.OSVR_Pose3;
import com.jme3.system.osvr.osvrrendermanageropengl.OSVR_OpenResultsOpenGL;
import com.jme3.system.osvr.osvrrendermanageropengl.OSVR_RenderBufferOpenGL;
import com.jme3.system.osvr.osvrrendermanageropengl.OSVR_RenderInfoOpenGL;
import com.jme3.system.osvr.osvrrendermanageropengl.OSVR_RenderParams;
import com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ViewportDescription;
import com.jme3.system.osvr.osvrrendermanageropengl.OsvrRenderManagerOpenGLLibrary;
import com.ochafik.lang.jnaerator.runtime.NativeSize; import com.ochafik.lang.jnaerator.runtime.NativeSize;
import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
@ -23,18 +32,6 @@ import com.sun.jna.ptr.PointerByReference;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.util.logging.Logger; import java.util.logging.Logger;
import osvrclientkit.OsvrClientKitLibrary;
import osvrdisplay.OsvrDisplayLibrary;
import osvrdisplay.OsvrDisplayLibrary.OSVR_DisplayConfig;
import osvrmatrixconventions.OSVR_Pose3;
import osvrrendermanageropengl.OSVR_OpenResultsOpenGL;
import osvrrendermanageropengl.OSVR_RenderBufferOpenGL;
import osvrrendermanageropengl.OSVR_RenderInfoOpenGL;
import osvrrendermanageropengl.OSVR_RenderParams;
import osvrrendermanageropengl.OSVR_ViewportDescription;
import osvrrendermanageropengl.OsvrRenderManagerOpenGLLibrary;
/** /**
* A class that wraps an <a href="http://www.osvr.org/">OSVR</a> system. * A class that wraps an <a href="http://www.osvr.org/">OSVR</a> system.
* @author reden - phr00t - https://github.com/phr00t * @author reden - phr00t - https://github.com/phr00t
@ -87,7 +84,7 @@ public class OSVR implements VRAPI {
OSVR_RenderParams.ByValue renderParams; OSVR_RenderParams.ByValue renderParams;
OsvrClientKitLibrary.OSVR_ClientContext context; OsvrClientKitLibrary.OSVR_ClientContext context;
osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue graphicsLibrary; com.jme3.system.osvr.osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue graphicsLibrary;
Pointer renderManager, renderManagerOpenGL, renderInfoCollection, registerBufferState; Pointer renderManager, renderManagerOpenGL, renderInfoCollection, registerBufferState;
OSVRInput VRinput; OSVRInput VRinput;
NativeSize numRenderInfo; NativeSize numRenderInfo;
@ -111,14 +108,14 @@ public class OSVR implements VRAPI {
boolean initSuccess = false; boolean initSuccess = false;
boolean flipEyes = false; boolean flipEyes = false;
private VRAppState app = null; private VREnvironment environment = null;
/** /**
* Create a new <a href="http://www.osvr.org/">OSVR</a> system attached to the given {@link VRAppState app state}. * Create a new <a href="http://www.osvr.org/">OSVR</a> system attached to the given {@link VREnvironment VR environment}.
* @param app the app state to which the input is attached. * @param environment the {@link VREnvironment VR environment} to which the input is attached.
*/ */
public OSVR(VRAppState app){ public OSVR(VREnvironment environment){
this.app = app; this.environment = environment;
} }
/** /**
@ -150,7 +147,7 @@ public class OSVR implements VRAPI {
hmdPose.setAutoSynch(false); hmdPose.setAutoSynch(false);
context = OsvrClientKitLibrary.osvrClientInit(defaultJString, 0); context = OsvrClientKitLibrary.osvrClientInit(defaultJString, 0);
VRinput = new OSVRInput(app); VRinput = new OSVRInput(environment);
initSuccess = context != null && VRinput.init(); initSuccess = context != null && VRinput.init();
if( initSuccess ) { if( initSuccess ) {
PointerByReference grabDisplay = new PointerByReference(); PointerByReference grabDisplay = new PointerByReference();
@ -206,7 +203,7 @@ public class OSVR implements VRAPI {
public boolean initVRCompositor(boolean allowed) { public boolean initVRCompositor(boolean allowed) {
if( !allowed || renderManager != null ) return false; if( !allowed || renderManager != null ) return false;
grabGLFWContext(); grabGLFWContext();
graphicsLibrary = new osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue(); graphicsLibrary = new com.jme3.system.osvr.osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue();
graphicsLibrary.toolkit = null; graphicsLibrary.toolkit = null;
graphicsLibrary.setAutoSynch(false); graphicsLibrary.setAutoSynch(false);
grabRM = new PointerByReference(); grabRMOGL = new PointerByReference(); grabRM = new PointerByReference(); grabRMOGL = new PointerByReference();
@ -272,7 +269,7 @@ public class OSVR implements VRAPI {
} }
@Override @Override
public void _setFlipEyes(boolean set) { public void setFlipEyes(boolean set) {
flipEyes = set; flipEyes = set;
} }
@ -376,7 +373,7 @@ public class OSVR implements VRAPI {
if( eyeLeftInfo == null ) return cam.getProjectionMatrix(); if( eyeLeftInfo == null ) return cam.getProjectionMatrix();
if( eyeMatrix[EYE_LEFT] == null ) { if( eyeMatrix[EYE_LEFT] == null ) {
FloatBuffer tfb = FloatBuffer.allocate(16); FloatBuffer tfb = FloatBuffer.allocate(16);
osvrdisplay.OsvrDisplayLibrary.osvrClientGetViewerEyeSurfaceProjectionMatrixf(displayConfig, 0, (byte)EYE_LEFT, 0, cam.getFrustumNear(), cam.getFrustumFar(), (short)0, tfb); com.jme3.system.osvr.osvrdisplay.OsvrDisplayLibrary.osvrClientGetViewerEyeSurfaceProjectionMatrixf(displayConfig, 0, (byte)EYE_LEFT, 0, cam.getFrustumNear(), cam.getFrustumFar(), (short)0, tfb);
eyeMatrix[EYE_LEFT] = new Matrix4f(); eyeMatrix[EYE_LEFT] = new Matrix4f();
eyeMatrix[EYE_LEFT].set(tfb.get(0), tfb.get(4), tfb.get(8), tfb.get(12), eyeMatrix[EYE_LEFT].set(tfb.get(0), tfb.get(4), tfb.get(8), tfb.get(12),
tfb.get(1), tfb.get(5), tfb.get(9), tfb.get(13), tfb.get(1), tfb.get(5), tfb.get(9), tfb.get(13),
@ -391,7 +388,7 @@ public class OSVR implements VRAPI {
if( eyeRightInfo == null ) return cam.getProjectionMatrix(); if( eyeRightInfo == null ) return cam.getProjectionMatrix();
if( eyeMatrix[EYE_RIGHT] == null ) { if( eyeMatrix[EYE_RIGHT] == null ) {
FloatBuffer tfb = FloatBuffer.allocate(16); FloatBuffer tfb = FloatBuffer.allocate(16);
osvrdisplay.OsvrDisplayLibrary.osvrClientGetViewerEyeSurfaceProjectionMatrixf(displayConfig, 0, (byte)EYE_RIGHT, 0, cam.getFrustumNear(), cam.getFrustumFar(), (short)0, tfb); com.jme3.system.osvr.osvrdisplay.OsvrDisplayLibrary.osvrClientGetViewerEyeSurfaceProjectionMatrixf(displayConfig, 0, (byte)EYE_RIGHT, 0, cam.getFrustumNear(), cam.getFrustumFar(), (short)0, tfb);
eyeMatrix[EYE_RIGHT] = new Matrix4f(); eyeMatrix[EYE_RIGHT] = new Matrix4f();
eyeMatrix[EYE_RIGHT].set(tfb.get(0), tfb.get(4), tfb.get(8), tfb.get(12), eyeMatrix[EYE_RIGHT].set(tfb.get(0), tfb.get(4), tfb.get(8), tfb.get(12),
tfb.get(1), tfb.get(5), tfb.get(9), tfb.get(13), tfb.get(1), tfb.get(5), tfb.get(9), tfb.get(13),
@ -461,10 +458,4 @@ public class OSVR implements VRAPI {
public HmdType getType() { public HmdType getType() {
return HmdType.OSVR; return HmdType.OSVR;
} }
@Override
public VRAppState getVRAppState() {
return app;
}
} }

@ -7,26 +7,24 @@ package com.jme3.input.vr;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.jme3.app.VRAppState; import com.jme3.app.VREnvironment;
import com.jme3.app.VRApplication;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.system.osvr.osvrclientkit.OsvrClientKitLibrary;
import com.jme3.system.osvr.osvrclientkit.OsvrClientKitLibrary.OSVR_ClientInterface;
import com.jme3.system.osvr.osvrclientreporttypes.OSVR_AnalogReport;
import com.jme3.system.osvr.osvrclientreporttypes.OSVR_ButtonReport;
import com.jme3.system.osvr.osvrclientreporttypes.OSVR_Pose3;
import com.jme3.system.osvr.osvrinterface.OsvrInterfaceLibrary;
import com.jme3.system.osvr.osvrtimevalue.OSVR_TimeValue;
import com.jme3.util.VRViewManagerOSVR;
import com.sun.jna.Callback; import com.sun.jna.Callback;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference; import com.sun.jna.ptr.PointerByReference;
import jmevr.util.VRViewManager;
import osvrclientkit.OsvrClientKitLibrary;
import osvrclientkit.OsvrClientKitLibrary.OSVR_ClientInterface;
import osvrclientreporttypes.OSVR_AnalogReport;
import osvrclientreporttypes.OSVR_ButtonReport;
import osvrclientreporttypes.OSVR_Pose3;
import osvrinterface.OsvrInterfaceLibrary;
import osvrtimevalue.OSVR_TimeValue;
/** /**
* A class that wraps an <a href="http://www.osvr.org/">OSVR</a> input. * A class that wraps an <a href="http://www.osvr.org/">OSVR</a> input.
@ -64,7 +62,7 @@ public class OSVRInput implements VRInputAPI {
private static final Vector2f lastCallAxis[] = new Vector2f[16]; private static final Vector2f lastCallAxis[] = new Vector2f[16];
private static float axisMultiplier = 1f; private static float axisMultiplier = 1f;
private VRAppState app = null; private VREnvironment environment = null;
/** /**
* Get the system String that identifies a controller. * Get the system String that identifies a controller.
@ -91,11 +89,11 @@ public class OSVRInput implements VRInputAPI {
/** /**
* Create a new <a href="http://www.osvr.org/">OSVR</a> input attached to the given {@link VRAppState app state}. * Create a new <a href="http://www.osvr.org/">OSVR</a> input attached to the given {@link VREnvironment VR environment}.
* @param app the app state to which the input is attached. * @param environment the {@link VREnvironment VR environment} to which the input is attached.
*/ */
public OSVRInput(VRAppState app){ public OSVRInput(VREnvironment environment){
this.app = app; this.environment = environment;
} }
@ -167,7 +165,7 @@ public class OSVRInput implements VRInputAPI {
private OSVR_ClientInterface getInterface(byte[] str) { private OSVR_ClientInterface getInterface(byte[] str) {
PointerByReference pbr = new PointerByReference(); PointerByReference pbr = new PointerByReference();
OsvrClientKitLibrary.osvrClientGetInterface((OsvrClientKitLibrary.OSVR_ClientContext)app.getVRHardware().getVRSystem(), str, pbr); OsvrClientKitLibrary.osvrClientGetInterface((OsvrClientKitLibrary.OSVR_ClientContext)environment.getVRHardware().getVRSystem(), str, pbr);
return new OSVR_ClientInterface(pbr.getValue()); return new OSVR_ClientInterface(pbr.getValue());
} }
@ -303,9 +301,9 @@ public class OSVRInput implements VRInputAPI {
@Override @Override
public Quaternion getFinalObserverRotation(int index) { public Quaternion getFinalObserverRotation(int index) {
VRViewManager vrvm = app.getVRViewManager(); VRViewManagerOSVR vrvm = (VRViewManagerOSVR)environment.getVRViewManager();
if( vrvm == null || isInputDeviceTracking(index) == false ) return null; if( vrvm == null || isInputDeviceTracking(index) == false ) return null;
Object obs = app.getObserver(); Object obs = environment.getObserver();
if( obs instanceof Camera ) { if( obs instanceof Camera ) {
tempq.set(((Camera)obs).getRotation()); tempq.set(((Camera)obs).getRotation());
} else { } else {
@ -316,9 +314,9 @@ public class OSVRInput implements VRInputAPI {
@Override @Override
public Vector3f getFinalObserverPosition(int index) { public Vector3f getFinalObserverPosition(int index) {
VRViewManager vrvm = app.getVRViewManager(); VRViewManagerOSVR vrvm = (VRViewManagerOSVR) environment.getVRViewManager();
if( vrvm == null || isInputDeviceTracking(index) == false ) return null; if( vrvm == null || isInputDeviceTracking(index) == false ) return null;
Object obs = app.getObserver(); Object obs = environment.getObserver();
Vector3f pos = getPosition(index); Vector3f pos = getPosition(index);
if( obs instanceof Camera ) { if( obs instanceof Camera ) {
((Camera)obs).getRotation().mult(pos, pos); ((Camera)obs).getRotation().mult(pos, pos);
@ -349,13 +347,6 @@ public class OSVRInput implements VRInputAPI {
axisMultiplier = set; axisMultiplier = set;
} }
@Override
public VRAppState getVRAppState() {
return app;
}
@Override @Override
public VRTrackedController getTrackedController(int index) { public VRTrackedController getTrackedController(int index) {
// TODO Auto-generated method stub // TODO Auto-generated method stub

@ -5,8 +5,7 @@
*/ */
package com.jme3.input.vr; package com.jme3.input.vr;
import com.jme3.app.VRAppState; import com.jme3.app.VREnvironment;
import com.jme3.app.VRApplication;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
@ -19,22 +18,19 @@ import com.jme3.system.jopenvr.OpenVRUtil;
import com.jme3.system.jopenvr.TrackedDevicePose_t; import com.jme3.system.jopenvr.TrackedDevicePose_t;
import com.jme3.system.jopenvr.VR_IVRCompositor_FnTable; import com.jme3.system.jopenvr.VR_IVRCompositor_FnTable;
import com.jme3.system.jopenvr.VR_IVRSystem_FnTable; import com.jme3.system.jopenvr.VR_IVRSystem_FnTable;
import com.jme3.util.VRUtil;
import com.sun.jna.Memory; import com.sun.jna.Memory;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.ptr.FloatByReference; import com.sun.jna.ptr.FloatByReference;
import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference; import com.sun.jna.ptr.LongByReference;
import java.nio.FloatBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import jmevr.util.VRUtil;
/** /**
* A class that wraps an <a href="https://github.com/ValveSoftware/openvr/wiki/API-Documentation">OpenVR</a> system. * 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 reden - phr00t - https://github.com/phr00t
@ -84,15 +80,15 @@ public class OpenVR implements VRAPI {
private static long frameCount; private static long frameCount;
private static OpenVRInput VRinput; private static OpenVRInput VRinput;
private VRAppState app = null; private VREnvironment environment = null;
/** /**
* Create a new <a href="https://github.com/ValveSoftware/openvr/wiki/API-Documentation">OpenVR</a> system * Create a new <a href="https://github.com/ValveSoftware/openvr/wiki/API-Documentation">OpenVR</a> system
* attached to the given {@link VRAppState VR app state}. * attached to the given {@link VREnvironment VR environment}.
* @param appState the VR app state to which the api is attached. * @param environment the VR environment to which this API is attached.
*/ */
public OpenVR(VRAppState appState){ public OpenVR(VREnvironment environment){
this.app = appState; this.environment = environment;
} }
@Override @Override
@ -118,7 +114,7 @@ public class OpenVR implements VRAPI {
private static long latencyWaitTime = 0; private static long latencyWaitTime = 0;
@Override @Override
public void _setFlipEyes(boolean set) { public void setFlipEyes(boolean set) {
flipEyes = set; flipEyes = set;
} }
@ -180,7 +176,7 @@ public class OpenVR implements VRAPI {
} }
// init controllers for the first time // init controllers for the first time
VRinput = new OpenVRInput(app); VRinput = new OpenVRInput(environment);
VRinput.init(); VRinput.init();
VRinput.updateConnectedControllers(); VRinput.updateConnectedControllers();
@ -206,7 +202,7 @@ public class OpenVR implements VRAPI {
if(compositorFunctions != null && hmdErrorStore.getValue() == 0 ){ if(compositorFunctions != null && hmdErrorStore.getValue() == 0 ){
compositorFunctions.setAutoSynch(false); compositorFunctions.setAutoSynch(false);
compositorFunctions.read(); compositorFunctions.read();
if( app.isSeatedExperience() ) { if( environment.isSeatedExperience() ) {
compositorFunctions.SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated); compositorFunctions.SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated);
} else { } else {
compositorFunctions.SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding); compositorFunctions.SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding);
@ -356,7 +352,7 @@ public class OpenVR implements VRAPI {
frameCount = nowCount; frameCount = nowCount;
vrsystemFunctions.GetDeviceToAbsoluteTrackingPose.apply( vrsystemFunctions.GetDeviceToAbsoluteTrackingPose.apply(
app.isSeatedExperience()?JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated: environment.isSeatedExperience()?JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated:
JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding, JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding,
fSecondsUntilPhotons, hmdTrackedDevicePoseReference, JOpenVRLibrary.k_unMaxTrackedDeviceCount); fSecondsUntilPhotons, hmdTrackedDevicePoseReference, JOpenVRLibrary.k_unMaxTrackedDeviceCount);
} }
@ -373,7 +369,7 @@ public class OpenVR implements VRAPI {
VRInput._updateConnectedControllers(); VRInput._updateConnectedControllers();
}*/ }*/
//update controllers pose information //update controllers pose information
app.getVRinput().updateControllerStates(); environment.getVRinput().updateControllerStates();
// read pose data from native // read pose data from native
for (int nDevice = 0; nDevice < JOpenVRLibrary.k_unMaxTrackedDeviceCount; ++nDevice ){ for (int nDevice = 0; nDevice < JOpenVRLibrary.k_unMaxTrackedDeviceCount; ++nDevice ){
@ -447,7 +443,7 @@ public class OpenVR implements VRAPI {
@Override @Override
public Vector3f getSeatedToAbsolutePosition() { public Vector3f getSeatedToAbsolutePosition() {
if( app.isSeatedExperience() == false ) return Vector3f.ZERO; if( environment.isSeatedExperience() == false ) return Vector3f.ZERO;
if( hmdSeatToStand == null ) { if( hmdSeatToStand == null ) {
hmdSeatToStand = new Vector3f(); hmdSeatToStand = new Vector3f();
HmdMatrix34_t mat = vrsystemFunctions.GetSeatedZeroPoseToStandingAbsoluteTrackingPose.apply(); HmdMatrix34_t mat = vrsystemFunctions.GetSeatedZeroPoseToStandingAbsoluteTrackingPose.apply();
@ -525,9 +521,4 @@ public class OpenVR implements VRAPI {
} }
} }
@Override
public VRAppState getVRAppState() {
return app;
}
} }

@ -9,8 +9,7 @@ import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.jme3.app.VRAppState; import com.jme3.app.VREnvironment;
import com.jme3.app.VRApplication;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
@ -20,9 +19,8 @@ import com.jme3.system.jopenvr.JOpenVRLibrary;
import com.jme3.system.jopenvr.OpenVRUtil; import com.jme3.system.jopenvr.OpenVRUtil;
import com.jme3.system.jopenvr.VRControllerState_t; import com.jme3.system.jopenvr.VRControllerState_t;
import com.jme3.system.jopenvr.VR_IVRSystem_FnTable; import com.jme3.system.jopenvr.VR_IVRSystem_FnTable;
import com.jme3.util.VRUtil;
import jmevr.util.VRUtil; import com.jme3.util.VRViewManagerOpenVR;
import jmevr.util.VRViewManager;
/* /*
make helper functions to pull the following easily from raw data (DONE) make helper functions to pull the following easily from raw data (DONE)
@ -98,16 +96,16 @@ public class OpenVRInput implements VRInputAPI {
private final Quaternion tempq = new Quaternion(); private final Quaternion tempq = new Quaternion();
private VRAppState app; private VREnvironment environment;
private List<VRTrackedController> trackedControllers = null; private List<VRTrackedController> trackedControllers = null;
/** /**
* Create a new <a href="https://github.com/ValveSoftware/openvr/wiki/API-Documentation">OpenVR</a> input attached to the given application. * Create a new <a href="https://github.com/ValveSoftware/openvr/wiki/API-Documentation">OpenVR</a> input attached to the given VR environment.
* @param application the application to which the input is attached. * @param environment the VR environment to which the input is attached.
*/ */
public OpenVRInput(VRAppState appState){ public OpenVRInput(VREnvironment environment){
this.app = appState; this.environment = environment;
} }
@Override @Override
@ -297,18 +295,28 @@ public class OpenVRInput implements VRInputAPI {
@Override @Override
public boolean isInputFocused() { public boolean isInputFocused() {
return ((VR_IVRSystem_FnTable)app.getVRHardware().getVRSystem()).IsInputFocusCapturedByAnotherProcess.apply() == 0;
if (environment != null){
return ((VR_IVRSystem_FnTable)environment.getVRHardware().getVRSystem()).IsInputFocusCapturedByAnotherProcess.apply() == 0;
} else {
throw new IllegalStateException("VR input is not attached to a VR environment.");
}
} }
@Override @Override
public boolean isInputDeviceTracking(int index) { public boolean isInputDeviceTracking(int index) {
if( index < 0 || index >= controllerCount ) return false; if( index < 0 || index >= controllerCount ){
return false;
}
return OpenVR.hmdTrackedDevicePoses[controllerIndex[index]].bPoseIsValid != 0; return OpenVR.hmdTrackedDevicePoses[controllerIndex[index]].bPoseIsValid != 0;
} }
@Override @Override
public Quaternion getOrientation(int index) { public Quaternion getOrientation(int index) {
if( isInputDeviceTracking(index) == false ) return null; if( isInputDeviceTracking(index) == false ){
return null;
}
index = controllerIndex[index]; index = controllerIndex[index];
VRUtil.convertMatrix4toQuat(OpenVR.poseMatrices[index], rotStore[index]); VRUtil.convertMatrix4toQuat(OpenVR.poseMatrices[index], rotStore[index]);
return rotStore[index]; return rotStore[index];
@ -316,7 +324,10 @@ public class OpenVRInput implements VRInputAPI {
@Override @Override
public Vector3f getPosition(int index) { public Vector3f getPosition(int index) {
if( isInputDeviceTracking(index) == false ) return null; if( isInputDeviceTracking(index) == false ){
return null;
}
// the hmdPose comes in rotated funny, fix that here // the hmdPose comes in rotated funny, fix that here
index = controllerIndex[index]; index = controllerIndex[index];
OpenVR.poseMatrices[index].toTranslationVector(posStore[index]); OpenVR.poseMatrices[index].toTranslationVector(posStore[index]);
@ -327,22 +338,44 @@ public class OpenVRInput implements VRInputAPI {
@Override @Override
public Quaternion getFinalObserverRotation(int index) { public Quaternion getFinalObserverRotation(int index) {
VRViewManager vrvm = app.getVRViewManager();
if( vrvm == null || isInputDeviceTracking(index) == false ) return null; if (environment != null){
Object obs = app.getObserver(); VRViewManagerOpenVR vrvm = (VRViewManagerOpenVR)environment.getVRViewManager();
if (vrvm != null){
if(isInputDeviceTracking(index) == false ){
return null;
}
Object obs = environment.getObserver();
if( obs instanceof Camera ) { if( obs instanceof Camera ) {
tempq.set(((Camera)obs).getRotation()); tempq.set(((Camera)obs).getRotation());
} else { } else {
tempq.set(((Spatial)obs).getWorldRotation()); tempq.set(((Spatial)obs).getWorldRotation());
} }
return tempq.multLocal(getOrientation(index)); return tempq.multLocal(getOrientation(index));
} else {
throw new IllegalStateException("VR environment has no valid view manager.");
}
} else {
throw new IllegalStateException("VR input is not attached to a VR environment.");
}
} }
@Override @Override
public Vector3f getFinalObserverPosition(int index) { public Vector3f getFinalObserverPosition(int index) {
VRViewManager vrvm = app.getVRViewManager();
if( vrvm == null || isInputDeviceTracking(index) == false ) return null; if (environment != null){
Object obs = app.getObserver(); VRViewManagerOpenVR vrvm = (VRViewManagerOpenVR)environment.getVRViewManager();
if (vrvm != null){
if(isInputDeviceTracking(index) == false ){
return null;
}
Object obs = environment.getObserver();
Vector3f pos = getPosition(index); Vector3f pos = getPosition(index);
if( obs instanceof Camera ) { if( obs instanceof Camera ) {
((Camera)obs).getRotation().mult(pos, pos); ((Camera)obs).getRotation().mult(pos, pos);
@ -351,28 +384,40 @@ public class OpenVRInput implements VRInputAPI {
((Spatial)obs).getWorldRotation().mult(pos, pos); ((Spatial)obs).getWorldRotation().mult(pos, pos);
return pos.addLocal(((Spatial)obs).getWorldTranslation()); return pos.addLocal(((Spatial)obs).getWorldTranslation());
} }
} else {
throw new IllegalStateException("VR environment has no valid view manager.");
}
} else {
throw new IllegalStateException("VR input is not attached to a VR environment.");
}
} }
@Override @Override
public void triggerHapticPulse(int controllerIndex, float seconds) { public void triggerHapticPulse(int controllerIndex, float seconds) {
if( app.isInVR() == false || isInputDeviceTracking(controllerIndex) == false ) return; if( environment.isInVR() == false || isInputDeviceTracking(controllerIndex) == false ){
return;
}
// apparently only axis ID of 0 works // apparently only axis ID of 0 works
((VR_IVRSystem_FnTable)app.getVRHardware().getVRSystem()).TriggerHapticPulse.apply(OpenVRInput.controllerIndex[controllerIndex], ((VR_IVRSystem_FnTable)environment.getVRHardware().getVRSystem()).TriggerHapticPulse.apply(OpenVRInput.controllerIndex[controllerIndex],
0, (short)Math.round(3f * seconds / 1e-3f)); 0, (short)Math.round(3f * seconds / 1e-3f));
} }
@Override @Override
public void updateConnectedControllers() { public void updateConnectedControllers() {
logger.config("Updating connected controllers."); logger.config("Updating connected controllers.");
if (environment != null){
controllerCount = 0; controllerCount = 0;
for(int i=0;i<JOpenVRLibrary.k_unMaxTrackedDeviceCount;i++) { for(int i=0;i<JOpenVRLibrary.k_unMaxTrackedDeviceCount;i++) {
if( ((OpenVR)app.getVRHardware()).getVRSystem().GetTrackedDeviceClass.apply(i) == JOpenVRLibrary.ETrackedDeviceClass.ETrackedDeviceClass_TrackedDeviceClass_Controller ) { if( ((OpenVR)environment.getVRHardware()).getVRSystem().GetTrackedDeviceClass.apply(i) == JOpenVRLibrary.ETrackedDeviceClass.ETrackedDeviceClass_TrackedDeviceClass_Controller ) {
String controllerName = "Unknown"; String controllerName = "Unknown";
String manufacturerName = "Unknown"; String manufacturerName = "Unknown";
try { try {
controllerName = OpenVRUtil.getTrackedDeviceStringProperty(((OpenVR)app.getVRHardware()).getVRSystem(), i, JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_TrackingSystemName_String); controllerName = OpenVRUtil.getTrackedDeviceStringProperty(((OpenVR)environment.getVRHardware()).getVRSystem(), i, JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_TrackingSystemName_String);
manufacturerName = OpenVRUtil.getTrackedDeviceStringProperty(((OpenVR)app.getVRHardware()).getVRSystem(), i, JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_ManufacturerName_String); manufacturerName = OpenVRUtil.getTrackedDeviceStringProperty(((OpenVR)environment.getVRHardware()).getVRSystem(), i, JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_ManufacturerName_String);
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.WARNING, e.getMessage(), e); logger.log(Level.WARNING, e.getMessage(), e);
} }
@ -388,23 +433,27 @@ public class OpenVRInput implements VRInputAPI {
logger.config(" Controller "+(i+1)+"/"+JOpenVRLibrary.k_unMaxTrackedDeviceCount+" ignored."); logger.config(" Controller "+(i+1)+"/"+JOpenVRLibrary.k_unMaxTrackedDeviceCount+" ignored.");
} }
} }
} else {
throw new IllegalStateException("VR input is not attached to a VR environment.");
}
} }
@Override @Override
public void updateControllerStates() { public void updateControllerStates() {
if (environment != null){
for(int i=0;i<controllerCount;i++) { for(int i=0;i<controllerCount;i++) {
int index = controllerIndex[i]; int index = controllerIndex[i];
((OpenVR)app.getVRHardware()).getVRSystem().GetControllerState.apply(index, cStates[index], 5); ((OpenVR)environment.getVRHardware()).getVRSystem().GetControllerState.apply(index, cStates[index], 5);
cStates[index].readField("ulButtonPressed"); cStates[index].readField("ulButtonPressed");
cStates[index].readField("rAxis"); cStates[index].readField("rAxis");
needsNewVelocity[index] = true; needsNewVelocity[index] = true;
needsNewAngVelocity[index] = true; needsNewAngVelocity[index] = true;
} }
} else {
throw new IllegalStateException("VR input is not attached to a VR environment.");
} }
@Override
public VRAppState getVRAppState() {
return app;
} }
} }

@ -5,7 +5,6 @@
*/ */
package com.jme3.input.vr; package com.jme3.input.vr;
import com.jme3.app.VRAppState;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
@ -32,12 +31,6 @@ public interface VRAPI {
*/ */
public boolean initVRCompositor(boolean allowed); public boolean initVRCompositor(boolean allowed);
/**
* Get the {@link VRAppState VR app state} to which this api is attached.
* @return the VR app state to which this input is attached.
*/
public VRAppState getVRAppState();
/** /**
* Get the object that wraps natively the VR system. * Get the object that wraps natively the VR system.
* @return the object that wraps natively the VR system. * @return the object that wraps natively the VR system.
@ -63,10 +56,10 @@ public interface VRAPI {
public VRInputAPI getVRinput(); public VRInputAPI getVRinput();
/** /**
* Do not use. Prefers the preconfigure routine from the VRApplication. * Flip the left and right eye..
* @param set <code>true</code> if the eyes has to be flipped and <code>false</code> otherwise. * @param set <code>true</code> if the eyes has to be flipped and <code>false</code> otherwise.
*/ */
public void _setFlipEyes(boolean set); public void setFlipEyes(boolean set);
/** /**
* Set if latency information has to be logged. * Set if latency information has to be logged.

@ -5,8 +5,6 @@
*/ */
package com.jme3.input.vr; package com.jme3.input.vr;
import com.jme3.app.VRAppState;
import com.jme3.app.VRApplication;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
@ -197,9 +195,4 @@ public interface VRInputAPI {
*/ */
public void triggerHapticPulse(int controllerIndex, float seconds); public void triggerHapticPulse(int controllerIndex, float seconds);
/**
* Get the {@link VRAppState VR app state} to which this api is attached.
* @return the VR app state to which this input is attached.
*/
public VRAppState getVRAppState();
} }

@ -2,7 +2,7 @@
* To change this template, choose Tools | Templates * To change this template, choose Tools | Templates
* and open the template in the editor. * and open the template in the editor.
*/ */
package jmevr.util; package com.jme3.post;
import com.jme3.asset.AssetManager; import com.jme3.asset.AssetManager;
import com.jme3.post.filters.FogFilter; import com.jme3.post.filters.FogFilter;

@ -30,7 +30,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package jmevr.util; package com.jme3.scene;
import com.jme3.scene.Mesh; import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer.Type; import com.jme3.scene.VertexBuffer.Type;

@ -45,6 +45,7 @@ import com.jme3.math.Matrix4f;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.post.SceneProcessor; import com.jme3.post.SceneProcessor;
import com.jme3.profile.AppProfiler;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.RenderManager;
import com.jme3.renderer.Renderer; import com.jme3.renderer.Renderer;
@ -100,6 +101,8 @@ public abstract class AbstractShadowRendererVR implements SceneProcessor, Savabl
protected RenderState forcedRenderState = new RenderState(); protected RenderState forcedRenderState = new RenderState();
protected Boolean renderBackFacesShadows; protected Boolean renderBackFacesShadows;
protected AppProfiler profiler = null;
/** /**
* true if the fallback material should be used, otherwise false * true if the fallback material should be used, otherwise false
*/ */
@ -379,6 +382,11 @@ public abstract class AbstractShadowRendererVR implements SceneProcessor, Savabl
*/ */
protected abstract Camera getShadowCam(int shadowMapIndex); protected abstract Camera getShadowCam(int shadowMapIndex);
@Override
public void setProfiler(AppProfiler profiler) {
this.profiler = profiler;
}
/** /**
* responsible for displaying the frustum of the shadow cam for debug * responsible for displaying the frustum of the shadow cam for debug
* purpose * purpose

@ -42,7 +42,6 @@ import com.jme3.material.Material;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.profile.AppProfiler;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
import com.jme3.renderer.queue.GeometryList; import com.jme3.renderer.queue.GeometryList;
import com.jme3.renderer.queue.RenderQueue; import com.jme3.renderer.queue.RenderQueue;
@ -77,8 +76,6 @@ public class DirectionalLightShadowRendererVR extends AbstractShadowRendererVR {
//Holding the info for fading shadows in the far distance //Holding the info for fading shadows in the far distance
private boolean stabilize = true; private boolean stabilize = true;
private AppProfiler profiler = null;
/** /**
* Used for serialzation use * Used for serialzation use
* DirectionalLightShadowRenderer#DirectionalLightShadowRenderer(AssetManager * DirectionalLightShadowRenderer#DirectionalLightShadowRenderer(AssetManager
@ -304,9 +301,4 @@ public class DirectionalLightShadowRendererVR extends AbstractShadowRendererVR {
protected boolean checkCulling(Camera viewCam) { protected boolean checkCulling(Camera viewCam) {
return true; return true;
} }
@Override
public void setProfiler(AppProfiler profiler) {
this.profiler = profiler;
}
} }

@ -5,13 +5,13 @@
*/ */
package com.jme3.shadow; package com.jme3.shadow;
import com.jme3.app.VRApplication; import com.jme3.app.Application;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
import com.jme3.math.Vector4f; import com.jme3.math.Vector4f;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
/** /**
* An instanced version of the {@link DirectionalLightShadowFilterVR directional light shadow filter}. * An instanced version of the {@link DirectionalLightShadowFilterVR directional light shadow filter} dedi.
* @author reden - phr00t - https://github.com/phr00t * @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> * @author Julien Seinturier - (c) 2016 - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a>
*/ */
@ -19,30 +19,53 @@ public class InstancedDirectionalShadowFilter extends DirectionalLightShadowFilt
private final Vector4f temp4f = new Vector4f(), temp4f2 = new Vector4f(); private final Vector4f temp4f = new Vector4f(), temp4f2 = new Vector4f();
private VRApplication application; private boolean instanceRendering = false;
private Camera rightCamera = null;
/** /**
* Create a new instanced version of the {@link DirectionalLightShadowFilterVR directional light shadow filter}. * Create a new instanced version of the {@link DirectionalLightShadowFilterVR directional light shadow filter}.
* @param application the VR application that this filter is attached to. * @param application the application that this filter is attached to.
* @param camera * @param camera
* @param shadowMapSize the size of the rendered shadowmaps (512, 1024, 2048, etc...) * @param shadowMapSize the size of the rendered shadowmaps (512, 1024, 2048, etc...)
* @param nbSplits the number of shadow maps rendered (the more shadow maps the more quality, the less fps). * @param nbSplits the number of shadow maps rendered (the more shadow maps the more quality, the less fps).
* @param instancedRendering <code>true</code> if this filter has to use instance rendering and <code>false</code> otherwise. * @param instancedRendering <code>true</code> if this filter has to use instance rendering and <code>false</code> otherwise.
* @param rightCamera the camera used as right eye in stereo rendering mode.
*/ */
public InstancedDirectionalShadowFilter(VRApplication application, Camera camera, int shadowMapSize, int nbSplits, boolean instancedRendering) { public InstancedDirectionalShadowFilter(Application application, Camera camera, int shadowMapSize, int nbSplits, boolean instancedRendering, Camera rightCamera) {
super(application.getAssetManager(), shadowMapSize, nbSplits, "Common/MatDefs/VR/PostShadowFilter.j3md"); super(application.getAssetManager(), shadowMapSize, nbSplits, "Common/MatDefs/VR/PostShadowFilter.j3md");
this.instanceRendering = instancedRendering;
this.rightCamera = rightCamera;
} }
@Override @Override
protected void preFrame(float tpf) { protected void preFrame(float tpf) {
shadowRenderer.preFrame(tpf); shadowRenderer.preFrame(tpf);
if( application.isInstanceVRRendering() ) { if( instanceRendering ) {
material.setMatrix4("ViewProjectionMatrixInverseRight", application.getVRViewManager().getRightCamera().getViewProjectionMatrix().invert()); material.setMatrix4("ViewProjectionMatrixInverseRight", rightCamera.getViewProjectionMatrix().invert());
Matrix4f m = application.getVRViewManager().getRightCamera().getViewProjectionMatrix(); Matrix4f m = rightCamera.getViewProjectionMatrix();
material.setVector4("ViewProjectionMatrixRow2Right", temp4f2.set(m.m20, m.m21, m.m22, m.m23)); material.setVector4("ViewProjectionMatrixRow2Right", temp4f2.set(m.m20, m.m21, m.m22, m.m23));
} }
material.setMatrix4("ViewProjectionMatrixInverse", viewPort.getCamera().getViewProjectionMatrix().invert()); material.setMatrix4("ViewProjectionMatrixInverse", viewPort.getCamera().getViewProjectionMatrix().invert());
Matrix4f m = viewPort.getCamera().getViewProjectionMatrix(); Matrix4f m = viewPort.getCamera().getViewProjectionMatrix();
material.setVector4("ViewProjectionMatrixRow2", temp4f.set(m.m20, m.m21, m.m22, m.m23)); material.setVector4("ViewProjectionMatrixRow2", temp4f.set(m.m20, m.m21, m.m22, m.m23));
} }
/**
* Get if this filter is using instance rendering.
* @return <code>true</code> if this filter is using instance rendering and <code>false</code> otherwise.
* @see #setInstanceRendering(boolean)
*/
public boolean isInstanceRendering() {
return instanceRendering;
}
/**
* Set if this filter has to use instance rendering.
* @param instanceRendering <code>true</code> if this filter has to use instance rendering and <code>false</code> otherwise.
* @see #isInstanceRendering()
*/
public void setInstanceRendering(boolean instanceRendering) {
this.instanceRendering = instanceRendering;
}
} }

@ -39,14 +39,12 @@ import com.jme3.input.TouchInput;
import com.jme3.input.lwjgl.GlfwJoystickInput; import com.jme3.input.lwjgl.GlfwJoystickInput;
import com.jme3.input.lwjgl.GlfwKeyInputVR; import com.jme3.input.lwjgl.GlfwKeyInputVR;
import com.jme3.input.lwjgl.GlfwMouseInputVR; import com.jme3.input.lwjgl.GlfwMouseInputVR;
import com.jme3.renderer.opengl.GL;
import com.jme3.system.AppSettings; import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext; import com.jme3.system.JmeContext;
import com.jme3.system.JmeSystem; import com.jme3.system.JmeSystem;
import com.jme3.system.NanoTimer; import com.jme3.system.NanoTimer;
import org.lwjgl.glfw.*; import org.lwjgl.glfw.*;
import org.lwjgl.opengl.GL11;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level; import java.util.logging.Level;

@ -1,4 +1,4 @@
package osvrclientkit; package com.jme3.system.osvr.osvrclientkit;
import com.sun.jna.Callback; import com.sun.jna.Callback;
import com.sun.jna.Library; import com.sun.jna.Library;
import com.sun.jna.Native; import com.sun.jna.Native;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrmatrixconventions; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrclientreporttypes;
import com.sun.jna.Library; import com.sun.jna.Library;
import com.sun.jna.Native; import com.sun.jna.Native;
import com.sun.jna.NativeLibrary; import com.sun.jna.NativeLibrary;

@ -1,4 +1,5 @@
package osvrdisplay; package com.jme3.system.osvr.osvrdisplay;
import com.jme3.system.osvr.osvrclientkit.OsvrClientKitLibrary;
import com.sun.jna.Library; import com.sun.jna.Library;
import com.sun.jna.Native; import com.sun.jna.Native;
import com.sun.jna.NativeLibrary; import com.sun.jna.NativeLibrary;
@ -12,7 +13,7 @@ import java.nio.ByteBuffer;
import java.nio.DoubleBuffer; import java.nio.DoubleBuffer;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import osvrclientkit.OsvrClientKitLibrary;
/** /**
* JNA Wrapper for library <b>osvrDisplay</b><br> * JNA Wrapper for library <b>osvrDisplay</b><br>
* This file was autogenerated by <a href="http://jnaerator.googlecode.com/">JNAerator</a>,<br> * This file was autogenerated by <a href="http://jnaerator.googlecode.com/">JNAerator</a>,<br>

@ -1,10 +1,10 @@
package osvrinterface; package com.jme3.system.osvr.osvrinterface;
import com.jme3.system.osvr.osvrclientkit.OsvrClientKitLibrary.OSVR_ClientInterface;
import com.jme3.system.osvr.osvrclientreporttypes.OSVR_Pose3;
import com.jme3.system.osvr.osvrtimevalue.OSVR_TimeValue;
import com.sun.jna.Library; import com.sun.jna.Library;
import com.sun.jna.Native; import com.sun.jna.Native;
import com.sun.jna.NativeLibrary; import com.sun.jna.NativeLibrary;
import osvrclientkit.OsvrClientKitLibrary.OSVR_ClientInterface;
import osvrclientreporttypes.OSVR_Pose3;
import osvrtimevalue.OSVR_TimeValue;
/** /**
* JNA Wrapper for library <b>osvrInterface</b><br> * JNA Wrapper for library <b>osvrInterface</b><br>
* This file was autogenerated by <a href="http://jnaerator.googlecode.com/">JNAerator</a>,<br> * This file was autogenerated by <a href="http://jnaerator.googlecode.com/">JNAerator</a>,<br>

@ -1,4 +1,4 @@
package osvrmatrixconventions; package com.jme3.system.osvr.osvrmatrixconventions;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrclientreporttypes; package com.jme3.system.osvr.osvrmatrixconventions;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrmatrixconventions; package com.jme3.system.osvr.osvrmatrixconventions;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrmatrixconventions; package com.jme3.system.osvr.osvrmatrixconventions;
import com.sun.jna.Library; import com.sun.jna.Library;
import com.sun.jna.Native; import com.sun.jna.Native;
import com.sun.jna.NativeLibrary; import com.sun.jna.NativeLibrary;

@ -1,4 +1,4 @@
package osvrrendermanager; package com.jme3.system.osvr.osvrrendermanager;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrrendermanager; package com.jme3.system.osvr.osvrrendermanager;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrrendermanageropengl; package com.jme3.system.osvr.osvrrendermanager;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrrendermanager; package com.jme3.system.osvr.osvrrendermanager;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrrendermanager; package com.jme3.system.osvr.osvrrendermanager;
import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference;
import com.sun.jna.Library; import com.sun.jna.Library;
import com.sun.jna.Native; import com.sun.jna.Native;
@ -62,7 +62,7 @@ public class OsvrRenderManagerLibrary implements Library {
*/ */
public static native byte osvrRenderManagerFinishRegisterRenderBuffers(Pointer renderManager, Pointer registerBufferState, byte appWillNotOverwriteBeforeNewPresent); public static native byte osvrRenderManagerFinishRegisterRenderBuffers(Pointer renderManager, Pointer registerBufferState, byte appWillNotOverwriteBeforeNewPresent);
/** Original signature : <code>OSVR_ReturnCode osvrRenderManagerPresentSolidColorf(OSVR_RenderManager, OSVR_RGB_FLOAT)</code> */ /** Original signature : <code>OSVR_ReturnCode osvrRenderManagerPresentSolidColorf(OSVR_RenderManager, OSVR_RGB_FLOAT)</code> */
public static native byte osvrRenderManagerPresentSolidColorf(Pointer renderManager, osvrrendermanager.OSVR_RGB.ByValue rgb); public static native byte osvrRenderManagerPresentSolidColorf(Pointer renderManager, com.jme3.system.osvr.osvrrendermanager.OSVR_RGB.ByValue rgb);
/** /**
* when you're done.<br> * when you're done.<br>
* Original signature : <code>OSVR_ReturnCode osvrRenderManagerGetRenderInfoCollection(OSVR_RenderManager, OSVR_RenderParams, OSVR_RenderInfoCollection*)</code> * Original signature : <code>OSVR_ReturnCode osvrRenderManagerGetRenderInfoCollection(OSVR_RenderManager, OSVR_RenderParams, OSVR_RenderInfoCollection*)</code>
@ -81,37 +81,37 @@ public class OsvrRenderManagerLibrary implements Library {
/** /**
* @return True on success, false on failure (null pointer).<br> * @return True on success, false on failure (null pointer).<br>
* Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_OpenGL(double*, OSVR_ProjectionMatrix)</code><br> * Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_OpenGL(double*, OSVR_ProjectionMatrix)</code><br>
* @deprecated use the safer methods {@link #OSVR_Projection_to_OpenGL(java.nio.DoubleBuffer, osvrrendermanager.OSVR_ProjectionMatrix.ByValue)} and {@link #OSVR_Projection_to_OpenGL(com.sun.jna.ptr.DoubleByReference, osvrrendermanager.OSVR_ProjectionMatrix.ByValue)} instead * @deprecated use the safer methods {@link #OSVR_Projection_to_OpenGL(java.nio.DoubleBuffer, com.jme3.system.osvr.osvrrendermanager.OSVR_ProjectionMatrix.ByValue)} and {@link #OSVR_Projection_to_OpenGL(com.sun.jna.ptr.DoubleByReference, com.jme3.system.osvr.osvrrendermanager.OSVR_ProjectionMatrix.ByValue)} instead
*/ */
@Deprecated @Deprecated
public static native byte OSVR_Projection_to_OpenGL(DoubleByReference OpenGL_out, osvrrendermanager.OSVR_ProjectionMatrix.ByValue projection_in); public static native byte OSVR_Projection_to_OpenGL(DoubleByReference OpenGL_out, com.jme3.system.osvr.osvrrendermanager.OSVR_ProjectionMatrix.ByValue projection_in);
/** /**
* @return True on success, false on failure (null pointer).<br> * @return True on success, false on failure (null pointer).<br>
* Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_OpenGL(double*, OSVR_ProjectionMatrix)</code> * Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_OpenGL(double*, OSVR_ProjectionMatrix)</code>
*/ */
public static native byte OSVR_Projection_to_OpenGL(DoubleBuffer OpenGL_out, osvrrendermanager.OSVR_ProjectionMatrix.ByValue projection_in); public static native byte OSVR_Projection_to_OpenGL(DoubleBuffer OpenGL_out, com.jme3.system.osvr.osvrrendermanager.OSVR_ProjectionMatrix.ByValue projection_in);
/** /**
* @return True on success, false on failure (null pointer).<br> * @return True on success, false on failure (null pointer).<br>
* Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_D3D(float[16], OSVR_ProjectionMatrix)</code><br> * Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_D3D(float[16], OSVR_ProjectionMatrix)</code><br>
* @deprecated use the safer methods {@link #OSVR_Projection_to_D3D(java.nio.FloatBuffer, osvrrendermanager.OSVR_ProjectionMatrix.ByValue)} and {@link #OSVR_Projection_to_D3D(com.sun.jna.ptr.FloatByReference, osvrrendermanager.OSVR_ProjectionMatrix.ByValue)} instead * @deprecated use the safer methods {@link #OSVR_Projection_to_D3D(java.nio.FloatBuffer, com.jme3.system.osvr.osvrrendermanager.OSVR_ProjectionMatrix.ByValue)} and {@link #OSVR_Projection_to_D3D(com.sun.jna.ptr.FloatByReference, com.jme3.system.osvr.osvrrendermanager.OSVR_ProjectionMatrix.ByValue)} instead
*/ */
@Deprecated @Deprecated
public static native byte OSVR_Projection_to_D3D(FloatByReference D3D_out, osvrrendermanager.OSVR_ProjectionMatrix.ByValue projection_in); public static native byte OSVR_Projection_to_D3D(FloatByReference D3D_out, com.jme3.system.osvr.osvrrendermanager.OSVR_ProjectionMatrix.ByValue projection_in);
/** /**
* @return True on success, false on failure (null pointer).<br> * @return True on success, false on failure (null pointer).<br>
* Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_D3D(float[16], OSVR_ProjectionMatrix)</code> * Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_D3D(float[16], OSVR_ProjectionMatrix)</code>
*/ */
public static native byte OSVR_Projection_to_D3D(FloatBuffer D3D_out, osvrrendermanager.OSVR_ProjectionMatrix.ByValue projection_in); public static native byte OSVR_Projection_to_D3D(FloatBuffer D3D_out, com.jme3.system.osvr.osvrrendermanager.OSVR_ProjectionMatrix.ByValue projection_in);
/** /**
* @return True on success, false on failure (null pointer).<br> * @return True on success, false on failure (null pointer).<br>
* Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_Unreal(float[16], OSVR_ProjectionMatrix)</code><br> * Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_Unreal(float[16], OSVR_ProjectionMatrix)</code><br>
* @deprecated use the safer methods {@link #OSVR_Projection_to_Unreal(java.nio.FloatBuffer, osvrrendermanager.OSVR_ProjectionMatrix.ByValue)} and {@link #OSVR_Projection_to_Unreal(com.sun.jna.ptr.FloatByReference, osvrrendermanager.OSVR_ProjectionMatrix.ByValue)} instead * @deprecated use the safer methods {@link #OSVR_Projection_to_Unreal(java.nio.FloatBuffer, com.jme3.system.osvr.osvrrendermanager.OSVR_ProjectionMatrix.ByValue)} and {@link #OSVR_Projection_to_Unreal(com.sun.jna.ptr.FloatByReference, com.jme3.system.osvr.osvrrendermanager.OSVR_ProjectionMatrix.ByValue)} instead
*/ */
@Deprecated @Deprecated
public static native byte OSVR_Projection_to_Unreal(FloatByReference Unreal_out, osvrrendermanager.OSVR_ProjectionMatrix.ByValue projection_in); public static native byte OSVR_Projection_to_Unreal(FloatByReference Unreal_out, com.jme3.system.osvr.osvrrendermanager.OSVR_ProjectionMatrix.ByValue projection_in);
/** /**
* @return True on success, false on failure (null pointer).<br> * @return True on success, false on failure (null pointer).<br>
* Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_Unreal(float[16], OSVR_ProjectionMatrix)</code> * Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_Unreal(float[16], OSVR_ProjectionMatrix)</code>
*/ */
public static native byte OSVR_Projection_to_Unreal(FloatBuffer Unreal_out, osvrrendermanager.OSVR_ProjectionMatrix.ByValue projection_in); public static native byte OSVR_Projection_to_Unreal(FloatBuffer Unreal_out, com.jme3.system.osvr.osvrrendermanager.OSVR_ProjectionMatrix.ByValue projection_in);
} }

@ -1,4 +1,4 @@
package osvrrendermanageropengl; package com.jme3.system.osvr.osvrrendermanageropengl;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;
@ -10,7 +10,7 @@ import java.util.List;
*/ */
public class OSVR_GraphicsLibraryOpenGL extends Structure { public class OSVR_GraphicsLibraryOpenGL extends Structure {
/** C type : const OSVR_OpenGLToolkitFunctions* */ /** C type : const OSVR_OpenGLToolkitFunctions* */
public osvrrendermanageropengl.OSVR_OpenGLToolkitFunctions.ByReference toolkit; public com.jme3.system.osvr.osvrrendermanageropengl.OSVR_OpenGLToolkitFunctions.ByReference toolkit;
public OSVR_GraphicsLibraryOpenGL() { public OSVR_GraphicsLibraryOpenGL() {
super(); super();
} }
@ -18,7 +18,7 @@ public class OSVR_GraphicsLibraryOpenGL extends Structure {
return Arrays.asList("toolkit"); return Arrays.asList("toolkit");
} }
/** @param toolkit C type : const OSVR_OpenGLToolkitFunctions* */ /** @param toolkit C type : const OSVR_OpenGLToolkitFunctions* */
public OSVR_GraphicsLibraryOpenGL(osvrrendermanageropengl.OSVR_OpenGLToolkitFunctions.ByReference toolkit) { public OSVR_GraphicsLibraryOpenGL(com.jme3.system.osvr.osvrrendermanageropengl.OSVR_OpenGLToolkitFunctions.ByReference toolkit) {
super(); super();
this.toolkit = toolkit; this.toolkit = toolkit;
} }

@ -1,4 +1,4 @@
package osvrrendermanageropengl; package com.jme3.system.osvr.osvrrendermanageropengl;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrrendermanageropengl; package com.jme3.system.osvr.osvrrendermanageropengl;
import com.ochafik.lang.jnaerator.runtime.NativeSize; import com.ochafik.lang.jnaerator.runtime.NativeSize;
import com.sun.jna.Callback; import com.sun.jna.Callback;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;

@ -1,4 +1,4 @@
package osvrrendermanageropengl; package com.jme3.system.osvr.osvrrendermanageropengl;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrrendermanageropengl; package com.jme3.system.osvr.osvrrendermanageropengl;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrrendermanageropengl; package com.jme3.system.osvr.osvrrendermanageropengl;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrrendermanageropengl; package com.jme3.system.osvr.osvrrendermanageropengl;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,9 +1,9 @@
package osvrrendermanageropengl; package com.jme3.system.osvr.osvrrendermanageropengl;
import com.jme3.system.osvr.osvrmatrixconventions.OSVR_Pose3;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import osvrmatrixconventions.OSVR_Pose3;
/** /**
* This file was autogenerated by <a href="http://jnaerator.googlecode.com/">JNAerator</a>,<br> * This file was autogenerated by <a href="http://jnaerator.googlecode.com/">JNAerator</a>,<br>
* a tool written by <a href="http://ochafik.com/">Olivier Chafik</a> that <a href="http://code.google.com/p/jnaerator/wiki/CreditsAndLicense">uses a few opensource projects.</a>.<br> * a tool written by <a href="http://ochafik.com/">Olivier Chafik</a> that <a href="http://code.google.com/p/jnaerator/wiki/CreditsAndLicense">uses a few opensource projects.</a>.<br>

@ -1,4 +1,4 @@
package osvrrendermanager; package com.jme3.system.osvr.osvrrendermanageropengl;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrrendermanageropengl; package com.jme3.system.osvr.osvrrendermanageropengl;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,5 @@
package osvrrendermanageropengl; package com.jme3.system.osvr.osvrrendermanageropengl;
import com.jme3.system.osvr.osvrclientkit.OsvrClientKitLibrary;
import com.ochafik.lang.jnaerator.runtime.NativeSize; import com.ochafik.lang.jnaerator.runtime.NativeSize;
import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference; import com.ochafik.lang.jnaerator.runtime.NativeSizeByReference;
import com.sun.jna.Library; import com.sun.jna.Library;
@ -13,7 +14,6 @@ import com.sun.jna.ptr.PointerByReference;
import java.nio.DoubleBuffer; import java.nio.DoubleBuffer;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import osvrclientkit.OsvrClientKitLibrary;
/** /**
* JNA Wrapper for library <b>osvrRenderManagerOpenGL</b><br> * JNA Wrapper for library <b>osvrRenderManagerOpenGL</b><br>
* This file was autogenerated by <a href="http://jnaerator.googlecode.com/">JNAerator</a>,<br> * This file was autogenerated by <a href="http://jnaerator.googlecode.com/">JNAerator</a>,<br>
@ -67,7 +67,7 @@ public class OsvrRenderManagerOpenGLLibrary implements Library {
*/ */
public static native byte osvrRenderManagerFinishRegisterRenderBuffers(Pointer renderManager, Pointer registerBufferState, byte appWillNotOverwriteBeforeNewPresent); public static native byte osvrRenderManagerFinishRegisterRenderBuffers(Pointer renderManager, Pointer registerBufferState, byte appWillNotOverwriteBeforeNewPresent);
/** Original signature : <code>OSVR_ReturnCode osvrRenderManagerPresentSolidColorf(OSVR_RenderManager, OSVR_RGB_FLOAT)</code> */ /** Original signature : <code>OSVR_ReturnCode osvrRenderManagerPresentSolidColorf(OSVR_RenderManager, OSVR_RGB_FLOAT)</code> */
public static native byte osvrRenderManagerPresentSolidColorf(Pointer renderManager, osvrrendermanageropengl.OSVR_RGB.ByValue rgb); public static native byte osvrRenderManagerPresentSolidColorf(Pointer renderManager, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_RGB.ByValue rgb);
/** /**
* when you're done.<br> * when you're done.<br>
* Original signature : <code>OSVR_ReturnCode osvrRenderManagerGetRenderInfoCollection(OSVR_RenderManager, OSVR_RenderParams, OSVR_RenderInfoCollection*)</code> * Original signature : <code>OSVR_ReturnCode osvrRenderManagerGetRenderInfoCollection(OSVR_RenderManager, OSVR_RenderParams, OSVR_RenderInfoCollection*)</code>
@ -86,55 +86,55 @@ public class OsvrRenderManagerOpenGLLibrary implements Library {
/** /**
* @return True on success, false on failure (null pointer).<br> * @return True on success, false on failure (null pointer).<br>
* Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_OpenGL(double*, OSVR_ProjectionMatrix)</code><br> * Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_OpenGL(double*, OSVR_ProjectionMatrix)</code><br>
* @deprecated use the safer methods {@link #OSVR_Projection_to_OpenGL(java.nio.DoubleBuffer, osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue)} and {@link #OSVR_Projection_to_OpenGL(com.sun.jna.ptr.DoubleByReference, osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue)} instead * @deprecated use the safer methods {@link #OSVR_Projection_to_OpenGL(java.nio.DoubleBuffer, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue)} and {@link #OSVR_Projection_to_OpenGL(com.sun.jna.ptr.DoubleByReference, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue)} instead
*/ */
@Deprecated @Deprecated
public static native byte OSVR_Projection_to_OpenGL(DoubleByReference OpenGL_out, osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue projection_in); public static native byte OSVR_Projection_to_OpenGL(DoubleByReference OpenGL_out, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue projection_in);
/** /**
* @return True on success, false on failure (null pointer).<br> * @return True on success, false on failure (null pointer).<br>
* Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_OpenGL(double*, OSVR_ProjectionMatrix)</code> * Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_OpenGL(double*, OSVR_ProjectionMatrix)</code>
*/ */
public static native byte OSVR_Projection_to_OpenGL(DoubleBuffer OpenGL_out, osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue projection_in); public static native byte OSVR_Projection_to_OpenGL(DoubleBuffer OpenGL_out, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue projection_in);
/** /**
* @return True on success, false on failure (null pointer).<br> * @return True on success, false on failure (null pointer).<br>
* Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_D3D(float[16], OSVR_ProjectionMatrix)</code><br> * Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_D3D(float[16], OSVR_ProjectionMatrix)</code><br>
* @deprecated use the safer methods {@link #OSVR_Projection_to_D3D(java.nio.FloatBuffer, osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue)} and {@link #OSVR_Projection_to_D3D(com.sun.jna.ptr.FloatByReference, osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue)} instead * @deprecated use the safer methods {@link #OSVR_Projection_to_D3D(java.nio.FloatBuffer, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue)} and {@link #OSVR_Projection_to_D3D(com.sun.jna.ptr.FloatByReference, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue)} instead
*/ */
@Deprecated @Deprecated
public static native byte OSVR_Projection_to_D3D(FloatByReference D3D_out, osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue projection_in); public static native byte OSVR_Projection_to_D3D(FloatByReference D3D_out, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue projection_in);
/** /**
* @return True on success, false on failure (null pointer).<br> * @return True on success, false on failure (null pointer).<br>
* Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_D3D(float[16], OSVR_ProjectionMatrix)</code> * Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_D3D(float[16], OSVR_ProjectionMatrix)</code>
*/ */
public static native byte OSVR_Projection_to_D3D(FloatBuffer D3D_out, osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue projection_in); public static native byte OSVR_Projection_to_D3D(FloatBuffer D3D_out, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue projection_in);
/** /**
* @return True on success, false on failure (null pointer).<br> * @return True on success, false on failure (null pointer).<br>
* Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_Unreal(float[16], OSVR_ProjectionMatrix)</code><br> * Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_Unreal(float[16], OSVR_ProjectionMatrix)</code><br>
* @deprecated use the safer methods {@link #OSVR_Projection_to_Unreal(java.nio.FloatBuffer, osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue)} and {@link #OSVR_Projection_to_Unreal(com.sun.jna.ptr.FloatByReference, osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue)} instead * @deprecated use the safer methods {@link #OSVR_Projection_to_Unreal(java.nio.FloatBuffer, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue)} and {@link #OSVR_Projection_to_Unreal(com.sun.jna.ptr.FloatByReference, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue)} instead
*/ */
@Deprecated @Deprecated
public static native byte OSVR_Projection_to_Unreal(FloatByReference Unreal_out, osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue projection_in); public static native byte OSVR_Projection_to_Unreal(FloatByReference Unreal_out, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue projection_in);
/** /**
* @return True on success, false on failure (null pointer).<br> * @return True on success, false on failure (null pointer).<br>
* Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_Unreal(float[16], OSVR_ProjectionMatrix)</code> * Original signature : <code>OSVR_ReturnCode OSVR_Projection_to_Unreal(float[16], OSVR_ProjectionMatrix)</code>
*/ */
public static native byte OSVR_Projection_to_Unreal(FloatBuffer Unreal_out, osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue projection_in); public static native byte OSVR_Projection_to_Unreal(FloatBuffer Unreal_out, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ProjectionMatrix.ByValue projection_in);
/** /**
* Original signature : <code>OSVR_ReturnCode osvrCreateRenderManagerOpenGL(OSVR_ClientContext, const char[], OSVR_GraphicsLibraryOpenGL, OSVR_RenderManager*, OSVR_RenderManagerOpenGL*)</code><br> * Original signature : <code>OSVR_ReturnCode osvrCreateRenderManagerOpenGL(OSVR_ClientContext, const char[], OSVR_GraphicsLibraryOpenGL, OSVR_RenderManager*, OSVR_RenderManagerOpenGL*)</code><br>
* @deprecated use the safer methods {@link #osvrCreateRenderManagerOpenGL(osvrrendermanageropengl.OsvrRenderManagerOpenGLLibrary.OSVR_ClientContext, byte[], osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue, com.sun.jna.ptr.PointerByReference, com.sun.jna.ptr.PointerByReference)} and {@link #osvrCreateRenderManagerOpenGL(com.sun.jna.Pointer, com.sun.jna.Pointer, osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue, com.sun.jna.ptr.PointerByReference, com.sun.jna.ptr.PointerByReference)} instead * @deprecated use the safer methods {@link #osvrCreateRenderManagerOpenGL(com.jme3.system.osvr.osvrrendermanageropengl.OsvrRenderManagerOpenGLLibrary.OSVR_ClientContext, byte[], com.jme3.system.osvr.osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue, com.sun.jna.ptr.PointerByReference, com.sun.jna.ptr.PointerByReference)} and {@link #osvrCreateRenderManagerOpenGL(com.sun.jna.Pointer, com.sun.jna.Pointer, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue, com.sun.jna.ptr.PointerByReference, com.sun.jna.ptr.PointerByReference)} instead
*/ */
@Deprecated @Deprecated
public static native byte osvrCreateRenderManagerOpenGL(Pointer clientContext, Pointer graphicsLibraryName, osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue graphicsLibrary, PointerByReference renderManagerOut, PointerByReference renderManagerOpenGLOut); public static native byte osvrCreateRenderManagerOpenGL(Pointer clientContext, Pointer graphicsLibraryName, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue graphicsLibrary, PointerByReference renderManagerOut, PointerByReference renderManagerOpenGLOut);
/** Original signature : <code>OSVR_ReturnCode osvrCreateRenderManagerOpenGL(OSVR_ClientContext, const char[], OSVR_GraphicsLibraryOpenGL, OSVR_RenderManager*, OSVR_RenderManagerOpenGL*)</code> */ /** Original signature : <code>OSVR_ReturnCode osvrCreateRenderManagerOpenGL(OSVR_ClientContext, const char[], OSVR_GraphicsLibraryOpenGL, OSVR_RenderManager*, OSVR_RenderManagerOpenGL*)</code> */
public static native byte osvrCreateRenderManagerOpenGL(OsvrClientKitLibrary.OSVR_ClientContext clientContext, byte graphicsLibraryName[], osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue graphicsLibrary, PointerByReference renderManagerOut, PointerByReference renderManagerOpenGLOut); public static native byte osvrCreateRenderManagerOpenGL(OsvrClientKitLibrary.OSVR_ClientContext clientContext, byte graphicsLibraryName[], com.jme3.system.osvr.osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue graphicsLibrary, PointerByReference renderManagerOut, PointerByReference renderManagerOpenGLOut);
/** Original signature : <code>OSVR_ReturnCode osvrRenderManagerGetRenderInfoOpenGL(OSVR_RenderManagerOpenGL, OSVR_RenderInfoCount, OSVR_RenderParams, OSVR_RenderInfoOpenGL*)</code> */ /** Original signature : <code>OSVR_ReturnCode osvrRenderManagerGetRenderInfoOpenGL(OSVR_RenderManagerOpenGL, OSVR_RenderInfoCount, OSVR_RenderParams, OSVR_RenderInfoOpenGL*)</code> */
public static native byte osvrRenderManagerGetRenderInfoOpenGL(Pointer renderManager, NativeSize renderInfoIndex, OSVR_RenderParams.ByValue renderParams, OSVR_RenderInfoOpenGL renderInfoOut); public static native byte osvrRenderManagerGetRenderInfoOpenGL(Pointer renderManager, NativeSize renderInfoIndex, OSVR_RenderParams.ByValue renderParams, OSVR_RenderInfoOpenGL renderInfoOut);
/** Original signature : <code>OSVR_ReturnCode osvrRenderManagerOpenDisplayOpenGL(OSVR_RenderManagerOpenGL, OSVR_OpenResultsOpenGL*)</code> */ /** Original signature : <code>OSVR_ReturnCode osvrRenderManagerOpenDisplayOpenGL(OSVR_RenderManagerOpenGL, OSVR_OpenResultsOpenGL*)</code> */
public static native byte osvrRenderManagerOpenDisplayOpenGL(Pointer renderManager, OSVR_OpenResultsOpenGL openResultsOut); public static native byte osvrRenderManagerOpenDisplayOpenGL(Pointer renderManager, OSVR_OpenResultsOpenGL openResultsOut);
/** Original signature : <code>OSVR_ReturnCode osvrRenderManagerPresentRenderBufferOpenGL(OSVR_RenderManagerPresentState, OSVR_RenderBufferOpenGL, OSVR_RenderInfoOpenGL, OSVR_ViewportDescription)</code> */ /** Original signature : <code>OSVR_ReturnCode osvrRenderManagerPresentRenderBufferOpenGL(OSVR_RenderManagerPresentState, OSVR_RenderBufferOpenGL, OSVR_RenderInfoOpenGL, OSVR_ViewportDescription)</code> */
public static native byte osvrRenderManagerPresentRenderBufferOpenGL(Pointer presentState, osvrrendermanageropengl.OSVR_RenderBufferOpenGL.ByValue buffer, OSVR_RenderInfoOpenGL.ByValue renderInfoUsed, osvrrendermanageropengl.OSVR_ViewportDescription.ByValue normalizedCroppingViewport); public static native byte osvrRenderManagerPresentRenderBufferOpenGL(Pointer presentState, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_RenderBufferOpenGL.ByValue buffer, OSVR_RenderInfoOpenGL.ByValue renderInfoUsed, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ViewportDescription.ByValue normalizedCroppingViewport);
/** Original signature : <code>OSVR_ReturnCode osvrRenderManagerRegisterRenderBufferOpenGL(OSVR_RenderManagerRegisterBufferState, OSVR_RenderBufferOpenGL)</code> */ /** Original signature : <code>OSVR_ReturnCode osvrRenderManagerRegisterRenderBufferOpenGL(OSVR_RenderManagerRegisterBufferState, OSVR_RenderBufferOpenGL)</code> */
public static native byte osvrRenderManagerRegisterRenderBufferOpenGL(Pointer registerBufferState, osvrrendermanageropengl.OSVR_RenderBufferOpenGL.ByValue renderBuffer); public static native byte osvrRenderManagerRegisterRenderBufferOpenGL(Pointer registerBufferState, com.jme3.system.osvr.osvrrendermanageropengl.OSVR_RenderBufferOpenGL.ByValue renderBuffer);
/** /**
* Gets a given OSVR_RenderInfoOpenGL from an OSVR_RenderInfoCollection.<br> * Gets a given OSVR_RenderInfoOpenGL from an OSVR_RenderInfoCollection.<br>
* Original signature : <code>OSVR_ReturnCode osvrRenderManagerGetRenderInfoFromCollectionOpenGL(OSVR_RenderInfoCollection, OSVR_RenderInfoCount, OSVR_RenderInfoOpenGL*)</code> * Original signature : <code>OSVR_ReturnCode osvrRenderManagerGetRenderInfoFromCollectionOpenGL(OSVR_RenderInfoCollection, OSVR_RenderInfoCount, OSVR_RenderInfoOpenGL*)</code>

@ -1,4 +1,4 @@
package osvrtimevalue; package com.jme3.system.osvr.osvrtimevalue;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
import java.util.Arrays; import java.util.Arrays;

@ -1,4 +1,4 @@
package osvrtimevalue; package com.jme3.system.osvr.osvrtimevalue;
import com.sun.jna.Library; import com.sun.jna.Library;
import com.sun.jna.Native; import com.sun.jna.Native;
import com.sun.jna.NativeLibrary; import com.sun.jna.NativeLibrary;

@ -0,0 +1,223 @@
package com.jme3.util;
import com.jme3.app.VREnvironment;
import com.jme3.post.CartoonSSAO;
import com.jme3.post.Filter;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.FilterUtil;
import com.jme3.post.SceneProcessor;
import com.jme3.post.filters.FogFilter;
import com.jme3.post.filters.TranslucentBucketFilter;
import com.jme3.post.ssao.SSAOFilter;
import com.jme3.renderer.Camera;
import com.jme3.renderer.ViewPort;
import com.jme3.shadow.DirectionalLightShadowFilter;
import com.jme3.shadow.VRDirectionalLightShadowRenderer;
import com.jme3.texture.Texture2D;
/**
* A VR view manager. This class holds methods that enable to submit 3D views to the VR compositor.
* System dependent classes should extends from this one.
* @author Julien Seinturier - (c) 2016 - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a>
*/
public abstract class AbstractVRViewManager implements VRViewManager {
//private static final Logger logger = Logger.getLogger(AbstractVRViewManager.class.getName());
protected VREnvironment environment = null;
protected Camera leftCamera;
protected ViewPort leftViewport;
protected FilterPostProcessor leftPostProcessor;
protected Texture2D leftEyeTexture;
protected Texture2D leftEyeDepth;
protected Camera rightCamera;
protected ViewPort rightViewport;
protected FilterPostProcessor rightPostProcessor;
protected Texture2D rightEyeTexture;
protected Texture2D rightEyeDepth;
private float resMult = 1f;
private float heightAdjustment;
@Override
public Camera getLeftCamera() {
return leftCamera;
}
@Override
public Camera getRightCamera() {
return rightCamera;
}
@Override
public ViewPort getLeftViewport() {
return leftViewport;
}
@Override
public ViewPort getRightViewport() {
return rightViewport;
}
@Override
public Texture2D getLeftTexture(){
return leftEyeTexture;
}
@Override
public Texture2D getRightTexture(){
return rightEyeTexture;
}
@Override
public Texture2D getLeftDepth(){
return leftEyeDepth;
}
@Override
public Texture2D getRightDepth(){
return rightEyeDepth;
}
@Override
public FilterPostProcessor getLeftPostProcessor(){
return leftPostProcessor;
}
@Override
public FilterPostProcessor getRightPostProcessor(){
return rightPostProcessor;
}
@Override
public float getResolutionMuliplier() {
return resMult;
}
@Override
public void setResolutionMultiplier(float resMult) {
this.resMult = resMult;
}
@Override
public float getHeightAdjustment() {
return heightAdjustment;
}
@Override
public void setHeightAdjustment(float amount) {
heightAdjustment = amount;
}
@Override
public VREnvironment getVREnvironment(){
return environment;
}
/**
* Handles moving filters from the main view to each eye
*/
public void moveScreenProcessingToEyes() {
if (environment != null){
if( getRightViewport() == null ){
return;
}
if (environment.getApplication() != null){
syncScreenProcessing(environment.getApplication().getViewPort());
environment.getApplication().getViewPort().clearProcessors();
} else {
throw new IllegalStateException("The VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Sets the two views to use the list of {@link SceneProcessor processors}.
* @param sourceViewport the {@link ViewPort viewport} that contains the processors to use.
*/
public void syncScreenProcessing(ViewPort sourceViewport) {
if (environment != null){
if( getRightViewport() == null ){
return;
}
if (environment.getApplication() != null){
// setup post processing filters
if( getRightPostProcessor() == null ) {
rightPostProcessor = new FilterPostProcessor(environment.getApplication().getAssetManager());
leftPostProcessor = new FilterPostProcessor(environment.getApplication().getAssetManager());
}
// clear out all filters & processors, to start from scratch
getRightPostProcessor().removeAllFilters();
getLeftPostProcessor().removeAllFilters();
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());
// 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()) {
if (sceneProcessor instanceof FilterPostProcessor) {
for(Filter f : ((FilterPostProcessor)sceneProcessor).getFilterList() ) {
if( f instanceof TranslucentBucketFilter ) {
// just remove this filter, we will add it at the end manually
((FilterPostProcessor)sceneProcessor).removeFilter(f);
} else {
getLeftPostProcessor().addFilter(f);
// clone to the right
Filter f2;
if(f instanceof FogFilter){
f2 = FilterUtil.cloneFogFilter((FogFilter)f);
} else if (f instanceof CartoonSSAO ) {
f2 = new CartoonSSAO((CartoonSSAO)f);
} else if (f instanceof SSAOFilter){
f2 = FilterUtil.cloneSSAOFilter((SSAOFilter)f);
} else if (f instanceof DirectionalLightShadowFilter){
f2 = FilterUtil.cloneDirectionalLightShadowFilter(environment.getApplication().getAssetManager(), (DirectionalLightShadowFilter)f);
} else {
f2 = f; // dof, bloom, lightscattering etc.
}
getRightPostProcessor().addFilter(f2);
}
}
} else if (sceneProcessor instanceof VRDirectionalLightShadowRenderer) {
// shadow processing
// TODO: make right shadow processor use same left shadow maps for performance
VRDirectionalLightShadowRenderer dlsr = (VRDirectionalLightShadowRenderer) sceneProcessor;
VRDirectionalLightShadowRenderer dlsrRight = dlsr.clone();
dlsrRight.setLight(dlsr.getLight());
getRightViewport().getProcessors().add(0, dlsrRight);
getLeftViewport().getProcessors().add(0, sceneProcessor);
}
}
// make sure each has a translucent filter renderer
getLeftPostProcessor().addFilter(new TranslucentBucketFilter());
getRightPostProcessor().addFilter(new TranslucentBucketFilter());
} else {
throw new IllegalStateException("The VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
}

@ -0,0 +1,15 @@
package com.jme3.util;
/**
* A enumeration that describes the GUI display positioning modes.
* @author Julien Seinturier - (c) 2016 - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a>
*
*/
public enum VRGUIPositioningMode {
MANUAL,
AUTO_CAM_ALL,
AUTO_CAM_ALL_SKIP_PITCH,
AUTO_OBSERVER_POS_CAM_ROTATION,
AUTO_OBSERVER_ALL,
AUTO_OBSERVER_ALL_CAMHEIGHT
}

@ -0,0 +1,474 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.jme3.util;
import com.jme3.app.VREnvironment;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Spatial;
import com.jme3.scene.CenterQuad;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.system.AppSettings;
import com.jme3.texture.FrameBuffer;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import java.awt.GraphicsEnvironment;
import java.util.Iterator;
/**
* A class dedicated to the management and the display of a Graphical User Interface (GUI) within a VR environment.
* @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 VRGuiManager {
private Camera camLeft, camRight;
private float guiDistance = 1.5f;
private float guiScale = 1f;
private float guiPositioningElastic;
private VRGUIPositioningMode posMode = VRGUIPositioningMode.AUTO_CAM_ALL;
private final Matrix3f orient = new Matrix3f();
private Vector2f screenSize;
protected boolean wantsReposition;
private Vector2f ratio;
private final Vector3f EoldPos = new Vector3f();
private final Quaternion EoldDir = new Quaternion();
private final Vector3f look = new Vector3f();
private final Vector3f left = new Vector3f();
private final Vector3f temppos = new Vector3f();
private final Vector3f up = new Vector3f();
private boolean useCurvedSurface = false;
private boolean overdraw = false;
private Geometry guiQuad;
private Node guiQuadNode;
private ViewPort offView;
private Texture2D guiTexture;
private final Quaternion tempq = new Quaternion();
private VREnvironment environment = null;
/**
* Create a new GUI manager attached to the given app state.
* @param environment the VR environment to which this manager is attached to.
*/
public VRGuiManager(VREnvironment environment){
this.environment = environment;
}
/**
*
* Makes auto GUI positioning happen not immediately, but like an
* elastic connected to the headset. Setting to 0 disables (default)
* Higher settings make it track the headset quicker.
*
* @param elastic amount of elasticity
*/
public void setPositioningElasticity(float elastic) {
guiPositioningElastic = elastic;
}
public float getPositioningElasticity() {
return guiPositioningElastic;
}
/**
* Get the GUI {@link VRGUIPositioningMode positioning mode}.
* @return the GUI {@link VRGUIPositioningMode positioning mode}.
* @see #setPositioningMode(VRGUIPositioningMode)
*/
public VRGUIPositioningMode getPositioningMode() {
return posMode;
}
/**
* Set the GUI {@link VRGUIPositioningMode positioning mode}.
* @param mode the GUI {@link VRGUIPositioningMode positioning mode}.
* @see #getPositioningMode()
*/
public void setPositioningMode(VRGUIPositioningMode mode) {
posMode = mode;
}
/**
* Get the GUI canvas size. This method return the size in pixels of the GUI available area within the VR view.
* @return the GUI canvas size. This method return the size in pixels of the GUI available area within the VR view.
*/
public Vector2f getCanvasSize() {
if (environment != null){
if (environment.getApplication() != null){
if( screenSize == null ) {
if( environment.isInVR() && environment.getVRHardware() != null ) {
screenSize = new Vector2f();
environment.getVRHardware().getRenderSize(screenSize);
screenSize.multLocal(environment.getVRViewManager().getResolutionMuliplier());
} else {
AppSettings as = environment.getApplication().getContext().getSettings();
screenSize = new Vector2f(as.getWidth(), as.getHeight());
}
}
return screenSize;
} else {
throw new IllegalStateException("VR GUI manager underlying environment is not attached to any application.");
}
} else {
throw new IllegalStateException("VR GUI manager is not attached to any environment.");
}
}
/**
* Get the ratio between the {@link #getCanvasSize() GUI canvas size} and the application main windows (if available) or the screen size.
* @return the ratio between the {@link #getCanvasSize() GUI canvas size} and the application main windows (if available).
* @see #getCanvasSize()
*/
public Vector2f getCanvasToWindowRatio() {
if (environment != null){
if (environment.getApplication() != null){
if( ratio == null ) {
ratio = new Vector2f();
Vector2f canvas = getCanvasSize();
int width = Integer.min(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getWidth(),
environment.getApplication().getContext().getSettings().getWidth());
int height = Integer.min(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getHeight(),
environment.getApplication().getContext().getSettings().getHeight());
ratio.x = Float.max(1f, canvas.x / width);
ratio.y = Float.max(1f, canvas.y / height);
}
return ratio;
} else {
throw new IllegalStateException("VR GUI manager underlying environment is not attached to any application.");
}
} else {
throw new IllegalStateException("VR GUI manager is not attached to any environment.");
}
}
/**
* Inform this manager that it has to position the GUI.
*/
public void positionGui() {
wantsReposition = true;
}
/**
* Position the GUI to the given location.
* @param pos the position of the GUI.
* @param dir the rotation of the GUI.
* @param tpf the time per frame.
*/
private void positionTo(Vector3f pos, Quaternion dir, float tpf) {
if (environment != null){
Vector3f guiPos = guiQuadNode.getLocalTranslation();
guiPos.set(0f, 0f, guiDistance);
dir.mult(guiPos, guiPos);
guiPos.x += pos.x;
guiPos.y += pos.y + environment.getVRHeightAdjustment();
guiPos.z += pos.z;
if( guiPositioningElastic > 0f && posMode != VRGUIPositioningMode.MANUAL ) {
// mix pos & dir with current pos & dir
guiPos.interpolateLocal(EoldPos, guiPos, Float.min(1f, tpf * guiPositioningElastic));
EoldPos.set(guiPos);
}
} else {
throw new IllegalStateException("VR GUI manager is not attached to any environment.");
}
}
/**
* Update the GUI geometric state. This method should be called after GUI modification.
*/
protected void updateGuiQuadGeometricState() {
guiQuadNode.updateGeometricState();
}
/**
* Position the GUI without delay.
* @param tpf the time per frame.
*/
protected void positionGuiNow(float tpf) {
if (environment != null){
wantsReposition = false;
if( environment.isInVR() == false ){
return;
}
guiQuadNode.setLocalScale(guiDistance * guiScale * 4f, 4f * guiDistance * guiScale, 1f);
switch( posMode ) {
case MANUAL:
case AUTO_CAM_ALL_SKIP_PITCH:
case AUTO_CAM_ALL:
if( camLeft != null && camRight != null ) {
// get middle point
temppos.set(camLeft.getLocation()).interpolateLocal(camRight.getLocation(), 0.5f);
positionTo(temppos, camLeft.getRotation(), tpf);
}
rotateScreenTo(camLeft.getRotation(), tpf);
break;
case AUTO_OBSERVER_POS_CAM_ROTATION:
Object obs = environment.getObserver();
if( obs != null ) {
if( obs instanceof Camera ) {
positionTo(((Camera)obs).getLocation(), camLeft.getRotation(), tpf);
} else {
positionTo(((Spatial)obs).getWorldTranslation(), camLeft.getRotation(), tpf);
}
}
rotateScreenTo(camLeft.getRotation(), tpf);
break;
case AUTO_OBSERVER_ALL:
case AUTO_OBSERVER_ALL_CAMHEIGHT:
obs = environment.getObserver();
if( obs != null ) {
Quaternion q;
if( obs instanceof Camera ) {
q = ((Camera)obs).getRotation();
temppos.set(((Camera)obs).getLocation());
} else {
q = ((Spatial)obs).getWorldRotation();
temppos.set(((Spatial)obs).getWorldTranslation());
}
if( posMode == VRGUIPositioningMode.AUTO_OBSERVER_ALL_CAMHEIGHT ) {
temppos.y = camLeft.getLocation().y;
}
positionTo(temppos, q, tpf);
rotateScreenTo(q, tpf);
}
break;
}
} else {
throw new IllegalStateException("VR GUI manager is not attached to any environment.");
}
}
/**
* Rotate the GUI to the given direction.
* @param dir the direction to rotate to.
* @param tpf the time per frame.
*/
private void rotateScreenTo(Quaternion dir, float tpf) {
dir.getRotationColumn(2, look).negateLocal();
dir.getRotationColumn(0, left).negateLocal();
orient.fromAxes(left, dir.getRotationColumn(1, up), look);
Quaternion rot = tempq.fromRotationMatrix(orient);
if( posMode == VRGUIPositioningMode.AUTO_CAM_ALL_SKIP_PITCH ){
VRUtil.stripToYaw(rot);
}
if( guiPositioningElastic > 0f && posMode != VRGUIPositioningMode.MANUAL ) {
// mix pos & dir with current pos & dir
EoldDir.nlerp(rot, tpf * guiPositioningElastic);
guiQuadNode.setLocalRotation(EoldDir);
} else {
guiQuadNode.setLocalRotation(rot);
}
}
/**
* Get the GUI distance from the observer.
* @return the GUI distance from the observer.
* @see #setGuiDistance(float)
*/
public float getGuiDistance() {
return guiDistance;
}
/**
* Set the GUI distance from the observer.
* @param newGuiDistance the GUI distance from the observer.
* @see #getGuiDistance()
*/
public void setGuiDistance(float newGuiDistance) {
guiDistance = newGuiDistance;
}
/**
* Get the GUI scale.
* @return the GUI scale.
* @see #setGuiScale(float)
*/
public float getGUIScale(){
return guiScale;
}
/**
* Set the GUI scale.
* @param scale the GUI scale.
* @see #getGUIScale()
*/
public void setGuiScale(float scale) {
guiScale = scale;
}
/**
* Adjust the GUI distance from the observer.
* This method increment / decrement the {@link #getGuiDistance() GUI distance} by the given value.
* @param adjustAmount the increment (if positive) / decrement (if negative) value of the GUI distance.
*/
public void adjustGuiDistance(float adjustAmount) {
guiDistance += adjustAmount;
}
/**
* Set up the GUI.
* @param leftcam the left eye camera.
* @param rightcam the right eye camera.
* @param left the left eye viewport.
* @param right the right eye viewport.
*/
protected void setupGui(Camera leftcam, Camera rightcam, ViewPort left, ViewPort right) {
if (environment != null){
if( environment.hasTraditionalGUIOverlay() ) {
camLeft = leftcam;
camRight = rightcam;
Spatial guiScene = getGuiQuad(camLeft);
left.attachScene(guiScene);
if( right != null ) right.attachScene(guiScene);
setPositioningMode(posMode);
}
} else {
throw new IllegalStateException("VR GUI manager is not attached to any environment.");
}
}
/**
* Get if the GUI has to use curved surface.
* @return <code>true</code> if the GUI has to use curved surface and <code>false</code> otherwise.
* @see #setCurvedSurface(boolean)
*/
public boolean isCurverSurface(){
return useCurvedSurface;
}
/**
* Set if the GUI has to use curved surface.
* @param set <code>true</code> if the GUI has to use curved surface and <code>false</code> otherwise.
* @see #isCurverSurface()
*/
public void setCurvedSurface(boolean set) {
useCurvedSurface = set;
}
/**
* Get if the GUI has to be displayed even if it is behind objects.
* @return <code>true</code> if the GUI has to use curved surface and <code>false</code> otherwise.
* @see #setGuiOverdraw(boolean)
*/
public boolean isGuiOverdraw(){
return overdraw;
}
/**
* Set if the GUI has to be displayed even if it is behind objects.
* @param set <code>true</code> if the GUI has to use curved surface and <code>false</code> otherwise.
* @see #isGuiOverdraw()
*/
public void setGuiOverdraw(boolean set) {
overdraw = set;
}
/**
* Create a GUI quad for the given camera.
* @param sourceCam the camera
* @return a GUI quad for the given camera.
*/
private Spatial getGuiQuad(Camera sourceCam){
if (environment != null){
if (environment.getApplication() != null){
if( guiQuadNode == null ) {
Vector2f guiCanvasSize = getCanvasSize();
Camera offCamera = sourceCam.clone();
offCamera.setParallelProjection(true);
offCamera.setLocation(Vector3f.ZERO);
offCamera.lookAt(Vector3f.UNIT_Z, Vector3f.UNIT_Y);
offView = environment.getApplication().getRenderManager().createPreView("GUI View", offCamera);
offView.setClearFlags(true, true, true);
offView.setBackgroundColor(ColorRGBA.BlackNoAlpha);
// create offscreen framebuffer
FrameBuffer offBuffer = new FrameBuffer((int)guiCanvasSize.x, (int)guiCanvasSize.y, 1);
//setup framebuffer's texture
guiTexture = new Texture2D((int)guiCanvasSize.x, (int)guiCanvasSize.y, Format.RGBA8);
guiTexture.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
guiTexture.setMagFilter(Texture.MagFilter.Bilinear);
//setup framebuffer to use texture
offBuffer.setDepthBuffer(Format.Depth);
offBuffer.setColorTexture(guiTexture);
//set viewport to render to offscreen framebuffer
offView.setOutputFrameBuffer(offBuffer);
// setup framebuffer's scene
Iterator<Spatial> spatialIter = environment.getApplication().getGuiViewPort().getScenes().iterator();
while(spatialIter.hasNext()){
offView.attachScene(spatialIter.next());
}
if( useCurvedSurface ) {
guiQuad = (Geometry)environment.getApplication().getAssetManager().loadModel("Common/Util/gui_mesh.j3o");
} else {
guiQuad = new Geometry("guiQuad", new CenterQuad(1f, 1f));
}
Material mat = new Material(environment.getApplication().getAssetManager(), "Common/MatDefs/VR/GuiOverlay.j3md");
mat.getAdditionalRenderState().setDepthTest(!overdraw);
mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
mat.getAdditionalRenderState().setDepthWrite(false);
mat.setTexture("ColorMap", guiTexture);
guiQuad.setQueueBucket(Bucket.Translucent);
guiQuad.setMaterial(mat);
guiQuadNode = new Node("gui-quad-node");
guiQuadNode.setQueueBucket(Bucket.Translucent);
guiQuadNode.attachChild(guiQuad);
}
return guiQuadNode;
} else {
throw new IllegalStateException("VR GUI manager underlying environment is not attached to any application.");
}
} else {
throw new IllegalStateException("VR GUI manager is not attached to any environment.");
}
}
}

@ -0,0 +1,334 @@
/*
* 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.util;
import java.util.logging.Logger;
import org.lwjgl.glfw.GLFW;
import com.jme3.app.VREnvironment;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.lwjgl.GlfwMouseInputVR;
import com.jme3.input.vr.VRInputType;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.Vector2f;
import com.jme3.scene.Node;
import com.jme3.system.AppSettings;
import com.jme3.system.lwjgl.LwjglWindow;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.ui.Picture;
/**
* A class dedicated to the handling of the mouse within VR environment.
* @author Julien Seinturier - (c) 2016 - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a>
*
*/
public class VRMouseManager {
private static final Logger logger = Logger.getLogger(VRMouseManager.class.getName());
private VREnvironment environment = null;
private final int AVERAGE_AMNT = 4;
private int avgCounter;
private Picture mouseImage;
private int recentCenterCount = 0;
private final Vector2f cursorPos = new Vector2f();
private float ySize, sensitivity = 8f, acceleration = 2f;
private final float[] lastXmv = new float[AVERAGE_AMNT], lastYmv = new float[AVERAGE_AMNT];
private boolean thumbstickMode;
private float moveScale = 1f;
private float avg(float[] arr) {
float amt = 0f;
for(float f : arr) amt += f;
return amt / arr.length;
}
/**
* Create a new VR mouse manager within the given {@link VREnvironment VR environment}.
* @param environment the VR environment of the mouse manager.
*/
public VRMouseManager(VREnvironment environment){
this.environment = environment;
}
/**
* Initialize the VR mouse manager.
*/
protected void initialize() {
logger.config("Initializing VR mouse manager.");
// load default mouseimage
mouseImage = new Picture("mouse");
setImage("Common/Util/mouse.png");
// hide default cursor by making it invisible
MouseInput mi = environment.getApplication().getContext().getMouseInput();
if( mi instanceof GlfwMouseInputVR ){
((GlfwMouseInputVR)mi).hideActiveCursor();
}
centerMouse();
logger.config("Initialized VR mouse manager [SUCCESS]");
}
public void setThumbstickMode(boolean set) {
thumbstickMode = set;
}
public boolean isThumbstickMode() {
return thumbstickMode;
}
/**
* Set the speed of the mouse.
* @param sensitivity the sensitivity of the mouse.
* @param acceleration the acceleration of the mouse.
* @see #getSpeedAcceleration()
* @see #getSpeedSensitivity()
*/
public void setSpeed(float sensitivity, float acceleration) {
this.sensitivity = sensitivity;
this.acceleration = acceleration;
}
/**
* Get the sensitivity of the mouse.
* @return the sensitivity of the mouse.
* @see #setSpeed(float, float)
*/
public float getSpeedSensitivity() {
return sensitivity;
}
/**
* Get the acceleration of the mouse.
* @return the acceleration of the mouse.
* @see #setSpeed(float, float)
*/
public float getSpeedAcceleration() {
return acceleration;
}
/**
* Set the mouse move scale.
* @param set the mouse move scale.
*/
public void setMouseMoveScale(float set) {
moveScale = set;
}
/**
* Set the image to use as mouse cursor. The given string describe an asset that the underlying application asset manager has to load.
* @param texture the image to use as mouse cursor.
*/
public void setImage(String texture) {
if (environment != null){
if (environment.getApplication() != null){
if( environment.isInVR() == false ){
Texture tex = environment.getApplication().getAssetManager().loadTexture(texture);
mouseImage.setTexture(environment.getApplication().getAssetManager(), (Texture2D)tex, true);
ySize = tex.getImage().getHeight();
mouseImage.setHeight(ySize);
mouseImage.setWidth(tex.getImage().getWidth());
mouseImage.getMaterial().getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
mouseImage.getMaterial().getAdditionalRenderState().setDepthWrite(false);
} else {
Texture tex = environment.getApplication().getAssetManager().loadTexture(texture);
mouseImage.setTexture(environment.getApplication().getAssetManager(), (Texture2D)tex, true);
ySize = tex.getImage().getHeight();
mouseImage.setHeight(ySize);
mouseImage.setWidth(tex.getImage().getWidth());
mouseImage.getMaterial().getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
mouseImage.getMaterial().getAdditionalRenderState().setDepthWrite(false);
}
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Update analog controller as it was a mouse controller.
* @param inputIndex the index of the controller attached to the VR system.
* @param mouseListener the JMonkey mouse listener to trigger.
* @param mouseXName the mouseX identifier.
* @param mouseYName the mouseY identifier
* @param tpf the time per frame.
*/
public void updateAnalogAsMouse(int inputIndex, AnalogListener mouseListener, String mouseXName, String mouseYName, float tpf) {
if (environment != null){
if (environment.getApplication() != null){
// got a tracked controller to use as the "mouse"
if( environment.isInVR() == false ||
environment.getVRinput() == null ||
environment.getVRinput().isInputDeviceTracking(inputIndex) == false ){
return;
}
Vector2f tpDelta;
if( thumbstickMode ) {
tpDelta = environment.getVRinput().getAxis(inputIndex, VRInputType.ViveTrackpadAxis);
} else {
tpDelta = environment.getVRinput().getAxisDeltaSinceLastCall(inputIndex, VRInputType.ViveTrackpadAxis);
}
float Xamount = (float)Math.pow(Math.abs(tpDelta.x) * sensitivity, acceleration);
float Yamount = (float)Math.pow(Math.abs(tpDelta.y) * sensitivity, acceleration);
if( tpDelta.x < 0f ){
Xamount = -Xamount;
}
if( tpDelta.y < 0f ){
Yamount = -Yamount;
}
Xamount *= moveScale; Yamount *= moveScale;
if( mouseListener != null ) {
if( tpDelta.x != 0f && mouseXName != null ) mouseListener.onAnalog(mouseXName, Xamount * 0.2f, tpf);
if( tpDelta.y != 0f && mouseYName != null ) mouseListener.onAnalog(mouseYName, Yamount * 0.2f, tpf);
}
if( environment.getApplication().getInputManager().isCursorVisible() ) {
int index = (avgCounter+1) % AVERAGE_AMNT;
lastXmv[index] = Xamount * 133f;
lastYmv[index] = Yamount * 133f;
cursorPos.x -= avg(lastXmv);
cursorPos.y -= avg(lastYmv);
Vector2f maxsize = environment.getVRGUIManager().getCanvasSize();
if( cursorPos.x > maxsize.x ){
cursorPos.x = maxsize.x;
}
if( cursorPos.x < 0f ){
cursorPos.x = 0f;
}
if( cursorPos.y > maxsize.y ){
cursorPos.y = maxsize.y;
}
if( cursorPos.y < 0f ){
cursorPos.y = 0f;
}
}
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Get the actual cursor position.
* @return the actual cursor position.
*/
public Vector2f getCursorPosition() {
if (environment != null){
if (environment.getApplication() != null){
if( environment.isInVR() ) {
return cursorPos;
}
return environment.getApplication().getInputManager().getCursorPosition();
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Center the mouse on the display.
*/
public void centerMouse() {
if (environment != null){
if (environment.getApplication() != null){
// set mouse in center of the screen if newly added
Vector2f size = environment.getVRGUIManager().getCanvasSize();
MouseInput mi = environment.getApplication().getContext().getMouseInput();
AppSettings as = environment.getApplication().getContext().getSettings();
if( mi instanceof GlfwMouseInputVR ) ((GlfwMouseInputVR)mi).setCursorPosition((int)(as.getWidth() / 2f), (int)(as.getHeight() / 2f));
if( environment.isInVR() ) {
cursorPos.x = size.x / 2f;
cursorPos.y = size.y / 2f;
recentCenterCount = 2;
}
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Update the mouse manager. This method should not be called manually.
* The standard behavior for this method is to be called from the {@link VRViewManager#update(float) update method} of the attached {@link VRViewManager VR view manager}.
* @param tpf the time per frame.
*/
protected void update(float tpf) {
// if we are showing the cursor, add our picture as it
if( environment.getApplication().getInputManager().isCursorVisible() ) {
if( mouseImage.getParent() == null ) {
environment.getApplication().getGuiViewPort().attachScene(mouseImage);
centerMouse();
// the "real" mouse pointer should stay hidden
if (environment.getApplication().getContext() instanceof LwjglWindow){
GLFW.glfwSetInputMode(((LwjglWindow)environment.getApplication().getContext()).getWindowHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED);
}
}
// handle mouse movements, which may be in addition to (or exclusive from) tracked movement
MouseInput mi = environment.getApplication().getContext().getMouseInput();
if( mi instanceof GlfwMouseInputVR ) {
if( recentCenterCount <= 0 ) {
//Vector2f winratio = VRGuiManager.getCanvasToWindowRatio();
cursorPos.x += ((GlfwMouseInputVR)mi).getLastDeltaX();// * winratio.x;
cursorPos.y += ((GlfwMouseInputVR)mi).getLastDeltaY();// * winratio.y;
if( cursorPos.x < 0f ) cursorPos.x = 0f;
if( cursorPos.y < 0f ) cursorPos.y = 0f;
if( cursorPos.x > environment.getVRGUIManager().getCanvasSize().x ) cursorPos.x = environment.getVRGUIManager().getCanvasSize().x;
if( cursorPos.y > environment.getVRGUIManager().getCanvasSize().y ) cursorPos.y = environment.getVRGUIManager().getCanvasSize().y;
} else recentCenterCount--;
((GlfwMouseInputVR)mi).clearDeltas();
}
// ok, update the cursor graphic position
Vector2f currentPos = getCursorPosition();
mouseImage.setLocalTranslation(currentPos.x, currentPos.y - ySize, environment.getVRGUIManager().getGuiDistance() + 1f);
mouseImage.updateGeometricState();
} else if( mouseImage.getParent() != null ) {
Node n = mouseImage.getParent();
mouseImage.removeFromParent();
if (n != null){
n.updateGeometricState();
}
}
}
}

@ -2,7 +2,7 @@
* To change this template, choose Tools | Templates * To change this template, choose Tools | Templates
* and open the template in the editor. * and open the template in the editor.
*/ */
package jmevr.util; package com.jme3.util;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
@ -12,10 +12,7 @@ import com.jme3.system.jopenvr.HmdMatrix44_t;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/**
*
* @author reden
*/
public class VRUtil { public class VRUtil {
private static final long SLEEP_PRECISION = TimeUnit.MILLISECONDS.toNanos(4); private static final long SLEEP_PRECISION = TimeUnit.MILLISECONDS.toNanos(4);

@ -0,0 +1,156 @@
package com.jme3.util;
import com.jme3.app.VRAppState;
import com.jme3.app.VREnvironment;
import com.jme3.app.state.AppState;
import com.jme3.post.FilterPostProcessor;
import com.jme3.renderer.Camera;
import com.jme3.renderer.ViewPort;
import com.jme3.texture.Texture2D;
/**
* A VR view manager. This interface describes methods that enable to submit 3D views to the VR compositor.
* @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 interface VRViewManager {
/**
* The name of the left view.
*/
public final static String LEFT_VIEW_NAME = "Left View";
/**
* The name of the right view.
*/
public final static String RIGHT_VIEW_NAME = "Right View";
/**
* Get the {@link Camera camera} attached to the left eye.
* @return the {@link Camera camera} attached to the left eye.
* @see #getRightCamera()
*/
public Camera getLeftCamera();
/**
* Get the {@link Camera camera} attached to the right eye.
* @return the {@link Camera camera} attached to the right eye.
* @see #getLeftCamera()
*/
public Camera getRightCamera();
/**
* Get the {@link ViewPort viewport} attached to the left eye.
* @return the {@link ViewPort viewport} attached to the left eye.
* @see #getRightViewport()
*/
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()
*/
public ViewPort getRightViewport();
/**
* Get the texture attached to the left eye.
* @return the texture attached to the left eye.
* @see #getRightTexture()
*/
public Texture2D getLeftTexture();
/**
* Get the texture attached to the right eye.
* @return the texture attached to the right eye.
* @see #getLeftTexture()
*/
public Texture2D getRightTexture();
/**
* Get the depth texture attached to the left eye.
* @return the texture attached to the left eye.
* @see #getRightTexture()
*/
public Texture2D getLeftDepth();
/**
* Get the depth texture attached to the right eye.
* @return the texture attached to the right eye.
* @see #getLeftTexture()
*/
public Texture2D getRightDepth();
/**
* Get the {@link FilterPostProcessor filter post processor} attached to the left eye.
* @return the {@link FilterPostProcessor filter post processor} attached to the left eye.
* @see #getRightPostProcessor()
*/
public FilterPostProcessor getLeftPostProcessor();
/**
* Get the {@link FilterPostProcessor filter post processor} attached to the right eye.
* @return the {@link FilterPostProcessor filter post processor} attached to the right eye.
* @see #getLeftPostProcessor()
*/
public FilterPostProcessor getRightPostProcessor();
/**
* Get the resolution multiplier.
* @return the resolution multiplier.
* @see #setResolutionMultiplier(float)
*/
public float getResolutionMuliplier();
/**
* Set the resolution multiplier.
* @param resMult the resolution multiplier.
* @see #getResolutionMuliplier()
*/
public void setResolutionMultiplier(float resMult);
/**
* Get the height adjustment to apply to the cameras before rendering.
* @return the height adjustment to apply to the cameras before rendering.
* @see #setHeightAdjustment(float)
*/
public float getHeightAdjustment();
/**
* Set the height adjustment to apply to the cameras before rendering.
* @param amount the height adjustment to apply to the cameras before rendering.
* @see #getHeightAdjustment()
*/
public void setHeightAdjustment(float amount);
/**
* Get the {@link VREnvironment VR environment} to which the view manager is attached.
* @return the {@link VREnvironment VR environment} to which the view manager is attached.
*/
public VREnvironment getVREnvironment();
/**
* Initialize the VR view manager. This method should be called after the attachment of a {@link VREnvironment VR environment} to an application.
*/
public void initialize();
/**
* Update the VR view manager.
* This method is called by the attached {@link VRAppState app state} and should not be called manually.
* @param tpf the time per frame.
*/
public void update(float tpf);
/**
* Send the rendering result as textures to the two eyes.
* This method should be called after all the rendering operations
* (for example at the end of the {@link AppState#postRender() postRender()} method of the attached app state.)
*/
public void postRender();
/**
* Handles moving filters from the main view to each eye.
*/
public void moveScreenProcessingToEyes();
}

@ -0,0 +1,957 @@
package com.jme3.util;
import java.awt.GraphicsEnvironment;
import java.util.Iterator;
import java.util.logging.Logger;
import com.jme3.app.VREnvironment;
import com.jme3.input.vr.OSVR;
import com.jme3.input.vr.VRAPI;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.post.CartoonSSAO;
import com.jme3.post.Filter;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.FilterUtil;
import com.jme3.post.SceneProcessor;
import com.jme3.post.filters.FogFilter;
import com.jme3.post.filters.TranslucentBucketFilter;
import com.jme3.post.ssao.SSAOFilter;
import com.jme3.renderer.Camera;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.VertexBuffer;
import com.jme3.shadow.DirectionalLightShadowFilter;
import com.jme3.shadow.VRDirectionalLightShadowRenderer;
import com.jme3.system.jopenvr.DistortionCoordinates_t;
import com.jme3.system.jopenvr.JOpenVRLibrary;
import com.jme3.system.jopenvr.OpenVRUtil;
import com.jme3.system.jopenvr.Texture_t;
import com.jme3.system.jopenvr.VR_IVRSystem_FnTable;
import com.jme3.system.lwjgl.LwjglWindow;
import com.jme3.system.osvr.osvrrendermanageropengl.OSVR_RenderBufferOpenGL;
import com.jme3.system.osvr.osvrrendermanageropengl.OSVR_ViewportDescription;
import com.jme3.system.osvr.osvrrendermanageropengl.OsvrRenderManagerOpenGLLibrary;
import com.jme3.texture.FrameBuffer;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.ui.Picture;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
public class VRViewManagerOSVR extends AbstractVRViewManager{
private static final Logger logger = Logger.getLogger(VRViewManagerOpenVR.class.getName());
private Camera leftCamera;
private ViewPort leftViewport;
private FilterPostProcessor leftPostProcessor;
private Texture2D leftEyeTexture;
private Texture2D leftEyeDepth;
private Camera rightCamera;
private ViewPort rightViewport;
private FilterPostProcessor rightPostProcessor;
private Texture2D rightEyeTexture;
private Texture2D rightEyeDepth;
// OpenVR values
private Texture_t leftTextureType;
private Texture_t rightTextureType;
// OSVR values
OSVR_RenderBufferOpenGL.ByValue[] osvr_renderBuffer;
OSVR_ViewportDescription.ByValue osvr_viewDescFull;
OSVR_ViewportDescription.ByValue osvr_viewDescLeft;
OSVR_ViewportDescription.ByValue osvr_viewDescRight;
Pointer osvr_rmBufferState;
//private static boolean useCustomDistortion;
private float heightAdjustment;
private Texture2D dualEyeTex;
private final PointerByReference grabRBS = new PointerByReference();
private float resMult = 1f;
//final & temp values for camera calculations
private final Vector3f finalPosition = new Vector3f();
private final Quaternion finalRotation = new Quaternion();
private final Vector3f hmdPos = new Vector3f();
private final Quaternion hmdRot = new Quaternion();
/**
* Create a new VR view manager attached to the given {@link VREnvironment VR environment}.
* @param environment the {@link VREnvironment VR environment} to which this view manager is attached.
*/
public VRViewManagerOSVR(VREnvironment environment){
this.environment = environment;
}
/**
* Get the {@link Camera camera} attached to the left eye.
* @return the {@link Camera camera} attached to the left eye.
* @see #getRightCamera()
*/
public Camera getLeftCamera() {
return leftCamera;
}
/**
* Get the {@link Camera camera} attached to the right eye.
* @return the {@link Camera camera} attached to the right eye.
* @see #getLeftCamera()
*/
public Camera getRightCamera() {
return rightCamera;
}
/**
* Get the {@link ViewPort viewport} attached to the left eye.
* @return the {@link ViewPort viewport} attached to the left eye.
* @see #getRightViewport()
*/
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()
*/
public ViewPort getRightViewport() {
return rightViewport;
}
/**
* Get the identifier of the left eye texture.
* @return the identifier of the left eye texture.
* @see #getRightTexId()
* @see #getFullTexId()
*/
protected int getLeftTexId() {
return (int)leftEyeTexture.getImage().getId();
}
/**
* Get the identifier of the right eye texture.
* @return the identifier of the right eye texture.
* @see #getLeftTexId()
* @see #getFullTexId()
*/
protected int getRightTexId() {
return (int)rightEyeTexture.getImage().getId();
}
/**
* Get the identifier of the full (dual eye) texture.
* @return the identifier of the full (dual eye) texture.
* @see #getLeftTexId()
* @see #getRightTexId()
*/
private int getFullTexId() {
return (int)dualEyeTex.getImage().getId();
}
/**
* Get the height adjustment to apply to the cameras before rendering.
* @return the height adjustment to apply to the cameras before rendering.
* @see #setHeightAdjustment(float)
*/
public float getHeightAdjustment() {
return heightAdjustment;
}
/**
* Set the height adjustment to apply to the cameras before rendering.
* @param amount the height adjustment to apply to the cameras before rendering.
* @see #getHeightAdjustment()
*/
public void setHeightAdjustment(float amount) {
heightAdjustment = amount;
}
/**
* Get the resolution multiplier.
* @return the resolution multiplier.
* @see #setResolutionMultiplier(float)
*/
public float getResolutionMuliplier() {
return resMult;
}
/**
* Set the resolution multiplier.
* @param resMult the resolution multiplier.
* @see #getResolutionMuliplier()
*/
public void setResolutionMultiplier(float resMult) {
this.resMult = resMult;
}
/**
* Initialize the system binds of the textures.
*/
private void initTextureSubmitStructs() {
leftTextureType = new Texture_t();
rightTextureType = new Texture_t();
// must be OSVR
osvr_renderBuffer = new OSVR_RenderBufferOpenGL.ByValue[2];
osvr_renderBuffer[OSVR.EYE_LEFT] = new OSVR_RenderBufferOpenGL.ByValue();
osvr_renderBuffer[OSVR.EYE_RIGHT] = new OSVR_RenderBufferOpenGL.ByValue();
osvr_renderBuffer[OSVR.EYE_LEFT].setAutoSynch(false);
osvr_renderBuffer[OSVR.EYE_RIGHT].setAutoSynch(false);
osvr_viewDescFull = new OSVR_ViewportDescription.ByValue();
osvr_viewDescFull.setAutoSynch(false);
osvr_viewDescFull.left = osvr_viewDescFull.lower = 0.0;
osvr_viewDescFull.width = osvr_viewDescFull.height = 1.0;
osvr_viewDescLeft = new OSVR_ViewportDescription.ByValue();
osvr_viewDescLeft.setAutoSynch(false);
osvr_viewDescLeft.left = osvr_viewDescLeft.lower = 0.0;
osvr_viewDescLeft.width = 0.5;
osvr_viewDescLeft.height = 1.0;
osvr_viewDescRight = new OSVR_ViewportDescription.ByValue();
osvr_viewDescRight.setAutoSynch(false);
osvr_viewDescRight.left = 0.5;
osvr_viewDescRight.lower = 0.0;
osvr_viewDescRight.width = 0.5;
osvr_viewDescRight.height = 1.0;
osvr_viewDescRight.write();
osvr_viewDescLeft.write();
osvr_viewDescFull.write();
osvr_renderBuffer[OSVR.EYE_LEFT].depthStencilBufferName = -1;
osvr_renderBuffer[OSVR.EYE_LEFT].colorBufferName = -1;
osvr_renderBuffer[OSVR.EYE_RIGHT].depthStencilBufferName = -1;
osvr_renderBuffer[OSVR.EYE_RIGHT].colorBufferName = -1;
}
/**
* Register the OSVR OpenGL buffer.
* @param buf the OSVR OpenGL buffer.
*/
private void registerOSVRBuffer(OSVR_RenderBufferOpenGL.ByValue buf) {
if (environment != null){
OsvrRenderManagerOpenGLLibrary.osvrRenderManagerStartRegisterRenderBuffers(grabRBS);
OsvrRenderManagerOpenGLLibrary.osvrRenderManagerRegisterRenderBufferOpenGL(grabRBS.getValue(), buf);
OsvrRenderManagerOpenGLLibrary.osvrRenderManagerFinishRegisterRenderBuffers(((OSVR)environment.getVRHardware()).getCompositor(), grabRBS.getValue(), (byte)0);
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Send the textures to the two eyes.
*/
public void postRender() {
if (environment != null){
if( environment.isInVR() ) {
VRAPI api = environment.getVRHardware();
if( api.getCompositor() != null ) {
// using the compositor...
int errl = 0, errr = 0;
if( environment.isInstanceRendering() ) {
if( leftTextureType.handle == -1 || leftTextureType.handle != getFullTexId() ) {
leftTextureType.handle = getFullTexId();
if( leftTextureType.handle != -1 ) {
leftTextureType.write();
if( api instanceof OSVR ) {
osvr_renderBuffer[OSVR.EYE_LEFT].colorBufferName = leftTextureType.handle;
osvr_renderBuffer[OSVR.EYE_LEFT].depthStencilBufferName = dualEyeTex.getImage().getId();
osvr_renderBuffer[OSVR.EYE_LEFT].write();
registerOSVRBuffer(osvr_renderBuffer[OSVR.EYE_LEFT]);
}
}
} else {
if( api instanceof OSVR ) {
((OSVR)api).handleRenderBufferPresent(osvr_viewDescLeft, osvr_viewDescRight,
osvr_renderBuffer[OSVR.EYE_LEFT], osvr_renderBuffer[OSVR.EYE_LEFT]);
}
}
} else if( leftTextureType.handle == -1 || rightTextureType.handle == -1 ||
leftTextureType.handle != getLeftTexId() || rightTextureType.handle != getRightTexId() ) {
leftTextureType.handle = getLeftTexId();
if( leftTextureType.handle != -1 ) {
logger.fine("Writing Left texture to native memory at " + leftTextureType.getPointer());
leftTextureType.write();
if( api instanceof OSVR ) {
osvr_renderBuffer[OSVR.EYE_LEFT].colorBufferName = leftTextureType.handle;
if( leftEyeDepth != null ) osvr_renderBuffer[OSVR.EYE_LEFT].depthStencilBufferName = leftEyeDepth.getImage().getId();
osvr_renderBuffer[OSVR.EYE_LEFT].write();
registerOSVRBuffer(osvr_renderBuffer[OSVR.EYE_LEFT]);
}
}
rightTextureType.handle = getRightTexId();
if( rightTextureType.handle != -1 ) {
logger.fine("Writing Right texture to native memory at " + leftTextureType.getPointer());
rightTextureType.write();
if( api instanceof OSVR ) {
osvr_renderBuffer[OSVR.EYE_RIGHT].colorBufferName = rightTextureType.handle;
if( rightEyeDepth != null ) osvr_renderBuffer[OSVR.EYE_RIGHT].depthStencilBufferName = rightEyeDepth.getImage().getId();
osvr_renderBuffer[OSVR.EYE_RIGHT].write();
registerOSVRBuffer(osvr_renderBuffer[OSVR.EYE_RIGHT]);
}
}
} else {
if( api instanceof OSVR ) {
((OSVR)api).handleRenderBufferPresent(osvr_viewDescFull, osvr_viewDescFull,
osvr_renderBuffer[OSVR.EYE_LEFT], osvr_renderBuffer[OSVR.EYE_RIGHT]);
}
}
if( errl != 0 ){
logger.severe("Submit to left compositor error: " + OpenVRUtil.getEVRCompositorErrorString(errl)+" ("+Integer.toString(errl)+")");
logger.severe(" Texture color space: "+OpenVRUtil.getEColorSpaceString(leftTextureType.eColorSpace));
logger.severe(" Texture type: "+OpenVRUtil.getETextureTypeString(leftTextureType.eType));
logger.severe(" Texture handle: "+leftTextureType.handle);
logger.severe(" Left eye texture "+leftEyeTexture.getName()+" ("+leftEyeTexture.getImage().getId()+")");
logger.severe(" Type: "+leftEyeTexture.getType());
logger.severe(" Size: "+leftEyeTexture.getImage().getWidth()+"x"+leftEyeTexture.getImage().getHeight());
logger.severe(" Image depth: "+leftEyeTexture.getImage().getDepth());
logger.severe(" Image format: "+leftEyeTexture.getImage().getFormat());
logger.severe(" Image color space: "+leftEyeTexture.getImage().getColorSpace());
}
if( errr != 0 ){
logger.severe("Submit to right compositor error: " + OpenVRUtil.getEVRCompositorErrorString(errl)+" ("+Integer.toString(errl)+")");
logger.severe(" Texture color space: "+OpenVRUtil.getEColorSpaceString(rightTextureType.eColorSpace));
logger.severe(" Texture type: "+OpenVRUtil.getETextureTypeString(rightTextureType.eType));
logger.severe(" Texture handle: "+rightTextureType.handle);
logger.severe(" Right eye texture "+rightEyeTexture.getName()+" ("+rightEyeTexture.getImage().getId()+")");
logger.severe(" Type: "+rightEyeTexture.getType());
logger.severe(" Size: "+rightEyeTexture.getImage().getWidth()+"x"+rightEyeTexture.getImage().getHeight());
logger.severe(" Image depth: "+rightEyeTexture.getImage().getDepth());
logger.severe(" Image format: "+rightEyeTexture.getImage().getFormat());
logger.severe(" Image color space: "+rightEyeTexture.getImage().getColorSpace());
}
}
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Initialize the VR view manager.
*/
public void initialize() {
logger.config("Initializing VR view manager.");
if (environment != null){
initTextureSubmitStructs();
setupCamerasAndViews();
setupVRScene();
moveScreenProcessingToEyes();
if( environment.hasTraditionalGUIOverlay() ) {
environment.getVRMouseManager().initialize();
// update the pose to position the gui correctly on start
update(0f);
environment.getVRGUIManager().positionGui();
}
if (environment.getApplication() != null){
// if we are OSVR, our primary mirror window needs to be the same size as the render manager's output...
if( environment.getVRHardware() instanceof OSVR ) {
int origWidth = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getWidth();
int origHeight = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getHeight();
long window = ((LwjglWindow)environment.getApplication().getContext()).getWindowHandle();
Vector2f windowSize = new Vector2f();
((OSVR)environment.getVRHardware()).getRenderSize(windowSize);
windowSize.x = Math.max(windowSize.x * 2f, leftCamera.getWidth());
org.lwjgl.glfw.GLFW.glfwSetWindowSize(window, (int)windowSize.x, (int)windowSize.y);
environment.getApplication().getContext().getSettings().setResolution((int)windowSize.x, (int)windowSize.y);
if (environment.getApplication().getRenderManager() != null) {
environment.getApplication().getRenderManager().notifyReshape((int)windowSize.x, (int)windowSize.y);
}
org.lwjgl.glfw.GLFW.glfwSetWindowPos(window, origWidth - (int)windowSize.x, 32);
org.lwjgl.glfw.GLFW.glfwFocusWindow(window);
org.lwjgl.glfw.GLFW.glfwSetCursorPos(window, origWidth / 2.0, origHeight / 2.0);
logger.config("Initialized VR view manager [SUCCESS]");
} else {
throw new IllegalStateException("Underlying VR hardware should be "+OSVR.class.getSimpleName());
}
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Prepare the size of the given {@link Camera camera} to adapt it to the underlying rendering context.
* @param cam the {@link Camera camera} to prepare.
* @param xMult the camera width multiplier.
*/
private void prepareCameraSize(Camera cam, float xMult) {
if (environment != null){
if (environment.getApplication() != null){
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
Vector2f size = new Vector2f();
VRAPI vrhmd = environment.getVRHardware();
if( vrhmd == null ) {
size.x = 1280f;
size.y = 720f;
} else {
vrhmd.getRenderSize(size);
}
if( size.x < environment.getApplication().getContext().getSettings().getWidth() ) {
size.x = environment.getApplication().getContext().getSettings().getWidth();
}
if( size.y < environment.getApplication().getContext().getSettings().getHeight() ) {
size.y = environment.getApplication().getContext().getSettings().getHeight();
}
if( environment.isInstanceRendering() ){
size.x *= 2f;
}
// other adjustments
size.x *= xMult;
size.x *= resMult;
size.y *= resMult;
if( cam.getWidth() != size.x || cam.getHeight() != size.y ){
cam.resize((int)size.x, (int)size.y, false);
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Replaces rootNode as the main cameras scene with the distortion mesh
*/
private void setupVRScene(){
if (environment != null){
if (environment.getApplication() != null){
// no special scene to setup if we are doing instancing
if( environment.isInstanceRendering() ) {
// distortion has to be done with compositor here... we want only one pass on our end!
if( environment.getApplication().getContext().getSettings().isSwapBuffers() ) {
setupMirrorBuffers(environment.getCamera(), dualEyeTex, true);
}
return;
}
leftEyeTexture = (Texture2D) leftViewport.getOutputFrameBuffer().getColorBuffer().getTexture();
rightEyeTexture = (Texture2D)rightViewport.getOutputFrameBuffer().getColorBuffer().getTexture();
leftEyeDepth = (Texture2D) leftViewport.getOutputFrameBuffer().getDepthBuffer().getTexture();
rightEyeDepth = (Texture2D)rightViewport.getOutputFrameBuffer().getDepthBuffer().getTexture();
// main viewport is either going to be a distortion scene or nothing
// mirroring is handled by copying framebuffers
Iterator<Spatial> spatialIter = environment.getApplication().getViewPort().getScenes().iterator();
while(spatialIter.hasNext()){
environment.getApplication().getViewPort().detachScene(spatialIter.next());
}
spatialIter = environment.getApplication().getGuiViewPort().getScenes().iterator();
while(spatialIter.hasNext()){
environment.getApplication().getGuiViewPort().detachScene(spatialIter.next());
}
// only setup distortion scene if compositor isn't running (or using custom mesh distortion option)
if( environment.getVRHardware().getCompositor() == null ) {
Node distortionScene = new Node();
Material leftMat = new Material(environment.getApplication().getAssetManager(), "Common/MatDefs/VR/OpenVR.j3md");
leftMat.setTexture("Texture", leftEyeTexture);
Geometry leftEye = new Geometry("box", setupDistortionMesh(JOpenVRLibrary.EVREye.EVREye_Eye_Left, environment.getVRHardware()));
leftEye.setMaterial(leftMat);
distortionScene.attachChild(leftEye);
Material rightMat = new Material(environment.getApplication().getAssetManager(), "Common/MatDefs/VR/OpenVR.j3md");
rightMat.setTexture("Texture", rightEyeTexture);
Geometry rightEye = new Geometry("box", setupDistortionMesh(JOpenVRLibrary.EVREye.EVREye_Eye_Right, environment.getVRHardware()));
rightEye.setMaterial(rightMat);
distortionScene.attachChild(rightEye);
distortionScene.updateGeometricState();
environment.getApplication().getViewPort().attachScene(distortionScene);
//if( useCustomDistortion ) setupFinalFullTexture(app.getViewPort().getCamera());
}
if( environment.getApplication().getContext().getSettings().isSwapBuffers() ) {
setupMirrorBuffers(environment.getCamera(), leftEyeTexture, false);
}
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Update the VR view manager.
* This method is called by the attached {@link VRApplication VR application} and should not be called manually.
* @param tpf the time per frame.
*/
public void update(float tpf) {
if (environment != null){
// grab the observer
Object obs = environment.getObserver();
Quaternion objRot;
Vector3f objPos;
if( obs instanceof Camera ) {
objRot = ((Camera)obs).getRotation();
objPos = ((Camera)obs).getLocation();
} else {
objRot = ((Spatial)obs).getWorldRotation();
objPos = ((Spatial)obs).getWorldTranslation();
}
// grab the hardware handle
VRAPI dev = environment.getVRHardware();
if( dev != null ) {
// update the HMD's position & orientation
dev.updatePose();
dev.getPositionAndOrientation(hmdPos, hmdRot);
if( obs != null ) {
// update hmdPos based on obs rotation
finalRotation.set(objRot);
finalRotation.mult(hmdPos, hmdPos);
finalRotation.multLocal(hmdRot);
}
finalizeCamera(dev.getHMDVectorPoseLeftEye(), objPos, leftCamera);
finalizeCamera(dev.getHMDVectorPoseRightEye(), objPos, rightCamera);
} else {
leftCamera.setFrame(objPos, objRot);
rightCamera.setFrame(objPos, objRot);
}
if( environment.hasTraditionalGUIOverlay() ) {
// update the mouse?
environment.getVRMouseManager().update(tpf);
// update GUI position?
if( environment.getVRGUIManager().wantsReposition || environment.getVRGUIManager().getPositioningMode() != VRGUIPositioningMode.MANUAL ) {
environment.getVRGUIManager().positionGuiNow(tpf);
environment.getVRGUIManager().updateGuiQuadGeometricState();
}
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Place the camera within the scene.
* @param eyePos the eye position.
* @param obsPosition the observer position.
* @param cam the camera to place.
*/
private void finalizeCamera(Vector3f eyePos, Vector3f obsPosition, Camera cam) {
finalRotation.mult(eyePos, finalPosition);
finalPosition.addLocal(hmdPos);
if( obsPosition != null ){
finalPosition.addLocal(obsPosition);
}
finalPosition.y += heightAdjustment;
cam.setFrame(finalPosition, finalRotation);
}
/**
* Handles moving filters from the main view to each eye
*/
public void moveScreenProcessingToEyes() {
if( rightViewport == null ){
return;
}
if (environment != null){
if (environment.getApplication() != null){
syncScreenProcessing(environment.getApplication().getViewPort());
environment.getApplication().getViewPort().clearProcessors();
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Sets the two views to use the list of {@link SceneProcessor processors}.
* @param sourceViewport the {@link ViewPort viewport} that contains the processors to use.
*/
public void syncScreenProcessing(ViewPort sourceViewport) {
if( rightViewport == null ){
return;
}
if (environment != null){
if (environment.getApplication() != null){
// setup post processing filters
if( rightPostProcessor == null ) {
rightPostProcessor = new FilterPostProcessor(environment.getApplication().getAssetManager());
leftPostProcessor = new FilterPostProcessor(environment.getApplication().getAssetManager());
}
// clear out all filters & processors, to start from scratch
rightPostProcessor.removeAllFilters();
leftPostProcessor.removeAllFilters();
leftViewport.clearProcessors();
rightViewport.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
leftViewport.addProcessor(leftPostProcessor);
rightViewport.addProcessor(rightPostProcessor);
// 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()) {
if (sceneProcessor instanceof FilterPostProcessor) {
for(Filter f : ((FilterPostProcessor)sceneProcessor).getFilterList() ) {
if( f instanceof TranslucentBucketFilter ) {
// just remove this filter, we will add it at the end manually
((FilterPostProcessor)sceneProcessor).removeFilter(f);
} else {
leftPostProcessor.addFilter(f);
// clone to the right
Filter f2;
if(f instanceof FogFilter){
f2 = FilterUtil.cloneFogFilter((FogFilter)f);
} else if (f instanceof CartoonSSAO ) {
f2 = new CartoonSSAO((CartoonSSAO)f);
} else if (f instanceof SSAOFilter){
f2 = FilterUtil.cloneSSAOFilter((SSAOFilter)f);
} else if (f instanceof DirectionalLightShadowFilter){
f2 = FilterUtil.cloneDirectionalLightShadowFilter(environment.getApplication().getAssetManager(), (DirectionalLightShadowFilter)f);
} else {
f2 = f; // dof, bloom, lightscattering etc.
}
rightPostProcessor.addFilter(f2);
}
}
} else if (sceneProcessor instanceof VRDirectionalLightShadowRenderer) {
// shadow processing
// TODO: make right shadow processor use same left shadow maps for performance
VRDirectionalLightShadowRenderer dlsr = (VRDirectionalLightShadowRenderer) sceneProcessor;
VRDirectionalLightShadowRenderer dlsrRight = dlsr.clone();
dlsrRight.setLight(dlsr.getLight());
rightViewport.getProcessors().add(0, dlsrRight);
leftViewport.getProcessors().add(0, sceneProcessor);
}
}
// make sure each has a translucent filter renderer
leftPostProcessor.addFilter(new TranslucentBucketFilter());
rightPostProcessor.addFilter(new TranslucentBucketFilter());
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
private void setupCamerasAndViews() {
if (environment != null){
if (environment.getApplication() != null){
// get desired frustrum from original camera
Camera origCam = environment.getCamera();
float fFar = origCam.getFrustumFar();
float fNear = origCam.getFrustumNear();
// if we are using OSVR get the eye info here
if( environment.getVRHardware() instanceof OSVR ) {
((OSVR)environment.getVRHardware()).getEyeInfo();
}
// restore frustrum on distortion scene cam, if needed
if( environment.isInstanceRendering() ) {
leftCamera = origCam;
} else if( environment.compositorAllowed() == false ) {
origCam.setFrustumFar(100f);
origCam.setFrustumNear(1f);
leftCamera = origCam.clone();
prepareCameraSize(origCam, 2f);
} else {
leftCamera = origCam.clone();
}
leftCamera.setFrustumPerspective(environment.getDefaultFOV(), environment.getDefaultAspect(), fNear, fFar);
prepareCameraSize(leftCamera, 1f);
if( environment.getVRHardware() != null ) leftCamera.setProjectionMatrix(environment.getVRHardware().getHMDMatrixProjectionLeftEye(leftCamera));
//org.lwjgl.opengl.GL11.glEnable(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_SRGB);
if( !environment.isInstanceRendering()) {
leftViewport = setupViewBuffers(leftCamera, LEFT_VIEW_NAME);
rightCamera = leftCamera.clone();
if( environment.getVRHardware() != null ){
rightCamera.setProjectionMatrix(environment.getVRHardware().getHMDMatrixProjectionRightEye(rightCamera));
}
rightViewport = setupViewBuffers(rightCamera, RIGHT_VIEW_NAME);
} else {
System.err.println("[VRViewManager] THIS CODE NEED CHANGES !!!");
leftViewport = environment.getApplication().getViewPort();
//leftViewport.attachScene(app.getRootNode());
rightCamera = leftCamera.clone();
if( environment.getVRHardware() != null ){
rightCamera.setProjectionMatrix(environment.getVRHardware().getHMDMatrixProjectionRightEye(rightCamera));
}
org.lwjgl.opengl.GL11.glEnable(org.lwjgl.opengl.GL30.GL_CLIP_DISTANCE0);
//FIXME: [jme-vr] Fix with JMonkey next release
//RenderManager._VRInstancing_RightCamProjection = camRight.getViewProjectionMatrix();
setupFinalFullTexture(environment.getApplication().getViewPort().getCamera());
}
// setup gui
environment.getVRGUIManager().setupGui(leftCamera, rightCamera, leftViewport, rightViewport);
if( environment.getVRHardware() != null ) {
// call these to cache the results internally
environment.getVRHardware().getHMDMatrixPoseLeftEye();
environment.getVRHardware().getHMDMatrixPoseRightEye();
}
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
private ViewPort setupMirrorBuffers(Camera cam, Texture tex, boolean expand) {
if (environment != null){
if (environment.getApplication() != null){
Camera clonecam = cam.clone();
ViewPort viewPort = environment.getApplication().getRenderManager().createPostView("MirrorView", clonecam);
clonecam.setParallelProjection(true);
viewPort.setClearFlags(true, true, true);
viewPort.setBackgroundColor(ColorRGBA.Black);
Picture pic = new Picture("fullscene");
pic.setLocalTranslation(-0.75f, -0.5f, 0f);
if( expand ) {
pic.setLocalScale(3f, 1f, 1f);
} else {
pic.setLocalScale(1.5f, 1f, 1f);
}
pic.setQueueBucket(Bucket.Opaque);
pic.setTexture(environment.getApplication().getAssetManager(), (Texture2D)tex, false);
viewPort.attachScene(pic);
viewPort.setOutputFrameBuffer(null);
pic.updateGeometricState();
return viewPort;
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
private void setupFinalFullTexture(Camera cam) {
if (environment != null){
if (environment.getApplication() != null){
// create offscreen framebuffer
FrameBuffer out = new FrameBuffer(cam.getWidth(), cam.getHeight(), 1);
//offBuffer.setSrgb(true);
//setup framebuffer's texture
dualEyeTex = new Texture2D(cam.getWidth(), cam.getHeight(), Image.Format.RGBA8);
dualEyeTex.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
dualEyeTex.setMagFilter(Texture.MagFilter.Bilinear);
logger.config("Dual eye texture "+dualEyeTex.getName()+" ("+dualEyeTex.getImage().getId()+")");
logger.config(" Type: "+dualEyeTex.getType());
logger.config(" Size: "+dualEyeTex.getImage().getWidth()+"x"+dualEyeTex.getImage().getHeight());
logger.config(" Image depth: "+dualEyeTex.getImage().getDepth());
logger.config(" Image format: "+dualEyeTex.getImage().getFormat());
logger.config(" Image color space: "+dualEyeTex.getImage().getColorSpace());
//setup framebuffer to use texture
out.setDepthBuffer(Image.Format.Depth);
out.setColorTexture(dualEyeTex);
ViewPort viewPort = environment.getApplication().getViewPort();
viewPort.setClearFlags(true, true, true);
viewPort.setBackgroundColor(ColorRGBA.Black);
viewPort.setOutputFrameBuffer(out);
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
private ViewPort setupViewBuffers(Camera cam, String viewName){
if (environment != null){
if (environment.getApplication() != null){
// create offscreen framebuffer
FrameBuffer offBufferLeft = new FrameBuffer(cam.getWidth(), cam.getHeight(), 1);
//offBufferLeft.setSrgb(true);
//setup framebuffer's texture
Texture2D offTex = new Texture2D(cam.getWidth(), cam.getHeight(), Image.Format.RGBA8);
offTex.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
offTex.setMagFilter(Texture.MagFilter.Bilinear);
//setup framebuffer to use texture
offBufferLeft.setDepthBuffer(Image.Format.Depth);
offBufferLeft.setColorTexture(offTex);
ViewPort viewPort = environment.getApplication().getRenderManager().createPreView(viewName, cam);
viewPort.setClearFlags(true, true, true);
viewPort.setBackgroundColor(ColorRGBA.Black);
Iterator<Spatial> spatialIter = environment.getApplication().getViewPort().getScenes().iterator();
while(spatialIter.hasNext()){
viewPort.attachScene(spatialIter.next());
}
//set viewport to render to offscreen framebuffer
viewPort.setOutputFrameBuffer(offBufferLeft);
return viewPort;
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Setup a distortion mesh for the stereo view.
* @param eye the eye to apply.
* @param api the underlying VR api
* @return the distorted mesh.
*/
public static Mesh setupDistortionMesh(int eye, VRAPI api) {
Mesh distortionMesh = new Mesh();
float m_iLensGridSegmentCountH = 43, m_iLensGridSegmentCountV = 43;
float w = 1f / (m_iLensGridSegmentCountH - 1f);
float h = 1f / (m_iLensGridSegmentCountV - 1f);
float u, v;
float verts[] = new float[(int) (m_iLensGridSegmentCountV * m_iLensGridSegmentCountH) * 3];
float texcoordR[] = new float[(int) (m_iLensGridSegmentCountV * m_iLensGridSegmentCountH) * 2];
float texcoordG[] = new float[(int) (m_iLensGridSegmentCountV * m_iLensGridSegmentCountH) * 2];
float texcoordB[] = new float[(int) (m_iLensGridSegmentCountV * m_iLensGridSegmentCountH) * 2];
int vertPos = 0, coordPos = 0;
float Xoffset = eye == JOpenVRLibrary.EVREye.EVREye_Eye_Left ? -1f : 0;
for (int y = 0; y < m_iLensGridSegmentCountV; y++) {
for (int x = 0; x < m_iLensGridSegmentCountH; x++) {
u = x * w;
v = 1 - y * h;
verts[vertPos] = Xoffset + u; // x
verts[vertPos + 1] = -1 + 2 * y * h; // y
verts[vertPos + 2] = 0f; // z
vertPos += 3;
DistortionCoordinates_t dc0 = new DistortionCoordinates_t();
if( api.getVRSystem() == null ) {
// default to no distortion
texcoordR[coordPos] = u;
texcoordR[coordPos + 1] = 1 - v;
texcoordG[coordPos] = u;
texcoordG[coordPos + 1] = 1 - v;
texcoordB[coordPos] = u;
texcoordB[coordPos + 1] = 1 - v;
} else {
((VR_IVRSystem_FnTable)api.getVRSystem()).ComputeDistortion.apply(eye, u, v, dc0);
texcoordR[coordPos] = dc0.rfRed[0];
texcoordR[coordPos + 1] = 1 - dc0.rfRed[1];
texcoordG[coordPos] = dc0.rfGreen[0];
texcoordG[coordPos + 1] = 1 - dc0.rfGreen[1];
texcoordB[coordPos] = dc0.rfBlue[0];
texcoordB[coordPos + 1] = 1 - dc0.rfBlue[1];
}
coordPos += 2;
}
}
// have UV coordinates & positions, now to setup indices
int[] indices = new int[(int) ((m_iLensGridSegmentCountV - 1) * (m_iLensGridSegmentCountH - 1)) * 6];
int indexPos = 0;
int a, b, c, d;
int offset = 0;
for (int y = 0; y < m_iLensGridSegmentCountV - 1; y++) {
for (int x = 0; x < m_iLensGridSegmentCountH - 1; x++) {
a = (int) (m_iLensGridSegmentCountH * y + x + offset);
b = (int) (m_iLensGridSegmentCountH * y + x + 1 + offset);
c = (int) ((y + 1) * m_iLensGridSegmentCountH + x + 1 + offset);
d = (int) ((y + 1) * m_iLensGridSegmentCountH + x + offset);
indices[indexPos] = a;
indices[indexPos + 1] = b;
indices[indexPos + 2] = c;
indices[indexPos + 3] = a;
indices[indexPos + 4] = c;
indices[indexPos + 5] = d;
indexPos += 6;
}
}
// OK, create the mesh
distortionMesh.setBuffer(VertexBuffer.Type.Position, 3, verts);
distortionMesh.setBuffer(VertexBuffer.Type.Index, 1, indices);
distortionMesh.setBuffer(VertexBuffer.Type.TexCoord, 2, texcoordR);
distortionMesh.setBuffer(VertexBuffer.Type.TexCoord2, 2, texcoordG);
distortionMesh.setBuffer(VertexBuffer.Type.TexCoord3, 2, texcoordB);
distortionMesh.setStatic();
return distortionMesh;
}
}

@ -0,0 +1,732 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.jme3.util;
import com.jme3.app.VREnvironment;
import com.jme3.input.vr.OpenVR;
import com.jme3.input.vr.VRAPI;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.VertexBuffer;
import com.jme3.system.jopenvr.DistortionCoordinates_t;
import com.jme3.system.jopenvr.JOpenVRLibrary;
import com.jme3.system.jopenvr.OpenVRUtil;
import com.jme3.system.jopenvr.Texture_t;
import com.jme3.system.jopenvr.VRTextureBounds_t;
import com.jme3.system.jopenvr.VR_IVRSystem_FnTable;
import com.jme3.texture.FrameBuffer;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.ui.Picture;
import java.util.Iterator;
import java.util.logging.Logger;
/**
* A VR view manager based on OpenVR. This class enable to submit 3D views to the VR compositor.
* @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 VRViewManagerOpenVR extends AbstractVRViewManager {
private static final Logger logger = Logger.getLogger(VRViewManagerOpenVR.class.getName());
// OpenVR values
private VRTextureBounds_t leftTextureBounds;
private Texture_t leftTextureType;
private VRTextureBounds_t rightTextureBounds;
private Texture_t rightTextureType;
private Texture2D dualEyeTex;
//final & temp values for camera calculations
private final Vector3f finalPosition = new Vector3f();
private final Quaternion finalRotation = new Quaternion();
private final Vector3f hmdPos = new Vector3f();
private final Quaternion hmdRot = new Quaternion();
/**
* Create a new VR view manager attached to the given {@link VREnvironment VR environment}.
* @param environment the {@link VREnvironment VR environment} to which this view manager is attached.
*/
public VRViewManagerOpenVR(VREnvironment environment){
this.environment = environment;
}
/**
* Get the identifier of the left eye texture.
* @return the identifier of the left eye texture.
* @see #getRightTexId()
* @see #getFullTexId()
*/
protected int getLeftTexId() {
return (int)getLeftTexture().getImage().getId();
}
/**
* Get the identifier of the right eye texture.
* @return the identifier of the right eye texture.
* @see #getLeftTexId()
* @see #getFullTexId()
*/
protected int getRightTexId() {
return (int)getRightTexture().getImage().getId();
}
/**
* Get the identifier of the full (dual eye) texture.
* @return the identifier of the full (dual eye) texture.
* @see #getLeftTexId()
* @see #getRightTexId()
*/
private int getFullTexId() {
return (int)dualEyeTex.getImage().getId();
}
/**
* Initialize the system binds of the textures.
*/
private void initTextureSubmitStructs() {
leftTextureType = new Texture_t();
rightTextureType = new Texture_t();
if (environment != null){
if( environment.getVRHardware() instanceof OpenVR ) {
leftTextureBounds = new VRTextureBounds_t();
rightTextureBounds = new VRTextureBounds_t();
// left eye
leftTextureBounds.uMax = 0.5f;
leftTextureBounds.uMin = 0f;
leftTextureBounds.vMax = 1f;
leftTextureBounds.vMin = 0f;
leftTextureBounds.setAutoSynch(false);
leftTextureBounds.setAutoRead(false);
leftTextureBounds.setAutoWrite(false);
leftTextureBounds.write();
// right eye
rightTextureBounds.uMax = 1f;
rightTextureBounds.uMin = 0.5f;
rightTextureBounds.vMax = 1f;
rightTextureBounds.vMin = 0f;
rightTextureBounds.setAutoSynch(false);
rightTextureBounds.setAutoRead(false);
rightTextureBounds.setAutoWrite(false);
rightTextureBounds.write();
// texture type
leftTextureType.eColorSpace = JOpenVRLibrary.EColorSpace.EColorSpace_ColorSpace_Gamma;
leftTextureType.eType = JOpenVRLibrary.ETextureType.ETextureType_TextureType_OpenGL;
leftTextureType.setAutoSynch(false);
leftTextureType.setAutoRead(false);
leftTextureType.setAutoWrite(false);
leftTextureType.handle = -1;
rightTextureType.eColorSpace = JOpenVRLibrary.EColorSpace.EColorSpace_ColorSpace_Gamma;
rightTextureType.eType = JOpenVRLibrary.ETextureType.ETextureType_TextureType_OpenGL;
rightTextureType.setAutoSynch(false);
rightTextureType.setAutoRead(false);
rightTextureType.setAutoWrite(false);
rightTextureType.handle = -1;
logger.config("Init eyes native texture binds");
logger.config(" Left eye texture");
logger.config(" address: "+leftTextureType.getPointer());
logger.config(" size: "+leftTextureType.size()+" bytes");
logger.config(" color space: "+OpenVRUtil.getEColorSpaceString(leftTextureType.eColorSpace));
logger.config(" type: "+OpenVRUtil.getETextureTypeString(leftTextureType.eType));
logger.config(" auto read: "+leftTextureType.getAutoRead());
logger.config(" auto write: "+leftTextureType.getAutoWrite());
logger.config(" handle address: "+leftTextureType.handle);
logger.config(" handle value: "+leftTextureType.handle);
logger.config("");
logger.config(" Right eye texture");
logger.config(" address: "+rightTextureType.getPointer());
logger.config(" size: "+rightTextureType.size()+" bytes");
logger.config(" color space: "+OpenVRUtil.getEColorSpaceString(rightTextureType.eColorSpace));
logger.config(" type: "+OpenVRUtil.getETextureTypeString(rightTextureType.eType));
logger.config(" auto read: "+rightTextureType.getAutoRead());
logger.config(" auto write: "+rightTextureType.getAutoWrite());
logger.config(" handle address: "+rightTextureType.handle);
logger.config(" handle value: "+rightTextureType.handle);
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
@Override
public void postRender() {
if (environment != null){
if( environment.isInVR() ) {
VRAPI api = environment.getVRHardware();
if( api.getCompositor() != null ) {
// using the compositor...
int errl = 0, errr = 0;
if( environment.isInstanceRendering() ) {
if( leftTextureType.handle == -1 || leftTextureType.handle != getFullTexId() ) {
leftTextureType.handle = getFullTexId();
if( leftTextureType.handle != -1 ) {
leftTextureType.write();
}
} else {
if( api instanceof OpenVR ) {
int submitFlag = JOpenVRLibrary.EVRSubmitFlags.EVRSubmitFlags_Submit_Default;
errr = ((OpenVR)api).getCompositor().Submit.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Right, leftTextureType, rightTextureBounds, submitFlag);
errl = ((OpenVR)api).getCompositor().Submit.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Left, leftTextureType, leftTextureBounds, submitFlag);
}
}
} else if( leftTextureType.handle == -1 || rightTextureType.handle == -1 ||
leftTextureType.handle != getLeftTexId() || rightTextureType.handle != getRightTexId() ) {
leftTextureType.handle = getLeftTexId();
if( leftTextureType.handle != -1 ) {
logger.fine("Writing Left texture to native memory at " + leftTextureType.getPointer());
leftTextureType.write();
}
rightTextureType.handle = getRightTexId();
if( rightTextureType.handle != -1 ) {
logger.fine("Writing Right texture to native memory at " + leftTextureType.getPointer());
rightTextureType.write();
}
} else {
if( api instanceof OpenVR ) {
errl = ((OpenVR)api).getCompositor().Submit.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Left, leftTextureType, null,
JOpenVRLibrary.EVRSubmitFlags.EVRSubmitFlags_Submit_Default);
errr = ((OpenVR)api).getCompositor().Submit.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Right, rightTextureType, null,
JOpenVRLibrary.EVRSubmitFlags.EVRSubmitFlags_Submit_Default);
} else {
}
}
if( errl != 0 ){
logger.severe("Submit to left compositor error: " + OpenVRUtil.getEVRCompositorErrorString(errl)+" ("+Integer.toString(errl)+")");
logger.severe(" Texture color space: "+OpenVRUtil.getEColorSpaceString(leftTextureType.eColorSpace));
logger.severe(" Texture type: "+OpenVRUtil.getETextureTypeString(leftTextureType.eType));
logger.severe(" Texture handle: "+leftTextureType.handle);
logger.severe(" Left eye texture "+leftEyeTexture.getName()+" ("+leftEyeTexture.getImage().getId()+")");
logger.severe(" Type: "+leftEyeTexture.getType());
logger.severe(" Size: "+leftEyeTexture.getImage().getWidth()+"x"+leftEyeTexture.getImage().getHeight());
logger.severe(" Image depth: "+leftEyeTexture.getImage().getDepth());
logger.severe(" Image format: "+leftEyeTexture.getImage().getFormat());
logger.severe(" Image color space: "+leftEyeTexture.getImage().getColorSpace());
}
if( errr != 0 ){
logger.severe("Submit to right compositor error: " + OpenVRUtil.getEVRCompositorErrorString(errl)+" ("+Integer.toString(errl)+")");
logger.severe(" Texture color space: "+OpenVRUtil.getEColorSpaceString(rightTextureType.eColorSpace));
logger.severe(" Texture type: "+OpenVRUtil.getETextureTypeString(rightTextureType.eType));
logger.severe(" Texture handle: "+rightTextureType.handle);
logger.severe(" Right eye texture "+rightEyeTexture.getName()+" ("+rightEyeTexture.getImage().getId()+")");
logger.severe(" Type: "+rightEyeTexture.getType());
logger.severe(" Size: "+rightEyeTexture.getImage().getWidth()+"x"+rightEyeTexture.getImage().getHeight());
logger.severe(" Image depth: "+rightEyeTexture.getImage().getDepth());
logger.severe(" Image format: "+rightEyeTexture.getImage().getFormat());
logger.severe(" Image color space: "+rightEyeTexture.getImage().getColorSpace());
}
}
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
@Override
public void initialize() {
logger.config("Initializing VR view manager.");
if (environment != null){
initTextureSubmitStructs();
setupCamerasAndViews();
setupVRScene();
moveScreenProcessingToEyes();
if( environment.hasTraditionalGUIOverlay() ) {
environment.getVRMouseManager().initialize();
// update the pose to position the gui correctly on start
update(0f);
environment.getVRGUIManager().positionGui();
}
logger.config("Initialized VR view manager [SUCCESS]");
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Prepare the size of the given {@link Camera camera} to adapt it to the underlying rendering context.
* @param cam the {@link Camera camera} to prepare.
* @param xMult the camera width multiplier.
*/
private void prepareCameraSize(Camera cam, float xMult) {
if (environment != null){
if (environment.getApplication() != null){
Vector2f size = new Vector2f();
VRAPI vrhmd = environment.getVRHardware();
if( vrhmd == null ) {
size.x = 1280f;
size.y = 720f;
} else {
vrhmd.getRenderSize(size);
}
if( size.x < environment.getApplication().getContext().getSettings().getWidth() ) {
size.x = environment.getApplication().getContext().getSettings().getWidth();
}
if( size.y < environment.getApplication().getContext().getSettings().getHeight() ) {
size.y = environment.getApplication().getContext().getSettings().getHeight();
}
if( environment.isInstanceRendering() ){
size.x *= 2f;
}
// other adjustments
size.x *= xMult;
size.x *= getResolutionMuliplier();
size.y *= getResolutionMuliplier();
if( cam.getWidth() != size.x || cam.getHeight() != size.y ){
cam.resize((int)size.x, (int)size.y, false);
}
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Replaces rootNode as the main cameras scene with the distortion mesh
*/
private void setupVRScene(){
if (environment != null){
if (environment.getApplication() != null){
// no special scene to setup if we are doing instancing
if( environment.isInstanceRendering() ) {
// distortion has to be done with compositor here... we want only one pass on our end!
if( environment.getApplication().getContext().getSettings().isSwapBuffers() ) {
setupMirrorBuffers(environment.getCamera(), dualEyeTex, true);
}
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();
// main viewport is either going to be a distortion scene or nothing
// mirroring is handled by copying framebuffers
Iterator<Spatial> spatialIter = environment.getApplication().getViewPort().getScenes().iterator();
while(spatialIter.hasNext()){
environment.getApplication().getViewPort().detachScene(spatialIter.next());
}
spatialIter = environment.getApplication().getGuiViewPort().getScenes().iterator();
while(spatialIter.hasNext()){
environment.getApplication().getGuiViewPort().detachScene(spatialIter.next());
}
// only setup distortion scene if compositor isn't running (or using custom mesh distortion option)
if( environment.getVRHardware().getCompositor() == null ) {
Node distortionScene = new Node();
Material leftMat = new Material(environment.getApplication().getAssetManager(), "Common/MatDefs/VR/OpenVR.j3md");
leftMat.setTexture("Texture", leftEyeTexture);
Geometry leftEye = new Geometry("box", setupDistortionMesh(JOpenVRLibrary.EVREye.EVREye_Eye_Left, environment.getVRHardware()));
leftEye.setMaterial(leftMat);
distortionScene.attachChild(leftEye);
Material rightMat = new Material(environment.getApplication().getAssetManager(), "Common/MatDefs/VR/OpenVR.j3md");
rightMat.setTexture("Texture", rightEyeTexture);
Geometry rightEye = new Geometry("box", setupDistortionMesh(JOpenVRLibrary.EVREye.EVREye_Eye_Right, environment.getVRHardware()));
rightEye.setMaterial(rightMat);
distortionScene.attachChild(rightEye);
distortionScene.updateGeometricState();
environment.getApplication().getViewPort().attachScene(distortionScene);
//if( useCustomDistortion ) setupFinalFullTexture(app.getViewPort().getCamera());
}
if( environment.getApplication().getContext().getSettings().isSwapBuffers() ) {
setupMirrorBuffers(environment.getCamera(), leftEyeTexture, false);
}
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
@Override
public void update(float tpf) {
if (environment != null){
// grab the observer
Object obs = environment.getObserver();
Quaternion objRot;
Vector3f objPos;
if( obs instanceof Camera ) {
objRot = ((Camera)obs).getRotation();
objPos = ((Camera)obs).getLocation();
} else {
objRot = ((Spatial)obs).getWorldRotation();
objPos = ((Spatial)obs).getWorldTranslation();
}
// grab the hardware handle
VRAPI dev = environment.getVRHardware();
if( dev != null ) {
// update the HMD's position & orientation
dev.updatePose();
dev.getPositionAndOrientation(hmdPos, hmdRot);
if( obs != null ) {
// update hmdPos based on obs rotation
finalRotation.set(objRot);
finalRotation.mult(hmdPos, hmdPos);
finalRotation.multLocal(hmdRot);
}
finalizeCamera(dev.getHMDVectorPoseLeftEye(), objPos, getLeftCamera());
finalizeCamera(dev.getHMDVectorPoseRightEye(), objPos, getRightCamera());
} else {
getLeftCamera().setFrame(objPos, objRot);
getRightCamera().setFrame(objPos, objRot);
}
if( environment.hasTraditionalGUIOverlay() ) {
// update the mouse?
environment.getVRMouseManager().update(tpf);
// update GUI position?
if( environment.getVRGUIManager().wantsReposition || environment.getVRGUIManager().getPositioningMode() != VRGUIPositioningMode.MANUAL ) {
environment.getVRGUIManager().positionGuiNow(tpf);
environment.getVRGUIManager().updateGuiQuadGeometricState();
}
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Place the camera within the scene.
* @param eyePos the eye position.
* @param obsPosition the observer position.
* @param cam the camera to place.
*/
private void finalizeCamera(Vector3f eyePos, Vector3f obsPosition, Camera cam) {
finalRotation.mult(eyePos, finalPosition);
finalPosition.addLocal(hmdPos);
if( obsPosition != null ) finalPosition.addLocal(obsPosition);
finalPosition.y += getHeightAdjustment();
cam.setFrame(finalPosition, finalRotation);
}
private void setupCamerasAndViews() {
if (environment != null){
// get desired frustrum from original camera
Camera origCam = environment.getCamera();
float fFar = origCam.getFrustumFar();
float fNear = origCam.getFrustumNear();
// restore frustrum on distortion scene cam, if needed
if( environment.isInstanceRendering() ) {
leftCamera = origCam;
} else if( environment.compositorAllowed() == false ) {
origCam.setFrustumFar(100f);
origCam.setFrustumNear(1f);
leftCamera = origCam.clone();
prepareCameraSize(origCam, 2f);
} else {
leftCamera = origCam.clone();
}
getLeftCamera().setFrustumPerspective(environment.getDefaultFOV(), environment.getDefaultAspect(), fNear, fFar);
prepareCameraSize(getLeftCamera(), 1f);
if( environment.getVRHardware() != null ) {
getLeftCamera().setProjectionMatrix(environment.getVRHardware().getHMDMatrixProjectionLeftEye(getLeftCamera()));
}
//org.lwjgl.opengl.GL11.glEnable(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_SRGB);
if( !environment.isInstanceRendering()) {
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);
} else {
if (environment.getApplication() != null){
logger.severe("THIS CODE NEED CHANGES !!!");
leftViewport = environment.getApplication().getViewPort();
//leftViewport.attachScene(app.getRootNode());
rightCamera = getLeftCamera().clone();
if( environment.getVRHardware() != null ){
getRightCamera().setProjectionMatrix(environment.getVRHardware().getHMDMatrixProjectionRightEye(getRightCamera()));
}
org.lwjgl.opengl.GL11.glEnable(org.lwjgl.opengl.GL30.GL_CLIP_DISTANCE0);
//FIXME: [jme-vr] Fix with JMonkey next release
//RenderManager._VRInstancing_RightCamProjection = camRight.getViewProjectionMatrix();
setupFinalFullTexture(environment.getApplication().getViewPort().getCamera());
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
}
// setup gui
environment.getVRGUIManager().setupGui(getLeftCamera(), getRightCamera(), getLeftViewport(), getRightViewport());
if( environment.getVRHardware() != null ) {
// call these to cache the results internally
environment.getVRHardware().getHMDMatrixPoseLeftEye();
environment.getVRHardware().getHMDMatrixPoseRightEye();
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
private ViewPort setupMirrorBuffers(Camera cam, Texture tex, boolean expand) {
if (environment != null){
if (environment.getApplication() != null){
Camera clonecam = cam.clone();
ViewPort viewPort = environment.getApplication().getRenderManager().createPostView("MirrorView", clonecam);
clonecam.setParallelProjection(true);
viewPort.setClearFlags(true, true, true);
viewPort.setBackgroundColor(ColorRGBA.Black);
Picture pic = new Picture("fullscene");
pic.setLocalTranslation(-0.75f, -0.5f, 0f);
if( expand ) {
pic.setLocalScale(3f, 1f, 1f);
} else {
pic.setLocalScale(1.5f, 1f, 1f);
}
pic.setQueueBucket(Bucket.Opaque);
pic.setTexture(environment.getApplication().getAssetManager(), (Texture2D)tex, false);
viewPort.attachScene(pic);
viewPort.setOutputFrameBuffer(null);
pic.updateGeometricState();
return viewPort;
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
private void setupFinalFullTexture(Camera cam) {
if (environment != null){
if (environment.getApplication() != null){
// create offscreen framebuffer
FrameBuffer out = new FrameBuffer(cam.getWidth(), cam.getHeight(), 1);
//offBuffer.setSrgb(true);
//setup framebuffer's texture
dualEyeTex = new Texture2D(cam.getWidth(), cam.getHeight(), Image.Format.RGBA8);
dualEyeTex.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
dualEyeTex.setMagFilter(Texture.MagFilter.Bilinear);
logger.config("Dual eye texture "+dualEyeTex.getName()+" ("+dualEyeTex.getImage().getId()+")");
logger.config(" Type: "+dualEyeTex.getType());
logger.config(" Size: "+dualEyeTex.getImage().getWidth()+"x"+dualEyeTex.getImage().getHeight());
logger.config(" Image depth: "+dualEyeTex.getImage().getDepth());
logger.config(" Image format: "+dualEyeTex.getImage().getFormat());
logger.config(" Image color space: "+dualEyeTex.getImage().getColorSpace());
//setup framebuffer to use texture
out.setDepthBuffer(Image.Format.Depth);
out.setColorTexture(dualEyeTex);
ViewPort viewPort = environment.getApplication().getViewPort();
viewPort.setClearFlags(true, true, true);
viewPort.setBackgroundColor(ColorRGBA.Black);
viewPort.setOutputFrameBuffer(out);
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
private ViewPort setupViewBuffers(Camera cam, String viewName){
if (environment != null){
if (environment.getApplication() != null){
// create offscreen framebuffer
FrameBuffer offBufferLeft = new FrameBuffer(cam.getWidth(), cam.getHeight(), 1);
//offBufferLeft.setSrgb(true);
//setup framebuffer's texture
Texture2D offTex = new Texture2D(cam.getWidth(), cam.getHeight(), Image.Format.RGBA8);
offTex.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
offTex.setMagFilter(Texture.MagFilter.Bilinear);
//setup framebuffer to use texture
offBufferLeft.setDepthBuffer(Image.Format.Depth);
offBufferLeft.setColorTexture(offTex);
ViewPort viewPort = environment.getApplication().getRenderManager().createPreView(viewName, cam);
viewPort.setClearFlags(true, true, true);
viewPort.setBackgroundColor(ColorRGBA.Black);
Iterator<Spatial> spatialIter = environment.getApplication().getViewPort().getScenes().iterator();
while(spatialIter.hasNext()){
viewPort.attachScene(spatialIter.next());
}
//set viewport to render to offscreen framebuffer
viewPort.setOutputFrameBuffer(offBufferLeft);
return viewPort;
} else {
throw new IllegalStateException("This VR environment is not attached to any application.");
}
} else {
throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
}
}
/**
* Setup a distortion mesh for the stereo view.
* @param eye the eye to apply.
* @param api the underlying VR api
* @return the distorted mesh.
*/
public static Mesh setupDistortionMesh(int eye, VRAPI api) {
Mesh distortionMesh = new Mesh();
float m_iLensGridSegmentCountH = 43, m_iLensGridSegmentCountV = 43;
float w = 1f / (m_iLensGridSegmentCountH - 1f);
float h = 1f / (m_iLensGridSegmentCountV - 1f);
float u, v;
float verts[] = new float[(int) (m_iLensGridSegmentCountV * m_iLensGridSegmentCountH) * 3];
float texcoordR[] = new float[(int) (m_iLensGridSegmentCountV * m_iLensGridSegmentCountH) * 2];
float texcoordG[] = new float[(int) (m_iLensGridSegmentCountV * m_iLensGridSegmentCountH) * 2];
float texcoordB[] = new float[(int) (m_iLensGridSegmentCountV * m_iLensGridSegmentCountH) * 2];
int vertPos = 0, coordPos = 0;
float Xoffset = eye == JOpenVRLibrary.EVREye.EVREye_Eye_Left ? -1f : 0;
for (int y = 0; y < m_iLensGridSegmentCountV; y++) {
for (int x = 0; x < m_iLensGridSegmentCountH; x++) {
u = x * w;
v = 1 - y * h;
verts[vertPos] = Xoffset + u; // x
verts[vertPos + 1] = -1 + 2 * y * h; // y
verts[vertPos + 2] = 0f; // z
vertPos += 3;
DistortionCoordinates_t dc0 = new DistortionCoordinates_t();
if( api.getVRSystem() == null ) {
// default to no distortion
texcoordR[coordPos] = u;
texcoordR[coordPos + 1] = 1 - v;
texcoordG[coordPos] = u;
texcoordG[coordPos + 1] = 1 - v;
texcoordB[coordPos] = u;
texcoordB[coordPos + 1] = 1 - v;
} else {
((VR_IVRSystem_FnTable)api.getVRSystem()).ComputeDistortion.apply(eye, u, v, dc0);
texcoordR[coordPos] = dc0.rfRed[0];
texcoordR[coordPos + 1] = 1 - dc0.rfRed[1];
texcoordG[coordPos] = dc0.rfGreen[0];
texcoordG[coordPos + 1] = 1 - dc0.rfGreen[1];
texcoordB[coordPos] = dc0.rfBlue[0];
texcoordB[coordPos + 1] = 1 - dc0.rfBlue[1];
}
coordPos += 2;
}
}
// have UV coordinates & positions, now to setup indices
int[] indices = new int[(int) ((m_iLensGridSegmentCountV - 1) * (m_iLensGridSegmentCountH - 1)) * 6];
int indexPos = 0;
int a, b, c, d;
int offset = 0;
for (int y = 0; y < m_iLensGridSegmentCountV - 1; y++) {
for (int x = 0; x < m_iLensGridSegmentCountH - 1; x++) {
a = (int) (m_iLensGridSegmentCountH * y + x + offset);
b = (int) (m_iLensGridSegmentCountH * y + x + 1 + offset);
c = (int) ((y + 1) * m_iLensGridSegmentCountH + x + 1 + offset);
d = (int) ((y + 1) * m_iLensGridSegmentCountH + x + offset);
indices[indexPos] = a;
indices[indexPos + 1] = b;
indices[indexPos + 2] = c;
indices[indexPos + 3] = a;
indices[indexPos + 4] = c;
indices[indexPos + 5] = d;
indexPos += 6;
}
}
// OK, create the mesh
distortionMesh.setBuffer(VertexBuffer.Type.Position, 3, verts);
distortionMesh.setBuffer(VertexBuffer.Type.Index, 1, indices);
distortionMesh.setBuffer(VertexBuffer.Type.TexCoord, 2, texcoordR);
distortionMesh.setBuffer(VertexBuffer.Type.TexCoord2, 2, texcoordG);
distortionMesh.setBuffer(VertexBuffer.Type.TexCoord3, 2, texcoordB);
distortionMesh.setStatic();
return distortionMesh;
}
}

@ -1,107 +0,0 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jmevr.util;
import com.jme3.app.VRApplication;
import com.jme3.input.vr.VRAPI;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer;
import com.jme3.system.jopenvr.DistortionCoordinates_t;
import com.jme3.system.jopenvr.JOpenVRLibrary;
import com.jme3.system.jopenvr.VR_IVRSystem_FnTable;
/**
*
* @author reden
*/
public class MeshUtil {
public static Mesh setupDistortionMesh(int eye, VRAPI api) {
Mesh distortionMesh = new Mesh();
float m_iLensGridSegmentCountH = 43, m_iLensGridSegmentCountV = 43;
float w = 1f / (m_iLensGridSegmentCountH - 1f);
float h = 1f / (m_iLensGridSegmentCountV - 1f);
float u, v;
float verts[] = new float[(int) (m_iLensGridSegmentCountV * m_iLensGridSegmentCountH) * 3];
float texcoordR[] = new float[(int) (m_iLensGridSegmentCountV * m_iLensGridSegmentCountH) * 2];
float texcoordG[] = new float[(int) (m_iLensGridSegmentCountV * m_iLensGridSegmentCountH) * 2];
float texcoordB[] = new float[(int) (m_iLensGridSegmentCountV * m_iLensGridSegmentCountH) * 2];
int vertPos = 0, coordPos = 0;
float Xoffset = eye == JOpenVRLibrary.EVREye.EVREye_Eye_Left ? -1f : 0;
for (int y = 0; y < m_iLensGridSegmentCountV; y++) {
for (int x = 0; x < m_iLensGridSegmentCountH; x++) {
u = x * w;
v = 1 - y * h;
verts[vertPos] = Xoffset + u; // x
verts[vertPos + 1] = -1 + 2 * y * h; // y
verts[vertPos + 2] = 0f; // z
vertPos += 3;
DistortionCoordinates_t dc0 = new DistortionCoordinates_t();
if( api.getVRSystem() == null ) {
// default to no distortion
texcoordR[coordPos] = u;
texcoordR[coordPos + 1] = 1 - v;
texcoordG[coordPos] = u;
texcoordG[coordPos + 1] = 1 - v;
texcoordB[coordPos] = u;
texcoordB[coordPos + 1] = 1 - v;
} else {
((VR_IVRSystem_FnTable)api.getVRSystem()).ComputeDistortion.apply(eye, u, v, dc0);
texcoordR[coordPos] = dc0.rfRed[0];
texcoordR[coordPos + 1] = 1 - dc0.rfRed[1];
texcoordG[coordPos] = dc0.rfGreen[0];
texcoordG[coordPos + 1] = 1 - dc0.rfGreen[1];
texcoordB[coordPos] = dc0.rfBlue[0];
texcoordB[coordPos + 1] = 1 - dc0.rfBlue[1];
}
coordPos += 2;
}
}
// have UV coordinates & positions, now to setup indices
int[] indices = new int[(int) ((m_iLensGridSegmentCountV - 1) * (m_iLensGridSegmentCountH - 1)) * 6];
int indexPos = 0;
int a, b, c, d;
int offset = 0;
for (int y = 0; y < m_iLensGridSegmentCountV - 1; y++) {
for (int x = 0; x < m_iLensGridSegmentCountH - 1; x++) {
a = (int) (m_iLensGridSegmentCountH * y + x + offset);
b = (int) (m_iLensGridSegmentCountH * y + x + 1 + offset);
c = (int) ((y + 1) * m_iLensGridSegmentCountH + x + 1 + offset);
d = (int) ((y + 1) * m_iLensGridSegmentCountH + x + offset);
indices[indexPos] = a;
indices[indexPos + 1] = b;
indices[indexPos + 2] = c;
indices[indexPos + 3] = a;
indices[indexPos + 4] = c;
indices[indexPos + 5] = d;
indexPos += 6;
}
}
// OK, create the mesh
distortionMesh.setBuffer(VertexBuffer.Type.Position, 3, verts);
distortionMesh.setBuffer(VertexBuffer.Type.Index, 1, indices);
distortionMesh.setBuffer(VertexBuffer.Type.TexCoord, 2, texcoordR);
distortionMesh.setBuffer(VertexBuffer.Type.TexCoord2, 2, texcoordG);
distortionMesh.setBuffer(VertexBuffer.Type.TexCoord3, 2, texcoordB);
distortionMesh.setStatic();
return distortionMesh;
}
}

@ -1,334 +0,0 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jmevr.util;
import com.jme3.app.Application;
import com.jme3.app.VRAppState;
import com.jme3.app.VRApplication;
import com.jme3.app.state.AppState;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Matrix3f;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Spatial;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.system.AppSettings;
import com.jme3.texture.FrameBuffer;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import java.awt.GraphicsEnvironment;
import java.util.Iterator;
/**
*
* @author
* phr00t
*/
public class VRGuiManager {
public enum POSITIONING_MODE {
MANUAL, AUTO_CAM_ALL, AUTO_CAM_ALL_SKIP_PITCH, AUTO_OBSERVER_POS_CAM_ROTATION, AUTO_OBSERVER_ALL, AUTO_OBSERVER_ALL_CAMHEIGHT
}
private Camera camLeft, camRight;
private float guiDistance = 1.5f, guiScale = 1f, guiPositioningElastic;
private POSITIONING_MODE posMode = POSITIONING_MODE.AUTO_CAM_ALL;
private final Matrix3f orient = new Matrix3f();
private Vector2f screenSize;
protected boolean wantsReposition;
private VRAppState app = null;
private Application application = null;
/**
* Create a new GUI manager attached to the given app state.
* @param app the VR app state that this manager is attached to.
*/
public VRGuiManager(){
}
/**
* Get the VR app state to which this GUI manager is attached.
* @return the VR app state to which this GUI manager is attached.
*/
public VRAppState getVRAppState(){
return app;
}
/**
* Attach the GUI manager to an app state and an Application.
* The application has to be the one that the app state is attached.
* This method should be called from the {@link AppState#initialize(com.jme3.app.state.AppStateManager, Application) initialize}
* method of the {@link AppState} instance.
* @param app the VR app state that this manager is attached to.
* @param application the application to whitch the app state is attcached.
*/
public void attach(VRAppState app, Application application){
this.app = app;
this.application = application;
}
/**
*
* Makes auto GUI positioning happen not immediately, but like an
* elastic connected to the headset. Setting to 0 disables (default)
* Higher settings make it track the headset quicker.
*
* @param elastic amount of elasticity
*/
public void setPositioningElasticity(float elastic) {
guiPositioningElastic = elastic;
}
public float getPositioningElasticity() {
return guiPositioningElastic;
}
public void setPositioningMode(POSITIONING_MODE mode) {
posMode = mode;
}
public Vector2f getCanvasSize() {
if( screenSize == null ) {
if( app.isInVR() && app.getVRHardware() != null ) {
screenSize = new Vector2f();
app.getVRHardware().getRenderSize(screenSize);
screenSize.multLocal(app.getVRViewManager().getResolutionMuliplier());
} else {
AppSettings as = application.getContext().getSettings();
screenSize = new Vector2f(as.getWidth(), as.getHeight());
}
}
return screenSize;
}
private Vector2f ratio;
public Vector2f getCanvasToWindowRatio() {
if( ratio == null ) {
ratio = new Vector2f();
Vector2f canvas = getCanvasSize();
int width = Integer.min(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getWidth(),
application.getContext().getSettings().getWidth());
int height = Integer.min(GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getHeight(),
application.getContext().getSettings().getHeight());
ratio.x = Float.max(1f, canvas.x / width);
ratio.y = Float.max(1f, canvas.y / height);
}
return ratio;
}
public POSITIONING_MODE getPositioningMode() {
return posMode;
}
public void positionGui() {
wantsReposition = true;
}
private final Vector3f EoldPos = new Vector3f();
private final Quaternion EoldDir = new Quaternion();
private void positionTo(Vector3f pos, Quaternion dir, float tpf) {
Vector3f guiPos = guiQuadNode.getLocalTranslation();
guiPos.set(0f, 0f, guiDistance);
dir.mult(guiPos, guiPos);
guiPos.x += pos.x;
guiPos.y += pos.y + app.getVRHeightAdjustment();
guiPos.z += pos.z;
if( guiPositioningElastic > 0f && posMode != POSITIONING_MODE.MANUAL ) {
// mix pos & dir with current pos & dir
guiPos.interpolateLocal(EoldPos, guiPos, Float.min(1f, tpf * guiPositioningElastic));
EoldPos.set(guiPos);
}
}
protected void updateGuiQuadGeometricState() {
guiQuadNode.updateGeometricState();
}
protected void positionGuiNow(float tpf) {
wantsReposition = false;
if( app.isInVR() == false ) return;
guiQuadNode.setLocalScale(guiDistance * guiScale * 4f, 4f * guiDistance * guiScale, 1f);
switch( posMode ) {
case MANUAL:
case AUTO_CAM_ALL_SKIP_PITCH:
case AUTO_CAM_ALL:
if( camLeft != null && camRight != null ) {
// get middle point
temppos.set(camLeft.getLocation()).interpolateLocal(camRight.getLocation(), 0.5f);
positionTo(temppos, camLeft.getRotation(), tpf);
}
rotateScreenTo(camLeft.getRotation(), tpf);
break;
case AUTO_OBSERVER_POS_CAM_ROTATION:
Object obs = app.getObserver();
if( obs != null ) {
if( obs instanceof Camera ) {
positionTo(((Camera)obs).getLocation(), camLeft.getRotation(), tpf);
} else {
positionTo(((Spatial)obs).getWorldTranslation(), camLeft.getRotation(), tpf);
}
}
rotateScreenTo(camLeft.getRotation(), tpf);
break;
case AUTO_OBSERVER_ALL:
case AUTO_OBSERVER_ALL_CAMHEIGHT:
obs = app.getObserver();
if( obs != null ) {
Quaternion q;
if( obs instanceof Camera ) {
q = ((Camera)obs).getRotation();
temppos.set(((Camera)obs).getLocation());
} else {
q = ((Spatial)obs).getWorldRotation();
temppos.set(((Spatial)obs).getWorldTranslation());
}
if( posMode == POSITIONING_MODE.AUTO_OBSERVER_ALL_CAMHEIGHT ) {
temppos.y = camLeft.getLocation().y;
}
positionTo(temppos, q, tpf);
rotateScreenTo(q, tpf);
}
break;
}
}
private final Vector3f look = new Vector3f(), left = new Vector3f(), temppos = new Vector3f(), up = new Vector3f();
private final Quaternion tempq = new Quaternion();
private void rotateScreenTo(Quaternion dir, float tpf) {
dir.getRotationColumn(2, look).negateLocal();
dir.getRotationColumn(0, left).negateLocal();
orient.fromAxes(left, dir.getRotationColumn(1, up), look);
Quaternion rot = tempq.fromRotationMatrix(orient);
if( posMode == POSITIONING_MODE.AUTO_CAM_ALL_SKIP_PITCH ) VRUtil.stripToYaw(rot);
if( guiPositioningElastic > 0f && posMode != POSITIONING_MODE.MANUAL ) {
// mix pos & dir with current pos & dir
EoldDir.nlerp(rot, tpf * guiPositioningElastic);
guiQuadNode.setLocalRotation(EoldDir);
} else {
guiQuadNode.setLocalRotation(rot);
}
}
public void setGuiDistance(float newGuiDistance) {
guiDistance = newGuiDistance;
}
public void setGuiScale(float scale) {
guiScale = scale;
}
public float getGuiDistance() {
return guiDistance;
}
public void adjustGuiDistance(float adjustAmount) {
guiDistance += adjustAmount;
}
protected void setupGui(Camera leftcam, Camera rightcam, ViewPort left, ViewPort right) {
if( app.hasTraditionalGUIOverlay() ) {
camLeft = leftcam;
camRight = rightcam;
Spatial guiScene = getGuiQuad(camLeft);
left.attachScene(guiScene);
if( right != null ) right.attachScene(guiScene);
setPositioningMode(posMode);
}
}
/*
do not use, set by preconfigure routine in VRApplication
*/
public void _enableCurvedSuface(boolean set) {
useCurvedSurface = set;
}
/*
do not use, set by preconfigure routine in VRApplication
*/
public void _enableGuiOverdraw(boolean set) {
overdraw = set;
}
private boolean useCurvedSurface = false, overdraw = false;
private Geometry guiQuad;
private Node guiQuadNode;
private ViewPort offView;
private Texture2D guiTexture;
private Spatial getGuiQuad(Camera sourceCam){
if( guiQuadNode == null ) {
Vector2f guiCanvasSize = getCanvasSize();
Camera offCamera = sourceCam.clone();
offCamera.setParallelProjection(true);
offCamera.setLocation(Vector3f.ZERO);
offCamera.lookAt(Vector3f.UNIT_Z, Vector3f.UNIT_Y);
offView = application.getRenderManager().createPreView("GUI View", offCamera);
offView.setClearFlags(true, true, true);
offView.setBackgroundColor(ColorRGBA.BlackNoAlpha);
// create offscreen framebuffer
FrameBuffer offBuffer = new FrameBuffer((int)guiCanvasSize.x, (int)guiCanvasSize.y, 1);
//setup framebuffer's texture
guiTexture = new Texture2D((int)guiCanvasSize.x, (int)guiCanvasSize.y, Format.RGBA8);
guiTexture.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
guiTexture.setMagFilter(Texture.MagFilter.Bilinear);
//setup framebuffer to use texture
offBuffer.setDepthBuffer(Format.Depth);
offBuffer.setColorTexture(guiTexture);
//set viewport to render to offscreen framebuffer
offView.setOutputFrameBuffer(offBuffer);
// setup framebuffer's scene
Iterator<Spatial> spatialIter = application.getGuiViewPort().getScenes().iterator();
while(spatialIter.hasNext()){
offView.attachScene(spatialIter.next());
}
if( useCurvedSurface ) {
guiQuad = (Geometry)application.getAssetManager().loadModel("Common/Util/gui_mesh.j3o");
} else {
guiQuad = new Geometry("guiQuad", new CenterQuad(1f, 1f));
}
Material mat = new Material(application.getAssetManager(), "Common/MatDefs/VR/GuiOverlay.j3md");
mat.getAdditionalRenderState().setDepthTest(!overdraw);
mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
mat.getAdditionalRenderState().setDepthWrite(false);
mat.setTexture("ColorMap", guiTexture);
guiQuad.setQueueBucket(Bucket.Translucent);
guiQuad.setMaterial(mat);
guiQuadNode = new Node("gui-quad-node");
guiQuadNode.setQueueBucket(Bucket.Translucent);
guiQuadNode.attachChild(guiQuad);
}
return guiQuadNode;
}
}

@ -1,234 +0,0 @@
/*
* 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 jmevr.util;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.glfw.GLFW;
import com.jme3.app.Application;
import com.jme3.app.VRAppState;
import com.jme3.app.VRApplication;
import com.jme3.app.state.AppState;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.lwjgl.GlfwMouseInputVR;
import com.jme3.input.vr.VRInputType;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.Vector2f;
import com.jme3.scene.Node;
import com.jme3.system.AppSettings;
import com.jme3.system.lwjgl.LwjglWindow;
import com.jme3.system.lwjgl.LwjglWindowVR;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.ui.Picture;
/**
*
* @author Phr00t
*/
public class VRMouseManager {
private static final Logger logger = Logger.getLogger(VRMouseManager.class.getName());
private Application application = null;
private VRAppState app = null;
private final int AVERAGE_AMNT = 4;
private int avgCounter;
private Picture mouseImage;
private int recentCenterCount = 0;
private final Vector2f cursorPos = new Vector2f();
private float ySize, sensitivity = 8f, acceleration = 2f;
private final float[] lastXmv = new float[AVERAGE_AMNT], lastYmv = new float[AVERAGE_AMNT];
private boolean thumbstickMode;
private float moveScale = 1f;
private float avg(float[] arr) {
float amt = 0f;
for(float f : arr) amt += f;
return amt / arr.length;
}
public VRMouseManager(){
}
/**
* Attach the mouse manager to an app state and an Application.
* The application has to be the one that the app state is attached.
* This method should be called from the {@link AppState#initialize(com.jme3.app.state.AppStateManager, Application) initialize}
* method of the {@link AppState} instance.
* @param app the VR app state that this manager is attached to.
* @param application the application to whitch the app state is attcached.
*/
public void attach(VRAppState app, Application application){
this.app = app;
this.application = application;
}
protected void init() {
logger.config("Initializing VR mouse manager.");
// load default mouseimage
mouseImage = new Picture("mouse");
setImage("Common/Util/mouse.png");
// hide default cursor by making it invisible
MouseInput mi = application.getContext().getMouseInput();
if( mi instanceof GlfwMouseInputVR ){
((GlfwMouseInputVR)mi).hideActiveCursor();
}
centerMouse();
logger.config("Initialized VR mouse manager [SUCCESS]");
}
public void setThumbstickMode(boolean set) {
thumbstickMode = set;
}
public boolean isThumbstickMode() {
return thumbstickMode;
}
public void setSpeed(float sensitivity, float acceleration) {
this.sensitivity = sensitivity;
this.acceleration = acceleration;
}
public float getSpeedSensitivity() {
return sensitivity;
}
public float getSpeedAcceleration() {
return acceleration;
}
public void setMouseMoveScale(float set) {
moveScale = set;
}
public void setImage(String texture) {
if( app.isInVR() == false ){
Texture tex = application.getAssetManager().loadTexture(texture);
mouseImage.setTexture(application.getAssetManager(), (Texture2D)tex, true);
ySize = tex.getImage().getHeight();
mouseImage.setHeight(ySize);
mouseImage.setWidth(tex.getImage().getWidth());
mouseImage.getMaterial().getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
mouseImage.getMaterial().getAdditionalRenderState().setDepthWrite(false);
} else {
Texture tex = application.getAssetManager().loadTexture(texture);
mouseImage.setTexture(application.getAssetManager(), (Texture2D)tex, true);
ySize = tex.getImage().getHeight();
mouseImage.setHeight(ySize);
mouseImage.setWidth(tex.getImage().getWidth());
mouseImage.getMaterial().getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
mouseImage.getMaterial().getAdditionalRenderState().setDepthWrite(false);
}
}
public void updateAnalogAsMouse(int inputIndex, AnalogListener mouseListener, String mouseXName, String mouseYName, float tpf) {
// got a tracked controller to use as the "mouse"
if( app.isInVR() == false ||
app.getVRinput() == null ||
app.getVRinput().isInputDeviceTracking(inputIndex) == false ) return;
Vector2f tpDelta;
if( thumbstickMode ) {
tpDelta = app.getVRinput().getAxis(inputIndex, VRInputType.ViveTrackpadAxis);
} else {
tpDelta = app.getVRinput().getAxisDeltaSinceLastCall(inputIndex, VRInputType.ViveTrackpadAxis);
}
float Xamount = (float)Math.pow(Math.abs(tpDelta.x) * sensitivity, acceleration);
float Yamount = (float)Math.pow(Math.abs(tpDelta.y) * sensitivity, acceleration);
if( tpDelta.x < 0f ) Xamount = -Xamount;
if( tpDelta.y < 0f ) Yamount = -Yamount;
Xamount *= moveScale; Yamount *= moveScale;
if( mouseListener != null ) {
if( tpDelta.x != 0f && mouseXName != null ) mouseListener.onAnalog(mouseXName, Xamount * 0.2f, tpf);
if( tpDelta.y != 0f && mouseYName != null ) mouseListener.onAnalog(mouseYName, Yamount * 0.2f, tpf);
}
if( application.getInputManager().isCursorVisible() ) {
int index = (avgCounter+1) % AVERAGE_AMNT;
lastXmv[index] = Xamount * 133f;
lastYmv[index] = Yamount * 133f;
cursorPos.x -= avg(lastXmv);
cursorPos.y -= avg(lastYmv);
Vector2f maxsize = app.getVRGUIManager().getCanvasSize();
if( cursorPos.x > maxsize.x ) cursorPos.x = maxsize.x;
if( cursorPos.x < 0f ) cursorPos.x = 0f;
if( cursorPos.y > maxsize.y ) cursorPos.y = maxsize.y;
if( cursorPos.y < 0f ) cursorPos.y = 0f;
}
}
public Vector2f getCursorPosition() {
if( app.isInVR() ) {
return cursorPos;
}
return application.getInputManager().getCursorPosition();
}
public void centerMouse() {
// set mouse in center of the screen if newly added
Vector2f size = app.getVRGUIManager().getCanvasSize();
MouseInput mi = application.getContext().getMouseInput();
AppSettings as = application.getContext().getSettings();
if( mi instanceof GlfwMouseInputVR ) ((GlfwMouseInputVR)mi).setCursorPosition((int)(as.getWidth() / 2f), (int)(as.getHeight() / 2f));
if( app.isInVR() ) {
cursorPos.x = size.x / 2f;
cursorPos.y = size.y / 2f;
recentCenterCount = 2;
}
}
protected void update(float tpf) {
// if we are showing the cursor, add our picture as it
if( application.getInputManager().isCursorVisible() ) {
if( mouseImage.getParent() == null ) {
application.getGuiViewPort().attachScene(mouseImage);
centerMouse();
// the "real" mouse pointer should stay hidden
if (application.getContext() instanceof LwjglWindow){
GLFW.glfwSetInputMode(((LwjglWindow)application.getContext()).getWindowHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED);
}
}
// handle mouse movements, which may be in addition to (or exclusive from) tracked movement
MouseInput mi = application.getContext().getMouseInput();
if( mi instanceof GlfwMouseInputVR ) {
if( recentCenterCount <= 0 ) {
//Vector2f winratio = VRGuiManager.getCanvasToWindowRatio();
cursorPos.x += ((GlfwMouseInputVR)mi).getLastDeltaX();// * winratio.x;
cursorPos.y += ((GlfwMouseInputVR)mi).getLastDeltaY();// * winratio.y;
if( cursorPos.x < 0f ) cursorPos.x = 0f;
if( cursorPos.y < 0f ) cursorPos.y = 0f;
if( cursorPos.x > app.getVRGUIManager().getCanvasSize().x ) cursorPos.x = app.getVRGUIManager().getCanvasSize().x;
if( cursorPos.y > app.getVRGUIManager().getCanvasSize().y ) cursorPos.y = app.getVRGUIManager().getCanvasSize().y;
} else recentCenterCount--;
((GlfwMouseInputVR)mi).clearDeltas();
}
// ok, update the cursor graphic position
Vector2f currentPos = getCursorPosition();
mouseImage.setLocalTranslation(currentPos.x, currentPos.y - ySize, app.getVRGUIManager().getGuiDistance() + 1f);
mouseImage.updateGeometricState();
} else if( mouseImage.getParent() != null ) {
Node n = mouseImage.getParent();
mouseImage.removeFromParent();
if (n != null){
n.updateGeometricState();
}
}
}
}

@ -1,863 +0,0 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package jmevr.util;
import com.jme3.app.Application;
import com.jme3.app.VRAppState;
import com.jme3.app.VRApplication;
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.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.post.CartoonSSAO;
import com.jme3.post.Filter;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.SceneProcessor;
import com.jme3.post.filters.FogFilter;
import com.jme3.post.filters.TranslucentBucketFilter;
import com.jme3.post.ssao.SSAOFilter;
import com.jme3.renderer.Camera;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.shadow.DirectionalLightShadowFilter;
import com.jme3.shadow.VRDirectionalLightShadowRenderer;
import com.jme3.system.jopenvr.JOpenVRLibrary;
import com.jme3.system.jopenvr.OpenVRUtil;
import com.jme3.system.jopenvr.Texture_t;
import com.jme3.system.jopenvr.VRTextureBounds_t;
import com.jme3.system.lwjgl.LwjglWindow;
import com.jme3.texture.FrameBuffer;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.ui.Picture;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
import java.awt.GraphicsEnvironment;
import java.util.Iterator;
import java.util.logging.Logger;
import osvrrendermanageropengl.OSVR_RenderBufferOpenGL;
import osvrrendermanageropengl.OSVR_ViewportDescription;
import osvrrendermanageropengl.OsvrRenderManagerOpenGLLibrary;
/**
* A VR view manager. This class enable to submit 3D views to the VR compositor.
* @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 VRViewManager {
private static final Logger logger = Logger.getLogger(VRViewManager.class.getName());
/**
* The name of the left view.
*/
public final static String LEFT_VIEW_NAME = "Left View";
/**
* The name of the right view.
*/
public final static String RIGHT_VIEW_NAME = "Right View";
private VRAppState app;
private Application application;
private Camera leftCamera;
private ViewPort leftViewport;
private FilterPostProcessor leftPostProcessor;
private Texture2D leftEyeTexture;
private Texture2D leftEyeDepth;
private Camera rightCamera;
private ViewPort rightViewport;
private FilterPostProcessor rightPostProcessor;
private Texture2D rightEyeTexture;
private Texture2D rightEyeDepth;
// OpenVR values
private VRTextureBounds_t leftTextureBounds;
private Texture_t leftTextureType;
private VRTextureBounds_t rightTextureBounds;
private Texture_t rightTextureType;
// OSVR values
OSVR_RenderBufferOpenGL.ByValue[] osvr_renderBuffer;
OSVR_ViewportDescription.ByValue osvr_viewDescFull;
OSVR_ViewportDescription.ByValue osvr_viewDescLeft;
OSVR_ViewportDescription.ByValue osvr_viewDescRight;
Pointer osvr_rmBufferState;
//private static boolean useCustomDistortion;
private float heightAdjustment;
private Texture2D dualEyeTex;
private final PointerByReference grabRBS = new PointerByReference();
private float resMult = 1f;
//final & temp values for camera calculations
private final Vector3f finalPosition = new Vector3f();
private final Quaternion finalRotation = new Quaternion();
private final Vector3f hmdPos = new Vector3f();
private final Quaternion hmdRot = new Quaternion();
/**
* Create a new VR view manager attached to the given {@link VRAppState VR app state}.<br>
* in order to be used, this manager has to be attached to an app state and to an application.
*/
public VRViewManager(){
}
/**
* Attach this manager to the given {@link VRAppState app state} and the given {@link Application application}.
* The application has to be the one that the app state is attached.
* This method should be called from the {@link AppState#initialize(com.jme3.app.state.AppStateManager, Application) initialize}
* method of the {@link AppState} instance.
* @param app the {@link VRAppState VR app state} to which this manager is linked.
* @param application the {@link Application} which the app state is attached.
*/
public void attach(VRAppState app, Application application){
this.app = app;
this.application = application;
}
/**
* Get the {@link Camera camera} attached to the left eye.
* @return the {@link Camera camera} attached to the left eye.
* @see #getRightCamera()
*/
public Camera getLeftCamera() {
return leftCamera;
}
/**
* Get the {@link Camera camera} attached to the right eye.
* @return the {@link Camera camera} attached to the right eye.
* @see #getLeftCamera()
*/
public Camera getRightCamera() {
return rightCamera;
}
/**
* Get the {@link ViewPort viewport} attached to the left eye.
* @return the {@link ViewPort viewport} attached to the left eye.
* @see #getRightViewport()
*/
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()
*/
public ViewPort getRightViewport() {
return rightViewport;
}
/**
* Get the identifier of the left eye texture.
* @return the identifier of the left eye texture.
* @see #getRightTexId()
* @see #getFullTexId()
*/
private int getLeftTexId() {
return (int)leftEyeTexture.getImage().getId();
}
/**
* Get the identifier of the right eye texture.
* @return the identifier of the right eye texture.
* @see #getLeftTexId()
* @see #getFullTexId()
*/
private int getRightTexId() {
return (int)rightEyeTexture.getImage().getId();
}
/**
* Get the identifier of the full (dual eye) texture.
* @return the identifier of the full (dual eye) texture.
* @see #getLeftTexId()
* @see #getRightTexId()
*/
private int getFullTexId() {
return (int)dualEyeTex.getImage().getId();
}
/**
* Get the height adjustment to apply to the cameras before rendering.
* @return the height adjustment to apply to the cameras before rendering.
* @see #setHeightAdjustment(float)
*/
public float getHeightAdjustment() {
return heightAdjustment;
}
/**
* Set the height adjustment to apply to the cameras before rendering.
* @param amount the height adjustment to apply to the cameras before rendering.
* @see #getHeightAdjustment()
*/
public void setHeightAdjustment(float amount) {
heightAdjustment = amount;
}
/**
* Get the resolution multiplier.
* @return the resolution multiplier.
* @see #setResolutionMultiplier(float)
*/
public float getResolutionMuliplier() {
return resMult;
}
/**
* Set the resolution multiplier.
* @param resMult the resolution multiplier.
* @see #getResolutionMuliplier()
*/
public void setResolutionMultiplier(float resMult) {
this.resMult = resMult;
}
/**
* Initialize the system binds of the textures.
*/
private void initTextureSubmitStructs() {
leftTextureType = new Texture_t();
rightTextureType = new Texture_t();
if( app.getVRHardware() instanceof OpenVR ) {
leftTextureBounds = new VRTextureBounds_t();
rightTextureBounds = new VRTextureBounds_t();
// left eye
leftTextureBounds.uMax = 0.5f;
leftTextureBounds.uMin = 0f;
leftTextureBounds.vMax = 1f;
leftTextureBounds.vMin = 0f;
leftTextureBounds.setAutoSynch(false);
leftTextureBounds.setAutoRead(false);
leftTextureBounds.setAutoWrite(false);
leftTextureBounds.write();
// right eye
rightTextureBounds.uMax = 1f;
rightTextureBounds.uMin = 0.5f;
rightTextureBounds.vMax = 1f;
rightTextureBounds.vMin = 0f;
rightTextureBounds.setAutoSynch(false);
rightTextureBounds.setAutoRead(false);
rightTextureBounds.setAutoWrite(false);
rightTextureBounds.write();
// texture type
// FIXME: Synchronize with JMonkey given texture (at this time is linear but was Gamma with phr00t implementation)
leftTextureType.eColorSpace = JOpenVRLibrary.EColorSpace.EColorSpace_ColorSpace_Gamma;
//leftTextureType.eColorSpace = JOpenVRLibrary.EColorSpace.EColorSpace_ColorSpace_Linear;
leftTextureType.eType = JOpenVRLibrary.ETextureType.ETextureType_TextureType_OpenGL;
leftTextureType.setAutoSynch(false);
leftTextureType.setAutoRead(false);
leftTextureType.setAutoWrite(false);
leftTextureType.handle = -1;
// FIXME: Synchronize with JMonkey given texture (at this time is linear but was Gamma with phr00t implementation)
rightTextureType.eColorSpace = JOpenVRLibrary.EColorSpace.EColorSpace_ColorSpace_Gamma;
//rightTextureType.eColorSpace = JOpenVRLibrary.EColorSpace.EColorSpace_ColorSpace_Linear;
rightTextureType.eType = JOpenVRLibrary.ETextureType.ETextureType_TextureType_OpenGL;
rightTextureType.setAutoSynch(false);
rightTextureType.setAutoRead(false);
rightTextureType.setAutoWrite(false);
rightTextureType.handle = -1;
logger.config("Init eyes native texture binds");
logger.config(" Left eye texture");
logger.config(" address: "+leftTextureType.getPointer());
logger.config(" size: "+leftTextureType.size()+" bytes");
logger.config(" color space: "+OpenVRUtil.getEColorSpaceString(leftTextureType.eColorSpace));
logger.config(" type: "+OpenVRUtil.getETextureTypeString(leftTextureType.eType));
logger.config(" auto read: "+leftTextureType.getAutoRead());
logger.config(" auto write: "+leftTextureType.getAutoWrite());
logger.config(" handle address: "+leftTextureType.handle);
logger.config(" handle value: "+leftTextureType.handle);
logger.config("");
logger.config(" Right eye texture");
logger.config(" address: "+rightTextureType.getPointer());
logger.config(" size: "+rightTextureType.size()+" bytes");
logger.config(" color space: "+OpenVRUtil.getEColorSpaceString(rightTextureType.eColorSpace));
logger.config(" type: "+OpenVRUtil.getETextureTypeString(rightTextureType.eType));
logger.config(" auto read: "+rightTextureType.getAutoRead());
logger.config(" auto write: "+rightTextureType.getAutoWrite());
logger.config(" handle address: "+rightTextureType.handle);
logger.config(" handle value: "+rightTextureType.handle);
} else if( app.getVRHardware() instanceof OSVR ) {
// must be OSVR
osvr_renderBuffer = new OSVR_RenderBufferOpenGL.ByValue[2];
osvr_renderBuffer[OSVR.EYE_LEFT] = new OSVR_RenderBufferOpenGL.ByValue();
osvr_renderBuffer[OSVR.EYE_RIGHT] = new OSVR_RenderBufferOpenGL.ByValue();
osvr_renderBuffer[OSVR.EYE_LEFT].setAutoSynch(false);
osvr_renderBuffer[OSVR.EYE_RIGHT].setAutoSynch(false);
osvr_viewDescFull = new OSVR_ViewportDescription.ByValue();
osvr_viewDescFull.setAutoSynch(false);
osvr_viewDescFull.left = osvr_viewDescFull.lower = 0.0;
osvr_viewDescFull.width = osvr_viewDescFull.height = 1.0;
osvr_viewDescLeft = new OSVR_ViewportDescription.ByValue();
osvr_viewDescLeft.setAutoSynch(false);
osvr_viewDescLeft.left = osvr_viewDescLeft.lower = 0.0;
osvr_viewDescLeft.width = 0.5;
osvr_viewDescLeft.height = 1.0;
osvr_viewDescRight = new OSVR_ViewportDescription.ByValue();
osvr_viewDescRight.setAutoSynch(false);
osvr_viewDescRight.left = 0.5;
osvr_viewDescRight.lower = 0.0;
osvr_viewDescRight.width = 0.5;
osvr_viewDescRight.height = 1.0;
osvr_viewDescRight.write();
osvr_viewDescLeft.write();
osvr_viewDescFull.write();
osvr_renderBuffer[OSVR.EYE_LEFT].depthStencilBufferName = -1;
osvr_renderBuffer[OSVR.EYE_LEFT].colorBufferName = -1;
osvr_renderBuffer[OSVR.EYE_RIGHT].depthStencilBufferName = -1;
osvr_renderBuffer[OSVR.EYE_RIGHT].colorBufferName = -1;
}
}
/**
* Register the OSVR OpenGL buffer.
* @param buf the OSVR OpenGL buffer.
*/
private void registerOSVRBuffer(OSVR_RenderBufferOpenGL.ByValue buf) {
OsvrRenderManagerOpenGLLibrary.osvrRenderManagerStartRegisterRenderBuffers(grabRBS);
OsvrRenderManagerOpenGLLibrary.osvrRenderManagerRegisterRenderBufferOpenGL(grabRBS.getValue(), buf);
OsvrRenderManagerOpenGLLibrary.osvrRenderManagerFinishRegisterRenderBuffers(((OSVR)app.getVRHardware()).getCompositor(), grabRBS.getValue(), (byte)0);
}
/**
* Send the textures to the two eyes.
*/
public void sendTextures() {
if( app.isInVR() ) {
VRAPI api = app.getVRHardware();
if( api.getCompositor() != null ) {
// using the compositor...
int errl = 0, errr = 0;
if( app.isInstanceVRRendering() ) {
if( leftTextureType.handle == -1 || leftTextureType.handle != getFullTexId() ) {
leftTextureType.handle = getFullTexId();
if( leftTextureType.handle != -1 ) {
leftTextureType.write();
if( api instanceof OSVR ) {
osvr_renderBuffer[OSVR.EYE_LEFT].colorBufferName = leftTextureType.handle;
osvr_renderBuffer[OSVR.EYE_LEFT].depthStencilBufferName = dualEyeTex.getImage().getId();
osvr_renderBuffer[OSVR.EYE_LEFT].write();
registerOSVRBuffer(osvr_renderBuffer[OSVR.EYE_LEFT]);
}
}
} else {
if( api instanceof OpenVR ) {
int submitFlag = JOpenVRLibrary.EVRSubmitFlags.EVRSubmitFlags_Submit_Default;
errr = ((OpenVR)api).getCompositor().Submit.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Right, leftTextureType, rightTextureBounds, submitFlag);
errl = ((OpenVR)api).getCompositor().Submit.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Left, leftTextureType, leftTextureBounds, submitFlag);
} else if( api instanceof OSVR ) {
((OSVR)api).handleRenderBufferPresent(osvr_viewDescLeft, osvr_viewDescRight,
osvr_renderBuffer[OSVR.EYE_LEFT], osvr_renderBuffer[OSVR.EYE_LEFT]);
}
}
} else if( leftTextureType.handle == -1 || rightTextureType.handle == -1 ||
leftTextureType.handle != getLeftTexId() || rightTextureType.handle != getRightTexId() ) {
leftTextureType.handle = getLeftTexId();
if( leftTextureType.handle != -1 ) {
logger.fine("Writing Left texture to native memory at " + leftTextureType.getPointer());
leftTextureType.write();
if( api instanceof OSVR ) {
osvr_renderBuffer[OSVR.EYE_LEFT].colorBufferName = leftTextureType.handle;
if( leftEyeDepth != null ) osvr_renderBuffer[OSVR.EYE_LEFT].depthStencilBufferName = leftEyeDepth.getImage().getId();
osvr_renderBuffer[OSVR.EYE_LEFT].write();
registerOSVRBuffer(osvr_renderBuffer[OSVR.EYE_LEFT]);
}
}
rightTextureType.handle = getRightTexId();
if( rightTextureType.handle != -1 ) {
logger.fine("Writing Right texture to native memory at " + leftTextureType.getPointer());
rightTextureType.write();
if( api instanceof OSVR ) {
osvr_renderBuffer[OSVR.EYE_RIGHT].colorBufferName = rightTextureType.handle;
if( rightEyeDepth != null ) osvr_renderBuffer[OSVR.EYE_RIGHT].depthStencilBufferName = rightEyeDepth.getImage().getId();
osvr_renderBuffer[OSVR.EYE_RIGHT].write();
registerOSVRBuffer(osvr_renderBuffer[OSVR.EYE_RIGHT]);
}
}
} else {
if( api instanceof OpenVR ) {
errl = ((OpenVR)api).getCompositor().Submit.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Left, leftTextureType, null,
JOpenVRLibrary.EVRSubmitFlags.EVRSubmitFlags_Submit_Default);
errr = ((OpenVR)api).getCompositor().Submit.apply(JOpenVRLibrary.EVREye.EVREye_Eye_Right, rightTextureType, null,
JOpenVRLibrary.EVRSubmitFlags.EVRSubmitFlags_Submit_Default);
} else if( api instanceof OSVR ) {
((OSVR)api).handleRenderBufferPresent(osvr_viewDescFull, osvr_viewDescFull,
osvr_renderBuffer[OSVR.EYE_LEFT], osvr_renderBuffer[OSVR.EYE_RIGHT]);
}
}
if( errl != 0 ){
logger.severe("Submit to left compositor error: " + OpenVRUtil.getEVRCompositorErrorString(errl)+" ("+Integer.toString(errl)+")");
logger.severe(" Texture color space: "+OpenVRUtil.getEColorSpaceString(leftTextureType.eColorSpace));
logger.severe(" Texture type: "+OpenVRUtil.getETextureTypeString(leftTextureType.eType));
logger.severe(" Texture handle: "+leftTextureType.handle);
logger.severe(" Left eye texture "+leftEyeTexture.getName()+" ("+leftEyeTexture.getImage().getId()+")");
logger.severe(" Type: "+leftEyeTexture.getType());
logger.severe(" Size: "+leftEyeTexture.getImage().getWidth()+"x"+leftEyeTexture.getImage().getHeight());
logger.severe(" Image depth: "+leftEyeTexture.getImage().getDepth());
logger.severe(" Image format: "+leftEyeTexture.getImage().getFormat());
logger.severe(" Image color space: "+leftEyeTexture.getImage().getColorSpace());
}
if( errr != 0 ){
logger.severe("Submit to right compositor error: " + OpenVRUtil.getEVRCompositorErrorString(errl)+" ("+Integer.toString(errl)+")");
logger.severe(" Texture color space: "+OpenVRUtil.getEColorSpaceString(rightTextureType.eColorSpace));
logger.severe(" Texture type: "+OpenVRUtil.getETextureTypeString(rightTextureType.eType));
logger.severe(" Texture handle: "+rightTextureType.handle);
logger.severe(" Right eye texture "+rightEyeTexture.getName()+" ("+rightEyeTexture.getImage().getId()+")");
logger.severe(" Type: "+rightEyeTexture.getType());
logger.severe(" Size: "+rightEyeTexture.getImage().getWidth()+"x"+rightEyeTexture.getImage().getHeight());
logger.severe(" Image depth: "+rightEyeTexture.getImage().getDepth());
logger.severe(" Image format: "+rightEyeTexture.getImage().getFormat());
logger.severe(" Image color space: "+rightEyeTexture.getImage().getColorSpace());
}
}
}
}
/**
* Initialize the VR view manager.
*/
public void initialize() {
logger.config("Initializing VR view manager.");
initTextureSubmitStructs();
setupCamerasAndViews();
setupVRScene();
moveScreenProcessingToEyes();
if( app.hasTraditionalGUIOverlay() ) {
app.getVRMouseManager().init();
// update the pose to position the gui correctly on start
update(0f);
app.getVRGUIManager().positionGui();
}
// if we are OSVR, our primary mirror window needs to be the same size as the render manager's output...
if( app.getVRHardware() instanceof OSVR ) {
int origWidth = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getWidth();
int origHeight = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode().getHeight();
long window = ((LwjglWindow)application.getContext()).getWindowHandle();
Vector2f windowSize = new Vector2f();
((OSVR)app.getVRHardware()).getRenderSize(windowSize);
windowSize.x = Math.max(windowSize.x * 2f, leftCamera.getWidth());
org.lwjgl.glfw.GLFW.glfwSetWindowSize(window, (int)windowSize.x, (int)windowSize.y);
application.getContext().getSettings().setResolution((int)windowSize.x, (int)windowSize.y);
if (application.getRenderManager() != null) {
application.getRenderManager().notifyReshape((int)windowSize.x, (int)windowSize.y);
}
org.lwjgl.glfw.GLFW.glfwSetWindowPos(window, origWidth - (int)windowSize.x, 32);
org.lwjgl.glfw.GLFW.glfwFocusWindow(window);
org.lwjgl.glfw.GLFW.glfwSetCursorPos(window, origWidth / 2.0, origHeight / 2.0);
}
logger.config("Initialized VR view manager [SUCCESS]");
}
/**
* Prepare the size of the given {@link Camera camera} to adapt it to the underlying rendering context.
* @param cam the {@link Camera camera} to prepare.
* @param xMult the camera width multiplier.
*/
private void prepareCameraSize(Camera cam, float xMult) {
Vector2f size = new Vector2f();
VRAPI vrhmd = app.getVRHardware();
if( vrhmd == null ) {
size.x = 1280f;
size.y = 720f;
} else {
vrhmd.getRenderSize(size);
}
if( size.x < application.getContext().getSettings().getWidth() ) {
size.x = application.getContext().getSettings().getWidth();
}
if( size.y < application.getContext().getSettings().getHeight() ) {
size.y = application.getContext().getSettings().getHeight();
}
if( app.isInstanceVRRendering() ) size.x *= 2f;
// other adjustments
size.x *= xMult;
size.x *= resMult;
size.y *= resMult;
if( cam.getWidth() != size.x || cam.getHeight() != size.y ) cam.resize((int)size.x, (int)size.y, false);
}
/**
* Replaces rootNode as the main cameras scene with the distortion mesh
*/
private void setupVRScene(){
// no special scene to setup if we are doing instancing
if( app.isInstanceVRRendering() ) {
// distortion has to be done with compositor here... we want only one pass on our end!
if( application.getContext().getSettings().isSwapBuffers() ) {
setupMirrorBuffers(app.getCamera(), dualEyeTex, true);
}
return;
}
leftEyeTexture = (Texture2D) leftViewport.getOutputFrameBuffer().getColorBuffer().getTexture();
rightEyeTexture = (Texture2D)rightViewport.getOutputFrameBuffer().getColorBuffer().getTexture();
leftEyeDepth = (Texture2D) leftViewport.getOutputFrameBuffer().getDepthBuffer().getTexture();
rightEyeDepth = (Texture2D)rightViewport.getOutputFrameBuffer().getDepthBuffer().getTexture();
// main viewport is either going to be a distortion scene or nothing
// mirroring is handled by copying framebuffers
Iterator<Spatial> spatialIter = application.getViewPort().getScenes().iterator();
while(spatialIter.hasNext()){
application.getViewPort().detachScene(spatialIter.next());
}
spatialIter = application.getGuiViewPort().getScenes().iterator();
while(spatialIter.hasNext()){
application.getGuiViewPort().detachScene(spatialIter.next());
}
// only setup distortion scene if compositor isn't running (or using custom mesh distortion option)
if( app.getVRHardware().getCompositor() == null ) {
Node distortionScene = new Node();
Material leftMat = new Material(application.getAssetManager(), "Common/MatDefs/VR/OpenVR.j3md");
leftMat.setTexture("Texture", leftEyeTexture);
Geometry leftEye = new Geometry("box", MeshUtil.setupDistortionMesh(JOpenVRLibrary.EVREye.EVREye_Eye_Left, app.getVRHardware()));
leftEye.setMaterial(leftMat);
distortionScene.attachChild(leftEye);
Material rightMat = new Material(application.getAssetManager(), "Common/MatDefs/VR/OpenVR.j3md");
rightMat.setTexture("Texture", rightEyeTexture);
Geometry rightEye = new Geometry("box", MeshUtil.setupDistortionMesh(JOpenVRLibrary.EVREye.EVREye_Eye_Right, app.getVRHardware()));
rightEye.setMaterial(rightMat);
distortionScene.attachChild(rightEye);
distortionScene.updateGeometricState();
application.getViewPort().attachScene(distortionScene);
//if( useCustomDistortion ) setupFinalFullTexture(app.getViewPort().getCamera());
}
if( application.getContext().getSettings().isSwapBuffers() ) {
setupMirrorBuffers(app.getCamera(), leftEyeTexture, false);
}
}
/**
* Update the VR view manager.
* This method is called by the attached {@link VRApplication VR application} and should not be called manually.
* @param tpf the time per frame.
*/
public void update(float tpf) {
// grab the observer
Object obs = app.getObserver();
Quaternion objRot;
Vector3f objPos;
if( obs instanceof Camera ) {
objRot = ((Camera)obs).getRotation();
objPos = ((Camera)obs).getLocation();
} else {
objRot = ((Spatial)obs).getWorldRotation();
objPos = ((Spatial)obs).getWorldTranslation();
}
// grab the hardware handle
VRAPI dev = app.getVRHardware();
if( dev != null ) {
// update the HMD's position & orientation
dev.updatePose();
dev.getPositionAndOrientation(hmdPos, hmdRot);
if( obs != null ) {
// update hmdPos based on obs rotation
finalRotation.set(objRot);
finalRotation.mult(hmdPos, hmdPos);
finalRotation.multLocal(hmdRot);
}
finalizeCamera(dev.getHMDVectorPoseLeftEye(), objPos, leftCamera);
finalizeCamera(dev.getHMDVectorPoseRightEye(), objPos, rightCamera);
} else {
leftCamera.setFrame(objPos, objRot);
rightCamera.setFrame(objPos, objRot);
}
if( app.hasTraditionalGUIOverlay() ) {
// update the mouse?
app.getVRMouseManager().update(tpf);
// update GUI position?
if( app.getVRGUIManager().wantsReposition || app.getVRGUIManager().getPositioningMode() != VRGuiManager.POSITIONING_MODE.MANUAL ) {
app.getVRGUIManager().positionGuiNow(tpf);
app.getVRGUIManager().updateGuiQuadGeometricState();
}
}
}
/**
* Place the camera within the scene.
* @param eyePos the eye position.
* @param obsPosition the observer position.
* @param cam the camera to place.
*/
private void finalizeCamera(Vector3f eyePos, Vector3f obsPosition, Camera cam) {
finalRotation.mult(eyePos, finalPosition);
finalPosition.addLocal(hmdPos);
if( obsPosition != null ) finalPosition.addLocal(obsPosition);
finalPosition.y += heightAdjustment;
cam.setFrame(finalPosition, finalRotation);
}
/**
* Handles moving filters from the main view to each eye
*/
public void moveScreenProcessingToEyes() {
if( rightViewport == null ) return;
syncScreenProcessing(application.getViewPort());
application.getViewPort().clearProcessors();
}
/**
* Sets the two views to use the list of {@link SceneProcessor processors}.
* @param sourceViewport the {@link ViewPort viewport} that contains the processors to use.
*/
public void syncScreenProcessing(ViewPort sourceViewport) {
if( rightViewport == null ) return;
// setup post processing filters
if( rightPostProcessor == null ) {
rightPostProcessor = new FilterPostProcessor(application.getAssetManager());
leftPostProcessor = new FilterPostProcessor(application.getAssetManager());
}
// clear out all filters & processors, to start from scratch
rightPostProcessor.removeAllFilters();
leftPostProcessor.removeAllFilters();
leftViewport.clearProcessors();
rightViewport.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
leftViewport.addProcessor(leftPostProcessor);
rightViewport.addProcessor(rightPostProcessor);
// 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()) {
if (sceneProcessor instanceof FilterPostProcessor) {
for(Filter f : ((FilterPostProcessor)sceneProcessor).getFilterList() ) {
if( f instanceof TranslucentBucketFilter ) {
// just remove this filter, we will add it at the end manually
((FilterPostProcessor)sceneProcessor).removeFilter(f);
} else {
leftPostProcessor.addFilter(f);
// clone to the right
Filter f2;
if(f instanceof FogFilter){
f2 = FilterUtil.cloneFogFilter((FogFilter)f);
} else if (f instanceof CartoonSSAO ) {
f2 = new CartoonSSAO((CartoonSSAO)f);
} else if (f instanceof SSAOFilter){
f2 = FilterUtil.cloneSSAOFilter((SSAOFilter)f);
} else if (f instanceof DirectionalLightShadowFilter){
f2 = FilterUtil.cloneDirectionalLightShadowFilter(application.getAssetManager(), (DirectionalLightShadowFilter)f);
} else {
f2 = f; // dof, bloom, lightscattering etc.
}
rightPostProcessor.addFilter(f2);
}
}
} else if (sceneProcessor instanceof VRDirectionalLightShadowRenderer) {
// shadow processing
// TODO: make right shadow processor use same left shadow maps for performance
VRDirectionalLightShadowRenderer dlsr = (VRDirectionalLightShadowRenderer) sceneProcessor;
VRDirectionalLightShadowRenderer dlsrRight = dlsr.clone();
dlsrRight.setLight(dlsr.getLight());
rightViewport.getProcessors().add(0, dlsrRight);
leftViewport.getProcessors().add(0, sceneProcessor);
}
}
// make sure each has a translucent filter renderer
leftPostProcessor.addFilter(new TranslucentBucketFilter());
rightPostProcessor.addFilter(new TranslucentBucketFilter());
}
private void setupCamerasAndViews() {
// get desired frustrum from original camera
Camera origCam = app.getCamera();
float fFar = origCam.getFrustumFar();
float fNear = origCam.getFrustumNear();
// if we are using OSVR get the eye info here
if( app.getVRHardware() instanceof OSVR ) {
((OSVR)app.getVRHardware()).getEyeInfo();
}
// restore frustrum on distortion scene cam, if needed
if( app.isInstanceVRRendering() ) {
leftCamera = origCam;
} else if( app.compositorAllowed() == false ) {
origCam.setFrustumFar(100f);
origCam.setFrustumNear(1f);
leftCamera = origCam.clone();
prepareCameraSize(origCam, 2f);
} else {
leftCamera = origCam.clone();
}
leftCamera.setFrustumPerspective(app.getDefaultFOV(), app.getDefaultAspect(), fNear, fFar);
prepareCameraSize(leftCamera, 1f);
if( app.getVRHardware() != null ) leftCamera.setProjectionMatrix(app.getVRHardware().getHMDMatrixProjectionLeftEye(leftCamera));
//org.lwjgl.opengl.GL11.glEnable(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_SRGB);
if( !app.isInstanceVRRendering()) {
leftViewport = setupViewBuffers(leftCamera, LEFT_VIEW_NAME);
rightCamera = leftCamera.clone();
if( app.getVRHardware() != null ){
rightCamera.setProjectionMatrix(app.getVRHardware().getHMDMatrixProjectionRightEye(rightCamera));
}
rightViewport = setupViewBuffers(rightCamera, RIGHT_VIEW_NAME);
} else {
System.err.println("[VRViewManager] THIS CODE NEED CHANGES !!!");
leftViewport = application.getViewPort();
//leftViewport.attachScene(app.getRootNode());
rightCamera = leftCamera.clone();
if( app.getVRHardware() != null ){
rightCamera.setProjectionMatrix(app.getVRHardware().getHMDMatrixProjectionRightEye(rightCamera));
}
org.lwjgl.opengl.GL11.glEnable(org.lwjgl.opengl.GL30.GL_CLIP_DISTANCE0);
//FIXME: [jme-vr] Fix with JMonkey next release
//RenderManager._VRInstancing_RightCamProjection = camRight.getViewProjectionMatrix();
setupFinalFullTexture(application.getViewPort().getCamera());
}
// setup gui
app.getVRGUIManager().setupGui(leftCamera, rightCamera, leftViewport, rightViewport);
if( app.getVRHardware() != null ) {
// call these to cache the results internally
app.getVRHardware().getHMDMatrixPoseLeftEye();
app.getVRHardware().getHMDMatrixPoseRightEye();
}
}
private ViewPort setupMirrorBuffers(Camera cam, Texture tex, boolean expand) {
Camera clonecam = cam.clone();
ViewPort viewPort = application.getRenderManager().createPostView("MirrorView", clonecam);
clonecam.setParallelProjection(true);
viewPort.setClearFlags(true, true, true);
viewPort.setBackgroundColor(ColorRGBA.Black);
Picture pic = new Picture("fullscene");
pic.setLocalTranslation(-0.75f, -0.5f, 0f);
if( expand ) {
pic.setLocalScale(3f, 1f, 1f);
} else {
pic.setLocalScale(1.5f, 1f, 1f);
}
pic.setQueueBucket(Bucket.Opaque);
pic.setTexture(application.getAssetManager(), (Texture2D)tex, false);
viewPort.attachScene(pic);
viewPort.setOutputFrameBuffer(null);
pic.updateGeometricState();
return viewPort;
}
private void setupFinalFullTexture(Camera cam) {
// create offscreen framebuffer
FrameBuffer out = new FrameBuffer(cam.getWidth(), cam.getHeight(), 1);
//offBuffer.setSrgb(true);
//setup framebuffer's texture
dualEyeTex = new Texture2D(cam.getWidth(), cam.getHeight(), Image.Format.RGBA8);
dualEyeTex.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
dualEyeTex.setMagFilter(Texture.MagFilter.Bilinear);
logger.config("Dual eye texture "+dualEyeTex.getName()+" ("+dualEyeTex.getImage().getId()+")");
logger.config(" Type: "+dualEyeTex.getType());
logger.config(" Size: "+dualEyeTex.getImage().getWidth()+"x"+dualEyeTex.getImage().getHeight());
logger.config(" Image depth: "+dualEyeTex.getImage().getDepth());
logger.config(" Image format: "+dualEyeTex.getImage().getFormat());
logger.config(" Image color space: "+dualEyeTex.getImage().getColorSpace());
//setup framebuffer to use texture
out.setDepthBuffer(Image.Format.Depth);
out.setColorTexture(dualEyeTex);
ViewPort viewPort = application.getViewPort();
viewPort.setClearFlags(true, true, true);
viewPort.setBackgroundColor(ColorRGBA.Black);
viewPort.setOutputFrameBuffer(out);
}
private ViewPort setupViewBuffers(Camera cam, String viewName){
// create offscreen framebuffer
FrameBuffer offBufferLeft = new FrameBuffer(cam.getWidth(), cam.getHeight(), 1);
//offBufferLeft.setSrgb(true);
//setup framebuffer's texture
Texture2D offTex = new Texture2D(cam.getWidth(), cam.getHeight(), Image.Format.RGBA8);
offTex.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
offTex.setMagFilter(Texture.MagFilter.Bilinear);
//setup framebuffer to use texture
offBufferLeft.setDepthBuffer(Image.Format.Depth);
offBufferLeft.setColorTexture(offTex);
ViewPort viewPort = application.getRenderManager().createPreView(viewName, cam);
viewPort.setClearFlags(true, true, true);
viewPort.setBackgroundColor(ColorRGBA.Black);
Iterator<Spatial> spatialIter = application.getViewPort().getScenes().iterator();
while(spatialIter.hasNext()){
viewPort.attachScene(spatialIter.next());
}
//set viewport to render to offscreen framebuffer
viewPort.setOutputFrameBuffer(offBufferLeft);
return viewPort;
}
}
Loading…
Cancel
Save