diff --git a/jme3-vr/src/main/java/com/jme3/input/vr/OSVR.java b/jme3-vr/src/main/java/com/jme3/input/vr/OSVR.java index dce04e7b4..0258998b4 100644 --- a/jme3-vr/src/main/java/com/jme3/input/vr/OSVR.java +++ b/jme3-vr/src/main/java/com/jme3/input/vr/OSVR.java @@ -1,461 +1,461 @@ -/* - -https://github.com/sensics/OSVR-RenderManager/blob/master/examples/RenderManagerOpenGLCAPIExample.cpp - -- JVM crashes often.. placing breakpoints during initialization clears it up most of the time (WHY!?) - - OSVR is just unstable.. any way to improve things? -- render manager looks good, but left eye seems stretched - - */ -package com.jme3.input.vr; - -import com.jme3.app.VREnvironment; -import com.jme3.math.Matrix4f; -import com.jme3.math.Quaternion; -import com.jme3.math.Vector2f; -import com.jme3.math.Vector3f; -import com.jme3.renderer.Camera; -import com.jme3.system.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.NativeSizeByReference; -import com.sun.jna.Pointer; -import com.sun.jna.ptr.PointerByReference; -import java.nio.FloatBuffer; -import java.util.logging.Logger; - -/** - * A class that wraps an OSVR system. - * @author reden - phr00t - https://github.com/phr00t - * @author Julien Seinturier - (c) 2016 - JOrigin project - http:/www.jorigin.org - */ -public class OSVR implements VRAPI { - - private static final Logger logger = Logger.getLogger(OSVR.class.getName()); - - /** - * The first viewer index. - */ - public static final int FIRST_VIEWER = 0; - - /** - * The left eye index. - */ - public static final int EYE_LEFT = 0; - - /** - * The right eye index. - */ - public static final int EYE_RIGHT = 1; - - /** - * The size of the left eye. - */ - public static final NativeSize EYE_LEFT_SIZE = new NativeSize(EYE_LEFT); - - /** - * The size of the right eye. - */ - public static final NativeSize EYE_RIGHT_SIZE = new NativeSize(EYE_RIGHT); - - /** - * The default J String. - */ - public static byte[] defaultJString = { 'j', (byte)0 }; - - /** - * The default OpenGL String. - */ - public static byte[] OpenGLString = { 'O', 'p', 'e', 'n', 'G', 'L', (byte)0 }; - - private final Matrix4f[] eyeMatrix = new Matrix4f[2]; - - private PointerByReference grabRM; - private PointerByReference grabRMOGL; - private PointerByReference grabRIC; - - OSVR_RenderParams.ByValue renderParams; - OsvrClientKitLibrary.OSVR_ClientContext context; - com.jme3.system.osvr.osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue graphicsLibrary; - Pointer renderManager, renderManagerOpenGL, renderInfoCollection, registerBufferState; - OSVRInput VRinput; - NativeSize numRenderInfo; - NativeSizeByReference grabNumInfo = new NativeSizeByReference(); - OSVR_RenderInfoOpenGL.ByValue eyeLeftInfo, eyeRightInfo; - Matrix4f hmdPoseLeftEye; - Matrix4f hmdPoseRightEye; - Vector3f hmdPoseLeftEyeVec, hmdPoseRightEyeVec, hmdSeatToStand; - OSVR_DisplayConfig displayConfig; - OSVR_Pose3 hmdPose = new OSVR_Pose3(); - Vector3f storePos = new Vector3f(); - Quaternion storeRot = new Quaternion(); - PointerByReference presentState = new PointerByReference(); - OSVR_OpenResultsOpenGL openResults = new OSVR_OpenResultsOpenGL(); - - long glfwContext; - long renderManagerContext; - long wglGLFW; - long wglRM; - - boolean initSuccess = false; - boolean flipEyes = false; - - private VREnvironment environment = null; - - /** - * Create a new OSVR system attached to the given {@link VREnvironment VR environment}. - * @param environment the {@link VREnvironment VR environment} to which the input is attached. - */ - public OSVR(VREnvironment environment){ - this.environment = environment; - } - - /** - * Access to the underlying OSVR structures. - * @param leftView the left viewport. - * @param rightView the right viewport. - * @param leftBuffer the left buffer. - * @param rightBuffer the right buffer. - * @return true if the structure are accessible and false otherwise. - */ - public boolean handleRenderBufferPresent(OSVR_ViewportDescription.ByValue leftView, OSVR_ViewportDescription.ByValue rightView, - OSVR_RenderBufferOpenGL.ByValue leftBuffer, OSVR_RenderBufferOpenGL.ByValue rightBuffer) { - if( eyeLeftInfo == null || eyeRightInfo == null ) return false; - byte retval; - OsvrRenderManagerOpenGLLibrary.osvrRenderManagerStartPresentRenderBuffers(presentState); - getEyeInfo(); - OsvrRenderManagerOpenGLLibrary.osvrRenderManagerPresentRenderBufferOpenGL(presentState.getValue(), leftBuffer, eyeLeftInfo, leftView); - OsvrRenderManagerOpenGLLibrary.osvrRenderManagerPresentRenderBufferOpenGL(presentState.getValue(), rightBuffer, eyeRightInfo, rightView); - retval = OsvrRenderManagerOpenGLLibrary.osvrRenderManagerFinishPresentRenderBuffers(renderManager, presentState.getValue(), renderParams, (byte)0); - return retval == 0; // only check the last error, since if something errored above, the last call won't work & all calls will log to syserr - } - - - - @Override - public boolean initialize() { - - logger.config("Initialize OSVR system."); - - hmdPose.setAutoSynch(false); - context = OsvrClientKitLibrary.osvrClientInit(defaultJString, 0); - VRinput = new OSVRInput(environment); - initSuccess = context != null && VRinput.init(); - if( initSuccess ) { - PointerByReference grabDisplay = new PointerByReference(); - byte retval = OsvrDisplayLibrary.osvrClientGetDisplay(context, grabDisplay); - if( retval != 0 ) { - System.out.println("OSVR Get Display Error: " + retval); - initSuccess = false; - return false; - } - displayConfig = new OSVR_DisplayConfig(grabDisplay.getValue()); - System.out.println("Waiting for the display to fully start up, including receiving initial pose update..."); - int i = 400; - while (OsvrDisplayLibrary.osvrClientCheckDisplayStartup(displayConfig) != 0) { - if( i-- < 0 ) { - System.out.println("Couldn't get display startup update in time, continuing anyway..."); - break; - } - OsvrClientKitLibrary.osvrClientUpdate(context); - try { - Thread.sleep(5); - } catch(Exception e) { } - } - System.out.println("OK, display startup status is good!"); - } - return initSuccess; - } - - - /** - * Grab the current GLFW context. - */ - public void grabGLFWContext() { - // get current conext - wglGLFW = org.lwjgl.opengl.WGL.wglGetCurrentContext(); - glfwContext = org.lwjgl.glfw.GLFW.glfwGetCurrentContext(); - } - - /** - * Enable context sharing. - * @return true if the context is successfully shared and false otherwise. - */ - public boolean shareContext() { - if( org.lwjgl.opengl.WGL.wglShareLists(wglRM, wglGLFW)) { - System.out.println("Context sharing success!"); - return true; - } else { - System.out.println("Context sharing problem..."); - return false; - } - } - - @Override - public boolean initVRCompositor(boolean allowed) { - if( !allowed || renderManager != null ) return false; - grabGLFWContext(); - graphicsLibrary = new com.jme3.system.osvr.osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue(); - graphicsLibrary.toolkit = null; - graphicsLibrary.setAutoSynch(false); - grabRM = new PointerByReference(); grabRMOGL = new PointerByReference(); - byte retval = OsvrRenderManagerOpenGLLibrary.osvrCreateRenderManagerOpenGL(context, OpenGLString, graphicsLibrary, grabRM, grabRMOGL); - if( retval == 0 ) { - renderManager = grabRM.getValue(); renderManagerOpenGL = grabRMOGL.getValue(); - if( renderManager == null || renderManagerOpenGL == null ) { - System.out.println("Render Manager Created NULL, error!"); - return false; - } - openResults.setAutoSynch(false); - retval = OsvrRenderManagerOpenGLLibrary.osvrRenderManagerOpenDisplayOpenGL(renderManager, openResults); - if( retval == 0 ) { - wglRM = org.lwjgl.opengl.WGL.wglGetCurrentContext(); - renderManagerContext = org.lwjgl.glfw.GLFW.glfwGetCurrentContext(); - shareContext(); - OsvrClientKitLibrary.osvrClientUpdate(context); - renderParams = new OSVR_RenderParams.ByValue(); - renderParams.setAutoSynch(false); - OsvrRenderManagerOpenGLLibrary.osvrRenderManagerGetDefaultRenderParams(renderParams); - grabRIC = new PointerByReference(); - retval = OsvrRenderManagerOpenGLLibrary.osvrRenderManagerGetRenderInfoCollection(renderManager, renderParams, grabRIC); - if( retval == 0 ) { - renderInfoCollection = grabRIC.getValue(); - OsvrRenderManagerOpenGLLibrary.osvrRenderManagerGetNumRenderInfoInCollection(renderInfoCollection, grabNumInfo); - numRenderInfo = grabNumInfo.getValue(); - eyeLeftInfo = new OSVR_RenderInfoOpenGL.ByValue(); - eyeRightInfo = new OSVR_RenderInfoOpenGL.ByValue(); - eyeLeftInfo.setAutoSynch(false); - eyeRightInfo.setAutoSynch(false); - return true; - } - OsvrRenderManagerOpenGLLibrary.osvrDestroyRenderManager(renderManager); - System.out.println("OSVR Render Manager Info Collection Error: " + retval); - return false; - } - OsvrRenderManagerOpenGLLibrary.osvrDestroyRenderManager(renderManager); - System.out.println("OSVR Open Render Manager Display Error: " + retval); - return false; - } - System.out.println("OSVR Create Render Manager Error: " + retval); - return false; - } - - @Override - public OsvrClientKitLibrary.OSVR_ClientContext getVRSystem() { - return context; - } - - @Override - public Pointer getCompositor() { - return renderManager; - } - - @Override - public String getName() { - return "OSVR"; - } - - @Override - public VRInputAPI getVRinput() { - return VRinput; - } - - @Override - public void setFlipEyes(boolean set) { - flipEyes = set; - } - - @Override - public void printLatencyInfoToConsole(boolean set) { - - } - - @Override - public int getDisplayFrequency() { - return 60; //debug display frequency - } - - @Override - public void destroy() { - if( renderManager != null ) OsvrRenderManagerOpenGLLibrary.osvrDestroyRenderManager(renderManager); - if( displayConfig != null ) OsvrDisplayLibrary.osvrClientFreeDisplay(displayConfig); - } - - @Override - public boolean isInitialized() { - return initSuccess; - } - - @Override - public void reset() { - // TODO: no native OSVR reset function - // may need to take current position and negate it from future values - } - - @Override - public void getRenderSize(Vector2f store) { - if( eyeLeftInfo == null || eyeLeftInfo.viewport.width == 0.0 ) { - store.x = 1280f; store.y = 720f; - } else { - store.x = (float)eyeLeftInfo.viewport.width; - store.y = (float)eyeLeftInfo.viewport.height; - } - } - - /** - * Read and update the eye info from the underlying OSVR system. - */ - public void getEyeInfo() { - OsvrRenderManagerOpenGLLibrary.osvrRenderManagerGetRenderInfoFromCollectionOpenGL(renderInfoCollection, EYE_LEFT_SIZE, eyeLeftInfo); - OsvrRenderManagerOpenGLLibrary.osvrRenderManagerGetRenderInfoFromCollectionOpenGL(renderInfoCollection, EYE_RIGHT_SIZE, eyeRightInfo); - eyeLeftInfo.read(); eyeRightInfo.read(); - } -/* - @Override - public float getFOV(int dir) { - return 105f; //default FOV - } -*/ - @Override - public float getInterpupillaryDistance() { - return 0.065f; //default IPD - } - - @Override - public Quaternion getOrientation() { - storeRot.set((float)-hmdPose.rotation.data[1], - (float)hmdPose.rotation.data[2], - (float)-hmdPose.rotation.data[3], - (float)hmdPose.rotation.data[0]); - if( storeRot.equals(Quaternion.ZERO) ) storeRot.set(Quaternion.DIRECTION_Z); - return storeRot; - } - - @Override - public Vector3f getPosition() { - storePos.x = (float)-hmdPose.translation.data[0]; - storePos.y = (float)hmdPose.translation.data[1]; - storePos.z = (float)-hmdPose.translation.data[2]; - return storePos; - } - - @Override - public void getPositionAndOrientation(Vector3f storePos, Quaternion storeRot) { - storePos.x = (float)-hmdPose.translation.data[0]; - storePos.y = (float)hmdPose.translation.data[1]; - storePos.z = (float)-hmdPose.translation.data[2]; - storeRot.set((float)-hmdPose.rotation.data[1], - (float)hmdPose.rotation.data[2], - (float)-hmdPose.rotation.data[3], - (float)hmdPose.rotation.data[0]); - if( storeRot.equals(Quaternion.ZERO) ) storeRot.set(Quaternion.DIRECTION_Z); - } - - @Override - public void updatePose() { - if( context == null || displayConfig == null ) return; - OsvrClientKitLibrary.osvrClientUpdate(context); - OsvrDisplayLibrary.osvrClientGetViewerPose(displayConfig, FIRST_VIEWER, hmdPose.getPointer()); - VRinput.updateControllerStates(); - hmdPose.read(); - } - - @Override - public Matrix4f getHMDMatrixProjectionLeftEye(Camera cam) { - if( eyeLeftInfo == null ) return cam.getProjectionMatrix(); - if( eyeMatrix[EYE_LEFT] == null ) { - FloatBuffer tfb = FloatBuffer.allocate(16); - 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].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(2), tfb.get(6), tfb.get(10), tfb.get(14), - tfb.get(3), tfb.get(7), tfb.get(11), tfb.get(15)); - } - return eyeMatrix[EYE_LEFT]; - } - - @Override - public Matrix4f getHMDMatrixProjectionRightEye(Camera cam) { - if( eyeRightInfo == null ) return cam.getProjectionMatrix(); - if( eyeMatrix[EYE_RIGHT] == null ) { - FloatBuffer tfb = FloatBuffer.allocate(16); - 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].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(2), tfb.get(6), tfb.get(10), tfb.get(14), - tfb.get(3), tfb.get(7), tfb.get(11), tfb.get(15)); - } - return eyeMatrix[EYE_RIGHT]; - } - - @Override - public Vector3f getHMDVectorPoseLeftEye() { - if( hmdPoseLeftEyeVec == null ) { - hmdPoseLeftEyeVec = new Vector3f(); - hmdPoseLeftEyeVec.x = 0.065f * -0.5f; - if( flipEyes == false ) hmdPoseLeftEyeVec.x *= -1f; // it seems these need flipping - } - return hmdPoseLeftEyeVec; - } - - @Override - public Vector3f getHMDVectorPoseRightEye() { - if( hmdPoseRightEyeVec == null ) { - hmdPoseRightEyeVec = new Vector3f(); - hmdPoseRightEyeVec.x = 0.065f * 0.5f; - if( flipEyes == false ) hmdPoseRightEyeVec.x *= -1f; // it seems these need flipping - } - return hmdPoseRightEyeVec; - } - - @Override - public Vector3f getSeatedToAbsolutePosition() { - return Vector3f.ZERO; - } - - @Override - public Matrix4f getHMDMatrixPoseLeftEye() { - // not actually used internally... - /*if( hmdPoseLeftEye != null ) { - return hmdPoseLeftEye; - } else { - FloatBuffer mat = FloatBuffer.allocate(16); - OsvrDisplayLibrary.osvrClientGetViewerEyeViewMatrixf(displayConfig, FIRST_VIEWER, (byte)EYE_LEFT, - (short)(OsvrMatrixConventionsLibrary.OSVR_MatrixVectorFlags.OSVR_MATRIX_COLVECTORS | - OsvrMatrixConventionsLibrary.OSVR_MatrixOrderingFlags.OSVR_MATRIX_COLMAJOR), tempfb); - hmdPoseLeftEye = new Matrix4f(tempfb.array()); - return hmdPoseLeftEye; - }*/ - return null; - } - - @Override - public Matrix4f getHMDMatrixPoseRightEye() { - // not actually used internally... - /*if( hmdPoseRightEye != null ) { - return hmdPoseRightEye; - } else { - OsvrDisplayLibrary.osvrClientGetViewerEyeViewMatrixf(displayConfig, FIRST_VIEWER, (byte)EYE_RIGHT, - (short)(OsvrMatrixConventionsLibrary.OSVR_MatrixVectorFlags.OSVR_MATRIX_COLVECTORS | - OsvrMatrixConventionsLibrary.OSVR_MatrixOrderingFlags.OSVR_MATRIX_COLMAJOR), tempfb); - hmdPoseRightEye = new Matrix4f(tempfb.array()); - return hmdPoseRightEye; - }*/ - return null; - } - - @Override - public HmdType getType() { - return HmdType.OSVR; - } -} +/* + +https://github.com/sensics/OSVR-RenderManager/blob/master/examples/RenderManagerOpenGLCAPIExample.cpp + +- JVM crashes often.. placing breakpoints during initialization clears it up most of the time (WHY!?) + - OSVR is just unstable.. any way to improve things? +- render manager looks good, but left eye seems stretched + + */ +package com.jme3.input.vr; + +import com.jme3.app.VREnvironment; +import com.jme3.math.Matrix4f; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; +import com.jme3.renderer.Camera; +import com.jme3.system.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.NativeSizeByReference; +import com.sun.jna.Pointer; +import com.sun.jna.ptr.PointerByReference; +import java.nio.FloatBuffer; +import java.util.logging.Logger; + +/** + * A class that wraps an OSVR system. + * @author reden - phr00t - https://github.com/phr00t + * @author Julien Seinturier - (c) 2016 - JOrigin project - http:/www.jorigin.org + */ +public class OSVR implements VRAPI { + + private static final Logger logger = Logger.getLogger(OSVR.class.getName()); + + /** + * The first viewer index. + */ + public static final int FIRST_VIEWER = 0; + + /** + * The left eye index. + */ + public static final int EYE_LEFT = 0; + + /** + * The right eye index. + */ + public static final int EYE_RIGHT = 1; + + /** + * The size of the left eye. + */ + public static final NativeSize EYE_LEFT_SIZE = new NativeSize(EYE_LEFT); + + /** + * The size of the right eye. + */ + public static final NativeSize EYE_RIGHT_SIZE = new NativeSize(EYE_RIGHT); + + /** + * The default J String. + */ + public static byte[] defaultJString = { 'j', (byte)0 }; + + /** + * The default OpenGL String. + */ + public static byte[] OpenGLString = { 'O', 'p', 'e', 'n', 'G', 'L', (byte)0 }; + + private final Matrix4f[] eyeMatrix = new Matrix4f[2]; + + private PointerByReference grabRM; + private PointerByReference grabRMOGL; + private PointerByReference grabRIC; + + OSVR_RenderParams.ByValue renderParams; + OsvrClientKitLibrary.OSVR_ClientContext context; + com.jme3.system.osvr.osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue graphicsLibrary; + Pointer renderManager, renderManagerOpenGL, renderInfoCollection, registerBufferState; + OSVRInput VRinput; + NativeSize numRenderInfo; + NativeSizeByReference grabNumInfo = new NativeSizeByReference(); + OSVR_RenderInfoOpenGL.ByValue eyeLeftInfo, eyeRightInfo; + Matrix4f hmdPoseLeftEye; + Matrix4f hmdPoseRightEye; + Vector3f hmdPoseLeftEyeVec, hmdPoseRightEyeVec, hmdSeatToStand; + OSVR_DisplayConfig displayConfig; + OSVR_Pose3 hmdPose = new OSVR_Pose3(); + Vector3f storePos = new Vector3f(); + Quaternion storeRot = new Quaternion(); + PointerByReference presentState = new PointerByReference(); + OSVR_OpenResultsOpenGL openResults = new OSVR_OpenResultsOpenGL(); + + long glfwContext; + long renderManagerContext; + long wglGLFW; + long wglRM; + + boolean initSuccess = false; + boolean flipEyes = false; + + private VREnvironment environment = null; + + /** + * Create a new OSVR system attached to the given {@link VREnvironment VR environment}. + * @param environment the {@link VREnvironment VR environment} to which the input is attached. + */ + public OSVR(VREnvironment environment){ + this.environment = environment; + } + + /** + * Access to the underlying OSVR structures. + * @param leftView the left viewport. + * @param rightView the right viewport. + * @param leftBuffer the left buffer. + * @param rightBuffer the right buffer. + * @return true if the structure are accessible and false otherwise. + */ + public boolean handleRenderBufferPresent(OSVR_ViewportDescription.ByValue leftView, OSVR_ViewportDescription.ByValue rightView, + OSVR_RenderBufferOpenGL.ByValue leftBuffer, OSVR_RenderBufferOpenGL.ByValue rightBuffer) { + if( eyeLeftInfo == null || eyeRightInfo == null ) return false; + byte retval; + OsvrRenderManagerOpenGLLibrary.osvrRenderManagerStartPresentRenderBuffers(presentState); + getEyeInfo(); + OsvrRenderManagerOpenGLLibrary.osvrRenderManagerPresentRenderBufferOpenGL(presentState.getValue(), leftBuffer, eyeLeftInfo, leftView); + OsvrRenderManagerOpenGLLibrary.osvrRenderManagerPresentRenderBufferOpenGL(presentState.getValue(), rightBuffer, eyeRightInfo, rightView); + retval = OsvrRenderManagerOpenGLLibrary.osvrRenderManagerFinishPresentRenderBuffers(renderManager, presentState.getValue(), renderParams, (byte)0); + return retval == 0; // only check the last error, since if something errored above, the last call won't work & all calls will log to syserr + } + + + + @Override + public boolean initialize() { + + logger.config("Initialize OSVR system."); + + hmdPose.setAutoSynch(false); + context = OsvrClientKitLibrary.osvrClientInit(defaultJString, 0); + VRinput = new OSVRInput(environment); + initSuccess = context != null && VRinput.init(); + if( initSuccess ) { + PointerByReference grabDisplay = new PointerByReference(); + byte retval = OsvrDisplayLibrary.osvrClientGetDisplay(context, grabDisplay); + if( retval != 0 ) { + System.out.println("OSVR Get Display Error: " + retval); + initSuccess = false; + return false; + } + displayConfig = new OSVR_DisplayConfig(grabDisplay.getValue()); + System.out.println("Waiting for the display to fully start up, including receiving initial pose update..."); + int i = 400; + while (OsvrDisplayLibrary.osvrClientCheckDisplayStartup(displayConfig) != 0) { + if( i-- < 0 ) { + System.out.println("Couldn't get display startup update in time, continuing anyway..."); + break; + } + OsvrClientKitLibrary.osvrClientUpdate(context); + try { + Thread.sleep(5); + } catch(Exception e) { } + } + System.out.println("OK, display startup status is good!"); + } + return initSuccess; + } + + + /** + * Grab the current GLFW context. + */ + public void grabGLFWContext() { + // get current conext + wglGLFW = org.lwjgl.opengl.WGL.wglGetCurrentContext(); + glfwContext = org.lwjgl.glfw.GLFW.glfwGetCurrentContext(); + } + + /** + * Enable context sharing. + * @return true if the context is successfully shared and false otherwise. + */ + public boolean shareContext() { + if( org.lwjgl.opengl.WGL.wglShareLists(wglRM, wglGLFW)) { + System.out.println("Context sharing success!"); + return true; + } else { + System.out.println("Context sharing problem..."); + return false; + } + } + + @Override + public boolean initVRCompositor(boolean allowed) { + if( !allowed || renderManager != null ) return false; + grabGLFWContext(); + graphicsLibrary = new com.jme3.system.osvr.osvrrendermanageropengl.OSVR_GraphicsLibraryOpenGL.ByValue(); + graphicsLibrary.toolkit = null; + graphicsLibrary.setAutoSynch(false); + grabRM = new PointerByReference(); grabRMOGL = new PointerByReference(); + byte retval = OsvrRenderManagerOpenGLLibrary.osvrCreateRenderManagerOpenGL(context, OpenGLString, graphicsLibrary, grabRM, grabRMOGL); + if( retval == 0 ) { + renderManager = grabRM.getValue(); renderManagerOpenGL = grabRMOGL.getValue(); + if( renderManager == null || renderManagerOpenGL == null ) { + System.out.println("Render Manager Created NULL, error!"); + return false; + } + openResults.setAutoSynch(false); + retval = OsvrRenderManagerOpenGLLibrary.osvrRenderManagerOpenDisplayOpenGL(renderManager, openResults); + if( retval == 0 ) { + wglRM = org.lwjgl.opengl.WGL.wglGetCurrentContext(); + renderManagerContext = org.lwjgl.glfw.GLFW.glfwGetCurrentContext(); + shareContext(); + OsvrClientKitLibrary.osvrClientUpdate(context); + renderParams = new OSVR_RenderParams.ByValue(); + renderParams.setAutoSynch(false); + OsvrRenderManagerOpenGLLibrary.osvrRenderManagerGetDefaultRenderParams(renderParams); + grabRIC = new PointerByReference(); + retval = OsvrRenderManagerOpenGLLibrary.osvrRenderManagerGetRenderInfoCollection(renderManager, renderParams, grabRIC); + if( retval == 0 ) { + renderInfoCollection = grabRIC.getValue(); + OsvrRenderManagerOpenGLLibrary.osvrRenderManagerGetNumRenderInfoInCollection(renderInfoCollection, grabNumInfo); + numRenderInfo = grabNumInfo.getValue(); + eyeLeftInfo = new OSVR_RenderInfoOpenGL.ByValue(); + eyeRightInfo = new OSVR_RenderInfoOpenGL.ByValue(); + eyeLeftInfo.setAutoSynch(false); + eyeRightInfo.setAutoSynch(false); + return true; + } + OsvrRenderManagerOpenGLLibrary.osvrDestroyRenderManager(renderManager); + System.out.println("OSVR Render Manager Info Collection Error: " + retval); + return false; + } + OsvrRenderManagerOpenGLLibrary.osvrDestroyRenderManager(renderManager); + System.out.println("OSVR Open Render Manager Display Error: " + retval); + return false; + } + System.out.println("OSVR Create Render Manager Error: " + retval); + return false; + } + + @Override + public OsvrClientKitLibrary.OSVR_ClientContext getVRSystem() { + return context; + } + + @Override + public Pointer getCompositor() { + return renderManager; + } + + @Override + public String getName() { + return "OSVR"; + } + + @Override + public VRInputAPI getVRinput() { + return VRinput; + } + + @Override + public void setFlipEyes(boolean set) { + flipEyes = set; + } + + @Override + public void printLatencyInfoToConsole(boolean set) { + + } + + @Override + public int getDisplayFrequency() { + return 60; //debug display frequency + } + + @Override + public void destroy() { + if( renderManager != null ) OsvrRenderManagerOpenGLLibrary.osvrDestroyRenderManager(renderManager); + if( displayConfig != null ) OsvrDisplayLibrary.osvrClientFreeDisplay(displayConfig); + } + + @Override + public boolean isInitialized() { + return initSuccess; + } + + @Override + public void reset() { + // TODO: no native OSVR reset function + // may need to take current position and negate it from future values + } + + @Override + public void getRenderSize(Vector2f store) { + if( eyeLeftInfo == null || eyeLeftInfo.viewport.width == 0.0 ) { + store.x = 1280f; store.y = 720f; + } else { + store.x = (float)eyeLeftInfo.viewport.width; + store.y = (float)eyeLeftInfo.viewport.height; + } + } + + /** + * Read and update the eye info from the underlying OSVR system. + */ + public void getEyeInfo() { + OsvrRenderManagerOpenGLLibrary.osvrRenderManagerGetRenderInfoFromCollectionOpenGL(renderInfoCollection, EYE_LEFT_SIZE, eyeLeftInfo); + OsvrRenderManagerOpenGLLibrary.osvrRenderManagerGetRenderInfoFromCollectionOpenGL(renderInfoCollection, EYE_RIGHT_SIZE, eyeRightInfo); + eyeLeftInfo.read(); eyeRightInfo.read(); + } +/* + @Override + public float getFOV(int dir) { + return 105f; //default FOV + } +*/ + @Override + public float getInterpupillaryDistance() { + return 0.065f; //default IPD + } + + @Override + public Quaternion getOrientation() { + storeRot.set((float)hmdPose.rotation.data[1], + (float)hmdPose.rotation.data[2], + (float)hmdPose.rotation.data[3], + (float)hmdPose.rotation.data[0]); + if( storeRot.equals(Quaternion.ZERO) ) storeRot.set(Quaternion.DIRECTION_Z); + return storeRot; + } + + @Override + public Vector3f getPosition() { + storePos.x = (float)-hmdPose.translation.data[0]; + storePos.y = (float)hmdPose.translation.data[1]; + storePos.z = (float)-hmdPose.translation.data[2]; + return storePos; + } + + @Override + public void getPositionAndOrientation(Vector3f storePos, Quaternion storeRot) { + storePos.x = (float)-hmdPose.translation.data[0]; + storePos.y = (float)hmdPose.translation.data[1]; + storePos.z = (float)-hmdPose.translation.data[2]; + storeRot.set((float)hmdPose.rotation.data[1], + (float)hmdPose.rotation.data[2], + (float)hmdPose.rotation.data[3], + (float)hmdPose.rotation.data[0]); + if( storeRot.equals(Quaternion.ZERO) ) storeRot.set(Quaternion.DIRECTION_Z); + } + + @Override + public void updatePose() { + if( context == null || displayConfig == null ) return; + OsvrClientKitLibrary.osvrClientUpdate(context); + OsvrDisplayLibrary.osvrClientGetViewerPose(displayConfig, FIRST_VIEWER, hmdPose.getPointer()); + VRinput.updateControllerStates(); + hmdPose.read(); + } + + @Override + public Matrix4f getHMDMatrixProjectionLeftEye(Camera cam) { + if( eyeLeftInfo == null ) return cam.getProjectionMatrix(); + if( eyeMatrix[EYE_LEFT] == null ) { + FloatBuffer tfb = FloatBuffer.allocate(16); + 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].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(2), tfb.get(6), tfb.get(10), tfb.get(14), + tfb.get(3), tfb.get(7), tfb.get(11), tfb.get(15)); + } + return eyeMatrix[EYE_LEFT]; + } + + @Override + public Matrix4f getHMDMatrixProjectionRightEye(Camera cam) { + if( eyeRightInfo == null ) return cam.getProjectionMatrix(); + if( eyeMatrix[EYE_RIGHT] == null ) { + FloatBuffer tfb = FloatBuffer.allocate(16); + 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].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(2), tfb.get(6), tfb.get(10), tfb.get(14), + tfb.get(3), tfb.get(7), tfb.get(11), tfb.get(15)); + } + return eyeMatrix[EYE_RIGHT]; + } + + @Override + public Vector3f getHMDVectorPoseLeftEye() { + if( hmdPoseLeftEyeVec == null ) { + hmdPoseLeftEyeVec = new Vector3f(); + hmdPoseLeftEyeVec.x = 0.065f * -0.5f; + if( flipEyes == false ) hmdPoseLeftEyeVec.x *= -1f; // it seems these need flipping + } + return hmdPoseLeftEyeVec; + } + + @Override + public Vector3f getHMDVectorPoseRightEye() { + if( hmdPoseRightEyeVec == null ) { + hmdPoseRightEyeVec = new Vector3f(); + hmdPoseRightEyeVec.x = 0.065f * 0.5f; + if( flipEyes == false ) hmdPoseRightEyeVec.x *= -1f; // it seems these need flipping + } + return hmdPoseRightEyeVec; + } + + @Override + public Vector3f getSeatedToAbsolutePosition() { + return Vector3f.ZERO; + } + + @Override + public Matrix4f getHMDMatrixPoseLeftEye() { + // not actually used internally... + /*if( hmdPoseLeftEye != null ) { + return hmdPoseLeftEye; + } else { + FloatBuffer mat = FloatBuffer.allocate(16); + OsvrDisplayLibrary.osvrClientGetViewerEyeViewMatrixf(displayConfig, FIRST_VIEWER, (byte)EYE_LEFT, + (short)(OsvrMatrixConventionsLibrary.OSVR_MatrixVectorFlags.OSVR_MATRIX_COLVECTORS | + OsvrMatrixConventionsLibrary.OSVR_MatrixOrderingFlags.OSVR_MATRIX_COLMAJOR), tempfb); + hmdPoseLeftEye = new Matrix4f(tempfb.array()); + return hmdPoseLeftEye; + }*/ + return null; + } + + @Override + public Matrix4f getHMDMatrixPoseRightEye() { + // not actually used internally... + /*if( hmdPoseRightEye != null ) { + return hmdPoseRightEye; + } else { + OsvrDisplayLibrary.osvrClientGetViewerEyeViewMatrixf(displayConfig, FIRST_VIEWER, (byte)EYE_RIGHT, + (short)(OsvrMatrixConventionsLibrary.OSVR_MatrixVectorFlags.OSVR_MATRIX_COLVECTORS | + OsvrMatrixConventionsLibrary.OSVR_MatrixOrderingFlags.OSVR_MATRIX_COLMAJOR), tempfb); + hmdPoseRightEye = new Matrix4f(tempfb.array()); + return hmdPoseRightEye; + }*/ + return null; + } + + @Override + public HmdType getType() { + return HmdType.OSVR; + } +} diff --git a/jme3-vr/src/main/java/com/jme3/util/VRViewManagerOSVR.java b/jme3-vr/src/main/java/com/jme3/util/VRViewManagerOSVR.java index e3d85406e..2019e6210 100644 --- a/jme3-vr/src/main/java/com/jme3/util/VRViewManagerOSVR.java +++ b/jme3-vr/src/main/java/com/jme3/util/VRViewManagerOSVR.java @@ -50,18 +50,6 @@ 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; @@ -73,15 +61,10 @@ public class VRViewManagerOSVR extends AbstractVRViewManager{ 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(); @@ -96,42 +79,6 @@ public class VRViewManagerOSVR extends AbstractVRViewManager{ 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. @@ -162,42 +109,6 @@ public class VRViewManagerOSVR extends AbstractVRViewManager{ 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. */ @@ -442,8 +353,8 @@ public class VRViewManagerOSVR extends AbstractVRViewManager{ // other adjustments size.x *= xMult; - size.x *= resMult; - size.y *= resMult; + size.x *= getResolutionMuliplier(); + size.y *= getResolutionMuliplier(); if( cam.getWidth() != size.x || cam.getHeight() != size.y ){ cam.resize((int)size.x, (int)size.y, false); @@ -469,10 +380,10 @@ public class VRViewManagerOSVR extends AbstractVRViewManager{ 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(); + 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 @@ -587,7 +498,7 @@ public class VRViewManagerOSVR extends AbstractVRViewManager{ if( obsPosition != null ){ finalPosition.addLocal(obsPosition); } - finalPosition.y += heightAdjustment; + finalPosition.y += getHeightAdjustment(); cam.setFrame(finalPosition, finalRotation); } @@ -595,7 +506,7 @@ public class VRViewManagerOSVR extends AbstractVRViewManager{ * Handles moving filters from the main view to each eye */ public void moveScreenProcessingToEyes() { - if( rightViewport == null ){ + if( getRightViewPort() == null ){ return; } @@ -617,7 +528,7 @@ public class VRViewManagerOSVR extends AbstractVRViewManager{ * @param sourceViewport the {@link ViewPort viewport} that contains the processors to use. */ public void syncScreenProcessing(ViewPort sourceViewport) { - if( rightViewport == null ){ + if( getRightViewPort() == null ){ return; } @@ -631,13 +542,13 @@ public class VRViewManagerOSVR extends AbstractVRViewManager{ // clear out all filters & processors, to start from scratch rightPostProcessor.removeAllFilters(); leftPostProcessor.removeAllFilters(); - leftViewport.clearProcessors(); - rightViewport.clearProcessors(); + getLeftViewPort().clearProcessors(); + getRightViewPort().clearProcessors(); // if we have no processors to sync, don't add the FilterPostProcessor if( sourceViewport.getProcessors().isEmpty() ) return; // add post processors we just made, which are empty - leftViewport.addProcessor(leftPostProcessor); - rightViewport.addProcessor(rightPostProcessor); + getLeftViewPort().addProcessor(leftPostProcessor); + getRightViewPort().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()) { @@ -670,8 +581,8 @@ public class VRViewManagerOSVR extends AbstractVRViewManager{ VRDirectionalLightShadowRenderer dlsr = (VRDirectionalLightShadowRenderer) sceneProcessor; VRDirectionalLightShadowRenderer dlsrRight = dlsr.clone(); dlsrRight.setLight(dlsr.getLight()); - rightViewport.getProcessors().add(0, dlsrRight); - leftViewport.getProcessors().add(0, sceneProcessor); + getRightViewPort().getProcessors().add(0, dlsrRight); + getLeftViewPort().getProcessors().add(0, sceneProcessor); } } // make sure each has a translucent filter renderer @@ -718,16 +629,16 @@ public class VRViewManagerOSVR extends AbstractVRViewManager{ //org.lwjgl.opengl.GL11.glEnable(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_SRGB); if( !environment.isInstanceRendering()) { - leftViewport = setupViewBuffers(leftCamera, LEFT_VIEW_NAME); + 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); + rightViewPort = setupViewBuffers(rightCamera, RIGHT_VIEW_NAME); } else { System.err.println("[VRViewManager] THIS CODE NEED CHANGES !!!"); - leftViewport = environment.getApplication().getViewPort(); + leftViewPort = environment.getApplication().getViewPort(); //leftViewport.attachScene(app.getRootNode()); rightCamera = leftCamera.clone(); if( environment.getVRHardware() != null ){ @@ -742,7 +653,7 @@ public class VRViewManagerOSVR extends AbstractVRViewManager{ } // setup gui - environment.getVRGUIManager().setupGui(leftCamera, rightCamera, leftViewport, rightViewport); + environment.getVRGUIManager().setupGui(leftCamera, rightCamera, getLeftViewPort(), getRightViewPort()); if( environment.getVRHardware() != null ) { // call these to cache the results internally