void BuildSpatialSurfaceObserver() { _spatialSurfaceObserver = new SpatialSurfaceObserver(); var positionFormat = DirectXPixelFormat.R32G32B32A32Float; var normalFormat = DirectXPixelFormat.R32G32B32A32Float; _spatialSurfaceMeshOptions = new SpatialSurfaceMeshOptions { IncludeVertexNormals = true, VertexPositionFormat = positionFormat, VertexNormalFormat = normalFormat, TriangleIndexFormat = DirectXPixelFormat.R16UInt }; var boundingBox = new SpatialBoundingBox { Center = new Vector3(0f, 0f, 0f), Extents = new Vector3(10f, 10f, 10f) }; var bounds = SpatialBoundingVolume.FromBox(_spatialCoordinateSystem, boundingBox); _spatialSurfaceObserver.SetBoundingVolume(bounds); _spatialSurfaceObserver.ObservedSurfacesChanged += SpatialSurfaceObserverOnObservedSurfacesChanged; }
/// <inheritdoc /> public WindowsMixedRealitySpatialMeshObserver(string name, uint priority, WindowsMixedRealitySpatialMeshObserverProfile profile, IMixedRealitySpatialAwarenessSystem parentService) : base(name, priority, profile, parentService) { #if WINDOWS_UWP if (profile.MeshLevelOfDetail == SpatialAwarenessMeshLevelOfDetail.Custom) { trianglesPerCubicMeter = profile.TrianglesPerCubicMeter; } if (SpatialSurfaceObserver.IsSupported()) { spatialSurfaceObserver = new SpatialSurfaceObserver(); spatialSurfaceMeshOptions = new SpatialSurfaceMeshOptions { IncludeVertexNormals = true }; // TODO Determine which formats are the correct ones to use. var supportedVertexPositionFormats = SpatialSurfaceMeshOptions.SupportedVertexPositionFormats; var supportedVertexNormalFormats = SpatialSurfaceMeshOptions.SupportedVertexNormalFormats; for (int i = 0; i < supportedVertexPositionFormats.Count; i++) { if (supportedVertexPositionFormats[i] == Windows.Graphics.DirectX.DirectXPixelFormat.R16G16B16A16IntNormalized) { spatialSurfaceMeshOptions.VertexPositionFormat = Windows.Graphics.DirectX.DirectXPixelFormat.R16G16B16A16IntNormalized; break; } } for (int i = 0; i < supportedVertexNormalFormats.Count; i++) { if (supportedVertexNormalFormats[i] == Windows.Graphics.DirectX.DirectXPixelFormat.R8G8B8A8IntNormalized) { spatialSurfaceMeshOptions.VertexNormalFormat = Windows.Graphics.DirectX.DirectXPixelFormat.R8G8B8A8IntNormalized; break; } } // If a very high detail setting with spatial mapping is used, it can be beneficial // to use a 32-bit unsigned integer format for indices instead of the default 16-bit. if (MeshLevelOfDetail == SpatialAwarenessMeshLevelOfDetail.High) { var supportedTriangleIndexFormats = SpatialSurfaceMeshOptions.SupportedTriangleIndexFormats; for (int i = 0; i < supportedTriangleIndexFormats.Count; i++) { if (supportedTriangleIndexFormats[i] == Windows.Graphics.DirectX.DirectXPixelFormat.R8G8B8A8IntNormalized) { spatialSurfaceMeshOptions.TriangleIndexFormat = Windows.Graphics.DirectX.DirectXPixelFormat.R32UInt; } } } } }
/// <summary> /// Initializes a new instance of the <see cref="SpatialMappingManagerUWP"/> class. /// </summary> public SpatialMappingManagerUWP() { this.surfaces = new Dictionary <Guid, SpatialMappingSurface>(); this.extents = Vector3.One * 10.0f; this.TrianglesPerCubicMeter = 500; this.ObtainNormals = true; this.pendingChanges = true; this.surfaceMeshOptions = new SpatialSurfaceMeshOptions() { IncludeVertexNormals = this.ObtainNormals, VertexPositionFormat = Windows.Graphics.DirectX.DirectXPixelFormat.R32G32B32A32Float, VertexNormalFormat = Windows.Graphics.DirectX.DirectXPixelFormat.R32G32B32A32Float, ////TriangleIndexFormat = Windows.Graphics.DirectX.DirectXPixelFormat.R32UInt }; }
public async Task AddOrUpdateAsync(SpatialSurfaceInfo spatialSurfaceInfo, SpatialSurfaceMeshOptions options) { var mesh = await spatialSurfaceInfo.TryComputeLatestMeshAsync(1000.0d, options); if (mesh == null) { return; } var tempList = new Dictionary <Guid, SurfaceMesh>(_internalList); // See if we already have this one.... var hasOne = tempList.ContainsKey(mesh.SurfaceInfo.Id); if (hasOne) { // Update var surfaceMesh = tempList[mesh.SurfaceInfo.Id]; if (surfaceMesh.UpdateTime < mesh.SurfaceInfo.UpdateTime) { surfaceMesh.CalculateAllVertices(mesh); surfaceMesh.UpdateTime = mesh.SurfaceInfo.UpdateTime; } } else { // Add new var newMesh = new SurfaceMesh { Id = mesh.SurfaceInfo.Id, UpdateTime = mesh.SurfaceInfo.UpdateTime, CoordinateSystem = CoordinateSystem, DirectXDevice = DirectXDevice }; newMesh.CalculateAllVertices(mesh); tempList[newMesh.Id] = newMesh; } lock (_lockObject) _internalList = tempList; }
private void OnSurfaceUpdate(SpatialSurfaceObserver observer, object args) { var surfaceDict = observer.GetObservedSurfaces(); foreach (var surface in surfaceDict) { // Find or add a surface mesh for this surface SurfaceMesh mesh = meshes.Find(m => m.id == surface.Key); if (mesh == null) { mesh = new SurfaceMesh { mesh = new Mesh(), id = surface.Key, lastUpdate = new DateTimeOffset() }; meshes.Add(mesh); } // Ask for an update to the mesh data, if it's old if (surface.Value.UpdateTime > mesh.lastUpdate) { mesh.lastUpdate = surface.Value.UpdateTime; SpatialSurfaceMeshOptions opts = new SpatialSurfaceMeshOptions(); opts.IncludeVertexNormals = false; opts.TriangleIndexFormat = Windows.Graphics.DirectX.DirectXPixelFormat.R32UInt; opts.VertexPositionFormat = Windows.Graphics.DirectX.DirectXPixelFormat.R32G32B32A32Float; surface.Value.TryComputeLatestMeshAsync(trisPerMeter, opts).Completed = (info, state) => { // Send update to the main thread for upload to GPU if (state == Windows.Foundation.AsyncStatus.Completed) { queuedUpdates.Add(info.GetResults()); } }; } } }
/// <summary> /// Update the surface /// </summary> /// <param name="handler">The handler to receive the surface information</param> /// <param name="change">The surface change</param> /// <param name="surface">The surface to update</param> /// <param name="trianglesPerCubicMeter">The max triangles per cubic meter</param> /// <param name="surfaceInfo">The surface info</param> /// <param name="surfaceOptions">The mesh options</param> private async void UpdateSurface(OnSurfaceChangedHandler handler, SurfaceChange change, SpatialMappingSurfaceInternal surface, float trianglesPerCubicMeter, SpatialSurfaceInfo surfaceInfo, SpatialSurfaceMeshOptions surfaceOptions) { if (surface.IsProcessing) { return; } try { surface.IsProcessing = true; // Generate the mesh from the MixedReality surface info SpatialSurfaceMesh surfaceMesh = await surfaceInfo.TryComputeLatestMeshAsync(trianglesPerCubicMeter, surfaceOptions); if (surfaceMesh != null && surface.UpdateTime < surfaceMesh.SurfaceInfo.UpdateTime) { // Update the surface mesh surface.UpdateSurfaceMesh(surfaceMesh); if (handler != null) { handler(surface.Id, surface, change, surface.UpdateTime); } } } finally { surface.IsProcessing = false; } }