add support for htc vive focus vision hmd auto-detection and various htc hmds auto-detection support on android

This commit is contained in:
Mamadou Babaei
2025-02-14 12:09:14 +01:00
parent b77d637801
commit 69ffb62e74
10 changed files with 290 additions and 40 deletions
@@ -37,7 +37,7 @@
FSGHMDTrackingSettings::FSGHMDTrackingSettings()
: FSGHMDTrackingSettings{
ESGViveHMDDetectionPriority::HtcViveFocus3First
ESGViveHMDDetectionPriority::FocusVision_XRElite_Focus3
}
{
}
@@ -54,7 +54,7 @@ struct SENSEGLOVESETTINGS_API FSGHMDTrackingSettings
public:
/**
* Determines which VIVE HMD to prioritize for detection, as the current detection mechanism cannot differentiate
* between the HTC VIVE Focus 3 and the HTC VIVE XR Elite.
* between HTC VIVE Focus Vision, HTC VIVE XR Elite, and HTC VIVE Focus 3.
*/
UPROPERTY(Config, EditDefaultsOnly, Category="HMD Tracking")
ESGViveHMDDetectionPriority ViveHMDDetectionPriority;
@@ -70,11 +70,11 @@ public:
* the tracking hardware.
*
* Caution:
* Due to highly experimental nature of the HMD auto-detection feature, the HTC VIVE Focus 3 and HTC XR Elite
* cannot be distinguished from each other in the current iteration. However, since the tracker devices and offsets
* for both headsets are the same, this should not affect performance or functionality.
* The order in which the HMD is detected can be specified through the HMD-tracker setting
* `ViveHMDDetectionPriority`.
* Due to highly experimental nature of the HMD auto-detection feature, the HTC VIVE Focus Vision, HTC VIVE XR
* Elite, and HTC VIVE Focus Vision cannot be distinguished from each other in the current iteration. However,
* since the tracker devices and offsets for all these headsets are the same, this should not affect the
* performance or any functionality. The order in which the HMD is detected can be specified through the
* HMD-tracker setting `ViveHMDDetectionPriority`.
*/
UPROPERTY(Config, EditDefaultsOnly, Category = "Wrist Tracking")
ESGPositionalTrackingHardware TrackingHardware;
@@ -150,13 +150,19 @@ bool FSGHMDTracker::IsHtcVivePro()
/// NOTE
// VIVE Pro:
// - Official Spec: 1440 x 1600 pixels per eye (2880 x 1600 pixels combined)
// - Unreal OpenXR Resolution: 4936 x 2740
// - Unreal OpenXR Resolution (PCVR): 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
// - Unreal OpenXR Resolution (PCVR): 5016 x 2508
// - Unreal OpenXR Resolution (Standalone): ?
// VIVE XR Elite
// - Official Spec: 1920 x 1920 pixels per eye (3840 x 1920 pixels combined)
// - Unreal OpenXR Resolution: 5016 x 2508
// - Unreal OpenXR Resolution (PCVR): 5016 x 2508
// - Unreal OpenXR Resolution (Standalone): ?
// VIVE Focus Vision
// - Official Spec: 2448 x 2448 pixels per eye (4896 x 2448 pixels combined)
// - Unreal OpenXR Resolution (PCVR): 5016 x 2508
// - Unreal OpenXR Resolution (Standalone): 1720 x 1720
if (HmdMonitorInfo.ResolutionX < 5000 && HmdMonitorInfo.ResolutionY > 2700)
{
bResolutionMatches = true;
@@ -173,6 +179,13 @@ bool FSGHMDTracker::IsHtcVivePro()
bool FSGHMDTracker::IsHtcViveFocus3()
{
#if PLATFORM_ANDROID
static const FName DeviceIdentifier{TEXT("WAVE:SUE")};
const FName DeviceName{GetDeviceName()};
const bool bNameMatches = DeviceName == DeviceIdentifier;
#else /* PLATFORM_ANDROID */
static const FName DeviceIdentifier{TEXT("Vive OpenXR: Vive SRanipal")};
static const FString ViveDeviceIdentifier{TEXT("Vive")};
static const FString SRanipalDeviceIdentifier{TEXT("SRanipal")};
@@ -186,11 +199,12 @@ bool FSGHMDTracker::IsHtcViveFocus3()
bNameMatches = DeviceNameString.Contains(ViveDeviceIdentifier)
|| DeviceNameString.Contains(SRanipalDeviceIdentifier);
}
#endif /* PLATFORM_ANDROID */
/// NOTE
/// For the time being since we cannot distinguish between VIVE Focus 3 and VIVE XR Elite using resolution checks,
/// we skip the resolution checks altogether and assume it's not a VIVE Pro, as VIVE Pro won't come with Android
/// support.
/// For the time being since we cannot distinguish between VIVE Focus Vision, VIVE XR Elite, and VIVE Focus 3 using
/// resolution checks, we skip the resolution checks altogether and assume it's not a VIVE Pro, as VIVE Pro won't
/// come with Android support.
#if PLATFORM_ANDROID
bool bResolutionMatches = true;
#else /* PLATFORM_ANDROID */
@@ -209,15 +223,21 @@ bool FSGHMDTracker::IsHtcViveFocus3()
/// NOTE
// VIVE Pro:
// - Official Spec: 1440 x 1600 pixels per eye (2880 x 1600 pixels combined)
// - Unreal OpenXR Resolution: 4936 x 2740
// - Unreal OpenXR Resolution (PCVR): 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
// - Unreal OpenXR Resolution (PCVR): 5016 x 2508
// - Unreal OpenXR Resolution (Standalone): ?
// VIVE XR Elite
// - Official Spec: 1920 x 1920 pixels per eye (3840 x 1920 pixels combined)
// - Unreal OpenXR Resolution: 5016 x 2508
if (HmdMonitorInfo.ResolutionX > 5000
&& (HmdMonitorInfo.ResolutionY > 2500 && HmdMonitorInfo.ResolutionY < 2700))
// - Unreal OpenXR Resolution (PCVR): 5016 x 2508
// - Unreal OpenXR Resolution (Standalone): ?
// VIVE Focus Vision
// - Official Spec: 2448 x 2448 pixels per eye (4896 x 2448 pixels combined)
// - Unreal OpenXR Resolution (PCVR): 5016 x 2508
// - Unreal OpenXR Resolution (Standalone): 1720 x 1720
if (HmdMonitorInfo.ResolutionX > 5000 &&
(HmdMonitorInfo.ResolutionY > 2500 && HmdMonitorInfo.ResolutionY < 2700))
{
bResolutionMatches = true;
}
@@ -233,6 +253,13 @@ bool FSGHMDTracker::IsHtcViveFocus3()
bool FSGHMDTracker::IsHtcViveXRElite()
{
#if PLATFORM_ANDROID
static const FName DeviceIdentifier{TEXT("WAVE:SUE")};
const FName DeviceName{GetDeviceName()};
const bool bNameMatches = DeviceName == DeviceIdentifier;
#else /* PLATFORM_ANDROID */
static const FName DeviceIdentifier{TEXT("Vive OpenXR: Vive SRanipal")};
static const FString ViveDeviceIdentifier{TEXT("Vive")};
static const FString SRanipalDeviceIdentifier{TEXT("SRanipal")};
@@ -246,11 +273,12 @@ bool FSGHMDTracker::IsHtcViveXRElite()
bNameMatches = DeviceNameString.Contains(ViveDeviceIdentifier)
|| DeviceNameString.Contains(SRanipalDeviceIdentifier);
}
#endif /* PLATFORM_ANDROID */
/// NOTE
/// For the time being since we cannot distinguish between VIVE Focus 3 and VIVE XR Elite using resolution checks,
/// we skip the resolution checks altogether and assume it's not a VIVE Pro, as VIVE Pro won't come with Android
/// support.
/// For the time being since we cannot distinguish between VIVE Focus Vision, VIVE XR Elite, and VIVE Focus 3 using
/// resolution checks, we skip the resolution checks altogether and assume it's not a VIVE Pro, as VIVE Pro won't
/// come with Android support.
#if PLATFORM_ANDROID
bool bResolutionMatches = true;
#else /* PLATFORM_ANDROID */
@@ -269,13 +297,93 @@ bool FSGHMDTracker::IsHtcViveXRElite()
/// NOTE
// VIVE Pro:
// - Official Spec: 1440 x 1600 pixels per eye (2880 x 1600 pixels combined)
// - Unreal OpenXR Resolution: 4936 x 2740
// - Unreal OpenXR Resolution (PCVR): 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
// - Unreal OpenXR Resolution (PCVR): 5016 x 2508
// - Unreal OpenXR Resolution (Standalone): ?
// VIVE XR Elite
// - Official Spec: 1920 x 1920 pixels per eye (3840 x 1920 pixels combined)
// - Unreal OpenXR Resolution: 5016 x 2508
// - Unreal OpenXR Resolution (PCVR): 5016 x 2508
// - Unreal OpenXR Resolution (Standalone): ?
// VIVE Focus Vision
// - Official Spec: 2448 x 2448 pixels per eye (4896 x 2448 pixels combined)
// - Unreal OpenXR Resolution (PCVR): 5016 x 2508
// - Unreal OpenXR Resolution (Standalone): 1720 x 1720
if (HmdMonitorInfo.ResolutionX > 5000 &&
(HmdMonitorInfo.ResolutionY > 2500 && HmdMonitorInfo.ResolutionY < 2700))
{
bResolutionMatches = true;
}
}
}
}
#endif /* PLATFORM_ANDROID */
const bool bMatched = bNameMatches && bResolutionMatches;
return bMatched;
}
bool FSGHMDTracker::IsHtcViveFocusVision()
{
#if PLATFORM_ANDROID
static const FName DeviceIdentifier{TEXT("WAVE:SUE")};
const FName DeviceName{GetDeviceName()};
const bool bNameMatches = DeviceName == DeviceIdentifier;
#else /* PLATFORM_ANDROID */
static const FName DeviceIdentifier{TEXT("Vive OpenXR: Vive SRanipal")};
static const FString ViveDeviceIdentifier{TEXT("Vive")};
static const FString SRanipalDeviceIdentifier{TEXT("SRanipal")};
const FName DeviceName{GetDeviceName()};
bool bNameMatches = DeviceName == DeviceIdentifier;
if (!bNameMatches)
{
const FString DeviceNameString{GetDeviceName().ToString()};
bNameMatches = DeviceNameString.Contains(ViveDeviceIdentifier)
|| DeviceNameString.Contains(SRanipalDeviceIdentifier);
}
#endif /* PLATFORM_ANDROID */
/// NOTE
/// For the time being since we cannot distinguish between VIVE Focus Vision, VIVE XR Elite, and VIVE Focus 3 using
/// resolution checks, we skip the resolution checks altogether and assume it's not a VIVE Pro, as VIVE Pro won't
/// come with Android support.
#if PLATFORM_ANDROID
bool bResolutionMatches = true;
#else /* PLATFORM_ANDROID */
bool bResolutionMatches = false;
if (bNameMatches)
{
if (GEngine && 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 (PCVR): 4936 x 2740
// VIVE Focus 3:
// - Official Spec: 2448 x 2448 pixels per eye (4896 x 2448 pixels combined)
// - Unreal OpenXR Resolution (PCVR): 5016 x 2508
// - Unreal OpenXR Resolution (Standalone): ?
// VIVE XR Elite
// - Official Spec: 1920 x 1920 pixels per eye (3840 x 1920 pixels combined)
// - Unreal OpenXR Resolution (PCVR): 5016 x 2508
// - Unreal OpenXR Resolution (Standalone): ?
// VIVE Focus Vision
// - Official Spec: 2448 x 2448 pixels per eye (4896 x 2448 pixels combined)
// - Unreal OpenXR Resolution (PCVR): 5016 x 2508
// - Unreal OpenXR Resolution (Standalone): 1720 x 1720
if (HmdMonitorInfo.ResolutionX > 5000 &&
(HmdMonitorInfo.ResolutionY > 2500 && HmdMonitorInfo.ResolutionY < 2700))
{
@@ -315,9 +423,34 @@ ESGHeadMountedDisplayDevice FSGHMDTracker::GetDeviceType()
const USGSettings* Settings{USGSettings::GetInstance()};
ensureAlwaysMsgf(Settings, TEXT("The settings subsystem has not been initialized!"));
if (Settings->GetTrackingSettings().HMDTrackingSettings.ViveHMDDetectionPriority ==
ESGViveHMDDetectionPriority::HtcViveFocus3First)
ESGViveHMDDetectionPriority::FocusVision_XRElite_Focus3)
{
if (IsHtcViveFocusVision())
{
return ESGHeadMountedDisplayDevice::HtcViveFocusVision;
}
if (IsHtcViveXRElite())
{
return ESGHeadMountedDisplayDevice::HtcViveXRElite;
}
if (IsHtcViveFocus3())
{
return ESGHeadMountedDisplayDevice::HtcViveFocus3;
}
}
if (Settings->GetTrackingSettings().HMDTrackingSettings.ViveHMDDetectionPriority ==
ESGViveHMDDetectionPriority::FocusVision_Focus3_XRElite)
{
if (IsHtcViveFocusVision())
{
return ESGHeadMountedDisplayDevice::HtcViveFocusVision;
}
if (IsHtcViveFocus3())
{
return ESGHeadMountedDisplayDevice::HtcViveFocus3;
@@ -328,7 +461,28 @@ ESGHeadMountedDisplayDevice FSGHMDTracker::GetDeviceType()
return ESGHeadMountedDisplayDevice::HtcViveXRElite;
}
}
else
if (Settings->GetTrackingSettings().HMDTrackingSettings.ViveHMDDetectionPriority ==
ESGViveHMDDetectionPriority::XRElite_FocusVision_Focus3)
{
if (IsHtcViveXRElite())
{
return ESGHeadMountedDisplayDevice::HtcViveXRElite;
}
if (IsHtcViveFocusVision())
{
return ESGHeadMountedDisplayDevice::HtcViveFocusVision;
}
if (IsHtcViveFocus3())
{
return ESGHeadMountedDisplayDevice::HtcViveFocus3;
}
}
if (Settings->GetTrackingSettings().HMDTrackingSettings.ViveHMDDetectionPriority ==
ESGViveHMDDetectionPriority::XRElite_Focus3_FocusVision)
{
if (IsHtcViveXRElite())
{
@@ -339,6 +493,49 @@ ESGHeadMountedDisplayDevice FSGHMDTracker::GetDeviceType()
{
return ESGHeadMountedDisplayDevice::HtcViveFocus3;
}
if (IsHtcViveFocusVision())
{
return ESGHeadMountedDisplayDevice::HtcViveFocusVision;
}
}
if (Settings->GetTrackingSettings().HMDTrackingSettings.ViveHMDDetectionPriority ==
ESGViveHMDDetectionPriority::Focus3_FocusVision_XRElite)
{
if (IsHtcViveFocus3())
{
return ESGHeadMountedDisplayDevice::HtcViveFocus3;
}
if (IsHtcViveFocusVision())
{
return ESGHeadMountedDisplayDevice::HtcViveFocusVision;
}
if (IsHtcViveXRElite())
{
return ESGHeadMountedDisplayDevice::HtcViveXRElite;
}
}
if (Settings->GetTrackingSettings().HMDTrackingSettings.ViveHMDDetectionPriority ==
ESGViveHMDDetectionPriority::Focus3_XRElite_FocusVision)
{
if (IsHtcViveFocus3())
{
return ESGHeadMountedDisplayDevice::HtcViveFocus3;
}
if (IsHtcViveXRElite())
{
return ESGHeadMountedDisplayDevice::HtcViveXRElite;
}
if (IsHtcViveFocusVision())
{
return ESGHeadMountedDisplayDevice::HtcViveFocusVision;
}
}
return ESGHeadMountedDisplayDevice::None;
@@ -95,9 +95,14 @@ public:
*/
static bool IsHtcViveXRElite();
/**
* Checks whether the HMD device is HTC VIVE Focus Vision, or not.
*/
static bool IsHtcViveFocusVision();
FORCEINLINE static bool IsAHtcViveDevice()
{
return IsHtcVivePro() || IsHtcViveFocus3() || IsHtcViveXRElite();
return IsHtcVivePro() || IsHtcViveFocus3() || IsHtcViveXRElite() || IsHtcViveFocusVision();
}
static ESGHeadMountedDisplayDevice GetDeviceType();
@@ -64,17 +64,32 @@ enum class ESGHeadMountedDisplayDevice : uint8
/* The HTC VIVE XR Elite HMD. */
HtcViveXRElite UMETA(DisplayName = "HTC VIVE XR Elite"),
/* The HTC VIVE Focus 3 HMD. */
HtcViveFocusVision UMETA(DisplayName = "HTC VIVE Focus Vision"),
};
/*
* The
* The HTC VIVE HMD detection priority for HTC devices that we cannot distinguish.
*/
UENUM(BlueprintType)
enum class ESGViveHMDDetectionPriority : uint8
{
/* First try to detect HTC VIVE Focus 3. */
HtcViveFocus3First UMETA(DisplayName = "HTC VIVE Focus 3 First"),
/* First try to detect HTC VIVE Focus Vision, then XR Elite, and then Focus 3. */
FocusVision_XRElite_Focus3 UMETA(DisplayName = "Focus Vision (1st), XR Elite (2nd), Focus3 (3rd)"),
/* First try to detect HTC VIVE XR Elite. */
HtcViveXREliteFirst UMETA(DisplayName = "HTC VIVE XR Elite First"),
};
/* First try to detect HTC VIVE Focus Vision, then Focus 3, and then XR Elite. */
FocusVision_Focus3_XRElite UMETA(DisplayName = "Focus Vision (1st), Focus3 (2nd), XR Elite (3rd)"),
/* First try to detect HTC VIVE XR Elite, then Focus Vision, and then Focus 3. */
XRElite_FocusVision_Focus3 UMETA(DisplayName = "XR Elite (1st), Focus Vision (2nd), Focus3 (3rd)"),
/* First try to detect HTC VIVE XR Elite, then Focus 3, and then Focus Vision. */
XRElite_Focus3_FocusVision UMETA(DisplayName = "XR Elite (1st), Focus3 (2nd), Focus Vision (3rd)"),
/* First try to detect HTC VIVE Focus 3, then Focus Vision, and then XR Elite. */
Focus3_FocusVision_XRElite UMETA(DisplayName = "Focus3 (1st), Focus Vision (2nd), XR Elite (3rd)"),
/* First try to detect HTC VIVE Focus 3, then XR Elite, and then Focus Vision. */
Focus3_XRElite_FocusVision UMETA(DisplayName = "Focus3 (1st), XR Elite (2nd), Focus Vision (3rd)"),
};