From dbe611a94fa4e3ee5c8da3822346d2eb650379d7 Mon Sep 17 00:00:00 2001 From: elvissteinjr Date: Mon, 23 Jan 2023 18:43:48 +0100 Subject: [PATCH 1/2] Activate laser pointer when controller is pointing the at the overlay using the tip matrix - Replace controller angle check with intersection check that accounts for the controller tip offset - Add some VMatrix implementations from the SDK to allow for basic use of the class - Add functions to convert between VMatrix & HmdMatrix34_t --- L4D2VR/sdk/vector.h | 63 +++++++++++++++++++++++-- L4D2VR/vr.cpp | 110 +++++++++++++++++++++++++++++++++++++++++++- L4D2VR/vr.h | 4 ++ 3 files changed, 171 insertions(+), 6 deletions(-) diff --git a/L4D2VR/sdk/vector.h b/L4D2VR/sdk/vector.h index dbfdf3f..91b26de 100644 --- a/L4D2VR/sdk/vector.h +++ b/L4D2VR/sdk/vector.h @@ -404,13 +404,24 @@ class VMatrix { public: - VMatrix(); + VMatrix() + { + } + VMatrix( vec_t m00, vec_t m01, vec_t m02, vec_t m03, vec_t m10, vec_t m11, vec_t m12, vec_t m13, vec_t m20, vec_t m21, vec_t m22, vec_t m23, vec_t m30, vec_t m31, vec_t m32, vec_t m33 - ); + ) + { + Init( + m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, + m30, m31, m32, m33 + ); + } // Creates a matrix where the X axis = forward // the Y axis = left, and the Z axis = up @@ -426,7 +437,28 @@ class VMatrix vec_t m10, vec_t m11, vec_t m12, vec_t m13, vec_t m20, vec_t m21, vec_t m22, vec_t m23, vec_t m30, vec_t m31, vec_t m32, vec_t m33 - ); + ) + { + m[0][0] = m00; + m[0][1] = m01; + m[0][2] = m02; + m[0][3] = m03; + + m[1][0] = m10; + m[1][1] = m11; + m[1][2] = m12; + m[1][3] = m13; + + m[2][0] = m20; + m[2][1] = m21; + m[2][2] = m22; + m[2][3] = m23; + + m[3][0] = m30; + m[3][1] = m31; + m[3][2] = m32; + m[3][3] = m33; + } // Initialize from a 3x4 @@ -529,7 +561,30 @@ class VMatrix VMatrix &operator=(const VMatrix &mOther); // Multiply two matrices (out = this * vm). - void MatrixMul(const VMatrix &vm, VMatrix &out) const; + void MatrixMul(const VMatrix &vm, VMatrix &out) const + { + out.Init( + m[0][0]*vm.m[0][0] + m[0][1]*vm.m[1][0] + m[0][2]*vm.m[2][0] + m[0][3]*vm.m[3][0], + m[0][0]*vm.m[0][1] + m[0][1]*vm.m[1][1] + m[0][2]*vm.m[2][1] + m[0][3]*vm.m[3][1], + m[0][0]*vm.m[0][2] + m[0][1]*vm.m[1][2] + m[0][2]*vm.m[2][2] + m[0][3]*vm.m[3][2], + m[0][0]*vm.m[0][3] + m[0][1]*vm.m[1][3] + m[0][2]*vm.m[2][3] + m[0][3]*vm.m[3][3], + + m[1][0]*vm.m[0][0] + m[1][1]*vm.m[1][0] + m[1][2]*vm.m[2][0] + m[1][3]*vm.m[3][0], + m[1][0]*vm.m[0][1] + m[1][1]*vm.m[1][1] + m[1][2]*vm.m[2][1] + m[1][3]*vm.m[3][1], + m[1][0]*vm.m[0][2] + m[1][1]*vm.m[1][2] + m[1][2]*vm.m[2][2] + m[1][3]*vm.m[3][2], + m[1][0]*vm.m[0][3] + m[1][1]*vm.m[1][3] + m[1][2]*vm.m[2][3] + m[1][3]*vm.m[3][3], + + m[2][0]*vm.m[0][0] + m[2][1]*vm.m[1][0] + m[2][2]*vm.m[2][0] + m[2][3]*vm.m[3][0], + m[2][0]*vm.m[0][1] + m[2][1]*vm.m[1][1] + m[2][2]*vm.m[2][1] + m[2][3]*vm.m[3][1], + m[2][0]*vm.m[0][2] + m[2][1]*vm.m[1][2] + m[2][2]*vm.m[2][2] + m[2][3]*vm.m[3][2], + m[2][0]*vm.m[0][3] + m[2][1]*vm.m[1][3] + m[2][2]*vm.m[2][3] + m[2][3]*vm.m[3][3], + + m[3][0]*vm.m[0][0] + m[3][1]*vm.m[1][0] + m[3][2]*vm.m[2][0] + m[3][3]*vm.m[3][0], + m[3][0]*vm.m[0][1] + m[3][1]*vm.m[1][1] + m[3][2]*vm.m[2][1] + m[3][3]*vm.m[3][1], + m[3][0]*vm.m[0][2] + m[3][1]*vm.m[1][2] + m[3][2]*vm.m[2][2] + m[3][3]*vm.m[3][2], + m[3][0]*vm.m[0][3] + m[3][1]*vm.m[1][3] + m[3][2]*vm.m[2][3] + m[3][3]*vm.m[3][3] + ); + } // Add two matrices. const VMatrix &operator+=(const VMatrix &other); diff --git a/L4D2VR/vr.cpp b/L4D2VR/vr.cpp index 28ea1d6..76899c3 100644 --- a/L4D2VR/vr.cpp +++ b/L4D2VR/vr.cpp @@ -415,9 +415,13 @@ void VR::ProcessMenuInput() { vr::VROverlayHandle_t currentOverlay = m_Game->m_EngineClient->IsInGame() ? m_HUDHandle : m_MainMenuHandle; + // Check if left or right hand controller is pointing at the overlay + const bool isHoveringOverlay = CheckOverlayIntersectionForController(currentOverlay, vr::TrackedControllerRole_LeftHand) || + CheckOverlayIntersectionForController(currentOverlay, vr::TrackedControllerRole_RightHand); + // Overlays can't process action inputs if the laser is active, so - // only activate laser if the controller is aiming forward. - if (abs(m_RightControllerAngAbs.x) < 45 || abs(m_LeftControllerAngAbs.x) < 45) + // only activate laser if a controller is pointing at the overlay + if (isHoveringOverlay) { vr::VROverlay()->SetOverlayFlag(currentOverlay, vr::VROverlayFlags_MakeOverlaysInteractiveIfVisible, true); @@ -716,6 +720,108 @@ void VR::ProcessInput() } } +VMatrix VR::VMatrixToHmdMatrix(const vr::HmdMatrix34_t &hmdMat) +{ + // VMatrix has a different implicit coordinate system than HmdMatrix34_t, but this function does not convert between them + VMatrix vMat( + hmdMat.m[0][0], hmdMat.m[1][0], hmdMat.m[2][0], 0.0f, + hmdMat.m[0][1], hmdMat.m[1][1], hmdMat.m[2][1], 0.0f, + hmdMat.m[0][2], hmdMat.m[1][2], hmdMat.m[2][2], 0.0f, + hmdMat.m[0][3], hmdMat.m[1][3], hmdMat.m[2][3], 1.0f + ); + + return vMat; +} + +vr::HmdMatrix34_t VR::VMatrixFromHmdMatrix(const VMatrix &vMat) +{ + vr::HmdMatrix34_t hmdMat = {0}; + + hmdMat.m[0][0] = vMat.m[0][0]; + hmdMat.m[1][0] = vMat.m[0][1]; + hmdMat.m[2][0] = vMat.m[0][2]; + + hmdMat.m[0][1] = vMat.m[1][0]; + hmdMat.m[1][1] = vMat.m[1][1]; + hmdMat.m[2][1] = vMat.m[1][2]; + + hmdMat.m[0][2] = vMat.m[2][0]; + hmdMat.m[1][2] = vMat.m[2][1]; + hmdMat.m[2][2] = vMat.m[2][2]; + + hmdMat.m[0][3] = vMat.m[3][0]; + hmdMat.m[1][3] = vMat.m[3][1]; + hmdMat.m[2][3] = vMat.m[3][2]; + + return hmdMat; +} + +vr::HmdMatrix34_t VR::GetControllerTipMatrix(vr::ETrackedControllerRole controllerRole) +{ + vr::VRInputValueHandle_t inputValue = vr::k_ulInvalidInputValueHandle; + + if (controllerRole == vr::TrackedControllerRole_RightHand) + { + m_Input->GetInputSourceHandle("/user/hand/right", &inputValue); + } + else if (controllerRole == vr::TrackedControllerRole_LeftHand) + { + m_Input->GetInputSourceHandle("/user/hand/left", &inputValue); + } + + if (inputValue != vr::k_ulInvalidInputValueHandle) + { + char buffer[vr::k_unMaxPropertyStringSize]; + + m_System->GetStringTrackedDeviceProperty(vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(controllerRole), vr::Prop_RenderModelName_String, + buffer, vr::k_unMaxPropertyStringSize); + + vr::RenderModel_ControllerMode_State_t controllerState = {0}; + vr::RenderModel_ComponentState_t componentState = {0}; + + if (vr::VRRenderModels()->GetComponentStateForDevicePath(buffer, vr::k_pch_Controller_Component_Tip, inputValue, &controllerState, &componentState)) + { + return componentState.mTrackingToComponentLocal; + } + } + + // Not a hand controller role or tip lookup failed, return identity + const vr::HmdMatrix34_t identity = + { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f + }; + + return identity; +} + +bool VR::CheckOverlayIntersectionForController(vr::VROverlayHandle_t overlayHandle, vr::ETrackedControllerRole controllerRole) +{ + vr::TrackedDeviceIndex_t deviceIndex = m_System->GetTrackedDeviceIndexForControllerRole(controllerRole); + + if (deviceIndex == vr::k_unTrackedDeviceIndexInvalid) + return false; + + vr::TrackedDevicePose_t &controllerPose = m_Poses[deviceIndex]; + + if (!controllerPose.bPoseIsValid) + return false; + + VMatrix controllerVMatrix = VMatrixToHmdMatrix(controllerPose.mDeviceToAbsoluteTracking); + VMatrix tipVMatrix = VMatrixToHmdMatrix(GetControllerTipMatrix(controllerRole)); + tipVMatrix.MatrixMul(controllerVMatrix, controllerVMatrix); + + vr::VROverlayIntersectionParams_t params = {0}; + vr::VROverlayIntersectionResults_t results = {0}; + + params.eOrigin = vr::VRCompositor()->GetTrackingSpace(); + params.vSource = { controllerVMatrix.m[3][0], controllerVMatrix.m[3][1], controllerVMatrix.m[3][2]}; + params.vDirection = {-controllerVMatrix.m[2][0], -controllerVMatrix.m[2][1], -controllerVMatrix.m[2][2]}; + + return m_Overlay->ComputeOverlayIntersection(overlayHandle, ¶ms, &results); +} + QAngle VR::GetRightControllerAbsAngle() { return m_RightControllerAngAbs; diff --git a/L4D2VR/vr.h b/L4D2VR/vr.h index 914a3e0..523a215 100644 --- a/L4D2VR/vr.h +++ b/L4D2VR/vr.h @@ -196,6 +196,10 @@ class VR void GetViewParameters(); void ProcessMenuInput(); void ProcessInput(); + VMatrix VMatrixToHmdMatrix(const vr::HmdMatrix34_t &hmdMat); + vr::HmdMatrix34_t VMatrixFromHmdMatrix(const VMatrix &vMat); + vr::HmdMatrix34_t GetControllerTipMatrix(vr::ETrackedControllerRole controllerRole); + bool CheckOverlayIntersectionForController(vr::VROverlayHandle_t overlayHandle, vr::ETrackedControllerRole controllerRole); QAngle GetRightControllerAbsAngle(); Vector GetRightControllerAbsPos(); Vector GetRecommendedViewmodelAbsPos(); From ef66335641ff79c50c24861eccaae74872343f0b Mon Sep 17 00:00:00 2001 From: elvissteinjr Date: Sat, 11 Feb 2023 00:59:31 +0100 Subject: [PATCH 2/2] Swap function names of VMatrixFromHmdMatrix() & VMatrixToHmdMatrix() Oops. --- L4D2VR/vr.cpp | 8 ++++---- L4D2VR/vr.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/L4D2VR/vr.cpp b/L4D2VR/vr.cpp index 76899c3..bb53309 100644 --- a/L4D2VR/vr.cpp +++ b/L4D2VR/vr.cpp @@ -720,7 +720,7 @@ void VR::ProcessInput() } } -VMatrix VR::VMatrixToHmdMatrix(const vr::HmdMatrix34_t &hmdMat) +VMatrix VR::VMatrixFromHmdMatrix(const vr::HmdMatrix34_t &hmdMat) { // VMatrix has a different implicit coordinate system than HmdMatrix34_t, but this function does not convert between them VMatrix vMat( @@ -733,7 +733,7 @@ VMatrix VR::VMatrixToHmdMatrix(const vr::HmdMatrix34_t &hmdMat) return vMat; } -vr::HmdMatrix34_t VR::VMatrixFromHmdMatrix(const VMatrix &vMat) +vr::HmdMatrix34_t VR::VMatrixToHmdMatrix(const VMatrix &vMat) { vr::HmdMatrix34_t hmdMat = {0}; @@ -808,8 +808,8 @@ bool VR::CheckOverlayIntersectionForController(vr::VROverlayHandle_t overlayHand if (!controllerPose.bPoseIsValid) return false; - VMatrix controllerVMatrix = VMatrixToHmdMatrix(controllerPose.mDeviceToAbsoluteTracking); - VMatrix tipVMatrix = VMatrixToHmdMatrix(GetControllerTipMatrix(controllerRole)); + VMatrix controllerVMatrix = VMatrixFromHmdMatrix(controllerPose.mDeviceToAbsoluteTracking); + VMatrix tipVMatrix = VMatrixFromHmdMatrix(GetControllerTipMatrix(controllerRole)); tipVMatrix.MatrixMul(controllerVMatrix, controllerVMatrix); vr::VROverlayIntersectionParams_t params = {0}; diff --git a/L4D2VR/vr.h b/L4D2VR/vr.h index 523a215..11c8fea 100644 --- a/L4D2VR/vr.h +++ b/L4D2VR/vr.h @@ -196,8 +196,8 @@ class VR void GetViewParameters(); void ProcessMenuInput(); void ProcessInput(); - VMatrix VMatrixToHmdMatrix(const vr::HmdMatrix34_t &hmdMat); - vr::HmdMatrix34_t VMatrixFromHmdMatrix(const VMatrix &vMat); + VMatrix VMatrixFromHmdMatrix(const vr::HmdMatrix34_t &hmdMat); + vr::HmdMatrix34_t VMatrixToHmdMatrix(const VMatrix &vMat); vr::HmdMatrix34_t GetControllerTipMatrix(vr::ETrackedControllerRole controllerRole); bool CheckOverlayIntersectionForController(vr::VROverlayHandle_t overlayHandle, vr::ETrackedControllerRole controllerRole); QAngle GetRightControllerAbsAngle();