implement our own GetMotionControllerData instead of using the one from the XRTrackingSystem as it only picks up the first hand tracking plugin in order to make sure at least internally we use the hand-tracking data from senseglove
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
#include "Engine/SkeletalMesh.h"
|
||||
#include "Engine/World.h"
|
||||
#include "GameFramework/WorldSettings.h"
|
||||
#include "IOpenXRHMD.h"
|
||||
#include "IOpenXRHMDModule.h"
|
||||
#include "IXRTrackingSystem.h"
|
||||
#include "OpenXRCore.h"
|
||||
@@ -972,6 +973,192 @@ FTransform FSGXRTracker::FImpl::GetMeshFingerStartBoneRefTransform(
|
||||
return Transform;
|
||||
}
|
||||
|
||||
bool FSGXRTracker::GetMotionControllerData(
|
||||
UObject* WorldContextObject, const EControllerHand Hand, FXRMotionControllerData& OutMotionControllerData)
|
||||
{
|
||||
OutMotionControllerData.DeviceName = NAME_None;
|
||||
OutMotionControllerData.ApplicationInstanceID = FApp::GetInstanceId();
|
||||
OutMotionControllerData.DeviceVisualType = EXRVisualType::Controller;
|
||||
OutMotionControllerData.TrackingStatus = ETrackingStatus::NotTracked;
|
||||
OutMotionControllerData.HandIndex = Hand;
|
||||
OutMotionControllerData.bValid = false;
|
||||
|
||||
if (!IsValid(WorldContextObject))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IXRTrackingSystem* XRTrackingSystem{GEngine ? GEngine->XRSystem.Get() : nullptr};
|
||||
if (!XRTrackingSystem)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IOpenXRHMD* OpenXRHMD{XRTrackingSystem->GetIOpenXRHMD()};
|
||||
if (!OpenXRHMD)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TArray<int32> Devices;
|
||||
const int32 HandIndex = static_cast<int32>(Hand);
|
||||
const bool bGotDevices =
|
||||
XRTrackingSystem->EnumerateTrackedDevices(Devices, EXRTrackedDeviceType::Controller);
|
||||
if (bGotDevices && Devices.IsValidIndex(HandIndex))
|
||||
{
|
||||
const XrSession Session{OpenXRHMD->GetSession()};
|
||||
if (Session)
|
||||
{
|
||||
XrInteractionProfileState Profile = {XR_TYPE_INTERACTION_PROFILE_STATE};
|
||||
const XrPath TopLevelUserPath{OpenXRHMD->GetTrackedDevicePath(Devices[HandIndex])};
|
||||
const XrResult CurrentInteractionProfile{
|
||||
xrGetCurrentInteractionProfile(Session, TopLevelUserPath, &Profile)
|
||||
};
|
||||
if (XR_SUCCEEDED(CurrentInteractionProfile) && Profile.interactionProfile != XR_NULL_PATH)
|
||||
{
|
||||
OutMotionControllerData.DeviceName = FOpenXRPath(Profile.interactionProfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const FName HandTrackerName{"OpenXRHandTracking"};
|
||||
TArray<IHandTracker*> HandTrackers = IModularFeatures::Get().GetModularFeatureImplementations<IHandTracker>(
|
||||
IHandTracker::GetModularFeatureName());
|
||||
IHandTracker* HandTracker{nullptr};
|
||||
for (IHandTracker* HandTrackerIterator: HandTrackers)
|
||||
{
|
||||
if (!HandTrackerIterator)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const FName DeviceTypeName{HandTrackerIterator->GetHandTrackerDeviceTypeName()};
|
||||
if (DeviceTypeName != HandTrackerName)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
FSGXRTracker* SGXRTracker{static_cast<FSGXRTracker*>(HandTrackerIterator)};
|
||||
if (!SGXRTracker)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
HandTracker = SGXRTracker;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Hand == EControllerHand::Left || Hand == EControllerHand::Right)
|
||||
{
|
||||
static const FName MotionControllerName("OpenXR");
|
||||
TArray<IMotionController*> MotionControllers{
|
||||
IModularFeatures::Get().GetModularFeatureImplementations<IMotionController>(
|
||||
IMotionController::GetModularFeatureName())
|
||||
};
|
||||
IMotionController* MotionController{nullptr};
|
||||
for (IMotionController* MotionControllerIterator: MotionControllers)
|
||||
{
|
||||
if (!MotionControllerIterator)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const FName DeviceTypeName{MotionControllerIterator->GetMotionControllerDeviceTypeName()};
|
||||
if (DeviceTypeName != MotionControllerName)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
MotionController = MotionControllerIterator;
|
||||
break;
|
||||
}
|
||||
|
||||
const float WorldToMeters = XRTrackingSystem->GetWorldToMetersScale();
|
||||
if (MotionController)
|
||||
{
|
||||
const FTransform TrackingToWorld{XRTrackingSystem->GetTrackingToWorldTransform()};
|
||||
|
||||
{
|
||||
const FName AimSource{Hand == EControllerHand::Left ? FName{TEXT("LeftAim")} : FName{TEXT("RightAim")}};
|
||||
FRotator AimSourceRotation;
|
||||
FVector AimSourcePosition;
|
||||
const bool bGotAimOrientationAndPosition =
|
||||
MotionController->GetControllerOrientationAndPosition(
|
||||
0, AimSource, AimSourceRotation, AimSourcePosition, WorldToMeters);
|
||||
if (bGotAimOrientationAndPosition)
|
||||
{
|
||||
OutMotionControllerData.AimPosition = TrackingToWorld.TransformPosition(AimSourcePosition);
|
||||
OutMotionControllerData.AimRotation =
|
||||
TrackingToWorld.TransformRotation(AimSourceRotation.Quaternion());
|
||||
}
|
||||
OutMotionControllerData.bValid |= bGotAimOrientationAndPosition;
|
||||
}
|
||||
|
||||
const FName GripSource{Hand == EControllerHand::Left ? FName{TEXT("LeftGrip")} : FName{TEXT("RightGrip")}};
|
||||
{
|
||||
FRotator GripRotation;
|
||||
FVector GripPosition;
|
||||
const bool bGotGripSourceOrientationAndPosition =
|
||||
MotionController->GetControllerOrientationAndPosition(
|
||||
0, GripSource, GripRotation, GripPosition, WorldToMeters);
|
||||
if (bGotGripSourceOrientationAndPosition)
|
||||
{
|
||||
OutMotionControllerData.GripPosition = TrackingToWorld.TransformPosition(GripPosition);
|
||||
OutMotionControllerData.GripRotation =
|
||||
TrackingToWorld.TransformRotation(GripRotation.Quaternion());
|
||||
}
|
||||
OutMotionControllerData.bValid |= bGotGripSourceOrientationAndPosition;
|
||||
}
|
||||
|
||||
{
|
||||
const FName PalmSource{
|
||||
Hand == EControllerHand::Left ? FName{TEXT("LeftPalm")} : FName{TEXT("RightPalm")}
|
||||
};
|
||||
FRotator PalmRotation;
|
||||
FVector PalmPosition;
|
||||
const bool bGotPalmOrientationAndPosition = MotionController->GetControllerOrientationAndPosition(
|
||||
0, PalmSource, PalmRotation, PalmPosition, WorldToMeters);
|
||||
if (bGotPalmOrientationAndPosition)
|
||||
{
|
||||
OutMotionControllerData.GripPosition = TrackingToWorld.TransformPosition(PalmPosition);
|
||||
OutMotionControllerData.GripRotation =
|
||||
TrackingToWorld.TransformRotation(PalmRotation.Quaternion());
|
||||
}
|
||||
OutMotionControllerData.bValid |= bGotPalmOrientationAndPosition;
|
||||
}
|
||||
|
||||
OutMotionControllerData.TrackingStatus = MotionController->GetControllerTrackingStatus(0, GripSource);
|
||||
}
|
||||
|
||||
const bool bHandTrackingStateValid = HandTracker && HandTracker->IsHandTrackingStateValid();
|
||||
if (bHandTrackingStateValid)
|
||||
{
|
||||
OutMotionControllerData.DeviceVisualType = EXRVisualType::Hand;
|
||||
|
||||
OutMotionControllerData.bValid = HandTracker->GetAllKeypointStates(
|
||||
Hand, OutMotionControllerData.HandKeyPositions, OutMotionControllerData.HandKeyRotations,
|
||||
OutMotionControllerData.HandKeyRadii);
|
||||
|
||||
if (!ensureAlwaysMsgf(
|
||||
!OutMotionControllerData.bValid
|
||||
|| (OutMotionControllerData.HandKeyPositions.Num() == EHandKeypointCount
|
||||
&& OutMotionControllerData.HandKeyRotations.Num() == EHandKeypointCount
|
||||
&& OutMotionControllerData.HandKeyRadii.Num() == EHandKeypointCount),
|
||||
TEXT("Corrupted OutMotionControllerData!")))
|
||||
{
|
||||
OutMotionControllerData.bValid = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO
|
||||
// This is reportedly a WMR-specific convenience function for rapid prototyping. Not sure if it's useful for OpenXR.
|
||||
OutMotionControllerData.bIsGrasped = false;
|
||||
|
||||
return OutMotionControllerData.bValid;
|
||||
}
|
||||
|
||||
FSGXRTracker::FSGXRTracker(const TSharedRef<FGenericApplicationMessageHandler>& InMessageHandler)
|
||||
: Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user