using System.Collections.Generic; using Unity.Collections; using UnityEngine.XR.ARSubsystems; namespace UnityEngine.XR.ARFoundation { /// /// Generates a mesh for an . /// /// /// If this GameObject has a MeshFilter and/or MeshCollider, /// this component will generate a mesh from the underlying XRFace. /// [RequireComponent(typeof(ARFace))] [HelpURL(typeof(ARFaceMeshVisualizer))] public sealed class ARFaceMeshVisualizer : MonoBehaviour { /// /// Get the Mesh that this visualizer creates and manages. /// public Mesh mesh { get; private set; } void SetVisible(bool visible) { m_MeshRenderer = GetComponent(); if (m_MeshRenderer == null) { return; } //if it is getting visible after being invisible for a while, set its topology if (visible && !m_MeshRenderer.enabled) { SetMeshTopology(); } m_MeshRenderer.enabled = visible; } void SetMeshTopology() { if (mesh == null) { return; } using (new ScopedProfiler("SetMeshTopology")) { using (new ScopedProfiler("ClearMesh")) mesh.Clear(); if (m_Face.vertices.Length > 0 && m_Face.indices.Length > 0) { using (new ScopedProfiler("SetVertices")) mesh.SetVertices(m_Face.vertices); using (new ScopedProfiler("SetIndices")) mesh.SetIndices(m_Face.indices, MeshTopology.Triangles, 0, false); using (new ScopedProfiler("RecalculateBounds")) mesh.RecalculateBounds(); if (m_Face.normals.Length == m_Face.vertices.Length) { using (new ScopedProfiler("SetNormals")) mesh.SetNormals(m_Face.normals); } else { using (new ScopedProfiler("RecalculateNormals")) mesh.RecalculateNormals(); } } if (m_Face.uvs.Length > 0) { using (new ScopedProfiler("SetUVs")) mesh.SetUVs(0, m_Face.uvs); } var meshFilter = GetComponent(); if (meshFilter != null) { meshFilter.sharedMesh = mesh; } var meshCollider = GetComponent(); if (meshCollider != null) { meshCollider.sharedMesh = mesh; } m_TopologyUpdatedThisFrame = true; } } void UpdateVisibility() { var visible = enabled && (m_Face.trackingState != TrackingState.None) && (ARSession.state > ARSessionState.Ready); SetVisible(visible); } void OnUpdated(ARFaceUpdatedEventArgs eventArgs) { UpdateVisibility(); if (!m_TopologyUpdatedThisFrame) { SetMeshTopology(); } m_TopologyUpdatedThisFrame = false; } void OnSessionStateChanged(ARSessionStateChangedEventArgs eventArgs) { UpdateVisibility(); } void Awake() { mesh = new Mesh(); m_MeshRenderer = GetComponent(); m_Face = GetComponent(); } void OnEnable() { m_Face.updated += OnUpdated; ARSession.stateChanged += OnSessionStateChanged; UpdateVisibility(); } void OnDisable() { m_Face.updated -= OnUpdated; ARSession.stateChanged -= OnSessionStateChanged; } ARFace m_Face; MeshRenderer m_MeshRenderer; bool m_TopologyUpdatedThisFrame; } }