diff --git a/Source/SenseGloveTracking/Private/SGTracking/SGXRTracker.cpp b/Source/SenseGloveTracking/Private/SGTracking/SGXRTracker.cpp index 3dce390b..968287c0 100644 --- a/Source/SenseGloveTracking/Private/SGTracking/SGXRTracker.cpp +++ b/Source/SenseGloveTracking/Private/SGTracking/SGXRTracker.cpp @@ -1013,6 +1013,235 @@ FTransform FSGXRTracker::FImpl::GetMeshFingerStartBoneRefTransform( return Transform; } +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7 + +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; + } + +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 4 + IOpenXRHMD* OpenXRHMD{XRTrackingSystem->GetIOpenXRHMD()}; +#else /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 4 */ + FOpenXRHMD* OpenXRHMD{static_cast(GEngine->XRSystem.Get())}; +#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 4 */ + if (!OpenXRHMD) + { + return false; + } + + TArray Devices; + const int32 HandIndex = static_cast(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 HandTrackers = IModularFeatures::Get().GetModularFeatureImplementations( + 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(HandTrackerIterator)}; + if (!SGXRTracker) + { + continue; + } + + HandTracker = SGXRTracker; + break; + } + + if (Hand == EControllerHand::Left || Hand == EControllerHand::Right) + { + static const FName MotionControllerName("OpenXR"); + TArray MotionControllers{ + IModularFeatures::Get().GetModularFeatureImplementations( + 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; + +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 + bool bTracked = false; +#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ + + OutMotionControllerData.bValid = HandTracker->GetAllKeypointStates( + Hand, + OutMotionControllerData.HandKeyPositions, + OutMotionControllerData.HandKeyRotations, + OutMotionControllerData.HandKeyRadii +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 + , bTracked +#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ + ); + +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 + // Unused! + (void) bTracked; +#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ + +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 + // TODO + // Begin backward compatibility with the deprecated function, remove this block along with the deprecated + // GetAllKeypointStates (though it should be time to remove this entire function as well)! + if (!OutMotionControllerData.bValid) + { + PRAGMA_DISABLE_DEPRECATION_WARNINGS + OutMotionControllerData.bValid = HandTracker->GetAllKeypointStates( + Hand, + OutMotionControllerData.HandKeyPositions, + OutMotionControllerData.HandKeyRotations, + OutMotionControllerData.HandKeyRadii); + PRAGMA_ENABLE_DEPRECATION_WARNINGS + } + // End backward compability. +#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 */ + + if (!ensureAlwaysMsgf( + !OutMotionControllerData.bValid + || (OutMotionControllerData.HandKeyPositions.Num() == EHandKeypointCount + && OutMotionControllerData.HandKeyRotations.Num() == EHandKeypointCount + && OutMotionControllerData.HandKeyRadii.Num() == EHandKeypointCount), + TEXT("Corrupted OutMotionControllerData!"))) + { + OutMotionControllerData.bValid = false; + return false; + } + } + } + + if (OutMotionControllerData.bValid) + { + OutMotionControllerData.TrackingStatus = ETrackingStatus::Tracked; + } + + return OutMotionControllerData.bValid; +} + +#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION < 7 */ + #if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 5 bool FSGXRTracker::GetMotionControllerState(