private async void Update() { // even though this is an 'async' function, unity will call Update each frame // even if a previous update is awaiting. if (_awaiting) { return; } Action nextAction; Tuple <ObjectAnchorsBoundingBox, IEnumerable <ObjectQuery> > nextQuery; if (UpdateQueue.TryDequeue(out nextAction)) { nextAction(); } else if (_queryQueue.TryDequeue(out nextQuery)) { _awaiting = true; QueryActive = true; ActiveQueries = nextQuery; await _objectAnchorsService.DetectObjectAsync(nextQuery.Item2.ToArray()); ActiveQueries = null; QueryActive = false; _awaiting = false; } else if (_objectAnchorsService.Status == ObjectAnchorsServiceStatus.Running) { if (TrackingStrategy == TrackingModeStrategy.Auto) { ManageLocatedObjectTrackingStates(); } // If nothing has been found, try another query. if (_instanceToTrackedObject.Count == 0 && ActiveDetectionStrategy == DetectionStrategy.Auto) { RefillGlobalQueryQueue(); } } }
private Task DetectObjectAsync(Microsoft.Azure.ObjectAnchors.SpatialGraph.SpatialGraphCoordinateSystem?coordinateSystem, ObjectAnchorsLocation cameraLocation) { // // Coordinate system may not be available at this time, try it later. // if (!coordinateSystem.HasValue) { return(Task.CompletedTask); } // // Get camera location and coordinate system. // var cameraForward = cameraLocation.Orientation * Vector3.forward; var estimatedTargetLocation = new ObjectAnchorsLocation { Position = cameraLocation.Position + cameraForward * SearchFrustumFarDistance * 0.5f, Orientation = Quaternion.Euler(0.0f, cameraLocation.Orientation.eulerAngles.y, 0.0f), }; // // Remove detected objects far away from the camera. // foreach (var instance in _objectAnchorsService.TrackingResults) { var location = instance.Location; if (location.HasValue) { var modelBbox = _objectAnchorsService.GetModelBoundingBox(instance.ModelId); Debug.Assert(modelBbox.HasValue); // Compute the coordinate of instance bounding box center in Unity world. var instancePosition = location.Value.Position + location.Value.Orientation * modelBbox.Value.Center; var offset = instancePosition - cameraLocation.Position; if (offset.magnitude > SearchFrustumFarDistance * 1.5f) { _objectAnchorsService.RemoveObjectInstance(instance.InstanceId); } } } // // Detect object(s) in field of view, bounding box, or sphere. // var objectQueries = new List <Microsoft.Azure.ObjectAnchors.ObjectQuery>(); var trackingResults = _objectAnchorsService.TrackingResults; lock (_objectQueries) foreach (var objectQuery in _objectQueries) { var modelId = objectQuery.Key; var query = objectQuery.Value.Query; // // Optionally skip a model detection if an instance is already found. // if (SearchSingleInstance) { if (trackingResults.Where(r => r.ModelId == modelId).Count() > 0) { continue; } } var modelBox = _objectAnchorsService.GetModelBoundingBox(modelId); Debug.Assert(modelBox.HasValue); query.SearchAreas.Clear(); switch (SearchAreaShape) { case SearchAreaKind.Box: { // Adapt bounding box size to model size. Note that Extents.z is model's height. float modelXYSize = new Vector2(modelBox.Value.Extents.x, modelBox.Value.Extents.y).magnitude; var boundingBox = new ObjectAnchorsBoundingBox { Center = estimatedTargetLocation.Position, Orientation = estimatedTargetLocation.Orientation, Extents = new Vector3(modelXYSize * SearchAreaScaleFactor, modelBox.Value.Extents.z * SearchAreaScaleFactor, modelXYSize * SearchAreaScaleFactor), }; query.SearchAreas.Add( Microsoft.Azure.ObjectAnchors.ObjectSearchArea.FromOrientedBox( coordinateSystem.Value, boundingBox.ToSpatialGraph())); break; } case SearchAreaKind.FieldOfView: { var fieldOfView = new ObjectAnchorsFieldOfView { Position = cameraLocation.Position, Orientation = cameraLocation.Orientation, FarDistance = SearchFrustumFarDistance, HorizontalFieldOfViewInDegrees = SearchFrustumHorizontalFovInDegrees, AspectRatio = SearchFrustumAspectRatio, }; query.SearchAreas.Add( Microsoft.Azure.ObjectAnchors.ObjectSearchArea.FromFieldOfView( coordinateSystem.Value, fieldOfView.ToSpatialGraph())); break; } case SearchAreaKind.Sphere: { // Adapt sphere radius to model size. float modelDiagonalSize = modelBox.Value.Extents.magnitude; var sphere = new ObjectAnchorsSphere { Center = estimatedTargetLocation.Position, Radius = modelDiagonalSize * 0.5f * SearchAreaScaleFactor, }; query.SearchAreas.Add( Microsoft.Azure.ObjectAnchors.ObjectSearchArea.FromSphere( coordinateSystem.Value, sphere.ToSpatialGraph())); break; } } objectQueries.Add(query); } // // Pause a while if detection is not required. // if (objectQueries.Count == 0) { Thread.Sleep(100); return(Task.CompletedTask); } // // Run detection. // // Add event to the queue. _objectAnchorsEventQueue.Enqueue( new ObjectAnchorsServiceEvent { Kind = ObjectAnchorsServiceEventKind.DetectionAttempted, Args = null }); return(_objectAnchorsService.DetectObjectAsync(objectQueries.ToArray())); }