/// <summary> /// Queues queries for all known models around the requested bounds /// </summary> /// <param name="queryBounds"></param> public void QueueQueriesInBounds(ObjectAnchorsBoundingBox queryBounds) { List <ObjectQuery> nextQuerySet = new List <ObjectQuery>(); SpatialGraph.SpatialGraphCoordinateSystem?coordinateSystem = ObjectAnchorsWorldManager.GlobalCoordinateSystem; if (!coordinateSystem.HasValue) { Debug.LogError("no coordinate system?"); return; } foreach (TrackableObjectData tod in _trackableObjectDataLoader.TrackableObjects) { ObjectQuery nextQuery = _objectAnchorsService.CreateObjectQuery(tod.ModelId); nextQuery.MaxScaleChange = MaxScaleChange; if (tod.UseCustomParameters) { nextQuery.MinSurfaceCoverage = tod.MinSurfaceCoverage; nextQuery.IsExpectedToBeStandingOnGroundPlane = tod.IsExpectedToBeStandingOnGroundPlane; nextQuery.ExpectedMaxVerticalOrientationInDegrees = tod.ExpectedMaxVerticalOrientationInDegrees; nextQuery.MaxScaleChange = tod.MaxScaleChange; } else { nextQuery.MinSurfaceCoverage *= CoverageThresholdFactor; nextQuery.ExpectedMaxVerticalOrientationInDegrees = AllowedVerticalOrientationInDegrees; } nextQuery.SearchAreas.Add(ObjectSearchArea.FromOrientedBox( coordinateSystem.Value, queryBounds.ToOuSdk()) ); nextQuerySet.Add(nextQuery); } _queryQueue.Enqueue(new Tuple <ObjectAnchorsBoundingBox, IEnumerable <ObjectQuery> >(queryBounds, nextQuerySet)); Debug.Log($"{Time.frameCount} next query size {nextQuerySet.Count} query queue size {_queryQueue.Count} max scale change {MaxScaleChange} AllowedVerticalOrientationInDegrees {AllowedVerticalOrientationInDegrees}"); }
public async Task <bool> LoadObjectModelsAsync(string modelPath) { IObjectAnchorsService objectAnchorsService = ObjectAnchorsService.GetService(); Debug.Log($"{Application.persistentDataPath} {objectAnchorsService != null}"); string[] ouFiles = Directory.GetFiles(modelPath, "*.ou", SearchOption.AllDirectories); foreach (var file in ouFiles) { // Represent a model by TrackableObject, and load its model into OU service. var trackableObject = new TrackableObjectData(); trackableObject.ModelFilePath = file.Replace('/', '\\'); trackableObject.ModelId = await objectAnchorsService.AddObjectModelAsync(trackableObject.ModelFilePath); if (trackableObject.ModelId != Guid.Empty) { // Query the default coverage threshold from this object model. ObjectQuery query = objectAnchorsService.CreateObjectQuery(trackableObject.ModelId); trackableObject.MinSurfaceCoverageFromObjectModel = query.MinSurfaceCoverage; trackableObject.ModelMesh = GenerateMesh(trackableObject.ModelId); trackableObject.logicalBoundingBox = objectAnchorsService.GetModelBoundingBox(trackableObject.ModelId); _trackableObjects.Add(trackableObject); _modelIdToTrackableObject.Add(trackableObject.ModelId, trackableObject); Debug.Log($"Loaded Model\n{trackableObject}"); } else { Debug.LogError($"failed to load model {trackableObject.ModelFilePath}"); } } if (_trackableObjects.Count > 0) { ModelsLoaded?.Invoke(this, EventArgs.Empty); } return(_trackableObjects.Count > 0); }
private Dictionary <Guid, ObjectQueryState> InitializeObjectQueries() { var objectQueries = new Dictionary <Guid, ObjectQueryState>(); foreach (var modelId in _objectAnchorsService.ModelIds) { // // Create a query and set the parameters. // var queryState = new GameObject($"ObjectQueryState for model {modelId}").AddComponent <ObjectQueryState>(); queryState.Query = _objectAnchorsService.CreateObjectQuery(modelId, ObservationMode); if (ShowEnvironmentObservations) { queryState.EnvironmentMaterial = EnvironmentMaterial; } objectQueries.Add(modelId, queryState); } return(objectQueries); }
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; foreach (var modelId in _objectAnchorsService.ModelIds) { // // 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); // // Create a query and set the parameters. // var query = _objectAnchorsService.CreateObjectQuery(modelId); Debug.Assert(query != null); if (SearchAreaAsBoundingBox) { // 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.ToOuSdk())); } if (SearchAreaAsFieldOfView) { 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.ToOuSdk())); } if (SearchAreaAsSphere) { // 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.ToOuSdk())); } 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())); }