mirror of
https://github.com/DrBeef/ioq3quest.git
synced 2024-11-25 13:31:10 +00:00
Merge pull request #75 from lvonasek/OpenXR
OpenXR menuyaw and recenter support added
This commit is contained in:
commit
325641f90e
5 changed files with 96 additions and 67 deletions
|
@ -294,12 +294,18 @@ void VR_EnterVR( engine_t* engine, ovrJava java ) {
|
|||
ALOGE("Failed to create XR session: %d.", initResult);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Create a space to the first path
|
||||
XrReferenceSpaceCreateInfo spaceCreateInfo = {};
|
||||
spaceCreateInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
||||
spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_VIEW;
|
||||
spaceCreateInfo.poseInReferenceSpace.orientation.w = 1.0f;
|
||||
OXR(xrCreateReferenceSpace(engine->appState.Session, &spaceCreateInfo, &engine->appState.HeadSpace));
|
||||
}
|
||||
|
||||
void VR_LeaveVR( engine_t* engine ) {
|
||||
if (engine->appState.Session) {
|
||||
OXR(xrDestroySpace(engine->appState.HeadSpace));
|
||||
OXR(xrDestroySpace(engine->appState.LocalSpace));
|
||||
// StageSpace is optional.
|
||||
if (engine->appState.StageSpace != XR_NULL_HANDLE) {
|
||||
OXR(xrDestroySpace(engine->appState.StageSpace));
|
||||
|
@ -307,7 +313,6 @@ void VR_LeaveVR( engine_t* engine ) {
|
|||
OXR(xrDestroySpace(engine->appState.FakeStageSpace));
|
||||
engine->appState.CurrentSpace = XR_NULL_HANDLE;
|
||||
OXR(xrDestroySession(engine->appState.Session));
|
||||
OXR(xrDestroyInstance(engine->appState.Instance));
|
||||
engine->appState.Session = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,8 @@ typedef struct {
|
|||
int *menuCursorX;
|
||||
int *menuCursorY;
|
||||
qboolean menuLeftHanded;
|
||||
|
||||
float recenterYaw;
|
||||
} vr_clientinfo_t;
|
||||
|
||||
#endif //vr_clientinfo_h
|
|
@ -23,6 +23,7 @@ extern vr_clientinfo_t vr;
|
|||
extern cvar_t *vr_heightAdjust;
|
||||
|
||||
XrView* projections;
|
||||
GLboolean stageSupported = GL_FALSE;
|
||||
|
||||
void VR_UpdateStageBounds(ovrApp* pappState) {
|
||||
XrExtent2Df stageBounds = {};
|
||||
|
@ -161,6 +162,54 @@ void VR_GetResolution(engine_t* engine, int *pWidth, int *pHeight)
|
|||
}
|
||||
}
|
||||
|
||||
void VR_Recenter(engine_t* engine) {
|
||||
|
||||
// Calculate recenter reference
|
||||
XrReferenceSpaceCreateInfo spaceCreateInfo = {};
|
||||
spaceCreateInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
||||
spaceCreateInfo.poseInReferenceSpace.orientation.w = 1.0f;
|
||||
if (engine->appState.CurrentSpace != XR_NULL_HANDLE) {
|
||||
vec3_t rotation = {0, 0, 0};
|
||||
XrSpaceLocation loc = {};
|
||||
loc.type = XR_TYPE_SPACE_LOCATION;
|
||||
OXR(xrLocateSpace(engine->appState.HeadSpace, engine->appState.CurrentSpace, engine->predictedDisplayTime, &loc));
|
||||
QuatToYawPitchRoll(loc.pose.orientation, rotation, vr.hmdorientation);
|
||||
|
||||
vr.recenterYaw += radians(vr.hmdorientation[YAW]);
|
||||
spaceCreateInfo.poseInReferenceSpace.orientation.x = 0;
|
||||
spaceCreateInfo.poseInReferenceSpace.orientation.y = sin(vr.recenterYaw / 2);
|
||||
spaceCreateInfo.poseInReferenceSpace.orientation.z = 0;
|
||||
spaceCreateInfo.poseInReferenceSpace.orientation.w = cos(vr.recenterYaw / 2);
|
||||
}
|
||||
|
||||
// Delete previous space instances
|
||||
if (engine->appState.StageSpace != XR_NULL_HANDLE) {
|
||||
OXR(xrDestroySpace(engine->appState.StageSpace));
|
||||
}
|
||||
if (engine->appState.FakeStageSpace != XR_NULL_HANDLE) {
|
||||
OXR(xrDestroySpace(engine->appState.FakeStageSpace));
|
||||
}
|
||||
|
||||
// Create a default stage space to use if SPACE_TYPE_STAGE is not
|
||||
// supported, or calls to xrGetReferenceSpaceBoundsRect fail.
|
||||
spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
|
||||
spaceCreateInfo.poseInReferenceSpace.position.y = -1.6750f;
|
||||
OXR(xrCreateReferenceSpace(engine->appState.Session, &spaceCreateInfo, &engine->appState.FakeStageSpace));
|
||||
ALOGV("Created fake stage space from local space with offset");
|
||||
engine->appState.CurrentSpace = engine->appState.FakeStageSpace;
|
||||
|
||||
if (stageSupported) {
|
||||
spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE;
|
||||
spaceCreateInfo.poseInReferenceSpace.position.y = 0.0f;
|
||||
OXR(xrCreateReferenceSpace(engine->appState.Session, &spaceCreateInfo, &engine->appState.StageSpace));
|
||||
ALOGV("Created stage space");
|
||||
engine->appState.CurrentSpace = engine->appState.StageSpace;
|
||||
}
|
||||
|
||||
// Update menu orientation
|
||||
vr.menuYaw = 0;
|
||||
}
|
||||
|
||||
void VR_InitRenderer( engine_t* engine ) {
|
||||
#if ENABLE_GL_DEBUG
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
|
@ -227,7 +276,6 @@ void VR_InitRenderer( engine_t* engine ) {
|
|||
OXR(xrEnumerateReferenceSpaces(
|
||||
engine->appState.Session, numOutputSpaces, &numOutputSpaces, referenceSpaces));
|
||||
|
||||
GLboolean stageSupported = GL_FALSE;
|
||||
for (uint32_t i = 0; i < numOutputSpaces; i++) {
|
||||
if (referenceSpaces[i] == XR_REFERENCE_SPACE_TYPE_STAGE) {
|
||||
stageSupported = GL_TRUE;
|
||||
|
@ -237,32 +285,8 @@ void VR_InitRenderer( engine_t* engine ) {
|
|||
|
||||
free(referenceSpaces);
|
||||
|
||||
// Create a space to the first path
|
||||
XrReferenceSpaceCreateInfo spaceCreateInfo = {};
|
||||
spaceCreateInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
|
||||
spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_VIEW;
|
||||
spaceCreateInfo.poseInReferenceSpace.orientation.w = 1.0f;
|
||||
OXR(xrCreateReferenceSpace(engine->appState.Session, &spaceCreateInfo, &engine->appState.HeadSpace));
|
||||
|
||||
spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
|
||||
OXR(xrCreateReferenceSpace(engine->appState.Session, &spaceCreateInfo, &engine->appState.LocalSpace));
|
||||
|
||||
// Create a default stage space to use if SPACE_TYPE_STAGE is not
|
||||
// supported, or calls to xrGetReferenceSpaceBoundsRect fail.
|
||||
{
|
||||
spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
|
||||
spaceCreateInfo.poseInReferenceSpace.position.y = -1.6750f;
|
||||
OXR(xrCreateReferenceSpace(engine->appState.Session, &spaceCreateInfo, &engine->appState.FakeStageSpace));
|
||||
ALOGV("Created fake stage space from local space with offset");
|
||||
engine->appState.CurrentSpace = engine->appState.FakeStageSpace;
|
||||
}
|
||||
|
||||
if (stageSupported) {
|
||||
spaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE;
|
||||
spaceCreateInfo.poseInReferenceSpace.position.y = 0.0f;
|
||||
OXR(xrCreateReferenceSpace(engine->appState.Session, &spaceCreateInfo, &engine->appState.StageSpace));
|
||||
ALOGV("Created stage space");
|
||||
engine->appState.CurrentSpace = engine->appState.StageSpace;
|
||||
if (engine->appState.CurrentSpace == XR_NULL_HANDLE) {
|
||||
VR_Recenter(engine);
|
||||
}
|
||||
|
||||
projections = (XrView*)(malloc(ovrMaxNumEyes * sizeof(XrView)));
|
||||
|
@ -323,7 +347,9 @@ void VR_DrawFrame( engine_t* engine ) {
|
|||
}
|
||||
|
||||
GLboolean stageBoundsDirty = GL_TRUE;
|
||||
ovrApp_HandleXrEvents(&engine->appState);
|
||||
if (ovrApp_HandleXrEvents(&engine->appState)) {
|
||||
VR_Recenter(engine);
|
||||
}
|
||||
if (engine->appState.SessionActive == GL_FALSE) {
|
||||
return;
|
||||
}
|
||||
|
@ -358,44 +384,34 @@ void VR_DrawFrame( engine_t* engine ) {
|
|||
beginFrameDesc.next = NULL;
|
||||
OXR(xrBeginFrame(engine->appState.Session, &beginFrameDesc));
|
||||
|
||||
// We extract Yaw, Pitch, Roll instead of directly using the orientation
|
||||
// to allow "additional" yaw manipulation with mouse/controller.
|
||||
XrSpaceLocation loc = {};
|
||||
loc.type = XR_TYPE_SPACE_LOCATION;
|
||||
OXR(xrLocateSpace(
|
||||
engine->appState.HeadSpace, engine->appState.CurrentSpace, frameState.predictedDisplayTime, &loc));
|
||||
OXR(xrLocateSpace(engine->appState.HeadSpace, engine->appState.CurrentSpace, frameState.predictedDisplayTime, &loc));
|
||||
XrPosef xfStageFromHead = loc.pose;
|
||||
OXR(xrLocateSpace(
|
||||
engine->appState.HeadSpace, engine->appState.LocalSpace, frameState.predictedDisplayTime, &loc));
|
||||
const XrQuaternionf quatHmd = xfStageFromHead.orientation;
|
||||
const XrVector3f positionHmd = xfStageFromHead.position;
|
||||
vec3_t rotation = {0, 0, 0};
|
||||
QuatToYawPitchRoll(quatHmd, rotation, vr.hmdorientation);
|
||||
VectorSet(vr.hmdposition, positionHmd.x, positionHmd.y + vr_heightAdjust->value, positionHmd.z);
|
||||
|
||||
{
|
||||
// We extract Yaw, Pitch, Roll instead of directly using the orientation
|
||||
// to allow "additional" yaw manipulation with mouse/controller.
|
||||
XrSpaceLocation loc = {};
|
||||
loc.type = XR_TYPE_SPACE_LOCATION;
|
||||
OXR(xrLocateSpace(engine->appState.HeadSpace, engine->appState.CurrentSpace, frameState.predictedDisplayTime, &loc));
|
||||
XrPosef xfStageFromHead = loc.pose;
|
||||
const XrQuaternionf quatHmd = xfStageFromHead.orientation;
|
||||
const XrVector3f positionHmd = xfStageFromHead.position;
|
||||
vec3_t rotation = {0, 0, 0};
|
||||
QuatToYawPitchRoll(quatHmd, rotation, vr.hmdorientation);
|
||||
VectorSet(vr.hmdposition, positionHmd.x, positionHmd.y + vr_heightAdjust->value, positionHmd.z);
|
||||
//Position
|
||||
VectorSubtract(vr.hmdposition_last, vr.hmdposition, vr.hmdposition_delta);
|
||||
|
||||
//Position
|
||||
VectorSubtract(vr.hmdposition_last, vr.hmdposition, vr.hmdposition_delta);
|
||||
//Keep this for our records
|
||||
VectorCopy(vr.hmdposition, vr.hmdposition_last);
|
||||
|
||||
//Keep this for our records
|
||||
VectorCopy(vr.hmdposition, vr.hmdposition_last);
|
||||
//Orientation
|
||||
VectorSubtract(vr.hmdorientation_last, vr.hmdorientation, vr.hmdorientation_delta);
|
||||
|
||||
//Orientation
|
||||
VectorSubtract(vr.hmdorientation_last, vr.hmdorientation, vr.hmdorientation_delta);
|
||||
//Keep this for our records
|
||||
VectorCopy(vr.hmdorientation, vr.hmdorientation_last);
|
||||
|
||||
//Keep this for our records
|
||||
VectorCopy(vr.hmdorientation, vr.hmdorientation_last);
|
||||
|
||||
// View yaw delta
|
||||
const float clientview_yaw = vr.clientviewangles[YAW] - vr.hmdorientation[YAW];
|
||||
vr.clientview_yaw_delta = vr.clientview_yaw_last - clientview_yaw;
|
||||
vr.clientview_yaw_last = clientview_yaw;
|
||||
}
|
||||
// View yaw delta
|
||||
const float clientview_yaw = vr.clientviewangles[YAW] - vr.hmdorientation[YAW];
|
||||
vr.clientview_yaw_delta = vr.clientview_yaw_last - clientview_yaw;
|
||||
vr.clientview_yaw_last = clientview_yaw;
|
||||
|
||||
XrViewLocateInfo projectionInfo = {};
|
||||
projectionInfo.type = XR_TYPE_VIEW_LOCATE_INFO;
|
||||
|
@ -465,6 +481,7 @@ void VR_DrawFrame( engine_t* engine ) {
|
|||
|
||||
XrCompositionLayerProjectionView projection_layer_elements[2] = {};
|
||||
if (!VR_useScreenLayer() && !(cl.snap.ps.pm_flags & PMF_FOLLOW && vr.follow_mode == VRFM_FIRSTPERSON)) {
|
||||
vr.menuYaw = vr.hmdorientation[YAW];
|
||||
|
||||
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
|
||||
ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer;
|
||||
|
@ -500,7 +517,7 @@ void VR_DrawFrame( engine_t* engine ) {
|
|||
XrCompositionLayerCylinderKHR cylinder_layer = {};
|
||||
cylinder_layer.type = XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR;
|
||||
cylinder_layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
|
||||
cylinder_layer.space = engine->appState.LocalSpace;
|
||||
cylinder_layer.space = engine->appState.CurrentSpace;
|
||||
cylinder_layer.eyeVisibility = XR_EYE_VISIBILITY_BOTH;
|
||||
memset(&cylinder_layer.subImage, 0, sizeof(XrSwapchainSubImage));
|
||||
cylinder_layer.subImage.swapchain = engine->appState.Renderer.FrameBuffer.ColorSwapChain.Handle;
|
||||
|
@ -510,8 +527,12 @@ void VR_DrawFrame( engine_t* engine ) {
|
|||
cylinder_layer.subImage.imageRect.extent.height = height;
|
||||
cylinder_layer.subImage.imageArrayIndex = 0;
|
||||
const XrVector3f axis = {0.0f, 1.0f, 0.0f};
|
||||
const XrVector3f pos = {xfStageFromHead.position.x, -0.25f, xfStageFromHead.position.z - 4.0f};
|
||||
cylinder_layer.pose.orientation = XrQuaternionf_CreateFromVectorAngle(axis, 0);
|
||||
XrVector3f pos = {
|
||||
xfStageFromHead.position.x - sin(radians(vr.menuYaw)) * 4.0f,
|
||||
-0.25f,
|
||||
xfStageFromHead.position.z - cos(radians(vr.menuYaw)) * 4.0f
|
||||
};
|
||||
cylinder_layer.pose.orientation = XrQuaternionf_CreateFromVectorAngle(axis, radians(vr.menuYaw));
|
||||
cylinder_layer.pose.position = pos;
|
||||
cylinder_layer.radius = 12.0f;
|
||||
cylinder_layer.centralAngle = MATH_PI * 0.5f;
|
||||
|
|
|
@ -236,7 +236,6 @@ void ovrApp_Clear(ovrApp* app) {
|
|||
memset(&app->ViewConfigurationView, 0, ovrMaxNumEyes * sizeof(XrViewConfigurationView));
|
||||
app->SystemId = XR_NULL_SYSTEM_ID;
|
||||
app->HeadSpace = XR_NULL_HANDLE;
|
||||
app->LocalSpace = XR_NULL_HANDLE;
|
||||
app->StageSpace = XR_NULL_HANDLE;
|
||||
app->FakeStageSpace = XR_NULL_HANDLE;
|
||||
app->CurrentSpace = XR_NULL_HANDLE;
|
||||
|
@ -314,8 +313,9 @@ void ovrApp_HandleSessionStateChanges(ovrApp* app, XrSessionState state) {
|
|||
}
|
||||
}
|
||||
|
||||
void ovrApp_HandleXrEvents(ovrApp* app) {
|
||||
GLboolean ovrApp_HandleXrEvents(ovrApp* app) {
|
||||
XrEventDataBuffer eventDataBuffer = {};
|
||||
GLboolean recenter = GL_FALSE;
|
||||
|
||||
// Poll for events
|
||||
for (;;) {
|
||||
|
@ -368,6 +368,7 @@ void ovrApp_HandleXrEvents(ovrApp* app) {
|
|||
ref_space_change_event->referenceSpaceType,
|
||||
(void*)ref_space_change_event->session,
|
||||
FromXrTime(ref_space_change_event->changeTime));
|
||||
recenter = GL_TRUE;
|
||||
} break;
|
||||
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: {
|
||||
const XrEventDataSessionStateChanged* session_state_changed_event =
|
||||
|
@ -398,6 +399,7 @@ void ovrApp_HandleXrEvents(ovrApp* app) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
return recenter;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -79,7 +79,6 @@ typedef struct {
|
|||
XrViewConfigurationView ViewConfigurationView[ovrMaxNumEyes];
|
||||
XrSystemId SystemId;
|
||||
XrSpace HeadSpace;
|
||||
XrSpace LocalSpace;
|
||||
XrSpace StageSpace;
|
||||
XrSpace FakeStageSpace;
|
||||
XrSpace CurrentSpace;
|
||||
|
@ -159,7 +158,7 @@ typedef enum {
|
|||
|
||||
void ovrApp_Clear(ovrApp* app);
|
||||
void ovrApp_Destroy(ovrApp* app);
|
||||
void ovrApp_HandleXrEvents(ovrApp* app);
|
||||
GLboolean ovrApp_HandleXrEvents(ovrApp* app);
|
||||
|
||||
void ovrFramebuffer_Acquire(ovrFramebuffer* frameBuffer);
|
||||
void ovrFramebuffer_Resolve(ovrFramebuffer* frameBuffer);
|
||||
|
|
Loading…
Reference in a new issue