using GLTFast; using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using UnityEngine; public class SceneManagementGLTF : MonoBehaviour { /// /// Path to GLTF File (relative to streaming assets in editor, else persistentdatapath) /// public string _PathToGLTF; /// /// Validity in milliseconds for a subscription to the WA /// public int _ValiditySubscription = 100000; /// /// List of trackables and anchors in the AR Scene /// private Dictionary m_trackablesAndAnchorsInARScene; /// /// Unity Start Method /// protected async void Start() { m_trackablesAndAnchorsInARScene = new Dictionary(); await LoadGltfBinaryFromMemory(); Transform loaded = this.transform.GetChild(0); FindWorldStorageTransform(loaded); foreach(KeyValuePair toSubscribe in m_trackablesAndAnchorsInARScene) { int validity = _ValiditySubscription; Guid subscriptionUUID; // TODO : if only one : subscribeToPose, if multiple subscribetoPoses WorldAnalysisInterface.Instance.SubscribeToPose(null, toSubscribe.Key, ETSI.ARF.OpenAPI.WorldAnalysis.Mode_WorldAnalysis.DEVICE_TO_TRACKABLES, PoseCallback, ref validity, out subscriptionUUID); //TODO : find a value for the token parameter. } } /// /// The callback function used in the susbscription method. It instantiate a prefab or update its pose based on the current situation. /// /// /// The pose to update in the SM public void PoseCallback(WorldAnalysisInterface.PoseEstimationResult result, ETSI.ARF.OpenAPI.WorldAnalysis.Pose pose) { if (pose.EstimationState != ETSI.ARF.OpenAPI.WorldAnalysis.PoseEstimationState.OK) { Debug.Log("State Not Ok for " + pose.Uuid + " "+ pose.EstimationState.ToString() + " " + pose.InstructionInfo); return; } if (pose.Value.Type == ETSI.ARF.OpenAPI.WorldAnalysis.PoseValueType.VECTOR_QUATERNION) { ETSI.ARF.OpenAPI.WorldAnalysis.VectorQuaternionPoseValue value = (ETSI.ARF.OpenAPI.WorldAnalysis.VectorQuaternionPoseValue)pose.Value; if (m_trackablesAndAnchorsInARScene.ContainsKey(pose.Uuid)) { m_trackablesAndAnchorsInARScene[pose.Uuid].transform.position = WorldAnalysisUnityHelper.ConvertETSIVector3ToUnity(value.Position); m_trackablesAndAnchorsInARScene[pose.Uuid].transform.rotation = WorldAnalysisUnityHelper.ConvertETSIARFQuaternionToUnity(value.Rotation); } else { Debug.LogWarning("Callback for unwanted uuid"); } } else { Debug.LogWarning("Pose value type not supported yet :" +pose.Value.Type); // Todo : manage other types } } /// /// Load a GLTF from local memory according to _PathToGLTF /// /// ascync method protected async Task LoadGltfBinaryFromMemory() { #if UNITY_EDITOR string prefix = Application.streamingAssetsPath; #else string prefix = Application.persistentDataPath; #endif var filePath = prefix + "/" + _PathToGLTF; Debug.Log("PATH : " + filePath); byte[] data = File.ReadAllBytes(filePath); Debug.Log("File Size " + data.Length); var gltf = new GltfImport(); bool success = await gltf.LoadGltfBinary( data, // The URI of the original data is important for resolving relative URIs within the glTF new Uri(filePath) ); GameObjectInstantiator instantiator = new GameObjectInstantiator(gltf, this.transform); if (success) { success = await gltf.InstantiateMainSceneAsync(instantiator); } } /// /// In the loaded GLTF File : find all World Storage Trackables and Anchors /// /// Loaded GLTF Transforms protected void FindWorldStorageTransform(Transform trGLTF) { if (trGLTF.name.StartsWith("ws:")) { string id = trGLTF.name.Substring(3); Debug.Log("Add " + id + " " + trGLTF.name); m_trackablesAndAnchorsInARScene.Add(new Guid(id), trGLTF); } foreach(Transform child in trGLTF) { FindWorldStorageTransform(child); } } }