using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR.ARFoundation; using UnityEngine.XR.ARSubsystems; using System.IO; using Unity.XR.CoreUtils; using static WorldAnalysisARFoundationModule; using ETSI.ARF.OpenAPI.WorldStorage; public class WorldAnalysisARFoundationModuleMesh : WorldAnalysisARFoundationModule { /// <summary> /// ARFoundation Image tracking management /// </summary> private ARTrackedObjectManager m_trackedObjectManager; /// <summary> /// Name of all meshes that have been added to the library /// </summary> private List<string> m_trackedMeshesInLibrary; /// <summary> /// List of tracked meshses with tracking infos /// </summary> private Dictionary<string,TrackableInfo> m_trackedMeshes = new Dictionary<string,TrackableInfo>(); /// <summary> /// Link between trackable name and uuid /// </summary> private Dictionary<Guid, string> m_uuidToName = new Dictionary<Guid, string >(); /// <summary> /// Bundle with all the XRReferenceObjectEntry /// </summary> private XRReferenceObjectEntry [] m_entries ; /// <summary> /// Initialize image tracking module /// </summary> public void Initialize() { XROrigin origin = UnityEngine.Object.FindAnyObjectByType<XROrigin>(); m_trackedObjectManager = origin.gameObject.AddComponent<ARTrackedObjectManager>(); XRReferenceObjectLibrary library = (XRReferenceObjectLibrary) ScriptableObject.CreateInstance(typeof(XRReferenceObjectLibrary)); m_trackedObjectManager.referenceLibrary = library ; m_trackedMeshesInLibrary = new List<string>(); m_trackedObjectManager.trackedObjectPrefab = (GameObject)Resources.Load("ARFMeshTrackingPrefab"); m_trackedObjectManager.trackedObjectsChanged += OnTrackedMeshesChanged; m_trackedObjectManager.enabled = true ; // when instantiated without library : it is disabled m_entries = null; #if UNITY_EDITOR string bundlePath = Application.streamingAssetsPath + "/arfmeshes" ; #else string bundlePath = Application.persistentDataPath + "/arfmeshes" ; #endif if (System.IO.File.Exists(bundlePath)) { AssetBundle bu = AssetBundle.LoadFromFile(bundlePath); m_entries = bu.LoadAllAssets<XRReferenceObjectEntry>() ; } } /// <summary> /// found /// </summary> /// <param name="uuid">name of the mesh trackable</param> public TrackableInfo GetPoseTrackable(Guid uuid) { if (m_uuidToName.ContainsKey(uuid)) { string name = m_uuidToName[uuid]; if (m_trackedMeshes.ContainsKey(name)) { return m_trackedMeshes[name]; } } return null; } /// <summary> /// Add a trackable : need to be an image /// </summary> /// <param name="trackable">Image trackable</param> /// <returns>Supported or not</returns> public bool AddTrackable(Trackable trackable) { /// Here : we don't check if the trackable is allready added, AddMeshToLibrary does it if (trackable.TrackableType != ETSI.ARF.OpenAPI.WorldStorage.TrackableType.MESH) { return false; } bool resul = AddMeshToLibrary(trackable.Name) ;// (float)trackable.TrackableSize[0]); if (resul) { m_uuidToName[trackable.UUID] = trackable.Name; } return true; } /// <summary> /// Initialize capability object with image tracking /// </summary> public ETSI.ARF.OpenAPI.WorldAnalysis.Capability GetSupportedCapability() { ETSI.ARF.OpenAPI.WorldAnalysis.Capability capabilityMesh = new ETSI.ARF.OpenAPI.WorldAnalysis.Capability(); capabilityMesh.TrackableType = ETSI.ARF.OpenAPI.WorldAnalysis.TrackableType.MESH; ETSI.ARF.OpenAPI.WorldAnalysis.EncodingInformationStructure encodingInformation = new ETSI.ARF.OpenAPI.WorldAnalysis.EncodingInformationStructure(); encodingInformation.DataFormat = ETSI.ARF.OpenAPI.WorldAnalysis.EncodingInformationStructureDataFormat.ARKIT; encodingInformation.Version = "1.01"; capabilityMesh.EncodingInformation = encodingInformation; capabilityMesh.Framerate = 30; // Not particularly specified on ARKit capabilityMesh.Latency = 0; // Not particularly specified on ARKit capabilityMesh.Accuracy = 1; // Not particularly specified on ARKit return capabilityMesh ; } /// <summary> /// Event manager for when a mesh is tracked /// </summary> /// <param name="eventArgs">the event</param> private void OnTrackedMeshesChanged(ARTrackedObjectsChangedEventArgs eventArgs) { foreach (var trackedMesh in eventArgs.updated) { Vector3 position = trackedMesh.transform.position; Quaternion rotation = trackedMesh.transform.rotation; TrackableInfo info = new TrackableInfo(); info.name = trackedMesh.referenceObject.name; if (trackedMesh.trackingState == TrackingState.Tracking) { info.state = ETSI.ARF.OpenAPI.WorldAnalysis.PoseEstimationState.OK; info.confidence = 100; } else if (trackedMesh.trackingState == TrackingState.Limited) { info.state = ETSI.ARF.OpenAPI.WorldAnalysis.PoseEstimationState.OK; info.confidence = 50; } else { info.state = ETSI.ARF.OpenAPI.WorldAnalysis.PoseEstimationState.FAILURE; //ADD NOT_TRACKED ? info.confidence = 0; } info.timeStamp = unchecked((int)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()); info.position = position; info.rotation = rotation; info.trackableType = ETSI.ARF.OpenAPI.WorldAnalysis.TrackableType.MESH; m_trackedMeshes[info.name] = info; } } /// <summary> /// Add a new mesh to the arfoundation library /// </summary> /// <param name="fileName">file name</param> /// <returns></returns> protected bool AddMeshToLibrary(string fileName) { // check if mesh is in the library if (m_trackedMeshesInLibrary.Contains(fileName)) { Debug.Log("Mesh allready added to library"); return true; } if (m_entries == null) { Debug.LogWarning("Try to Track Mesh but ARF Bundle with meshes is null"); return false ; } XRReferenceObjectEntry toAdd = null ; foreach(XRReferenceObjectEntry entry in m_entries) { if (entry.name == fileName) { toAdd = entry ; } } if (toAdd == null) { Debug.LogWarning("Try to Track Mesh " + fileName + " but XRReferenceObjectEntry not found in bundle"); return false; } AddARObjectEntryToLibrary(toAdd , fileName); return true; } /// <summary> /// Add a Mesh /// </summary> private async void AddARObjectEntryToLibrary(XRReferenceObjectEntry arobject , string objectName) { while (ARSession.state == ARSessionState.CheckingAvailability || ARSession.state == ARSessionState.None) { await System.Threading.Tasks.Task.Delay(100); } XRReferenceObject referenceObject = new XRReferenceObject(objectName); referenceObject.AddEntry(arobject); m_trackedObjectManager.referenceLibrary.Add(referenceObject); if (!m_trackedObjectManager.enabled) m_trackedObjectManager.enabled = true; // necessary because when object manger is instantiated without library it is disabled } }