mirror of
https://github.com/DrBeef/ioq3quest.git
synced 2024-11-10 14:52:00 +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);
|
ALOGE("Failed to create XR session: %d.", initResult);
|
||||||
exit(1);
|
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 ) {
|
void VR_LeaveVR( engine_t* engine ) {
|
||||||
if (engine->appState.Session) {
|
if (engine->appState.Session) {
|
||||||
OXR(xrDestroySpace(engine->appState.HeadSpace));
|
OXR(xrDestroySpace(engine->appState.HeadSpace));
|
||||||
OXR(xrDestroySpace(engine->appState.LocalSpace));
|
|
||||||
// StageSpace is optional.
|
// StageSpace is optional.
|
||||||
if (engine->appState.StageSpace != XR_NULL_HANDLE) {
|
if (engine->appState.StageSpace != XR_NULL_HANDLE) {
|
||||||
OXR(xrDestroySpace(engine->appState.StageSpace));
|
OXR(xrDestroySpace(engine->appState.StageSpace));
|
||||||
|
@ -307,7 +313,6 @@ void VR_LeaveVR( engine_t* engine ) {
|
||||||
OXR(xrDestroySpace(engine->appState.FakeStageSpace));
|
OXR(xrDestroySpace(engine->appState.FakeStageSpace));
|
||||||
engine->appState.CurrentSpace = XR_NULL_HANDLE;
|
engine->appState.CurrentSpace = XR_NULL_HANDLE;
|
||||||
OXR(xrDestroySession(engine->appState.Session));
|
OXR(xrDestroySession(engine->appState.Session));
|
||||||
OXR(xrDestroyInstance(engine->appState.Instance));
|
|
||||||
engine->appState.Session = NULL;
|
engine->appState.Session = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,8 @@ typedef struct {
|
||||||
int *menuCursorX;
|
int *menuCursorX;
|
||||||
int *menuCursorY;
|
int *menuCursorY;
|
||||||
qboolean menuLeftHanded;
|
qboolean menuLeftHanded;
|
||||||
|
|
||||||
|
float recenterYaw;
|
||||||
} vr_clientinfo_t;
|
} vr_clientinfo_t;
|
||||||
|
|
||||||
#endif //vr_clientinfo_h
|
#endif //vr_clientinfo_h
|
|
@ -23,6 +23,7 @@ extern vr_clientinfo_t vr;
|
||||||
extern cvar_t *vr_heightAdjust;
|
extern cvar_t *vr_heightAdjust;
|
||||||
|
|
||||||
XrView* projections;
|
XrView* projections;
|
||||||
|
GLboolean stageSupported = GL_FALSE;
|
||||||
|
|
||||||
void VR_UpdateStageBounds(ovrApp* pappState) {
|
void VR_UpdateStageBounds(ovrApp* pappState) {
|
||||||
XrExtent2Df stageBounds = {};
|
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 ) {
|
void VR_InitRenderer( engine_t* engine ) {
|
||||||
#if ENABLE_GL_DEBUG
|
#if ENABLE_GL_DEBUG
|
||||||
glEnable(GL_DEBUG_OUTPUT);
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
|
@ -227,7 +276,6 @@ void VR_InitRenderer( engine_t* engine ) {
|
||||||
OXR(xrEnumerateReferenceSpaces(
|
OXR(xrEnumerateReferenceSpaces(
|
||||||
engine->appState.Session, numOutputSpaces, &numOutputSpaces, referenceSpaces));
|
engine->appState.Session, numOutputSpaces, &numOutputSpaces, referenceSpaces));
|
||||||
|
|
||||||
GLboolean stageSupported = GL_FALSE;
|
|
||||||
for (uint32_t i = 0; i < numOutputSpaces; i++) {
|
for (uint32_t i = 0; i < numOutputSpaces; i++) {
|
||||||
if (referenceSpaces[i] == XR_REFERENCE_SPACE_TYPE_STAGE) {
|
if (referenceSpaces[i] == XR_REFERENCE_SPACE_TYPE_STAGE) {
|
||||||
stageSupported = GL_TRUE;
|
stageSupported = GL_TRUE;
|
||||||
|
@ -237,32 +285,8 @@ void VR_InitRenderer( engine_t* engine ) {
|
||||||
|
|
||||||
free(referenceSpaces);
|
free(referenceSpaces);
|
||||||
|
|
||||||
// Create a space to the first path
|
if (engine->appState.CurrentSpace == XR_NULL_HANDLE) {
|
||||||
XrReferenceSpaceCreateInfo spaceCreateInfo = {};
|
VR_Recenter(engine);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
projections = (XrView*)(malloc(ovrMaxNumEyes * sizeof(XrView)));
|
projections = (XrView*)(malloc(ovrMaxNumEyes * sizeof(XrView)));
|
||||||
|
@ -323,7 +347,9 @@ void VR_DrawFrame( engine_t* engine ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
GLboolean stageBoundsDirty = GL_TRUE;
|
GLboolean stageBoundsDirty = GL_TRUE;
|
||||||
ovrApp_HandleXrEvents(&engine->appState);
|
if (ovrApp_HandleXrEvents(&engine->appState)) {
|
||||||
|
VR_Recenter(engine);
|
||||||
|
}
|
||||||
if (engine->appState.SessionActive == GL_FALSE) {
|
if (engine->appState.SessionActive == GL_FALSE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -358,15 +384,6 @@ void VR_DrawFrame( engine_t* engine ) {
|
||||||
beginFrameDesc.next = NULL;
|
beginFrameDesc.next = NULL;
|
||||||
OXR(xrBeginFrame(engine->appState.Session, &beginFrameDesc));
|
OXR(xrBeginFrame(engine->appState.Session, &beginFrameDesc));
|
||||||
|
|
||||||
XrSpaceLocation loc = {};
|
|
||||||
loc.type = XR_TYPE_SPACE_LOCATION;
|
|
||||||
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));
|
|
||||||
|
|
||||||
{
|
|
||||||
// We extract Yaw, Pitch, Roll instead of directly using the orientation
|
// We extract Yaw, Pitch, Roll instead of directly using the orientation
|
||||||
// to allow "additional" yaw manipulation with mouse/controller.
|
// to allow "additional" yaw manipulation with mouse/controller.
|
||||||
XrSpaceLocation loc = {};
|
XrSpaceLocation loc = {};
|
||||||
|
@ -395,7 +412,6 @@ void VR_DrawFrame( engine_t* engine ) {
|
||||||
const float clientview_yaw = vr.clientviewangles[YAW] - vr.hmdorientation[YAW];
|
const float clientview_yaw = vr.clientviewangles[YAW] - vr.hmdorientation[YAW];
|
||||||
vr.clientview_yaw_delta = vr.clientview_yaw_last - clientview_yaw;
|
vr.clientview_yaw_delta = vr.clientview_yaw_last - clientview_yaw;
|
||||||
vr.clientview_yaw_last = clientview_yaw;
|
vr.clientview_yaw_last = clientview_yaw;
|
||||||
}
|
|
||||||
|
|
||||||
XrViewLocateInfo projectionInfo = {};
|
XrViewLocateInfo projectionInfo = {};
|
||||||
projectionInfo.type = XR_TYPE_VIEW_LOCATE_INFO;
|
projectionInfo.type = XR_TYPE_VIEW_LOCATE_INFO;
|
||||||
|
@ -465,6 +481,7 @@ void VR_DrawFrame( engine_t* engine ) {
|
||||||
|
|
||||||
XrCompositionLayerProjectionView projection_layer_elements[2] = {};
|
XrCompositionLayerProjectionView projection_layer_elements[2] = {};
|
||||||
if (!VR_useScreenLayer() && !(cl.snap.ps.pm_flags & PMF_FOLLOW && vr.follow_mode == VRFM_FIRSTPERSON)) {
|
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++) {
|
for (int eye = 0; eye < ovrMaxNumEyes; eye++) {
|
||||||
ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer;
|
ovrFramebuffer* frameBuffer = &engine->appState.Renderer.FrameBuffer;
|
||||||
|
@ -500,7 +517,7 @@ void VR_DrawFrame( engine_t* engine ) {
|
||||||
XrCompositionLayerCylinderKHR cylinder_layer = {};
|
XrCompositionLayerCylinderKHR cylinder_layer = {};
|
||||||
cylinder_layer.type = XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR;
|
cylinder_layer.type = XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR;
|
||||||
cylinder_layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
|
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;
|
cylinder_layer.eyeVisibility = XR_EYE_VISIBILITY_BOTH;
|
||||||
memset(&cylinder_layer.subImage, 0, sizeof(XrSwapchainSubImage));
|
memset(&cylinder_layer.subImage, 0, sizeof(XrSwapchainSubImage));
|
||||||
cylinder_layer.subImage.swapchain = engine->appState.Renderer.FrameBuffer.ColorSwapChain.Handle;
|
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.imageRect.extent.height = height;
|
||||||
cylinder_layer.subImage.imageArrayIndex = 0;
|
cylinder_layer.subImage.imageArrayIndex = 0;
|
||||||
const XrVector3f axis = {0.0f, 1.0f, 0.0f};
|
const XrVector3f axis = {0.0f, 1.0f, 0.0f};
|
||||||
const XrVector3f pos = {xfStageFromHead.position.x, -0.25f, xfStageFromHead.position.z - 4.0f};
|
XrVector3f pos = {
|
||||||
cylinder_layer.pose.orientation = XrQuaternionf_CreateFromVectorAngle(axis, 0);
|
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.pose.position = pos;
|
||||||
cylinder_layer.radius = 12.0f;
|
cylinder_layer.radius = 12.0f;
|
||||||
cylinder_layer.centralAngle = MATH_PI * 0.5f;
|
cylinder_layer.centralAngle = MATH_PI * 0.5f;
|
||||||
|
|
|
@ -236,7 +236,6 @@ void ovrApp_Clear(ovrApp* app) {
|
||||||
memset(&app->ViewConfigurationView, 0, ovrMaxNumEyes * sizeof(XrViewConfigurationView));
|
memset(&app->ViewConfigurationView, 0, ovrMaxNumEyes * sizeof(XrViewConfigurationView));
|
||||||
app->SystemId = XR_NULL_SYSTEM_ID;
|
app->SystemId = XR_NULL_SYSTEM_ID;
|
||||||
app->HeadSpace = XR_NULL_HANDLE;
|
app->HeadSpace = XR_NULL_HANDLE;
|
||||||
app->LocalSpace = XR_NULL_HANDLE;
|
|
||||||
app->StageSpace = XR_NULL_HANDLE;
|
app->StageSpace = XR_NULL_HANDLE;
|
||||||
app->FakeStageSpace = XR_NULL_HANDLE;
|
app->FakeStageSpace = XR_NULL_HANDLE;
|
||||||
app->CurrentSpace = 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 = {};
|
XrEventDataBuffer eventDataBuffer = {};
|
||||||
|
GLboolean recenter = GL_FALSE;
|
||||||
|
|
||||||
// Poll for events
|
// Poll for events
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -368,6 +368,7 @@ void ovrApp_HandleXrEvents(ovrApp* app) {
|
||||||
ref_space_change_event->referenceSpaceType,
|
ref_space_change_event->referenceSpaceType,
|
||||||
(void*)ref_space_change_event->session,
|
(void*)ref_space_change_event->session,
|
||||||
FromXrTime(ref_space_change_event->changeTime));
|
FromXrTime(ref_space_change_event->changeTime));
|
||||||
|
recenter = GL_TRUE;
|
||||||
} break;
|
} break;
|
||||||
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: {
|
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: {
|
||||||
const XrEventDataSessionStateChanged* session_state_changed_event =
|
const XrEventDataSessionStateChanged* session_state_changed_event =
|
||||||
|
@ -398,6 +399,7 @@ void ovrApp_HandleXrEvents(ovrApp* app) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return recenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -79,7 +79,6 @@ typedef struct {
|
||||||
XrViewConfigurationView ViewConfigurationView[ovrMaxNumEyes];
|
XrViewConfigurationView ViewConfigurationView[ovrMaxNumEyes];
|
||||||
XrSystemId SystemId;
|
XrSystemId SystemId;
|
||||||
XrSpace HeadSpace;
|
XrSpace HeadSpace;
|
||||||
XrSpace LocalSpace;
|
|
||||||
XrSpace StageSpace;
|
XrSpace StageSpace;
|
||||||
XrSpace FakeStageSpace;
|
XrSpace FakeStageSpace;
|
||||||
XrSpace CurrentSpace;
|
XrSpace CurrentSpace;
|
||||||
|
@ -159,7 +158,7 @@ typedef enum {
|
||||||
|
|
||||||
void ovrApp_Clear(ovrApp* app);
|
void ovrApp_Clear(ovrApp* app);
|
||||||
void ovrApp_Destroy(ovrApp* app);
|
void ovrApp_Destroy(ovrApp* app);
|
||||||
void ovrApp_HandleXrEvents(ovrApp* app);
|
GLboolean ovrApp_HandleXrEvents(ovrApp* app);
|
||||||
|
|
||||||
void ovrFramebuffer_Acquire(ovrFramebuffer* frameBuffer);
|
void ovrFramebuffer_Acquire(ovrFramebuffer* frameBuffer);
|
||||||
void ovrFramebuffer_Resolve(ovrFramebuffer* frameBuffer);
|
void ovrFramebuffer_Resolve(ovrFramebuffer* frameBuffer);
|
||||||
|
|
Loading…
Reference in a new issue