/**************************************************************************** * 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(); } } } }