资源名称
基于Pico Unity SDK 3.0.5 和Pico体感追踪器正式版 进行开发
主要模式
独立追踪、动作捕捉
模式说明
独立追踪
API返回每个传感器独立的信息,包括在空间中的位置、旋转等信息。需要注意的是,当追踪器背对头显,或者距离头显超出1米以上,就会丢失位置信息,只剩下旋转信息。
动作捕捉
API返回身体点位的信息,如果需要用于驱动人物模型,需要单独计算关节的IK,可以接入Pico Avatar,已经做好了IK的计算。
示例代码
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Unity.XR.PXR;
using UnityEngine;
using UnityEngine.UI;
public class GetPicoTracker : MonoBehaviour
{
public MotionTrackerConnectState state = new MotionTrackerConnectState();
/// <summary>
/// 硬件信息展示
/// </summary>
public Text TrackerDeviceInfo;
/// <summary>
/// 校准状态展示
/// </summary>
public Text CalibStateInfo;
/// <summary>
/// 追踪器电量
/// </summary>
public Text TrackerBattery;
/// <summary>
/// 当前设备是否支持全身动捕
/// </summary>
public Text BodyTrackingSupported;
public Transform bodytrackers;
private int bodytrackingSum = 24;
void Start()
{
}
void Update()
{
MotionTracking();
if(CalibState==1)
BodyTracking();
}
private int objectTrackersMaxNum = 3;
public Transform[] objectTrackers;
void MotionTracking()
{
#if UNITY_ANDROID
// 获取当前的追踪模式:全身动捕或独立追踪
MotionTrackerMode trackingMode = PXR_MotionTracking.GetMotionTrackerMode();
if (trackingMode != MotionTrackerMode.MotionTracking)
return;
for (int i = 0; i < objectTrackersMaxNum; i++)
{
objectTrackers[i].localScale = Vector3.zero;
}
// 更新体感追踪器的位姿信息
// 获取体感追踪器的序列号,用于识别它们
MotionTrackerConnectState mtcs = new MotionTrackerConnectState();
int ret = PXR_MotionTracking.GetMotionTrackerConnectStateWithSN(ref mtcs);
if (ret == 0)
{
if (mtcs.trackersSN.Length > 0)
{
for (int i = 0; i < mtcs.trackerSum; i++)
{
string sn = mtcs.trackersSN[i].value.ToString().Trim();
if (!string.IsNullOrEmpty(sn))
{
// 获取每个体感追踪器的位置和旋转预估值
MotionTrackerLocations locations = new MotionTrackerLocations();
MotionTrackerConfidence confidence = new MotionTrackerConfidence();
int result = PXR_MotionTracking.GetMotionTrackerLocations(mtcs.trackersSN[i], ref locations, ref confidence);
// 如果成功获取位置和旋转信息
if (result == 0)
{
MotionTrackerLocation localLocation = locations.localLocation;
objectTrackers[i].localPosition = localLocation.pose.Position.ToVector3();
objectTrackers[i].localRotation = localLocation.pose.Orientation.ToQuat();
objectTrackers[i].localScale = Vector3.one;
}
}
}
}
}
#endif
}
void BodyTracking()
{
#if UNITY_ANDROID
MotionTrackerMode trackingMode = PXR_MotionTracking.GetMotionTrackerMode();
if (trackingMode != MotionTrackerMode.BodyTracking)
return;
BodyTrackingGetDataInfo bdi = new BodyTrackingGetDataInfo();
BodyTrackingData bd = new BodyTrackingData();
int ret = PXR_MotionTracking.GetBodyTrackingData(ref bdi, ref bd);
for (int i = 0; i < bodytrackingSum; i++)
{
bodytrackers.GetChild(i).position = new Vector3((float)bd.roleDatas[i].localPose.PosX, (float)bd.roleDatas[i].localPose.PosY, (float)bd.roleDatas[i].localPose.PosZ);
bodytrackers.GetChild(i).rotation = new Quaternion((float)bd.roleDatas[i].localPose.RotQx, (float)bd.roleDatas[i].localPose.RotQy, (float)bd.roleDatas[i].localPose.RotQz, (float)bd.roleDatas[i].localPose.RotQw);
bodytrackers.GetChild(i).localScale = Vector3.one * 0.05f;
}
#endif
}
/// <summary>
/// 全身动捕模式检查
/// </summary>
public void CheckBodyTracking()
{
PXR_MotionTracking.CheckMotionTrackerModeAndNumber(MotionTrackerMode.BodyTracking, MotionTrackerNum.TWO);//开启
}
/// <summary>
/// 独立追踪模式检查
/// </summary>
public void CheckMotionTracking()
{
PXR_MotionTracking.CheckMotionTrackerModeAndNumber(MotionTrackerMode.MotionTracking, MotionTrackerNum.TWO);//开启
}
/// <summary>
/// 获取硬件信息
/// </summary>
public void GetTrackerDeviceInfo()
{
PXR_MotionTracking.GetMotionTrackerConnectStateWithSN(ref state);
TrackerDeviceInfo.text = "已连接追踪器数量:" + state.trackerSum;
for (int i = 0; i < state.trackersSN.Length; i++)
{
TrackerDeviceInfo.text += "设备" + i + "SN码:" + state.trackersSN[i].value;
}
}
/// <summary>
/// 追踪器电池电量获取
/// </summary>
public void CheckTrackerBattery()
{
TrackerBattery.text = "";
for (int i = 0; i < state.trackerSum; i++)
{
int battery = 0; // PICO 体感追踪器(正式版)取值范围: 0-10
PXR_Input.GetMotionTrackerBattery(i + 1, ref battery);
TrackerBattery.text += "追踪器" + i + "电量:" + battery;
}
}
/// <summary>
/// 获取校准状态
/// </summary>
public void GetTrackCalibState()
{
int calibrated = 0;
PXR_Input.GetMotionTrackerCalibState(ref calibrated);
if (calibrated == 0) CalibStateInfo.text = "未校准";
if (calibrated == 1) CalibStateInfo.text = "已校准";
CalibState = calibrated;
}
/// <summary>
/// 校准状态
/// </summary>
public int CalibState;
/// <summary>
/// 启动校准程序接口
/// </summary>
public void StartMotionTrackerCalibApp()
{
PXR_MotionTracking.StartMotionTrackerCalibApp();//启动校准
}
public void StopBodyTracking()
{
int ret = PXR_MotionTracking.StopBodyTracking();
}
/// <summary>
/// 查询当前设备是否支持全身动捕
/// </summary>
public void GetBodyTrackingSupported()
{
bool result = false;
PXR_MotionTracking.GetBodyTrackingSupported(ref result);
if (result)
BodyTrackingSupported.text = "当前设备支持全身动捕";
else
BodyTrackingSupported.text = "当前设备不支持全身动捕";
}
/// <summary>
/// 开启标准精度动捕
/// </summary>
public void StartNormalBodyTracking()
{
// 设置骨骼长度
BodyTrackingBoneLength boneLength = new BodyTrackingBoneLength();
// 开启全身动捕默认模式
int ret = PXR_MotionTracking.StartBodyTracking(BodyTrackingMode.BTM_FULL_BODY_LOW, boneLength);
}
/// <summary>
/// 开启高精度动捕
/// </summary>
public void StartHighBodyTracking()
{
// 设置骨骼长度
BodyTrackingBoneLength boneLength = new BodyTrackingBoneLength();
// 开启全身动捕默认模式
int ret = PXR_MotionTracking.StartBodyTracking(BodyTrackingMode.BTM_FULL_BODY_HIGH, boneLength);
}
}