From 314e8b028890c60f0d3a7ec0019e7920f0af2c9b Mon Sep 17 00:00:00 2001 From: Lubos Date: Tue, 10 May 2022 19:21:13 +0200 Subject: [PATCH 1/9] OpenXR attach actions to session just once --- android/app/src/main/cpp/code/vr/vr_input.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/android/app/src/main/cpp/code/vr/vr_input.c b/android/app/src/main/cpp/code/vr/vr_input.c index aa008c52..c01c6272 100644 --- a/android/app/src/main/cpp/code/vr/vr_input.c +++ b/android/app/src/main/cpp/code/vr/vr_input.c @@ -40,6 +40,7 @@ XrAction vibrateRightFeedback; XrActionSet runningActionSet; XrSpace leftControllerAimSpace = XR_NULL_HANDLE; XrSpace rightControllerAimSpace = XR_NULL_HANDLE; +qboolean actionsAttached = qfalse; qboolean inputInitialized = qfalse; qboolean useSimpleProfile = qfalse; @@ -1364,12 +1365,15 @@ void IN_VRSyncActions( void ) engine_t* engine = VR_GetEngine(); // Attach to session - XrSessionActionSetsAttachInfo attachInfo = {}; - attachInfo.type = XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO; - attachInfo.next = NULL; - attachInfo.countActionSets = 1; - attachInfo.actionSets = &runningActionSet; - OXR(xrAttachSessionActionSets(engine->appState.Session, &attachInfo)); + if (!actionsAttached) { + XrSessionActionSetsAttachInfo attachInfo = {}; + attachInfo.type = XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO; + attachInfo.next = NULL; + attachInfo.countActionSets = 1; + attachInfo.actionSets = &runningActionSet; + OXR(xrAttachSessionActionSets(engine->appState.Session, &attachInfo)); + actionsAttached = qtrue; + } // sync action data XrActiveActionSet activeActionSet = {}; From 437e3829aa2f3dac85cd53793b03654663ff46b1 Mon Sep 17 00:00:00 2001 From: Lubos Date: Tue, 10 May 2022 19:23:51 +0200 Subject: [PATCH 2/9] OpenXR ignore controller velocity --- android/app/src/main/cpp/code/vr/vr_input.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/android/app/src/main/cpp/code/vr/vr_input.c b/android/app/src/main/cpp/code/vr/vr_input.c index c01c6272..43b46665 100644 --- a/android/app/src/main/cpp/code/vr/vr_input.c +++ b/android/app/src/main/cpp/code/vr/vr_input.c @@ -1404,21 +1404,12 @@ void IN_VRUpdateControllers( float predictedDisplayTime ) XrSpace controllerSpace[] = {leftControllerAimSpace, rightControllerAimSpace}; for (int i = 0; i < 2; i++) { if (ActionPoseIsActive(controller[i], subactionPath[i])) { - XrSpaceVelocity vel = {}; - vel.type = XR_TYPE_SPACE_VELOCITY; XrSpaceLocation loc = {}; loc.type = XR_TYPE_SPACE_LOCATION; - loc.next = &vel; OXR(xrLocateSpace(controllerSpace[i], engine->appState.CurrentSpace, predictedDisplayTime, &loc)); engine->appState.TrackedController[i].Active = (loc.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0; engine->appState.TrackedController[i].Pose = loc.pose; - - // apply velocity - float dt = (in_vrEventTime - lastframetime) * 0.001f; - for (int j = 0; j < 3; j++) { - (&engine->appState.TrackedController[i].Pose.position.x)[j] += (&vel.linearVelocity.x)[j] * dt; - } } else { ovrTrackedController_Clear(&engine->appState.TrackedController[i]); } From 244b8344ff2a121dfbbd6c0843a1d48a3216d271 Mon Sep 17 00:00:00 2001 From: Lubos Date: Tue, 10 May 2022 19:34:18 +0200 Subject: [PATCH 3/9] OpenXR do not call stop haptics every frame --- android/app/src/main/cpp/code/vr/vr_input.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/cpp/code/vr/vr_input.c b/android/app/src/main/cpp/code/vr/vr_input.c index 43b46665..1994e005 100644 --- a/android/app/src/main/cpp/code/vr/vr_input.c +++ b/android/app/src/main/cpp/code/vr/vr_input.c @@ -228,6 +228,7 @@ void QuatToYawPitchRoll(XrQuaternionf q, vec3_t rotation, vec3_t out) { //0 = left, 1 = right float vibration_channel_duration[2] = {0.0f, 0.0f}; float vibration_channel_intensity[2] = {0.0f, 0.0f}; +qboolean vibration_stopped[2] = {qtrue, qtrue}; void VR_Vibrate( int duration, int chan, float intensity ) { @@ -271,6 +272,7 @@ static void VR_processHaptics() { hapticActionInfo.next = NULL; hapticActionInfo.action = i == 0 ? vibrateLeftFeedback : vibrateRightFeedback; OXR(xrApplyHapticFeedback(VR_GetEngine()->appState.Session, &hapticActionInfo, (const XrHapticBaseHeader*)&vibration)); + vibration_stopped[i] = qfalse; if (vibration_channel_duration[i] != -1.0f) { vibration_channel_duration[i] -= frametime; @@ -280,13 +282,14 @@ static void VR_processHaptics() { vibration_channel_intensity[i] = 0.0f; } } - } else { + } else if (!vibration_stopped[i]) { // Stop haptics XrHapticActionInfo hapticActionInfo = {}; hapticActionInfo.type = XR_TYPE_HAPTIC_ACTION_INFO; hapticActionInfo.next = NULL; hapticActionInfo.action = i == 0 ? vibrateLeftFeedback : vibrateRightFeedback; OXR(xrStopHapticFeedback(VR_GetEngine()->appState.Session, &hapticActionInfo)); + vibration_stopped[i] = qtrue; } } } From 859cecb424720456395446b84400106a26440bc9 Mon Sep 17 00:00:00 2001 From: Lubos Date: Tue, 10 May 2022 20:35:53 +0200 Subject: [PATCH 4/9] OpenXR getting view matrix simplified --- android/app/src/main/cpp/code/vr/vr_renderer.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/android/app/src/main/cpp/code/vr/vr_renderer.c b/android/app/src/main/cpp/code/vr/vr_renderer.c index 2e4885ab..ca3ee413 100644 --- a/android/app/src/main/cpp/code/vr/vr_renderer.c +++ b/android/app/src/main/cpp/code/vr/vr_renderer.c @@ -393,7 +393,7 @@ void VR_DrawFrame( engine_t* engine ) { projectionInfo.type = XR_TYPE_VIEW_LOCATE_INFO; projectionInfo.viewConfigurationType = engine->appState.ViewportConfig.viewConfigurationType; projectionInfo.displayTime = frameState.predictedDisplayTime; - projectionInfo.space = engine->appState.HeadSpace; + projectionInfo.space = engine->appState.CurrentSpace; XrViewState viewState = {XR_TYPE_VIEW_STATE, NULL}; @@ -410,11 +410,9 @@ void VR_DrawFrame( engine_t* engine ) { // XrFovf fov = {}; - XrPosef viewTransform[2]; + XrPosef invViewTransform[2]; for (int eye = 0; eye < ovrMaxNumEyes; eye++) { - XrPosef xfHeadFromEye = projections[eye].pose; - XrPosef xfStageFromEye = XrPosef_Multiply(xfStageFromHead, xfHeadFromEye); - viewTransform[eye] = XrPosef_Inverse(xfStageFromEye); + invViewTransform[eye] = projections[eye].pose; fov.angleLeft += projections[eye].fov.angleLeft / 2.0f; fov.angleRight += projections[eye].fov.angleRight / 2.0f; @@ -467,7 +465,7 @@ void VR_DrawFrame( engine_t* engine ) { memset(&projection_layer_elements[eye], 0, sizeof(XrCompositionLayerProjectionView)); projection_layer_elements[eye].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW; - projection_layer_elements[eye].pose = XrPosef_Inverse(viewTransform[eye]); + projection_layer_elements[eye].pose = invViewTransform[eye]; projection_layer_elements[eye].fov = fov; memset(&projection_layer_elements[eye].subImage, 0, sizeof(XrSwapchainSubImage)); From d354212c5d0f2a65664ce11e4131a9093473a9aa Mon Sep 17 00:00:00 2001 From: Lubos Date: Tue, 10 May 2022 22:26:55 +0200 Subject: [PATCH 5/9] OpenXR change the way of getting the head position --- android/app/src/main/cpp/code/vr/vr_input.c | 10 +--------- android/app/src/main/cpp/code/vr/vr_input.h | 2 +- android/app/src/main/cpp/code/vr/vr_renderer.c | 14 +++++++------- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/android/app/src/main/cpp/code/vr/vr_input.c b/android/app/src/main/cpp/code/vr/vr_input.c index 1994e005..0afb600c 100644 --- a/android/app/src/main/cpp/code/vr/vr_input.c +++ b/android/app/src/main/cpp/code/vr/vr_input.c @@ -1425,16 +1425,10 @@ void IN_VRUpdateControllers( float predictedDisplayTime ) IN_VRController(qtrue, engine->appState.TrackedController[1].Pose); } -XrPosef IN_VRUpdateHMD( float predictedDisplayTime ) +void IN_VRUpdateHMD( XrPosef xfStageFromHead ) { - engine_t* engine = VR_GetEngine(); - // 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, predictedDisplayTime, &loc)); - XrPosef xfStageFromHead = loc.pose; const XrQuaternionf quatHmd = xfStageFromHead.orientation; const XrVector3f positionHmd = xfStageFromHead.position; vec3_t rotation = {0, 0, 0}; @@ -1457,8 +1451,6 @@ XrPosef IN_VRUpdateHMD( float predictedDisplayTime ) 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; - - return xfStageFromHead; } //#endif diff --git a/android/app/src/main/cpp/code/vr/vr_input.h b/android/app/src/main/cpp/code/vr/vr_input.h index 358cb5fb..02a2f900 100644 --- a/android/app/src/main/cpp/code/vr/vr_input.h +++ b/android/app/src/main/cpp/code/vr/vr_input.h @@ -9,7 +9,7 @@ void IN_VRInputFrame( void ); void IN_VRInit( void ); void IN_VRSyncActions( void ); -XrPosef IN_VRUpdateHMD( float predictedDisplayTime ); +void IN_VRUpdateHMD( XrPosef xfStageFromHead ); void IN_VRUpdateControllers( float predictedDisplayTime ); void QuatToYawPitchRoll(XrQuaternionf q, vec3_t rotation, vec3_t out); diff --git a/android/app/src/main/cpp/code/vr/vr_renderer.c b/android/app/src/main/cpp/code/vr/vr_renderer.c index ca3ee413..5d73ab80 100644 --- a/android/app/src/main/cpp/code/vr/vr_renderer.c +++ b/android/app/src/main/cpp/code/vr/vr_renderer.c @@ -384,11 +384,6 @@ void VR_DrawFrame( engine_t* engine ) { beginFrameDesc.next = NULL; OXR(xrBeginFrame(engine->appState.Session, &beginFrameDesc)); - // Update HMD and controllers - XrPosef xfStageFromHead = IN_VRUpdateHMD( frameState.predictedDisplayTime ); - IN_VRSyncActions(); - IN_VRUpdateControllers( frameState.predictedDisplayTime ); - XrViewLocateInfo projectionInfo = {}; projectionInfo.type = XR_TYPE_VIEW_LOCATE_INFO; projectionInfo.viewConfigurationType = engine->appState.ViewportConfig.viewConfigurationType; @@ -422,6 +417,11 @@ void VR_DrawFrame( engine_t* engine ) { vr.fov_x = (fabs(fov.angleLeft) + fabs(fov.angleRight)) * 180.0f / M_PI; vr.fov_y = (fabs(fov.angleUp) + fabs(fov.angleDown)) * 180.0f / M_PI; + // Update HMD and controllers + IN_VRUpdateHMD( invViewTransform[0] ); + IN_VRSyncActions(); + IN_VRUpdateControllers( frameState.predictedDisplayTime ); + //Projection used for drawing HUD models etc float hudScale = M_PI * 15.0f / 180.0f; const ovrMatrix4f monoVRMatrix = ovrMatrix4f_CreateProjectionFov( @@ -505,9 +505,9 @@ void VR_DrawFrame( engine_t* engine ) { cylinder_layer.subImage.imageArrayIndex = 0; const XrVector3f axis = {0.0f, 1.0f, 0.0f}; XrVector3f pos = { - xfStageFromHead.position.x - sin(radians(vr.menuYaw)) * 4.0f, + invViewTransform[0].position.x - sin(radians(vr.menuYaw)) * 4.0f, -0.25f, - xfStageFromHead.position.z - cos(radians(vr.menuYaw)) * 4.0f + invViewTransform[0].position.z - cos(radians(vr.menuYaw)) * 4.0f }; cylinder_layer.pose.orientation = XrQuaternionf_CreateFromVectorAngle(axis, radians(vr.menuYaw)); cylinder_layer.pose.position = pos; From 5ecbbac97e652c2380cbcd27f2c2adb1c322562a Mon Sep 17 00:00:00 2001 From: Lubos Date: Tue, 10 May 2022 22:30:10 +0200 Subject: [PATCH 6/9] OpenXR restore haptics calling --- android/app/src/main/cpp/code/vr/vr_input.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/android/app/src/main/cpp/code/vr/vr_input.c b/android/app/src/main/cpp/code/vr/vr_input.c index 0afb600c..9fe23a1e 100644 --- a/android/app/src/main/cpp/code/vr/vr_input.c +++ b/android/app/src/main/cpp/code/vr/vr_input.c @@ -228,7 +228,6 @@ void QuatToYawPitchRoll(XrQuaternionf q, vec3_t rotation, vec3_t out) { //0 = left, 1 = right float vibration_channel_duration[2] = {0.0f, 0.0f}; float vibration_channel_intensity[2] = {0.0f, 0.0f}; -qboolean vibration_stopped[2] = {qtrue, qtrue}; void VR_Vibrate( int duration, int chan, float intensity ) { @@ -272,7 +271,6 @@ static void VR_processHaptics() { hapticActionInfo.next = NULL; hapticActionInfo.action = i == 0 ? vibrateLeftFeedback : vibrateRightFeedback; OXR(xrApplyHapticFeedback(VR_GetEngine()->appState.Session, &hapticActionInfo, (const XrHapticBaseHeader*)&vibration)); - vibration_stopped[i] = qfalse; if (vibration_channel_duration[i] != -1.0f) { vibration_channel_duration[i] -= frametime; @@ -282,14 +280,13 @@ static void VR_processHaptics() { vibration_channel_intensity[i] = 0.0f; } } - } else if (!vibration_stopped[i]) { + } else { // Stop haptics XrHapticActionInfo hapticActionInfo = {}; hapticActionInfo.type = XR_TYPE_HAPTIC_ACTION_INFO; hapticActionInfo.next = NULL; hapticActionInfo.action = i == 0 ? vibrateLeftFeedback : vibrateRightFeedback; OXR(xrStopHapticFeedback(VR_GetEngine()->appState.Session, &hapticActionInfo)); - vibration_stopped[i] = qtrue; } } } From 5068ce7199b648d7fb34849b3d85c3e5f7629747 Mon Sep 17 00:00:00 2001 From: Lubos Date: Wed, 11 May 2022 16:11:54 +0200 Subject: [PATCH 7/9] OpenXR recenter after the first frame --- android/app/src/main/cpp/code/vr/vr_renderer.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/android/app/src/main/cpp/code/vr/vr_renderer.c b/android/app/src/main/cpp/code/vr/vr_renderer.c index 5d73ab80..bf8bbd46 100644 --- a/android/app/src/main/cpp/code/vr/vr_renderer.c +++ b/android/app/src/main/cpp/code/vr/vr_renderer.c @@ -24,6 +24,7 @@ extern cvar_t *vr_heightAdjust; XrView* projections; GLboolean stageSupported = GL_FALSE; +GLboolean needRecenter = GL_FALSE; void VR_UpdateStageBounds(ovrApp* pappState) { XrExtent2Df stageBounds = {}; @@ -287,6 +288,7 @@ void VR_InitRenderer( engine_t* engine ) { if (engine->appState.CurrentSpace == XR_NULL_HANDLE) { VR_Recenter(engine); + needRecenter = GL_TRUE; } projections = (XrView*)(malloc(ovrMaxNumEyes * sizeof(XrView))); @@ -534,4 +536,9 @@ void VR_DrawFrame( engine_t* engine ) { OXR(xrEndFrame(engine->appState.Session, &endFrameInfo)); frameBuffer->TextureSwapChainIndex++; frameBuffer->TextureSwapChainIndex %= frameBuffer->TextureSwapChainLength; + + if (needRecenter) { + VR_Recenter(engine); + needRecenter = GL_FALSE; + } } From f2dbc90823c9b0fbea07aef226cc33e3c9feb027 Mon Sep 17 00:00:00 2001 From: Lubos Date: Wed, 11 May 2022 16:51:07 +0200 Subject: [PATCH 8/9] OpenXR controllers coordinates relative to head space --- android/app/src/main/cpp/code/vr/vr_input.c | 6 +++--- android/app/src/main/cpp/code/vr/vr_input.h | 2 +- android/app/src/main/cpp/code/vr/vr_renderer.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/android/app/src/main/cpp/code/vr/vr_input.c b/android/app/src/main/cpp/code/vr/vr_input.c index 9fe23a1e..d47d176c 100644 --- a/android/app/src/main/cpp/code/vr/vr_input.c +++ b/android/app/src/main/cpp/code/vr/vr_input.c @@ -1394,7 +1394,7 @@ void IN_VRSyncActions( void ) getInfo.subactionPath = XR_NULL_PATH; } -void IN_VRUpdateControllers( float predictedDisplayTime ) +void IN_VRUpdateControllers( XrPosef xfStageFromHead, float predictedDisplayTime ) { engine_t* engine = VR_GetEngine(); @@ -1406,10 +1406,10 @@ void IN_VRUpdateControllers( float predictedDisplayTime ) if (ActionPoseIsActive(controller[i], subactionPath[i])) { XrSpaceLocation loc = {}; loc.type = XR_TYPE_SPACE_LOCATION; - OXR(xrLocateSpace(controllerSpace[i], engine->appState.CurrentSpace, predictedDisplayTime, &loc)); + OXR(xrLocateSpace(controllerSpace[i], engine->appState.HeadSpace, predictedDisplayTime, &loc)); engine->appState.TrackedController[i].Active = (loc.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0; - engine->appState.TrackedController[i].Pose = loc.pose; + engine->appState.TrackedController[i].Pose = XrPosef_Multiply(xfStageFromHead, loc.pose); } else { ovrTrackedController_Clear(&engine->appState.TrackedController[i]); } diff --git a/android/app/src/main/cpp/code/vr/vr_input.h b/android/app/src/main/cpp/code/vr/vr_input.h index 02a2f900..3da499a5 100644 --- a/android/app/src/main/cpp/code/vr/vr_input.h +++ b/android/app/src/main/cpp/code/vr/vr_input.h @@ -10,7 +10,7 @@ void IN_VRInputFrame( void ); void IN_VRInit( void ); void IN_VRSyncActions( void ); void IN_VRUpdateHMD( XrPosef xfStageFromHead ); -void IN_VRUpdateControllers( float predictedDisplayTime ); +void IN_VRUpdateControllers( XrPosef xfStageFromHead, float predictedDisplayTime ); void QuatToYawPitchRoll(XrQuaternionf q, vec3_t rotation, vec3_t out); diff --git a/android/app/src/main/cpp/code/vr/vr_renderer.c b/android/app/src/main/cpp/code/vr/vr_renderer.c index bf8bbd46..8d29fb2b 100644 --- a/android/app/src/main/cpp/code/vr/vr_renderer.c +++ b/android/app/src/main/cpp/code/vr/vr_renderer.c @@ -421,8 +421,8 @@ void VR_DrawFrame( engine_t* engine ) { // Update HMD and controllers IN_VRUpdateHMD( invViewTransform[0] ); + IN_VRUpdateControllers( invViewTransform[0], frameState.predictedDisplayTime ); IN_VRSyncActions(); - IN_VRUpdateControllers( frameState.predictedDisplayTime ); //Projection used for drawing HUD models etc float hudScale = M_PI * 15.0f / 180.0f; From 0a3d6137872dec250838f94f7760f0e15fd2656d Mon Sep 17 00:00:00 2001 From: Lubos Date: Fri, 13 May 2022 18:31:16 +0200 Subject: [PATCH 9/9] Revert "OpenXR recenter after the first frame" This reverts commit 5068ce7199b648d7fb34849b3d85c3e5f7629747. --- android/app/src/main/cpp/code/vr/vr_renderer.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/android/app/src/main/cpp/code/vr/vr_renderer.c b/android/app/src/main/cpp/code/vr/vr_renderer.c index 8d29fb2b..0b0a58a9 100644 --- a/android/app/src/main/cpp/code/vr/vr_renderer.c +++ b/android/app/src/main/cpp/code/vr/vr_renderer.c @@ -24,7 +24,6 @@ extern cvar_t *vr_heightAdjust; XrView* projections; GLboolean stageSupported = GL_FALSE; -GLboolean needRecenter = GL_FALSE; void VR_UpdateStageBounds(ovrApp* pappState) { XrExtent2Df stageBounds = {}; @@ -288,7 +287,6 @@ void VR_InitRenderer( engine_t* engine ) { if (engine->appState.CurrentSpace == XR_NULL_HANDLE) { VR_Recenter(engine); - needRecenter = GL_TRUE; } projections = (XrView*)(malloc(ovrMaxNumEyes * sizeof(XrView))); @@ -536,9 +534,4 @@ void VR_DrawFrame( engine_t* engine ) { OXR(xrEndFrame(engine->appState.Session, &endFrameInfo)); frameBuffer->TextureSwapChainIndex++; frameBuffer->TextureSwapChainIndex %= frameBuffer->TextureSwapChainLength; - - if (needRecenter) { - VR_Recenter(engine); - needRecenter = GL_FALSE; - } }