From 4d61896403362d7300b88dcd76f6150174a2ca2c Mon Sep 17 00:00:00 2001 From: Lubos Date: Tue, 21 Nov 2023 23:07:58 +0100 Subject: [PATCH] OpenXR - Projection matrix on Quest 3 fixed --- Common/VR/PPSSPPVR.cpp | 57 +++++++++++++-------------------------- Core/Config.cpp | 1 - Core/Config.h | 1 - UI/GameSettingsScreen.cpp | 1 - 4 files changed, 18 insertions(+), 42 deletions(-) diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index 83486dded8..84c76e970b 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -26,13 +26,6 @@ #include "Core/KeyMap.h" #include "Core/System.h" -enum VRMatrix { - VR_PROJECTION_MATRIX, - VR_VIEW_MATRIX_LEFT_EYE, - VR_VIEW_MATRIX_RIGHT_EYE, - VR_MATRIX_COUNT -}; - enum VRMirroring { VR_MIRRORING_AXIS_X, VR_MIRRORING_AXIS_Y, @@ -51,9 +44,10 @@ static int vr3DGeometryCount = 0; static long vrCompat[VR_COMPAT_MAX]; static bool vrFlatForced = false; static bool vrFlatGame = false; -static float vrMatrix[VR_MATRIX_COUNT][16]; +static double vrFov[2] = {}; static bool vrMirroring[VR_MIRRORING_COUNT]; static int vrMirroringVariant = 0; +static float vrViewMatrix[2][16]; static XrView vrView[2]; static void (*cbNativeAxis)(const AxisInput *axis, size_t count); @@ -642,28 +636,16 @@ bool StartVRRender() { } UpdateVRViewMatrices(); - // Update projection matrix + // Calculate field of view XrFovf fov = {}; - for (int eye = 0; eye < ovrMaxNumEyes; eye++) { - fov.angleLeft += vrView[eye].fov.angleLeft / 2.0f; - fov.angleRight += vrView[eye].fov.angleRight / 2.0f; - fov.angleUp += vrView[eye].fov.angleUp / 2.0f; - fov.angleDown += vrView[eye].fov.angleDown / 2.0f; + for (auto & eye : vrView) { + fov.angleLeft += eye.fov.angleLeft / 2.0f; + fov.angleRight += eye.fov.angleRight / 2.0f; + fov.angleUp += eye.fov.angleUp / 2.0f; + fov.angleDown += eye.fov.angleDown / 2.0f; } - float nearZ = g_Config.fFieldOfViewPercentage / 200.0f; - float tanAngleLeft = tanf(fov.angleLeft); - float tanAngleRight = tanf(fov.angleRight); - float tanAngleDown = tanf(fov.angleDown); - float tanAngleUp = tanf(fov.angleUp); - float M[16] = {}; - M[0] = 2 / (tanAngleRight - tanAngleLeft); - M[2] = (tanAngleRight + tanAngleLeft) / (tanAngleRight - tanAngleLeft); - M[5] = 2 / (tanAngleUp - tanAngleDown); - M[6] = (tanAngleUp + tanAngleDown) / (tanAngleUp - tanAngleDown); - M[10] = -1; - M[11] = -(nearZ + nearZ); - M[14] = -1; - memcpy(vrMatrix[VR_PROJECTION_MATRIX], M, sizeof(float) * 16); + vrFov[0] = 2.0 / (tan(fov.angleRight) - tan(fov.angleLeft)); + vrFov[1] = 2.0 / (tan(fov.angleUp) - tan(fov.angleDown)); // Decide if the scene is 3D or not VR_SetConfigFloat(VR_CONFIG_CANVAS_ASPECT, 480.0f / 272.0f); @@ -808,19 +790,16 @@ void UpdateVRParams(float* projMatrix) { } void UpdateVRProjection(float* projMatrix, float* leftEye, float* rightEye) { - float* hmdProjection = vrMatrix[VR_PROJECTION_MATRIX]; - for (int i = 0; i < 16; i++) { - if ((hmdProjection[i] > 0) != (projMatrix[i] > 0)) { - hmdProjection[i] *= -1.0f; - } - } + float hmdProjection[16]; + memcpy(hmdProjection, projMatrix, 16 * sizeof(float)); + hmdProjection[0] = vrFov[0]; + hmdProjection[5] = vrFov[1]; memcpy(leftEye, hmdProjection, 16 * sizeof(float)); memcpy(rightEye, hmdProjection, 16 * sizeof(float)); } void UpdateVRView(float* leftEye, float* rightEye) { float* dst[] = {leftEye, rightEye}; - float* matrix[] = {vrMatrix[VR_VIEW_MATRIX_LEFT_EYE], vrMatrix[VR_VIEW_MATRIX_RIGHT_EYE]}; for (int index = 0; index < 2; index++) { // Validate the view matrix @@ -834,7 +813,7 @@ void UpdateVRView(float* leftEye, float* rightEye) { // Get view matrix from the headset Lin::Matrix4x4 hmdView = {}; - memcpy(hmdView.m, matrix[index], 16 * sizeof(float)); + memcpy(hmdView.m, vrViewMatrix[index], 16 * sizeof(float)); // Combine the matrices Lin::Matrix4x4 renderView = hmdView * gameView; @@ -943,12 +922,12 @@ void UpdateVRViewMatrices() { M[11] += side.z; } - for (int matrix = VR_VIEW_MATRIX_LEFT_EYE; matrix <= VR_VIEW_MATRIX_RIGHT_EYE; matrix++) { + for (int eye = 0; eye < ovrMaxNumEyes; eye++) { // Stereoscopy bool vrStereo = !PSP_CoreParameter().compat.vrCompat().ForceMono && g_Config.bEnableStereo; if (vrStereo) { - bool mirrored = vrMirroring[VR_MIRRORING_AXIS_Z] ^ (matrix == VR_VIEW_MATRIX_RIGHT_EYE); + bool mirrored = vrMirroring[VR_MIRRORING_AXIS_Z] ^ (eye == 1); float dx = fabs(vrView[1].pose.position.x - vrView[0].pose.position.x); float dy = fabs(vrView[1].pose.position.y - vrView[0].pose.position.y); float dz = fabs(vrView[1].pose.position.z - vrView[0].pose.position.z); @@ -961,6 +940,6 @@ void UpdateVRViewMatrices() { M[11] += separation.z; } - memcpy(vrMatrix[matrix], M, sizeof(float) * 16); + memcpy(vrViewMatrix[eye], M, sizeof(float) * 16); } } diff --git a/Core/Config.cpp b/Core/Config.cpp index 2aca9cafc3..82df658513 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -935,7 +935,6 @@ static const ConfigSetting vrSettings[] = { ConfigSetting("VRCameraPitch", &g_Config.iCameraPitch, 0, CfgFlag::PER_GAME), ConfigSetting("VRCanvasDistance", &g_Config.fCanvasDistance, 12.0f, CfgFlag::DEFAULT), ConfigSetting("VRCanvas3DDistance", &g_Config.fCanvas3DDistance, 3.0f, CfgFlag::DEFAULT), - ConfigSetting("VRFieldOfView", &g_Config.fFieldOfViewPercentage, 100.0f, CfgFlag::PER_GAME), ConfigSetting("VRHeadUpDisplayScale", &g_Config.fHeadUpDisplayScale, 0.3f, CfgFlag::PER_GAME), ConfigSetting("VRMotionLength", &g_Config.fMotionLength, 0.5f, CfgFlag::DEFAULT), ConfigSetting("VRHeadRotationScale", &g_Config.fHeadRotationScale, 5.0f, CfgFlag::PER_GAME), diff --git a/Core/Config.h b/Core/Config.h index e05a4b5fbf..e7b19e573b 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -442,7 +442,6 @@ public: float fCameraSide; float fCanvasDistance; float fCanvas3DDistance; - float fFieldOfViewPercentage; float fHeadUpDisplayScale; float fMotionLength; float fHeadRotationScale; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 0ed4537fc8..a56191a77f 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1170,7 +1170,6 @@ void GameSettingsScreen::CreateVRSettings(UI::ViewGroup *vrSettings) { vrSettings->Add(new ItemHeader(vr->T("VR camera"))); vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fCanvasDistance, 1.0f, 15.0f, 12.0f, vr->T("Distance to 2D menus and scenes"), 1.0f, screenManager(), "")); vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fCanvas3DDistance, 1.0f, 15.0f, 3.0f, vr->T("Distance to 3D scenes when VR disabled"), 1.0f, screenManager(), "")); - vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fFieldOfViewPercentage, 100.0f, 200.0f, 100.0f, vr->T("Field of view scale"), 10.0f, screenManager(), vr->T("% of native FoV"))); vrSettings->Add(new CheckBox(&g_Config.bRescaleHUD, vr->T("Heads-up display detection"))); PopupSliderChoiceFloat* vrHudScale = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fHeadUpDisplayScale, 0.0f, 1.5f, 0.3f, vr->T("Heads-up display scale"), 0.1f, screenManager(), "")); vrHudScale->SetEnabledPtr(&g_Config.bRescaleHUD);