Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • arf/world-analysis-api-helpers/unity-world-analysis-arfoundation-wrapper-package
1 result
Show changes
Commits on Source (3)
Showing
with 827 additions and 38 deletions
......@@ -36,11 +36,14 @@ ARKit can track meshes that are defined in the .arobject format. Such an object
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.
To support adding .arobject without recompiling the full application, we use a dedicated AssetBundle (named "arfmeshes"). To do so:
To support adding .arobject without recompiling the full application, we use a dedicated AssetBundle.
* Place you .arobject in the Assets Folder. For instance under Assets/ARObjects
* Associate the ARKitReferenceObjectEntry with the arfmeshes AssetBundle in the editor
* Build the AssetBundles. For that you can use the following menu: ARF--> Build AssetBundles iOS
* Pace the "arfmeshes" file in the Unity persistent data path of the application on the user device.
Then you have two options:
* Placing the AssetBundle "arfmeshes" file (with this exact file name) 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 AssetBundle to the Unity persistent data path on the user device. Only one AssetBundle can be loaded.
The name of the Trackable in the World Storage must correspond to the name of the ARKitReferenceObjectEntry.
......
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4ae147bac9ff8453284f59548528c2aa, type: 3}
m_Name: ARCoreExtensionsConfig
m_EditorClassIdentifier:
CloudAnchorMode: 1
SemanticMode: 0
GeospatialMode: 0
StreetscapeGeometryMode: 0
fileFormatVersion: 2
guid: cf9adc83079e8e1479b1a105856aab0e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &6911754431728604848
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6911754431728604849}
m_Layer: 0
m_Name: ARFAnchorTrackingPrefab
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &6911754431728604849
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6911754431728604848}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6911754432812775763}
- {fileID: 6911754433267149346}
- {fileID: 6911754433204531549}
- {fileID: 5348077246929615354}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &6911754432812775762
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6911754432812775763}
- component: {fileID: 6911754432812775758}
- component: {fileID: 6911754432812775757}
- component: {fileID: 6911754432812775756}
m_Layer: 0
m_Name: Z
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &6911754432812775763
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6911754432812775762}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0.0701}
m_LocalScale: {x: 0.01, y: 0.01, z: 0.11557999}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 6911754431728604849}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &6911754432812775758
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6911754432812775762}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &6911754432812775757
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6911754432812775762}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 9fd9c0bd2f4f1438888297d0668f871b, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!65 &6911754432812775756
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6911754432812775762}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!1 &6911754433204531548
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6911754433204531549}
- component: {fileID: 6911754433204531544}
- component: {fileID: 6911754433204531551}
- component: {fileID: 6911754433204531550}
m_Layer: 0
m_Name: Y
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &6911754433204531549
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6911754433204531548}
serializedVersion: 2
m_LocalRotation: {x: -0.5, y: -0.5, z: -0.5, w: 0.5}
m_LocalPosition: {x: 0, y: 0.0525, z: 0.0033}
m_LocalScale: {x: 0.0100000035, y: 0.01, z: 0.11558006}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 6911754431728604849}
m_LocalEulerAnglesHint: {x: -90, y: -90.00001, z: 0}
--- !u!33 &6911754433204531544
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6911754433204531548}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &6911754433204531551
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6911754433204531548}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: de76e3ad692ba4492aaca3dd54e65f04, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!65 &6911754433204531550
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6911754433204531548}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!1 &6911754433267149345
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6911754433267149346}
- component: {fileID: 6911754433267149341}
- component: {fileID: 6911754433267149340}
- component: {fileID: 6911754433267149347}
m_Layer: 0
m_Name: X
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &6911754433267149346
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6911754433267149345}
serializedVersion: 2
m_LocalRotation: {x: 0, y: -0.7071068, z: 0, w: 0.7071068}
m_LocalPosition: {x: 0.0528, y: 0, z: 0.0033}
m_LocalScale: {x: 0.01, y: 0.01, z: 0.11558}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 6911754431728604849}
m_LocalEulerAnglesHint: {x: 0, y: -90, z: 0}
--- !u!33 &6911754433267149341
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6911754433267149345}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &6911754433267149340
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6911754433267149345}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 9d815ae4d5a7b46ae99e4e5ed084d3a8, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!65 &6911754433267149347
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6911754433267149345}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!1 &7290371484074973697
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5348077246929615354}
- component: {fileID: 3993039649644943769}
- component: {fileID: 5219444789236537599}
m_Layer: 0
m_Name: Cylinder
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5348077246929615354
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7290371484074973697}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.025, y: 0.025, z: 0.025}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 6911754431728604849}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &3993039649644943769
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7290371484074973697}
m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &5219444789236537599
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7290371484074973697}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
fileFormatVersion: 2
guid: e5177a22bf3f76943a9c36a96126aaf5
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
......@@ -69,6 +69,7 @@ public class WorldAnalysisARFoundation : MonoBehaviour, WorldAnalysisInterface
protected void Awake()
{
Instance = this;
this.gameObject.AddComponent<WorldAnalysisARFoundationCoroutineHelper>();
m_relocalizationInformations = new Dictionary<Guid, ETSI.ARF.OpenAPI.WorldStorage.RelocalizationInformation>();
m_computedPoses = new Dictionary<Guid, ETSI.ARF.OpenAPI.WorldAnalysis.Pose>();
m_subscriptionsPoses = new Dictionary<Guid, SubscriptionInfo>();
......@@ -76,10 +77,16 @@ public class WorldAnalysisARFoundation : MonoBehaviour, WorldAnalysisInterface
m_trackableModules = new List<WorldAnalysisARFoundationModule>();
WorldAnalysisARFoundationModuleImage imageModule = new WorldAnalysisARFoundationModuleImage();
m_trackableModules.Add(imageModule);
#if UNITY_IOS
#if UNITY_IOS
WorldAnalysisARFoundationModuleMesh meshModule = new WorldAnalysisARFoundationModuleMesh();
m_trackableModules.Add(meshModule);
#endif
#endif
#if UNITY_ANDROID
// todo add script define symbol for using arcore extensions
WorldAnalysisARFoundationModuleARCoreAnchor arCoreAnchorModule = new WorldAnalysisARFoundationModuleARCoreAnchor();
m_trackableModules.Add(arCoreAnchorModule);
#endif
foreach(WorldAnalysisARFoundationModule module in m_trackableModules)
{
module.Initialize();
......
using System.Collections;
using UnityEngine;
public class WorldAnalysisARFoundationCoroutineHelper : MonoBehaviour
{
//Singleton
public static WorldAnalysisARFoundationCoroutineHelper Instance { get; private set; }
private void Awake()
{
// If there is an instance, and it's not me, delete myself.
Debug.Log("HERE SINGLETON AWAKE");
if (Instance != null && Instance != this)
{
Destroy(this);
}
else
{
Instance = this;
}
}
public void StartACoroutine(IEnumerator coroutine)
{
Debug.Log("HERE SINGLETON");
StartCoroutine(coroutine);
}
}
fileFormatVersion: 2
guid: bba8c444e6fa865469446e417be28e45
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
......@@ -18,13 +18,14 @@ public class WorldAnalysisARFoundationHelper
string fileName = "";
#if UNITY_EDITOR
string folder = Application.streamingAssetsPath;
#else
#else
string folder = Application.persistentDataPath;
#endif
#endif
string uniqueFileName = "/Temp"+ System.Guid.NewGuid()+".data";
using (var client = new WebClient())
{
await client.DownloadFileTaskAsync(toLoad, folder + "/Temp.data");
await client.DownloadFileTaskAsync(toLoad, folder + uniqueFileName);
string header_contentDisposition = client.ResponseHeaders["content-disposition"];
if (header_contentDisposition == null)
{
......@@ -40,7 +41,7 @@ public class WorldAnalysisARFoundationHelper
{
File.Delete(filePath);
}
File.Move(folder + "/Temp.data", filePath);
File.Move(folder + uniqueFileName, filePath);
}
return new KeyValuePair<string, string>(filePath , fileName);
}
......
#if UNITY_ANDROID
using System;
using System.Collections;
using System.Collections.Generic;
using Google.XR.ARCoreExtensions;
using Unity.XR.CoreUtils;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using static WorldAnalysisARFoundationModule;
public class WorldAnalysisARFoundationModuleARCoreAnchor : WorldAnalysisARFoundationModule
{
/// <summary>
///
/// </summary>
private ARAnchorManager m_anchorManager;
/// <summary>
/// IDs of all the cloud anchors that have been resolved
/// </summary>
private List<string> m_cloudAnchorAdded;//useful ?
/// <summary>
/// List of cloud anchors with tracking infos
/// </summary>
private Dictionary<string, TrackableInfo> m_trackedCloudAnchors = new Dictionary<string, TrackableInfo>();
/// <summary>
///
/// </summary>
private List<ResolveCloudAnchorPromise> _resolvePromises = new List<ResolveCloudAnchorPromise>();
/// <summary>
///
/// </summary>
private List<ResolveCloudAnchorResult> _resolveResults = new List<ResolveCloudAnchorResult>();
/// <summary>
/// Correspondance between google cloud id and local trackable id
/// </summary>
private Dictionary<string, string> m_localIdToCloudId = new Dictionary<string, string>();
/// <summary>
/// ETSI ID
/// </summary>
private Dictionary<string, string> m_CloudIdToETSIId = new Dictionary<string, string>();
/// <summary>
///
/// </summary>
private GameObject m_anchorPrefab;
/// <summary>
/// Initialize ARCore cloud anchors tracking module
/// </summary>
public void Initialize()
{
XROrigin origin = UnityEngine.Object.FindAnyObjectByType<XROrigin>();
m_anchorManager = origin.gameObject.AddComponent<ARAnchorManager>();
m_cloudAnchorAdded = new List<string>();
m_anchorPrefab = (GameObject)Resources.Load("ARFAnchorTrackingPrefab");
m_anchorManager.anchorPrefab = m_anchorPrefab;
m_anchorManager.anchorsChanged += OnTrackedCloudAnchorChanged;
}
/// <summary>
///
/// </summary>
/// <param name="uuid"></param>
/// <returns></returns>
public TrackableInfo GetPoseTrackable(Guid uuid)
{
if (m_trackedCloudAnchors.ContainsKey(uuid.ToString()))
{
return m_trackedCloudAnchors[uuid.ToString()];
}
else
{
return null;
}
}
/// <summary>
///
/// </summary>
/// <param name="trackable"></param>
/// <returns></returns>
public bool AddTrackable(ETSI.ARF.OpenAPI.WorldStorage.Trackable trackable)
{
/// Here : we don't check if the trackable is allready added, AddImageToLibrary does it
if (trackable.TrackableType != ETSI.ARF.OpenAPI.WorldStorage.TrackableType.MAP)
{
return false;
}
AddNewARCoreCloudAnchor(trackable);
return true;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public ETSI.ARF.OpenAPI.WorldAnalysis.Capability GetSupportedCapability()
{
ETSI.ARF.OpenAPI.WorldAnalysis.Capability capabilityARCoreAnchor = new ETSI.ARF.OpenAPI.WorldAnalysis.Capability();
capabilityARCoreAnchor.TrackableType = ETSI.ARF.OpenAPI.WorldAnalysis.TrackableType.MAP;
ETSI.ARF.OpenAPI.WorldAnalysis.EncodingInformationStructure encodingInformation = new ETSI.ARF.OpenAPI.WorldAnalysis.EncodingInformationStructure();
encodingInformation.DataFormat = ETSI.ARF.OpenAPI.WorldAnalysis.EncodingInformationStructureDataFormat.ARCORE;
encodingInformation.Version = "1.01";
capabilityARCoreAnchor.EncodingInformation = encodingInformation;
capabilityARCoreAnchor.Framerate = 30; // Not particularly specified on ARKit and ARCore
capabilityARCoreAnchor.Latency = 0; // Not particularly specified on ARKit and ARCore
capabilityARCoreAnchor.Accuracy = 1; // Not particularly specified on ARKit and ARCore
return capabilityARCoreAnchor;
}
/// <summary>
///
/// </summary>
/// <param name="eventArgs"></param>
private void OnTrackedCloudAnchorChanged(ARAnchorsChangedEventArgs eventArgs)
{
foreach (var trackedCloudAnchor in eventArgs.updated)
{
Vector3 position = trackedCloudAnchor.transform.position;
Quaternion rotation = trackedCloudAnchor.transform.rotation;
TrackableInfo info = new TrackableInfo();
info.name = trackedCloudAnchor.name;
string localId = trackedCloudAnchor.trackableId.subId1.ToString("X16");// there must be a better way : does it work every time?
if (m_localIdToCloudId.ContainsKey(localId))
{
info.name = m_CloudIdToETSIId[m_localIdToCloudId[localId]];
}
else
{
Debug.Log("ARCore Cloud Anchor No correspondance for Local Anchor " + localId);
continue;
}
if (trackedCloudAnchor.trackingState == TrackingState.Tracking)
{
info.state = ETSI.ARF.OpenAPI.WorldAnalysis.PoseEstimationState.OK;
info.confidence = 100;
}
else if (trackedCloudAnchor.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.IMAGE_MARKER;
m_trackedCloudAnchors[info.name] = info;
}
}
/// <summary>
///
/// </summary>
/// <param name="trackable"></param>
private async void AddNewARCoreCloudAnchor(ETSI.ARF.OpenAPI.WorldStorage.Trackable trackable )
{
while (ARSession.state == ARSessionState.CheckingAvailability || ARSession.state == ARSessionState.None ||ARSession.state == ARSessionState.SessionInitializing)
{
await System.Threading.Tasks.Task.Delay(100);
}
string googleCloudID = trackable.Name;
m_CloudIdToETSIId.Add(googleCloudID, trackable.UUID.ToString());
ResolveCloudAnchor(googleCloudID);
}
/// <summary>
/// Resolves Cloud Anchors using a given id
/// </summary>
/// <param name="cloudId"></param>
public void ResolveCloudAnchor(string cloudId)
{
var promise = m_anchorManager.ResolveCloudAnchorAsync(cloudId);
if (promise.State == PromiseState.Done)
{
Debug.LogFormat("Failed to resolve Cloud Anchor " + cloudId);
}
else
{
_resolvePromises.Add(promise);
var coroutine = ResolveAnchor(promise, cloudId);
WorldAnalysisARFoundationCoroutineHelper.Instance.StartACoroutine(coroutine);
}
}
/// <summary>
///
/// </summary>
/// <param name="promise"></param>
/// <returns></returns>
private IEnumerator ResolveAnchor(ResolveCloudAnchorPromise promise, string cloudId)
{
yield return promise;
var result = promise.Result;
_resolvePromises.Remove(promise);
_resolveResults.Add(result);
if (result.CloudAnchorState == CloudAnchorState.Success)
{
Debug.Log("ARCloud Anchor Resolve Sucess" +cloudId);
m_localIdToCloudId.Add(result.Anchor.trackableId.subId2.ToString("X16"), cloudId); // should be a better way: not sure about that but subId2 of the ARCloudAnchor seems to correspond to subId1 of local anchor that is updated by Anchor Manager
}
else
{
Debug.Log("ARCloud Anchor Resolve Failed" + result.CloudAnchorState + " " +cloudId);
}
}
}
#endif
\ No newline at end of file
fileFormatVersion: 2
guid: 2cec98c043216c94db7d09c20b3cce67
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
......@@ -17,7 +17,11 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod
/// <summary>
/// Name of all images that have been added to the library
/// </summary>
private List<string> m_trackedImageInLibrary;
private List<string> m_trackedImageInLibrary;
/// <summary>
/// All url of images that have allready been downloaded
/// </summary>
private List<string> m_allDownloadedImages;
/// <summary>
/// List of tracked images with tracking infos
/// </summary>
......@@ -35,6 +39,7 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod
XROrigin origin = UnityEngine.Object.FindAnyObjectByType<XROrigin>();
m_trackedImageManager = origin.gameObject.AddComponent<ARTrackedImageManager>();
m_trackedImageInLibrary = new List<string>();
m_allDownloadedImages = new List<string>();
m_trackedImageManager.trackedImagePrefab = (GameObject)Resources.Load("ARFImageTrackingPrefab");
m_trackedImageManager.trackedImagesChanged += OnTrackedImagesChanged;
}
......@@ -172,8 +177,12 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod
if (!found)
{
// Here we don't check if url exists and still return true: could be improve
LoadTextureFromURL(url, fileName, imageWidthInMeters);
// Do not download the same image twice
if (!m_allDownloadedImages.Contains(url))
{
// Here we don't check if url exists and still return true: could be improve
LoadTextureFromURL(url, fileName, imageWidthInMeters);
}
}
else
{
......@@ -206,6 +215,7 @@ public class WorldAnalysisARFoundationModuleImage : WorldAnalysisARFoundationMod
public 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);
}
......
......@@ -17,7 +17,11 @@ public class WorldAnalysisARFoundationModuleMesh : WorldAnalysisARFoundationModu
/// <summary>
/// Name of all meshes that have been added to the library
/// </summary>
private List<string> m_trackedMeshesInLibrary;
private List<string> m_trackedMeshesInLibrary;
/// <summary>
/// Has downloaded asset bundle from an url
/// </summary>
private bool m_hasDownloadedBundle;
/// <summary>
/// List of tracked meshses with tracking infos
/// </summary>
......@@ -45,17 +49,7 @@ public class WorldAnalysisARFoundationModuleMesh : WorldAnalysisARFoundationModu
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>() ;
}
m_hasDownloadedBundle = false;
}
/// <summary>
......@@ -87,7 +81,20 @@ public class WorldAnalysisARFoundationModuleMesh : WorldAnalysisARFoundationModu
{
return false;
}
bool resul = AddMeshToLibrary(trackable.Name) ;// (float)trackable.TrackableSize[0]);
// Check if an AssetBundle url is provided
string url = "";
if (trackable.KeyvalueTags.ContainsKey("url"))
{
foreach (string s in trackable.KeyvalueTags["url"])
{
// first one
url = s;
break;
}
}
bool resul = AddMeshToLibrary(trackable.Name , url) ;// (float)trackable.TrackableSize[0]);
if (resul)
{
m_uuidToName[trackable.UUID] = trackable.Name;
......@@ -96,7 +103,7 @@ public class WorldAnalysisARFoundationModuleMesh : WorldAnalysisARFoundationModu
}
/// <summary>
/// Initialize capability object with image tracking
/// Initialize capability object with Mesh tracking
/// </summary>
public ETSI.ARF.OpenAPI.WorldAnalysis.Capability GetSupportedCapability()
{
......@@ -153,7 +160,7 @@ public class WorldAnalysisARFoundationModuleMesh : WorldAnalysisARFoundationModu
/// </summary>
/// <param name="fileName">file name</param>
/// <returns></returns>
protected bool AddMeshToLibrary(string fileName)
protected bool AddMeshToLibrary(string fileName, string url)
{
// check if mesh is in the library
if (m_trackedMeshesInLibrary.Contains(fileName))
......@@ -164,8 +171,29 @@ public class WorldAnalysisARFoundationModuleMesh : WorldAnalysisARFoundationModu
if (m_entries == null)
{
Debug.LogWarning("Try to Track Mesh but ARF Bundle with meshes is null");
return false ;
#if UNITY_EDITOR
string bundlePath = Application.streamingAssetsPath + "/arfmeshes";
#else
string bundlePath = Application.persistentDataPath + "/arfmeshes" ;
#endif
if (url.Length > 0 && !m_hasDownloadedBundle)
{
KeyValuePair<string, string> download = System.Threading.Tasks.Task.Run(() => WorldAnalysisARFoundationHelper.DownloadFileHTTP(url)).Result; // synchronous : not perfect at all prevent to add another mesh while bundle is downloading
bundlePath = download.Key;
m_hasDownloadedBundle = true;
}
if (System.IO.File.Exists(bundlePath))
{
AssetBundle bu = AssetBundle.LoadFromFile(bundlePath);
m_entries = bu.LoadAllAssets<XRReferenceObjectEntry>();
}
else
{
return false;
}
}
XRReferenceObjectEntry toAdd = null ;
......
......@@ -6,7 +6,8 @@
"GUID:065e856e9f9becb49abdf0cb6855a039",
"GUID:a9420e37d7990b54abdef6688edbe313",
"GUID:92703082f92b41ba80f0d6912de66115",
"GUID:dc960734dc080426fa6612f1c5fe95f3"
"GUID:dc960734dc080426fa6612f1c5fe95f3",
"GUID:b35d8248e1a04478bb2d70fe76652ddf"
],
"includePlatforms": [],
"excludePlatforms": [],
......
......@@ -2,16 +2,15 @@
"author": "ETSI-ISG-ARF",
"name": "etsi.isg.arf.worldanalysisarfoundation",
"version": "0.0.1",
"displayName": "ISG-ARF World Analysis ARFoundation Wrapper Package ",
"displayName": "ISG-ARF World Analysis ARFoundation Wrapper Package",
"description": "ARFoundation wrapper for the World Analysis of the Augmented Reality Framework",
"unity": "2021.3",
"dependencies": {
"etsi.isg.arf.worldstorage" : "0.0.2",
"etsi.isg.arf.worldanalysis" : "0.0.1",
"com.unity.xr.arfoundation": "5.1.3",
"com.unity.xr.arkit": "5.1.3",
"com.unity.xr.arcore": "5.1.3"
},
"etsi.isg.arf.worldstorage": "0.0.2",
"etsi.isg.arf.worldanalysis": "0.0.1",
"com.unity.xr.arfoundation": "5.1.3",
"com.unity.xr.arkit": "5.1.3",
"com.unity.xr.arcore": "5.1.3"
},
"keywords": []
}
\ No newline at end of file