#define GrayCamera
using UnityEngine;
using System.Runtime.InteropServices;
using System;
using EZXR.Glass.SixDof;
using EZXR.Glass.Core;
namespace EZXR.Glass.Inputs
{
///
/// 确保此脚本执行顺序在ARHandSDK中为首位,因为整个ARHandSDK的数据刷新在此脚本的Update中
///
[ScriptExecutionOrder(-53)]
///
/// 与底层算法交互
///
public class NativeSwapManager : MonoBehaviour
{
#region 单例
private static NativeSwapManager instance;
public static NativeSwapManager Instance
{
get
{
return instance;
}
}
#endregion
#region 与算法交互的struct定义
[StructLayout(LayoutKind.Sequential)]
public struct Point2
{
public float x;
public float y;
public override string ToString()
{
return "(" + x + "," + y + ")";
}
}
[StructLayout(LayoutKind.Sequential)]
public struct Point3
{
public float x;
public float y;
public float z;
public Point3(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
public Point3(Vector3 point)
{
x = point.x;
y = point.y;
z = point.z;
}
public override string ToString()
{
return "(" + x + "," + y + "," + z + ")";
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct HandTrackingData
{
public int version;
///
/// 检测范围内是否存在手
///
[MarshalAs(UnmanagedType.I1)]
public bool isTracked;
public float confidence;
///
/// 用来确定这个数据是左手的还是右手的
///
public HandType handType;
///
/// 手势类型
///
public GestureType gestureType;
///
/// 手部节点的数量
///
public uint handJointsCount;
///
/// 0是拇指根节点,3是大拇指指尖点,4是食指根节点,16是小拇指根节点向手腕延伸点(不到手腕),21是掌心点,22是手腕靠近大拇指,23是手腕靠近小拇指,24是手腕中心点
///
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 25)]
public HandJointData[] handJointData;
///
/// 模型手拉伸的比例参数
///
public float model_scale;
///
/// 数组id从0到4分别代表大拇指到小拇指
/// 值:0代表伸直,1代表完全弯曲
///
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public float[] fingler_curl;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public int[] reserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct HandJointData
{
public int version;
public HandJointType handJointType;
public Mat4f handJointPose;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public int[] reserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct Mat4f
{
public Vector4f col0;
public Vector4f col1;
public Vector4f col2;
public Vector4f col3;
}
public struct Vector4f
{
public float x, y, z, w;
}
#endregion
private partial struct NativeAPI
{
#if EZXRCS
[DllImport(NativeConsts.NativeLibrary)]
public static extern void getHandPoseData([Out, In] IntPtr handposedata, int size);
[DllImport(NativeConsts.NativeLibrary)]
public static extern void getHandPoseDataWithHeadPose([Out, In] IntPtr handposedata, int handposedataSize, float[] headpose, int headposeSize, double headposetimestamp);
#else
[DllImport(NativeConsts.NativeLibrary)]
public static extern void getHandPoseData([Out, In] IntPtr handposedata);
[DllImport(NativeConsts.NativeLibrary)]
public static extern void getHandPoseDataWithHeadPose([Out, In] IntPtr handposedata, float[] headpose, double headposetimestamp);
#endif
}
///
///
///
/// 0是GPU,1是DSP
///
[DllImport(NativeConsts.NativeLibrary)]
public static extern bool setHandRunMode(int mode);
public static void filterPoint(ref Point3 point, int id)
{
//if (!Application.isEditor)
//{
// filter_point(ref point, id);
//}
}
#region 变量定义
///
/// HandTrackingData更新的话会通知到外部
///
public static event Action OnHandTrackingDataUpdated;
///
/// 用于从算法c++获得检测结果,这个指针是在非托管区域开辟的内存的指针(内存大小是2个HandTrackingData长度)
///
public static IntPtr ptr_HandTrackingData;
public static IntPtr ptr_HandTrackingData0;
///
/// 手部追踪数据
///
HandTrackingData[] handTrackingData = new HandTrackingData[2];
int handTrackingDataLength;
#endregion
private void Awake()
{
instance = this;
}
void Start()
{
//为了接收算法的结果,在非托管内存区域开辟长度为2个HandTrackingData的内存
handTrackingDataLength = Marshal.SizeOf(typeof(HandTrackingData));
ptr_HandTrackingData = Marshal.AllocHGlobal(handTrackingDataLength * 2);
ptr_HandTrackingData0 = new IntPtr(ptr_HandTrackingData.ToInt64() + handTrackingDataLength);
//用于将Marshal开辟的非托管区域的所有值清零以避免内存区域原数据造成的影响
HandTrackingData handTrackingDataTemp = new HandTrackingData();
Marshal.StructureToPtr(handTrackingDataTemp, ptr_HandTrackingData, false);
Marshal.StructureToPtr(handTrackingDataTemp, ptr_HandTrackingData0, false);
handTrackingData[0] = new HandTrackingData();
handTrackingData[1] = new HandTrackingData();
}
void Update()
{
if (!Application.isEditor && (ARFrame.SessionStatus == EZVIOState.EZVIOCameraState_Tracking || ARFrame.SessionStatus == EZVIOState.EZVIOCameraState_Track_Limited))
{
Vector3 position = Vector3.zero;
Quaternion rotation = Quaternion.identity;
//Debug.Log("开始get_nreal_result_predict");
//getHandPoseData(ptr_HandTrackingData);
position = HMDPoseTracker.Instance.Head.position;
rotation = HMDPoseTracker.Instance.Head.rotation;
float[] headPosearr = new float[]{
position.x,position.y,position.z,
rotation.x,rotation.y,rotation.z,rotation.w };
#if EZXRCS
NativeAPI.getHandPoseDataWithHeadPose(ptr_HandTrackingData, handTrackingDataLength * 2, headPosearr, headPosearr.Length, ARFrame.HeadPoseTimestamp);
#else
NativeAPI.getHandPoseDataWithHeadPose(ptr_HandTrackingData, headPosearr, ARFrame.HeadPoseTimestamp);
#endif
//Debug.Log("得到数据get_nreal_result_predict");
//Debug.Log("开始解析handTrackingData");
handTrackingData[0] = Marshal.PtrToStructure(ptr_HandTrackingData);
handTrackingData[1] = Marshal.PtrToStructure(ptr_HandTrackingData0);
//Debug.Log("解析handTrackingData完毕");
//#region 用于测试
//NativeSwapManager.Mat4f mat4 = handTrackingData[0].handJointData[21].handJointPose;
//Matrix4x4 m = new Matrix4x4();
//m.SetColumn(0, new Vector4(mat4.col0.x, mat4.col0.y, mat4.col0.z, mat4.col0.w));
//m.SetColumn(1, new Vector4(mat4.col1.x, mat4.col1.y, mat4.col1.z, mat4.col1.w));
//m.SetColumn(2, new Vector4(mat4.col2.x, mat4.col2.y, mat4.col2.z, mat4.col2.w));
//m.SetColumn(3, new Vector4(mat4.col3.x, mat4.col3.y, mat4.col3.z, mat4.col3.w));
//if (!m.ValidTRS())
//{
// return;
//}
//Vector3 pos = m.GetColumn(3);
//Debug.Log("Launcher - Test => headPosition:" + position.ToString("0.00") + ", headRotation:" + rotation.ToString("0.00000") + ", HeadPoseTimestamp:" + ARFrame.HeadPoseTimestamp + ", handPosition:" + pos.ToString("0.00"));
//#endregion
if (OnHandTrackingDataUpdated != null)
{
OnHandTrackingDataUpdated(handTrackingData);
}
}
}
}
}