/// <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(UnityEngine.VR.WSA.SurfaceId id, UnityEngine.VR.WSA.SurfaceChange changeType, Bounds bounds, DateTime updateTime)
        {
            // Verify that the client of the Surface Observer is expecting updates.
            if (ObserverState != ObserverStates.Running)
            {
                return;
            }

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

            case UnityEngine.VR.WSA.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;
            }
        }
Пример #2
0
        /// <summary>
        /// Calls GetMeshAsync to update the SurfaceData and re-activate the surface object when ready.
        /// </summary>
        /// <param name="id">Identifier of the SurfaceData object to update.</param>
        /// <param name="surface">The SurfaceData object to update.</param>
        private void QueueSurfaceDataRequest(UnityEngine.VR.WSA.SurfaceId id, GameObject surface)
        {
            UnityEngine.VR.WSA.SurfaceData surfaceData = new UnityEngine.VR.WSA.SurfaceData(id,
                                                                                            surface.GetComponent <MeshFilter>(),
                                                                                            surface.GetComponent <UnityEngine.VR.WSA.WorldAnchor>(),
                                                                                            surface.GetComponent <MeshCollider>(),
                                                                                            TrianglesPerCubicMeter,
                                                                                            true);

            surfaceWorkQueue.Enqueue(surfaceData);
        }
Пример #3
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(UnityEngine.VR.WSA.SurfaceId id, UnityEngine.VR.WSA.SurfaceChange changeType, Bounds bounds, System.DateTime updateTime)
        {
            // Verify that the client of the Surface Observer is expecting updates.
            if (ObserverState != ObserverStates.Running)
            {
                return;
            }

            GameObject surface;

            switch (changeType)
            {
            // Adding and updating are nearly identical.  The only difference is if a new gameobject to contain
            // the surface needs to be created.
            case UnityEngine.VR.WSA.SurfaceChange.Added:
            case UnityEngine.VR.WSA.SurfaceChange.Updated:
                // Check to see if the surface is known to the observer.
                // If so, we want to add it for cleanup after we get new meshes
                // We do this because Unity doesn't properly cleanup baked collision data
                if (surfaces.TryGetValue(id.handle, out surface))
                {
                    pendingCleanup.Add(id.handle, surface);
                    surfaces.Remove(id.handle);
                }

                // Get an available surface object ready to be used
                surface = GetSurfaceObject(id.handle, transform);

                // Add the surface to our dictionary of known surfaces so
                // we can interact with it later.
                surfaces.Add(id.handle, surface);

                // Add the request to create the mesh for this surface to our work queue.
                QueueSurfaceDataRequest(id, surface);
                break;

            case UnityEngine.VR.WSA.SurfaceChange.Removed:
                // Always process surface removal events.
                // This code can be made more thread safe
                if (surfaces.TryGetValue(id.handle, out surface))
                {
                    surfaces.Remove(id.handle);
                    CleanupSurface(surface);
                    RemoveSurfaceObject(surface, false);
                }
                break;
            }

            // Event
            if (SurfaceChanged != null)
            {
                SurfaceChanged(id, changeType, bounds, updateTime);
            }
        }
        /// <summary>
        /// Called once per frame.
        /// </summary>
        private void Update()
        {
            if ((ObserverState == ObserverStates.Running) && (outstandingMeshRequest == null))
            {
                if (surfaceWorkQueue.Count > 0)
                {
                    // We're using a simple first-in-first-out rule for requesting meshes, but a more sophisticated algorithm could prioritize
                    // the queue based on distance to the user or some other metric.
                    UnityEngine.VR.WSA.SurfaceId surfaceID = surfaceWorkQueue.Dequeue();

                    string surfaceName = ("Surface-" + surfaceID.handle);

                    SurfaceObject newSurface;
                    UnityEngine.VR.WSA.WorldAnchor worldAnchor;

                    if (spareSurfaceObject == null)
                    {
                        newSurface = CreateSurfaceObject(
                            mesh: null,
                            objectName: surfaceName,
                            parentObject: transform,
                            meshID: surfaceID.handle,
                            drawVisualMeshesOverride: false
                            );

                        worldAnchor = newSurface.Object.AddComponent <UnityEngine.VR.WSA.WorldAnchor>();
                    }
                    else
                    {
                        newSurface         = spareSurfaceObject.Value;
                        spareSurfaceObject = null;

                        Debug.Assert(!newSurface.Object.activeSelf);
                        newSurface.Object.SetActive(true);

                        Debug.Assert(newSurface.Filter.sharedMesh == null);
                        Debug.Assert(newSurface.Collider.sharedMesh == null);
                        newSurface.Object.name = surfaceName;
                        Debug.Assert(newSurface.Object.transform.parent == transform);
                        newSurface.ID = surfaceID.handle;
                        newSurface.Renderer.enabled = false;

                        worldAnchor = newSurface.Object.GetComponent <UnityEngine.VR.WSA.WorldAnchor>();
                        Debug.Assert(worldAnchor != null);
                    }

                    var surfaceData = new UnityEngine.VR.WSA.SurfaceData(
                        surfaceID,
                        newSurface.Filter,
                        worldAnchor,
                        newSurface.Collider,
                        TrianglesPerCubicMeter,
                        _bakeCollider: true
                        );

                    if (observer.RequestMeshAsync(surfaceData, SurfaceObserver_OnDataReady))
                    {
                        outstandingMeshRequest = newSurface;
                    }
                    else
                    {
                        Debug.LogErrorFormat("Mesh request for failed. Is {0} a valid Surface ID?", surfaceID.handle);

                        Debug.Assert(outstandingMeshRequest == null);
                        ReclaimSurface(newSurface);
                    }
                }
                else if ((Time.unscaledTime - updateTime) >= TimeBetweenUpdates)
                {
                    observer.Update(SurfaceObserver_OnSurfaceChanged);
                    updateTime = Time.unscaledTime;
                }
            }
        }