@@ -415,9 +415,13 @@ void VR::ProcessMenuInput()
415415{
416416 vr::VROverlayHandle_t currentOverlay = m_Game->m_EngineClient ->IsInGame () ? m_HUDHandle : m_MainMenuHandle;
417417
418+ // Check if left or right hand controller is pointing at the overlay
419+ const bool isHoveringOverlay = CheckOverlayIntersectionForController (currentOverlay, vr::TrackedControllerRole_LeftHand) ||
420+ CheckOverlayIntersectionForController (currentOverlay, vr::TrackedControllerRole_RightHand);
421+
418422 // Overlays can't process action inputs if the laser is active, so
419- // only activate laser if the controller is aiming forward.
420- if (abs (m_RightControllerAngAbs. x ) < 45 || abs (m_LeftControllerAngAbs. x ) < 45 )
423+ // only activate laser if a controller is pointing at the overlay
424+ if (isHoveringOverlay )
421425 {
422426 vr::VROverlay ()->SetOverlayFlag (currentOverlay, vr::VROverlayFlags_MakeOverlaysInteractiveIfVisible, true );
423427
@@ -716,6 +720,108 @@ void VR::ProcessInput()
716720 }
717721}
718722
723+ VMatrix VR::VMatrixFromHmdMatrix (const vr::HmdMatrix34_t &hmdMat)
724+ {
725+ // VMatrix has a different implicit coordinate system than HmdMatrix34_t, but this function does not convert between them
726+ VMatrix vMat (
727+ hmdMat.m [0 ][0 ], hmdMat.m [1 ][0 ], hmdMat.m [2 ][0 ], 0 .0f ,
728+ hmdMat.m [0 ][1 ], hmdMat.m [1 ][1 ], hmdMat.m [2 ][1 ], 0 .0f ,
729+ hmdMat.m [0 ][2 ], hmdMat.m [1 ][2 ], hmdMat.m [2 ][2 ], 0 .0f ,
730+ hmdMat.m [0 ][3 ], hmdMat.m [1 ][3 ], hmdMat.m [2 ][3 ], 1 .0f
731+ );
732+
733+ return vMat;
734+ }
735+
736+ vr::HmdMatrix34_t VR::VMatrixToHmdMatrix (const VMatrix &vMat)
737+ {
738+ vr::HmdMatrix34_t hmdMat = {0 };
739+
740+ hmdMat.m [0 ][0 ] = vMat.m [0 ][0 ];
741+ hmdMat.m [1 ][0 ] = vMat.m [0 ][1 ];
742+ hmdMat.m [2 ][0 ] = vMat.m [0 ][2 ];
743+
744+ hmdMat.m [0 ][1 ] = vMat.m [1 ][0 ];
745+ hmdMat.m [1 ][1 ] = vMat.m [1 ][1 ];
746+ hmdMat.m [2 ][1 ] = vMat.m [1 ][2 ];
747+
748+ hmdMat.m [0 ][2 ] = vMat.m [2 ][0 ];
749+ hmdMat.m [1 ][2 ] = vMat.m [2 ][1 ];
750+ hmdMat.m [2 ][2 ] = vMat.m [2 ][2 ];
751+
752+ hmdMat.m [0 ][3 ] = vMat.m [3 ][0 ];
753+ hmdMat.m [1 ][3 ] = vMat.m [3 ][1 ];
754+ hmdMat.m [2 ][3 ] = vMat.m [3 ][2 ];
755+
756+ return hmdMat;
757+ }
758+
759+ vr::HmdMatrix34_t VR::GetControllerTipMatrix (vr::ETrackedControllerRole controllerRole)
760+ {
761+ vr::VRInputValueHandle_t inputValue = vr::k_ulInvalidInputValueHandle;
762+
763+ if (controllerRole == vr::TrackedControllerRole_RightHand)
764+ {
765+ m_Input->GetInputSourceHandle (" /user/hand/right" , &inputValue);
766+ }
767+ else if (controllerRole == vr::TrackedControllerRole_LeftHand)
768+ {
769+ m_Input->GetInputSourceHandle (" /user/hand/left" , &inputValue);
770+ }
771+
772+ if (inputValue != vr::k_ulInvalidInputValueHandle)
773+ {
774+ char buffer[vr::k_unMaxPropertyStringSize];
775+
776+ m_System->GetStringTrackedDeviceProperty (vr::VRSystem ()->GetTrackedDeviceIndexForControllerRole (controllerRole), vr::Prop_RenderModelName_String,
777+ buffer, vr::k_unMaxPropertyStringSize);
778+
779+ vr::RenderModel_ControllerMode_State_t controllerState = {0 };
780+ vr::RenderModel_ComponentState_t componentState = {0 };
781+
782+ if (vr::VRRenderModels ()->GetComponentStateForDevicePath (buffer, vr::k_pch_Controller_Component_Tip, inputValue, &controllerState, &componentState))
783+ {
784+ return componentState.mTrackingToComponentLocal ;
785+ }
786+ }
787+
788+ // Not a hand controller role or tip lookup failed, return identity
789+ const vr::HmdMatrix34_t identity =
790+ {
791+ 1 .0f , 0 .0f , 0 .0f , 0 .0f ,
792+ 0 .0f , 1 .0f , 0 .0f , 0 .0f ,
793+ 0 .0f , 0 .0f , 1 .0f , 0 .0f
794+ };
795+
796+ return identity;
797+ }
798+
799+ bool VR::CheckOverlayIntersectionForController (vr::VROverlayHandle_t overlayHandle, vr::ETrackedControllerRole controllerRole)
800+ {
801+ vr::TrackedDeviceIndex_t deviceIndex = m_System->GetTrackedDeviceIndexForControllerRole (controllerRole);
802+
803+ if (deviceIndex == vr::k_unTrackedDeviceIndexInvalid)
804+ return false ;
805+
806+ vr::TrackedDevicePose_t &controllerPose = m_Poses[deviceIndex];
807+
808+ if (!controllerPose.bPoseIsValid )
809+ return false ;
810+
811+ VMatrix controllerVMatrix = VMatrixFromHmdMatrix (controllerPose.mDeviceToAbsoluteTracking );
812+ VMatrix tipVMatrix = VMatrixFromHmdMatrix (GetControllerTipMatrix (controllerRole));
813+ tipVMatrix.MatrixMul (controllerVMatrix, controllerVMatrix);
814+
815+ vr::VROverlayIntersectionParams_t params = {0 };
816+ vr::VROverlayIntersectionResults_t results = {0 };
817+
818+ params.eOrigin = vr::VRCompositor ()->GetTrackingSpace ();
819+ params.vSource = { controllerVMatrix.m [3 ][0 ], controllerVMatrix.m [3 ][1 ], controllerVMatrix.m [3 ][2 ]};
820+ params.vDirection = {-controllerVMatrix.m [2 ][0 ], -controllerVMatrix.m [2 ][1 ], -controllerVMatrix.m [2 ][2 ]};
821+
822+ return m_Overlay->ComputeOverlayIntersection (overlayHandle, ¶ms, &results);
823+ }
824+
719825QAngle VR::GetRightControllerAbsAngle ()
720826{
721827 return m_RightControllerAngAbs;
0 commit comments