October3d55/M/PICOOpen7991a2a23d57V5/Source/PICOOpenXRMovement/Private/PICO_BodyTracking.cpp

144 lines
4.3 KiB
C++

// Copyright 2023 PICO Inc. All Rights Reserved.
#include "PICO_BodyTracking.h"
#include "PICO_MovementModule.h"
#include "OpenXRCore.h"
#include "PICOOpenXRRuntimeSettings.h"
#if PLATFORM_ANDROID
#include "Android/AndroidApplication.h"
#endif
FBodyTrackingPICO::FBodyTrackingPICO()
{
Locations.SetNum(XR_BODY_JOINT_COUNT_BD);
}
void FBodyTrackingPICO::Register()
{
RegisterOpenXRExtensionModularFeature();
}
void FBodyTrackingPICO::Unregister()
{
UnregisterOpenXRExtensionModularFeature();
}
bool FBodyTrackingPICO::GetRequiredExtensions(TArray<const ANSICHAR*>& OutExtensions)
{
if (UPICOOpenXRRuntimeSettings::GetBoolConfigByKey("bEnableBodyTracking"))
{
OutExtensions.Add("XR_BD_body_tracking");
return true;
}
return false;
}
const void* FBodyTrackingPICO::OnGetSystem(XrInstance InInstance, const void* InNext)
{
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrCreateBodyTrackerBD", (PFN_xrVoidFunction*)&xrCreateBodyTrackerBD));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrDestroyBodyTrackerBD", (PFN_xrVoidFunction*)&xrDestroyBodyTrackerBD));
XR_ENSURE(xrGetInstanceProcAddr(InInstance, "xrLocateBodyJointsBD", (PFN_xrVoidFunction*)&xrLocateBodyJointsBD));
Instance = InInstance;
return InNext;
}
void FBodyTrackingPICO::PostGetSystem(XrInstance InInstance, XrSystemId InSystem)
{
XrSystemBodyTrackingPropertiesBD BodyTrackingSystemProperties = { (XrStructureType)XR_TYPE_SYSTEM_BODY_TRACKING_PROPERTIES_BD };
XrSystemProperties systemProperties{ XR_TYPE_SYSTEM_PROPERTIES,&BodyTrackingSystemProperties };
XR_ENSURE(xrGetSystemProperties(InInstance, InSystem, &systemProperties));
bCurrentDeviceSupportBodyTracking = BodyTrackingSystemProperties.supportsBodyTracking == XR_TRUE;
}
void FBodyTrackingPICO::PostCreateSession(XrSession InSession)
{
Session = InSession;
}
void FBodyTrackingPICO::UpdateDeviceLocations(XrSession InSession, XrTime DisplayTime, XrSpace TrackingSpace)
{
PredictedTime = DisplayTime;
BaseSpace = TrackingSpace;
}
bool FBodyTrackingPICO::TryGetBodyState(FBodyStatePICO& outBodyState, float WorldToMeters)
{
if (bBodyTrackerIsRunning)
{
XrBodyJointsLocateInfoBD GetInfo = { (XrStructureType)XR_TYPE_BODY_JOINTS_LOCATE_INFO_BD };
GetInfo.baseSpace = BaseSpace;
GetInfo.time = PredictedTime;
outBodyState.IsActive = false;
outBodyState.BaseJointsData.SetNum(Locations.Num());
XrBodyJointLocationsBD BodyData = { (XrStructureType)XR_TYPE_BODY_JOINT_LOCATIONS_BD };
BodyData.jointLocationCount = Locations.Num();
BodyData.jointLocations = Locations.GetData();
if (XR_SUCCEEDED(xrLocateBodyJointsBD(BodyTracker, &GetInfo, &BodyData)))
{
outBodyState.IsActive = BodyData.allJointPosesTracked == XR_TRUE;
if (outBodyState.IsActive)
{
for (int i = 0; i < XR_BODY_JOINT_COUNT_BD; ++i)
{
outBodyState.BaseJointsData[i].Joint = (EBodyJointPICO)i;
outBodyState.BaseJointsData[i].bIsValid = Locations[i].locationFlags & (XR_SPACE_LOCATION_ORIENTATION_VALID_BIT | XR_SPACE_LOCATION_POSITION_VALID_BIT);
outBodyState.BaseJointsData[i].Orientation = FRotator(ToFQuat(Locations[i].pose.orientation));
outBodyState.BaseJointsData[i].Position = ToFVector(Locations[i].pose.position, WorldToMeters);
}
}
return true;
}
}
outBodyState.IsActive = false;
return false;
}
bool FBodyTrackingPICO::IsBodyTrackingEnabled()
{
return bBodyTrackerIsRunning;
}
bool FBodyTrackingPICO::IsBodyTrackingSupported()
{
return bCurrentDeviceSupportBodyTracking;
}
bool FBodyTrackingPICO::StartBodyTracking(EBodyTrackingModePICO Mode)
{
if (bCurrentDeviceSupportBodyTracking && Session != XR_NULL_HANDLE && BodyTracker == XR_NULL_HANDLE)
{
XrBodyTrackerCreateInfoBD CreateInfo = { (XrStructureType)XR_TYPE_BODY_TRACKER_CREATE_INFO_BD };
CreateInfo.jointSet = (XrBodyJointSetBD)Mode;
if (XR_FAILED(xrCreateBodyTrackerBD(Session, &CreateInfo, &BodyTracker)))
{
return false;
}
UE_LOG(PICOOpenXRMovement, Log, TEXT("Created BodyTracker."));
bBodyTrackerIsRunning = true;
return true;
}
return false;
}
bool FBodyTrackingPICO::StopBodyTracking()
{
if (BodyTracker != XR_NULL_HANDLE)
{
UE_LOG(PICOOpenXRMovement, Log, TEXT("Destroyed BodyTracker."));
bBodyTrackerIsRunning = false;
XrResult Result = xrDestroyBodyTrackerBD(BodyTracker);
if (XR_SUCCEEDED(Result))
{
BodyTracker = XR_NULL_HANDLE;
return true;
}
return false;
}
return false;
}