Ejemplo n.º 1
0
    private void TrySearchObject()
    {
        if (Interlocked.CompareExchange(ref _detectionCompleted, 0, 1) == 1)
        {
            if (_cachedCameraMain == null)
            {
                _cachedCameraMain = Camera.main;
            }

            var cameraLocation = new ObjectAnchorsLocation
            {
                Position    = _cachedCameraMain.transform.position,
                Orientation = _cachedCameraMain.transform.rotation,
            };

            var coordinateSystem = ObjectAnchorsWorldManager.GlobalCoordinateSystem;

            Task.Run(async() =>
            {
                try
                {
                    await DetectObjectAsync(coordinateSystem, cameraLocation);
                }
                catch (Exception ex)
                {
                    UnityEngine.WSA.Application.InvokeOnAppThread(() =>
                    {
                        TextLogger.Log($"Detection failed. Exception message: {ex.ToString()}");
                    }, false);
                }

                Interlocked.CompareExchange(ref _detectionCompleted, 1, 0);
            });
        }
    }
Ejemplo n.º 2
0
    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()));
    }