remove FXRMotionControllerData or replace its usage with FXRHandTrackingState as we fully dropped support for it

This commit is contained in:
Mamadou Babaei
2026-02-18 19:38:02 +01:00
parent c712fb428a
commit 8007f212ce
32 changed files with 73 additions and 733 deletions
-3
View File
@@ -77,9 +77,6 @@ Welcom to the SenseGlove Unreal Engine Handbook!
- [Consuming FXRHandTrackingState](advanced-topics/openxr/consuming-fxrhandtrackingstate/README.md)
- [Blueprint](advanced-topics/openxr/consuming-fxrhandtrackingstate/blueprint.md)
- [C++](advanced-topics/openxr/consuming-fxrhandtrackingstate/cpp.md)
- [Consuming FXRMotionControllerData](advanced-topics/openxr/consuming-fxrmotioncontrollerdata/README.md)
- [Blueprint](advanced-topics/openxr/consuming-fxrmotioncontrollerdata/blueprint.md)
- [C++](advanced-topics/openxr/consuming-fxrmotioncontrollerdata/cpp.md)
- [Third-Party Integrations](advanced-topics/openxr/third-party-integrations/README.md)
- [Third-Party Tutorials](advanced-topics/openxr/third-party-tutorials/README.md)
+2 -18
View File
@@ -4,34 +4,18 @@ The SenseGlove Unreal Engine Plugin has provided OpenXR-compatible hand tracking
Typically a user does not need to know anything about OpenXR to use the plugin, so this section of the handbook is for advanced users who are looking for a way to directly consume the OpenXR data coming directly from either a SenseGlove device or if enabled in the plugin settings from hand-tracking.
Since the SenseGlove Unreal Engine Plugin registers itself as an `OpenXRHandTracking` motion controller device it becomes a hand-tracking provider for Unreal Engine, thus the OpenXR data from SenseGlove could always be retrieved from the Unreal Engine's `IXTrackingSystem` with one caveat. The caveat is if another OpenXR-compatible hand-tracking plugin, e.g. Epic's own OpenXRHandTracking, is enabled simultaneously it's not guaranteed that the `FXRMotionControllerData` and `FXRHandTrackingState` structs retrieved from the `IXTrackingSystem::GetMotionControllerData()` and `IXTrackingSystem::GetHandTrackingState()` methods are coming from SenseGlove, as these methods return the first hand-tracking plugin they could find. Thus, SenseGlove provides its own implementation of `GetMotionControllerData()` and `GetHandTrackingState()` which guarantee the retrieved `FXRMotionControllerData` or `FXRHandTrackingState` are coming from the SenseGlove Unreal Engine Plugin; and this is the preferred way to that.
Since the SenseGlove Unreal Engine Plugin registers itself as an `OpenXRHandTracking` motion controller device it becomes a hand-tracking provider for Unreal Engine, thus the OpenXR data from SenseGlove could always be retrieved from the Unreal Engine's `IXTrackingSystem` with one caveat. The caveat is if another OpenXR-compatible hand-tracking plugin, e.g. Epic's own OpenXRHandTracking, is enabled simultaneously it's not guaranteed that the `FXRHandTrackingState` structs retrieved from the `IXTrackingSystem::GetMotionControllerData()` and `IXTrackingSystem::GetHandTrackingState()` methods are coming from SenseGlove, as these methods return the first hand-tracking plugin they could find. Thus, SenseGlove provides its own implementation of `GetMotionControllerData()` and `GetHandTrackingState()` which guarantee the retrieved `FXRHandTrackingState` are coming from the SenseGlove Unreal Engine Plugin; and this is the preferred way to that.
> [!NOTE]
> In order to retrieve the latest `FXRMotionControllerState` available, The
> In order to retrieve the latest `FXRHandTrackingState` available, The
> SenseGlove Unreal Engine Plugin provides an alternative implementation for
> `IXTrackingSystem::GetMotionControllerState()` as well . However, since this
> method does not rely on the `OpenXRHandTracking` provider, it may become
> redundant. As a result, we might consider removing this functionality in
> future updates in favor of the one that Unreal Engine provides.
> [!IMPORTANT]
> Unreal Engine versions `5.2`, `5.3`, and `5.4` are limited to
> `FXRMotionControllerData` since at the time of their release no
> `FXRHandTrackingState` was available.
> Also please keep in mind that, while `FXRMotionControllerData` is pretty much
> usable and functional in Unreal Engine `5.5`, it is recommended to utilize
> `FXRHandTrackingState` instead. This is because this version of UE has
> deprecated `FXRMotionControllerData` in favor of the
> `FXRMotionControllerState` and `FXRHandTrackingState` structs. Prior to
> version `5.5`, `FXRMotionControllerData` handled both motion controller and
> hand tracking data. From `5.5` onward, these responsibilities have been
> separated into the two distinct structs, providing clearer and more
> specialized handling of each.
In the next sections we'll see:
- [How we can directly consume the `FXRMotionControllerData`](consuming-fxrmotioncontrollerdata/) on UE `5.2`, `5.3`, `5.4`, and `5.5` to draw and animate debug virtual hands in both [Blueprint](consuming-fxrmotioncontrollerdata/blueprint.md) and [C++](consuming-fxrmotioncontrollerdata/cpp.md).
- [How we can directly consume the `FXRHandTrackingState`](consuming-fxrhandtrackingstate/) on UE `5.5` to draw and animate debug virtual hands in both [Blueprint](consuming-fxrhandtrackingstate/blueprint.md) and [C++](consuming-fxrhandtrackingstate/cpp.md).
- [The Consuming OpenXR Hand-Tracking Data tutorial series](third-party-tutorials/) provides a comprehensive introduction to virtual reality, OpenXR hand-tracking, and gesture detection in Unreal Engine. Additionally, this tutorial series covers procedural virtual hand mesh animation using the OpenXR hand-tracking data.
@@ -1,19 +1,5 @@
# Consuming FXRHandTrackingState
> [!IMPORTANT]
> Unreal Engine versions `5.2`, `5.3`, and `5.4` are limited to
> `FXRMotionControllerData` since at the time of their release no
> `FXRHandTrackingState` was available.
> Also please keep in mind that, while `FXRMotionControllerData` is pretty much
> usable and functional in Unreal Engine `5.5`, it is recommended to utilize
> `FXRHandTrackingState` instead. This is because this version of UE has
> deprecated `FXRMotionControllerData` in favor of the
> `FXRMotionControllerState` and `FXRHandTrackingState` structs. Prior to
> version `5.5`, `FXRMotionControllerData` handled both motion controller and
> hand-tracking data. From `5.5` onward, these responsibilities have been
> separated into the two distinct structs, providing clearer and more
> specialized handling of each.
Taking a closer look at the `FXRHandTrackingState` declaration inside the Unreal Engine's `HeadMountedDisplay` module at [`Engine/Source/Runtime/HeadMountedDisplay/Public/HeadMountedDisplayTypes.h`](https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Source/Runtime/HeadMountedDisplay/Public/HeadMountedDisplayTypes.h), figuring out the data structure might not seem very straightforward:
```cpp
@@ -1,19 +1,5 @@
# Consuming FXRHandTrackingState in Blueprint
> [!IMPORTANT]
> Unreal Engine versions `5.2`, `5.3`, and `5.4` are limited to
> `FXRMotionControllerData` since at the time of their release no
> `FXRHandTrackingState` was available.
> Also please keep in mind that, while `FXRMotionControllerData` is pretty much
> usable and functional in Unreal Engine `5.5`, it is recommended to utilize
> `FXRHandTrackingState` instead. This is because this version of UE has
> deprecated `FXRMotionControllerData` in favor of the
> `FXRMotionControllerState` and `FXRHandTrackingState` structs. Prior to
> version `5.5`, `FXRMotionControllerData` handled both motion controller and
> hand tracking data. From `5.5` onward, these responsibilities have been
> separated into the two distinct structs, providing clearer and more
> specialized handling of each.
Before continuing this section, please ensure you've studied the [Consuming FXRHandTrackingState](./) section, first.
## Drawing and Animating Virtual Hands
@@ -62,4 +48,4 @@ Before continuing this section, please ensure you've studied the [Consuming FXRH
13. Now, go back to the `VRTemplateMap` and use the VR Preview button to run the game. If everything's done correctly, you should be able to see the virtual hands inside your VR simulation.
![FXRHandTrackingState animated debug virtual hands](../consuming-fxrhandtrackingstate-fxrmotioncontrollerdata-animated-debug-virtual-hands.gif "FXRHandTrackingState animated debug virtual hands")
![FXRHandTrackingState animated debug virtual hands](../consuming-fxrhandtrackingstate-animated-debug-virtual-hands.gif "FXRHandTrackingState animated debug virtual hands")
@@ -1,19 +1,5 @@
# Consuming FXRHandTrackingState in C++
> [!IMPORTANT]
> Unreal Engine versions `5.2`, `5.3`, and `5.4` are limited to
> `FXRMotionControllerData` since at the time of their release no
> `FXRHandTrackingState` was available.
> Also please keep in mind that, while `FXRMotionControllerData` is pretty much
> usable and functional in Unreal Engine `5.5`, it is recommended to utilize
> `FXRHandTrackingState` instead. This is because this version of UE has
> deprecated `FXRMotionControllerData` in favor of the
> `FXRMotionControllerState` and `FXRHandTrackingState` structs. Prior to
> version `5.5`, `FXRMotionControllerData` handled both motion controller and
> hand tracking data. From `5.5` onward, these responsibilities have been
> separated into the two distinct structs, providing clearer and more
> specialized handling of each.
Before continuing this section, please ensure you've first studied the [Consuming FXRHandTrackingState](./) section.
## Drawing and Animating Virtual Hands
@@ -256,4 +242,4 @@ void ADebugPawn::DrawHand(const EControllerHand Hand) const
15. Now, rebuild the source code and go back to the `VRTemplateMap`, then use the VR Preview button to run the game. If everything's done correctly, you should be able to see the virtual hands inside your VR simulation.
![FXRHandTrackingState animated debug virtual hands](../consuming-fxrhandtrackingstate-fxrmotioncontrollerdata-animated-debug-virtual-hands.gif "FXRHandTrackingState animated debug virtual hands")
![FXRHandTrackingState animated debug virtual hands](../consuming-fxrhandtrackingstate-animated-debug-virtual-hands.gif "FXRHandTrackingState animated debug virtual hands")
@@ -1,277 +0,0 @@
# Consuming FXRMotionControllerData
> [!IMPORTANT]
> Unreal Engine versions `5.2`, `5.3`, and `5.4` are limited to
> `FXRMotionControllerData` since at the time of their release no
> `FXRHandTrackingState` was available.
> Also please keep in mind that, while `FXRMotionControllerData` is pretty much
> usable and functional in Unreal Engine `5.5`, it is recommended to utilize
> `FXRHandTrackingState` instead. This is because this version of UE has
> deprecated `FXRMotionControllerData` in favor of the
> `FXRMotionControllerState` and `FXRHandTrackingState` structs. Prior to
> version `5.5`, `FXRMotionControllerData` handled both motion controller and
> hand tracking data. From `5.5` onward, these responsibilities have been
> separated into the two distinct structs, providing clearer and more
> specialized handling of each.
Taking a closer look at the `FXRMotionControllerData` declaration inside the Unreal Engine's `HeadMountedDisplay` module at [`Engine/Source/Runtime/HeadMountedDisplay/Public/HeadMountedDisplayTypes.h`](https://github.com/EpicGames/UnrealEngine/blob/5.5/Engine/Source/Runtime/HeadMountedDisplay/Public/HeadMountedDisplayTypes.h), figuring out the data structure might not seem very straightforward:
```cpp
USTRUCT(BlueprintType)
struct FXRMotionControllerData
{
GENERATED_USTRUCT_BODY();
UPROPERTY(BlueprintReadOnly, Category = "XR")
bool bValid = false;
UPROPERTY(BlueprintReadOnly, Category = "XR")
FName DeviceName;
UPROPERTY(BlueprintReadOnly, Category = "XR")
FGuid ApplicationInstanceID;
UPROPERTY(BlueprintReadOnly, Category = "XR")
EXRVisualType DeviceVisualType = EXRVisualType::Controller;
UPROPERTY(BlueprintReadOnly, Category = "XR")
EControllerHand HandIndex = EControllerHand::Left;
UPROPERTY(BlueprintReadOnly, Category = "XR")
ETrackingStatus TrackingStatus = ETrackingStatus::NotTracked;
// Vector representing an object being held in the player's hand
UPROPERTY(BlueprintReadOnly, Category = "XR")
FVector GripPosition = FVector(0.0f);
// Quaternion representing an object being held in the player's hand
UPROPERTY(BlueprintReadOnly, Category = "XR")
FQuat GripRotation = FQuat(EForceInit::ForceInitToZero);
// For handheld controllers, gives a vector for pointing at objects
UPROPERTY(BlueprintReadOnly, Category = "XR")
FVector AimPosition = FVector(0.0f);
// For handheld controllers, gives a quaternion for pointing at objects
UPROPERTY(BlueprintReadOnly, Category = "XR")
FQuat AimRotation = FQuat(EForceInit::ForceInitToZero);
// For handheld controllers, gives a vector for representing the hand
UPROPERTY(BlueprintReadOnly, Category = "XR")
FVector PalmPosition = FVector(0.0f);
// For handheld controllers, gives a quaternion for representing the hand
UPROPERTY(BlueprintReadOnly, Category = "XR")
FQuat PalmRotation = FQuat(EForceInit::ForceInitToZero);
// The indices of this array are the values of EHandKeypoint (Palm, Wrist, ThumbMetacarpal, etc).
UPROPERTY(BlueprintReadOnly, Category = "XR")
TArray<FVector> HandKeyPositions;
// The indices of this array are the values of EHandKeypoint (Palm, Wrist, ThumbMetacarpal, etc).
UPROPERTY(BlueprintReadOnly, Category = "XR")
TArray<FQuat> HandKeyRotations;
// The indices of this array are the values of EHandKeypoint (Palm, Wrist, ThumbMetacarpal, etc).
UPROPERTY(BlueprintReadOnly, Category = "XR")
TArray<float> HandKeyRadii;
UPROPERTY(BlueprintReadOnly, Category = "XR")
bool bIsGrasped = false;
};
```
Which on the Blueprint side it looks like this:
![FXRMotionControllerData Blueprint representation](consuming-fxrmotioncontrollerdata-blueprint-representation.png "FXRMotionControllerData Blueprint representation")
But, fear not, we've got you covered!
## FXRMotionControllerData in Unreal Engine
`FXRMotionControllerData` is a structure in Unreal Engine designed to hold detailed information about the state of a motion controller device at a given moment. This structure is essential for handling motion controller inputs in virtual reality (VR) applications, providing the necessary data to accurately track and represent the user's hand movements and actions within the virtual environment.
### Structure Members of FXRMotionControllerData
- **bValid**
- **Description**: A boolean flag indicating whether the data is valid or not.
- **Usage**: This is used to check if the motion controller data is correctly initialized and can be used for further processing.
- **DeviceName**
- **Type**: `FName`
- **Description**: The name of the device.
- **Usage**: Identifies which motion controller device the data is coming from, useful when multiple devices are in use.
- **ApplicationInstanceID**
- **Type**: `FString`
- **Description**: A unique identifier for the application instance.
- **Usage**: Helps in differentiating data from different instances of an application, ensuring the correct instance processes the data.
- **DeviceVisualType**
- **Type**: `EXRVisualType`
- **Description**: Enum specifying the visual type of the device (e.g., controller, hand).
- **Usage**: Used to differentiate between various motion controller devices or hand-tracking representations for rendering and interaction purposes.
- **HandIndex**
- **Type**: `EControllerHand`
- **Description**: Enum indicating which hand is being tracked (left or right).
- **Usage**: Helps identify whether the motion data pertains to the left or right hand, essential for hand-specific actions or interactions.
- **TrackingStatus**
- **Type**: `EXRTrackingStatus`
- **Description**: Enum indicating the tracking status of the motion controller.
- **Usage**: Shows whether the controller is being tracked accurately, with possible statuses like `Tracked`, `NotTracked`, etc.
- **GripPosition**
- **Type**: `FVector`
- **Description**: The position of the grip in world coordinates.
- **Usage**: Provides the 3D coordinates of the controller's grip, essential for positioning the virtual representation of the controller.
- **GripRotation**
- **Type**: `FQuat`
- **Description**: The rotation of the grip in world coordinates.
- **Usage**: Provides the orientation of the controller's grip, allowing for accurate rotation and alignment in the virtual space.
- **AimPosition**
- **Type**: `FVector`
- **Description**: The position of the aim point in world coordinates.
- **Usage**: Specifies where the controller is aiming, useful for aiming or pointing actions.
- **AimRotation**
- **Type**: `FQuat`
- **Description**: The rotation of the aim point in world coordinates.
- **Usage**: Determines the orientation of the aim direction, important for actions like shooting or selecting objects in VR.
- **PalmPosition**
- **Type**: `FVector`
- **Description**: The position of the palm in world coordinates.
- **Usage**: Provides the 3D location of the palm, important for determining hand gestures or interactions in VR.
- **PalmRotation**
- **Type**: `FQuat`
- **Description**: The rotation of the palm in world coordinates.
- **Usage**: Defines the orientation of the palm, crucial for hand-based interaction accuracy and realism in VR experiences.
- **HandKeyPositions**
- **Type**: `TArray<FVector>`
- **Description**: An array of vectors representing key positions of the hand.
- **Usage**: Provides detailed positions of key points on the hand, useful for precise hand tracking and interaction.
- **HandKeyRotations**
- **Type**: `TArray<FQuat>`
- **Description**: An array of quaternions representing key rotations of the hand.
- **Usage**: Complements the hand key positions with rotational data, ensuring accurate representation of hand movements.
- **HandKeyRadii**
- **Type**: `TArray<float>`
- **Description**: An array of floats representing the radii of key points of the hand.
- **Usage**: Gives the size of the hand key points, aiding in collision detection and interaction fidelity.
- **bIsGrasped**
- **Type**: `bool`
- **Description**: A boolean indicating whether the controller is currently grasping an object.
- **Usage**: Determines if the user is holding something, affecting interactions and animations.
### Organization of FXRMotionControllerData
The structure is organized to encapsulate all relevant data needed for hand and motion controller tracking in a coherent and accessible manner. Boolean flags `bValid` and `bIsGrasped` provide quick checks on the state of the controller data. Identifiers `DeviceName` and `ApplicationInstanceID` ensure the correct association of data. Positional and rotational data `GripPosition`, `GripRotation`, `AimPosition`, and `AimRotation` offer precise tracking of the controller's movement. Arrays `HandKeyPositions`, `HandKeyRotations`, and `HandKeyRadii` allow detailed hand tracking, which is critical for immersive VR experiences. Lastly, the tracking status `TrackingStatus` informs the system of the reliability of the data being processed and whether the motion controller is actively being tracked or it's inactive at the moment.
### Processing the Data for Drawing and Animating a Virtual Hand
In order to draw and animate a virtual hand in real-time whether the data is coming from hand-tracking or a SenseGlove device, we could consume the data from the `HandKeyPositions` and `HandKeyRotations` fields of the `FXRMotionControllerData` struct.
Both `HandKeyPositions` and `HandKeyRotations` contain 26 elements as defined by OpenXR's [`XR_HAND_JOINT_COUNT_EXT`](https://registry.khronos.org/OpenXR/specs/1.1/man/html/XR_HAND_JOINT_COUNT_EXT.html) and [`XrHandJointLocationsEXT`](https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrHandJointLocationsEXT.html), etc.
Unreal Engine also provides an enum called `EHandKeypoint` naming the 26 joints, and the equivalent of `XR_HAND_JOINT_COUNT_EXT` as `EHandKeypointCount` inside [`Engine/Source/Runtime/HeadMountedDisplay/Public/HeadMountedDisplayTypes.h`](https://github.com/EpicGames/UnrealEngine/blob/5.5/Engine/Source/Runtime/HeadMountedDisplay/Public/HeadMountedDisplayTypes.h) as follows:
```cpp
/**
* Transforms that are tracked on the hand.
* Matches the enums from WMR to make it a direct mapping
*/
UENUM(BlueprintType)
enum class EHandKeypoint : uint8
{
Palm,
Wrist,
ThumbMetacarpal,
ThumbProximal,
ThumbDistal,
ThumbTip,
IndexMetacarpal,
IndexProximal,
IndexIntermediate,
IndexDistal,
IndexTip,
MiddleMetacarpal,
MiddleProximal,
MiddleIntermediate,
MiddleDistal,
MiddleTip,
RingMetacarpal,
RingProximal,
RingIntermediate,
RingDistal,
RingTip,
LittleMetacarpal,
LittleProximal,
LittleIntermediate,
LittleDistal,
LittleTip
};
const int32 EHandKeypointCount = static_cast<int32>(EHandKeypoint::LittleTip) + 1;
```
So, getting the any joint's position or rotation is as easy as casting the enum value and passing it as the array index.
```cpp
FXRMotionControllerData MotionControllerData;
const bool bGotMotionControllerData = FSGXRTracker::GetMotionControllerData(
GetWorld(), EControllerHand::Left, MotionControllerData);
// Return if the struct data is invalid!
if (!bGotMotionControllerData || !MotionControllerData.bValid)
{
return;
}
// Return if the device is not being tracked!
if (MotionControllerData.TrackingStatus == ETrackingStatus::NotTracked)
{
return;
}
// Ensure that MotionControllerData.DeviceVisualType is a hand!
if (!ensureAlwaysMsgf(MotionControllerData.DeviceVisualType
== EXRVisualType::Hand,
TEXT("Invalid DeviceVisualType type!")))
{
}
// Ensure that MotionControllerData.HandKeyPositions has the position data
// for 26 joints!
if (!ensureAlwaysMsgf(MotionControllerData.HandKeyPositions.Num()
== EHandKeypointCount,
TEXT("Invalid HandKeyPositions count!")))
{
return;
}
// Ensure that MotionControllerData.HandKeyRotations has the rotation data
// for 26 joints!
if (!ensureAlwaysMsgf(MotionControllerData.HandKeyRotations.Num()
== EHandKeypointCount,
TEXT("Invalid HandKeyRotations count!")))
{
return;
}
static constexpr int32 PalmIndex = static_cast<int32>(EHandKeypoint::Palm);
const FVector& PalmPosition{
MotionControllerData.HandKeyPositions[PalmIndex]
};
const FRotator& PalmRotation{
MotionControllerData.HandKeyRotations[PalmIndex].Rotator()
};
```
The equivalent Blueprint code for the above looks something like this:
![Get a joint position and rotation from FXRMotionControllerData in Blueprint](consuming-fxrmotioncontrollerdata-blueprint-get-joint-position-rotation.png "Get a joint position and rotation from FXRMotionControllerData in Blueprint")
OK, now that we've got a glimpse of how the virtual hand's joint data could be processed we are going to draw and animate a virtual hand in both [Blueprint](blueprint.md) and [C++](cpp.md) in the upcoming sections.
@@ -1,65 +0,0 @@
# Consuming FXRMotionControllerData in Blueprint
> [!IMPORTANT]
> Unreal Engine versions `5.2`, `5.3`, and `5.4` are limited to
> `FXRMotionControllerData` since at the time of their release no
> `FXRHandTrackingState` was available.
> Also please keep in mind that, while `FXRMotionControllerData` is pretty much
> usable and functional in Unreal Engine `5.5`, it is recommended to utilize
> `FXRHandTrackingState` instead. This is because this version of UE has
> deprecated `FXRMotionControllerData` in favor of the
> `FXRMotionControllerState` and `FXRHandTrackingState` structs. Prior to
> version `5.5`, `FXRMotionControllerData` handled both motion controller and
> hand tracking data. From `5.5` onward, these responsibilities have been
> separated into the two distinct structs, providing clearer and more
> specialized handling of each.
Before continuing this section, please ensure you've studied the [Consuming FXRMotionControllerData](./) section, first.
## Drawing and Animating Virtual Hands
1. Create a new Virtual Reality project based [the Unreal VR Template](https://dev.epicgames.com/documentation/en-us/unreal-engine/vr-template-in-unreal-engine).
2. Make sure the [SenseGlove UnrealEngine plugin is installed and enabled](/getting-started/installation.md) inside your new project.
![Enabling the SenseGlove Unreal Engine Plugin](enabling-senseglove-unrealp-engine-plugin.png "Enabling the SenseGlove Unreal Engine Plugin")
3. You could use either hand-tracking or a SenseGlove device as the input data, or both of the inside the same project. Whether you would like to use hand-tracking or a SenseGlove device, please make sure the required steps are taken for each of those first.
4. You could add the required Blueprint code for drawing virtual hands to either your Level Buleprint or the VRPawn Blueprint Class located at `/Content/VRTemplate/Blueprints/VRPawn`. In this guide we are going to add the code to our VRPawn.
5. Add a new function named `Draw Hand` with an input parameter of type `EController Hand` named `Hand`.
![Adding the Blueprint Draw Hand function](consuming-fxrmotioncontrollerdata-blueprint-add-draw-hand-function.png "Adding the Blueprint Draw Hand function")
6. Inside this function's event graph add a `Get Motion Controller Data` node from `SenseGlove > Tracking > XR Tracker > Get Motion Controller Data`.
![Adding the Get Motion Controller Data node](consuming-fxrmotioncontrollerdata-blueprint-add-get-motion-controller-data-node.png "Adding the Get Motion Controller Data node")
7. Then connect the functions `Hand` input parameter to the `Get Motion Controller Data`'s `Hand` input and right-click on the `OutMotionControllerData` parameter and use the `Break XRMotionControllerData` node to break the struct to it's fields.
![Breaking the XR Motion Controller Data node](consuming-fxrmotioncontrollerdata-blueprint-break-xr-motion-controller-data.png "Breaking the XR Motion Controller Data node")
8. After this, we need to perform data validation by checking the return status of the `Get Motion Controller Data` function and `FXRMotionControllerData`'s `Valid` field. Then, we check if the motion controller device is being tracked and indeed coming from a hand-tracking source. And, finally, we check whether we have the positions and rotations for exactly `26` joints or not.
![FXRMotionControllerData validation](consuming-fxrmotioncontrollerdata-blueprint-validation.png "FXRMotionControllerData validation")
9. OK, now it's time to draw the joints! If we check out the SenseGlove Debug module's draw option, we notice there are various ways to draw the debug virtual hand. Drawing a cube or a gizmo per joint, or draw the whole hand all at once by passing the retrieved `FXRMotionControllerData` to the `DebugVirtualHand::Draw` function! But, since the point of this tutorial is to learn how to consume the `FXRMotionControllerData` we ignore the last option. Between the debug cubes or gizmos, we are going to choose the gizmos since they better represent the rotations than the cubes.
![Some options for drawing a debug virtual hand](consuming-fxrmotioncontrollerdata-blueprint-debug-virtual-hand-draw-options.png "Some options for drawing a debug virtual hand")
10. In the last step inside the `Draw Hand` function, in order to draw a virtual hand with `26` joints, we have to first iterate through either of the `Hand Key Positions` or `Hand Key Rotations` arrays from the `FXRMotionControllerData` struct. Since we made sure both arrays have `26` elements before we reached this step, it's safe to just iterate over one and use the `Array Index` inside a `For Each Loop` or a `For Loop` to access the position and rotation of every joint. Then we use each array `Get (a ref)` method to access the position and rotation data inside the loop and call the `Draw` function from `SenseGlove > Debug > Gizmo` per every joint. Please note that there are two `Draw` functions and the only difference between the two is that one accepts an `FQuat` and the other a `FRotator` for its `Rotation` input parameter. In this case, we use the `FQuat` variant to avoid an extra conversion to `FRotator`. Also, please adjust the `Thickness` option for the `Settings` parameter from `1.0` to `0.2`, as the default value might be too thick for drawing a joint gizmo.
![Drawing a debug gizmo per each hand's joint](consuming-fxrmotioncontrollerdata-blueprint-draw-debug-gizmo-per-joint.png "Drawing a debug gizmo per each hand's joint")
11. Well, now the full implementation for the `Draw Hand` function insde the `VRPawn` should look something like this:
![VRPawn Draw Hand function final implementation](consuming-fxrmotioncontrollerdata-blueprint-draw-hand-function-implementation.png "VRPawn Draw Hand function final implementation")
12. Finally, go back to `VRPawn`'s event graph and the following code to the `Tick` event. Basically what we do here is call our newly implemented `Draw Hand` twice, once for each hand.
![Attempt to draw the left and right virtual hands every frame from the VR Pawn Tick event](consuming-fxrmotioncontrollerdata-blueprint-vrpawn-draw-virtual-hands-every-frame.png "Attempt to draw the left and right virtual hands every frame from the VR Pawn Tick event")
13. Now, go back to the `VRTemplateMap` and use the VR Preview button to run the game. If everything's done correctly, you should be able to see the virtual hands inside your VR simulation.
![FXRMotionControllerData animated debug virtual hands](../consuming-fxrhandtrackingstate-fxrmotioncontrollerdata-animated-debug-virtual-hands.gif "FXRMotionControllerData animated debug virtual hands")
@@ -1,266 +0,0 @@
# Consuming FXRMotionControllerData in C++
> [!IMPORTANT]
> Unreal Engine versions `5.2`, `5.3`, and `5.4` are limited to
> `FXRMotionControllerData` since at the time of their release no
> `FXRHandTrackingState` was available.
> Also please keep in mind that, while `FXRMotionControllerData` is pretty much
> usable and functional in Unreal Engine `5.5`, it is recommended to utilize
> `FXRHandTrackingState` instead. This is because this version of UE has
> deprecated `FXRMotionControllerData` in favor of the
> `FXRMotionControllerState` and `FXRHandTrackingState` structs. Prior to
> version `5.5`, `FXRMotionControllerData` handled both motion controller and
> hand tracking data. From `5.5` onward, these responsibilities have been
> separated into the two distinct structs, providing clearer and more
> specialized handling of each.
Before continuing this section, please ensure you've first studied the [Consuming FXRMotionControllerData](./) section.
## Drawing and Animating Virtual Hands
1. Create a new Virtual Reality project based [the Unreal VR Template](https://dev.epicgames.com/documentation/en-us/unreal-engine/vr-template-in-unreal-engine).
2. Make sure the [SenseGlove UnrealEngine plugin is installed and enabled](/getting-started/installation.md) inside your new project.
![Enabling the SenseGlove Unreal Engine Plugin](enabling-senseglove-unrealp-engine-plugin.png "Enabling the SenseGlove Unreal Engine Plugin")
3. You could use either hand-tracking or a SenseGlove device as the input data, or both of the inside the same project. Whether you would like to use hand-tracking or a SenseGlove device, please make sure the required steps are taken for each of those first.
4. From the `Tools` menu choose `New C++ class...`.
![Creating a new C++ class](consuming-fxrmotioncontrollerdata-cpp-new-class.png "Creating a new C++ class")
5. Choose the Unreal Engine's `APawn` class as the parent class for the new C++ pawn class.
![Choosing APawn as the parent class](consuming-fxrmotioncontrollerdata-cpp-add-class-choose-name.png "Choosing APawn as the parent class")
6. Name the new pawn class `DebugPawn`.
![Naming the new C++ class DebugPawn](consuming-fxrmotioncontrollerdata-cpp-add-class-choose-parent.png "Naming the new C++ class DebugPawn")
7. Since we have created a new C++ class, this converts the current Blueprint VRTemplateMap project to a C++ one. That's why the Unreal Editor will give us a few prompts regarding opening the project in the default IDE and rebuilding the code. It might be simpler to just close the editor, then rebuild the source code inside your favorite IDE, and then start the editor with the converted project again.
8. Find and open the VRPawn Blueprint Class located at `/Content/VRTemplate/Blueprints/VRPawn` inside the Blueprint Editor and from the `File` menu choose the `Reparent Blueprint` class.
![Reparenting the VRPawn Blueprint class](consuming-fxrmotioncontrollerdata-cpp-reparent.png "Reparenting the VRPawn Blueprint class")
9. In the new `Reparent blueprint` window choose `DebugPawn` as the new parent.
![Reparenting the VRPawn Blueprint class to ADebugPawn](consuming-fxrmotioncontrollerdata-cpp-reparent-debug-pawn.png "Reparenting the VRPawn Blueprint class to ADebugPawn")
10. By looking at the `Parent Class` label located under the Blueprint Editor window control buttons verify that the `ADebugPawn` class has been set as the new parent.
![Veifying whether the VRPawn Blueprint class set to ADebugPawn or not](consuming-fxrmotioncontrollerdata-cpp-verify-parent-class.png "Veifying whether the VRPawn Blueprint class set to ADebugPawn or not")
11. Locate the project's main Build file, in our case `VirtualHandCpp/Source/VirtualHandCpp/VirtualHandCpp.Build.cs` and add the `InputDevice`, `OpenXRHMD`, `SenseGloveBuildHacks`, `SenseGloveDebug`, `SenseGloveSettings`, and `SenseGloveTracking` modules as either a private or public dependency.
```csharp
// Fill out your copyright notice in the Description page of Project Settings.
using UnrealBuildTool;
public class VirtualHandCpp : ModuleRules
{
public VirtualHandCpp(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
PrivateDependencyModuleNames.AddRange(new string[]
{
"InputDevice",
"OpenXRHMD",
"SenseGloveBuildHacks",
"SenseGloveDebug",
"SenseGloveSettings",
"SenseGloveTracking"
});
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
// Uncomment if you are using online features
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
}
}
```
12. Locate the C++ header and source file for the `ADebugPawn` inside the project in your C++ IDE. In our case they are located at `VirtualHandCpp/Source/VirtualHandCpp/DebugPawn.h` and `VirtualHandCpp/Source/VirtualHandCpp/DebugPawn.cpp`.
13. Modify the `DebugPawn.h` header file to look like this:
```cpp
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "SGSettings/SGDebugGizmoSettings.h"
#include "DebugPawn.generated.h"
UCLASS()
class VIRTUALHANDCPP_API ADebugPawn : public APawn
{
GENERATED_BODY()
private:
// The virtual hand drawing settings.
UPROPERTY(EditDefaultsOnly, Category="DebugPawn",
meta=(AllowPrivateAccess="false"))
FSGDebugGizmoSettings HandDrawingSettings;
public:
// Sets default values for this pawn's properties
ADebugPawn();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
private:
// The method responsible for drawing a virtual hand.
void DrawHand(EControllerHand Hand) const;
};
```
14. Modify the `DebugPawn.cpp` implementation file to look like this:
```cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "DebugPawn.h"
#include "SGDebug/SGDebugGizmo.h"
#include "SGTracking/SGXRTracker.h"
// Sets default values
ADebugPawn::ADebugPawn()
{
// Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// Set the default virtual hand drawing settings.
HandDrawingSettings = FSGDebugGizmoSettings{
1.0f,
FColor{255, 0, 0, 255},
FColor{0, 255, 0, 255},
FColor{0, 0, 255, 255},
false,
1.1f,
0,
0.2f,
};
}
// Called when the game starts or when spawned
void ADebugPawn::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ADebugPawn::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// Attempt at drawing the left/right virtual hands every frame.
DrawHand(EControllerHand::Left);
DrawHand(EControllerHand::Right);
}
// Called to bind functionality to input
void ADebugPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
}
void ADebugPawn::DrawHand(const EControllerHand Hand) const
{
// Get the world and cache it, if it's null we return early.
UWorld* World{GetWorld()};
if (!IsValid(World))
{
return;
}
FXRMotionControllerData MotionControllerData;
const bool bGotMotionControllerData = FSGXRTracker::GetMotionControllerData(
World, Hand, MotionControllerData);
// Return if the struct data is invalid!
if (!bGotMotionControllerData || !MotionControllerData.bValid)
{
return;
}
// Return if the device is not being tracked!
if (MotionControllerData.TrackingStatus == ETrackingStatus::NotTracked)
{
return;
}
// Ensure that MotionControllerData.DeviceVisualType is a hand!
if (!ensureAlwaysMsgf(MotionControllerData.DeviceVisualType
== EXRVisualType::Hand,
TEXT("Invalid DeviceVisualType type!")))
{
}
// Ensure that MotionControllerData.HandKeyPositions has the position data
// for 26 joints!
if (!ensureAlwaysMsgf(MotionControllerData.HandKeyPositions.Num()
== EHandKeypointCount,
TEXT("Invalid HandKeyPositions count!")))
{
return;
}
// Ensure that MotionControllerData.HandKeyRotations has the rotation data
// for 26 joints!
if (!ensureAlwaysMsgf(MotionControllerData.HandKeyRotations.Num()
== EHandKeypointCount,
TEXT("Invalid HandKeyRotations count!")))
{
return;
}
// Iterate over the hand joint positions and rotations!
for (int32 JointIndex = 0; JointIndex < EHandKeypointCount; ++JointIndex)
{
const FVector& JointPosition{
MotionControllerData.HandKeyPositions[JointIndex]
};
const FQuat& JointRotation{
MotionControllerData.HandKeyRotations[JointIndex]
};
// Draw a single joint's gizmo!
// Please note that we could alternatively:
// Use FSGDebugCube::Draw() to draw a cube.
// Or use the FSGDebugVirtualHand::Draw() method and pass the
// MotionControllerData directly to draw the virtual hand
// all at once without iterating the joints. But, that's not
// goal of this tutorial.
FSGDebugGizmo::Draw(World, JointPosition, JointRotation, HandDrawingSettings);
}
}
```
15. Now, rebuild the source code and go back to the `VRTemplateMap`, then use the VR Preview button to run the game. If everything's done correctly, you should be able to see the virtual hands inside your VR simulation.
![FXRMotionControllerData animated debug virtual hands](../consuming-fxrhandtrackingstate-fxrmotioncontrollerdata-animated-debug-virtual-hands.gif "FXRMotionControllerData animated debug virtual hands")
+9
View File
@@ -29,12 +29,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Dropped support for Unreal Engine `5.4`, which was already deprecated via the `v2.7.x` release series.
- Dropped support for Epic Native/Cross Toolchains `v22` (previously used for building UE `5.3` and `5.4` Linux dependencies), as they were already deprecated via previous releases.
- Removed support for the deprecated `FXRMotionControllerData`. The plugin now exclusively uses `FXRHandTrackingState` (introduced in Unreal Engine 5.5+ and supported by The SenseGlove Unreal Engine Plugin since [`v2.2.0`](#220---2024-10-22) for OpenXR hand tracking. This affects only projects that directly consume `FXRMotionControllerData` from the SenseGlove plugin in their own custom hand-tracking or interaction systems. Please see [the v2.7.x to v2.8.x migration guide](../misc/upgrade-guide/#upgrading-from-v27x-to-v28x) for more details.
### Documentation
- Added a [v2.7.x to v2.8.x migration guide](../misc/upgrade-guide/#upgrading-from-v27x-to-v28x) for transitioning from `FXRMotionControllerData` to `FXRHandTrackingState` for projects that directly consume SenseGlove OpenXR data.
- Updated [Enabling XR_EXT_hand_tracking on VR Headsets](../getting-started/enabling-xr-ext-hand-tracking-vr-headsets/) documentation, replacing `FXRMotionControllerData` usage with `FXRHandTrackingState`.
- Updated [Setup the Virtual Hand Meshes](../getting-started/setup-virtual-hand-meshes/) documentation, replacing `FXRMotionControllerData` usage with `FXRHandTrackingState`.
- Updated [Plugin Configuration > Plugin Settings > Virtual Hand > Mesh](../plugin-configuration/plugin-settings/virtual-hand/mesh.md) documentation, replacing `FXRMotionControllerData` usage with `FXRHandTrackingState`.
- Removed the **Consuming FXRMotionControllerData** documentation section as it's no longer relevant.
- Removed the **Consuming FXRMotionControllerData > Blueprint** documentation section as it's no longer relevant.
- Removed the **Consuming FXRMotionControllerData > C++** documentation section as it's no longer relevant.
- Ensure deterministic dependency builds by pinning Rust toolchain.
- Changelog errata fixes.
- Minor changelog formatting fixes.
- Additional minor fixes and improvements that may not be listed here.
## [2.7.3] - 2026-02-17
@@ -61,7 +61,7 @@ For VIVE headsets relying on the VIVE Business Streaming application, ensure the
![VIVE Business Streaming - Hand tracking - Enabling XR_EXT_hand_tracking and Emulating VIVE Wrist Tracker as VIVE Tracker](vive-business-streaming-hand-tracking.png "VIVE Business Streaming - Hand tracking - Enabling XR_EXT_hand_tracking and Emulating VIVE Wrist Tracker as VIVE Tracker")
> [!NOTE]
> Tracking and accessing `FXRMotionControllerData` output from SenseGlove
> Tracking and accessing `FXRHandTrackingState` output from SenseGlove
> devices do not require Hand and Body Tracking to be enabled on the HMD device.
> Enabling this feature is only necessary if you wish to use hand-tracking as a
> fallback option when no glove is connected to your PC.
@@ -282,6 +282,6 @@ Next, navigate to `Project Settings > Plugins > SenseGlove > Virtual Hand Settin
- `Left Hand Reference Mesh`
- `Right Hand Reference Mesh`
This configuration guarantees that the tracking system correctly interprets the bone transforms of the virtual hand meshes when generating `FXRMotionControllerData`. Additionally, it allows the animation system to accurately use these bone transforms when processing `FXRMotionControllerData` and animating the virtual hand meshes.
This configuration guarantees that the tracking system correctly interprets the bone transforms of the virtual hand meshes when generating `FXRHandTrackingState`. Additionally, it allows the animation system to accurately use these bone transforms when processing `FXRHandTrackingState` and animating the virtual hand meshes.
![The SGPawn and the Plugin Virtual Hand Mesh Settings - Plugin settings](virtual-hand-mesh-settings-plugin.png "[The SGPawn and the Plugin Virtual Hand Mesh Settings - Plugin settings")
![The SGPawn and the Plugin Virtual Hand Mesh Settings - Plugin settings](virtual-hand-mesh-settings-plugin.png "[The SGPawn and the Plugin Virtual Hand Mesh Settings - Plugin settings")
+54
View File
@@ -1,5 +1,59 @@
# Upgrade Guide
## Upgrading from v2.7.x to v2.8.x
### Summary of Breaking Changes
Starting with **SenseGlove Unreal Engine Plugin v2.8.x**, support for `FXRMotionControllerData` has been **removed**.
Although:
* Unreal Engine **5.5** and **5.6** still support the deprecated `FXRMotionControllerData`, and
* These engine versions are still supported by plugin v2.8.x,
the plugin now fully transitions to **`FXRHandTrackingState`**, which is the modern and recommended API introduced in **Unreal Engine 5.5+** for OpenXR hand tracking.
Additionally:
* Plugin v2.8.x no longer supports **Unreal Engine 5.4**.
* Because `FXRHandTrackingState` is the forward-compatible OpenXR API, continued support for `FXRMotionControllerData` is no longer maintained in the plugin.
We have supported `FXRHandTrackingState` since [`v2.2.0` (released 2024-10-22)](../../appendix/changelog.html#220---2024-10-22), and it has been stable in production for several releases.
## Who Is Affected?
This change only affects you if:
* You maintain a **custom hand manipulation or tracking system**, and
* Your implementation directly consumes `FXRMotionControllerData` provided by the SenseGlove plugin.
If you rely solely on the plugins provided components and standard integration workflow, no action is required.
## Required Migration
If you are directly consuming `FXRMotionControllerData`, for your project to build or function as expected, you must migrate to:
```
FXRHandTrackingState
```
The migration is straightforward because both structures represent similar hand tracking data concepts within Unreals OpenXR framework.
A step-by-step explanation of how to work with `FXRHandTrackingState` is available in this third-party tutorial:
👉 [Introduction to Virtual Reality, OpenXR Hand Tracking, and Gesture Detection in Unreal Engine](../../advanced-topics/openxr/third-party-tutorials/index.html#introduction-to-virtual-reality-openxr-hand-tracking-and-gesture-detection-in-unreal-engine)
## Why This Change?
* `FXRMotionControllerData` is deprecated.
* `FXRHandTrackingState` is the future-proof OpenXR hand tracking API.
* The existing Unreal Engines OpenXR implementation is centered around `FXRHandTrackingState` and `FXRMotionControllerData` has been completely removed form UE `5.7`+.
* Removing legacy support simplifies the plugin architecture and aligns it with Unreals forward direction.
If you are already using `FXRHandTrackingState` or not directly consuming the OpenXR data, no changes are required when upgrading to v2.8.x.
## Upgrading from v2.0.x to v2.1.x
The transition from `v2.0.x` to `v2.1.x` introduces [numerous changes](../../appendix/changelog.md), including several breaking changes. The effort required to upgrade your project will vary depending on its complexity and which features of the SenseGlove Unreal Engine Project you are using. However, if you are working with a simple Blueprint project like [SGBasicDemo](https://dev.azure.com/SenseGlove/_git/SenseGlove-Unreal-SGBasicDemo), the upgrade process is quite straightforward. We successfully upgraded SGBasicDemo to [SGBasicDemo-OpenXR](https://dev.azure.com/SenseGlove/_git/SenseGlove-Unreal-SGBasicDemo-OpenXR) by following the procedure outlined below.
These are the notable changes that might affect your project:
-3
View File
@@ -79,9 +79,6 @@ For users familiar with the basics, this section explores advanced features of t
- [Consuming FXRHandTrackingState](../advanced-topics/openxr/consuming-fxrhandtrackingstate/)
- [Blueprint](../advanced-topics/openxr/consuming-fxrhandtrackingstate/blueprint.md)
- [C++](../advanced-topics/openxr/consuming-fxrhandtrackingstate/cpp.md)
- [Consuming FXRMotionControllerData](../advanced-topics/openxr/consuming-fxrmotioncontrollerdata/)
- [Blueprint](../advanced-topics/openxr/consuming-fxrmotioncontrollerdata/blueprint.md)
- [C++](../advanced-topics/openxr/consuming-fxrmotioncontrollerdata/cpp.md)
- [Third-Party Integrations](../advanced-topics/openxr/third-party-integrations/)
- [Third-Party Tutorials](../advanced-topics/openxr/third-party-tutorials/)
@@ -6,7 +6,7 @@ Utilized by the SenseGlove `Tracking` module to account for the current virtual
# LeftHandReferenceMesh
The virtual hand model for the left hand is to be used by the SenseGlove `Tracking` module to generate all the `26` joint data present in the `FXRMotionControllerData`. The main reason the `Tracking` module requires a virtual hand mesh as a reference is the SenseGlove Hand Pose format only provides `15` joints. So, the remaining joint data for `FXRMotionControllerData` are calculated from a virtual hand mesh compatible with the Epic rig and also the values specified by `DistalPhalangesLengthSettings`. Furthermore, when calculating the existing joints data, their current locations and rotations are taken into account in calculating the resulting `FXRMotionControllerData`.
The virtual hand model for the left hand is to be used by the SenseGlove `Tracking` module to generate all the `26` joint data present in the `FXRHandTrackingState`. The main reason the `Tracking` module requires a virtual hand mesh as a reference is the SenseGlove Hand Pose format only provides `15` joints. So, the remaining joint data for `FXRHandTrackingState` are calculated from a virtual hand mesh compatible with the Epic rig and also the values specified by `DistalPhalangesLengthSettings`. Furthermore, when calculating the existing joints data, their current locations and rotations are taken into account in calculating the resulting `FXRHandTrackingState`.
By default, no virtual hand mesh is set.
@@ -19,7 +19,7 @@ By default, no virtual hand mesh is set.
# RightHandReferenceMesh
The virtual hand model for the right hand is to be used by the SenseGlove `Tracking` module to generate all the `26` joint data present in the `FXRMotionControllerData`. The main reason the `Tracking` module requires a virtual hand mesh as a reference is the SenseGlove Hand Pose format only provides `15` joints. So, the remaining joint data for `FXRMotionControllerData` are calculated from a virtual hand mesh compatible with the Epic rig and also the values specified by `DistalPhalangesLengthSettings`. Furthermore, when calculating the existing joints data, their current locations and rotations are taken into account in calculating the resulting `FXRMotionControllerData`.
The virtual hand model for the right hand is to be used by the SenseGlove `Tracking` module to generate all the `26` joint data present in the `FXRHandTrackingState`. The main reason the `Tracking` module requires a virtual hand mesh as a reference is the SenseGlove Hand Pose format only provides `15` joints. So, the remaining joint data for `FXRHandTrackingState` are calculated from a virtual hand mesh compatible with the Epic rig and also the values specified by `DistalPhalangesLengthSettings`. Furthermore, when calculating the existing joints data, their current locations and rotations are taken into account in calculating the resulting `FXRHandTrackingState`.
By default, no virtual hand mesh is set.
@@ -32,7 +32,7 @@ By default, no virtual hand mesh is set.
# DistalPhalangesLengthSettings
The length of distal phalanges that cannot be retrieved from any virtual hand mesh compliant with the Epic standard rig. Also, the SenseGlove Hand Pose format does not provide these. This is used by SenseGlove `Tracking` module to calculate an `FXRMotionControllerData` the all `26` joints. The values you specify here depend on the shape of the virtual hand mesh and the defaults are approximated for the virtual hand model shipped with the Unreal Engine VRTemplate.
The length of distal phalanges that cannot be retrieved from any virtual hand mesh compliant with the Epic standard rig. Also, the SenseGlove Hand Pose format does not provide these. This is used by SenseGlove `Tracking` module to calculate an `FXRHandTrackingState` the all `26` joints. The values you specify here depend on the shape of the virtual hand mesh and the defaults are approximated for the virtual hand model shipped with the Unreal Engine VRTemplate.
## RootBoneRotationCorrection