cancel
Showing results for 
Search instead for 
Did you mean: 

Problems with MultiRoomMeshes

Zeljko777
Explorer

I have created a new Unity project. The goal was to create a passthrough project that runs exclusively on Windows PCs. The 3D objects should then be created based on the room data. In its final stage, the game will run on the PC, with the headset used for visualization! However, I encountered an issue that arises with multi-room data. If only one room is stored in the Meta Quest, the problem does not occur.

The software I used:

  • Unity 2022.3.53f1
  • VS2022 Community Edition
  • Meta XR All-in-One-SDK

For testing, I used the Blockbuilder function:

  • OVRCameraRig
  • SceneMesh Experimental

More information can be found in the images!
Has anyone experienced the same issue or can reproduce it?001.jpg002.jpg003.jpg004.jpg

1 ACCEPTED SOLUTION

Accepted Solutions

Zeljko777
Explorer

Hallo, I have solved the problem. Here is a update of the Code! You can use it it for the MetaQuestAllinOnesdk :-!

    using System.Collections.Generic;
    using UnityEngine;
    using System.Linq;
 
    public class RoomMeshController : MonoBehaviour
    {
        [SerializeField] private GameObject _meshPrefab;
        private RoomMeshEvent _roomMeshEvent;
        private Dictionary<Guid, RoomMeshAnchor> _roomMeshAnchors;
 
        private void Awake()
        {
            _roomMeshAnchors = new Dictionary<Guid, RoomMeshAnchor>();
            _roomMeshEvent = FindObjectOfType<RoomMeshEvent>();
        }
 
        private IEnumerator Start()
        {
            var timeout = 10f;
            var startTime = Time.time;
            while (!OVRPermissionsRequester.IsPermissionGranted(OVRPermissionsRequester.Permission.Scene))
            {
                if (Time.time - startTime > timeout)
                {
                    Debug.LogWarning($"[{nameof(RoomMeshController)}] Spatial Data permission is required to load Room Mesh.");
                    yield break;
                }
                yield return null;
            }
 
            yield return LoadRoomMesh();
            yield return UpdateVolume();
 
            foreach (var anchor in _roomMeshAnchors.Values)
            {
                timeout = 3f;
                startTime = Time.time;
                while (!anchor.IsCompleted)
                {
                    if (Time.time - startTime > timeout)
                    {
                        Debug.LogWarning($"[{nameof(RoomMeshController)}] Failed to create Room Mesh for anchor {anchor.gameObject.name}.");
                        continue;
                    }
                    yield return null;
                }
 
                _roomMeshEvent.OnRoomMeshLoadCompleted?.Invoke(anchor.GetComponent<MeshFilter>());
            }
        }
 
        private IEnumerator UpdateVolume()
        {
            foreach (var anchor in _roomMeshAnchors.Values)
            {
                while (!anchor.IsCompleted) yield return null;
 
                var parentMeshFilter = anchor.GetComponent<MeshFilter>();
                var parentMesh = parentMeshFilter.sharedMesh;
 
                var vertices = new List<Vector3>();
                var triangles = new List<int>();
 
                parentMesh.GetVertices(vertices);
                parentMesh.GetTriangles(triangles, 0);
 
                var c = new Color[triangles.Count];
                var v = new Vector3[triangles.Count];
                var idx = new int[triangles.Count];
                for (var i = 0; i < triangles.Count; i++)
                {
                    c[i] = new Color(
                        i % 3 == 0 ? 1.0f : 0.0f,
                        i % 3 == 1 ? 1.0f : 0.0f,
                        i % 3 == 2 ? 1.0f : 0.0f);
                    v[i] = vertices[triangles[i]];
                    idx[i] = i;
                }
 
                var mesh = new Mesh
                {
                    indexFormat = IndexFormat.UInt32
                };
                mesh.SetVertices(v);
                mesh.SetColors(c);
                mesh.SetIndices(idx, MeshTopology.Triangles, 0, true, 0);
                mesh.RecalculateBounds();
                mesh.RecalculateNormals();
 
                parentMeshFilter.sharedMesh = mesh;
            }
        }
 
        private IEnumerator LoadRoomMesh()
        {
            using (new OVRObjectPool.ListScope<OVRAnchor>(out var anchors))
            {
                var task = OVRAnchor.FetchAnchorsAsync(anchors, new OVRAnchor.FetchOptions
                {
                    SingleComponentType = typeof(OVRTriangleMesh)
                });
                while (task.IsPending) yield return null;
 
                if (anchors.Count == 0)
                {
                    Debug.LogWarning($"[{nameof(RoomMeshController)}] No RoomMesh available.");
                    yield break;
                }
 
                foreach (var anchor in anchors)
                {
                    if (!anchor.TryGetComponent(out OVRLocatable locatableComponent))
                    {
                        Debug.LogWarning($"[{nameof(RoomMeshController)}] Failed to localize the room mesh anchor.");
                        continue;
                    }
 
                    var localizeTask = locatableComponent.SetEnabledAsync(true);
                    while (localizeTask.IsPending) yield return null;
 
                    InstantiateRoomMesh(anchor, _meshPrefab);
                }
            }
        }
 
        private void InstantiateRoomMesh(OVRAnchor anchor, GameObject prefab)
        {
            var roomMeshAnchor = Instantiate(prefab, Vector3.zero, Quaternion.identity).GetComponent<RoomMeshAnchor>();
            roomMeshAnchor.gameObject.name = anchor.Uuid.ToString();
            roomMeshAnchor.gameObject.SetActive(true);
            roomMeshAnchor.Initialize(anchor);
            _roomMeshAnchors[anchor.Uuid] = roomMeshAnchor;
        }
    }
}


Please Look in The Codes the Changes, so you can Work with MultiMeshRooms :-)!

View solution in original post

1 REPLY 1

Zeljko777
Explorer

Hallo, I have solved the problem. Here is a update of the Code! You can use it it for the MetaQuestAllinOnesdk :-!

    using System.Collections.Generic;
    using UnityEngine;
    using System.Linq;
 
    public class RoomMeshController : MonoBehaviour
    {
        [SerializeField] private GameObject _meshPrefab;
        private RoomMeshEvent _roomMeshEvent;
        private Dictionary<Guid, RoomMeshAnchor> _roomMeshAnchors;
 
        private void Awake()
        {
            _roomMeshAnchors = new Dictionary<Guid, RoomMeshAnchor>();
            _roomMeshEvent = FindObjectOfType<RoomMeshEvent>();
        }
 
        private IEnumerator Start()
        {
            var timeout = 10f;
            var startTime = Time.time;
            while (!OVRPermissionsRequester.IsPermissionGranted(OVRPermissionsRequester.Permission.Scene))
            {
                if (Time.time - startTime > timeout)
                {
                    Debug.LogWarning($"[{nameof(RoomMeshController)}] Spatial Data permission is required to load Room Mesh.");
                    yield break;
                }
                yield return null;
            }
 
            yield return LoadRoomMesh();
            yield return UpdateVolume();
 
            foreach (var anchor in _roomMeshAnchors.Values)
            {
                timeout = 3f;
                startTime = Time.time;
                while (!anchor.IsCompleted)
                {
                    if (Time.time - startTime > timeout)
                    {
                        Debug.LogWarning($"[{nameof(RoomMeshController)}] Failed to create Room Mesh for anchor {anchor.gameObject.name}.");
                        continue;
                    }
                    yield return null;
                }
 
                _roomMeshEvent.OnRoomMeshLoadCompleted?.Invoke(anchor.GetComponent<MeshFilter>());
            }
        }
 
        private IEnumerator UpdateVolume()
        {
            foreach (var anchor in _roomMeshAnchors.Values)
            {
                while (!anchor.IsCompleted) yield return null;
 
                var parentMeshFilter = anchor.GetComponent<MeshFilter>();
                var parentMesh = parentMeshFilter.sharedMesh;
 
                var vertices = new List<Vector3>();
                var triangles = new List<int>();
 
                parentMesh.GetVertices(vertices);
                parentMesh.GetTriangles(triangles, 0);
 
                var c = new Color[triangles.Count];
                var v = new Vector3[triangles.Count];
                var idx = new int[triangles.Count];
                for (var i = 0; i < triangles.Count; i++)
                {
                    c[i] = new Color(
                        i % 3 == 0 ? 1.0f : 0.0f,
                        i % 3 == 1 ? 1.0f : 0.0f,
                        i % 3 == 2 ? 1.0f : 0.0f);
                    v[i] = vertices[triangles[i]];
                    idx[i] = i;
                }
 
                var mesh = new Mesh
                {
                    indexFormat = IndexFormat.UInt32
                };
                mesh.SetVertices(v);
                mesh.SetColors(c);
                mesh.SetIndices(idx, MeshTopology.Triangles, 0, true, 0);
                mesh.RecalculateBounds();
                mesh.RecalculateNormals();
 
                parentMeshFilter.sharedMesh = mesh;
            }
        }
 
        private IEnumerator LoadRoomMesh()
        {
            using (new OVRObjectPool.ListScope<OVRAnchor>(out var anchors))
            {
                var task = OVRAnchor.FetchAnchorsAsync(anchors, new OVRAnchor.FetchOptions
                {
                    SingleComponentType = typeof(OVRTriangleMesh)
                });
                while (task.IsPending) yield return null;
 
                if (anchors.Count == 0)
                {
                    Debug.LogWarning($"[{nameof(RoomMeshController)}] No RoomMesh available.");
                    yield break;
                }
 
                foreach (var anchor in anchors)
                {
                    if (!anchor.TryGetComponent(out OVRLocatable locatableComponent))
                    {
                        Debug.LogWarning($"[{nameof(RoomMeshController)}] Failed to localize the room mesh anchor.");
                        continue;
                    }
 
                    var localizeTask = locatableComponent.SetEnabledAsync(true);
                    while (localizeTask.IsPending) yield return null;
 
                    InstantiateRoomMesh(anchor, _meshPrefab);
                }
            }
        }
 
        private void InstantiateRoomMesh(OVRAnchor anchor, GameObject prefab)
        {
            var roomMeshAnchor = Instantiate(prefab, Vector3.zero, Quaternion.identity).GetComponent<RoomMeshAnchor>();
            roomMeshAnchor.gameObject.name = anchor.Uuid.ToString();
            roomMeshAnchor.gameObject.SetActive(true);
            roomMeshAnchor.Initialize(anchor);
            _roomMeshAnchors[anchor.Uuid] = roomMeshAnchor;
        }
    }
}


Please Look in The Codes the Changes, so you can Work with MultiMeshRooms :-)!