/****************************************************************************
* Copyright 2019 Nreal Techonology Limited. All rights reserved.
*
* This file is part of NRSDK.
*
* https://www.nreal.ai/
*
*****************************************************************************/
namespace NRKernal
{
using System;
using System.Collections.Generic;
using UnityEngine;
///
/// Holds information about NR Device's pose in the world coordinate, trackables, etc.. Through
/// this class, application can get the information of current frame. It contains session status,
/// lost tracking reason, device pose, trackables, etc.
public class NRFrame
{
/// Get the tracking state of HMD.
/// The session status.
public static SessionState SessionStatus
{
get
{
return NRSessionManager.Instance.SessionState;
}
}
/// Get the lost tracking reason of HMD.
/// The lost tracking reason.
public static LostTrackingReason LostTrackingReason
{
get
{
return NRSessionManager.Instance.LostTrackingReason;
}
}
/// Gets the nr renderer.
/// The nr renderer.
public static NRRenderer NRRenderer
{
get
{
return NRSessionManager.Instance.NRRenderer;
}
}
/// The head pose.
private static Pose m_HeadPose;
/// Get the pose of device in unity world coordinate.
/// Pose of device.
public static Pose HeadPose
{
get
{
return m_HeadPose;
}
}
public static bool isHeadPoseReady { get; private set; } = false;
/// Gets head pose by recommond timestamp.
/// [in,out] The pose.
/// True if it succeeds, false if it fails.
[Obsolete("Use 'GetFramePresentHeadPose' instead.")]
public static bool GetHeadPoseRecommend(ref Pose pose)
{
if (SessionStatus == SessionState.Running)
{
return NRSessionManager.Instance.NativeAPI.NativeHeadTracking.GetHeadPoseRecommend(ref pose);
}
return false;
}
/// Gets head pose by timestamp.
/// [in,out] The pose.
/// The timestamp.
/// True if it succeeds, false if it fails.
public static bool GetHeadPoseByTime(ref Pose pose, UInt64 timestamp)
{
if (SessionStatus == SessionState.Running)
{
return NRSessionManager.Instance.TrackingSubSystem.GetHeadPose(ref pose, timestamp);
}
return false;
}
///
/// Get the pose information when the current frame display on the screen.
///
///
/// current timestamp to the pose.
///
public static bool GetFramePresentHeadPose(ref Pose pose, ref LostTrackingReason lostReason, ref UInt64 timestamp)
{
if (SessionStatus == SessionState.Running &&
(NRRenderer == null || NRRenderer.CurrentState == NRRenderer.RendererState.Running))
{
isHeadPoseReady = NRSessionManager.Instance.TrackingSubSystem.GetFramePresentHeadPose(ref pose, ref lostReason, ref timestamp);
return isHeadPoseReady;
}
return false;
}
/// Get the pose of center camera between left eye and right eye.
/// The center eye pose.
public static Pose CenterEyePose
{
get
{
Transform leftCamera = NRSessionManager.Instance.NRHMDPoseTracker.leftCamera.transform;
Transform rightCamera = NRSessionManager.Instance.NRHMDPoseTracker.rightCamera.transform;
Vector3 centerEye_pos = (leftCamera.position + rightCamera.position) * 0.5f;
Quaternion centerEye_rot = Quaternion.Lerp(leftCamera.rotation, rightCamera.rotation, 0.5f);
return new Pose(centerEye_pos, centerEye_rot);
}
}
/// The eye position from head.
private static EyePoseData m_EyePosFromHead;
/// Get the offset position between eye and head.
/// The eye pose from head.
public static EyePoseData EyePoseFromHead
{
get
{
if (SessionStatus == SessionState.Running)
{
m_EyePosFromHead.LEyePose = NRDevice.Subsystem.GetDevicePoseFromHead(NativeDevice.LEFT_DISPLAY);
m_EyePosFromHead.REyePose = NRDevice.Subsystem.GetDevicePoseFromHead(NativeDevice.RIGHT_DISPLAY);
m_EyePosFromHead.RGBEyePose = NRDevice.Subsystem.GetDevicePoseFromHead(NativeDevice.RGB_CAMERA);
}
return m_EyePosFromHead;
}
}
/// Get the offset position between device and head.
/// The device pose from head.
public static Pose GetDevicePoseFromHead(NativeDevice device)
{
return NRDevice.Subsystem.GetDevicePoseFromHead(device);
}
/// Get the project matrix of camera in unity.
/// [out] True to result.
/// The znear.
/// The zfar.
/// project matrix of camera.
public static EyeProjectMatrixData GetEyeProjectMatrix(out bool result, float znear, float zfar)
{
return NRDevice.Subsystem.GetEyeProjectMatrix(out result, znear, zfar);
}
/// Get the intrinsic matrix of device.
/// The device intrinsic matrix.
public static NativeMat3f GetDeviceIntrinsicMatrix(NativeDevice device)
{
return NRDevice.Subsystem.GetDeviceIntrinsicMatrix(device);
}
/// Get the distortion param of device.
/// The device intrinsic matrix.
public static NRDistortionParams GetDeviceDistortion(NativeDevice device)
{
return NRDevice.Subsystem.GetDeviceDistortion(device);
}
/// Get the intrinsic matrix of rgb camera.
/// The RGB camera intrinsic matrix.
public static NativeMat3f GetRGBCameraIntrinsicMatrix()
{
return GetDeviceIntrinsicMatrix(NativeDevice.RGB_CAMERA);
}
/// Get the Distortion of rgbcamera.
/// The RGB camera distortion.
public static NRDistortionParams GetRGBCameraDistortion()
{
return GetDeviceDistortion(NativeDevice.RGB_CAMERA);
}
/// Gets the resolution of device.
/// device index.
/// The device resolution.
public static NativeResolution GetDeviceResolution(NativeDevice device)
{
return NRDevice.Subsystem.GetDeviceResolution(device);
}
/// Gets device fov.
/// The display index.
/// [in,out] The out device fov.
/// A NativeResult.
public static void GetEyeFov(NativeDevice eye, ref NativeFov4f fov)
{
NRDevice.Subsystem.GetEyeFov(eye, ref fov);
}
private static UInt64 m_CurrentPoseTimeStamp = 0;
public static UInt64 CurrentPoseTimeStamp
{
get
{
#if USING_XR_SDK
return NRSessionManager.Instance.TrackingSubSystem.GetHMDTimeNanos();
#else
return m_CurrentPoseTimeStamp;
#endif
}
}
internal static void ResetHeadPose()
{
m_CurrentPoseTimeStamp = 0;
m_HeadPose = Pose.identity;
}
internal static void OnPreUpdate(ref LostTrackingReason lostTrackReason)
{
Pose pose = Pose.identity;
LostTrackingReason lostReason = LostTrackingReason.NONE;
ulong timeStamp = 0;
bool result = GetFramePresentHeadPose(ref pose, ref lostReason, ref timeStamp);
if (result)
{
lostTrackReason = lostReason;
if (lostReason != LostTrackingReason.PRE_INITIALIZING && lostReason != LostTrackingReason.INITIALIZING)
{
m_HeadPose = pose;
m_CurrentPoseTimeStamp = timeStamp;
}
else
{
NRDebugger.Info("[NRFrame] OnPreUpdate: LostTrackReason={0}, pose={1}, timeStamp={2}, lastHeadPose={3}, lastTimeStamp={4}",
lostReason, pose.ToString("F4"), timeStamp, m_HeadPose.ToString("F4"), m_CurrentPoseTimeStamp);
}
}
// NRDebugger.Info("[NRFrame] OnPreUpdate: result={2}, LostTrackReason={3}, pos={0}, headPos={1}, ", pose.ToString("F4"), m_HeadPose.ToString("F4"), result, LostTrackingReason);
}
/// Get the list of trackables with specified filter.
/// Generic type parameter.
/// A list where the returned trackable is stored. The previous values
/// will be cleared.
/// Query filter.
public static void GetTrackables(List trackables, NRTrackableQueryFilter filter) where T : NRTrackable
{
if (SessionStatus != SessionState.Running)
{
return;
}
trackables.Clear();
NRSessionManager.Instance.TrackableFactory.GetTrackables(trackables, filter);
}
public static Matrix4x4 GetWorldMatrixFromUnityToNative()
{
var hmdPoseTracker = NRSessionManager.Instance.NRHMDPoseTracker;
if (hmdPoseTracker == null)
{
return Matrix4x4.identity;
}
else
{
return hmdPoseTracker.GetWorldOffsetMatrixFromNative();
}
}
}
}