/// <summary>
        /// Sends the observations using the mesh data contained within the configured 3D model.
        /// </summary>
        private void SendMeshObjects()
        {
            if (!sendObservations)
            {
                return;
            }

            if (spatialMeshObject != null)
            {
                MeshFilter[] meshFilters = spatialMeshObject.GetComponentsInChildren <MeshFilter>();
                for (int i = 0; i < meshFilters.Length; i++)
                {
                    SpatialAwarenessMeshObject meshObject = SpatialAwarenessMeshObject.Create(
                        meshFilters[i].sharedMesh,
                        MeshPhysicsLayer,
                        $"Spatial Object Mesh {currentMeshId}",
                        currentMeshId,
                        ObservedObjectParent);

                    meshObject.GameObject.transform.localPosition = meshFilters[i].transform.position;
                    meshObject.GameObject.transform.localRotation = meshFilters[i].transform.rotation;

                    ApplyMeshMaterial(meshObject);

                    meshes.Add(currentMeshId, meshObject);

                    meshEventData.Initialize(this, currentMeshId, meshObject);
                    SpatialAwarenessSystem?.HandleEvent(meshEventData, OnMeshAdded);

                    currentMeshId++;
                }
            }

            sendObservations = false;
        }
        /// <summary>
        /// Removes an observation.
        /// </summary>
        private void RemoveMeshObject(int meshId)
        {
            if (meshes.TryGetValue(meshId, out SpatialAwarenessMeshObject meshObject))
            {
                // Remove the mesh object from the collection.
                meshes.Remove(meshId);
                if (meshObject != null)
                {
                    SpatialAwarenessMeshObject.Cleanup(meshObject);
                }

                // Send the mesh removed event
                meshEventData.Initialize(this, meshId, null);
                SpatialAwarenessSystem?.HandleEvent(meshEventData, OnMeshRemoved);
            }
        }
        /// <summary>
        /// Removes the <see cref="SpatialAwarenessMeshObject"/> associated with the specified id.
        /// </summary>
        /// <param name="id">The id of the mesh to be removed.</param>
        protected void RemoveMeshObject(int id)
        {
            SpatialAwarenessMeshObject mesh;

            if (meshes.TryGetValue(id, out mesh))
            {
                // Remove the mesh object from the collection.
                meshes.Remove(id);

                // Reclaim the mesh object for future use.
                ReclaimMeshObject(mesh);

                // Send the mesh removed event
                meshEventData.Initialize(this, id, null);
                SpatialAwarenessSystem?.HandleEvent(meshEventData, OnMeshRemoved);
            }
        }
Пример #4
0
        private void MeshGenerationAction(MeshGenerationResult meshGenerationResult)
        {
            if (!IsRunning)
            {
                return;
            }

            using (MeshGenerationActionPerfMarker.Auto())
            {
                if (outstandingMeshObject == null)
                {
                    Debug.LogWarning($"MeshGenerationAction called for mesh id {meshGenerationResult.MeshId} while no request was outstanding.");
                    return;
                }

                switch (meshGenerationResult.Status)
                {
                case MeshGenerationStatus.InvalidMeshId:
                case MeshGenerationStatus.Canceled:
                case MeshGenerationStatus.UnknownError:
                    outstandingMeshObject = null;
                    break;

                case MeshGenerationStatus.Success:
                    // Since there is only one outstanding mesh object, update the id to match
                    // the one received after baking.
                    SpatialAwarenessMeshObject meshObject = outstandingMeshObject;
                    meshObject.Id         = meshGenerationResult.MeshId.GetHashCode();
                    outstandingMeshObject = null;

                    // Apply the appropriate material to the mesh.
                    SpatialAwarenessMeshDisplayOptions displayOption = DisplayOption;
                    if (displayOption != SpatialAwarenessMeshDisplayOptions.None)
                    {
                        meshObject.Renderer.enabled        = true;
                        meshObject.Renderer.sharedMaterial = (displayOption == SpatialAwarenessMeshDisplayOptions.Visible) ?
                                                             VisibleMaterial :
                                                             OcclusionMaterial;
                        meshObject.Collider.material = PhysicsMaterial;
                    }
                    else
                    {
                        meshObject.Renderer.enabled = false;
                    }

                    // Recalculate the mesh normals if requested.
                    if (RecalculateNormals)
                    {
                        meshObject.Filter.sharedMesh.RecalculateNormals();
                    }

                    // Add / update the mesh to our collection
                    bool sendUpdatedEvent = false;
                    if (meshes.ContainsKey(meshObject.Id))
                    {
                        // Reclaim the old mesh object for future use.
                        ReclaimMeshObject(meshes[meshObject.Id]);
                        meshes.Remove(meshObject.Id);

                        sendUpdatedEvent = true;
                    }
                    meshes.Add(meshObject.Id, meshObject);

                    meshObject.GameObject.transform.parent = (ObservedObjectParent.transform != null) ? ObservedObjectParent.transform : null;

                    meshEventData.Initialize(this, meshObject.Id, meshObject);
                    if (sendUpdatedEvent)
                    {
                        SpatialAwarenessSystem?.HandleEvent(meshEventData, OnMeshUpdated);
                    }
                    else
                    {
                        SpatialAwarenessSystem?.HandleEvent(meshEventData, OnMeshAdded);
                    }
                    break;
                }
            }
        }
        /// <summary>
        /// Handles the SurfaceObserver's OnDataReady event.
        /// </summary>
        /// <param name="cookedData">Struct containing output data.</param>
        /// <param name="outputWritten">Set to true if output has been written.</param>
        /// <param name="elapsedCookTimeSeconds">Seconds between mesh cook request and propagation of this event.</param>
        private void SurfaceObserver_OnDataReady(SurfaceData cookedData, bool outputWritten, float elapsedCookTimeSeconds)
        {
            if (!IsRunning)
            {
                return;
            }

            if (outstandingMeshObject == null)
            {
                return;
            }

            if (!outputWritten)
            {
                ReclaimMeshObject(outstandingMeshObject);
                outstandingMeshObject = null;
                return;
            }

            // Since there is only one outstanding mesh object, update the id to match
            // the one received after baking.
            SpatialAwarenessMeshObject meshObject = outstandingMeshObject;

            meshObject.Id         = cookedData.id.handle;
            outstandingMeshObject = null;

            // Apply the appropriate material to the mesh.
            SpatialAwarenessMeshDisplayOptions displayOption = DisplayOption;

            if (displayOption != SpatialAwarenessMeshDisplayOptions.None)
            {
                meshObject.Renderer.enabled        = true;
                meshObject.Renderer.sharedMaterial = (displayOption == SpatialAwarenessMeshDisplayOptions.Visible) ?
                                                     VisibleMaterial :
                                                     OcclusionMaterial;
            }
            else
            {
                meshObject.Renderer.enabled = false;
            }

            // Recalculate the mesh normals if requested.
            if (RecalculateNormals)
            {
                meshObject.Filter.sharedMesh.RecalculateNormals();
            }

            // Add / update the mesh to our collection
            bool sendUpdatedEvent = false;

            if (meshes.ContainsKey(cookedData.id.handle))
            {
                // Reclaim the old mesh object for future use.
                ReclaimMeshObject(meshes[cookedData.id.handle]);
                meshes.Remove(cookedData.id.handle);

                sendUpdatedEvent = true;
            }
            meshes.Add(cookedData.id.handle, meshObject);

            meshObject.GameObject.transform.parent = (ObservedObjectParent.transform != null) ? ObservedObjectParent.transform : null;

            meshEventData.Initialize(this, cookedData.id.handle, meshObject);
            if (sendUpdatedEvent)
            {
                SpatialAwarenessSystem?.HandleEvent(meshEventData, OnMeshUpdated);
            }
            else
            {
                SpatialAwarenessSystem?.HandleEvent(meshEventData, OnMeshAdded);
            }
        }
Пример #6
0
        private void MeshGenerationAction(MeshGenerationResult meshGenerationResult)
        {
            if (!IsRunning)
            {
                return;
            }

            using (MeshGenerationActionPerfMarker.Auto())
            {
                if (outstandingMeshObject == null)
                {
                    Debug.LogWarning($"MeshGenerationAction called for mesh id {meshGenerationResult.MeshId} while no request was outstanding.");
                    return;
                }

                switch (meshGenerationResult.Status)
                {
                case MeshGenerationStatus.InvalidMeshId:
                case MeshGenerationStatus.Canceled:
                case MeshGenerationStatus.UnknownError:
                    outstandingMeshObject = null;
                    break;

                case MeshGenerationStatus.Success:
                    // Since there is only one outstanding mesh object, update the id to match
                    // the one received after baking.
                    SpatialAwarenessMeshObject meshObject = outstandingMeshObject;
                    meshObject.Id         = meshGenerationResult.MeshId.GetHashCode();
                    outstandingMeshObject = null;

                    // Check to see if this is a new or updated mesh.
                    bool isMeshUpdate = meshes.ContainsKey(meshObject.Id);

                    // We presume that if the display option is not occlusion, that we should
                    // default to the visible material.
                    // Note: We check explicitly for a display option of none later in this method.
                    Material material = (DisplayOption == SpatialAwarenessMeshDisplayOptions.Occlusion) ?
                                        OcclusionMaterial : VisibleMaterial;

                    // If this is a mesh update, we want to preserve the mesh's previous material.
                    material = isMeshUpdate ? meshes[meshObject.Id].Renderer.sharedMaterial : material;

                    // Apply the appropriate material.
                    meshObject.Renderer.sharedMaterial = material;

                    // Recalculate the mesh normals if requested.
                    if (RecalculateNormals)
                    {
                        meshObject.Filter.sharedMesh.RecalculateNormals();
                    }

                    // Check to see if the display option is set to none. If so, we disable
                    // the renderer.
                    meshObject.Renderer.enabled = (DisplayOption != SpatialAwarenessMeshDisplayOptions.None);

                    // Set the physics material
                    if (meshObject.Renderer.enabled)
                    {
                        meshObject.Collider.material = PhysicsMaterial;
                    }

                    // Add / update the mesh to our collection
                    if (isMeshUpdate)
                    {
                        // Reclaim the old mesh object for future use.
                        ReclaimMeshObject(meshes[meshObject.Id]);
                        meshes.Remove(meshObject.Id);
                    }
                    meshes.Add(meshObject.Id, meshObject);

                    meshObject.GameObject.transform.parent = (ObservedObjectParent.transform != null) ?
                                                             ObservedObjectParent.transform : null;

                    meshEventData.Initialize(this, meshObject.Id, meshObject);
                    if (isMeshUpdate)
                    {
                        SpatialAwarenessSystem?.HandleEvent(meshEventData, OnMeshUpdated);
                    }
                    else
                    {
                        SpatialAwarenessSystem?.HandleEvent(meshEventData, OnMeshAdded);
                    }
                    break;
                }
            }
        }
        /// <summary>
        /// Handles the SurfaceObserver's OnDataReady event.
        /// </summary>
        /// <param name="cookedData">Struct containing output data.</param>
        /// <param name="outputWritten">Set to true if output has been written.</param>
        /// <param name="elapsedCookTimeSeconds">Seconds between mesh cook request and propagation of this event.</param>
        private void SurfaceObserver_OnDataReady(SurfaceData cookedData, bool outputWritten, float elapsedCookTimeSeconds)
        {
            if (!IsRunning)
            {
                return;
            }

            using (OnDataReadyPerfMarker.Auto())
            {
                if (outstandingMeshObject == null)
                {
                    return;
                }

                if (!outputWritten)
                {
                    ReclaimMeshObject(outstandingMeshObject);
                    outstandingMeshObject = null;
                    return;
                }

                // Since there is only one outstanding mesh object, update the id to match
                // the one received after baking.
                SpatialAwarenessMeshObject meshObject = outstandingMeshObject;
                meshObject.Id         = cookedData.id.handle;
                outstandingMeshObject = null;

                // Check to see if this is a new or updated mesh.
                bool isMeshUpdate = meshes.ContainsKey(meshObject.Id);

                // We presume that if the display option is not occlusion, that we should
                // default to the visible material.
                // Note: We check explicitly for a display option of none later in this method.
                Material material = (DisplayOption == SpatialAwarenessMeshDisplayOptions.Occlusion) ?
                                    OcclusionMaterial : VisibleMaterial;

                // If this is a mesh update, we want to preserve the mesh's previous material.
                material = isMeshUpdate ? meshes[meshObject.Id].Renderer.sharedMaterial : material;

                // Apply the appropriate material.
                meshObject.Renderer.sharedMaterial = material;

                // Recalculate the mesh normals if requested.
                if (RecalculateNormals)
                {
                    meshObject.Filter.sharedMesh.RecalculateNormals();
                }

                // Check to see if the display option is set to none. If so, we disable
                // the renderer.
                meshObject.Renderer.enabled = (DisplayOption != SpatialAwarenessMeshDisplayOptions.None);

                // Set the physics material
                if (meshObject.Renderer.enabled)
                {
                    meshObject.Collider.material = PhysicsMaterial;
                }

                // Add / update the mesh to our collection
                if (isMeshUpdate)
                {
                    // Reclaim the old mesh object for future use.
                    ReclaimMeshObject(meshes[meshObject.Id]);
                    meshes.Remove(meshObject.Id);
                }
                meshes.Add(meshObject.Id, meshObject);

                // Preserve local transform relative to parent.
                meshObject.GameObject.transform.SetParent(ObservedObjectParent != null ?
                                                          ObservedObjectParent.transform: null, false);

                meshEventData.Initialize(this, meshObject.Id, meshObject);
                if (isMeshUpdate)
                {
                    SpatialAwarenessSystem?.HandleEvent(meshEventData, OnMeshUpdated);
                }
                else
                {
                    SpatialAwarenessSystem?.HandleEvent(meshEventData, OnMeshAdded);
                }
            }
        }
Пример #8
0
 /// <summary>
 /// Sends SceneObject Added event via <see cref="IMixedRealitySpatialAwarenessObservationHandler{T}"/>
 /// </summary>
 /// <param name="sceneObj">The <see cref="SpatialAwarenessSceneObject"/> being created</param>
 /// <param name="id">the id associated with the <paramref name="sceneObj"/></param>
 protected virtual void SendSceneObjectAdded(SpatialAwarenessSceneObject sceneObj, Guid id)
 {
     // Send the mesh removed event
     sceneEventData.Initialize(this, id, sceneObj);
     SpatialAwarenessSystem?.HandleEvent(sceneEventData, OnSceneObjectAdded);
 }