From 07995f23e2ef8803e8fa34e57df4b83e07da5093 Mon Sep 17 00:00:00 2001 From: Mamadou Babaei Date: Tue, 9 Apr 2024 11:29:08 +0200 Subject: [PATCH] improve vive pro and vive focus 3 detection by utilizing optic resolution to distinguish them --- CHANGELOG.md | 2 +- .../Private/SenseGlove/SGHeadMountDisplay.cpp | 95 +++++++++++++++++-- .../Public/SenseGlove/SGHeadMountDisplay.h | 21 +--- h -f | 30 ++++++ 4 files changed, 122 insertions(+), 26 deletions(-) create mode 100644 h -f diff --git a/CHANGELOG.md b/CHANGELOG.md index 335e15fd..3113c25d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,7 +80,7 @@ This is a bugfix release. ### Added -- A fallback to HMD and wrist tracker hardware auto-detection mechanism has been added to be triggered in situations when automatic detection of the wrist tracker hardware is desired, e.g., either by not setting it explicitly, or setting it to the default None value (still not fully reliable for HTC hardware as it's not able to distinguish VIVE Pro and VIVE Focus 3). +- A fallback to HMD and wrist tracker hardware auto-detection mechanism has been added to be triggered in situations when automatic detection of the wrist tracker hardware is desired, e.g., either by not setting it explicitly, or setting it to the default None value. - Added the SGHeadMountDisplay utility class, exposed to both C++ and Blueprint, in order to easily gather information about the HMD at runtime. - Added the SGTypes header to the SenseGloveTypes module in order to define and share SenseGlove module types through this header across the plugin modules. - Added ESGHeadMountDisplayDevice enum with supported HMDs list. diff --git a/Source/SenseGlove/Private/SenseGlove/SGHeadMountDisplay.cpp b/Source/SenseGlove/Private/SenseGlove/SGHeadMountDisplay.cpp index bc65ea56..2ee3a192 100644 --- a/Source/SenseGlove/Private/SenseGlove/SGHeadMountDisplay.cpp +++ b/Source/SenseGlove/Private/SenseGlove/SGHeadMountDisplay.cpp @@ -38,20 +38,107 @@ #include "Engine/Engine.h" #include "IHeadMountedDisplay.h" #include "IXRTrackingSystem.h" +#include "SGLog/SGLog.h" FName FSGHeadMountDisplay::GetDeviceName() { if (GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed()) { const IHeadMountedDisplay* Device{GEngine->XRSystem->GetHMDDevice()}; - const FName DeviceName{Device->GetHMDName()}; - return DeviceName; + if (Device) + { + const FName DeviceName{Device->GetHMDName()}; + return DeviceName; + } } return NAME_None; } +bool FSGHeadMountDisplay::IsHtcVivePro() +{ +#if !PLATFORM_ANDROID + static const FName DeviceIdentifier{TEXT("Vive OpenXR: Vive SRanipal")}; + const bool bIdentifierMatches = GetDeviceName() == DeviceIdentifier; + if (bIdentifierMatches) + { + if (GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed()) + { + IHeadMountedDisplay* Device{GEngine->XRSystem->GetHMDDevice()}; + if (Device) + { + IHeadMountedDisplay::MonitorInfo HmdMonitorInfo; + Device->GetHMDMonitorInfo(HmdMonitorInfo); + + /// NOTE + // VIVE Pro: + // - Official Spec: 1440 x 1600 pixels per eye (2880 x 1600 pixels combined) + // - Unreal OpenXR Resolution: 4936 x 2740 + // VIVE Focus 3: + // - Official Spec: 2448 x 2448 pixels per eye (4896 x 2448 pixels combined) + // - Unreal OpenXR Resolution: 5016 x 2508 + if (HmdMonitorInfo.ResolutionX < 5000 && HmdMonitorInfo.ResolutionY > 2700) + { + return true; + } + } + } + } +#endif /* !PLATFORM_ANDROID */ + + return false; +} + +bool FSGHeadMountDisplay::IsHtcViveFocus3() +{ + static const FName DeviceIdentifier{TEXT("Vive OpenXR: Vive SRanipal")}; + const bool bIdentifierMatches = GetDeviceName() == DeviceIdentifier; + +#if PLATFORM_ANDROID + return bIdentifierMatches; +#else /* PLATFORM_ANDROID */ + if (bIdentifierMatches) + { + if (GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed()) + { + IHeadMountedDisplay* Device{GEngine->XRSystem->GetHMDDevice()}; + if (Device) + { + IHeadMountedDisplay::MonitorInfo HmdMonitorInfo; + Device->GetHMDMonitorInfo(HmdMonitorInfo); + + /// NOTE + // VIVE Pro: + // - Official Spec: 1440 x 1600 pixels per eye (2880 x 1600 pixels combined) + // - Unreal OpenXR Resolution: 4936 x 2740 + // VIVE Focus 3: + // - Official Spec: 2448 x 2448 pixels per eye (4896 x 2448 pixels combined) + // - Unreal OpenXR Resolution: 5016 x 2508 + if (HmdMonitorInfo.ResolutionX > 5000 + && (HmdMonitorInfo.ResolutionY > 2500 && HmdMonitorInfo.ResolutionY < 2700)) + { + return true; + } + } + } + } + + return false; +#endif /* PLATFORM_ANDROID */ +} + ESGHeadMountDisplayDevice FSGHeadMountDisplay::GetDeviceType() { + if (GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed()) + { + IHeadMountedDisplay::MonitorInfo HmdMonitorInfo; + IHeadMountedDisplay* Device{GEngine->XRSystem->GetHMDDevice()}; + Device->GetHMDMonitorInfo(HmdMonitorInfo); + const int32 ResX = HmdMonitorInfo.ResolutionX; + const int32 ResY = HmdMonitorInfo.ResolutionY; + SGLOG(HmdMonitorInfo.MonitorName, ResX, ResY, HmdMonitorInfo.DesktopX, HmdMonitorInfo.DesktopY, + HmdMonitorInfo.WindowSizeX, HmdMonitorInfo.WindowSizeY); + } + if (IsMetaQuest2()) { return ESGHeadMountDisplayDevice::MetaQuest2; @@ -67,15 +154,11 @@ ESGHeadMountDisplayDevice FSGHeadMountDisplay::GetDeviceType() return ESGHeadMountDisplayDevice::MetaQuest3; } - /// TODO - // WE NEED A MORE RELIABLE WAY TO DISTINGUISH VIVE Pro from VIVE Focus 3. if (IsHtcVivePro()) { return ESGHeadMountDisplayDevice::HtcVivePro; } - /// TODO - // WE NEED A MORE RELIABLE WAY TO DISTINGUISH VIVE Pro from VIVE Focus 3. if (IsHtcViveFocus3()) { return ESGHeadMountDisplayDevice::HtcViveFocus3; diff --git a/Source/SenseGlove/Public/SenseGlove/SGHeadMountDisplay.h b/Source/SenseGlove/Public/SenseGlove/SGHeadMountDisplay.h index 7a5a5881..d70c9834 100644 --- a/Source/SenseGlove/Public/SenseGlove/SGHeadMountDisplay.h +++ b/Source/SenseGlove/Public/SenseGlove/SGHeadMountDisplay.h @@ -72,25 +72,8 @@ public: return GetDeviceName() == DeviceIdentifier; } - FORCEINLINE static bool IsHtcVivePro() - { - /// TODO - // WE NEED A MORE RELIABLE WAY TO DISTINGUISH VIVE Pro from VIVE Focus 3. -#if PLATFORM_ANDROID - return false; -#else /* PLATFORM_ANDROID */ - static const FName DeviceIdentifier{TEXT("Vive OpenXR: Vive SRanipal")}; - return GetDeviceName() == DeviceIdentifier; -#endif /* PLATFORM_ANDROID */ - } - - FORCEINLINE static bool IsHtcViveFocus3() - { - /// TODO - // WE NEED A MORE RELIABLE WAY TO DISTINGUISH VIVE Pro from VIVE Focus 3. - static const FName DeviceIdentifier{TEXT("Vive OpenXR: Vive SRanipal")}; - return GetDeviceName() == DeviceIdentifier; - } + static bool IsHtcVivePro(); + static bool IsHtcViveFocus3(); static ESGHeadMountDisplayDevice GetDeviceType(); }; \ No newline at end of file diff --git a/h -f b/h -f new file mode 100644 index 00000000..30e126ea --- /dev/null +++ b/h -f @@ -0,0 +1,30 @@ +diff --git a/Source/SenseGlove/Private/SenseGlove/SGHeadMountDisplay.cpp b/Source/SenseGlove/Private/SenseGlove/SGHeadMountDisplay.cpp +index bc65ea56..1bda9233 100644 +--- a/Source/SenseGlove/Private/SenseGlove/SGHeadMountDisplay.cpp ++++ b/Source/SenseGlove/Private/SenseGlove/SGHeadMountDisplay.cpp +@@ -38,6 +38,7 @@ + #include "Engine/Engine.h" + #include "IHeadMountedDisplay.h" + #include "IXRTrackingSystem.h" ++#include "SGLog/SGLog.h" +  + FName FSGHeadMountDisplay::GetDeviceName() + { +@@ -52,6 +53,17 @@ FName FSGHeadMountDisplay::GetDeviceName() +  + ESGHeadMountDisplayDevice FSGHeadMountDisplay::GetDeviceType() + { ++ if (GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowed()) ++ { ++ IHeadMountedDisplay::MonitorInfo HmdMonitorInfo; ++ IHeadMountedDisplay* Device{GEngine->XRSystem->GetHMDDevice()}; ++ Device->GetHMDMonitorInfo(HmdMonitorInfo); ++ const int32 ResX = HmdMonitorInfo.ResolutionX; ++ const int32 ResY = HmdMonitorInfo.ResolutionY; ++ SGLOG(HmdMonitorInfo.MonitorName, ResX, ResY, HmdMonitorInfo.DesktopX, HmdMonitorInfo.DesktopY, ++ HmdMonitorInfo.WindowSizeX, HmdMonitorInfo.WindowSizeY); ++ } ++ + if (IsMetaQuest2()) + { + return ESGHeadMountDisplayDevice::MetaQuest2;