mirror of
https://github.com/MovingBlocks/Terasology
synced 2026-05-24 09:28:22 +00:00
Added jopenvrwrapper.
This commit is contained in:
parent
4b48a0ccf5
commit
ee3c9317e1
21 changed files with 715 additions and 0 deletions
|
|
@ -105,6 +105,7 @@ dependencies {
|
|||
compile group: 'org.lwjgl.lwjgl', name: 'lwjgl', version: LwjglVersion
|
||||
compile group: 'org.lwjgl.lwjgl', name: 'lwjgl_util', version: LwjglVersion
|
||||
compile group: 'java3d', name: 'vecmath', version: '1.3.1' // Note: Downgraded to this release until TeraMath ready
|
||||
compile "org.joml:joml:1.8.1"
|
||||
compile group: 'org.abego.treelayout', name: 'org.abego.treelayout.core', version: '1.0.3'
|
||||
compile group: 'com.miglayout', name: 'miglayout-core', version: '5.0'
|
||||
compile group: 'de.matthiasmann.twl', name: 'PNGDecoder', version: '1111'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
package openvrprovider;
|
||||
|
||||
import jopenvr.JOpenVRLibrary;
|
||||
import jopenvr.VRControllerState_t;
|
||||
|
||||
/* Interface intended to be front-facing to user for controller interaction. */
|
||||
public interface ControllerListener {
|
||||
public final int LEFT_CONTROLLER = 0;
|
||||
public final int RIGHT_CONTROLLER = 1;
|
||||
public static int k_EAxis_Trigger = 1;
|
||||
public static int k_EAxis_TouchPad = 0;
|
||||
public static long k_buttonTouchpad = (1L << JOpenVRLibrary.EVRButtonId.EVRButtonId_k_EButton_SteamVR_Touchpad);
|
||||
public static long k_buttonTrigger = (1L << JOpenVRLibrary.EVRButtonId.EVRButtonId_k_EButton_SteamVR_Trigger);
|
||||
public static long k_buttonAppMenu = (1L << JOpenVRLibrary.EVRButtonId.EVRButtonId_k_EButton_ApplicationMenu);
|
||||
public static long k_buttonGrip = (1L << JOpenVRLibrary.EVRButtonId.EVRButtonId_k_EButton_Grip);
|
||||
public static float triggerThreshold = .25f;
|
||||
|
||||
public void buttonStateChanged(VRControllerState_t stateBefore, VRControllerState_t stateAfter, int nController);
|
||||
// TODO: touch, axes
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package openvrprovider;
|
||||
|
||||
/* Mainly used to locate the OpenVR library on different platforms. */
|
||||
public class OSValidator {
|
||||
private static final String OS = System.getProperty("os.name").toLowerCase();
|
||||
private static final String arch = System.getProperty("os.arch");
|
||||
private static final String userDir = System.getProperty("user.dir");
|
||||
|
||||
public static boolean isWin64() {
|
||||
|
||||
return (OS.indexOf("win") >= 0 && arch.contains("64"));
|
||||
|
||||
}
|
||||
|
||||
public static boolean isWin32() {
|
||||
|
||||
return (OS.indexOf("win") >= 0 && arch.contains("32"));
|
||||
|
||||
}
|
||||
|
||||
public static boolean isLinux64() {
|
||||
|
||||
return (OS.indexOf("linux") >= 0 && arch.contains("64"));
|
||||
|
||||
}
|
||||
|
||||
public static boolean isLinux32() {
|
||||
|
||||
return (OS.indexOf("linux") >= 0 && arch.contains("32"));
|
||||
|
||||
}
|
||||
|
||||
public static boolean isMac() {
|
||||
|
||||
return (OS.indexOf("mac") >= 0);
|
||||
|
||||
}
|
||||
|
||||
public static String getOsString() {
|
||||
if (isWin64())
|
||||
return new String("win32-x86-64");
|
||||
else if (isWin32())
|
||||
return new String("win32-x86");
|
||||
else if (isLinux64())
|
||||
return new String("linux-x86-64");
|
||||
else if (isLinux32())
|
||||
return new String("linux-x86");
|
||||
else if (isMac())
|
||||
return new String("darwin");
|
||||
return new String("unknown");
|
||||
}
|
||||
|
||||
public static String getLibPath() {
|
||||
if (getOsString().contains("win"))
|
||||
return userDir + "\\openvr_natives\\" + getOsString();
|
||||
return userDir + "/openvr_natives/" + getOsString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,332 @@
|
|||
package openvrprovider;
|
||||
|
||||
import com.sun.jna.Memory;
|
||||
import com.sun.jna.NativeLibrary;
|
||||
import com.sun.jna.Pointer;
|
||||
import jopenvr.*;
|
||||
import jopenvr.JOpenVRLibrary.EVREventType;
|
||||
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static openvrprovider.ControllerListener.LEFT_CONTROLLER;
|
||||
import static openvrprovider.ControllerListener.RIGHT_CONTROLLER;
|
||||
|
||||
/* This class is designed to make all API calls to OpenVR, thereby insulating it from the user. If you're looking to get
|
||||
* some information from the headset/controllers you should probably look at OpenVRStereoRenderer, ControllerListener,
|
||||
* or OpenVRState
|
||||
* */
|
||||
public class OpenVRProvider {
|
||||
private static boolean initialized = false;
|
||||
private static VR_IVRSystem_FnTable vrsystem;
|
||||
private static VR_IVRCompositor_FnTable vrCompositor;
|
||||
private static VR_IVROverlay_FnTable vrOverlay;
|
||||
private static VR_IVRSettings_FnTable vrSettings;
|
||||
public OpenVRState vrState = new OpenVRState();
|
||||
private static int[] controllerDeviceIndex = new int[2];
|
||||
private static VRControllerState_t.ByReference[] inputStateRefernceArray = new VRControllerState_t.ByReference[2];
|
||||
private static VRControllerState_t[] controllerStateReference = new VRControllerState_t[2];
|
||||
private static IntBuffer hmdErrorStore;
|
||||
private static TrackedDevicePose_t.ByReference hmdTrackedDevicePoseReference;
|
||||
private static TrackedDevicePose_t[] hmdTrackedDevicePoses;
|
||||
// TextureIDs of framebuffers for each eye
|
||||
private float nearClip = 0.5f;
|
||||
private float farClip = 500.0f;
|
||||
private final static VRTextureBounds_t texBounds = new VRTextureBounds_t();
|
||||
public static Texture_t texType[] = new Texture_t[2];
|
||||
private static boolean[] controllerTracking = new boolean[2];
|
||||
//keyboard
|
||||
private static boolean keyboardShowing = false;
|
||||
private static boolean headIsTracking = false;
|
||||
|
||||
public boolean init() {
|
||||
try {
|
||||
if (!initializeOpenVRLibrary())
|
||||
return false;
|
||||
initializeJOpenVR();
|
||||
initOpenVRCompositor(true);
|
||||
initOpenVROverlay();
|
||||
initOpenVROSettings();
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
public void updateState()
|
||||
{
|
||||
if (!initialized)
|
||||
init();
|
||||
updatePose();
|
||||
pollControllers();
|
||||
pollInputEvents();
|
||||
}
|
||||
|
||||
private void pollControllers() {
|
||||
for (int c = 0; c < 2; c++) {
|
||||
if (controllerDeviceIndex[c] != -1) {
|
||||
vrsystem.GetControllerState.apply(controllerDeviceIndex[c], inputStateRefernceArray[c]);
|
||||
inputStateRefernceArray[c].read();
|
||||
controllerStateReference[c] = inputStateRefernceArray[c];
|
||||
vrState.updateControllerButtonState(controllerStateReference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean initializeOpenVRLibrary() throws Exception {
|
||||
if (initialized)
|
||||
return true;
|
||||
System.out.println("Adding OpenVR search path: " + OSValidator.getLibPath());
|
||||
NativeLibrary.addSearchPath("openvr_api", OSValidator.getLibPath());
|
||||
|
||||
if (jopenvr.JOpenVRLibrary.VR_IsHmdPresent() == 1) {
|
||||
System.out.println("VR Headset detected.");
|
||||
} else {
|
||||
System.out.println("VR Headset not detected.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public OpenVRProvider() {
|
||||
for (int c = 0; c < 2; c++) {
|
||||
controllerDeviceIndex[c] = -1;
|
||||
controllerStateReference[c] = new VRControllerState_t();
|
||||
inputStateRefernceArray[c] = new VRControllerState_t.ByReference();
|
||||
inputStateRefernceArray[c].setAutoRead(false);
|
||||
inputStateRefernceArray[c].setAutoWrite(false);
|
||||
inputStateRefernceArray[c].setAutoSynch(false);
|
||||
texType[c] = new Texture_t();
|
||||
}
|
||||
}
|
||||
|
||||
private static void initializeJOpenVR() throws Exception {
|
||||
hmdErrorStore = IntBuffer.allocate(1);
|
||||
vrsystem = null;
|
||||
JOpenVRLibrary.VR_InitInternal(hmdErrorStore, JOpenVRLibrary.EVRApplicationType.EVRApplicationType_VRApplication_Scene);
|
||||
if (hmdErrorStore.get(0) == 0) {
|
||||
// ok, try and get the vrsystem pointer..
|
||||
vrsystem = new VR_IVRSystem_FnTable(JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVRSystem_Version, hmdErrorStore));
|
||||
}
|
||||
if (vrsystem == null || hmdErrorStore.get(0) != 0) {
|
||||
throw new Exception(jopenvr.JOpenVRLibrary.VR_GetVRInitErrorAsEnglishDescription(hmdErrorStore.get(0)).getString(0));
|
||||
} else {
|
||||
|
||||
vrsystem.setAutoSynch(false);
|
||||
vrsystem.read();
|
||||
|
||||
System.out.println("OpenVR initialized & VR connected.");
|
||||
|
||||
hmdTrackedDevicePoseReference = new TrackedDevicePose_t.ByReference();
|
||||
hmdTrackedDevicePoses = (TrackedDevicePose_t[]) hmdTrackedDevicePoseReference.toArray(JOpenVRLibrary.k_unMaxTrackedDeviceCount);
|
||||
|
||||
// disable all this stuff which kills performance
|
||||
hmdTrackedDevicePoseReference.setAutoRead(false);
|
||||
hmdTrackedDevicePoseReference.setAutoWrite(false);
|
||||
hmdTrackedDevicePoseReference.setAutoSynch(false);
|
||||
for (int i = 0; i < JOpenVRLibrary.k_unMaxTrackedDeviceCount; i++) {
|
||||
hmdTrackedDevicePoses[i].setAutoRead(false);
|
||||
hmdTrackedDevicePoses[i].setAutoWrite(false);
|
||||
hmdTrackedDevicePoses[i].setAutoSynch(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// needed for in-game keyboard
|
||||
private static void initOpenVROverlay() throws Exception {
|
||||
vrOverlay = new VR_IVROverlay_FnTable(JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVROverlay_Version, hmdErrorStore));
|
||||
if (hmdErrorStore.get(0) == 0) {
|
||||
vrOverlay.setAutoSynch(false);
|
||||
vrOverlay.read();
|
||||
System.out.println("OpenVR Overlay initialized OK");
|
||||
} else {
|
||||
throw new Exception(jopenvr.JOpenVRLibrary.VR_GetVRInitErrorAsEnglishDescription(hmdErrorStore.get(0)).getString(0));
|
||||
}
|
||||
}
|
||||
|
||||
private static void initOpenVROSettings() throws Exception {
|
||||
vrSettings = new VR_IVRSettings_FnTable(JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVRSettings_Version, hmdErrorStore));
|
||||
if (hmdErrorStore.get(0) == 0) {
|
||||
vrSettings.setAutoSynch(false);
|
||||
vrSettings.read();
|
||||
System.out.println("OpenVR Settings initialized OK");
|
||||
} else {
|
||||
throw new Exception(jopenvr.JOpenVRLibrary.VR_GetVRInitErrorAsEnglishDescription(hmdErrorStore.get(0)).getString(0));
|
||||
}
|
||||
}
|
||||
|
||||
private static void initOpenVRCompositor(boolean set) throws Exception {
|
||||
if (set && vrsystem != null) {
|
||||
vrCompositor = new VR_IVRCompositor_FnTable(JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVRCompositor_Version, hmdErrorStore));
|
||||
if (hmdErrorStore.get(0) == 0) {
|
||||
System.out.println("OpenVR Compositor initialized OK.");
|
||||
vrCompositor.setAutoSynch(false);
|
||||
vrCompositor.read();
|
||||
vrCompositor.SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding);
|
||||
} else {
|
||||
throw new Exception(jopenvr.JOpenVRLibrary.VR_GetVRInitErrorAsEnglishDescription(hmdErrorStore.get(0)).getString(0));
|
||||
}
|
||||
}
|
||||
if (vrCompositor == null) {
|
||||
System.out.println("Skipping VR Compositor...");
|
||||
}
|
||||
|
||||
// left eye
|
||||
texBounds.uMax = 1f;
|
||||
texBounds.uMin = 0f;
|
||||
texBounds.vMax = 1f;
|
||||
texBounds.vMin = 0f;
|
||||
texBounds.setAutoSynch(false);
|
||||
texBounds.setAutoRead(false);
|
||||
texBounds.setAutoWrite(false);
|
||||
texBounds.write();
|
||||
// texture type
|
||||
for (int nEye = 0; nEye < 2; nEye++) {
|
||||
texType[0].eColorSpace = JOpenVRLibrary.EColorSpace.EColorSpace_ColorSpace_Gamma;
|
||||
texType[0].eType = JOpenVRLibrary.EGraphicsAPIConvention.EGraphicsAPIConvention_API_OpenGL;
|
||||
texType[0].setAutoSynch(false);
|
||||
texType[0].setAutoRead(false);
|
||||
texType[0].setAutoWrite(false);
|
||||
texType[0].handle = -1;
|
||||
texType[0].write();
|
||||
|
||||
}
|
||||
System.out.println("OpenVR Compositor initialized OK.");
|
||||
|
||||
}
|
||||
|
||||
public static boolean setKeyboardOverlayShowing(boolean showingState) {
|
||||
int ret = 1;
|
||||
if (showingState) {
|
||||
Pointer pointer = new Memory(3);
|
||||
pointer.setString(0, "mc");
|
||||
Pointer empty = new Memory(1);
|
||||
empty.setString(0, "");
|
||||
|
||||
ret = vrOverlay.ShowKeyboard.apply(0, 0, pointer, 256, empty, (byte) 1, 0);
|
||||
|
||||
keyboardShowing = 0 == ret; //0 = no error, > 0 see EVROverlayError
|
||||
|
||||
|
||||
if (ret != 0) {
|
||||
System.out.println("VR Overlay Error: " + vrOverlay.GetOverlayErrorNameFromEnum.apply(ret).getString(0));
|
||||
}
|
||||
|
||||
} else {
|
||||
try {
|
||||
vrOverlay.HideKeyboard.apply();
|
||||
} catch (Error e) {
|
||||
}
|
||||
keyboardShowing = false;
|
||||
}
|
||||
|
||||
return keyboardShowing;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (this.initialized) {
|
||||
JOpenVRLibrary.VR_ShutdownInternal();
|
||||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void findControllerDevices() {
|
||||
controllerDeviceIndex[RIGHT_CONTROLLER] = -1;
|
||||
controllerDeviceIndex[LEFT_CONTROLLER] = -1;
|
||||
|
||||
controllerDeviceIndex[RIGHT_CONTROLLER] = vrsystem.GetTrackedDeviceIndexForControllerRole.apply(JOpenVRLibrary.ETrackedControllerRole.ETrackedControllerRole_TrackedControllerRole_LeftHand);
|
||||
controllerDeviceIndex[LEFT_CONTROLLER] = vrsystem.GetTrackedDeviceIndexForControllerRole.apply(JOpenVRLibrary.ETrackedControllerRole.ETrackedControllerRole_TrackedControllerRole_RightHand);
|
||||
}
|
||||
|
||||
//jrbuda:: oh hello there you are.
|
||||
private static void pollInputEvents() {
|
||||
if (vrsystem == null) return;
|
||||
|
||||
jopenvr.VREvent_t event = new jopenvr.VREvent_t();
|
||||
|
||||
while (vrsystem.PollNextEvent.apply(event, event.size()) > 0) {
|
||||
|
||||
switch (event.eventType) {
|
||||
case EVREventType.EVREventType_VREvent_KeyboardClosed:
|
||||
//'huzzah'
|
||||
keyboardShowing = false;
|
||||
break;
|
||||
case EVREventType.EVREventType_VREvent_KeyboardCharInput:
|
||||
byte[] inbytes = event.data.getPointer().getByteArray(0, 8);
|
||||
int len = 0;
|
||||
for (byte b : inbytes) {
|
||||
if (b > 0) len++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePose() {
|
||||
if (vrsystem == null || vrCompositor == null)
|
||||
return;
|
||||
|
||||
vrCompositor.WaitGetPoses.apply(hmdTrackedDevicePoseReference, JOpenVRLibrary.k_unMaxTrackedDeviceCount, null, 0);
|
||||
for (int nDevice = 0; nDevice < JOpenVRLibrary.k_unMaxTrackedDeviceCount; ++nDevice) {
|
||||
hmdTrackedDevicePoses[nDevice].read();
|
||||
}
|
||||
|
||||
if (hmdTrackedDevicePoses[JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd].bPoseIsValid != 0) {
|
||||
for (int nEye = 0; nEye < 2; nEye++) {
|
||||
HmdMatrix34_t matPose = vrsystem.GetEyeToHeadTransform.apply(nEye);
|
||||
vrState.setEyePoseWRTHead(matPose, nEye);
|
||||
HmdMatrix44_t matProjection = vrsystem.GetProjectionMatrix.apply(nEye, nearClip, farClip, JOpenVRLibrary.EGraphicsAPIConvention.EGraphicsAPIConvention_API_OpenGL);
|
||||
vrState.setProjectionMatrix(matProjection, nEye);
|
||||
}
|
||||
vrState.setHeadPose(hmdTrackedDevicePoses[JOpenVRLibrary.k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking);
|
||||
headIsTracking = true;
|
||||
} else {
|
||||
headIsTracking = false;
|
||||
}
|
||||
|
||||
findControllerDevices();
|
||||
|
||||
for (int c = 0; c < 2; c++) {
|
||||
if (controllerDeviceIndex[c] != -1) {
|
||||
controllerTracking[c] = true;
|
||||
vrState.setControllerPose(hmdTrackedDevicePoses[controllerDeviceIndex[c]].mDeviceToAbsoluteTracking, c);
|
||||
} else {
|
||||
controllerTracking[c] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void triggerHapticPulse(int controller, int strength) {
|
||||
if (controllerDeviceIndex[controller] == -1)
|
||||
return;
|
||||
vrsystem.TriggerHapticPulse.apply(controllerDeviceIndex[controller], 0, (short) strength);
|
||||
}
|
||||
|
||||
public void submitFrame() {
|
||||
if (vrCompositor == null) return;
|
||||
if (vrCompositor.Submit == null) return;
|
||||
for (int nEye = 0; nEye < 2; nEye++) {
|
||||
int ret = vrCompositor.Submit.apply(
|
||||
nEye,
|
||||
texType[nEye], null,
|
||||
JOpenVRLibrary.EVRSubmitFlags.EVRSubmitFlags_Submit_Default);
|
||||
}
|
||||
if (vrCompositor.PostPresentHandoff != null)
|
||||
vrCompositor.PostPresentHandoff.apply();
|
||||
}
|
||||
|
||||
public void setNearClip(float _nearClip) {
|
||||
nearClip = _nearClip;
|
||||
}
|
||||
|
||||
public void setFarClip(float _farClip) {
|
||||
farClip = _farClip;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package openvrprovider;
|
||||
|
||||
import jopenvr.*;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/* Contains all of the information that the user will need from OpenVR without using any OpenVR data structures. The
|
||||
OpenVRProvider automatically updates this.
|
||||
*/
|
||||
public class OpenVRState {
|
||||
public static int LEFT_EYE = JOpenVRLibrary.EVREye.EVREye_Eye_Left;
|
||||
public static int RIGHT_EYE = JOpenVRLibrary.EVREye.EVREye_Eye_Right;
|
||||
|
||||
private List<ControllerListener> controllerListeners = new ArrayList<>();
|
||||
|
||||
public void addControllerListener(ControllerListener toAdd) {
|
||||
controllerListeners.add(toAdd);
|
||||
}
|
||||
|
||||
// In the head frame
|
||||
private Matrix4f[] eyePoses = new Matrix4f[2];
|
||||
private Matrix4f[] projectionMatrices = new Matrix4f[2];
|
||||
|
||||
// In the tracking system intertial frame
|
||||
private Matrix4f headPose = new Matrix4f(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
|
||||
// Controllers
|
||||
private static Matrix4f[] controllerPose = new Matrix4f[2];
|
||||
private static VRControllerState_t[] lastControllerState = new VRControllerState_t[2];
|
||||
|
||||
OpenVRState() {
|
||||
for (int c = 0; c < 2; c++) {
|
||||
lastControllerState[c] = new VRControllerState_t();
|
||||
controllerPose[c] = new Matrix4f(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
eyePoses[c] = new Matrix4f(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
projectionMatrices[c] = new Matrix4f(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
lastControllerState[c].rAxis[i] = new VRControllerAxis_t();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setHeadPose(HmdMatrix34_t inputPose) {
|
||||
OpenVRUtil.setSteamVRMatrix3ToMatrix4f(inputPose, headPose);
|
||||
}
|
||||
|
||||
public void setEyePoseWRTHead(HmdMatrix34_t inputPose, int nIndex) {
|
||||
OpenVRUtil.setSteamVRMatrix3ToMatrix4f(inputPose, eyePoses[nIndex]);
|
||||
}
|
||||
|
||||
public void setControllerPose(HmdMatrix34_t inputPose, int nIndex) {
|
||||
OpenVRUtil.setSteamVRMatrix3ToMatrix4f(inputPose, controllerPose[nIndex]);
|
||||
}
|
||||
|
||||
public Matrix4f getEyePose(int nEye) {
|
||||
Matrix4f matrixReturn = new Matrix4f(headPose);
|
||||
matrixReturn.mul(eyePoses[nEye]);
|
||||
return matrixReturn;
|
||||
}
|
||||
|
||||
public Matrix4f getEyeProjectionMatrix(int nEye) {
|
||||
return new Matrix4f(projectionMatrices[nEye]);
|
||||
}
|
||||
|
||||
public void updateControllerButtonState(
|
||||
VRControllerState_t[] controllerStateReference) {
|
||||
for (int c = 0; c < 2; c++) //each controller
|
||||
{
|
||||
// store previous state
|
||||
if (lastControllerState[c].ulButtonPressed != controllerStateReference[c].ulButtonPressed) {
|
||||
for (ControllerListener listener : controllerListeners) {
|
||||
listener.buttonStateChanged(lastControllerState[c], controllerStateReference[c], c);
|
||||
}
|
||||
}
|
||||
lastControllerState[c].unPacketNum = controllerStateReference[c].unPacketNum;
|
||||
lastControllerState[c].ulButtonPressed = controllerStateReference[c].ulButtonPressed;
|
||||
lastControllerState[c].ulButtonTouched = controllerStateReference[c].ulButtonTouched;
|
||||
|
||||
for (int i = 0; i < 5; i++) //5 axes but only [0] and [1] is anything, trigger and touchpad
|
||||
{
|
||||
if (controllerStateReference[c].rAxis[i] != null) {
|
||||
lastControllerState[c].rAxis[i].x = controllerStateReference[c].rAxis[i].x;
|
||||
lastControllerState[c].rAxis[i].y = controllerStateReference[c].rAxis[i].y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setProjectionMatrix(
|
||||
HmdMatrix44_t inputPose,
|
||||
int nEye) {
|
||||
OpenVRUtil.setSteamVRMatrix44ToMatrix4f(inputPose, projectionMatrices[nEye]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package openvrprovider;
|
||||
|
||||
import jopenvr.JOpenVRLibrary;
|
||||
import org.lwjgl.opengl.EXTFramebufferObject;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import static org.lwjgl.opengl.EXTFramebufferObject.*;
|
||||
import static org.lwjgl.opengl.GL11.GL_DEPTH_COMPONENT;
|
||||
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
|
||||
|
||||
/* This class is designed to manage the framebuffers for the headset. */
|
||||
public class OpenVRStereoRenderer {
|
||||
public OpenVRProvider vrProvider;
|
||||
|
||||
// TextureIDs of framebuffers for each eye
|
||||
private int eyeTextureIDs[] = new int[2];
|
||||
private int eyeFBOIds[] = new int[2];
|
||||
|
||||
public OpenVRStereoRenderer(OpenVRProvider _vrProvider, int lwidth, int lheight) {
|
||||
vrProvider = _vrProvider;
|
||||
createRenderTexture(lwidth, lheight);
|
||||
}
|
||||
|
||||
public void deleteRenderTextures() {
|
||||
if (eyeTextureIDs[0] > 0) GL11.glDeleteTextures(eyeTextureIDs[0]);
|
||||
}
|
||||
|
||||
public void createRenderTexture(int lwidth, int lheight) {
|
||||
for (int nEye = 0; nEye < 2; nEye++) {
|
||||
eyeFBOIds[nEye] = glGenFramebuffersEXT();
|
||||
EXTFramebufferObject.glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, eyeFBOIds[nEye]);
|
||||
|
||||
//depth buffer
|
||||
int depthbuffer = glGenRenderbuffersEXT();
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthbuffer);
|
||||
|
||||
//allocate space for the renderbuffer
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, lwidth, lheight);
|
||||
|
||||
//attach depth buffer to fbo
|
||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthbuffer);
|
||||
|
||||
eyeTextureIDs[nEye] = GL11.glGenTextures();
|
||||
int boundTextureId = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
|
||||
GL11.glBindTexture(GL_TEXTURE_2D, eyeTextureIDs[nEye]);
|
||||
GL11.glEnable(GL_TEXTURE_2D);
|
||||
GL11.glTexParameterf(GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
|
||||
GL11.glTexParameterf(GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
|
||||
GL11.glTexImage2D(GL_TEXTURE_2D, 0, GL11.GL_RGBA8, lwidth, lheight, 0, GL11.GL_RGBA, GL11.GL_INT, (java.nio.ByteBuffer) null);
|
||||
GL11.glBindTexture(GL_TEXTURE_2D, boundTextureId);
|
||||
|
||||
//attach texture to the fbo
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, eyeTextureIDs[nEye], 0);
|
||||
|
||||
//check completeness
|
||||
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||
System.out.println("An error occured creating the frame buffer.");
|
||||
}
|
||||
|
||||
vrProvider.texType[nEye].handle = eyeTextureIDs[nEye];
|
||||
vrProvider.texType[nEye].eColorSpace = JOpenVRLibrary.EColorSpace.EColorSpace_ColorSpace_Gamma;
|
||||
vrProvider.texType[nEye].eType = JOpenVRLibrary.EGraphicsAPIConvention.EGraphicsAPIConvention_API_OpenGL;
|
||||
vrProvider.texType[nEye].write();
|
||||
}
|
||||
}
|
||||
|
||||
public int getTextureHandleForEyeFramebuffer(int nEye) {
|
||||
return eyeFBOIds[nEye];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
package openvrprovider;
|
||||
|
||||
import jopenvr.HmdMatrix34_t;
|
||||
import jopenvr.HmdMatrix44_t;
|
||||
import jopenvr.VRControllerState_t;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/* Utility functions that don't interact with the headset (conversions and the like) */
|
||||
public class OpenVRUtil {
|
||||
|
||||
private static final long SLEEP_PRECISION = TimeUnit.MILLISECONDS.toNanos(4);
|
||||
private static final long SPIN_YIELD_PRECISION = TimeUnit.MILLISECONDS.toNanos(2);
|
||||
|
||||
public static Matrix4f convertSteamVRMatrix3ToMatrix4f(HmdMatrix34_t hmdMatrix) {
|
||||
return new Matrix4f(
|
||||
hmdMatrix.m[0], hmdMatrix.m[4], hmdMatrix.m[8], 0,
|
||||
hmdMatrix.m[1], hmdMatrix.m[5], hmdMatrix.m[9], 0,
|
||||
hmdMatrix.m[2], hmdMatrix.m[6], hmdMatrix.m[10], 0,
|
||||
hmdMatrix.m[3], hmdMatrix.m[7], hmdMatrix.m[11], 1f
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix4f convertSteamVRMatrix44ToMatrix4f(HmdMatrix44_t hmdMatrix) {
|
||||
return new Matrix4f(
|
||||
hmdMatrix.m[0], hmdMatrix.m[4], hmdMatrix.m[8], hmdMatrix.m[12],
|
||||
hmdMatrix.m[1], hmdMatrix.m[5], hmdMatrix.m[9], hmdMatrix.m[13],
|
||||
hmdMatrix.m[2], hmdMatrix.m[6], hmdMatrix.m[10], hmdMatrix.m[14],
|
||||
hmdMatrix.m[3], hmdMatrix.m[7], hmdMatrix.m[11], hmdMatrix.m[15]
|
||||
);
|
||||
}
|
||||
|
||||
public static void setSteamVRMatrix3ToMatrix4f(HmdMatrix34_t hmdMatrix, Matrix4f matrixToSet) {
|
||||
matrixToSet.set(
|
||||
hmdMatrix.m[0], hmdMatrix.m[4], hmdMatrix.m[8], 0,
|
||||
hmdMatrix.m[1], hmdMatrix.m[5], hmdMatrix.m[9], 0,
|
||||
hmdMatrix.m[2], hmdMatrix.m[6], hmdMatrix.m[10], 0,
|
||||
hmdMatrix.m[3], hmdMatrix.m[7], hmdMatrix.m[11], 1f
|
||||
);
|
||||
}
|
||||
|
||||
public static void setSteamVRMatrix44ToMatrix4f(HmdMatrix44_t hmdMatrix, Matrix4f matrixToSet) {
|
||||
matrixToSet.set(
|
||||
hmdMatrix.m[0], hmdMatrix.m[4], hmdMatrix.m[8], hmdMatrix.m[12],
|
||||
hmdMatrix.m[1], hmdMatrix.m[5], hmdMatrix.m[9], hmdMatrix.m[13],
|
||||
hmdMatrix.m[2], hmdMatrix.m[6], hmdMatrix.m[10], hmdMatrix.m[14],
|
||||
hmdMatrix.m[3], hmdMatrix.m[7], hmdMatrix.m[11], hmdMatrix.m[15]
|
||||
);
|
||||
}
|
||||
|
||||
public static void sleepNanos(long nanoDuration) {
|
||||
final long end = System.nanoTime() + nanoDuration;
|
||||
long timeLeft = nanoDuration;
|
||||
do {
|
||||
try {
|
||||
if (timeLeft > SLEEP_PRECISION) {
|
||||
Thread.sleep(1);
|
||||
} else if (timeLeft > SPIN_YIELD_PRECISION) {
|
||||
Thread.sleep(0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
timeLeft = end - System.nanoTime();
|
||||
} while (timeLeft > 0);
|
||||
}
|
||||
|
||||
public static VRControllerState_t createZeroControllerState() {
|
||||
VRControllerState_t state = new VRControllerState_t();
|
||||
// controller not connected, clear state
|
||||
state.ulButtonPressed = 0;
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (state.rAxis[i] != null) {
|
||||
state.rAxis[i].x = 0.0f;
|
||||
state.rAxis[i].y = 0.0f;
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
public static boolean isPressed(long nButton, long uiButtonPressed) {
|
||||
return ((uiButtonPressed & nButton) > 0);
|
||||
}
|
||||
|
||||
public static boolean switchedDown(long nButton, long stateBefore, long stateAfter) {
|
||||
return (!isPressed(nButton, stateBefore) && isPressed(nButton, stateAfter));
|
||||
}
|
||||
|
||||
public static boolean switchedUp(long nButton, long stateBefore, long stateAfter) {
|
||||
return (isPressed(nButton, stateBefore) && !isPressed(nButton, stateAfter));
|
||||
}
|
||||
}
|
||||
BIN
openvr_natives/darwin/libopenvr_api.dylib
Normal file
BIN
openvr_natives/darwin/libopenvr_api.dylib
Normal file
Binary file not shown.
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.apple.xcode.dsym.libopenvr_api.dylib</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>dSYM</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.apple.xcode.dsym.libopenvr_api.dylib</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>dSYM</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
Binary file not shown.
BIN
openvr_natives/linux-x86-64/libopenvr_api.so
Normal file
BIN
openvr_natives/linux-x86-64/libopenvr_api.so
Normal file
Binary file not shown.
BIN
openvr_natives/linux-x86-64/libopenvr_api.so.dbg
Normal file
BIN
openvr_natives/linux-x86-64/libopenvr_api.so.dbg
Normal file
Binary file not shown.
BIN
openvr_natives/linux-x86/libopenvr_api.so
Normal file
BIN
openvr_natives/linux-x86/libopenvr_api.so
Normal file
Binary file not shown.
BIN
openvr_natives/linux-x86/libopenvr_api.so.dbg
Normal file
BIN
openvr_natives/linux-x86/libopenvr_api.so.dbg
Normal file
Binary file not shown.
BIN
openvr_natives/win32-x86-64/openvr_api.dll
Normal file
BIN
openvr_natives/win32-x86-64/openvr_api.dll
Normal file
Binary file not shown.
BIN
openvr_natives/win32-x86-64/openvr_api.pdb
Normal file
BIN
openvr_natives/win32-x86-64/openvr_api.pdb
Normal file
Binary file not shown.
BIN
openvr_natives/win32-x86/openvr_api.dll
Normal file
BIN
openvr_natives/win32-x86/openvr_api.dll
Normal file
Binary file not shown.
BIN
openvr_natives/win32-x86/openvr_api.pdb
Normal file
BIN
openvr_natives/win32-x86/openvr_api.pdb
Normal file
Binary file not shown.
Loading…
Reference in a new issue