#if PICO_OPENXR_SDK
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Unity.XR.PXR;
using UnityEngine;
#if AR_FOUNDATION_5||AR_FOUNDATION_6
using UnityEngine.XR.ARSubsystems;
#endif
using UnityEngine.XR.OpenXR;
using UnityEngine.XR.OpenXR.Features;
#if UNITY_EDITOR
using UnityEditor.XR.OpenXR.Features;
#endif
namespace Unity.XR.OpenXR.Features.PICOSupport
{
public enum XrBodyJointSetBD
{
XR_BODY_JOINT_SET_DEFAULT_BD = 0, //default joint set XR_BODY_JOINT_SET_BODY_STAR_WITHOUT_ARM_BD
XR_BODY_JOINT_SET_BODY_START_WITHOUT_ARM_BD = 1,
XR_BODY_JOINT_SET_BODY_FULL_STAR_BD = 2
}
#if UNITY_EDITOR
[OpenXRFeature(UiName = "PICO Body Tracking",
Hidden = false,
BuildTargetGroups = new[] { UnityEditor.BuildTargetGroup.Android },
Company = "PICO",
OpenxrExtensionStrings = extensionString,
Version = PXR_Constants.SDKVersion,
FeatureId = featureId)]
#endif
public class BodyTrackingFeature : OpenXRFeatureBase
{
public const string featureId = "com.pico.openxr.feature.PICO_BodyTracking";
public const string extensionString = "XR_BD_body_tracking XR_PICO_body_tracking2";
public static bool isEnable => OpenXRRuntime.IsExtensionEnabled("XR_BD_body_tracking");
public override string GetExtensionString()
{
return extensionString;
}
[Obsolete("Please use StartBodyTracking(BodyJointSet JointSet, BodyTrackingBoneLength boneLength)")]
public static bool StartBodyTracking(XrBodyJointSetBD Mode)
{
if (!isEnable)
{
return false;
}
BodyTrackingBoneLength boneLength=new BodyTrackingBoneLength();
return StartBodyTracking((BodyJointSet)Mode, boneLength)==0;
}
/// Starts body tracking.
/// Specifies the body tracking mode (default or high-accuracy).
/// Specifies lengths (unit: cm) for the bones of the avatar, which is only available for the `BTM_FULL_BODY_HIGH` mode.
/// Bones that are not set lengths for will use the default values.
///
///
/// - `0`: success
/// - `1`: failure
///
public static int StartBodyTracking(BodyJointSet JointSet, BodyTrackingBoneLength boneLength)
{
if (!isEnable)
{
return 1;
}
BodyTrackingStartInfo startInfo = new BodyTrackingStartInfo();
startInfo.jointSet = JointSet;
startInfo.BoneLength = boneLength;
return Pxr_StartBodyTracking(ref startInfo);
}
/// Launches the PICO Motion Tracker app to perform calibration.
/// - For PICO Motion Tracker (Beta), the user needs to follow the instructions on the home of the PICO Motion Tracker app to complete calibration.
/// - For PICO Motion Tracker (Official), "single-glance calibration" will be performed. When a user has a glance at the PICO Motion Tracker on their lower legs, calibration is completed.
///
///
/// - `0`: success
/// - `1`: failure
///
public static int StartMotionTrackerCalibApp()
{
if (!isEnable)
{
return 1;
}
return Pxr_StartBodyTrackingCalibApp();
}
public static bool IsBodyTrackingSupported()
{
if (!isEnable)
{
return false;
}
bool supported=false;
Pxr_GetBodyTrackingSupported(ref supported);
return supported;
}
///
/// Gets the data about the poses of body joints.
///
/// Reserved parameter, pass `0`.
/// Contains the data about the poses of body joints, including position, action, and more.
[Obsolete("Please use GetBodyTrackingData",true)]
public static bool GetBodyTrackingPose(ref BodyTrackerResult bodyTrackerResult)
{
return false;
}
/// Stops body tracking.
///
/// - `0`: success
/// - `1`: failure
///
public static int StopBodyTracking()
{
return Pxr_StopBodyTracking();
}
[Obsolete("Please use StopBodyTracking")]
private void OnDestroy()
{
if (!isEnable)
{
return;
}
StopBodyTracking();
}
[Obsolete("Please use StartMotionTrackerCalibApp")]
public static void OpenFitnessBandCalibrationAPP()
{
StartMotionTrackerCalibApp();
}
/// Gets body tracking data.
/// Specifies the display time and the data filtering flags.
/// For the display time, for example, when it is set to 0.1 second, it means predicting the pose of the tracked node 0.1 seconds ahead.
///
/// Returns the array of data for all tracked nodes.
///
/// - `0`: success
/// - `1`: failure
///
public unsafe static int GetBodyTrackingData(ref BodyTrackingGetDataInfo getInfo, ref BodyTrackingData data)
{
if (!isEnable)
{
return 1;
}
int val = -1;
{
val = Pxr_GetBodyTrackingData(ref getInfo, ref data);
for (int i = 0; i < (int)BodyTrackerRole.ROLE_NUM; i++)
{
data.roleDatas[i].localPose.PosZ = -data.roleDatas[i].localPose.PosZ;
data.roleDatas[i].localPose.RotQz = -data.roleDatas[i].localPose.RotQz;
data.roleDatas[i].localPose.RotQw = -data.roleDatas[i].localPose.RotQw;
data.roleDatas[i].velo[3] = -data.roleDatas[i].velo[3];
data.roleDatas[i].acce[3] = -data.roleDatas[i].acce[3];
data.roleDatas[i].wvelo[3] = -data.roleDatas[i].wvelo[3];
data.roleDatas[i].wacce[3] = -data.roleDatas[i].wacce[3];
}
}
return val;
}
/// Gets the state of PICO Motion Tracker and, if any, the reason for an exception.
/// Indicates whether the PICO Motion Tracker is tracking normally:
/// - `true`: is tracking
/// - `false`: tracking lost
///
/// Returns the information about body tracking state.
///
/// - `0`: success
/// - `1`: failure
///
public static int GetBodyTrackingState(ref bool isTracking, ref BodyTrackingStatus state)
{
int val = -1;
{
val = Pxr_GetBodyTrackingState(ref isTracking, ref state);
}
return val;
}
#if AR_FOUNDATION_5||AR_FOUNDATION_6
public bool isBodyTracking=false;
static List s_HumanBodyDescriptors = new List();
protected override void OnSubsystemCreate()
{
base.OnSubsystemCreate();
if (isBodyTracking)
{
CreateSubsystem(
s_HumanBodyDescriptors,
PXR_HumanBodySubsystem.k_SubsystemId);
}
}
protected override void OnSubsystemStart()
{
if (isBodyTracking)
{
StartSubsystem();
}
}
protected override void OnSubsystemStop()
{
if (isBodyTracking)
{
StopSubsystem();
}
}
protected override void OnSubsystemDestroy()
{
if (isBodyTracking)
{
DestroySubsystem();
}
}
#endif
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int Pxr_StartBodyTrackingCalibApp();
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int Pxr_GetBodyTrackingSupported(ref bool supported);
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int Pxr_StartBodyTracking(ref BodyTrackingStartInfo startInfo);
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int Pxr_StopBodyTracking();
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int Pxr_GetBodyTrackingState(ref bool isTracking, ref BodyTrackingStatus state);
[DllImport(OpenXRExtensions.PXR_PLATFORM_DLL, CallingConvention = CallingConvention.Cdecl)]
private static extern int Pxr_GetBodyTrackingData(ref BodyTrackingGetDataInfo getInfo, ref BodyTrackingData data);
}
}
#endif