using System; using System.Runtime.InteropServices; namespace UnityEngine.XR.ARSubsystems { /// /// The session relative data associated with a plane. /// /// [StructLayout(LayoutKind.Sequential)] public struct BoundedPlane : ITrackable, IEquatable { static readonly BoundedPlane s_Default = new BoundedPlane( TrackableId.invalidId, TrackableId.invalidId, Pose.identity, Vector2.zero, Vector2.zero, PlaneAlignment.None, TrackingState.None, IntPtr.Zero, PlaneClassification.None); /// /// Gets a default-initialized . This may be /// different from the zero-initialized version, e.g., the /// is Pose.identity instead of zero-initialized. /// public static BoundedPlane defaultValue => s_Default; /// /// Constructs a new . This is just a data container /// for a plane's session relative data. These are typically created by /// . /// /// The associated with the plane. /// The plane which subsumed this one. Use if it has not been subsumed. /// The Pose associated with the plane. /// The center, in plane-space (relative to ) of the plane. /// The dimensions associated with the plane. /// The associated with the plane. /// The associated with the plane. /// The native pointer associated with the plane. /// The associated with the plane. public BoundedPlane( TrackableId trackableId, TrackableId subsumedBy, Pose pose, Vector2 center, Vector2 size, PlaneAlignment alignment, TrackingState trackingState, IntPtr nativePtr, PlaneClassification classification) { m_TrackableId = trackableId; m_SubsumedById = subsumedBy; m_Pose = pose; m_Center = center; m_Size = size; m_Alignment = alignment; m_TrackingState = trackingState; m_NativePtr = nativePtr; m_Classification = classification; } /// /// The associated with this plane. /// public TrackableId trackableId { get { return m_TrackableId; } } /// /// The associated with the plane which subsumed this one. Will be /// if this plane has not been subsumed. /// public TrackableId subsumedById { get { return m_SubsumedById; } } /// /// The Pose, in session space, of the plane. /// public Pose pose { get { return m_Pose; } } /// /// The center of the plane in plane space (relative to its ). /// public Vector2 center { get { return m_Center; } } /// /// The extents of the plane (half dimensions) in meters. /// public Vector2 extents { get { return m_Size * 0.5f; } } /// /// The size (dimensions) of the plane in meters. /// public Vector2 size { get { return m_Size; } } /// /// The of the plane. /// public PlaneAlignment alignment { get { return m_Alignment; } } /// /// The of the plane. /// public TrackingState trackingState { get { return m_TrackingState; } } /// /// A native pointer associated with this plane. /// The data pointer to by this pointer is implementation defined. /// public IntPtr nativePtr { get { return m_NativePtr; } } /// /// The of the plane. /// public PlaneClassification classification => m_Classification; /// /// The width of the plane in meters. /// public float width { get { return m_Size.x; } } /// /// The height (or depth) of the plane in meters. /// public float height { get { return m_Size.y; } } /// /// The normal of the plane in session space. /// public Vector3 normal { get { return m_Pose.up; } } /// /// Gets an infinite plane in session space. /// public Plane plane { get { return new Plane(normal, center); } } /// /// Get the four corners of the plane in session space in clockwise order. /// /// The first vertex. /// The second vertex. /// The third vertex. /// The fourth vertex. public void GetCorners( out Vector3 p0, out Vector3 p1, out Vector3 p2, out Vector3 p3) { var sessionCenter = m_Pose.rotation * center + m_Pose.position; var sessionHalfX = (m_Pose.right) * (width * .5f); var sessionHalfZ = (m_Pose.forward) * (height * .5f); p0 = sessionCenter - sessionHalfX - sessionHalfZ; p1 = sessionCenter - sessionHalfX + sessionHalfZ; p2 = sessionCenter + sessionHalfX + sessionHalfZ; p3 = sessionCenter + sessionHalfX - sessionHalfZ; } /// /// Generates a new string describing the plane's properties suitable for debugging purposes. /// /// A string describing the plane's properties. public override string ToString() { return string.Format( "Plane:\n\ttrackableId: {0}\n\tsubsumedById: {1}\n\tpose: {2}\n\tcenter: {3}\n\tsize: {4}\n\talignment: {5}\n\tclassification: {6}\n\ttrackingState: {7}\n\tnativePtr: {8:X16}", trackableId, subsumedById, pose, center, size, alignment, classification, trackingState, nativePtr.ToInt64()); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; return obj is BoundedPlane && Equals((BoundedPlane)obj); } public override int GetHashCode() { unchecked { var hashCode = m_TrackableId.GetHashCode(); hashCode = (hashCode * 486187739) + m_SubsumedById.GetHashCode(); hashCode = (hashCode * 486187739) + m_Pose.GetHashCode(); hashCode = (hashCode * 486187739) + m_Center.GetHashCode(); hashCode = (hashCode * 486187739) + m_Size.GetHashCode(); hashCode = (hashCode * 486187739) + ((int)m_Alignment).GetHashCode(); hashCode = (hashCode * 486187739) + ((int)m_Classification).GetHashCode(); hashCode = (hashCode * 486187739) + ((int)m_TrackingState).GetHashCode(); hashCode = (hashCode * 486187739) + m_NativePtr.GetHashCode(); return hashCode; } } public static bool operator ==(BoundedPlane lhs, BoundedPlane rhs) { return lhs.Equals(rhs); } public static bool operator !=(BoundedPlane lhs, BoundedPlane rhs) { return !lhs.Equals(rhs); } public bool Equals(BoundedPlane other) { return m_TrackableId.Equals(other.m_TrackableId) && m_SubsumedById.Equals(other.m_SubsumedById) && m_Pose.Equals(other.m_Pose) && m_Center.Equals(other.m_Center) && m_Size.Equals(other.m_Size) && (m_Alignment == other.m_Alignment) && (m_Classification == other.m_Classification) && (m_TrackingState == other.m_TrackingState) && (m_NativePtr == other.m_NativePtr); } TrackableId m_TrackableId; TrackableId m_SubsumedById; Vector2 m_Center; Pose m_Pose; Vector2 m_Size; PlaneAlignment m_Alignment; TrackingState m_TrackingState; IntPtr m_NativePtr; PlaneClassification m_Classification; } }