HoloLens2 空间映射提取

问题描述 投票:0回答:1

我目前遇到了与 HololLens2 相关的问题。 我尝试在运行时直接访问空间映射。所以我想实现一个扫描程序,用户必须扫描房间,然后我想导出这个网格。基本上我想像在设备门户中一样但在运行时创建房间扫描的 .obj。

因此我实施了一个解决方案,我在这里找到了它: https://learn.microsoft.com/en-us/windows/mixed-reality/mrtk-unity/mrtk2/features/spatial-awareness/usage-guide?view=mrtkunity-2022-05

现在的问题是我没有得到任何网格。

我目前使用MRTK 2.8.3.0和Unity 2022.3.10f1

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.Toolkit;
using Microsoft.MixedReality.Toolkit.SpatialAwareness;
using TMPro;
using Unity.VisualScripting;

public class Scanner_new : MonoBehaviour
{
    public GameObject txt;
    static int count = 0;

    // Start is called before the first frame update
    void Start()
    {
        TextMeshPro textMesh = txt.GetComponent<TextMeshPro>();

        // Use CoreServices to quickly get access to the IMixedRealitySpatialAwarenessSystem
        var spatialAwarenessService = CoreServices.SpatialAwarenessSystem;

        // Cast to the IMixedRealityDataProviderAccess to get access to the data providers
        var dataProviderAccess = spatialAwarenessService as IMixedRealityDataProviderAccess;

        var meshObserver = dataProviderAccess.GetDataProvider<IMixedRealitySpatialAwarenessMeshObserver>();
        if(meshObserver == null){
                count++;
                textMesh.text = "No Observer! \n";
                Debug.Log("No Observer! \n");
                return;
            }
        textMesh.text += "Accessing all the meshes: \n";
        // Loop through all known Meshes
        foreach (SpatialAwarenessMeshObject meshObject in meshObserver.Meshes.Values)
        {   textMesh.text = "here1 \n";
            Mesh mesh = meshObject.Filter.mesh;
            var triangles = mesh.GetTriangles(0);
            foreach (var triangle in triangles){
                textMesh.text = "here2 \n";
                textMesh.text += triangle + "\n";
                count++;
            }
        }
    }

    // Update is called once per frame
    public void Updater()
    {
        TextMeshPro textMesh = txt.GetComponent<TextMeshPro>();
        if(count == 0){
            // Use CoreServices to quickly get access to the IMixedRealitySpatialAwarenessSystem
            var spatialAwarenessService = CoreServices.SpatialAwarenessSystem;

            // Cast to the IMixedRealityDataProviderAccess to get access to the data providers
            var dataProviderAccess = spatialAwarenessService as IMixedRealityDataProviderAccess;

            var meshObserver = dataProviderAccess.GetDataProvider<IMixedRealitySpatialAwarenessMeshObserver>();
            if(meshObserver == null){
                count++;
                textMesh.text = "No Observer! \n";
                Debug.Log("No Observer! \n");
                return;
            }
            textMesh.text += "Accessing all the meshes: \n";
            // Loop through all known Meshes
            foreach (SpatialAwarenessMeshObject meshObject in meshObserver.Meshes.Values)
            {
                textMesh.text = "here1 \n";
                Mesh mesh = meshObject.Filter.mesh;
                var triangles = mesh.GetTriangles(0);
                foreach (var triangle in triangles){
                    textMesh.text = "here2 \n";
                    textMesh.text += triangle + "\n";
                    count++;
                }
            }
        }
    }
}

感谢您的帮助:)

c# unity-game-engine hololens mrtk
1个回答
0
投票

因为我忙了很长一段时间来寻找这个问题的解决方案,现在我也找到了一个我想在这里分享。

在 Unity 中,重要的是空间观察器“OpenXR 空间网格观察器”存在于空间感知选项卡下检查器中的混合现实工具包游戏对象中。

如果是这种情况,以下代码应该可以工作:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.Toolkit;
using Microsoft.MixedReality.Toolkit.SpatialAwareness;
using TMPro;
using Unity.VisualScripting;
using System.Globalization;
using System.IO;
using System;

public class Scanner_new : MonoBehaviour
{
    public GameObject txt;
    

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    public void Updater()
    {
        TextMeshPro textMesh = txt.GetComponent<TextMeshPro>();
        
        // Use CoreServices to quickly get access to the IMixedRealitySpatialAwarenessSystem
        var spatialAwarenessService = CoreServices.SpatialAwarenessSystem;

        // Cast to the IMixedRealityDataProviderAccess to get access to the data providers
        var dataProviderAccess = spatialAwarenessService as IMixedRealityDataProviderAccess;

        // Get the SpatialObjectMeshObserver specifically
        var meshObserverName = "OpenXR Spatial Mesh Observer";
        var spatialObjectMeshObserver = dataProviderAccess.GetDataProvider<IMixedRealitySpatialAwarenessMeshObserver>(meshObserverName);
        if(spatialObjectMeshObserver == null){
                textMesh.text += "No Observer! \n";
                return;
            }
        textMesh.text += "Accessing all the meshes: \n";
        List<MeshFilter> meshes = new List<MeshFilter>();
        // Loop through all known Meshes
        foreach (SpatialAwarenessMeshObject meshObject in spatialObjectMeshObserver.Meshes.Values)
        {   
            meshes.Add(meshObject.Filter);
        }
        create_obj(meshes, "\\Hello_World.obj");
        
        
    }
    private void create_obj(List<MeshFilter> meshes, string targetFileName){
        TextMeshPro textMesh = txt.GetComponent<TextMeshPro>();
        int adjust = 1;
        MeshFilter[] mf = meshes.ToArray();
        int countVertex = 0;

        System.Text.StringBuilder objFileContent = new System.Text.StringBuilder(4096);
        objFileContent.Append("# Automatic export of Hololens 2 scanned mesh scan. \r\n\r\n");

        // for each object gets the vertexes normals and faces
        for (int i = 0; i < mf.Length; i++)
        {
            Mesh m = mf[i].sharedMesh;
            objFileContent.Append("o Object." + (i + 1) + "\r\n");
            
            // inverts x as the coordinates are different from the ones of regular obj
            foreach (Vector3 v in m.vertices)
            {
                float x = -v.x;
                float z = v.z;
                objFileContent.Append("v " + x.ToString("0.000000", CultureInfo.InvariantCulture) + " " + v.y.ToString("0.000000", CultureInfo.InvariantCulture) + " " + z.ToString("0.000000", CultureInfo.InvariantCulture) + "\r\n");
            }

            objFileContent.Append("\r\n\r\n");

            foreach (Vector3 n in m.normals)
            {
                float x = n.x;
                float z = n.z;
                objFileContent.Append("vn " + x.ToString("0.000000", CultureInfo.InvariantCulture) + " " + n.y.ToString("0.000000", CultureInfo.InvariantCulture) + " " + z.ToString("0.000000", CultureInfo.InvariantCulture) + "\r\n");
            }
            objFileContent.Append("\r\n\r\n");

            // the count of the faces starts with 1 and is cumulative for 
            // all objects on the scene this is why it is add 
            // adjust + countVertex as the id of the vertexes
            for (int ti = 0; ti < m.triangles.Length; ti += 3)
            {
                objFileContent.Append("f " + (m.triangles[ti] + adjust + countVertex ) + "//" + (m.triangles[ti] + adjust + countVertex) + " " + (m.triangles[ti + 1] + adjust + countVertex) + "//" + (m.triangles[ti + 1] + adjust + countVertex) + " " + (m.triangles[ti + 2] + adjust + countVertex) + "//" + (m.triangles[ti + 2] + adjust + countVertex) + "\r\n");
            }
            objFileContent.Append("\r\n\r\n");
            countVertex += m.vertexCount;
      }
      try{
        // string objPath = Path.Combine(sceneFolderPath, sceneName + ".obj"); 
        using (StreamWriter sw = File.CreateText(Application.persistentDataPath + targetFileName))
        {
            sw.WriteLine(objFileContent.ToString());
        }
        textMesh.text += "SUCCESS: OBJ SAVED";
      }
      catch(Exception e){
        textMesh.text += e;
      }
       
    }
}

如您所见,代码直接从保存的数据生成一个 .obj 文件。此代码的灵感来自以下问题的答案:MRTK 2.4 - 在运行时保存空间网格

然后可以通过设备门户->文件资源管理器以及应用程序的 localState 文件夹访问 .obj 文件:)

© www.soinside.com 2019 - 2024. All rights reserved.