using System; using System.Runtime.InteropServices; using System.Text; using Unity.Collections; namespace UnityEngine.XR.ARSubsystems { /// /// Represents the properties included in the camera frame. /// [Flags] public enum XROcclusionFrameProperties { /// /// No occlusion frame properties are included. /// None = 0, /// /// The timestamp of the frame is included. /// Timestamp = 1 << 0, /// /// The near and far planes are included. /// NearFarPlanes = 1 << 1, /// /// The poses for the frame are included. /// Poses = 1 << 2, /// /// The fields of view for the frame are included. /// Fovs = 1 << 3, } /// /// Represents a frame captured by the device camera with included metadata. /// [StructLayout(LayoutKind.Sequential)] public struct XROcclusionFrame : IEquatable, IDisposable { /// /// The properties that are included in the frame. /// /// The included properties. public XROcclusionFrameProperties properties => m_Properties; XROcclusionFrameProperties m_Properties; /// /// The timestamp of the frame, in nanoseconds. /// long m_TimestampNs; XRNearFarPlanes m_NearFarPlanes; /// /// Indices are correlated with . /// NativeArray m_Poses; /// /// Indices are correlated with . /// NativeArray m_Fovs; /// /// Constructor. /// /// The properties that are included in the frame. /// The timestamp of the frame, in nanoseconds. /// The near and far planes. /// The poses from which the frame was rendered. /// The fields of view for the frame. public XROcclusionFrame( XROcclusionFrameProperties properties, long timestamp, XRNearFarPlanes nearFarPlanes, NativeArray poses, NativeArray fovs) { m_Properties = properties; m_TimestampNs = timestamp; m_NearFarPlanes = nearFarPlanes; m_Poses = poses; m_Fovs = fovs; } /// /// Get the timestamp of the frame, if possible. /// /// The timestamp of the camera frame, in nanoseconds. /// if the frame has a timestamp that was output to . /// Otherwise, . public bool TryGetTimestamp(out long timestampNs) { if ((m_Properties & XROcclusionFrameProperties.Timestamp) != 0) { timestampNs = m_TimestampNs; return true; } timestampNs = default; return false; } /// /// Get the near and far planes for the frame, if possible. /// /// The near and far planes, if this method returns . /// if the frame has near and far planes that were output to . /// Otherwise, . public bool TryGetNearFarPlanes(out XRNearFarPlanes nearFarPlanes) { if ((m_Properties & XROcclusionFrameProperties.NearFarPlanes) != 0) { nearFarPlanes = m_NearFarPlanes; return true; } nearFarPlanes = default; return false; } /// /// Get an array of poses from which the frame was rendered, if possible. /// Poses are in Unity world space. /// /// The output array of poses, if this method returns . /// if the frame has poses that were output to . /// Otherwise, . public bool TryGetPoses(out NativeArray poses) { if ((m_Properties & XROcclusionFrameProperties.Poses) != 0) { poses = m_Poses; return true; } poses = default; return false; } /// /// Get an array of fields of view for the frame if possible. /// /// The output array of fields of view, if this method returns . /// if the frame has fields of view that were output to . /// Otherwise, . public bool TryGetFovs(out NativeArray fovs) { if ((m_Properties & XROcclusionFrameProperties.Fovs) != 0) { fovs = m_Fovs; return true; } fovs = default; return false; } /// /// Compares for equality. /// /// The other to compare against. /// if the represents the same object. /// Otherwise, . public bool Equals(XROcclusionFrame other) { return m_Properties == other.m_Properties && m_TimestampNs.Equals(other.m_TimestampNs) && m_NearFarPlanes.Equals(other.m_NearFarPlanes) && m_Poses.Equals(other.m_Poses) && m_Fovs.Equals(other.m_Fovs); } /// /// Compares for equality. /// /// An object to compare against. /// if is an and /// is also . Otherwise, . public override bool Equals(object obj) { return obj is XROcclusionFrame frame && Equals(frame); } /// /// Compares and for equality using . /// /// The left-hand-side of the comparison. /// The right-hand-side of the comparison. /// if compares equal to . /// Otherwise, . public static bool operator ==(XROcclusionFrame lhs, XROcclusionFrame rhs) { return lhs.Equals(rhs); } /// /// Compares and for inequality using . /// /// The left-hand-side of the comparison. /// The right-hand-side of the comparison. /// if compares equal to . /// Otherwise, . public static bool operator !=(XROcclusionFrame lhs, XROcclusionFrame rhs) { return !lhs.Equals(rhs); } /// /// Generates a hash code suitable for use in HashSet and Dictionary. /// /// A hash of this . public override int GetHashCode() { int hashCode = 486187739; unchecked { hashCode = hashCode * 486187739 + m_TimestampNs.GetHashCode(); hashCode = hashCode * 486187739 + ((int)m_Properties).GetHashCode(); hashCode = hashCode * 486187739 + m_Poses.GetHashCode(); hashCode = hashCode * 486187739 + m_Fovs.GetHashCode(); } return hashCode; } /// /// Generates a string representation of this instance suitable for debugging purposes. /// /// The string. public override string ToString() { var sb = new StringBuilder(); sb.AppendLine("{"); if ((m_Properties & XROcclusionFrameProperties.Timestamp) != 0) sb.AppendLine($" TimestampNs: {m_TimestampNs}"); if ((m_Properties & XROcclusionFrameProperties.NearFarPlanes) != 0) sb.AppendLine($" NearZ: {m_NearFarPlanes.nearZ}\n FarZ: {m_NearFarPlanes.farZ}"); if ((m_Properties & XROcclusionFrameProperties.Poses) != 0) { for (var i = 0; i < m_Poses.Length; i++) { sb.AppendLine($" Poses[{i}]: {m_Poses[i]}"); } } if ((m_Properties & XROcclusionFrameProperties.Fovs) != 0) { for (var i = 0; i < m_Fovs.Length; i++) { sb.AppendLine($" Fovs[{i}]: {m_Fovs[i]}"); } } sb.AppendLine("}"); return sb.ToString(); } /// /// Dispose native resources associated with this frame, including the native array of display matrices. /// public void Dispose() { if (m_Poses.IsCreated) m_Poses.Dispose(); if (m_Fovs.IsCreated) m_Fovs.Dispose(); } } }