private void UpdateObservedSurfaces() { var surfaces = spatialSurfaceObserver.GetObservedSurfaces(); foreach (var spatialMeshObject in SpatialMeshObjects) { if (!surfaces.TryGetValue(spatialMeshObject.Key, out _)) { // We cannot call MeshInfo_Update since we no longer have a SpatialSurfaceInfo RaiseMeshRemoved(spatialMeshObject.Value); } } foreach (var surface in surfaces) { var surfaceBounds = surface.Value.TryGetBounds(WindowsMixedRealityUtilities.SpatialCoordinateSystem); var surfaceChangeStatus = SpatialMeshObjects.TryGetValue(surface.Key, out var spatialMeshObject) ? SpatialObserverStatus.Updated : SpatialObserverStatus.Added; if (surfaceBounds.HasValue) { MeshInfo_Update(surface.Value, surfaceChangeStatus); } else { if (surfaceChangeStatus == SpatialObserverStatus.Updated) { // Only remove if we've already created a mesh for it. MeshInfo_Update(surface.Value, SpatialObserverStatus.Removed); } } } }
/// <summary> /// Handler for RequestMeshAsync which will be used to set the material on the resulting mesh /// </summary> /// <param name="bakedData">The resulting data from the RequestMeshAsync call</param> /// <param name="outputWritten">Whether or not the output was written</param> /// <param name="elapsedBakeTimeSeconds">How long the baking took in seconds</param> protected override void SurfaceObserver_OnDataReady(SurfaceData bakedData, bool outputWritten, float elapsedBakeTimeSeconds) { if (bakedData.outputMesh != null) { GameObject go; if (SpatialMeshObjects.TryGetValue(bakedData.id, out go) && go != null) { if (go.GetComponent <MeshRenderer>() == null) { MeshRenderer meshRenderer = go.AddComponent <MeshRenderer>(); meshRenderer.receiveShadows = false; meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; } ApplyRenderingSetting(bakedData.outputMesh.GetComponent <MeshRenderer>()); } } }
private async void MeshInfo_Update(SpatialSurfaceInfo meshInfo, SpatialObserverStatus statusType) { if (statusType == SpatialObserverStatus.Removed) { if (SpatialMeshObjects.TryGetValue(meshInfo.Id, out var removedMeshObject)) { RaiseMeshRemoved(removedMeshObject); } return; } var spatialMeshObject = await RequestSpatialMeshObject(meshInfo.Id); if (meshInfo.UpdateTime.ToUniversalTime() <= spatialMeshObject.LastUpdated.ToUniversalTime()) { // No updates return; } try { await GenerateMeshAsync(meshInfo, spatialMeshObject); } catch (Exception e) { Debug.LogError(e); RaiseMeshRemoved(spatialMeshObject); return; } if (!SpatialMeshObjects.TryGetValue(meshInfo.Id, out var meshObject)) { Debug.LogWarning($"Failed to find a spatial mesh object for {meshInfo.Id}!"); // Likely it was removed before data could be cooked. return; } // Apply the appropriate material to the mesh. var displayOption = MeshDisplayOption; if (displayOption != SpatialMeshDisplayOptions.None) { meshObject.Collider.enabled = true; meshObject.Renderer.enabled = displayOption == SpatialMeshDisplayOptions.Visible || displayOption == SpatialMeshDisplayOptions.Occlusion; meshObject.Renderer.sharedMaterial = displayOption == SpatialMeshDisplayOptions.Visible ? MeshVisibleMaterial : MeshOcclusionMaterial; } else { meshObject.Renderer.enabled = false; meshObject.Collider.enabled = false; } if (!meshObject.GameObject.activeInHierarchy) { meshObject.GameObject.SetActive(true); } switch (statusType) { case SpatialObserverStatus.Added: RaiseMeshAdded(meshObject); break; case SpatialObserverStatus.Updated: RaiseMeshUpdated(meshObject); break; default: throw new ArgumentOutOfRangeException($"{nameof(SpatialObserverStatus)}.{statusType} was not handled!"); } }
/// <summary> /// Handles the SurfaceObserver's OnSurfaceChanged event. /// </summary> /// <param name="surfaceId">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 async void SurfaceObserver_OnSurfaceChanged(SurfaceId surfaceId, SurfaceChange changeType, Bounds bounds, DateTime updateTime) { // If we're adding or updating a mesh if (changeType != SurfaceChange.Removed) { var spatialMeshObject = await RequestSpatialMeshObject(surfaceId.handle); spatialMeshObject.GameObject.name = $"SpatialMesh_{surfaceId.handle.ToString()}"; var worldAnchor = spatialMeshObject.GameObject.EnsureComponent <WorldAnchor>(); var surfaceData = new SurfaceData(surfaceId, spatialMeshObject.Filter, worldAnchor, spatialMeshObject.Collider, MeshTrianglesPerCubicMeter, true); if (!observer.RequestMeshAsync(surfaceData, OnDataReady)) { Debug.LogError($"Mesh request failed for spatial observer with Id {surfaceId.handle.ToString()}"); RaiseMeshRemoved(spatialMeshObject); } void OnDataReady(SurfaceData cookedData, bool outputWritten, float elapsedCookTimeSeconds) { if (!outputWritten) { Debug.LogWarning($"No output for {cookedData.id.handle}"); return; } if (!SpatialMeshObjects.TryGetValue(cookedData.id.handle, out SpatialMeshObject meshObject)) { // Likely it was removed before data could be cooked. return; } // Apply the appropriate material to the mesh. SpatialMeshDisplayOptions displayOption = MeshDisplayOption; if (displayOption != SpatialMeshDisplayOptions.None) { meshObject.Renderer.enabled = true; meshObject.Renderer.sharedMaterial = (displayOption == SpatialMeshDisplayOptions.Visible) ? MeshVisibleMaterial : MeshOcclusionMaterial; } else { meshObject.Renderer.enabled = false; } // Recalculate the mesh normals if requested. if (MeshRecalculateNormals) { meshObject.Filter.sharedMesh.RecalculateNormals(); } meshObject.GameObject.SetActive(true); switch (changeType) { case SurfaceChange.Added: RaiseMeshAdded(meshObject); break; case SurfaceChange.Updated: RaiseMeshUpdated(meshObject); break; } } } else if (SpatialMeshObjects.TryGetValue(surfaceId.handle, out SpatialMeshObject meshObject)) { RaiseMeshRemoved(meshObject); } }
private async void MeshInfo_Update(MeshInfo meshInfo) { if (meshInfo.ChangeState == MeshChangeState.Unchanged) { return; } // If we're adding or updating a mesh if (meshInfo.ChangeState != MeshChangeState.Removed) { var spatialMeshObject = await RequestSpatialMeshObject(meshInfo.MeshId.GetHashCode()); spatialMeshObject.GameObject.name = $"SpatialMesh_{meshInfo.MeshId.ToString()}"; var meshAttributes = MeshRecalculateNormals ? MeshVertexAttributes.Normals : MeshVertexAttributes.None; try { meshSubsystem.GenerateMeshAsync(meshInfo.MeshId, spatialMeshObject.Mesh, spatialMeshObject.Collider, meshAttributes, OnMeshGenerated); } catch (Exception e) { Debug.LogError($"{e.Message}\n{e.StackTrace}"); } void OnMeshGenerated(MeshGenerationResult result) { if (result.Status == MeshGenerationStatus.GenerationAlreadyInProgress) { return; } if (result.Status != MeshGenerationStatus.Success) { Debug.LogWarning($"No output for {result.MeshId.ToString()} | {result.Status}"); RaiseMeshRemoved(spatialMeshObject); return; } if (!SpatialMeshObjects.TryGetValue(result.MeshId.GetHashCode(), out var meshObject)) { Debug.LogWarning($"Failed to find a spatial mesh object for {result.MeshId.ToString()}!"); // Likely it was removed before data could be cooked. return; } // Apply the appropriate material to the mesh. var displayOption = MeshDisplayOption; if (displayOption != SpatialMeshDisplayOptions.None) { meshObject.Collider.enabled = true; meshObject.Renderer.enabled = displayOption == SpatialMeshDisplayOptions.Visible || displayOption == SpatialMeshDisplayOptions.Occlusion; meshObject.Renderer.sharedMaterial = displayOption == SpatialMeshDisplayOptions.Visible ? MeshVisibleMaterial : MeshOcclusionMaterial; } else { meshObject.Renderer.enabled = false; meshObject.Collider.enabled = false; } // Recalculate the mesh normals if requested. if (MeshRecalculateNormals) { if (meshObject.Filter.sharedMesh != null) { meshObject.Filter.sharedMesh.RecalculateNormals(); } else { meshObject.Filter.mesh.RecalculateNormals(); } } meshObject.GameObject.SetActive(true); switch (meshInfo.ChangeState) { case MeshChangeState.Added: RaiseMeshAdded(meshObject); break; case MeshChangeState.Updated: RaiseMeshUpdated(meshObject); break; } } } else if (SpatialMeshObjects.TryGetValue(meshInfo.MeshId.GetHashCode(), out var meshObject)) { RaiseMeshRemoved(meshObject); } }
private async void MeshInfo_Update(MlMeshing2.MLMeshingBlockInfo meshInfo) { if (meshInfo.state == MlMeshing2.MLMeshingMeshState.Unchanged) { return; } // If we're adding or updating a mesh if (meshInfo.state != MlMeshing2.MLMeshingMeshState.Deleted) { var spatialMeshObject = await RequestSpatialMeshObject(meshInfo.id.ToGuid()); MeshGenerationResult meshResult; try { meshResult = await GenerateMeshAsync(meshInfo, spatialMeshObject); } catch (Exception e) { Debug.LogError(e); RaiseMeshRemoved(spatialMeshObject); return; } if (meshResult.Status == MlMeshing2.MLMeshingResult.Pending) { return; } if (meshResult.Status != MlMeshing2.MLMeshingResult.Success) { Debug.LogWarning($"No output for {meshResult.Id} | {meshResult.Status}"); RaiseMeshRemoved(spatialMeshObject); return; } if (!SpatialMeshObjects.TryGetValue(meshResult.Id.ToGuid(), out var meshObject)) { Debug.LogWarning($"Failed to find a spatial mesh object for {meshResult.Id}!"); // Likely it was removed before data could be cooked. return; } // Apply the appropriate material to the mesh. var displayOption = MeshDisplayOption; if (displayOption != SpatialMeshDisplayOptions.None) { meshObject.Collider.enabled = true; meshObject.Renderer.enabled = displayOption == SpatialMeshDisplayOptions.Visible || displayOption == SpatialMeshDisplayOptions.Occlusion; meshObject.Renderer.sharedMaterial = displayOption == SpatialMeshDisplayOptions.Visible ? MeshVisibleMaterial : MeshOcclusionMaterial; } else { meshObject.Renderer.enabled = false; meshObject.Collider.enabled = false; } if (!meshObject.GameObject.activeInHierarchy) { meshObject.GameObject.SetActive(true); } switch (meshInfo.state) { case MlMeshing2.MLMeshingMeshState.New: RaiseMeshAdded(meshObject); break; case MlMeshing2.MLMeshingMeshState.Updated: RaiseMeshUpdated(meshObject); break; } } else if (SpatialMeshObjects.TryGetValue(meshInfo.id.ToGuid(), out var meshObject)) { RaiseMeshRemoved(meshObject); } }