add support for htc vive wrist trackers on android

This commit is contained in:
Mamadou Babaei
2025-02-04 17:38:07 +01:00
parent 257b48bcb9
commit 8f8600cdc6
7 changed files with 155 additions and 35 deletions
+3
View File
@@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added the `FSGPluginUtils` utility class for other plugins or modules availability detection such as `Meta XR` and `ViveOpenXR`.
- Added various HTC HMDs auto-detection support on Android.
- Added support for HTC VIVE Focus Vision HMD auto-detection.
- Added support for HTC Vive Wrist Trackers support on Android using the official `ViveOpenXR` plugin's OpenXR positional tracking provider `OpenXRViveWristTracker`.
- Added enum `ESGOpenXRPositionalTrackingProvider`.
- Added the `OpenXRPositionalTrackingProvider` option to the plugin's wrist-tracker settings to either manually set the positional tracking provider or auto-detect it based on a combination of tracker hardware settings, targeted platform, available OpenXR plugins, or the auto-detected HMD hardware.
### Fixed
@@ -2,7 +2,24 @@
Provides the tracking settings applicable to wrist-tracking hardware.
![The Wrist-tracking Settings](wrist-tracking-settings.png "The Wrist-tracking Settings")
## OpenXRPositionalTrackingProvider
Specifies the type of OpenXR provider to use in order to extract the positional tracking data from the underlying XR system. If set to None, the plugin attempts to set this automatically by considering a combination of approaches including, the current value of `TrackingHardware` specified below, the platform it's targeted at, the available OpenXR plugins, along with HMD auto-detection mechanism to specify a compatible OpenXR tracking provider. Please note that the OpenXR provider depends on the combination of plugins, platform, and the settings you use. For example, it is possible to use a Vive Focus 3 Wrist Tracker on Microsoft Windows along with the Epic `OpenXRViveTracker` plugin and check the option `Emulate VIVE Wrist Tracker as VIVE Tracker` inside the VIVE Business Streaming application's Input settings. In that case, the correct OpenXR positional tracking provider to use would be `OpenXRViveTracker`. However, using the official ViveOpenXR plugin on Android, the correct OpenXR provider would be `OpenXRViveWristTracker`.
> [!CAUTION]
> HMD auto-detection is currently an experimental feature and may fail because
> HMD vendors occasionally change the properties utilized by the plugin for HMD
> detection. If you encounter issues, such as incorrect tracker offsets, it is
> recommended to explicitly specify the tracking hardware.
> [!CAUTION]
> Due to highly experimental nature of the HMD auto-detection feature, the HTC
> VIVE Focus Vision, HTC VIVE Focus 3, and HTC VIVE XR Elite 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`](../hmd-tracking.html#vivehmddetectionpriority).
## TrackingHardware
@@ -159,6 +159,7 @@ FSGWristTrackingSettings USGWristTrackerComponent::GetWristTrackingSettings() co
}
const FSGWristTrackingSettings WristTrackingSettings{
PluginWristTrackingSettings.OpenXRPositionalTrackingProvider,
PluginWristTrackingSettings.TrackingHardware,
PluginWristTrackingSettings.TrackingHardwareLocationOffsetLeftHand,
PluginWristTrackingSettings.TrackingHardwareLocationOffsetRightHand,
@@ -37,6 +37,7 @@
FSGWristTrackingSettings::FSGWristTrackingSettings()
: FSGWristTrackingSettings{
ESGOpenXRPositionalTrackingProvider::None,
ESGPositionalTrackingHardware::None,
FVector::ZeroVector,
FVector::ZeroVector,
@@ -44,12 +45,13 @@ FSGWristTrackingSettings::FSGWristTrackingSettings()
FRotator::ZeroRotator,
FName{TEXT("Left")},
FName{TEXT("Right")},
FSGWristTrackingDebuggingSettings{}
FSGWristTrackingDebuggingSettings{},
}
{
}
FSGWristTrackingSettings::FSGWristTrackingSettings(
const ESGOpenXRPositionalTrackingProvider InOpenXRPositionalTrackingProvider,
const ESGPositionalTrackingHardware InTrackingHardware,
const FVector& InTrackingHardwareLocationOffsetLeftHand,
const FVector& InTrackingHardwareLocationOffsetRightHand,
@@ -58,7 +60,8 @@ FSGWristTrackingSettings::FSGWristTrackingSettings(
const FName InLeftHandMotionSource,
const FName InRightHandMotionSource,
const FSGWristTrackingDebuggingSettings& InDebuggingSettings)
: TrackingHardware(InTrackingHardware),
: OpenXRPositionalTrackingProvider(InOpenXRPositionalTrackingProvider),
TrackingHardware(InTrackingHardware),
TrackingHardwareLocationOffsetLeftHand{InTrackingHardwareLocationOffsetLeftHand},
TrackingHardwareLocationOffsetRightHand{InTrackingHardwareLocationOffsetRightHand},
TrackingHardwareRotationOffsetLeftHand{InTrackingHardwareRotationOffsetLeftHand},
@@ -44,6 +44,7 @@
#include "SGSettings/SGWristTrackingDebuggingSettings.h"
#include "SGTypes/SGCoreTypes.h"
#include "SGTypes/SGTrackingTypes.h"
#include "SGWristTrackingSettings.generated.h"
@@ -58,6 +59,33 @@ struct SENSEGLOVESETTINGS_API FSGWristTrackingSettings
GENERATED_USTRUCT_BODY()
public:
/**
* Specifies the type of OpenXR provider to use in order to extract the positional tracking data from the
* underlying XR system. If set to None, the plugin attempts to set this automatically by considering a combination
* of approaches including, the current value of `TrackingHardware` specified below, the platform it's targeted at,
* the available OpenXR plugins, along with HMD auto-detection mechanism to specify a compatible OpenXR tracking
* provider. Please note that the OpenXR provider depends on the combination of plugins, platform, and the settings
* you use. For example, it is possible to use a Vive Focus 3 Wrist Tracker on Microsoft Windows along with the
* Epic `OpenXRViveTracker` plugin and check the option `Emulate VIVE Wrist Tracker as VIVE Tracker` inside the
* VIVE Business Streaming application's Input settings. In that case, the correct OpenXR positional tracking
* provider to use would be `OpenXRViveTracker`. However, using the official ViveOpenXR plugin on Android, the
* correct OpenXR provider would be `OpenXRViveWristTracker`.
*
* Caution:
* HMD auto-detection is currently an experimental feature and may fail because HMD vendors occasionally change the
* properties utilized by the plugin for HMD detection. If you encounter issues, such as incorrect tracker offsets,
* it is recommended to explicitly specify the tracking hardware.
*
* Caution:
* 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")
ESGOpenXRPositionalTrackingProvider OpenXRPositionalTrackingProvider;
/**
* Specifies the type of tracking hardware to use. If set to None, the plugin attempts at HMD auto-detection to
* automatically specify a compatible tracking hardware. If set to `Custom`, any desired location and rotation can
@@ -150,6 +178,7 @@ public:
FSGWristTrackingSettings();
FSGWristTrackingSettings(
const ESGOpenXRPositionalTrackingProvider InOpenXRPositionalTrackingProvider,
ESGPositionalTrackingHardware InTrackingHardware,
const FVector& InTrackingHardwareLocationOffsetLeftHand,
const FVector& InTrackingHardwareLocationOffsetRightHand,
@@ -60,6 +60,7 @@
#include "SGTypes/SGCoreTypes.h"
#include "SGTypes/SGTrackingTypes.h"
#include "SGUtils/SGEngineUtils.h"
#include "SGUtils/SGPluginUtils.h"
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION <= 3
void EnumerateOpenXRApiLayers(TArray<XrApiLayerProperties>& OutProperties)
@@ -100,6 +101,9 @@ struct FSGXRTracker::FImpl
static FName GetControllerHandEnumName(const EControllerHand ControllerHand);
static FName GetOpenXRPositionalTrackingProviderEnumName(
const ESGOpenXRPositionalTrackingProvider OpenXRPositionalTrackingProvider);
FORCEINLINE static bool ShouldFallbackToHandTrackingIfNoGloveDetected()
{
const USGSettings* Settings{USGSettings::GetInstance()};
@@ -658,6 +662,8 @@ struct FSGXRTracker::FImpl
bool UpdateXRHandTrackingData(FSGXRHandState& OutHandState, const XrHandJointsLocateInfoEXT& LocateInfo) const;
FName GetTargetOpenXRPositionalTrackingProviderName() const;
bool GetControllerTransform(const FName MotionSource, const float WorldToMetersScale,
FTransform& OutTransform, bool& bOutMotionSourceHandTracking) const;
@@ -732,6 +738,24 @@ FName FSGXRTracker::FImpl::GetControllerHandEnumName(const EControllerHand Contr
return ParsedName;
}
FName FSGXRTracker::FImpl::GetOpenXRPositionalTrackingProviderEnumName(
const ESGOpenXRPositionalTrackingProvider OpenXRPositionalTrackingProvider)
{
static UEnum* EnumPtr{StaticEnum<ESGOpenXRPositionalTrackingProvider>()};
ensureAlwaysMsgf(EnumPtr, TEXT("Failed to find the ESGOpenXRPositionalTrackingProvider enum!"));
static const int32 EnumNameLength = FString{TEXT("ESGOpenXRPositionalTrackingProvider::")}.Len();
const FName EnumItemName{
EnumPtr->GetNameByValue(static_cast<int64>(OpenXRPositionalTrackingProvider))
};
const FString EnumItemString{EnumItemName.ToString()};
const int32 EnumItemStringLength = EnumItemString.Len();
const int32 EnumItemNameLength = EnumItemStringLength - EnumNameLength;
const FName ParsedName{*EnumItemString.Right(EnumItemNameLength)};
return ParsedName;
}
ESGPositionalTrackingHardware FSGXRTracker::FImpl::GetPositionalTrackingHardware()
{
ESGPositionalTrackingHardware TrackerHardware = GetWristTrackingSettings().TrackingHardware;
@@ -2091,6 +2115,55 @@ bool FSGXRTracker::FImpl::UpdateXRHandTrackingData(
return true;
}
FName FSGXRTracker::FImpl::GetTargetOpenXRPositionalTrackingProviderName() const
{
const FSGWristTrackingSettings& WristTrackingSettings{GetWristTrackingSettings()};
ESGOpenXRPositionalTrackingProvider PositionalTrackingProvider =
WristTrackingSettings.OpenXRPositionalTrackingProvider;
if (PositionalTrackingProvider == ESGOpenXRPositionalTrackingProvider::None)
{
const bool bIsAHtcViveDevice = FSGHMDTracker::IsAHtcViveDevice();
if (bIsAHtcViveDevice)
{
#if PLATFORM_ANDROID
PositionalTrackingProvider = ESGOpenXRPositionalTrackingProvider::OpenXRViveWristTracker;
#else /* PLATFORM_ANDROID */
// TODO
// Revisit this later!
// For now only `Emulate VIVE Wrist Tracker as VIVE Tracker` option in VBE works on Windows
// const bool bIsViveOpenXRPluginLoaded = FSGPluginUtils::IsViveOpenXRPluginAvailable();
// if (bIsViveOpenXRPluginLoaded)
// {
// if (WristTrackingSettings.TrackingHardware == ESGPositionalTrackingHardware::ViveFocus3WristTracker)
// {
// PositionalTrackingProvider = ESGOpenXRPositionalTrackingProvider::OpenXRViveWristTracker;
// }
// else
// {
// PositionalTrackingProvider = ESGOpenXRPositionalTrackingProvider::OpenXRViveTracker;
// }
// }
// else
// {
// PositionalTrackingProvider = ESGOpenXRPositionalTrackingProvider::OpenXRViveTracker;
// }
PositionalTrackingProvider = ESGOpenXRPositionalTrackingProvider::OpenXRViveTracker;
#endif /* PLATFORM_ANDROID */
}
else
{
PositionalTrackingProvider = ESGOpenXRPositionalTrackingProvider::OpenXR;
}
}
const FName PositionalTrackingProviderName{
GetOpenXRPositionalTrackingProviderEnumName(PositionalTrackingProvider)
};
return PositionalTrackingProviderName;
}
bool FSGXRTracker::FImpl::GetControllerTransform(
const FName MotionSource, const float WorldToMetersScale,
FTransform& OutTransform, bool& bOutMotionSourceHandTracking) const
@@ -2111,9 +2184,6 @@ bool FSGXRTracker::FImpl::GetControllerTransform(
return false;
}
static const FName OpenXRName{TEXT("OpenXR")};
static const FName OpenXRViveTrackerName{TEXT("OpenXRViveTracker")};
const FSGWristTrackingSettings& WristTrackingSettings{GetWristTrackingSettings()};
const FName& PositionalTrackingHardwareMotionSource{
bRight
@@ -2125,26 +2195,15 @@ bool FSGXRTracker::FImpl::GetControllerTransform(
if (MotionSource == PositionalTrackingHardwareMotionSource)
{
const FName TargetPositionalTrackingProviderName{
GetTargetOpenXRPositionalTrackingProviderName()
};
const TArray<IMotionController*> MotionControllers{
IModularFeatures::Get().GetModularFeatureImplementations<IMotionController>(
IMotionController::GetModularFeatureName())
};
bool bLookingForViveTrackers = false;
if (WristTrackingSettings.TrackingHardware == ESGPositionalTrackingHardware::ViveTracker
|| WristTrackingSettings.TrackingHardware == ESGPositionalTrackingHardware::ViveFocus3WristTracker)
{
bLookingForViveTrackers = true;
}
else if (WristTrackingSettings.TrackingHardware == ESGPositionalTrackingHardware::None)
{
const bool bIsAHtcViveDevice = FSGHMDTracker::IsAHtcViveDevice();
if (bIsAHtcViveDevice)
{
bLookingForViveTrackers = true;
}
}
for (const IMotionController* MotionController: MotionControllers)
{
if (!MotionController)
@@ -2159,22 +2218,13 @@ bool FSGXRTracker::FImpl::GetControllerTransform(
continue;
}
if (bLookingForViveTrackers)
const FName DeviceTypeName{MotionController->GetMotionControllerDeviceTypeName()};
SGLOG("SGVIVEDEBUG", DeviceTypeName, TargetPositionalTrackingProviderName);
if (DeviceTypeName != TargetPositionalTrackingProviderName)
{
const FName DeviceTypeName{MotionController->GetMotionControllerDeviceTypeName()};
if (DeviceTypeName != OpenXRViveTrackerName)
{
continue;
}
}
else
{
const FName DeviceTypeName{MotionController->GetMotionControllerDeviceTypeName()};
if (DeviceTypeName != OpenXRName)
{
continue;
}
continue;
}
SGLOG("SGVIVEDEBUG", DeviceTypeName, TargetPositionalTrackingProviderName, "Matched");
FRotator Orientation;
FVector Position;
@@ -69,6 +69,23 @@ enum class ESGHeadMountedDisplayDevice : uint8
HtcViveFocusVision UMETA(DisplayName = "HTC VIVE Focus Vision"),
};
/* OpenXR provider for the positional tracking hardware. */
UENUM(BlueprintType)
enum class ESGOpenXRPositionalTrackingProvider : uint8
{
/* The default none value. Setting to 'None' will fall back to auto-detection. */
None UMETA(DisplayName = "None"),
/* OpenXR. */
OpenXR UMETA(DisplayName = "OpenXR"),
/* OpenXRViveTracker. */
OpenXRViveTracker UMETA(DisplayName = "OpenXRViveTracker"),
/* OpenXRViveWristTracker. */
OpenXRViveWristTracker UMETA(DisplayName = "OpenXRViveWristTracker"),
};
/*
* The HTC VIVE HMD detection priority for HTC devices that we cannot distinguish.
*/