Add initialization logic to OculusVR input

empirephoenix-patch-1
Campbell Suter 7 years ago
parent 7313abf58d
commit 3ac7888dc0
No known key found for this signature in database
GPG Key ID: 754A66CCF3F73C0F
  1. 253
      jme3-vr/src/main/java/com/jme3/input/vr/OculusVR.java

@ -8,10 +8,24 @@ package com.jme3.input.vr;
import com.jme3.app.VREnvironment;
import com.jme3.math.*;
import com.jme3.renderer.Camera;
import com.jme3.util.VRUtil;
import java.nio.IntBuffer;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.ovr.OVR.*;
import static org.lwjgl.ovr.OVRErrorCode.*;
import static org.lwjgl.system.MemoryUtil.*;
import static org.lwjgl.ovr.OVRUtil.ovr_Detect;
import org.lwjgl.BufferUtils;
import org.lwjgl.PointerBuffer;
import org.lwjgl.ovr.*;
/**
@ -26,6 +40,57 @@ public class OculusVR implements VRAPI {
private final VREnvironment environment;
private boolean initialized;
/**
* Pointer to the HMD object
*/
private long session;
/**
* Information about the VR session (should the app quit, is
* it visible or is the universal menu open, etc)
*/
private OVRSessionStatus sessionStatus;
/**
* HMD information, such as product name and manufacturer.
*/
private OVRHmdDesc hmdDesc;
/**
* The horizontal resolution of the HMD
*/
private int resolutionW;
/**
* The vertical resolution of the HMD
*/
private int resolutionH;
/**
* Field-of-view data for each eye (how many degrees from the
* center can the user see).
*/
private final OVRFovPort fovPorts[] = new OVRFovPort[2];
/**
* Data about each eye to be rendered - in particular, the
* offset from the center of the HMD to the eye.
*/
private final OVREyeRenderDesc eyeRenderDesc[] = new OVREyeRenderDesc[2];
/**
* Store the projections for each eye, so we don't have to malloc
* and recalculate them each frame.
*/
private final OVRMatrix4f[] projections = new OVRMatrix4f[2];
/**
* Store the poses for each eye.
*
* @see #getHMDMatrixPoseLeftEye()
*/
private final Matrix4f[] eyePoses = new Matrix4f[2];
public OculusVR(VREnvironment environment) {
this.environment = environment;
}
@ -42,23 +107,117 @@ public class OculusVR implements VRAPI {
@Override
public int getDisplayFrequency() {
throw new UnsupportedOperationException();
// TODO find correct frequency. I'm not sure
// if LibOVR has a way to do that, though.
return 60;
}
@Override
public boolean initialize() {
OVRDetectResult detect = OVRDetectResult.calloc();
ovr_Detect(0, detect);
System.out.println("OVRDetectResult.IsOculusHMDConnected = " + detect.IsOculusHMDConnected());
System.out.println("OVRDetectResult.IsOculusServiceRunning = " + detect.IsOculusServiceRunning());
boolean connected = detect.IsOculusHMDConnected();
LOGGER.info("OVRDetectResult.IsOculusHMDConnected = " + connected);
LOGGER.info("OVRDetectResult.IsOculusServiceRunning = " + detect.IsOculusServiceRunning());
detect.free();
if (detect.IsOculusHMDConnected() == false) {
if (!connected) {
return false;
}
initialized = true;
throw new UnsupportedOperationException("Not yet implemented!");
// step 1 - hmd init
System.out.println("step 1 - hmd init");
OVRLogCallback callback = new OVRLogCallback() {
@Override
public void invoke(long userData, int level, long message) {
System.out.println("LibOVR [" + userData + "] [" + level + "] " + memASCII(message));
}
};
OVRInitParams initParams = OVRInitParams.calloc();
initParams.LogCallback(callback);
//initParams.Flags(ovrInit_Debug);
if (ovr_Initialize(initParams) != ovrSuccess) {
System.out.println("init failed");
}
System.out.println("OVR SDK " + ovr_GetVersionString());
initParams.free();
// step 2 - hmd create
System.out.println("step 2 - hmd create");
PointerBuffer pHmd = memAllocPointer(1);
OVRGraphicsLuid luid = OVRGraphicsLuid.calloc();
if (ovr_Create(pHmd, luid) != ovrSuccess) {
System.out.println("create failed, try debug");
//debug headset is now enabled via the Oculus Configuration util . tools -> Service -> Configure
return false;
}
session = pHmd.get(0);
memFree(pHmd);
luid.free();
sessionStatus = OVRSessionStatus.calloc();
// step 3 - hmdDesc queries
System.out.println("step 3 - hmdDesc queries");
hmdDesc = OVRHmdDesc.malloc();
ovr_GetHmdDesc(session, hmdDesc);
System.out.println("ovr_GetHmdDesc = " + hmdDesc.ManufacturerString() + " " + hmdDesc.ProductNameString() + " " + hmdDesc.SerialNumberString() + " " + hmdDesc.Type());
if (hmdDesc.Type() == ovrHmd_None) {
System.out.println("missing init");
return false;
}
resolutionW = hmdDesc.Resolution().w();
resolutionH = hmdDesc.Resolution().h();
System.out.println("resolution W=" + resolutionW + ", H=" + resolutionH);
if (resolutionW == 0) {
System.out.println("Huh - width=0");
return false;
}
// FOV
for (int eye = 0; eye < 2; eye++) {
fovPorts[eye] = hmdDesc.DefaultEyeFov(eye);
System.out.println("eye " + eye + " = " + fovPorts[eye].UpTan() + ", " + fovPorts[eye].DownTan() + ", " + fovPorts[eye].LeftTan() + ", " + fovPorts[eye].RightTan());
}
// TODO what does this do? I think it might be the height of the player, for correct floor heights?
// playerEyePos = new Vector3f(0.0f, -ovr_GetFloat(session, OVR_KEY_EYE_HEIGHT, 1.65f), 0.0f);
// step 4 - tracking - no longer needed as of 0.8.0.0
// step 5 - projections
System.out.println("step 5 - projections");
for (int eye = 0; eye < 2; eye++) {
projections[eye] = OVRMatrix4f.malloc();
OVRUtil.ovrMatrix4f_Projection(fovPorts[eye], 0.5f, 500f, OVRUtil.ovrProjection_None, projections[eye]);
//1.3 was right handed, now none flag
}
// step 6 - render desc
System.out.println("step 6 - render desc");
for (int eye = 0; eye < 2; eye++) {
eyeRenderDesc[eye] = OVREyeRenderDesc.malloc();
ovr_GetRenderDesc(session, eye, fovPorts[eye], eyeRenderDesc[eye]);
// Changed from an offset to a pose, so there is also a rotation.
System.out.println("ipd eye " + eye + " = " + eyeRenderDesc[eye].HmdToEyePose().Position().x());
OVRPosef pose = eyeRenderDesc[eye].HmdToEyePose();
Matrix4f jPose = new Matrix4f();
jPose.setTranslation(vecO2J(pose.Position(), new Vector3f()));
jPose.setRotationQuaternion(quatO2J(pose.Orientation(), new Quaternion()));
eyePoses[eye] = jPose;
}
// step 7 - recenter
System.out.println("step 7 - recenter");
ovr_RecenterTrackingOrigin(session);
// throw new UnsupportedOperationException("Not yet implemented!");
return true;
}
@Override
@ -68,14 +227,18 @@ public class OculusVR implements VRAPI {
@Override
public void destroy() {
throw new UnsupportedOperationException();
}
@Override
public void reset() {
throw new UnsupportedOperationException();
}
@Override
public void getRenderSize(Vector2f store) {
store.x = resolutionW;
store.y = resolutionH;
}
@Override
@ -105,12 +268,12 @@ public class OculusVR implements VRAPI {
@Override
public Matrix4f getHMDMatrixProjectionLeftEye(Camera cam) {
throw new UnsupportedOperationException();
return matrixO2J(projections[ovrEye_Left], new Matrix4f());
}
@Override
public Matrix4f getHMDMatrixProjectionRightEye(Camera cam) {
throw new UnsupportedOperationException();
return matrixO2J(projections[ovrEye_Right], new Matrix4f());
}
@Override
@ -130,19 +293,28 @@ public class OculusVR implements VRAPI {
@Override
public Matrix4f getHMDMatrixPoseLeftEye() {
throw new UnsupportedOperationException();
return eyePoses[ovrEye_Left];
}
@Override
public HmdType getType() {
throw new UnsupportedOperationException();
public Matrix4f getHMDMatrixPoseRightEye() {
return eyePoses[ovrEye_Left];
}
@Override
public Matrix4f getHMDMatrixPoseRightEye() {
public HmdType getType() {
throw new UnsupportedOperationException();
}
public boolean initVRCompositor(boolean set) {
if (!set) {
throw new UnsupportedOperationException("Cannot use LibOVR without compositor!");
}
// TODO move initialization code here from VRViewManagerOculus
return true;
}
public void printLatencyInfoToConsole(boolean set) {
throw new UnsupportedOperationException("Not yet implemented!");
}
@ -159,7 +331,62 @@ public class OculusVR implements VRAPI {
throw new UnsupportedOperationException("Not yet implemented!");
}
public boolean initVRCompositor(boolean set) {
throw new UnsupportedOperationException("Not yet implemented!");
// UTILITIES
// TODO move to helper class
/**
* Copy the values from a LibOVR matrix into a jMonkeyEngine matrix.
*
* @param from The matrix to copy from.
* @param to The matrix to copy to.
* @return The {@code to} argument.
*/
public static Matrix4f matrixO2J(OVRMatrix4f from, Matrix4f to) {
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++) {
float val = from.M(x + y * 4); // TODO verify this
to.set(x, y, val);
}
}
return to;
}
/**
* Copy the values from a LibOVR quaternion into a jMonkeyEngine quaternion.
*
* @param from The quaternion to copy from.
* @param to The quaternion to copy to.
* @return The {@code to} argument.
*/
public static Quaternion quatO2J(OVRQuatf from, Quaternion to) {
to.set(
from.x(),
from.y(),
from.z(),
from.w()
);
return to;
}
/**
* Copy the values from a LibOVR vector into a jMonkeyEngine vector.
*
* @param from The vector to copy from.
* @param to The vector to copy to.
* @return The {@code to} argument.
*/
public static Vector3f vecO2J(OVRVector3f from, Vector3f to) {
to.set(
from.x(),
from.y(),
from.z()
);
return to;
}
}
/* vim: set ts=4 softtabstop=0 sw=4 expandtab: */

Loading…
Cancel
Save