diff --git a/Runtime/ARCoreExtensionsConfig.asset b/Runtime/ARCoreExtensionsConfig.asset new file mode 100644 index 0000000000000000000000000000000000000000..858be38bde9e1d397ff68c1504fe6899484cb0d2 --- /dev/null +++ b/Runtime/ARCoreExtensionsConfig.asset @@ -0,0 +1,18 @@ +%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 diff --git a/Runtime/ARCoreExtensionsConfig.asset.meta b/Runtime/ARCoreExtensionsConfig.asset.meta new file mode 100644 index 0000000000000000000000000000000000000000..69fdd4044d5158662769fef5b46d80037ea95cc1 --- /dev/null +++ b/Runtime/ARCoreExtensionsConfig.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cf9adc83079e8e1479b1a105856aab0e +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Resources/ARFAnchorTrackingPrefab.prefab b/Runtime/Resources/ARFAnchorTrackingPrefab.prefab new file mode 100644 index 0000000000000000000000000000000000000000..4b74c4b590933d962eb6e8d72cf7a5a7b84f5fd4 --- /dev/null +++ b/Runtime/Resources/ARFAnchorTrackingPrefab.prefab @@ -0,0 +1,435 @@ +%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} diff --git a/Runtime/Resources/ARFAnchorTrackingPrefab.prefab.meta b/Runtime/Resources/ARFAnchorTrackingPrefab.prefab.meta new file mode 100644 index 0000000000000000000000000000000000000000..b7050cb5a0d346c6b9324dc6b66d30473ecf728a --- /dev/null +++ b/Runtime/Resources/ARFAnchorTrackingPrefab.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e5177a22bf3f76943a9c36a96126aaf5 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/WorldAnalysisARFoundation.cs b/Runtime/Scripts/WorldAnalysisARFoundation.cs index bd82b85fc9caf3da00099d0a4ead5456560a54a1..671265f8bf35af04fa16a9854295ecfc755526f6 100644 --- a/Runtime/Scripts/WorldAnalysisARFoundation.cs +++ b/Runtime/Scripts/WorldAnalysisARFoundation.cs @@ -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(); diff --git a/Runtime/Scripts/WorldAnalysisARFoundationCoroutineHelper.cs b/Runtime/Scripts/WorldAnalysisARFoundationCoroutineHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..2aebd0785095b226a7c730b44282c2380cd9a4af --- /dev/null +++ b/Runtime/Scripts/WorldAnalysisARFoundationCoroutineHelper.cs @@ -0,0 +1,31 @@ +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); + } +} diff --git a/Runtime/Scripts/WorldAnalysisARFoundationCoroutineHelper.cs.meta b/Runtime/Scripts/WorldAnalysisARFoundationCoroutineHelper.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..9d9455dc23e9f6e0534f1b5006fcda57d18846e1 --- /dev/null +++ b/Runtime/Scripts/WorldAnalysisARFoundationCoroutineHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bba8c444e6fa865469446e417be28e45 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Scripts/WorldAnalysisARFoundationModuleARCoreAnchor.cs b/Runtime/Scripts/WorldAnalysisARFoundationModuleARCoreAnchor.cs new file mode 100644 index 0000000000000000000000000000000000000000..4ef7bc9e982336e803e099d781a2ce1497850a12 --- /dev/null +++ b/Runtime/Scripts/WorldAnalysisARFoundationModuleARCoreAnchor.cs @@ -0,0 +1,219 @@ +#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 diff --git a/Runtime/Scripts/WorldAnalysisARFoundationModuleARCoreAnchor.cs.meta b/Runtime/Scripts/WorldAnalysisARFoundationModuleARCoreAnchor.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..9e979e937c28e06821071d940c409c59fd2d374e --- /dev/null +++ b/Runtime/Scripts/WorldAnalysisARFoundationModuleARCoreAnchor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2cec98c043216c94db7d09c20b3cce67 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/etsi.isg.arf.worldanalysisarfoundation.asmdef b/Runtime/etsi.isg.arf.worldanalysisarfoundation.asmdef index 80bdd36751824aa6914254f8b4d4947580c2e0fa..8a0ef7e92cea6e2756409282e48069f6b081646e 100644 --- a/Runtime/etsi.isg.arf.worldanalysisarfoundation.asmdef +++ b/Runtime/etsi.isg.arf.worldanalysisarfoundation.asmdef @@ -6,7 +6,8 @@ "GUID:065e856e9f9becb49abdf0cb6855a039", "GUID:a9420e37d7990b54abdef6688edbe313", "GUID:92703082f92b41ba80f0d6912de66115", - "GUID:dc960734dc080426fa6612f1c5fe95f3" + "GUID:dc960734dc080426fa6612f1c5fe95f3", + "GUID:b35d8248e1a04478bb2d70fe76652ddf" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/package.json b/package.json index ff8e8c773f04d0041784dac220698e59703f81d8..57ef95e85ed246e7f0544a7c8927e47be95aa567 100644 --- a/package.json +++ b/package.json @@ -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