diff --git a/Editor/BuildResources/ARCoreiOSCloudAnchorDependencies.template b/Editor/BuildResources/ARCoreiOSCloudAnchorDependencies.template
index 88c31a8..75b3453 100644
--- a/Editor/BuildResources/ARCoreiOSCloudAnchorDependencies.template
+++ b/Editor/BuildResources/ARCoreiOSCloudAnchorDependencies.template
@@ -1,6 +1,6 @@
-
+
diff --git a/Editor/BuildResources/ARCoreiOSDependencies.template b/Editor/BuildResources/ARCoreiOSDependencies.template
index a5650e0..fa1d394 100644
--- a/Editor/BuildResources/ARCoreiOSDependencies.template
+++ b/Editor/BuildResources/ARCoreiOSDependencies.template
@@ -1,6 +1,6 @@
-
+
diff --git a/Editor/BuildResources/ARCoreiOSGeospatialDependencies.template b/Editor/BuildResources/ARCoreiOSGeospatialDependencies.template
index c897a00..1805bbf 100644
--- a/Editor/BuildResources/ARCoreiOSGeospatialDependencies.template
+++ b/Editor/BuildResources/ARCoreiOSGeospatialDependencies.template
@@ -1,6 +1,6 @@
-
+
diff --git a/Editor/BuildResources/ARCoreiOSSemanticsDependencies.template b/Editor/BuildResources/ARCoreiOSSemanticsDependencies.template
index 2377ba8..7f4a0f7 100644
--- a/Editor/BuildResources/ARCoreiOSSemanticsDependencies.template
+++ b/Editor/BuildResources/ARCoreiOSSemanticsDependencies.template
@@ -1,6 +1,6 @@
-
+
diff --git a/Editor/GeospatialCreator/Scripts/GeospatialCreatorCesiumAdapter.cs b/Editor/GeospatialCreator/Scripts/GeospatialCreatorCesiumAdapter.cs
index 75ecbfc..9b45f7b 100644
--- a/Editor/GeospatialCreator/Scripts/GeospatialCreatorCesiumAdapter.cs
+++ b/Editor/GeospatialCreator/Scripts/GeospatialCreatorCesiumAdapter.cs
@@ -144,6 +144,122 @@ internal static bool SetMapTileApiKeyForCesium3DTileset(
EditorUtility.SetDirty(tileset);
return true;
}
+
+ internal class Origin3DTilesetCesiumAdapter : Origin3DTilesetAdapter
+ {
+ // The parent ARGeospatialCreatorOrigin object that owns this instance of the Adapter
+ private readonly ARGeospatialCreatorOrigin _origin;
+
+ internal Origin3DTilesetCesiumAdapter(ARGeospatialCreatorOrigin origin)
+ {
+ _origin = origin;
+ }
+
+ /// Gets the parent ARGeospatialCreatorOrigin object.
+ public override ARGeospatialCreatorOrigin Origin
+ {
+ get
+ {
+ return _origin;
+ }
+ }
+
+ /// Sets the Cesium tileset's "Create Physics Meshes" setting.
+ /// Specifies whether to enable the setting or not.
+ public override void SetPhysicsMeshesEnabled(bool enable)
+ {
+ Cesium3DTileset tileset = GetTilesetComponent(Origin);
+ if (tileset == null)
+ {
+ Debug.LogError(
+ "No Cesium3DTileset component associated with Origin " + Origin.name);
+ return;
+ }
+
+ if (tileset.createPhysicsMeshes != enable)
+ {
+ tileset.createPhysicsMeshes = enable;
+ }
+ }
+
+ /// Gets the Cesium tileset's "Create Physics Meshes" setting.
+ public override bool GetPhysicsMeshesEnabled()
+ {
+ Cesium3DTileset tileset = GetTilesetComponent(Origin);
+ if (tileset == null)
+ {
+ Debug.LogError(
+ "No Cesium3DTileset component associated with Origin " + Origin.name);
+ return false;
+ }
+
+ return tileset.createPhysicsMeshes;
+ }
+
+ /// Retrieves percentage of tiles loaded for current view.
+ /// Percentage (0.0 to 100.0) of tiles loaded for current view.
+ public override float ComputeTilesetLoadProgress()
+ {
+ Cesium3DTileset tileset = GetTilesetComponent(Origin);
+ if (tileset == null)
+ {
+ Debug.LogError(
+ "No Cesium3DTileset component associated with Origin " + Origin.name);
+ return 0;
+ }
+ return tileset.ComputeLoadProgress();
+ }
+
+ /// Returns true if the collider belongs to a tile in this tileset.
+ /// The collider to be checked.
+ public override bool IsTileCollider(Collider collider)
+ {
+ if ((collider != null) &&
+ (collider.gameObject.GetComponent() != null))
+ {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ internal class OriginComponentCesiumAdapter : IOriginComponentAdapter
+ {
+ // The parent ARGeospatialCreatorOrigin object that owns this instance of the Adapter
+ private readonly ARGeospatialCreatorOrigin _origin;
+
+ public OriginComponentCesiumAdapter(ARGeospatialCreatorOrigin origin)
+ {
+ _origin = origin;
+ }
+
+ public GeoCoordinate GetOriginFromComponent()
+ {
+ CesiumForUnity.CesiumGeoreference geoRef = GetCesiumGeoreference();
+ return (geoRef == null) ? null :
+ new GeoCoordinate(geoRef.latitude, geoRef.longitude, geoRef.height);
+ }
+
+ public void SetComponentOrigin(GeoCoordinate newOrigin)
+ {
+ CesiumForUnity.CesiumGeoreference geoRef = GetCesiumGeoreference();
+ if (geoRef == null)
+ {
+ Debug.LogWarning("Origin location updated for " + _origin.gameObject.name +
+ ", but there is no Cesium Georeference subcomponent.");
+ return;
+ }
+
+ geoRef.latitude = newOrigin.Latitude;
+ geoRef.longitude = newOrigin.Longitude;
+ geoRef.height = newOrigin.Altitude;
+ }
+
+ private CesiumForUnity.CesiumGeoreference GetCesiumGeoreference()
+ {
+ return _origin.gameObject.GetComponent();
+ }
+ }
}
}
#endif // ARCORE_INTERNAL_USE_CESIUM
diff --git a/Editor/GeospatialCreator/Scripts/Internal/ARGeospatialCreatorAnchorEditor.cs b/Editor/GeospatialCreator/Scripts/Internal/ARGeospatialCreatorAnchorEditor.cs
index dfc0f78..46c715d 100644
--- a/Editor/GeospatialCreator/Scripts/Internal/ARGeospatialCreatorAnchorEditor.cs
+++ b/Editor/GeospatialCreator/Scripts/Internal/ARGeospatialCreatorAnchorEditor.cs
@@ -89,6 +89,52 @@ public override void OnInspectorGUI()
}
}
+ private void GUIForSnapToTile()
+ {
+ string snapToTileTooltip = "Visually position the anchor within the editor so it " +
+ "aligns with the top of the tile. This override in the editor does not impact " +
+ "the position at runtime.";
+
+ if (GUILayout.Button(new GUIContent("Snap to Tile", snapToTileTooltip)))
+ {
+ ARGeospatialCreatorOrigin origin =
+ _origin.objectReferenceValue as ARGeospatialCreatorOrigin;
+ if (origin == null)
+ {
+ Debug.LogError("An ARGeospatialCreatorOrigin object must be present in the " +
+ "scene and assigned to the anchor to use the Snap to Tile feature.");
+ return;
+ }
+
+ var tileset = origin._origin3DTilesetAdapter;
+ if (tileset.GetPhysicsMeshesEnabled() == false)
+ {
+#if ARCORE_INTERNAL_USE_CESIUM
+ Debug.LogError("Physics Meshes must be enabled on the tileset to use " +
+ "the Snap to Tile feature. Please enable the \"Create Physics Meshes\" " +
+ "setting in the Cesium3DTileset component owned by the Origin.",
+ GeospatialCreatorCesiumAdapter.GetTilesetComponent(origin));
+#else
+ Debug.LogError("Physics Meshes must be enabled on the tileset to use " +
+ "the Snap to Tile feature.");
+#endif
+ return;
+ }
+
+ (bool success, double tileAltitude) =
+ tileset.CalcTileAltitudeWGS84(_latitude.doubleValue, _longitude.doubleValue);
+ if (success)
+ {
+ _editorAltitudeOverride.doubleValue = tileAltitude;
+ }
+ else
+ {
+ Debug.LogWarning("Could not Snap to Tile at Latitude: " +
+ _latitude.doubleValue + " and Longitude: " + _longitude.doubleValue);
+ }
+ }
+ }
+
private void GUIForAltitude(AnchorAltitudeType altitudeType)
{
using (new EditorGUI.IndentLevelScope())
@@ -112,14 +158,16 @@ private void GUIForAltitude(AnchorAltitudeType altitudeType)
GUILayout.BeginHorizontal();
+ string overrideAltitudeLabel = "Override altitude in Editor Scene View";
_useEditorAltitudeOverride.boolValue = EditorGUILayout.Toggle(
- "Override altitude in Editor Scene View",
+ overrideAltitudeLabel,
_useEditorAltitudeOverride.boolValue);
// Allow the override value to be edited only if the flag is enabled.
EditorGUI.BeginDisabledGroup(!_useEditorAltitudeOverride.boolValue);
_editorAltitudeOverride.doubleValue = EditorGUILayout.DoubleField(
_editorAltitudeOverride.doubleValue);
+ GUIForSnapToTile();
EditorGUI.EndDisabledGroup();
GUILayout.EndHorizontal();
@@ -127,7 +175,7 @@ private void GUIForAltitude(AnchorAltitudeType altitudeType)
if (_useEditorAltitudeOverride.boolValue)
{
EditorGUILayout.HelpBox(
- "The Editor-only altitude override sets the altitude used in the Scene " +
+ "\"" + overrideAltitudeLabel + "\" sets the altitude used in the Scene " +
"View to position the anchor, in meters according to WGS84. This is " +
"useful to vizualize the anchor relative to the scene geometry in cases " +
"where the scene geometry altitude is not fully aligned with the real " +
@@ -136,7 +184,6 @@ private void GUIForAltitude(AnchorAltitudeType altitudeType)
MessageType.Info,
wide: true);
}
-
}
}
diff --git a/Editor/GeospatialCreator/Scripts/Internal/GeospatialAnchorUpdater.cs b/Editor/GeospatialCreator/Scripts/Internal/GeospatialAnchorUpdater.cs
index ae02ff7..692da2e 100644
--- a/Editor/GeospatialCreator/Scripts/Internal/GeospatialAnchorUpdater.cs
+++ b/Editor/GeospatialCreator/Scripts/Internal/GeospatialAnchorUpdater.cs
@@ -23,6 +23,7 @@
namespace Google.XR.ARCoreExtensions.GeospatialCreator.Editor.Internal
{
using System;
+ using Google.XR.ARCoreExtensions.Editor.Internal;
using Google.XR.ARCoreExtensions.GeospatialCreator;
using Google.XR.ARCoreExtensions.GeospatialCreator.Internal;
#if ARCORE_INTERNAL_USE_UNITY_MATH
@@ -62,6 +63,8 @@ static GeospatialAnchorUpdater()
var tracker = new GeospatialObjectTracker(actionFactory);
tracker.StartTracking();
+ GeospatialCreatorHelper.CountGeospatialCreatorAnchorsDelegate =
+ tracker.GetTrackedObjectsCount;
}
public GeospatialAnchorUpdater(ARGeospatialCreatorAnchor anchor)
@@ -139,6 +142,7 @@ private bool HasGeodeticPositionChanged()
{
return true;
}
+
return false;
}
@@ -211,7 +215,6 @@ private void UpdateUnityPosition()
// EditorAltitudeOverride value, if it is used.
double alt = _anchor.UseEditorAltitudeOverride ?
_anchor.EditorAltitudeOverride : _anchor.Altitude;
-
GeoCoordinate coor = new GeoCoordinate(
_anchor.Latitude,
_anchor.Longitude,
diff --git a/Editor/GeospatialCreator/Scripts/Internal/GeospatialObjectTracker.cs b/Editor/GeospatialCreator/Scripts/Internal/GeospatialObjectTracker.cs
index a5fe57e..f7367a6 100644
--- a/Editor/GeospatialCreator/Scripts/Internal/GeospatialObjectTracker.cs
+++ b/Editor/GeospatialCreator/Scripts/Internal/GeospatialObjectTracker.cs
@@ -92,6 +92,11 @@ public void StopTracking()
_trackedObjects.Clear();
}
+ public uint GetTrackedObjectsCount()
+ {
+ return Convert.ToUInt32(_trackedObjects.Count);
+ }
+
///
/// Handles EditorApplication.Update() events to check if GameObjects of type T have been
/// added to or removed from the scene. For new objects, a a new update Action is created
diff --git a/Editor/GeospatialCreator/Scripts/Internal/GeospatialOriginUpdater.cs b/Editor/GeospatialCreator/Scripts/Internal/GeospatialOriginUpdater.cs
index 3140d41..260c7a3 100644
--- a/Editor/GeospatialCreator/Scripts/Internal/GeospatialOriginUpdater.cs
+++ b/Editor/GeospatialCreator/Scripts/Internal/GeospatialOriginUpdater.cs
@@ -56,8 +56,11 @@ public GeospatialOriginUpdater(ARGeospatialCreatorOrigin origin)
{
_origin = origin;
#if ARCORE_INTERNAL_USE_CESIUM
- _origin._originComponentAdapter = new CesiumOriginAdapter(origin);
+ _origin._originComponentAdapter =
+ new GeospatialCreatorCesiumAdapter.OriginComponentCesiumAdapter(origin);
_origin.UpdateOriginFromComponent();
+ _origin._origin3DTilesetAdapter =
+ new GeospatialCreatorCesiumAdapter.Origin3DTilesetCesiumAdapter(origin);
#endif
}
@@ -66,44 +69,6 @@ private void EditorUpdate()
_origin.UpdateOriginFromComponent();
}
-#if ARCORE_INTERNAL_USE_CESIUM
- private class CesiumOriginAdapter : IOriginComponentAdapter
- {
- private readonly ARGeospatialCreatorOrigin _origin;
-
- public CesiumOriginAdapter(ARGeospatialCreatorOrigin origin)
- {
- _origin = origin;
- }
-
- public GeoCoordinate GetOriginFromComponent()
- {
- CesiumForUnity.CesiumGeoreference geoRef = GetCesiumGeoreference();
- return (geoRef == null) ? null :
- new GeoCoordinate(geoRef.latitude, geoRef.longitude, geoRef.height);
- }
-
- public void SetComponentOrigin(GeoCoordinate newOrigin)
- {
- CesiumForUnity.CesiumGeoreference geoRef = GetCesiumGeoreference();
- if (geoRef == null)
- {
- Debug.LogWarning("Origin location updated for " + _origin.gameObject.name +
- ", but there is no Cesium Georeference subcomponent.");
- return;
- }
-
- geoRef.latitude = newOrigin.Latitude;
- geoRef.longitude = newOrigin.Longitude;
- geoRef.height = newOrigin.Altitude;
- }
-
- private CesiumForUnity.CesiumGeoreference GetCesiumGeoreference()
- {
- return _origin.gameObject.GetComponent();
- }
- }
-#endif //ARCORE_INTERNAL_USE_CESIUM
}
}
#endif // ARCORE_INTERNAL_GEOSPATIAL_CREATOR_ENABLED
diff --git a/Editor/GeospatialCreator/Scripts/Internal/PlaceSearchHelper.cs b/Editor/GeospatialCreator/Scripts/Internal/PlaceSearchHelper.cs
index 675c4bc..d719d8b 100644
--- a/Editor/GeospatialCreator/Scripts/Internal/PlaceSearchHelper.cs
+++ b/Editor/GeospatialCreator/Scripts/Internal/PlaceSearchHelper.cs
@@ -22,6 +22,7 @@ namespace Google.XR.ARCoreExtensions.GeospatialCreator.Editor.Internal
using System;
using System.Diagnostics.CodeAnalysis;
using System.Text;
+ using System.Threading.Tasks;
using Google.XR.ARCoreExtensions.GeospatialCreator.Internal;
#if ARCORE_INTERNAL_USE_UNITY_MATH
using Unity.Mathematics;
@@ -35,6 +36,10 @@ internal class PlaceSearchHelper
private const string _searchFieldDefaultText =
"Type the name of a place and press \"Enter\"";
+ // Desired relative height (meters) from SceneView camera to target lat/lng's highest point
+ // (ie. Rooftop, or Terrain if no building)
+ private const double _sceneViewHeightAboveTile = 200;
+
private static readonly string[] _waitAnimation = new string[] { "/", "-", "\\", "|" };
private int _selectedPlaceIndex = 0;
@@ -115,8 +120,7 @@ public void GUIForSearch(UnityEngine.Object targetObject, string targetTypeName,
PlaceSearchResponse.Location loc = _response.GetLocation(_selectedPlaceIndex);
if (loc != null)
{
- SetSceneViewPreview(loc.lat, loc.lng, _request.CameraAltitude,
- _request.CameraAltitude - 3500.0f, animate: true, setPreviewPinFunc);
+ SetSceneViewPreview(loc.lat, loc.lng, animate: true, setPreviewPinFunc);
}
}
@@ -136,8 +140,7 @@ public void GUIForSearch(UnityEngine.Object targetObject, string targetTypeName,
PlaceSearchResponse.Location loc = _response.GetLocation(_selectedPlaceIndex);
if (loc != null)
{
- SetSceneViewPreview(loc.lat, loc.lng, _request.CameraAltitude,
- _request.CameraAltitude - 3500.0f, animate: true, setPreviewPinFunc);
+ SetSceneViewPreview(loc.lat, loc.lng, animate: true, setPreviewPinFunc);
}
}
@@ -150,8 +153,7 @@ public void GUIForSearch(UnityEngine.Object targetObject, string targetTypeName,
if (loc != null)
{
setLatLongAltFunc(loc.lat, loc.lng, 0.0);
- SetSceneViewPreview(loc.lat, loc.lng, _request.CameraAltitude,
- _request.CameraAltitude - 3500.0f, animate: false, setPreviewPinFunc);
+ SetSceneViewPreview(loc.lat, loc.lng, animate: false, setPreviewPinFunc);
// remove the preview pin since the object is there now
setPreviewPinFunc(null);
@@ -162,6 +164,60 @@ public void GUIForSearch(UnityEngine.Object targetObject, string targetTypeName,
EditorGUILayout.EndVertical();
}
+ // Move the SceneView camera to a given lat/lng/alt and have it face the tiles.
+ internal static void MoveSceneViewCamera(
+ double lat,
+ double lng,
+ double cameraAltitude,
+ bool animate)
+ {
+ ARGeospatialCreatorOrigin origin = ARGeospatialCreatorOrigin.FindDefaultOrigin();
+ GeoCoordinate originPoint = origin?._originPoint;
+ Vector3 originUnityCoord =
+ origin ? origin.gameObject.transform.position : Vector3.zero;
+ if (originPoint == null)
+ {
+ return;
+ }
+
+ // Make a high point where the camera will be
+ GeoCoordinate cameraGeoCoord = new GeoCoordinate(lat, lng, cameraAltitude);
+ Vector3 cameraViewPosition = GeoMath.GeoCoordinateToUnityWorld(
+ cameraGeoCoord, originPoint, originUnityCoord);
+
+ // Make a low point at a low altitude where the camera will pivot around
+ // This altitude should be lower than any possible terrain since the camera
+ // will not be able to easily zoom down to terrain below the pivot point
+ GeoCoordinate targetGeoCoord =
+ new GeoCoordinate(lat, lng, GeoMath.LowestElevationOnEarth);
+ Vector3 targetTerrainPosition = GeoMath.GeoCoordinateToUnityWorld(
+ targetGeoCoord, originPoint, originUnityCoord);
+
+ // Get the direction vector
+ Vector3 viewDirection = Vector3.Normalize(targetTerrainPosition - cameraViewPosition);
+
+ SceneView sceneView = SceneView.lastActiveSceneView;
+
+ // Compute the size parameter based on the desired distance from the camera.
+ float desiredDistanceCameraToTarget =
+ Vector3.Distance(cameraViewPosition, targetTerrainPosition);
+ float size = desiredDistanceCameraToTarget *
+ Mathf.Sin(sceneView.camera.fieldOfView * 0.5f * Mathf.Deg2Rad);
+
+ if (animate)
+ {
+ sceneView.LookAt(targetTerrainPosition,
+ Quaternion.LookRotation(viewDirection), size);
+ }
+ else
+ {
+ sceneView.LookAtDirect(targetTerrainPosition,
+ Quaternion.LookRotation(viewDirection), size);
+ }
+
+ sceneView.Repaint();
+ }
+
private void StartNewRequest(string searchString, GeoCoordinate originPoint, string apiKey)
{
// cancel any in-progress request
@@ -184,63 +240,48 @@ private void StartNewRequest(string searchString, GeoCoordinate originPoint, str
_selectedPlaceIndex = 0;
}
- private void SetSceneViewPreview(double lat, double lng, double cameraAlt,
- double objectAlt, bool animate, SetPreviewPinLocationDelegate setPreviewPinFunc)
+ private void SetSceneViewPreview(
+ double lat, double lng, bool animate, SetPreviewPinLocationDelegate setPreviewPinFunc)
{
- // hack the alt so it is above the point we place other things
- Vector3 originUnityCoords = Vector3.zero;
#if ARCORE_INTERNAL_GEOSPATIAL_CREATOR_ENABLED
ARGeospatialCreatorOrigin origin = ARGeospatialCreatorOrigin.FindDefaultOrigin();
- GeoCoordinate originPoint = origin?._originPoint;
- originUnityCoords = origin ? origin.gameObject.transform.position: Vector3.zero;
-#else // ARCORE_INTERNAL_GEOSPATIAL_CREATOR_ENABLED
- // just quick out if we creator is not enabled so can't get lat lng.
- GeoCoordinate originPoint = null;
-#endif // ARCORE_INTERNAL_GEOSPATIAL_CREATOR_ENABLED
-
- if (originPoint == null)
+ if (origin == null)
{
- // An error message was already printed (if needed) in FindDefaultOrigin()
return;
}
- // Make a high point where the camera will be
- GeoCoordinate cameraCoord = new GeoCoordinate(lat, lng, cameraAlt);
- Vector3 EUNHigh = GeoMath.GeoCoordinateToUnityWorld(
- cameraCoord,
- originPoint,
- originUnityCoords);
-
- // Make a low point where the object is
- GeoCoordinate objectCoord = new GeoCoordinate(lat, lng, objectAlt);
- Vector3 EUNLow = GeoMath.GeoCoordinateToUnityWorld(
- objectCoord,
- originPoint,
- originUnityCoords);
-
- // make a vector from that points from high to low.
- // So the vector that points down to earth
- Vector3 earthDownVec = Vector3.Normalize(EUNLow - EUNHigh);
- if (animate)
+ MoveSceneViewCameraAboveTerrainAsync(
+ origin._origin3DTilesetAdapter, lat, lng, animate);
+#endif // ARCORE_INTERNAL_GEOSPATIAL_CREATOR_ENABLED
+
+ // The altitude value can be zero, because we're using the location for a 2D icon that
+ // will be drawn over the scene view.
+ setPreviewPinFunc(new GeoCoordinate(lat, lng, 0.0));
+ }
+
+ // Calculates the terrain altitude at the given lat/lng and moves the SceneView camera
+ // at a reasonable height above it.
+ private async void MoveSceneViewCameraAboveTerrainAsync(
+ Origin3DTilesetAdapter tileset, double lat, double lng, bool animate)
+ {
+ // Move the camera high above the target location to begin loading the tiles
+ MoveSceneViewCamera(lat, lng, GeoMath.HighestElevationOnEarth, animate);
+
+ var (success, terrainAltitude) = await tileset.CalcTileAltitudeWGS84Async(lat, lng);
+ double cameraAltitude;
+ if (success)
{
- // position the camera at EUNHigh
- // Rotate from forward to earth down
- SceneView.lastActiveSceneView.LookAt(EUNLow,
- Quaternion.FromToRotation(Vector3.forward, earthDownVec));
- SceneView.lastActiveSceneView.pivot = EUNHigh;
+ cameraAltitude = terrainAltitude + _sceneViewHeightAboveTile;
}
else
{
- // position the camera at EUNHigh
- // Rotate from forward to earth down
- SceneView.lastActiveSceneView.LookAtDirect(EUNLow,
- Quaternion.FromToRotation(Vector3.forward, earthDownVec));
- SceneView.lastActiveSceneView.pivot = EUNHigh;
+ // If terrain sampling failed then set the camera to an altitude above all terrain.
+ Debug.Log("Could not get Terrain height. Setting camera at an altitude of " +
+ GeoMath.HighestElevationOnEarth + " meters.");
+ return;
}
- // The altitude value can be zero, because we're using the location for a 2D icon that
- // will be drawn over the scene view.
- setPreviewPinFunc(new GeoCoordinate(lat, lng, 0.0));
+ MoveSceneViewCamera(lat, lng, cameraAltitude, animate);
}
}
@@ -250,7 +291,6 @@ internal class PlaceSearchRequest
public bool LocationBias = false;
public double Latitude;
public double Longitude;
- public float CameraAltitude = 3500.0f;
public int Radius = 50000;
public string NextPageToken = string.Empty;
public string SearchText = string.Empty;
diff --git a/Editor/Scripts/Internal/ARCoreAnalytics.cs b/Editor/Scripts/Internal/ARCoreAnalytics.cs
index 8427378..7c80850 100644
--- a/Editor/Scripts/Internal/ARCoreAnalytics.cs
+++ b/Editor/Scripts/Internal/ARCoreAnalytics.cs
@@ -43,7 +43,7 @@ public class ARCoreAnalytics
private UnityWebRequest _webRequest;
///
- /// Static constructor permits a once-on-load analytics collection event.
+ /// Static constructor permits a once-after-editor-load analytics collection event.
///
static ARCoreAnalytics()
{
@@ -51,8 +51,10 @@ static ARCoreAnalytics()
Instance = new ARCoreAnalytics();
Instance.Load();
- // Send analytics immediately.
- Instance.SendAnalytics(_googleAnalyticsHost, LogRequestUtils.BuildLogRequest());
+ // Schedule the first analytics data to be sent after Editor Inspectors have updated.
+ // Otherwise, we might query the scene for analytics data before it is available.
+ Instance._lastUpdateTicks = DateTime.Now.Ticks;
+ EditorApplication.delayCall += OnEditorInspectorsUpdatedOnce;
// Use the Editor Update callback to monitor the communication to the server.
EditorApplication.update +=
@@ -140,5 +142,14 @@ public void OnAnalyticsUpdate()
_googleAnalyticsHost, LogRequestUtils.BuildLogRequest());
}
}
+
+ ///
+ /// Callback function to send analytics data after Editor Inspectors are ready.
+ ///
+ private static void OnEditorInspectorsUpdatedOnce()
+ {
+ Instance.SendAnalytics(
+ _googleAnalyticsHost, LogRequestUtils.BuildLogRequest());
+ }
}
}
diff --git a/Editor/Scripts/Internal/Analytics/ArcoreSdkLog.cs b/Editor/Scripts/Internal/Analytics/ArcoreSdkLog.cs
index 42da364..e242ac8 100644
--- a/Editor/Scripts/Internal/Analytics/ArcoreSdkLog.cs
+++ b/Editor/Scripts/Internal/Analytics/ArcoreSdkLog.cs
@@ -1,7 +1,7 @@
//-----------------------------------------------------------------------
//
//
-// Copyright 2019 Google LLC
+// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -44,24 +44,29 @@ public static partial class ArcoreSdkLogReflection {
static ArcoreSdkLogReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
- "ChRhcmNvcmVfc2RrX2xvZy5wcm90bxIRY29tLmdvb2dsZS5hcmNvcmUi/QMK",
+ "ChRhcmNvcmVfc2RrX2xvZy5wcm90bxIRY29tLmdvb2dsZS5hcmNvcmUinQUK",
"DEFyQ29yZVNka0xvZxIXCg9zZGtfaW5zdGFuY2VfaWQYASABKAkSFgoOc2Rr",
"X3Nlc3Npb25faWQYBSABKAkSGgoSYXJjb3JlX3Nka192ZXJzaW9uGAIgASgJ",
"EjkKCHNka190eXBlGAYgASgOMicuY29tLmdvb2dsZS5hcmNvcmUuQXJDb3Jl",
"U2RrTG9nLlNES1R5cGUSEgoKb3NfdmVyc2lvbhgDIAEoCRI8CgV1bml0eRgE",
"IAEoCzIrLmNvbS5nb29nbGUuYXJjb3JlLkFyQ29yZVNka0xvZy5Vbml0eUVu",
- "Z2luZUgAGrYBCgtVbml0eUVuZ2luZRIPCgd2ZXJzaW9uGAEgASgJEk0KDGVk",
- "aXRpb25fdHlwZRgCIAEoDjI3LmNvbS5nb29nbGUuYXJjb3JlLkFyQ29yZVNk",
- "a0xvZy5Vbml0eUVuZ2luZS5FZGl0aW9uVHlwZSJHCgtFZGl0aW9uVHlwZRIY",
- "ChRVTktOT1dOX0VESVRJT05fVFlQRRAAEgwKCFBFUlNPTkFMEAESEAoMUFJP",
- "RkVTU0lPTkFMEAIiUAoHU0RLVHlwZRIUChBVTktOT1dOX1NES19UWVBFEAAS",
- "DgoKQVJDT1JFX1NESxABEh8KG0FSRk9VTkRBVElPTl9FWFRFTlNJT05TX1NE",
- "SxACQggKBmVuZ2luZUIzqgIwR29vZ2xlLlhSLkFSQ29yZUV4dGVuc2lvbnMu",
- "RWRpdG9yLkludGVybmFsLlByb3RvYgZwcm90bzM="));
+ "Z2luZUgAEk0KEmdlb3NwYXRpYWxfY3JlYXRvchgHIAEoCzIxLmNvbS5nb29n",
+ "bGUuYXJjb3JlLkFyQ29yZVNka0xvZy5HZW9zcGF0aWFsQ3JlYXRvchq2AQoL",
+ "VW5pdHlFbmdpbmUSDwoHdmVyc2lvbhgBIAEoCRJNCgxlZGl0aW9uX3R5cGUY",
+ "AiABKA4yNy5jb20uZ29vZ2xlLmFyY29yZS5BckNvcmVTZGtMb2cuVW5pdHlF",
+ "bmdpbmUuRWRpdGlvblR5cGUiRwoLRWRpdGlvblR5cGUSGAoUVU5LTk9XTl9F",
+ "RElUSU9OX1RZUEUQABIMCghQRVJTT05BTBABEhAKDFBST0ZFU1NJT05BTBAC",
+ "Gk8KEUdlb3NwYXRpYWxDcmVhdG9yEiUKHWlzX2dlb3NwYXRpYWxfY3JlYXRv",
+ "cl9lbmFibGVkGAEgASgIEhMKC251bV9hbmNob3JzGAIgASgNIlAKB1NES1R5",
+ "cGUSFAoQVU5LTk9XTl9TREtfVFlQRRAAEg4KCkFSQ09SRV9TREsQARIfChtB",
+ "UkZPVU5EQVRJT05fRVhURU5TSU9OU19TREsQAkIICgZlbmdpbmVCM6oCMEdv",
+ "b2dsZS5YUi5BUkNvcmVFeHRlbnNpb25zLkVkaXRvci5JbnRlcm5hbC5Qcm90",
+ "b2IGcHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
- new pbr::GeneratedClrTypeInfo(typeof(global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog), global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Parser, new[]{ "SdkInstanceId", "SdkSessionId", "ArcoreSdkVersion", "SdkType", "OsVersion", "Unity" }, new[]{ "Engine" }, new[]{ typeof(global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.SDKType) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.UnityEngine), global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.UnityEngine.Parser, new[]{ "Version", "EditionType" }, null, new[]{ typeof(global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.UnityEngine.Types.EditionType) }, null)})
+ new pbr::GeneratedClrTypeInfo(typeof(global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog), global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Parser, new[]{ "SdkInstanceId", "SdkSessionId", "ArcoreSdkVersion", "SdkType", "OsVersion", "Unity", "GeospatialCreator" }, new[]{ "Engine" }, new[]{ typeof(global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.SDKType) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.UnityEngine), global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.UnityEngine.Parser, new[]{ "Version", "EditionType" }, null, new[]{ typeof(global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.UnityEngine.Types.EditionType) }, null),
+ new pbr::GeneratedClrTypeInfo(typeof(global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.GeospatialCreator), global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.GeospatialCreator.Parser, new[]{ "IsGeospatialCreatorEnabled", "NumAnchors" }, null, null, null)})
}));
}
#endregion
@@ -72,7 +77,7 @@ static ArcoreSdkLogReflection() {
/// Message with log extension for ARCore SDK within development engines, like
/// Unity and Unreal.
///
- /// Next ID: 7
+ /// Next ID: 8
///
public sealed partial class ArCoreSdkLog : pb::IMessage {
private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ArCoreSdkLog());
@@ -104,6 +109,7 @@ public ArCoreSdkLog(ArCoreSdkLog other) : this() {
arcoreSdkVersion_ = other.arcoreSdkVersion_;
sdkType_ = other.sdkType_;
osVersion_ = other.osVersion_;
+ geospatialCreator_ = other.geospatialCreator_ != null ? other.geospatialCreator_.Clone() : null;
switch (other.EngineCase) {
case EngineOneofCase.Unity:
Unity = other.Unity.Clone();
@@ -205,6 +211,20 @@ public string OsVersion {
}
}
+ /// Field number for the "geospatial_creator" field.
+ public const int GeospatialCreatorFieldNumber = 7;
+ private global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.GeospatialCreator geospatialCreator_;
+ ///
+ /// Data logged about the Geospatial Creator plugin usage in the project.
+ ///
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.GeospatialCreator GeospatialCreator {
+ get { return geospatialCreator_; }
+ set {
+ geospatialCreator_ = value;
+ }
+ }
+
private object engine_;
/// Enum of possible cases for the "engine" oneof.
public enum EngineOneofCase {
@@ -242,6 +262,7 @@ public bool Equals(ArCoreSdkLog other) {
if (SdkType != other.SdkType) return false;
if (OsVersion != other.OsVersion) return false;
if (!object.Equals(Unity, other.Unity)) return false;
+ if (!object.Equals(GeospatialCreator, other.GeospatialCreator)) return false;
if (EngineCase != other.EngineCase) return false;
return Equals(_unknownFields, other._unknownFields);
}
@@ -255,6 +276,7 @@ public override int GetHashCode() {
if (SdkType != 0) hash ^= SdkType.GetHashCode();
if (OsVersion.Length != 0) hash ^= OsVersion.GetHashCode();
if (engineCase_ == EngineOneofCase.Unity) hash ^= Unity.GetHashCode();
+ if (geospatialCreator_ != null) hash ^= GeospatialCreator.GetHashCode();
hash ^= (int) engineCase_;
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
@@ -293,6 +315,10 @@ public void WriteTo(pb::CodedOutputStream output) {
output.WriteRawTag(48);
output.WriteEnum((int) SdkType);
}
+ if (geospatialCreator_ != null) {
+ output.WriteRawTag(58);
+ output.WriteMessage(GeospatialCreator);
+ }
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
@@ -319,6 +345,9 @@ public int CalculateSize() {
if (engineCase_ == EngineOneofCase.Unity) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Unity);
}
+ if (geospatialCreator_ != null) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(GeospatialCreator);
+ }
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
@@ -345,6 +374,12 @@ public void MergeFrom(ArCoreSdkLog other) {
if (other.OsVersion.Length != 0) {
OsVersion = other.OsVersion;
}
+ if (other.geospatialCreator_ != null) {
+ if (geospatialCreator_ == null) {
+ GeospatialCreator = new global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.GeospatialCreator();
+ }
+ GeospatialCreator.MergeFrom(other.GeospatialCreator);
+ }
switch (other.EngineCase) {
case EngineOneofCase.Unity:
if (Unity == null) {
@@ -391,7 +426,14 @@ public void MergeFrom(pb::CodedInputStream input) {
break;
}
case 48: {
- sdkType_ = (global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.SDKType) input.ReadEnum();
+ SdkType = (global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.SDKType) input.ReadEnum();
+ break;
+ }
+ case 58: {
+ if (geospatialCreator_ == null) {
+ GeospatialCreator = new global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.GeospatialCreator();
+ }
+ input.ReadMessage(GeospatialCreator);
break;
}
}
@@ -572,7 +614,7 @@ public void MergeFrom(pb::CodedInputStream input) {
break;
}
case 16: {
- editionType_ = (global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.UnityEngine.Types.EditionType) input.ReadEnum();
+ EditionType = (global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Types.UnityEngine.Types.EditionType) input.ReadEnum();
break;
}
}
@@ -598,6 +640,174 @@ public enum EditionType {
}
+ ///
+ /// Message with data logged about Geospatial Creator usage.
+ ///
+ /// Next ID: 3
+ ///
+ public sealed partial class GeospatialCreator : pb::IMessage {
+ private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new GeospatialCreator());
+ private pb::UnknownFieldSet _unknownFields;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pb::MessageParser Parser { get { return _parser; } }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Google.XR.ARCoreExtensions.Editor.Internal.Proto.ArCoreSdkLog.Descriptor.NestedTypes[1]; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public GeospatialCreator() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public GeospatialCreator(GeospatialCreator other) : this() {
+ isGeospatialCreatorEnabled_ = other.isGeospatialCreatorEnabled_;
+ numAnchors_ = other.numAnchors_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public GeospatialCreator Clone() {
+ return new GeospatialCreator(this);
+ }
+
+ /// Field number for the "is_geospatial_creator_enabled" field.
+ public const int IsGeospatialCreatorEnabledFieldNumber = 1;
+ private bool isGeospatialCreatorEnabled_;
+ ///
+ /// Whether Geospatial Creator is enabled in the project settings.
+ ///
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public bool IsGeospatialCreatorEnabled {
+ get { return isGeospatialCreatorEnabled_; }
+ set {
+ isGeospatialCreatorEnabled_ = value;
+ }
+ }
+
+ /// Field number for the "num_anchors" field.
+ public const int NumAnchorsFieldNumber = 2;
+ private uint numAnchors_;
+ ///
+ /// The number of Geosptial Creator Anchors in the project's active scene.
+ ///
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public uint NumAnchors {
+ get { return numAnchors_; }
+ set {
+ numAnchors_ = value;
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override bool Equals(object other) {
+ return Equals(other as GeospatialCreator);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public bool Equals(GeospatialCreator other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (IsGeospatialCreatorEnabled != other.IsGeospatialCreatorEnabled) return false;
+ if (NumAnchors != other.NumAnchors) return false;
+ return Equals(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override int GetHashCode() {
+ int hash = 1;
+ if (IsGeospatialCreatorEnabled != false) hash ^= IsGeospatialCreatorEnabled.GetHashCode();
+ if (NumAnchors != 0) hash ^= NumAnchors.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
+ return hash;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (IsGeospatialCreatorEnabled != false) {
+ output.WriteRawTag(8);
+ output.WriteBool(IsGeospatialCreatorEnabled);
+ }
+ if (NumAnchors != 0) {
+ output.WriteRawTag(16);
+ output.WriteUInt32(NumAnchors);
+ }
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public int CalculateSize() {
+ int size = 0;
+ if (IsGeospatialCreatorEnabled != false) {
+ size += 1 + 1;
+ }
+ if (NumAnchors != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeUInt32Size(NumAnchors);
+ }
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
+ return size;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(GeospatialCreator other) {
+ if (other == null) {
+ return;
+ }
+ if (other.IsGeospatialCreatorEnabled != false) {
+ IsGeospatialCreatorEnabled = other.IsGeospatialCreatorEnabled;
+ }
+ if (other.NumAnchors != 0) {
+ NumAnchors = other.NumAnchors;
+ }
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+ break;
+ case 8: {
+ IsGeospatialCreatorEnabled = input.ReadBool();
+ break;
+ }
+ case 16: {
+ NumAnchors = input.ReadUInt32();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
}
#endregion
diff --git a/Editor/Scripts/Internal/GeospatialCreatorHelper.cs b/Editor/Scripts/Internal/GeospatialCreatorHelper.cs
index a298b83..b072560 100644
--- a/Editor/Scripts/Internal/GeospatialCreatorHelper.cs
+++ b/Editor/Scripts/Internal/GeospatialCreatorHelper.cs
@@ -48,6 +48,10 @@ public static class GeospatialCreatorHelper
public static readonly string CreatorEnabledSymbol =
"ARCORE_INTERNAL_GEOSPATIAL_CREATOR_ENABLED";
+ /// Single cast delegate used to bind function that returns the number of
+ /// Geospatial Creator Anchors in a scene.
+ public static Func CountGeospatialCreatorAnchorsDelegate;
+
private static readonly BuildTargetGroup[] _buildTargets = new BuildTargetGroup[]
{
BuildTargetGroup.Android,
@@ -147,6 +151,20 @@ public static void RemoveScriptingSymbols()
}
}
+ /// Counts the number of Geospatial Creator Anchors in the scene.
+ /// The anchor count returned by CountGeospatialCreatorAnchorsDelegate() if
+ /// it was set, otherwise 0.
+ public static uint CountGeospatialCreatorAnchors()
+ {
+ uint geospatialCreatorAnchorCount = 0;
+ if (CountGeospatialCreatorAnchorsDelegate != null)
+ {
+ geospatialCreatorAnchorCount = CountGeospatialCreatorAnchorsDelegate();
+ }
+
+ return geospatialCreatorAnchorCount;
+ }
+
private static void AddSymbol(string symbol, BuildTargetGroup target)
{
HashSet symbolSet = GetCurrentSymbolSet(target);
diff --git a/Editor/Scripts/Internal/LogRequestUtils.cs b/Editor/Scripts/Internal/LogRequestUtils.cs
index 86ca0a9..aeb9a59 100644
--- a/Editor/Scripts/Internal/LogRequestUtils.cs
+++ b/Editor/Scripts/Internal/LogRequestUtils.cs
@@ -25,8 +25,8 @@ namespace Google.XR.ARCoreExtensions.Editor.Internal
using System.Security.Cryptography;
using System.Text;
using Google.Protobuf;
- using Google.XR.ARCoreExtensions;
using Google.XR.ARCoreExtensions.Editor.Internal.Proto;
+ using Google.XR.ARCoreExtensions.Internal;
using UnityEditor;
using UnityEngine;
@@ -57,6 +57,15 @@ ArCoreSdkLog.Types.UnityEngine.Types.EditionType editionType
EditionType = editionType,
};
+ // Determine Geospatial Creator information.
+ ArCoreSdkLog.Types.GeospatialCreator geospatialCreatorMessage =
+ new ArCoreSdkLog.Types.GeospatialCreator()
+ {
+ IsGeospatialCreatorEnabled =
+ ARCoreExtensionsProjectSettings.Instance.GeospatialEditorEnabled,
+ NumAnchors = GeospatialCreatorHelper.CountGeospatialCreatorAnchors(),
+ };
+
// Collect the set of information to be sent to Google.
ArCoreSdkLog logSDK = new ArCoreSdkLog()
{
@@ -66,6 +75,7 @@ ArCoreSdkLog.Types.UnityEngine.Types.EditionType editionType
SdkType = ArCoreSdkLog.Types.SDKType.ArfoundationExtensionsSdk,
Unity = engine, // Unity engine version.
SdkSessionId = SessionId(),
+ GeospatialCreator = geospatialCreatorMessage,
};
// Assemble the Clearcut log event data.
diff --git a/Runtime/GeospatialCreatorRuntime/Scripts/ARGeospatialCreatorAnchor.cs b/Runtime/GeospatialCreatorRuntime/Scripts/ARGeospatialCreatorAnchor.cs
index 193c76c..c82fe36 100644
--- a/Runtime/GeospatialCreatorRuntime/Scripts/ARGeospatialCreatorAnchor.cs
+++ b/Runtime/GeospatialCreatorRuntime/Scripts/ARGeospatialCreatorAnchor.cs
@@ -36,7 +36,7 @@ namespace Google.XR.ARCoreExtensions.GeospatialCreator
///
/// A representation of a Geospatial Anchor that was created using the Geospatial Creator tool.
- /// This object is responsible for creating a proper ARGeospatialAnchor at runtime at the
+ /// This object is responsible for creating a proper ARGeospatialAnchor at runtime at the
/// latitude, longitude, and altitude specified.
///
[AddComponentMenu("XR/AR Geospatial Creator Anchor")]
@@ -57,13 +57,14 @@ public class ARGeospatialCreatorAnchor : ARGeospatialCreatorObject
internal const string _noAnchorManagersMessage =
"No ARAnchorManagers were found in the scene.";
- // TODO (b/298042491) This can be private & editor-only when the GEOSPATIAL_CREATOR_API
- // flag is permanently enabled. It cannot be removed entirely because we need to be able to
+#if UNITY_EDITOR
+ // This field is deprecated, but cannot be removed entirely because we need to be able to
// migrate the value for customers upgrading from older versions of ARCore Extensions.
[SerializeField]
[Obsolete("Superseded by EditorAltitudeOverride. See MigrateAltitudeOffset() comments.",
false)]
internal double _altitudeOffset;
+#endif // UNITY_EDITOR
#if !UNITY_EDITOR
#pragma warning disable CS0649
@@ -112,26 +113,40 @@ private enum AnchorResolutionState
}
#endif
-
///
- /// Gets and sets the ARAnchorManager used for resolving this anchor at runtime. The
- /// property is read-only at runtime.
- ///
- /// If null, this property will be given a default value during the Awake()
+ /// Gets and sets the used for resolving this anchor
+ /// at runtime. The property is read-only at runtime.
+ ///
+ /// If null, this property will be given a default value during the
+ /// Awake() message execution, as follows:
+ ///
+ /// -
#if ARCORE_USE_ARF_5 // use ARF 5
- /// message execution, as follows: If the XROrigin has an AnchorManager
+ /// If the has an
#elif ARCORE_USE_ARF_4 // use ARF 4
- /// message execution, as follows: If the ARSessionOrigin has an AnchorManager
+ /// If the has an
#else // ARF error
#error error must define ARCORE_USE_ARF_5 or ARCORE_USE_ARF_4
#endif
- /// subcomponent, that AnchorManager will be used; otherwise the first active and enabled
- /// ARAnchorManager object returned by Resources.FindObjectsOfTypeAll will be used. If
- /// there are no active and enabled ARAnchorManager components in the scene, the first
- /// inactive / disabled ARAnchorManager is used. If there are no ARAnchorManagers in the
- /// scene, an error will be logged and this property will remain null.
- /// GeospatialCreatorAnchors will not be resolved at runtime if the property remains null.
- ///
+ /// subcomponent, that will be used;
+ ///
+ /// -
+ /// otherwise the first active and enabled object
+ /// returned by will be used.
+ ///
+ /// -
+ /// If there are no
+ /// active and enabled components in the scene, the
+ /// first inactive / disabled is used.
+ ///
+ /// -
+ /// If there are no objects in the scene, an error will
+ /// be logged and this property will remain null.
+ ///
+ ///
+ /// objects will not be resolved at runtime
+ /// if the property remains null.
+ ///
public ARAnchorManager AnchorManager
{
get => _anchorManager;
@@ -144,23 +159,33 @@ public ARAnchorManager AnchorManager
///
/// Gets or sets the Geospatial Creator Origin used to resolve the location of this anchor.
/// This property only exists in Editor mode.
+ ///
+ /// This property will be given a default value in the Editor's Awake() message
+ /// execution, as follows:
+ ///
+ /// -
+ /// If there are no objects of type in the
+ /// scene, it will remain null and a warning will be logged.
+ ///
+ /// -
+ /// If there is exactly one object of type
+ /// in the scene, that origin will be assigned to this property.
+ ///
+ /// -
+ /// If more than one object of type are in
+ /// the scene, a warning is logged and the property will remain null. A default
+ /// origin in the scene will be used to resolve the Anchor's location.
+ ///
+ ///
///
- /// This property will be given a default value in the Editor's Awake() message
- /// execution, as follows:
- /// If there no object of type ARGeospatialCreatorOrigin in the scene, it will remain null
- /// and a warning will be logged.
- /// If there is exactly one object of type ARGeospatialCreatorOrigin in the scene, that
- /// origin will be assigned to this property.
- /// If more than one objects of type ARGeospatialCreatorOrigin are in the scene, a warning
- /// is logged and the property will remain null. A default origin in the scene will be used
- /// to resolve the Anchor's location.
- ///
public ARGeospatialCreatorOrigin Origin;
///
/// Indicates if the anchor should be rendered in the Editor's Scene view at the default
- /// Altitude, or at the altitude specified by EditorAltitudeOverride. If false,
- /// EditorAltitudeOverride is ignored. UseEditorAltitudeOverride is not available runtime.
+ /// , or at the altitude specified by
+ /// . If false,
+ /// is ignored.
+ /// UseEditorAltitudeOverride is not available at runtime.
///
public bool UseEditorAltitudeOverride
{
@@ -177,10 +202,13 @@ public bool UseEditorAltitudeOverride
///
/// Gets and sets the altitude (in WGS84 meters) at which the Anchor should be rendered in
- /// the Editor's scene view. This value is ignored when UseEditorAltitudeOverride is true.
- /// EditorAltitudeOverride is useful if the default altitude rooftop or terrain anchors is
- /// inaccurate, or if using WGS84 altitude and the scene geometry does not line up exactly
- /// with the real world. EditorAltitudeOverride is not used at runtime.
+ /// the Editor's scene view. This value is ignored when
+ /// is true.
+ ///
+ /// is useful if the default altitude rooftop or
+ /// terrain anchor is inaccurate, or if using WGS84 altitude and the scene geometry does not
+ /// line up exactly with the real world. is not
+ /// used at runtime.
///
public double EditorAltitudeOverride
{
@@ -233,11 +261,15 @@ public double Longitude
}
///
- /// Gets or sets the altitude. When AltitudeType is WSG84, this value is the altitude of
- /// the anchor, in meters according to WGS84. When AltitudeType is Terrain or Rooftop, this
- /// value is ONLY used in Editor mode, to determine the altitude at which to render the
- /// anchor in the Editor's Scene View. If AltitudeType is Terrain or Rooftop, this value is
- /// ignored in the Player.
+ /// Gets or sets the altitude. When is
+ /// , this value is the altitude of
+ /// the anchor, in meters according to WGS84.
+ ///
+ /// When is or
+ /// , this value is ONLY used in Editor mode, to
+ /// determine the altitude at which to render the anchor in the Editor's Scene View, and it
+ /// is ignored in the Player.
+ ///
public double Altitude
{
get => this._altitude;
@@ -253,7 +285,10 @@ public double Altitude
#endif
}
- /// Gets or sets the AltitudeType used for resolution of this anchor.
+ ///
+ /// Gets or sets the used for resolution of this
+ /// anchor.
+ ///
public AnchorAltitudeType AltitudeType
{
get => _altitudeType;
@@ -423,7 +458,7 @@ internal bool MigrateAltitudeOffset()
}
#pragma warning restore CS0618
-#endif // UINITY_EDITOR
+#endif // UNITY_EDITOR
#if !UNITY_EDITOR
private void Update()
@@ -470,13 +505,10 @@ private void AddGeoAnchorAtRuntime()
return;
}
-
if (_anchorManager == null)
{
- string errorReason =
- "The AnchorManager property for " + name + " is null";
- Debug.LogError("Unable to place ARGeospatialCreatorAnchor " + name + ": " +
- errorReason);
+ Debug.LogError("Unable to place ARGeospatialCreatorAnchor " + name + ": The " +
+ "AnchorManager property is null");
_anchorResolution = AnchorResolutionState.Complete;
return;
}
@@ -525,6 +557,8 @@ private void ResolveWGS84AltitudeAnchor()
{
ARGeospatialAnchor anchor = _anchorManager.AddAnchor(
Latitude, Longitude, Altitude, transform.rotation);
+
+ _anchorManager.ReportCreateGeospatialCreatorAnchor(ApiGeospatialAnchorType.WGS84);
FinishAnchor(anchor);
}
@@ -533,11 +567,10 @@ private void ResolveWGS84AltitudeAnchor()
// creating geospatial anchors.
private IEnumerator ResolveTerrainAnchor()
{
- double altitudeAboveTerrain = Altitude;
ARGeospatialAnchor anchor = null;
ResolveAnchorOnTerrainPromise promise =
_anchorManager.ResolveAnchorOnTerrainAsync(
- Latitude, Longitude, altitudeAboveTerrain, transform.rotation);
+ Latitude, Longitude, Altitude, transform.rotation);
yield return promise;
var result = promise.Result;
@@ -546,6 +579,7 @@ private IEnumerator ResolveTerrainAnchor()
anchor = result.Anchor;
}
+ _anchorManager.ReportCreateGeospatialCreatorAnchor(ApiGeospatialAnchorType.Terrain);
FinishAnchor(anchor);
yield break;
}
@@ -561,11 +595,10 @@ private IEnumerator ResolveTerrainAnchor()
// creating geospatial anchors.
private IEnumerator ResolveRooftopAnchor()
{
- double altitudeAboveRooftop = Altitude;
ARGeospatialAnchor anchor = null;
ResolveAnchorOnRooftopPromise promise =
_anchorManager.ResolveAnchorOnRooftopAsync(
- Latitude, Longitude, altitudeAboveRooftop, transform.rotation);
+ Latitude, Longitude, Altitude, transform.rotation);
yield return promise;
var result = promise.Result;
@@ -574,6 +607,7 @@ private IEnumerator ResolveRooftopAnchor()
anchor = result.Anchor;
}
+ _anchorManager.ReportCreateGeospatialCreatorAnchor(ApiGeospatialAnchorType.Rooftop);
FinishAnchor(anchor);
yield break;
}
diff --git a/Runtime/GeospatialCreatorRuntime/Scripts/ARGeospatialCreatorOrigin.cs b/Runtime/GeospatialCreatorRuntime/Scripts/ARGeospatialCreatorOrigin.cs
index 951d796..5dd4d6a 100644
--- a/Runtime/GeospatialCreatorRuntime/Scripts/ARGeospatialCreatorOrigin.cs
+++ b/Runtime/GeospatialCreatorRuntime/Scripts/ARGeospatialCreatorOrigin.cs
@@ -27,8 +27,8 @@ namespace Google.XR.ARCoreExtensions.GeospatialCreator
using UnityEngine;
///
- /// Provides a Geospatial Creator Origin that has both a lat/lon and gamespace coordinates. This is
- /// the reference point used by AR Anchors made in the Geospatial Creator to resolve their
+ /// Provides a Geospatial Creator Origin that has both a lat/lon and gamespace coordinates. This
+ /// is the reference point used by AR Anchors made in the Geospatial Creator to resolve their
/// location in gamespace.
///
#if ARCORE_INTERNAL_GEOSPATIAL_CREATOR_ENABLED
@@ -52,8 +52,8 @@ public class ARGeospatialCreatorOrigin : ARGeospatialCreatorObject
new GeoCoordinate(37.422098, -122.08286, 11.5);
///
- /// Gets the latitude of this origin, in decimal degrees. Will return Double.NaN if the
- /// origin point has not been initialized.
+ /// Gets the latitude of this origin, in decimal degrees. Will return
+ /// if the origin point has not been initialized.
///
public double Latitude
{
@@ -61,8 +61,8 @@ public double Latitude
}
///
- /// Gets the longitude of this origin, in decimal degrees. Will return Double.NaN if the
- /// origin point has not been initialized.
+ /// Gets the longitude of this origin, in decimal degrees. Will return
+ /// if the origin point has not been initialized.
///
public double Longitude
{
@@ -70,8 +70,8 @@ public double Longitude
}
///
- /// Gets the altiude of this origin, in meters according to WGS84. Will return Double.NaN
- /// if the origin point has not been initialized.
+ /// Gets the altiude of this origin, in meters according to WGS84. Will return
+ /// if the origin point has not been initialized.
///
public double Altitude
{
@@ -101,6 +101,12 @@ internal GeoCoordinate _originPoint
// comments in IOriginComponentAdapter for more details.
internal IOriginComponentAdapter _originComponentAdapter;
+ // An adapter to access the 3DTileset maintained by this GameObject's subcomponent.
+ // This property is set in the Editor assembly from the GeospatialOriginUpdater
+ // when the updater for this Origin is initialized. See the comments in
+ // Origin3DTilesetAdapter for more details.
+ internal Origin3DTilesetAdapter _origin3DTilesetAdapter;
+
///
/// Sets the geospatial location for this origin, including updating the location for any
/// dependent subcomponents. This method is only available in the Unity Editor; moving the
diff --git a/Runtime/GeospatialCreatorRuntime/Scripts/AnchorAltitudeType.cs b/Runtime/GeospatialCreatorRuntime/Scripts/AnchorAltitudeType.cs
index 6f30c4f..5f8b4f6 100644
--- a/Runtime/GeospatialCreatorRuntime/Scripts/AnchorAltitudeType.cs
+++ b/Runtime/GeospatialCreatorRuntime/Scripts/AnchorAltitudeType.cs
@@ -21,24 +21,58 @@
namespace Google.XR.ARCoreExtensions.GeospatialCreator
{
///
- /// Specifies how the ARGeospatialCreatorAnchor's Altitude and AlttudeOffset fields will be
+ /// Specifies how the 's
+ /// and
+ /// properties will be
/// interpreted.
public enum AnchorAltitudeType
{
///
- /// Altitude specifies the altitude of the anchor in meters for WGS84. AltitudeOffset is
- /// not used.
+ /// The anchor represents a WGS84
+ /// anchor.
+ /// The anchor's specifies the
+ /// altitude of the anchor in meters for WGS84.
+ ///
+ /// is not used.
+ ///
WGS84,
///
- /// Altitude specifies the relative altitude above/below the terrain, in meters. If the
- /// anchor does not appear to render at the correct height in the Editor, adjust the
- /// anchor's EditorAltitude property.
+ /// The anchor represents a Terrain
+ /// anchor.
+ /// The anchor's specifies the
+ /// relative altitude above or below the terrain, in meters.
+ ///
+ /// If the anchor does not appear to render at the correct height in the Editor, set the
+ /// anchor's
+ /// property to
+ /// true and use
+ ///
+ /// to adjust the anchor's visual altitude in the Editor. At runtime, the anchor will ignore
+ /// these values and use an altitude relative to the terrain at that anchor's horizontal
+ /// location.
+ ///
Terrain,
- /// Altitude specifies the relative altitude above/below the rooftop, in meters.
- /// If the anchor does not appear to render at the correct height in the Editor, adjust the
- /// anchor's EditorAltitude property.
+ ///
+ /// The anchor represents a Rooftop
+ /// anchor.
+ /// The anchor's specifies the
+ /// relative altitude above or below to a rooftop at that anchor's horizontal location, in
+ /// meters.
+ ///
+ /// If the anchor does not appear to render at the correct height in the Editor, set the
+ /// anchor's
+ /// property to
+ /// true and use
+ ///
+ /// to adjust the anchor's visual altitude in the Editor. At runtime, the anchor will ignore
+ /// these values and use an altitude relative to a rooftop at that anchor's horizontal
+ /// location.
+ ///
Rooftop
}
}
diff --git a/Runtime/GeospatialCreatorRuntime/Scripts/Internal/GeoMath.cs b/Runtime/GeospatialCreatorRuntime/Scripts/Internal/GeoMath.cs
index a5a120c..62af70f 100644
--- a/Runtime/GeospatialCreatorRuntime/Scripts/Internal/GeoMath.cs
+++ b/Runtime/GeospatialCreatorRuntime/Scripts/Internal/GeoMath.cs
@@ -30,6 +30,12 @@ namespace Google.XR.ARCoreExtensions.GeospatialCreator.Internal
// :TODO: b/277365140 Automated testing
internal static class GeoMath
{
+ // This value is higher than any terrain altitude on Earth (ie. Mt. Everest at 8848m)
+ public const double HighestElevationOnEarth = 9000;
+
+ // This value is lower than any terrain altitude on Earth (ie. Dead Sea shore at -420m)
+ public const double LowestElevationOnEarth = -420;
+
// Equatorial radius in meters
private const double _wgs84EllipsoidSemiMajorAxis = 6378137.0;
diff --git a/Runtime/GeospatialCreatorRuntime/Scripts/Internal/Origin3DTilesetAdapter.cs b/Runtime/GeospatialCreatorRuntime/Scripts/Internal/Origin3DTilesetAdapter.cs
new file mode 100644
index 0000000..5128c4c
--- /dev/null
+++ b/Runtime/GeospatialCreatorRuntime/Scripts/Internal/Origin3DTilesetAdapter.cs
@@ -0,0 +1,185 @@
+//-----------------------------------------------------------------------
+//
+//
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+//-----------------------------------------------------------------------
+
+namespace Google.XR.ARCoreExtensions.GeospatialCreator.Internal
+{
+ using System;
+ using System.Threading.Tasks;
+ using UnityEngine;
+#if UNITY_EDITOR
+ using UnityEditor;
+#endif // UNITY_EDITOR
+
+ ///
+ /// Used when an ARGeospatialCreatorOrigin's 3D Tileset is determined by or maintained by
+ /// a child object. For example, the default way to configure an origin is to add a
+ /// Cesium3D Tileset as a child object. The adapter pattern allows us to avoid
+ /// exposing the implementation details of the Cesium3D Tileset to the
+ /// ARGeospatialCreatorOrigin class.
+ ///
+ internal abstract class Origin3DTilesetAdapter
+ {
+ // How many milliseconds to wait for the tiles to load before attempting a hit test
+ private const int _tileLoadingWaitInterval = 100;
+
+ // How many seconds to try loading tiles before timing out
+ private readonly TimeSpan _tileLoadingWaitTimeout = TimeSpan.FromSeconds(5);
+
+ /// Gets the parent ARGeospatialCreatorOrigin object.
+ public abstract ARGeospatialCreatorOrigin Origin { get; }
+
+ ///
+ /// Whether or not physics meshes are enabled for the tileset to allow collision testing.
+ ///
+ /// True if physics meshes are enabled for the tileset.
+ public abstract bool GetPhysicsMeshesEnabled();
+
+ ///
+ /// Used to enable or disable physics meshes on the tileset.
+ ///
+ /// If true, tileset meshes will allow collision testing.
+ public abstract void SetPhysicsMeshesEnabled(bool enable);
+
+ ///
+ /// Returns what percentage of Tiles have loaded in the current view.
+ ///
+ /// Percentage (0.0 to 100.0) of tiles loaded in the current view.
+ public abstract float ComputeTilesetLoadProgress();
+
+ ///
+ /// Verifies whether a collider belongs to a tile in the tileset.
+ ///
+ /// The collider to be checked.
+ /// True if the collider belongs to a tile.
+ public abstract bool IsTileCollider(Collider collider);
+
+#if UNITY_EDITOR
+ ///
+ /// Asynchronously gets the terrain or rooftop altitude at the given lat and lng.
+ /// This method ensures that physics are enabled on the tileset and waits for the
+ /// tiles to load before computing the altitude.
+ ///
+ /// The latitude at which to sample the altitude.
+ /// The longitude at which to sample the altitude.
+ ///
+ /// Tuple with "success" and "terrainAltitude" named elements.
+ /// "success": True if the altitude was successfully calculated.
+ /// "terrainAltitude": Altitude of the terrain at lat/lng or 0.0 if calculations failed.
+ ///
+ ///
+ /// If disabled, this method will enable physics meshes on the tiles during its execution,
+ /// and it will revert the setting back to its previous value before returning.
+ /// The tileset will reload all its tiles each time this setting is changed.
+ ///
+ public virtual async Task<(bool success, double terrainAltitude)>
+ CalcTileAltitudeWGS84Async(double lat, double lng)
+ {
+ if (Origin?._originPoint == null)
+ {
+ return (false, 0.0);
+ }
+
+ // Enable physics meshes on the tileset to allow the raycast to hit
+ bool previousPhysicsSetting = GetPhysicsMeshesEnabled();
+ SetPhysicsMeshesEnabled(true);
+
+ // Wait an initial interval of at least one frame before computing tile load progress
+ // Otherwise, you will get 100% loaded because previous tiles haven't unloaded
+ await Task.Delay(_tileLoadingWaitInterval);
+
+ // Wait until all tiles have loaded or we've hit a timeout
+ DateTime waitStartTime = DateTime.UtcNow;
+ while ((ComputeTilesetLoadProgress() < 99.9f)
+ && (DateTime.UtcNow - waitStartTime < _tileLoadingWaitTimeout))
+ {
+ await Task.Delay(_tileLoadingWaitInterval);
+ }
+
+ // TODO: (b/319861940) improve accuracy of sampled altitude.
+ (bool hitSucceeded, double hitAltitude) = CalcTileAltitudeWGS84(lat, lng);
+
+ // Revert the physics meshes on the tileset to the previous setting
+ SetPhysicsMeshesEnabled(previousPhysicsSetting);
+
+ return (hitSucceeded, hitAltitude);
+ }
+
+ /// Gets the terrain or rooftop altitude at the given lat and lng.
+ /// The latitude at which to sample the altitude.
+ /// The longitude at which to sample the altitude.
+ ///
+ /// Tuple with "success" and "terrainAltitude" named elements.
+ /// "success": True if the altitude was successfully calculated.
+ /// "terrainAltitude": Altitude of the terrain at lat/lng or 0.0 if calculations failed.
+ ///
+ ///
+ /// Calculation can fail if the tiles haven't had time to load, if the tiles don't have
+ /// physics meshes enabled, or if the target tile is out of the camera's view while
+ /// Frustum Culling is enabled. Sampled altitude can be inaccurate if high precision
+ /// LODs haven't loaded for the tiles (ex: because the tile is far from the camera).
+ /// For accurate results, have the desired anchor position well within the camera view.
+ ///
+ public virtual (bool success, double terrainAltitude)
+ CalcTileAltitudeWGS84(double lat, double lng)
+ {
+ GeoCoordinate originPoint = Origin?._originPoint;
+ Vector3 originUnityCoord = Origin ? Origin.gameObject.transform.position: Vector3.zero;
+ if (originPoint == null)
+ {
+ return (false, 0.0);
+ }
+
+ // Make a high point where the ray will originate (above any possible terrain)
+ GeoCoordinate highGeoCoord =
+ new GeoCoordinate(lat, lng, GeoMath.HighestElevationOnEarth);
+ Vector3 rayOrigin = GeoMath.GeoCoordinateToUnityWorld(
+ highGeoCoord, originPoint, originUnityCoord);
+
+ // Make a low point at zero altitude where the ray will be cast towards
+ GeoCoordinate lowGeoCoord = new GeoCoordinate(lat, lng, 0.0);
+ Vector3 rayTarget = GeoMath.GeoCoordinateToUnityWorld(
+ lowGeoCoord, originPoint, originUnityCoord);
+
+ // Make a vector that points from the high point to the low point
+ Vector3 rayDirection = Vector3.Normalize(rayTarget - rayOrigin);
+
+ // Retrieve the highest altitude tile hit
+ bool hitSucceeded = false;
+ double hitAltitude = double.MinValue;
+ RaycastHit[] hits = Physics.RaycastAll(rayOrigin, rayDirection);
+ foreach (RaycastHit hit in hits)
+ {
+ if (IsTileCollider(hit.collider))
+ {
+ GeoCoordinate hitPoint = GeoMath.UnityWorldToGeoCoordinate(
+ hit.point, originPoint, originUnityCoord);
+ hitSucceeded = true;
+ hitAltitude = Math.Max(hitPoint.Altitude, hitAltitude);
+ }
+ }
+
+ // If there was no hit, return an altitude of zero
+ hitAltitude = hitSucceeded ? hitAltitude : 0.0;
+
+ return (hitSucceeded, hitAltitude);
+ }
+#endif // UNITY_EDITOR
+ }
+}
diff --git a/Runtime/GeospatialCreatorRuntime/Scripts/Internal/Origin3DTilesetAdapter.cs.meta b/Runtime/GeospatialCreatorRuntime/Scripts/Internal/Origin3DTilesetAdapter.cs.meta
new file mode 100644
index 0000000..c61eff6
--- /dev/null
+++ b/Runtime/GeospatialCreatorRuntime/Scripts/Internal/Origin3DTilesetAdapter.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4184a3ae46144475a98ea52885c2ec37
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Plugins/ARPresto.aar b/Runtime/Plugins/ARPresto.aar
index f490545..fed7f66 100644
Binary files a/Runtime/Plugins/ARPresto.aar and b/Runtime/Plugins/ARPresto.aar differ
diff --git a/Runtime/Plugins/arcore_client.aar b/Runtime/Plugins/arcore_client.aar
index e4c5c50..f7e32a5 100644
Binary files a/Runtime/Plugins/arcore_client.aar and b/Runtime/Plugins/arcore_client.aar differ
diff --git a/Runtime/Scripts/ARAnchorManagerExtensions.cs b/Runtime/Scripts/ARAnchorManagerExtensions.cs
index 49f080b..9b23854 100644
--- a/Runtime/Scripts/ARAnchorManagerExtensions.cs
+++ b/Runtime/Scripts/ARAnchorManagerExtensions.cs
@@ -776,5 +776,19 @@ public static ResolveAnchorOnTerrainPromise ResolveAnchorOnTerrainAsync(
return new ResolveAnchorOnTerrainPromise(future);
}
+
+ ///
+ /// Logs that a Geospatial Creator Anchor has been resolved into a Geospatial Anchor.
+ /// This call only serves to log the anchor creation for analytics and debugging purposes.
+ /// It does not run any logic related to creating the anchor.
+ ///
+ /// The instance.
+ /// The type of anchor that was created.
+ internal static void ReportCreateGeospatialCreatorAnchor(
+ this ARAnchorManager anchorManager, ApiGeospatialAnchorType anchorType)
+ {
+ EarthApi.ReportCreateGeospatialCreatorAnchor(
+ ARCoreExtensions._instance.currentARCoreSessionHandle, anchorType);
+ }
}
}
diff --git a/Runtime/Scripts/ARCoreExtensions.cs b/Runtime/Scripts/ARCoreExtensions.cs
index d3e2a23..0cd4645 100644
--- a/Runtime/Scripts/ARCoreExtensions.cs
+++ b/Runtime/Scripts/ARCoreExtensions.cs
@@ -27,6 +27,7 @@
namespace Google.XR.ARCoreExtensions
{
using System;
+ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Google.XR.ARCoreExtensions.Internal;
@@ -123,6 +124,11 @@ public delegate int OnChooseXRCameraConfigurationEvent(
List supportedConfigurations);
#if UNITY_ANDROID
+ // The max number of frames we will wait for a valid session handle to report analytics.
+ internal const int _frameTimeoutForSessionHandle = 60;
+
+ private bool _geospatialCreatorPlatformLoggedOnce = false;
+
internal const int _androidSSDKVersion = 31;
private static AndroidJavaClass _versionInfo;
@@ -227,9 +233,16 @@ public void OnEnable()
{
_arCoreCameraSubsystem.beforeGetCameraConfiguration += BeforeGetCameraConfiguration;
}
-#endif // UNITY_ANDROID
+ // TODO: (b/308463770) - Support Geospatial Creator Platform analytics on iOS.
+ if (_geospatialCreatorPlatformLoggedOnce == false)
+ {
+ StartCoroutine(ReportGeospatialCreatorPlatformWithDelay());
+ _geospatialCreatorPlatformLoggedOnce = true;
+ }
+#endif // UNITY_ANDROID
#if !UNITY_IOS || ARCORE_EXTENSIONS_IOS_SUPPORT
+ // TODO: (b/308163258) - EngineType isn't set bc session handle is usually invalid here
if (Session != null && currentARCoreSessionHandle != IntPtr.Zero && !_engineTypeLogged)
{
SessionApi.ReportEngineType(currentARCoreSessionHandle);
@@ -540,6 +553,32 @@ private void SelectCameraConfig()
CameraManager.currentConfiguration = configurations[configIndex];
}
}
+
+ private IEnumerator ReportGeospatialCreatorPlatformWithDelay()
+ {
+ // TODO: (b/308463770) - Support Geospatial Creator Platform analytics on iOS.
+#if !UNITY_IOS || GEOSPATIAL_IOS_SUPPORT
+ // Wait a few frames until the session handle is valid
+ int frameCount = 0;
+ while (currentARCoreSessionHandle == IntPtr.Zero &&
+ frameCount < _frameTimeoutForSessionHandle)
+ {
+ yield return null;
+ frameCount++;
+ }
+
+ ApiGeospatialCreatorPlatform geospatialCreatorPlatform =
+#if ARCORE_INTERNAL_GEOSPATIAL_CREATOR_ENABLED
+ ApiGeospatialCreatorPlatform.ArCoreExtensionsUnity;
+#else
+ ApiGeospatialCreatorPlatform.Disabled;
+#endif // ARCORE_INTERNAL_GEOSPATIAL_CREATOR_ENABLED
+
+ EarthApi.ReportGeospatialCreatorPlatform(currentARCoreSessionHandle,
+ geospatialCreatorPlatform);
+#endif // !UNITY_IOS || GEOSPATIAL_IOS_SUPPORT
+ yield return null;
+ }
#endif // UNITY_ANDROID
}
}
diff --git a/Runtime/Scripts/AREarthManager.cs b/Runtime/Scripts/AREarthManager.cs
index 02c1f61..e967ea5 100644
--- a/Runtime/Scripts/AREarthManager.cs
+++ b/Runtime/Scripts/AREarthManager.cs
@@ -157,9 +157,6 @@ public static VpsAvailabilityPromise CheckVpsAvailabilityAsync(double latitude,
(sessionHandle == IntPtr.Zero)
? IntPtr.Zero
: FutureApi.CheckVpsAvailabilityAsync(sessionHandle, latitude, longitude);
-#if UNITY_ANDROID
- ARPrestoApi.SetSessionRequired(false);
-#endif
return new VpsAvailabilityPromise(future);
}
diff --git a/Runtime/Scripts/GeospatialPose.cs b/Runtime/Scripts/GeospatialPose.cs
index 33c8a37..b496562 100644
--- a/Runtime/Scripts/GeospatialPose.cs
+++ b/Runtime/Scripts/GeospatialPose.cs
@@ -142,7 +142,7 @@ public struct GeospatialPose
public double HorizontalAccuracy;
///
- /// Estimated horizontal accuracy in meters.
+ /// Estimated vertical accuracy in meters.
///
/// We define vertical accuracy as the radius of the 68th percentile confidence level around
/// the estimated altitude. In other words, there is a 68% probability that the true
diff --git a/Runtime/Scripts/Internal/Types/ApiGeospatialAnchorType.cs b/Runtime/Scripts/Internal/Types/ApiGeospatialAnchorType.cs
new file mode 100644
index 0000000..3e35a31
--- /dev/null
+++ b/Runtime/Scripts/Internal/Types/ApiGeospatialAnchorType.cs
@@ -0,0 +1,30 @@
+//-----------------------------------------------------------------------
+//
+//
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+//-----------------------------------------------------------------------
+
+namespace Google.XR.ARCoreExtensions.Internal
+{
+ internal enum ApiGeospatialAnchorType
+ {
+ Unknown = 0,
+ WGS84 = 1,
+ Terrain = 2,
+ Rooftop = 3,
+ }
+}
diff --git a/Runtime/Scripts/Internal/Types/ApiGeospatialAnchorType.cs.meta b/Runtime/Scripts/Internal/Types/ApiGeospatialAnchorType.cs.meta
new file mode 100644
index 0000000..14d8622
--- /dev/null
+++ b/Runtime/Scripts/Internal/Types/ApiGeospatialAnchorType.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0bb7bfa0b8e714af88f6ca2495764f21
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Scripts/Internal/Types/ApiGeospatialCreatorPlatform.cs b/Runtime/Scripts/Internal/Types/ApiGeospatialCreatorPlatform.cs
new file mode 100644
index 0000000..29bac6a
--- /dev/null
+++ b/Runtime/Scripts/Internal/Types/ApiGeospatialCreatorPlatform.cs
@@ -0,0 +1,29 @@
+//-----------------------------------------------------------------------
+//
+//
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+//-----------------------------------------------------------------------
+
+namespace Google.XR.ARCoreExtensions.Internal
+{
+ internal enum ApiGeospatialCreatorPlatform
+ {
+ // 0, 2, and 4 are not supported values for Unity.
+ Disabled = 1,
+ ArCoreExtensionsUnity = 3,
+ }
+}
diff --git a/Runtime/Scripts/Internal/Types/ApiGeospatialCreatorPlatform.cs.meta b/Runtime/Scripts/Internal/Types/ApiGeospatialCreatorPlatform.cs.meta
new file mode 100644
index 0000000..2fd664e
--- /dev/null
+++ b/Runtime/Scripts/Internal/Types/ApiGeospatialCreatorPlatform.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 31db4cb898b7e41ccb66ea866a525763
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Scripts/Internal/Wrappers/EarthApi.cs b/Runtime/Scripts/Internal/Wrappers/EarthApi.cs
index 1140c31..cacbcd8 100644
--- a/Runtime/Scripts/Internal/Wrappers/EarthApi.cs
+++ b/Runtime/Scripts/Internal/Wrappers/EarthApi.cs
@@ -102,6 +102,40 @@ public static IntPtr AddAnchor(IntPtr sessionHandle, IntPtr earthHandle,
return anchorHandle;
}
+ public static void ReportCreateGeospatialCreatorAnchor(
+ IntPtr session, ApiGeospatialAnchorType anchorType)
+ {
+ // TODO: (b/308463770) - Support anchor creation analytics on iOS.
+#if UNITY_ANDROID
+#if !UNITY_IOS || GEOSPATIAL_IOS_SUPPORT
+ ApiArStatus status =
+ ExternApi.ArEarth_reportCreateGeospatialCreatorAnchor(session, anchorType);
+ if (status != ApiArStatus.Success)
+ {
+ Debug.LogErrorFormat(
+ "Failed to log Geospatial Creator Anchor Creation, status '{0}'", status);
+ }
+#endif
+#endif
+ }
+
+ public static void ReportGeospatialCreatorPlatform(
+ IntPtr session, ApiGeospatialCreatorPlatform platform)
+ {
+ // TODO: (b/308463770) - Support Geospatial Creator Platform analytics on iOS.
+#if UNITY_ANDROID
+#if !UNITY_IOS || GEOSPATIAL_IOS_SUPPORT
+ ApiArStatus status =
+ ExternApi.ArEarth_reportGeospatialCreatorPlatform(session, platform);
+ if (status != ApiArStatus.Success)
+ {
+ Debug.LogErrorFormat(
+ "Failed to log Geospatial Creator Platform, status '{0}'", status);
+ }
+#endif
+#endif
+ }
+
public static IntPtr ResolveAnchorOnTerrain(IntPtr sessionHandle, IntPtr earthHandle,
double latitude, double longitude, double altitudeAboveTerrain, Quaternion eunRotation)
{
@@ -235,6 +269,17 @@ public static extern ApiArStatus ArEarth_acquireNewAnchor(
IntPtr session, IntPtr earth, double latitude, double longitude,
double altitude, ref ApiQuaternion eus_quaternion_4, ref IntPtr out_anchor);
+ // TODO: (b/308463770) - Support anchor creation analytics on iOS.
+#if UNITY_ANDROID
+ [EarthImport(ApiConstants.ARCoreNativeApi)]
+ public static extern ApiArStatus ArEarth_reportCreateGeospatialCreatorAnchor(
+ IntPtr session, ApiGeospatialAnchorType anchorType);
+
+ [EarthImport(ApiConstants.ARCoreNativeApi)]
+ public static extern ApiArStatus ArEarth_reportGeospatialCreatorPlatform(
+ IntPtr session, ApiGeospatialCreatorPlatform platform);
+#endif // UNITY_ANDROID
+
[EarthImport(ApiConstants.ARCoreNativeApi)]
public static extern ApiArStatus ArEarth_resolveAndAcquireNewAnchorOnTerrain(
IntPtr session, IntPtr earth, double latitude, double longitude,
diff --git a/Runtime/Scripts/VersionInfo.cs b/Runtime/Scripts/VersionInfo.cs
index b90cc0e..2d0c66d 100644
--- a/Runtime/Scripts/VersionInfo.cs
+++ b/Runtime/Scripts/VersionInfo.cs
@@ -28,6 +28,6 @@ public class VersionInfo
///
/// The current ARCore Extensions package version.
///
- public static readonly string Version = "1.41.0";
+ public static readonly string Version = "1.42.0";
}
}
diff --git a/Samples~/Geospatial/Scenes/GeospatialArf5.unity b/Samples~/Geospatial/Scenes/GeospatialArf5.unity
index d9bface..c0936c1 100644
--- a/Samples~/Geospatial/Scenes/GeospatialArf5.unity
+++ b/Samples~/Geospatial/Scenes/GeospatialArf5.unity
@@ -2602,7 +2602,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3}
m_Name:
m_EditorClassIdentifier:
- m_SendPointerHoverToParent: 1
m_MoveRepeatDelay: 0.5
m_MoveRepeatRate: 0.1
m_XRTrackingOrigin: {fileID: 596133978}
diff --git a/Samples~/Geospatial/Scripts/GeospatialController.cs b/Samples~/Geospatial/Scripts/GeospatialController.cs
index 6e7a969..e9a087c 100644
--- a/Samples~/Geospatial/Scripts/GeospatialController.cs
+++ b/Samples~/Geospatial/Scripts/GeospatialController.cs
@@ -25,6 +25,22 @@
#warning For AR Foundation 5.X compatibility, define the ARCORE_USE_ARF_5 symbol
#endif
+#if !ENABLE_LEGACY_INPUT_MANAGER
+// Input.location will not work at runtime with out the old input system.
+// Given that sample has not been ported to support new input
+// Check that Project Settings > Player > Other Settings > Active Input Handling
+// is set to Both or Input Manager (Old)
+#error Input.location API requires Active Input Handling to be set to Input Manager (Old) or Both
+#endif
+
+#if !ENABLE_INPUT_SYSTEM && ARCORE_USE_ARF_5
+// The camera's pose driver in ARF5 needs Input System (New) but given we need Input Manager
+// (Old) for Input.location (see above) ARF5 needs both.
+// Check that Project Settings > Player > Other Settings > Active Input Handling
+// is set to Both
+#error The camera's pose driver needs Input System (New) so set Active Input Handling to Both
+#endif
+
namespace Google.XR.ARCoreExtensions.Samples.Geospatial
{
using System;
diff --git a/Samples~/PersistentCloudAnchors/Scenes/PersistentCloudAnchorsArf5.unity b/Samples~/PersistentCloudAnchors/Scenes/PersistentCloudAnchorsArf5.unity
index 39df4bd..6a7ad11 100644
--- a/Samples~/PersistentCloudAnchors/Scenes/PersistentCloudAnchorsArf5.unity
+++ b/Samples~/PersistentCloudAnchors/Scenes/PersistentCloudAnchorsArf5.unity
@@ -7349,7 +7349,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3}
m_Name:
m_EditorClassIdentifier:
- m_SendPointerHoverToParent: 1
m_MoveRepeatDelay: 0.5
m_MoveRepeatRate: 0.1
m_XRTrackingOrigin: {fileID: 1520494398}
diff --git a/Samples~/PersistentCloudAnchors/Scripts/PersistentCloudAnchorsController.cs b/Samples~/PersistentCloudAnchors/Scripts/PersistentCloudAnchorsController.cs
index 3372db4..78ce8fa 100644
--- a/Samples~/PersistentCloudAnchors/Scripts/PersistentCloudAnchorsController.cs
+++ b/Samples~/PersistentCloudAnchors/Scripts/PersistentCloudAnchorsController.cs
@@ -27,6 +27,13 @@
#warning For AR Foundation 5.X compatibility, define the ARCORE_USE_ARF_5 symbol
#endif
+#if !(ENABLE_INPUT_SYSTEM && ENABLE_LEGACY_INPUT_MANAGER) && ARCORE_USE_ARF_5
+// The camera's pose driver in ARF5 needs Input System (New) but sample has not been ported to
+// support new input so make sure Settings > Player > Other Settings > Active Input Handling
+// is set to Both
+#error The cloud anchores sample needs Active Input Handling set to Both
+#endif
+
namespace Google.XR.ARCoreExtensions.Samples.PersistentCloudAnchors
{
using System;
diff --git a/package.json b/package.json
index a8026a5..febd61d 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "com.google.ar.core.arfoundation.extensions",
"displayName": "ARCore Extensions",
- "version": "1.41.0",
+ "version": "1.42.0",
"unity": "2019.4",
"description": "Google ARCore Extensions for AR Foundation. This package provides access to ARCore features not covered by AR Foundation's cross platform API.",
"author":