Esempio n. 1
0
        /// <summary>
        /// Handles the SurfaceObserver's OnSurfaceChanged event.
        /// </summary>
        /// <param name="id">The identifier assigned to the surface which has changed.</param>
        /// <param name="changeType">The type of change that occurred on the surface.</param>
        /// <param name="bounds">The bounds of the surface.</param>
        /// <param name="updateTime">The date and time at which the change occurred.</param>
        private void SurfaceObserver_OnSurfaceChanged(SurfaceId id, SurfaceChange changeType, Bounds bounds, DateTime updateTime)
        {
            var soundManager = GameObject.Find("Audio Source");

            HoloToolkit.Unity.TextToSpeech t2s = soundManager.GetComponent <HoloToolkit.Unity.TextToSpeech>();
            t2s.Voice = HoloToolkit.Unity.TextToSpeechVoice.Zira;
            t2s.StartSpeaking("Observer 1");
            // Verify that the client of the Surface Observer is expecting updates.
            if (ObserverState != ObserverStates.Running)
            {
                return;
            }

            switch (changeType)
            {
            case SurfaceChange.Added:
            case SurfaceChange.Updated:
                surfaceWorkQueue.Enqueue(id);
                break;

            case SurfaceChange.Removed:
                SurfaceObject?removedSurface = RemoveSurfaceIfFound(id.handle, destroyGameObject: false);
                if (removedSurface != null)
                {
                    ReclaimSurface(removedSurface.Value);
                }
                break;

            default:
                Debug.LogErrorFormat("Unexpected {0} value: {1}.", changeType.GetType(), changeType);
                break;
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Iterator block, analyzes surface meshes to find planes and create new 3D cubes to represent each plane.
        /// </summary>
        /// <returns>Yield result.</returns>
        private IEnumerator MakePlanesRoutine()
        {
            // Remove any previously existing planes, as they may no longer be valid.
            for (int index = 0; index < ActivePlanes.Count; index++)
            {
                Destroy(ActivePlanes[index]);
            }

            // Pause our work, and continue on the next frame.
            yield return(null);

            float start = Time.realtimeSinceStartup;

            ActivePlanes.Clear();

            // Get the latest Mesh data from the Spatial Mapping Manager.
            List <PlaneFinding.MeshData> meshData = new List <PlaneFinding.MeshData>();
            List <MeshFilter>            filters  = SpatialMappingManager.Instance.GetMeshFilters();

            for (int index = 0; index < filters.Count; index++)
            {
                MeshFilter filter = filters[index];
                if (filter != null && filter.sharedMesh != null)
                {
                    // fix surface mesh normals so we can get correct plane orientation.
                    filter.mesh.RecalculateNormals();
                    meshData.Add(new PlaneFinding.MeshData(filter));
                }

                if ((Time.realtimeSinceStartup - start) > FrameTime)
                {
                    // Pause our work, and continue to make more PlaneFinding objects on the next frame.
                    yield return(null);

                    start = Time.realtimeSinceStartup;
                }
            }

            // Pause our work, and continue on the next frame.
            yield return(null);

#if !UNITY_EDITOR && UNITY_WSA
            // When not in the unity editor we can use a cool background task to help manage FindPlanes().
            Task <BoundedPlane[]> planeTask = Task.Run(() => PlaneFinding.FindPlanes(meshData, snapToGravityThreshold, MinArea));

            while (planeTask.IsCompleted == false)
            {
                yield return(null);
            }

            BoundedPlane[] planes = planeTask.Result;
#else
            // In the unity editor, the task class isn't available, but perf is usually good, so we'll just wait for FindPlanes to complete.
            BoundedPlane[] planes = PlaneFinding.FindPlanes(meshData, snapToGravityThreshold, MinArea);
#endif

            // Pause our work here, and continue on the next frame.
            yield return(null);

            start = Time.realtimeSinceStartup;

            float maxFloorArea   = 0.0f;
            float maxCeilingArea = 0.0f;
            FloorYPosition   = 0.0f;
            CeilingYPosition = 0.0f;
            float upNormalThreshold = 0.9f;

            if (SurfacePlanePrefab != null && SurfacePlanePrefab.GetComponent <SurfacePlane>() != null)
            {
                upNormalThreshold = SurfacePlanePrefab.GetComponent <SurfacePlane>().UpNormalThreshold;
            }

            // Find the floor and ceiling.
            // We classify the floor as the maximum horizontal surface below the user's head.
            // We classify the ceiling as the maximum horizontal surface above the user's head.
            var soundManager = GameObject.Find("Audio Source");
            HoloToolkit.Unity.TextToSpeech t2s = soundManager.GetComponent <HoloToolkit.Unity.TextToSpeech>();
            t2s.Voice = HoloToolkit.Unity.TextToSpeechVoice.Zira;
            t2s.StartSpeaking(planes.Length + "planes have been found");

            for (int i = 0; i < planes.Length; i++)
            {
                t2s.StartSpeaking("found plane " + i);

                BoundedPlane boundedPlane = planes[i];
                if (boundedPlane.Bounds.Center.y < 0 && boundedPlane.Plane.normal.y >= upNormalThreshold)
                {
                    maxFloorArea = Mathf.Max(maxFloorArea, boundedPlane.Area);
                    if (maxFloorArea == boundedPlane.Area)
                    {
                        FloorYPosition = boundedPlane.Bounds.Center.y;
                        t2s.StartSpeaking("found floor");
                    }
                }

                else if (boundedPlane.Bounds.Center.y > 0 && boundedPlane.Plane.normal.y <= -(upNormalThreshold))
                {
                    maxCeilingArea = Mathf.Max(maxCeilingArea, boundedPlane.Area);
                    if (maxCeilingArea == boundedPlane.Area)
                    {
                        CeilingYPosition = boundedPlane.Bounds.Center.y;
                    }
                }
            }
            t2s.StartSpeaking("finished finding floor");
            GameObject[] walls = GameObject.FindGameObjectsWithTag("staticWall");
            for (int i = 0; i < walls.Length; i++)
            {
                walls[i].transform.position.Set(walls[i].transform.position.x, FloorYPosition + 15.0f, walls[i].transform.position.z);
            }
            t2s.StartSpeaking("walls should be done");
            // Create SurfacePlane objects to represent each plane found in the Spatial Mapping mesh.
            for (int index = 0; index < planes.Length; index++)
            {
                GameObject   destinationPlane;
                BoundedPlane boundedPlane = planes[index];

                // Instantiate a SurfacePlane object, which will have the same bounds as our BoundedPlane object.
                if (SurfacePlanePrefab != null && SurfacePlanePrefab.GetComponent <SurfacePlane>() != null)
                {
                    destinationPlane = Instantiate(SurfacePlanePrefab);
                }
                else
                {
                    destinationPlane = GameObject.CreatePrimitive(PrimitiveType.Cube);
                    destinationPlane.AddComponent <SurfacePlane>();
                    destinationPlane.GetComponent <Renderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
                }

                destinationPlane.transform.parent = planesParent.transform;
                var surfacePlane = destinationPlane.GetComponent <SurfacePlane>();

                // Set the Plane property to adjust transform position/scale/rotation and determine plane type.
                surfacePlane.Plane = boundedPlane;

                SetPlaneVisibility(surfacePlane);

                if ((destroyPlanesMask & surfacePlane.PlaneType) == surfacePlane.PlaneType)
                {
                    DestroyImmediate(destinationPlane);
                }
                else
                {
                    // Set the plane to use the same layer as the SpatialMapping mesh.
                    destinationPlane.layer = SpatialMappingManager.Instance.PhysicsLayer;
                    ActivePlanes.Add(destinationPlane);
                }

                // If too much time has passed, we need to return control to the main game loop.
                if ((Time.realtimeSinceStartup - start) > FrameTime)
                {
                    // Pause our work here, and continue making additional planes on the next frame.
                    yield return(null);

                    start = Time.realtimeSinceStartup;
                }
            }

            Debug.Log("Finished making planes.");

            // We are done creating planes, trigger an event.
            EventHandler handler = MakePlanesComplete;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }

            makingPlanes = false;
        }