diff --git a/Runtime/Scripts/WorldAnalysisARFoundationModuleImage.cs b/Runtime/Scripts/WorldAnalysisARFoundationModuleImage.cs index ab15c6e30490d90212a7ab2c4c703835ebfc7e5d..781de5cb2b5c81787e1368e69650ddf3acf6bcd5 100644 --- a/Runtime/Scripts/WorldAnalysisARFoundationModuleImage.cs +++ b/Runtime/Scripts/WorldAnalysisARFoundationModuleImage.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using UnityEngine; +using UnityEngine.Networking; using UnityEngine.XR.ARFoundation; using UnityEngine.XR.ARSubsystems; using System.IO; @@ -123,7 +124,11 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod Quaternion rotation = trackedImage.transform.rotation; TrackableInfo info = new TrackableInfo(); + #if UNITY_VISIONOS + info.name = GetImageNameWithoutUUID(trackedImage.referenceImage.name); + #else info.name = trackedImage.referenceImage.name; + #endif if (trackedImage.trackingState == TrackingState.Tracking) { info.state = ETSI.ARF.OpenAPI.WorldAnalysis.PoseEstimationState.OK; @@ -147,6 +152,47 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod } } + +#if UNITY_VISIONOS + + /// Loaded one time + private XRReferenceImageLibrary m_libaryVision ; + + protected bool AddImageToLibrary(string fileName, string url, float imageWidthInMeters) + { + // VISION OS/Polyspatial 1.X does not suppoort dynamically adding images, url is ignored as well as imageWidthInMeters that cannot be modified + // Include change in 2.X : https://discussions.unity.com/t/adding-tracking-ar-maker-images-at-runtime-support-for-vision-pro/345127 + if (m_trackedImageInLibrary.Contains(fileName)) + { + Debug.Log("Image allready added to library"); + return true; + } + + // Load Image Library from resources folder + if (m_trackedImageManager.referenceLibrary == null) + { + m_libaryVision = (XRReferenceImageLibrary) Resources.Load("VisionOSImageLibrary"); + m_trackedImageManager.referenceLibrary = m_libaryVision; + } + + if (m_libaryVision != null) + { + if (!m_trackedImageManager.enabled) m_trackedImageManager.enabled = true; // Necessary? + foreach(XRReferenceImage image in m_libaryVision) + { + if (image.name == fileName) + { + m_trackedImageInLibrary.Add(fileName); + return true ; + } + } + } + return false ; + } + + +#else + /// <summary> /// Add a new image to the arfoundation library /// </summary> @@ -171,7 +217,7 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod bool found = CheckImageExist(ref imagePath); // try to find in jpg or png if (!found && url.Length == 0) { - Debug.LogWarning("Try to Track Image " + fileName + " but file not found"); + Debug.LogWarning("Try to track image " + fileName + " but file was not found"); return false; } @@ -191,6 +237,7 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod } return true; } +#endif /// <summary> /// Add a new image from local memory to the arfoundation library @@ -200,10 +247,51 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod /// <param name="imageWidthInMeters">image width in meters</param> private void LoadTextureFromMemory(string imagePath, string fileName, float imageWidthInMeters) { - var rawData = File.ReadAllBytes(imagePath); - Texture2D tex = new Texture2D(2, 2); - tex.LoadImage(rawData); - AddTextureToLibrary(tex, fileName, imageWidthInMeters); + try + { + byte[] rawData; + if (imagePath.Contains("://")) + { + // Hack to make sync request + UnityWebRequest request = UnityWebRequest.Get(imagePath); + request.SendWebRequest(); + while (!request.isDone) + { + if (request.result != UnityWebRequest.Result.InProgress) + { + break; + } + } + + if (request.result != UnityWebRequest.Result.Success) + { + rawData = null; + } + else + { + rawData = request.downloadHandler.data; + } + } + else + { + rawData = File.ReadAllBytes(imagePath); + } + + if (rawData != null) + { + Texture2D tex = new Texture2D(2, 2); + tex.LoadImage(rawData); + AddTextureToLibrary(tex, fileName, imageWidthInMeters); + } + else + { + Debug.LogError($"Fail to read data from file {imagePath}"); + } + } + catch(Exception ex) + { + Debug.LogError($"Fail to read data from file {imagePath} ({ex})"); + } } /// <summary> @@ -214,10 +302,22 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod /// <param name="imageWidthInMeters">image width in meters</param> private async void LoadTextureFromURL(string url, string fileName, float imageWidthInMeters) { - Debug.Log("Download image from url "+ url); - m_allDownloadedImages.Add(url); - KeyValuePair<string , string> downloaded = await WorldAnalysisARFoundationHelper.DownloadFileHTTP(url); - LoadTextureFromMemory(downloaded.Key, fileName, imageWidthInMeters); + Uri uri = new Uri(url); + + if (uri.Scheme == "file" && uri.LocalPath.StartsWith("/%streamingassets%/")) + { + // Load image from streaming assets + string imagePath = Path.Combine(Application.streamingAssetsPath, uri.LocalPath.Replace("/%streamingassets%/", "")); + Debug.Log($"Try to load image from {imagePath}"); + LoadTextureFromMemory(imagePath, fileName, imageWidthInMeters); + } + else + { + Debug.Log("Download image from url "+ url); + m_allDownloadedImages.Add(url); + KeyValuePair<string , string> downloaded = await WorldAnalysisARFoundationHelper.DownloadFileHTTP(url); + LoadTextureFromMemory(downloaded.Key, fileName, imageWidthInMeters); + } } /// <summary> @@ -235,13 +335,14 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod IReferenceImageLibrary library; if (m_trackedImageManager.referenceLibrary == null) { - library = m_trackedImageManager.CreateRuntimeLibrary(); // Create library if it does not exist + library = m_trackedImageManager.CreateRuntimeLibrary(); // Create library if it does not exist } else { library = m_trackedImageManager.referenceLibrary; } + if (library is MutableRuntimeReferenceImageLibrary mutableLibrary) { if (!m_trackedImageInLibrary.Contains(imageName)) @@ -282,4 +383,21 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod } return false; } + +#if UNITY_VISIONOS + /// <summary> + /// With images libraries not created at runtime Tracked images reference names include an UUID after a "_", this function removes it + /// </summary> + /// <param input="input"></param> + /// <returns></returns> + private string GetImageNameWithoutUUID(string input) + { + int lastIndex= input.LastIndexOf('_'); + if (lastIndex !=-1) + { + return input.Substring(0, lastIndex); + } + return input ; + } + #endif } \ No newline at end of file