diff --git a/README.md b/README.md index ae9dc0cce7839ad97243388b06bcdd4a3fda7ef9..497c9e525c8fabfda0f3785534c6ef79c23e1959 100644 --- a/README.md +++ b/README.md @@ -24,15 +24,15 @@ This wrapper for the World Analysis relies on the ARFoundation (version 5.1.x) U Image markers are supported on both iOS and Android platforms through ARKit and ARCore. -The name of the Trackable in the World Storage must correspond to the name of a file (jpg or png) placed in the Unity persistent data path of the application on the user device. +The name of the Trackable in the World Storage must correspond to the name of a file (jpg or png) placed in the Unity persistent data path of the application on the user device. The variable keyvalueTags of the Trackable can also contain a parameter with the "url" key providing a link to download the image. More information about ARFoundation Image Tracking can be found here: https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@5.1/manual/index.html ### Mesh Trackables ### -Mesh trackable are supported on iOS through ARKit. +Mesh trackables are supported on iOS through ARKit. -ARKit can track meshes that are defined in the .arobject format. Such an object can be scanned with the sample application provided here : https://developer.apple.com/documentation/arkit/arkit_in_ios/content_anchors/scanning_and_detecting_3d_objects +ARKit can track meshes that are defined in the .arobject format. Such an object can be scanned with the sample application provided here: https://developer.apple.com/documentation/arkit/arkit_in_ios/content_anchors/scanning_and_detecting_3d_objects Unity serializes .arobject into ARKitReferenceObjectEntry in the editor. ARKitReferenceObjectEntry cannot then be imported at runtime from a .arobjject file. Dynamic loading is not supported yet. diff --git a/Runtime/Scripts/WorldAnalysisARFoundationHelper.cs b/Runtime/Scripts/WorldAnalysisARFoundationHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..d1b128c8968c36f07d4fef375c65dfd18aaa0b0c --- /dev/null +++ b/Runtime/Scripts/WorldAnalysisARFoundationHelper.cs @@ -0,0 +1,47 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using System.Threading.Tasks; +using System.Net ; +using System.IO ; + +public class WorldAnalysisARFoundationHelper +{ + /// <summary> + /// Downaload file http + /// </summary> + /// <param name="toLoad">load url</param> + /// <returns>key and value with local path and file name with extension</returns> + public static async Task<KeyValuePair<string, string> > DownloadFileHTTP(string toLoad) + { + string filePath = ""; + string fileName = ""; + #if UNITY_EDITOR + string folder = Application.streamingAssetsPath; + #else + string folder = Application.persistentDataPath; + #endif + + using (var client = new WebClient()) + { + await client.DownloadFileTaskAsync(toLoad, folder + "/Temp.data"); + string header_contentDisposition = client.ResponseHeaders["content-disposition"]; + if (header_contentDisposition == null) + { + string[] splittedLink = toLoad.Split('/'); + fileName = splittedLink[splittedLink.Length - 1]; + } + else + { + fileName = new System.Net.Mime.ContentDisposition(header_contentDisposition).FileName; + } + filePath = folder + "/" + fileName; + if (File.Exists(filePath)) + { + File.Delete(filePath); + } + File.Move(folder + "/Temp.data", filePath); + } + return new KeyValuePair<string, string>(filePath , fileName); + } +} diff --git a/Runtime/Scripts/WorldAnalysisARFoundationHelper.cs.meta b/Runtime/Scripts/WorldAnalysisARFoundationHelper.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..5602d29efe0f7fa6755a7982cc579fae4bc483a9 --- /dev/null +++ b/Runtime/Scripts/WorldAnalysisARFoundationHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a7db7bb6556864f8a99c9e7d104f85df +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/WorldAnalysisARFoundationModuleImage.cs b/Runtime/Scripts/WorldAnalysisARFoundationModuleImage.cs index 4908f8b409b3c041ef348cc11d451252d155a8ae..60c1865888da512bdcc7f9a3fc888c9ae90b03b6 100644 --- a/Runtime/Scripts/WorldAnalysisARFoundationModuleImage.cs +++ b/Runtime/Scripts/WorldAnalysisARFoundationModuleImage.cs @@ -68,7 +68,20 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod { return false; } - bool resul = AddImageToLibrary(trackable.Name, (float)trackable.TrackableSize[0]); + + // Check if an image url is provided + string url = "" ; + if (trackable.KeyvalueTags.ContainsKey("url")) + { + foreach(string s in trackable.KeyvalueTags["url"]) + { + // first one + url = s ; + break ; + } + } + + bool resul = AddImageToLibrary(trackable.Name, url, (float)trackable.TrackableSize[0]); if (resul) { m_uuidToName[trackable.UUID] = trackable.Name; @@ -133,9 +146,10 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod /// Add a new image to the arfoundation library /// </summary> /// <param name="fileName">file name</param> + /// </param name="url"> potential url</param> /// <param name="imageWidthInMeters">image width in meters</param> - /// <returns></returns> - protected bool AddImageToLibrary(string fileName, float imageWidthInMeters) + /// <returns>image found or not</returns> + protected bool AddImageToLibrary(string fileName, string url, float imageWidthInMeters) { // check if image is in the library if (m_trackedImageInLibrary.Contains(fileName)) @@ -150,18 +164,50 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod #endif bool found = CheckImageExist(ref imagePath); // try to find in jpg or png - if (!found) + if (!found && url.Length == 0) { Debug.LogWarning("Try to Track Image " + fileName + " but file not found"); return false; } - - //Load texture and add it to arfoundation library + + if (!found) + { + // Here we don't check if url exists and still return true: could be improve + LoadTextureFromURL(url, fileName, imageWidthInMeters); + } + else + { + //Load texture and add it to arfoundation library + LoadTextureFromMemory(imagePath, fileName, imageWidthInMeters); + } + return true; + } + + /// <summary> + /// Add a new image from local memory to the arfoundation library + /// </summary> + /// </param name="imagePath"> local image path</param> + /// <param name="fileName">file name</param> + /// <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); - return true; + } + + /// <summary> + /// Add a new image from a given url to the arfoundation library + /// </summary> + /// </param name="url"> url to the image to download</param> + /// <param name="fileName">file name</param> + /// <param name="imageWidthInMeters">image width in meters</param> + public async void LoadTextureFromURL(string url, string fileName, float imageWidthInMeters) + { + Debug.Log("Download image from url "+ url); + KeyValuePair<string , string> downloaded = await WorldAnalysisARFoundationHelper.DownloadFileHTTP(url); + LoadTextureFromMemory(downloaded.Key, fileName, imageWidthInMeters); } /// <summary>