Esempio n. 1
0
        private async Task <MeshGenerationResult> GenerateMeshAsync(MlMeshing2.MLMeshingBlockInfo meshInfo, SpatialMeshObject spatialMeshObject)
        {
            int levelOfDetail = (int)MeshLevelOfDetail;

            if (levelOfDetail < 0)
            {
                Debug.LogWarning($"{MeshLevelOfDetail} is unsupported! Falling back to low level of detail.");
                levelOfDetail = 0;
            }

            var blockRequest = new MlMeshing2.MLMeshingBlockRequest
            {
                id    = meshInfo.id,
                level = (MlMeshing2.MLMeshingLOD)levelOfDetail
            };

            var meshRequest = new MlMeshing2.MLMeshingMeshRequest
            {
                request_count = 1,
                data          = blockRequest
            };

            if (!MlMeshing2.MLMeshingRequestMesh(meshingClientHandle, in meshRequest, out var outRequestHandle).IsOk)
            {
                Debug.LogError("Failed to request a new mesh!");
                return(new MeshGenerationResult(meshInfo.id, MlMeshing2.MLMeshingResult.Failed));
            }

            var meshRequestResult = new MlApi.MLResult(MlApi.MLResult.Code.Pending);

            var outMeshResult = new MlMeshing2.MLMeshingMesh
            {
                result = MlMeshing2.MLMeshingResult.Pending
            };

            await Awaiters.BackgroundThread;

            while (meshRequestResult.Value == MlApi.MLResult.Code.Pending)
            {
                meshRequestResult = MlMeshing2.MLMeshingGetMeshResult(meshingClientHandle, outRequestHandle, out outMeshResult);
                await Task.Delay(25); // TODO make this delay configurable?
            }

            await Awaiters.UnityMainThread;

            if (!meshRequestResult.IsOk ||
                outMeshResult.result == MlMeshing2.MLMeshingResult.Failed ||
                !MlMeshing2.MLMeshingFreeResource(meshingClientHandle, outRequestHandle).IsOk)
            {
                return(new MeshGenerationResult(meshInfo.id, MlMeshing2.MLMeshingResult.Failed));
            }

            if (outMeshResult.data_count != meshRequest.request_count)
            {
                Debug.LogError($"Mesh Block count mismatch! Expected {meshRequest.request_count} but got {outMeshResult.data_count} blocks.");
                return(new MeshGenerationResult(meshInfo.id, MlMeshing2.MLMeshingResult.Failed));
            }

            if (meshInfo.id != outMeshResult.data.id)
            {
                Debug.LogError($"Mesh info id mismatch!\n->{meshInfo.id}\n<-{outMeshResult.data.id}");
                return(new MeshGenerationResult(meshInfo.id, MlMeshing2.MLMeshingResult.Failed));
            }

            var mesh = spatialMeshObject.Mesh == null ? new Mesh() : spatialMeshObject.Mesh;

            mesh.name = $"Mesh_{meshInfo.id}";

            if (outMeshResult.data.vertex_count == 0 ||
                outMeshResult.data.vertex == null ||
                outMeshResult.data.index_count == 0 ||
                outMeshResult.data.index == null)
            {
                return(new MeshGenerationResult(meshInfo.id, outMeshResult.result));
            }

            await Awaiters.BackgroundThread;

            if (MeshRecalculateNormals)
            {
                var normals = new NativeArray <VertexData>((int)outMeshResult.data.vertex_count, Allocator.None);

                for (int i = 0; i < normals.Length; i++)
                {
                    normals[i] = new VertexData
                    {
                        Position = outMeshResult.data.vertex[i],
                        Normal   = outMeshResult.data.normal[i]
                    };
                }

                mesh.SetVertexBufferParams((int)outMeshResult.data.vertex_count, NormalsLayout);
                mesh.SetVertexBufferData(normals, 0, 0, (int)outMeshResult.data.vertex_count);

                normals.Dispose();
            }
            else
            {
                var vertices = new NativeArray <Vector3>((int)outMeshResult.data.vertex_count, Allocator.None);

                for (int i = 0; i < vertices.Length; i++)
                {
                    vertices[i] = outMeshResult.data.vertex[i];
                }

                mesh.SetVertexBufferParams((int)outMeshResult.data.vertex_count, VertexLayout);
                mesh.SetVertexBufferData(vertices, 0, 0, (int)outMeshResult.data.vertex_count);

                vertices.Dispose();
            }

            var indices = new NativeArray <short>(outMeshResult.data.index_count, Allocator.None);

            for (int i = 0; i < outMeshResult.data.index_count; i++)
            {
                indices[i] = (short)outMeshResult.data.index[i];
            }

            mesh.SetIndexBufferParams(outMeshResult.data.index_count, IndexFormat.UInt16);
            mesh.SetIndexBufferData(indices, 0, 0, outMeshResult.data.index_count);

            indices.Dispose();

            mesh.SetSubMesh(0, new SubMeshDescriptor(0, outMeshResult.data.index_count));
            mesh.Optimize();
            mesh.RecalculateBounds();

            if (MeshRecalculateNormals)
            {
                mesh.RecalculateNormals();
            }

            spatialMeshObject.Mesh = mesh;

            await Awaiters.UnityMainThread;

            return(new MeshGenerationResult(meshInfo.id, outMeshResult.result));
        }
Esempio n. 2
0
        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);
            }
        }