using System; using System.Runtime.InteropServices; using System.Text; 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, PlaneClassifications.None); /// /// Gets a default-initialized instance. This can 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 instance. Bounded Plane objects are typically created by /// XRPlaneSubsystem.GetChanges. /// /// The `TrackableId` 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 of the plane, in plane space (relative to ). /// The dimensions associated with the plane. /// The `PlaneAlignment` associated with the plane. /// The `TrackingState` associated with the plane. /// The native pointer associated with the plane. /// The `PlaneClassification` associated with the plane. [Obsolete("BoundedPlane(TrackableId, TrackableId, Pose, Vector2, Vector2, PlaneAlignment, TrackingState, IntPtr, PlaneClassification) has been deprecated in AR Foundation version 6.0. Use BoundedPlane(TrackableId, TrackableId, Pose, Vector2, Vector2, PlaneAlignment, TrackingState, IntPtr, PlaneClassifications) instead.")] 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_Classifications = classification.ConvertToPlaneClassifications(); } /// /// Constructs a new instance. BoundedPlane objects are typically created by /// XRPlaneSubsystem.GetChanges. /// /// The `TrackableId` associated with the plane. /// The plane which subsumed this one. Use if it has not been subsumed. /// The Pose describing the position and orientation of the plane. /// The center of the plane, in plane space (relative to ). /// The dimensions of the plane. /// The `PlaneAlignment` describing the alignment between the plane and the session space axes. /// The `TrackingState` describing how well the XR device is tracking the plane. /// The native pointer associated with the plane. /// The PlaneClassifications assigned to the plane by the XR device. public BoundedPlane( TrackableId trackableId, TrackableId subsumedBy, Pose pose, Vector2 center, Vector2 size, PlaneAlignment alignment, TrackingState trackingState, IntPtr nativePtr, PlaneClassifications classifications) { 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_Classifications = classifications; } /// /// The associated with this plane. /// public TrackableId trackableId => m_TrackableId; /// /// The associated with the plane which subsumed this one. Will be /// if this plane has not been subsumed. /// public TrackableId subsumedById => m_SubsumedById; /// /// The Pose, in session space, of the plane. /// public Pose pose => m_Pose; /// /// The center of the plane in plane space (relative to its ). /// public Vector2 center => m_Center; /// /// The extents of the plane (half dimensions) in meters. /// public Vector2 extents => m_Size * 0.5f; /// /// The size (dimensions) of the plane in meters. /// public Vector2 size => m_Size; /// /// The of the plane. /// public PlaneAlignment alignment => m_Alignment; /// /// The of the plane. /// public TrackingState trackingState => m_TrackingState; /// /// A native pointer associated with this plane. /// The data pointer to by this pointer is implementation defined. /// public IntPtr nativePtr => m_NativePtr; /// /// The classification of this plane. /// [Obsolete("classification has been deprecated in AR Foundation version 6.0. Use classifications instead.")] public PlaneClassification classification { get { PlaneClassification classificationTemp = PlaneClassification.None; classificationTemp.ConvertFromPlaneClassifications(m_Classifications); return classificationTemp; } } /// /// The classifications of this plane. /// public PlaneClassifications classifications => m_Classifications; /// /// The width of the plane in meters. /// public float width => m_Size.x; /// /// The height (or depth) of the plane in meters. /// public float height => m_Size.y; /// /// The normal of the plane in session space. /// public Vector3 normal => m_Pose.up; /// /// Gets an infinite plane in session space. /// public Plane plane => 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 that describes the plane's properties, suitable for debugging purposes. /// /// A string that describes the plane's properties. public override string ToString() { SharedStringBuilder.stringBuilder.AppendLine("Plane:"); SharedStringBuilder.stringBuilder.AppendLine("\ttrackableId: " + trackableId); SharedStringBuilder.stringBuilder.AppendLine("\tsubsumedById: " + subsumedById); SharedStringBuilder.stringBuilder.AppendLine("\tpose: " + pose); SharedStringBuilder.stringBuilder.AppendLine("\tcenter: " + center); SharedStringBuilder.stringBuilder.AppendLine("\tsize: " + size); SharedStringBuilder.stringBuilder.AppendLine("\talignment: " + alignment); SharedStringBuilder.stringBuilder.AppendLine("\tclassifications: " + classifications); SharedStringBuilder.stringBuilder.AppendLine("\ttrackingState: " + trackingState); SharedStringBuilder.stringBuilder.Append("\tnativePtr: "); SharedStringBuilder.stringBuilder.Append("" + nativePtr.ToInt64(), 0, 16); SharedStringBuilder.stringBuilder.Append("\n"); string tempString = SharedStringBuilder.stringBuilder.ToString(); SharedStringBuilder.stringBuilder.Clear(); return tempString; } /// /// Tests for equality. /// /// The `object` to compare against. /// `True` if is of type and /// also returns `true`; otherwise `false`. public override bool Equals(object obj) => (obj is BoundedPlane other) && Equals(other); /// /// Generates a hash suitable for use with containers like `HashSet` and `Dictionary`. /// /// A hash code generated from this object's fields. 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_Classifications).GetHashCode(); hashCode = (hashCode * 486187739) + ((int)m_TrackingState).GetHashCode(); hashCode = (hashCode * 486187739) + m_NativePtr.GetHashCode(); return hashCode; } } /// /// Tests for equality. Same as . /// /// The left-hand side of the comparison. /// The right-hand side of the comparison. /// `True` if is equal to , otherwise `false`. public static bool operator ==(BoundedPlane lhs, BoundedPlane rhs) => lhs.Equals(rhs); /// /// Tests for inequality. Same as `!`. /// /// The left-hand side of the comparison. /// The right-hand side of the comparison. /// `True` if is not equal to , otherwise `false`. public static bool operator !=(BoundedPlane lhs, BoundedPlane rhs) => !lhs.Equals(rhs); /// /// Tests for equality. /// /// The other to compare against. /// `True` if every field in is equal to this , otherwise false. 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_Classifications == other.m_Classifications) && (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; PlaneClassifications m_Classifications; } }