using System; using System.Text; using Unity.Collections; namespace UnityEngine.XR.ARSubsystems { /// /// Container for mesh data associated with an . Not all implementations /// support all data. Check for existence with NativeArray's IsCreated property. /// public struct XRFaceMesh : IEquatable, IDisposable { /// /// Attributes associated with the face mesh, such as normals and texture coordinates. /// Vertex positions and triangle indices are assumed to exist already. These are /// optional attributes. Used with . /// [Flags] public enum Attributes { /// /// No attributes specified. /// None = 0, /// /// The face mesh contains normals. /// Normals = 1 << 0, /// /// The face mesh contains texture coordinates. /// UVs = 1 << 1 } /// /// Resize the NativeArrays held by this struct. This method will deallocate /// the NativeArrays if they are not needed or if they are not the correct size. /// If they are already the correct size, this method does not mutate those NativeArrays. /// This facilitate memory reuse when the number of vertices or triangles in the face does /// not change frequently. /// /// The number of vertices in the mesh. /// The number of triangles in the mesh. /// Optional mesh attributes. This affects whether /// and will be (re)allocated or disposed. /// If a reallocation is required, this allocator will be used. public void Resize( int vertexCount, int triangleCount, Attributes attributes, Allocator allocator) { Resize(vertexCount, allocator, ref m_Vertices, true); Resize(vertexCount, allocator, ref m_Normals, (attributes & Attributes.Normals) != 0); Resize(vertexCount, allocator, ref m_UVs, (attributes & Attributes.UVs) != 0); Resize(triangleCount * 3, allocator, ref m_Indices, true); } /// /// The vertices in the mesh. This is a parallel array to /// and . /// public NativeArray vertices => m_Vertices; NativeArray m_Vertices; /// /// The normals in the mesh. This is a parallel array to /// and . /// public NativeArray normals => m_Normals; NativeArray m_Normals; /// /// The triangle indices of the mesh. There are three times as many indices as triangles. /// public NativeArray indices => m_Indices; NativeArray m_Indices; /// /// The texture coordinates for the mesh. This is a parallel /// array to and . /// public NativeArray uvs => m_UVs; NativeArray m_UVs; /// /// Disposes of the all four native arrays: /// , , , and . /// Checking for creation before calling Dispose. /// public void Dispose() { if (m_Vertices.IsCreated) m_Vertices.Dispose(); if (m_Normals.IsCreated) m_Normals.Dispose(); if (m_Indices.IsCreated) m_Indices.Dispose(); if (m_UVs.IsCreated) m_UVs.Dispose(); } /// /// 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 hash = m_Vertices.GetHashCode(); hash = hash * 486187739 + m_Normals.GetHashCode(); hash = hash * 486187739 + m_Indices.GetHashCode(); hash = hash * 486187739 + m_UVs.GetHashCode(); return hash; } } /// /// 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) { if (!(obj is XRFaceMesh)) return false; return Equals((XRFaceMesh)obj); } /// /// Generates a string suitable for debugging purposes. /// /// A string representation of this . public override string ToString() { return string.Format("XRFaceMesh: {0} vertices {1} normals {2} indices {3} uvs", m_Vertices.Length, m_Normals.Length, m_Indices.Length, m_UVs.Length); } /// /// Tests for equality. /// /// The other to compare against. /// `True` if every field in is equal to this , otherwise false. public bool Equals(XRFaceMesh other) { return m_Vertices.Equals(other.m_Vertices) && m_Normals.Equals(other.m_Normals) && m_Indices.Equals(other.m_Indices) && m_UVs.Equals(other.m_UVs); } /// /// 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 ==(XRFaceMesh lhs, XRFaceMesh 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 !=(XRFaceMesh lhs, XRFaceMesh rhs) => !lhs.Equals(rhs); static void Resize(int length, Allocator allocator, ref NativeArray array, bool shouldExist) where T : struct { if (shouldExist) { if (array.IsCreated) { if (array.Length != length) { array.Dispose(); array = new NativeArray(length, allocator); } } else { array = new NativeArray(length, allocator); } } else if (array.IsCreated) { array.Dispose(); } } } }