//====== Copyright Valve Corporation, All rights reserved. ======= #include "overlay.h" #include #include #include #include // Make sure this is correctly included #include #include namespace fs = std::filesystem; using namespace vr; #pragma region init OverlayInterface *s_pSharedVRController = NULL; OverlayInterface *OverlayInterface::SharedInstance() { if ( !s_pSharedVRController ) { s_pSharedVRController = new OverlayInterface(); } return s_pSharedVRController; } OverlayInterface::OverlayInterface() : m_strVRDriver( "No Driver" ) , m_strVRDisplay( "No Display" ) , m_eLastHmdError( vr::VRInitError_None ) , m_eCompositorError( vr::VRInitError_None ) , m_eOverlayError( vr::VRInitError_None ) , m_ulOverlayHandle( vr::k_ulOverlayHandleInvalid ) , m_pWidget( NULL ) { } OverlayInterface::~OverlayInterface() { } #pragma endregion vr::VROverlayHandle_t OverlayInterface::CreateInteractiveOverlay(const std::string& overlayName) { bool bSuccess = true; m_strName = overlayName; bSuccess = ConnectToVRRuntime(); bSuccess = bSuccess && vr::VRCompositor() != NULL; if( vr::VROverlay() ) { // vr::VROverlayHandle_t m_ulOverlayThumbnailHandle; std::string sKey = std::string( "sample." ) + m_strName; vr::VROverlayError overlayError = vr::VROverlay()->CreateOverlay( sKey.c_str(), m_strName.c_str(), &m_ulOverlayHandle ); bSuccess = bSuccess && overlayError == vr::VROverlayError_None; } if ( bSuccess ) { vr::VROverlay()->SetOverlayWidthInMeters(m_ulOverlayHandle, 0.2f); vr::VROverlay()->SetOverlayInputMethod(m_ulOverlayHandle, vr::VROverlayInputMethod_Mouse); /* vr::VROverlay()->SetOverlayColor(m_ulOverlayHandle, 1.0f, 0.0f, 1.0f); */ std::string relativePath = "../resources/PetPlay.png"; try { fs::path absolutePath = fs::absolute(relativePath); if (fs::exists(absolutePath)) { std::cout << "Absolute path: " << absolutePath << std::endl; // Correct usage of SetOverlayFromFile if it takes two arguments vr::VROverlay()->SetOverlayFromFile(m_ulOverlayHandle, absolutePath.string().c_str()); } else { std::cout << "File not found at: " << absolutePath << std::endl; } } catch (const fs::filesystem_error& e) { std::cerr << "Filesystem error: " << e.what() << std::endl; } catch (const std::exception& e) { std::cerr << "General error: " << e.what() << std::endl; } HmdMatrix34_t transformMatrix; //vr::VROverlay()->ShowKeyboardForOverlay(m_ulOverlayHandle, vr::EGamepadTextInputMode::k_EGamepadTextInputModeNormal, vr::EGamepadTextInputLineMode::k_EGamepadTextInputLineModeSingleLine); // Set the values of the matrix to represent your desired transformation // For example, to set the matrix to the identity matrix (no transformation) transformMatrix.m[0][0] = 1.0f; transformMatrix.m[0][1] = 0.0f; transformMatrix.m[0][2] = 0.0f; transformMatrix.m[0][3] = 0.0f; transformMatrix.m[1][0] = 0.0f; transformMatrix.m[1][1] = 1.0f; transformMatrix.m[1][2] = 0.0f; transformMatrix.m[1][3] = 0.0f; transformMatrix.m[2][0] = 0.0f; transformMatrix.m[2][1] = 0.0f; transformMatrix.m[2][2] = 1.0f; transformMatrix.m[2][3] = 0.0f; vr::VROverlay()->SetOverlayTransformAbsolute(m_ulOverlayHandle, vr::TrackingUniverseStanding, &transformMatrix); vr::VROverlay()->ShowOverlay(m_ulOverlayHandle); } return m_ulOverlayHandle; } vr::VROverlayHandle_t OverlayInterface::CreateAlignmentOverlay(bool mode) { if (mode) { std::cout << "p1" << std::endl; } else { std::cout << "p2" << std::endl; } bool bSuccess = true; m_strName = "alignmentoverlay"; bSuccess = ConnectToVRRuntime(); bSuccess = bSuccess && vr::VRCompositor() != NULL; if( vr::VROverlay() ) { // vr::VROverlayHandle_t m_ulOverlayThumbnailHandle; std::string sKey = std::string( "sample." ) + m_strName; vr::VROverlayError overlayError = vr::VROverlay()->CreateOverlay( sKey.c_str(), m_strName.c_str(), &m_ulOverlayHandle ); bSuccess = bSuccess && overlayError == vr::VROverlayError_None; } if ( bSuccess ) { vr::VROverlay()->SetOverlayWidthInMeters(m_ulOverlayHandle, 0.2f); vr::VROverlay()->SetOverlayInputMethod(m_ulOverlayHandle, vr::VROverlayInputMethod_Mouse); /* vr::VROverlay()->SetOverlayColor(m_ulOverlayHandle, 1.0f, 0.0f, 1.0f); */ std::string relativePath = ""; if (mode) { relativePath = "../resources/P1.png"; } else { relativePath = "../resources/P2.png"; } try { fs::path absolutePath = fs::absolute(relativePath); if (fs::exists(absolutePath)) { std::cout << "Absolute path: " << absolutePath << std::endl; // Correct usage of SetOverlayFromFile if it takes two arguments vr::VROverlay()->SetOverlayFromFile(m_ulOverlayHandle, absolutePath.string().c_str()); } else { std::cout << "File not found at: " << absolutePath << std::endl; } } catch (const fs::filesystem_error& e) { std::cerr << "Filesystem error: " << e.what() << std::endl; } catch (const std::exception& e) { std::cerr << "General error: " << e.what() << std::endl; } HmdMatrix34_t transformMatrix; //vr::VROverlay()->ShowKeyboardForOverlay(m_ulOverlayHandle, vr::EGamepadTextInputMode::k_EGamepadTextInputModeNormal, vr::EGamepadTextInputLineMode::k_EGamepadTextInputLineModeSingleLine); // ALIGNMENT MATRIX transformMatrix.m[0][0] = 1.0f; transformMatrix.m[0][1] = 0.0f; transformMatrix.m[0][2] = 0.0f; transformMatrix.m[0][3] = 0.0f; transformMatrix.m[1][0] = 0.0f; transformMatrix.m[1][1] = 0.0f; transformMatrix.m[1][2] = 0.0f; transformMatrix.m[1][3] = 0.0f; transformMatrix.m[2][0] = 0.0f; transformMatrix.m[2][1] = -1.0f; transformMatrix.m[2][2] = 1.0f; transformMatrix.m[2][3] = 0.0f; vr::VROverlay()->SetOverlayTransformAbsolute(m_ulOverlayHandle, vr::TrackingUniverseStanding, &transformMatrix); vr::VROverlay()->ShowOverlay(m_ulOverlayHandle); } return m_ulOverlayHandle; } vr::VROverlayHandle_t OverlayInterface::CreateBasicOverlay(const std::string& overlayName, const std::string& texpath ) { bool bSuccess = true; m_strName = overlayName; bSuccess = ConnectToVRRuntime(); bSuccess = bSuccess && vr::VRCompositor() != NULL; // Create the overlay if( vr::VROverlay() ) { // vr::VROverlayHandle_t m_ulOverlayThumbnailHandle; std::string sKey = std::string( "sample." ) + m_strName; vr::VROverlayError overlayError = vr::VROverlay()->CreateOverlay( sKey.c_str(), m_strName.c_str(), &m_ulOverlayHandle ); bSuccess = bSuccess && overlayError == vr::VROverlayError_None; } // if successful, set overlay properties if ( bSuccess ) { vr::VROverlay()->SetOverlayWidthInMeters(m_ulOverlayHandle, 0.2f); vr::VROverlay()->SetOverlayInputMethod(m_ulOverlayHandle, vr::VROverlayInputMethod_Mouse); /* vr::VROverlay()->SetOverlayColor(m_ulOverlayHandle, 1.0f, 0.0f, 1.0f); */ fs::path absolutePath = texpath; if (fs::exists(absolutePath)) { vr::VROverlay()->SetOverlayFromFile(m_ulOverlayHandle, absolutePath.string().c_str()); } else { std::cerr << "File not found at: " << absolutePath << std::endl; } HmdMatrix34_t transformMatrix; // Set the values of the matrix to represent your desired transformation // For example, to set the matrix to the identity matrix (no transformation) transformMatrix.m[0][0] = 1.0f; transformMatrix.m[0][1] = 0.0f; transformMatrix.m[0][2] = 0.0f; transformMatrix.m[0][3] = 0.0f; transformMatrix.m[1][0] = 0.0f; transformMatrix.m[1][1] = 1.0f; transformMatrix.m[1][2] = 0.0f; transformMatrix.m[1][3] = 0.0f; transformMatrix.m[2][0] = 0.0f; transformMatrix.m[2][1] = 0.0f; transformMatrix.m[2][2] = 1.0f; transformMatrix.m[2][3] = 0.0f; vr::VROverlay()->SetOverlayTransformAbsolute(m_ulOverlayHandle, vr::TrackingUniverseStanding, &transformMatrix); vr::VROverlay()->ShowOverlay(m_ulOverlayHandle); } return m_ulOverlayHandle; } #pragma region helpers std::string GetTrackedDeviceString(vr::IVRSystem *pHmd, vr::TrackedDeviceIndex_t unDevice, vr::TrackedDeviceProperty prop) { char buf[128]; vr::TrackedPropertyError err; pHmd->GetStringTrackedDeviceProperty( unDevice, prop, buf, sizeof( buf ), &err ); if (err != vr::TrackedProp_Success) { return std::string("Error Getting String: ") + pHmd->GetPropErrorNameFromEnum(err); } else { return buf; } } #pragma endregion #pragma region overlay movement bool OverlayInterface::IsGrippingOverlay(vr::IVRSystem* pVRSystem, vr::VROverlayHandle_t overlayHandle, vr::TrackedDeviceIndex_t controllerIndex) { // Get the controller's pose vr::TrackedDevicePose_t controllerPose; pVRSystem->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0, &controllerPose, 1); // Check if the controller is valid if (!controllerPose.bPoseIsValid) { return false; } // Convert the controller's pose to a matrix vr::HmdMatrix34_t controllerMatrix = controllerPose.mDeviceToAbsoluteTracking; // Project a ray from the controller vr::HmdVector3_t rayOrigin = {controllerMatrix.m[0][3], controllerMatrix.m[1][3], controllerMatrix.m[2][3]}; vr::HmdVector3_t rayDirection = {0, 0, -1}; // Assuming the controller is pointing forward // Check for intersection with the overlay vr::VROverlayIntersectionParams_t params; params.eOrigin = vr::TrackingUniverseStanding; params.vSource.v[0] = rayOrigin.v[0]; params.vSource.v[1] = rayOrigin.v[1]; params.vSource.v[2] = rayOrigin.v[2]; params.vDirection.v[0] = rayDirection.v[0]; params.vDirection.v[1] = rayDirection.v[1]; params.vDirection.v[2] = rayDirection.v[2]; vr::VROverlayIntersectionResults_t results; // If the intersection was successful, the controller is gripping the overlay bool isIntersecting = vr::VROverlay()->ComputeOverlayIntersection(overlayHandle, ¶ms, &results); if (!isIntersecting) { // Calculate the distance from the controller's ray to the overlay float distanceToOverlay = CalculateDistanceToOverlay(rayOrigin, rayDirection, overlayHandle); std::cout << "Missed overlay by: " << distanceToOverlay << " units" << std::endl; // Check if the distance is within the threshold for a successful grab float threshold = 0.8f; // Set the threshold value if (distanceToOverlay < threshold) { return true; // Consider it a successful grab if the distance is less than the threshold } } return isIntersecting; } vr::HmdMatrix34_t OverlayInterface::GetOverlayPos(VROverlayHandle_t m_ulOverlayHandle, HmdVector2_t *m_vOverlayPosition) { HmdMatrix34_t matTransform; vr::ETrackingUniverseOrigin eTrackingOrigin = vr::ETrackingUniverseOrigin::TrackingUniverseStanding; vr::EVROverlayError error = vr::VROverlay()->GetTransformForOverlayCoordinates(m_ulOverlayHandle, eTrackingOrigin, *m_vOverlayPosition, &matTransform); if (error != vr::VROverlayError_None) { // Handle error } return matTransform; } void LogHMDAndControllersPositions(vr::IVRSystem* pVRSystem) { // Define the tracking universe origin vr::ETrackingUniverseOrigin eTrackingOrigin = vr::TrackingUniverseStanding; // Define the prediction time (0 for the most current data) float fPredictionTime = 0.0f; // Allocate an array to hold the poses vr::TrackedDevicePose_t poses[vr::k_unMaxTrackedDeviceCount]; // Get the poses for all devices pVRSystem->GetDeviceToAbsoluteTrackingPose(eTrackingOrigin, fPredictionTime, poses, vr::k_unMaxTrackedDeviceCount); // Iterate through all tracked devices for (vr::TrackedDeviceIndex_t unDevice = 0; unDevice < vr::k_unMaxTrackedDeviceCount; ++unDevice) { // Check if the device is connected if (!pVRSystem->IsTrackedDeviceConnected(unDevice)) continue; // Get the device class vr::ETrackedDeviceClass deviceClass = pVRSystem->GetTrackedDeviceClass(unDevice); // Initialize a string to hold the device type std::string deviceType = "Unknown"; // Check if the device is an HMD, left controller, or right controller if (deviceClass == vr::TrackedDeviceClass_HMD) { deviceType = "HMD"; } else if (deviceClass == vr::TrackedDeviceClass_Controller) { // Check if it's the left or right controller vr::ETrackedControllerRole role = pVRSystem->GetControllerRoleForTrackedDeviceIndex(unDevice); if (role == vr::TrackedControllerRole_LeftHand) { deviceType = "Left Controller"; } else if (role == vr::TrackedControllerRole_RightHand) { deviceType = "Right Controller"; } } // Get the pose for the device vr::TrackedDevicePose_t& pose = poses[unDevice]; // Check if the pose is valid if (pose.bPoseIsValid) { // Extract the position from the pose vr::HmdVector3_t position = {pose.mDeviceToAbsoluteTracking.m[0][3], pose.mDeviceToAbsoluteTracking.m[1][3], pose.mDeviceToAbsoluteTracking.m[2][3]}; // Log the position with the device type //std::cout << deviceType << " Position: (" << position.v[0] << ", " << position.v[1] << ", " << position.v[2] << ")" << std::endl; } } } void OverlayInterface::SetOverlayPosition(vr::VROverlayHandle_t overlayHandle, vr::HmdMatrix34_t overlayPosition) { //overlayPosition.m[0][3] *= -1; // Set the overlay's transform to the controller's transform vr::VROverlay()->SetOverlayTransformAbsolute(overlayHandle, vr::TrackingUniverseStanding, &overlayPosition); } void OverlayInterface::SetOverlayPositionToController(vr::IVRSystem* pVRSystem, vr::VROverlayHandle_t overlayHandle, vr::TrackedDeviceIndex_t controllerIndex) { LogHMDAndControllersPositions(pVRSystem); // Log all device positions (for debugging purposes) std::cout << "Controller device id : " << controllerIndex << std::endl; // Allocate an array of TrackedDevicePose_t to hold the poses vr::TrackedDevicePose_t poses[vr::k_unMaxTrackedDeviceCount]; // Get the poses for all devices pVRSystem->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0, poses, vr::k_unMaxTrackedDeviceCount); // Check if the controller is valid if (!poses[controllerIndex].bPoseIsValid) { return; // Exit the function if the controller's pose is not valid } // Convert the controller's pose to a matrix vr::HmdMatrix34_t transformMatrix = poses[controllerIndex].mDeviceToAbsoluteTracking; // Set the overlay's transform to the controller's transform vr::VROverlay()->SetOverlayTransformAbsolute(overlayHandle, vr::TrackingUniverseStanding, &transformMatrix); } void OverlayInterface::UpdateButtonState(vr::IVRSystem* pVRSystem, vr::TrackedDeviceIndex_t controllerIndex, vr::EVRButtonId buttonId) { vr::VRControllerState_t controllerState; if (pVRSystem->GetControllerState(controllerIndex, &controllerState, sizeof(controllerState))) { bool isPressed = controllerState.ulButtonPressed & vr::ButtonMaskFromId(buttonId); ButtonState& state = buttonStates[controllerIndex][buttonId]; state.wasPressed = state.isPressed; state.isPressed = isPressed; } } void OverlayInterface::HandleVRInput(vr::IVRSystem* pVRSystem, VROverlayHandle_t pOverlayToCheckFor) { // Define the tracking universe origin vr::ETrackingUniverseOrigin eTrackingOrigin = vr::ETrackingUniverseOrigin::TrackingUniverseStanding; // Define the prediction time (0 for the most current data) float fPredictionTime = 0.0f; // Allocate an array to hold the poses vr::TrackedDevicePose_t poses[vr::k_unMaxTrackedDeviceCount]; // Get the poses for all devices pVRSystem->GetDeviceToAbsoluteTrackingPose(eTrackingOrigin, fPredictionTime, poses, vr::k_unMaxTrackedDeviceCount); vr::TrackedDeviceIndex_t leftControllerIndex = vr::k_unTrackedDeviceIndexInvalid; vr::TrackedDeviceIndex_t rightControllerIndex = vr::k_unTrackedDeviceIndexInvalid; // Iterate through all tracked devices to find the left and right controllers for (vr::TrackedDeviceIndex_t unDevice = 0; unDevice < vr::k_unMaxTrackedDeviceCount; ++unDevice) { // Check if the device is connected if (!pVRSystem->IsTrackedDeviceConnected(unDevice)) continue; // Get the device class vr::ETrackedDeviceClass deviceClass = pVRSystem->GetTrackedDeviceClass(unDevice); // Check if the device is a controller if (deviceClass == vr::TrackedDeviceClass_Controller) { // Check if it's the left or right controller vr::ETrackedControllerRole role = pVRSystem->GetControllerRoleForTrackedDeviceIndex(unDevice); if (role == vr::TrackedControllerRole_LeftHand) { leftControllerIndex = unDevice; } else if (role == vr::TrackedControllerRole_RightHand) { rightControllerIndex = unDevice; } } } // Update the state for each button UpdateButtonState(pVRSystem, leftControllerIndex, vr::k_EButton_Grip); UpdateButtonState(pVRSystem, rightControllerIndex, vr::k_EButton_Grip); OverlayInterface::ButtonState leftControllerButtonState = buttonStates[leftControllerIndex][vr::k_EButton_Grip]; OverlayInterface::ButtonState rightControllerButtonState = buttonStates[rightControllerIndex][vr::k_EButton_Grip]; if (leftControllerButtonState.isPressed) { printf("Grip button is held!\n"); if (IsControllerCloseToOverlay(pVRSystem, pOverlayToCheckFor, leftControllerIndex) && !isGripped) { isGripped = true; currentControllerGrippingOverlay = leftControllerIndex; printf("Left Controller Gripped Overlay!\n"); return; } } if (rightControllerButtonState.isPressed) { printf("Grip button is held!\n"); if(IsControllerCloseToOverlay(pVRSystem, pOverlayToCheckFor, rightControllerIndex) && !isGripped) { isGripped = true; currentControllerGrippingOverlay = rightControllerIndex; printf("Right Controller Gripped Overlay!\n"); return; } } if ((!leftControllerButtonState.isPressed) && (!rightControllerButtonState.isPressed)) { if (isGripped) { isGripped = false; currentControllerGrippingOverlay = vr::k_unTrackedDeviceIndexInvalid; // Reset to invalid index } } } float OverlayInterface::CalculateDistanceToOverlay(const vr::HmdVector3_t& rayOrigin, const vr::HmdVector3_t& rayDirection, vr::VROverlayHandle_t overlayHandle) { if (overlayHandle != vr::k_ulOverlayHandleInvalid) { vr::HmdMatrix34_t overlayMatrix; vr::ETrackingUniverseOrigin trackingUniverseOrigin = vr::TrackingUniverseStanding; vr::EVROverlayError error = vr::VROverlay()->GetOverlayTransformAbsolute(overlayHandle, &trackingUniverseOrigin, &overlayMatrix); if (error != vr::VROverlayError_None) { std::cerr << "Error getting overlay transform: " << error << std::endl; return -1.0f; // Return an error value } // Proceed with the rest of your code to calculate the distance } else { std::cerr << "Invalid overlay handle" << std::endl; return -1.0f; // Return an error value } // Assuming the overlay is flat and oriented along the Z-axis vr::HmdVector3_t overlayNormal = {0, 0, 1}; // Normal vector of the overlay (assuming it's flat and oriented along the Z-axis) // Get the overlay's transformation matrix vr::HmdMatrix34_t overlayMatrix; vr::ETrackingUniverseOrigin trackingUniverseOrigin = vr::TrackingUniverseStanding; vr::EVROverlayError error = vr::VROverlay()->GetOverlayTransformAbsolute(overlayHandle, &trackingUniverseOrigin, &overlayMatrix); if (error != vr::VROverlayError_None) { std::cerr << "Error getting overlay transform: " << error << std::endl; return -1.0f; // Return an error value } // Calculate the overlay's center vr::HmdVector3_t overlayCenter = {overlayMatrix.m[0][3], overlayMatrix.m[1][3], overlayMatrix.m[2][3]}; // Corrected calculation // Calculate the distance from the ray origin to the overlay vr::HmdVector3_t pointToPlane = {overlayCenter.v[0] - rayOrigin.v[0], overlayCenter.v[1] - rayOrigin.v[1], overlayCenter.v[2] - rayOrigin.v[2]}; float distance = std::abs(pointToPlane.v[0] * overlayNormal.v[0] + pointToPlane.v[1] * overlayNormal.v[1] + pointToPlane.v[2] * overlayNormal.v[2]) / std::sqrt(overlayNormal.v[0] * overlayNormal.v[0] + overlayNormal.v[1] * overlayNormal.v[1] + overlayNormal.v[2] * overlayNormal.v[2]); return distance; } std::map OverlayInterface::GetControllerIndexes(vr::IVRSystem* pVRSystem, vr::VROverlayHandle_t overlayHandle) { int counter = 0; for (vr::TrackedDeviceIndex_t unDevice = 0; unDevice < vr::k_unMaxTrackedDeviceCount; ++unDevice) { if (!pVRSystem->IsTrackedDeviceConnected(unDevice)) continue; // Check if the device is a controller if (pVRSystem->GetTrackedDeviceClass(unDevice) == vr::TrackedDeviceClass_Controller) { controllerIndexes[counter] = unDevice; counter++; } } return controllerIndexes; } OverlayInterface::ControllerPosition OverlayInterface::GetGrippingControllerPosition(vr::IVRSystem* pVRSystem, vr::VROverlayHandle_t overlayHandle, vr::TrackedDeviceIndex_t controllerIndex) { ControllerPosition result = {false, {0, 0, 0}}; // Check if the controller is gripping the overlay if (IsGrippingOverlay(pVRSystem, overlayHandle, controllerIndex)) { // Get the controller's pose vr::TrackedDevicePose_t controllerPose; pVRSystem->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0, &controllerPose, 1); // Check if the controller is valid if (controllerPose.bPoseIsValid) { // Directly extract the position from the pose result.position.v[0] = controllerPose.mDeviceToAbsoluteTracking.m[0][3]; result.position.v[1] = controllerPose.mDeviceToAbsoluteTracking.m[1][3]; result.position.v[2] = controllerPose.mDeviceToAbsoluteTracking.m[2][3]; result.isGripping = true; } } return result; } bool OverlayInterface::IsControllerCloseToOverlay(vr::IVRSystem* pVRSystem, vr::VROverlayHandle_t overlayHandle, vr::TrackedDeviceIndex_t controllerIndex) { vr::HmdVector3_t controllerPosition = GetGrippingControllerPosition(pVRSystem, overlayHandle, controllerIndex).position; vr::HmdMatrix34_t overlayMatrix; vr::ETrackingUniverseOrigin trackingUniverseOrigin = vr::TrackingUniverseStanding; vr::EVROverlayError error = vr::VROverlay()->GetOverlayTransformAbsolute(overlayHandle, &trackingUniverseOrigin, &overlayMatrix); if (error != vr::VROverlayError_None) { std::cerr << "Error getting overlay transform: " << error << std::endl; return false; // Return false if there's an error } // Calculate the overlay's center vr::HmdVector3_t overlayCenter = {overlayMatrix.m[0][3], overlayMatrix.m[1][3], overlayMatrix.m[2][3]}; // Calculate the distance from the controller to the overlay float distance = static_cast(std::sqrt(std::pow(controllerPosition.v[0] - overlayCenter.v[0], 2) + std::pow(controllerPosition.v[1] - overlayCenter.v[1], 2) + std::pow(controllerPosition.v[2] - overlayCenter.v[2], 2))); // Check if the distance is within the threshold for a successful grab float threshold = 0.8f; // Set the threshold value return distance < threshold; } #pragma endregion overlay movement #pragma region overlay networking vr::HmdMatrix34_t OverlayInterface::GetOverlayPositionAbsolute(vr::IVRSystem* pVRSystem, vr::VROverlayHandle_t overlayHandle) { vr::HmdMatrix34_t transformMatrix; vr::ETrackingUniverseOrigin trackingOrigin; vr::EVROverlayError error = vr::VROverlay()->GetOverlayTransformAbsolute(overlayHandle, &trackingOrigin, &transformMatrix); if (error != vr::VROverlayError_None) { std::cerr << "Error getting overlay transform in absolute terms: " << error << std::endl; // Initialize the matrix to identity if there is an error transformMatrix.m[0][0] = 1.0f; transformMatrix.m[0][1] = 0.0f; transformMatrix.m[0][2] = 0.0f; transformMatrix.m[0][3] = 0.0f; transformMatrix.m[1][0] = 0.0f; transformMatrix.m[1][1] = 1.0f; transformMatrix.m[1][2] = 0.0f; transformMatrix.m[1][3] = 0.0f; transformMatrix.m[2][0] = 0.0f; transformMatrix.m[2][1] = 0.0f; transformMatrix.m[2][2] = 1.0f; transformMatrix.m[2][3] = 0.0f; } return transformMatrix; } vr::HmdVector3_t OverlayInterface::GetHMDPositionRelativeToTrackingUniverseOrigin(vr::IVRSystem* pVRSystem) { // Define the tracking universe origin vr::ETrackingUniverseOrigin eTrackingOrigin = vr::ETrackingUniverseOrigin::TrackingUniverseStanding; // Define the prediction time (0 for the most current data) float fPredictionTime = 0.0f; // Allocate an array to hold the poses vr::TrackedDevicePose_t poses[vr::k_unMaxTrackedDeviceCount]; // Get the poses for all devices pVRSystem->GetDeviceToAbsoluteTrackingPose(eTrackingOrigin, fPredictionTime, poses, vr::k_unMaxTrackedDeviceCount); // Get the HMD index vr::TrackedDeviceIndex_t hmdIndex = vr::k_unTrackedDeviceIndex_Hmd; // Check if the HMD is valid if (!pVRSystem->IsTrackedDeviceConnected(hmdIndex)) { std::cerr << "HMD not connected." << std::endl; return {0, 0, 0}; // Return a zero vector if the HMD is not connected } // Get the pose for the HMD vr::TrackedDevicePose_t& hmdPose = poses[hmdIndex]; // Check if the pose is valid if (!hmdPose.bPoseIsValid) { std::cerr << "HMD pose not valid." << std::endl; return {0, 0, 0}; // Return a zero vector if the pose is not valid } // Extract the position from the pose vr::HmdVector3_t position = {hmdPose.mDeviceToAbsoluteTracking.m[0][3], hmdPose.mDeviceToAbsoluteTracking.m[1][3], hmdPose.mDeviceToAbsoluteTracking.m[2][3]}; return position; } std::string OverlayInterface::serializePositions(const vr::HmdMatrix34_t& overlayPosition, const vr::HmdVector3_t& hmdPosition) { std::stringstream ss; // Serialize overlay position for (int i = 0; i < 3; ++i) { for (int j = 0; j < 4; ++j) { ss << overlayPosition.m[i][j] << " "; } } // Serialize HMD position for (int i = 0; i < 3; ++i) { ss << hmdPosition.v[i] << " "; } return ss.str(); } #pragma endregion #pragma region init stuff void OverlayInterface::Shutdown() { DisconnectFromVRRuntime(); /* delete m_pScene; delete m_pFbo; delete m_pOffscreenSurface; if( m_pOpenGLContext ) { m_pOpenGLContext->destroy(); delete m_pOpenGLContext; m_pOpenGLContext = NULL; } */ } bool OverlayInterface::ConnectToVRRuntime() { m_eLastHmdError = vr::VRInitError_None; vr::IVRSystem *pVRSystem = vr::VR_Init( &m_eLastHmdError, vr::VRApplication_Overlay ); if ( m_eLastHmdError != vr::VRInitError_None ) { m_strVRDriver = "No Driver"; m_strVRDisplay = "No Display"; return false; } std::string GetTrackedDeviceString(vr::IVRSystem *pHmd, vr::TrackedDeviceIndex_t unDevice, vr::TrackedDeviceProperty prop); m_strVRDriver = GetTrackedDeviceString(pVRSystem, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String); m_strVRDisplay = GetTrackedDeviceString(pVRSystem, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SerialNumber_String); return true; } void OverlayInterface::DisconnectFromVRRuntime() { vr::VR_Shutdown(); } std::string OverlayInterface::GetVRDriverString() { return m_strVRDriver; } std::string OverlayInterface::GetVRDisplayString() { return m_strVRDisplay; } bool OverlayInterface::BHMDAvailable() { return vr::VRSystem() != NULL; } vr::HmdError OverlayInterface::GetLastHmdError() { return m_eLastHmdError; } #pragma endregion