From 957b263bb67212908acf6bc9d1205049434acfc3 Mon Sep 17 00:00:00 2001 From: Xinkai Jiang Date: Tue, 5 Nov 2024 19:42:28 +0100 Subject: [PATCH 1/5] coroutine for async downloading --- Assets/IRXRClient/Scripts/IRXRNetManager.cs | 13 ++- Assets/SceneLoader/Scripts/SimLoader.cs | 122 ++++++++++++++++++-- 2 files changed, 123 insertions(+), 12 deletions(-) diff --git a/Assets/IRXRClient/Scripts/IRXRNetManager.cs b/Assets/IRXRClient/Scripts/IRXRNetManager.cs index 47dd668..9592526 100644 --- a/Assets/IRXRClient/Scripts/IRXRNetManager.cs +++ b/Assets/IRXRClient/Scripts/IRXRNetManager.cs @@ -14,15 +14,16 @@ public enum ServerPort { Discovery = 7720, Service = 7721, Topic = 7722, + HTTP = 7723, } public enum ClientPort { Discovery = 7720, - Service = 7723, - Topic = 7724, + Service = 7730, + Topic = 7731, } -class HostInfo { +public class HostInfo { public string name; public string ip; public List topics = new(); @@ -37,7 +38,7 @@ public class IRXRNetManager : Singleton { public Action ConnectionSpin; private UdpClient _discoveryClient; private string _conncetionID = null; - private HostInfo _serverInfo = null; + public HostInfo _serverInfo = null; private HostInfo _localInfo = new HostInfo(); private List _sockets; @@ -331,4 +332,8 @@ public bool CheckServerService(string serviceName) { return false; } + public HostInfo GetServerInfo() { + return _serverInfo; + } + } \ No newline at end of file diff --git a/Assets/SceneLoader/Scripts/SimLoader.cs b/Assets/SceneLoader/Scripts/SimLoader.cs index 2d360af..25c7ada 100644 --- a/Assets/SceneLoader/Scripts/SimLoader.cs +++ b/Assets/SceneLoader/Scripts/SimLoader.cs @@ -1,9 +1,10 @@ using System; +using System.Collections; +using System.Collections.Generic; using UnityEngine; using System.Runtime.InteropServices; -using System.Collections.Generic; using Newtonsoft.Json; - +using UnityEngine.Networking; public class SceneLoader : MonoBehaviour { @@ -21,6 +22,8 @@ public class SceneLoader : MonoBehaviour { private Dictionary _cachedMeshes; private Dictionary _cachedTextures; + private int _coroutinesCompleted = 0; + void Awake() { _simMeshes = new(); _simMaterials = new(); @@ -57,7 +60,7 @@ void DownloadScene() { Debug.LogWarning("Scene Service is not found"); return; } - float downloadStartTime = Time.realtimeSinceStartup; + // float downloadStartTime = Time.realtimeSinceStartup; string asset_info = _netManager.RequestString("Scene"); if (asset_info == "Invild Service") { Debug.LogWarning("Invalid Service"); @@ -65,19 +68,122 @@ void DownloadScene() { } _simScene = JsonConvert.DeserializeObject(asset_info); DownloadAssets(_simScene); - float timeSpent = (Time.realtimeSinceStartup - downloadStartTime) * 1000; - Debug.Log($"Downloaded Scene in {(int)timeSpent} ms"); - updateAction += BuildScene; + // float timeSpent = (Time.realtimeSinceStartup - downloadStartTime) * 1000; + // Debug.Log($"Downloaded Scene in {(int)timeSpent} ms"); + // updateAction += BuildScene; } public void DownloadAssets(SimScene scene) { _simMeshes.Clear(); _simMaterials.Clear(); _simTextures.Clear(); - scene.meshes.ForEach(DownloadMesh); - scene.textures.ForEach(DownloadTexture); + _coroutinesCompleted = 0; + // scene.meshes.ForEach(DownloadMesh); + // scene.textures.ForEach(DownloadTexture); + StartCoroutine(DownloadAllAssets(scene)); + } + + +private IEnumerator DownloadAllAssets(SimScene scene) +{ + float downloadStartTime = Time.realtimeSinceStartup; + List coroutines = new List(); + for (int i = 0; i < scene.meshes.Count; i++) + { + coroutines.Add(DownloadMeshHTTP(scene.meshes[i])); + } + + for (int i = 0; i < scene.textures.Count; i++) + { + coroutines.Add(DownloadTextureHTTP(scene.textures[i])); + } + + List runningCoroutines = new List(); + foreach (var coroutine in coroutines) + { + runningCoroutines.Add(StartCoroutine(coroutine)); + } + + foreach (var runningCoroutine in runningCoroutines) + { + yield return runningCoroutine; + } + + Debug.Log("All assets have been downloaded."); + updateAction += BuildScene; + float timeSpent = (Time.realtimeSinceStartup - downloadStartTime) * 1000; + Debug.Log($"Downloaded Scene in {(int)timeSpent} ms"); +} + + IEnumerator DownloadMeshHTTP(SimMesh mesh) + { + if (_cachedMeshes.TryGetValue(mesh.dataHash, out Mesh cached)) { + mesh.compiledMesh = cached; + _simMeshes.Add(mesh.name, mesh); + } + else + { + HostInfo serverInfo = _netManager.GetServerInfo(); + string fileUrl = $"http://{serverInfo.ip}:{(int)ServerPort.HTTP}/?asset_tag={mesh.dataHash}"; + using (UnityWebRequest request = UnityWebRequest.Get(fileUrl)) + { + float downloadStartTime = Time.realtimeSinceStartup; + Debug.Log($"Downloading mesh data: {mesh.name} at {downloadStartTime}"); + yield return request.SendWebRequest(); + float timeSpent = (Time.realtimeSinceStartup - downloadStartTime) * 1000; + Debug.Log($"Downloaded {mesh.name} in {(int)timeSpent} ms"); + if (request.result != UnityWebRequest.Result.Success) + { + Debug.LogError($"Error downloading mesh data: {request.error}"); + } + else + { + // Debug.Log($"Downloaded mesh data: {mesh.name}"); + downloadStartTime = Time.realtimeSinceStartup; + byte[] byteArray = request.downloadHandler.data; + Span data = new Span(byteArray); + mesh.rawData = new SimMeshData + { + indices = MemoryMarshal.Cast(data.Slice(mesh.indicesLayout[0], mesh.indicesLayout[1] * sizeof(int))).ToArray(), + vertices = MemoryMarshal.Cast(data.Slice(mesh.verticesLayout[0], mesh.verticesLayout[1] * sizeof(float))).ToArray(), + normals = MemoryMarshal.Cast(data.Slice(mesh.normalsLayout[0], mesh.normalsLayout[1] * sizeof(float))).ToArray(), + uvs = MemoryMarshal.Cast(data.Slice(mesh.uvLayout[0], mesh.uvLayout[1] * sizeof(float))).ToArray(), + }; + timeSpent = (Time.realtimeSinceStartup - downloadStartTime) * 1000; + Debug.Log($"Processed {mesh.name} in {timeSpent} ms"); + } + } + } } + IEnumerator DownloadTextureHTTP(SimTexture texture) + { + if (_cachedTextures.TryGetValue(texture.dataHash, out Texture cached)){ + texture.compiledTexture = cached; + } + else + { + HostInfo serverInfo = _netManager.GetServerInfo(); + string fileUrl = $"http://{serverInfo.ip}:{(int)ServerPort.HTTP}/?asset_tag={texture.dataHash}"; + using (UnityWebRequest request = UnityWebRequest.Get(fileUrl)) + { + // Debug.Log($"Downloading texture data: {texture.name}"); + yield return request.SendWebRequest(); + if (request.result != UnityWebRequest.Result.Success) + { + Debug.LogError($"Error downloading mesh data: {request.error}"); + } + else + { + // Debug.Log($"Downloaded texture data: {texture.name}"); + texture.textureData = request.downloadHandler.data; + _simTextures.Add(texture.name, texture); + } + } + } + } + + private void DownloadMesh(SimMesh mesh) { if (_cachedMeshes.TryGetValue(mesh.dataHash, out Mesh cached)) { mesh.compiledMesh = cached; From d80baca9fc4c17274953e84b9789b270fa550da9 Mon Sep 17 00:00:00 2001 From: Xinkai Jiang Date: Fri, 8 Nov 2024 23:20:05 +0100 Subject: [PATCH 2/5] try to build mesh and texture after download for saving memory --- Assets/SceneLoader/Scripts/SimLoader.cs | 159 ++++++++++++------------ 1 file changed, 77 insertions(+), 82 deletions(-) diff --git a/Assets/SceneLoader/Scripts/SimLoader.cs b/Assets/SceneLoader/Scripts/SimLoader.cs index 25c7ada..738a3a1 100644 --- a/Assets/SceneLoader/Scripts/SimLoader.cs +++ b/Assets/SceneLoader/Scripts/SimLoader.cs @@ -14,23 +14,25 @@ public class SceneLoader : MonoBehaviour { private IRXRNetManager _netManager; private GameObject _simSceneObj; private SimScene _simScene; - private Dictionary _simObjTrans = new Dictionary(); + private Dictionary _simObjTrans = new (); - private Dictionary _simMeshes; - private Dictionary _simMaterials; - private Dictionary _simTextures; - private Dictionary _cachedMeshes; - private Dictionary _cachedTextures; + // private Dictionary _simMeshes; + // private Dictionary _simMaterials; + // private Dictionary _simTextures; + // private Dictionary _cachedMeshes; + // private Dictionary _cachedTextures; + + private Dictionary> _pendingMesh = new (); + private Dictionary> _pendingMaterial = new (); - private int _coroutinesCompleted = 0; void Awake() { - _simMeshes = new(); - _simMaterials = new(); - _simTextures = new(); + // _simMeshes = new(); + // _simMaterials = new(); + // _simTextures = new(); - _cachedTextures = new(); - _cachedMeshes = new(); + // _cachedTextures = new(); + // _cachedMeshes = new(); } void Start() { @@ -77,9 +79,6 @@ public void DownloadAssets(SimScene scene) { _simMeshes.Clear(); _simMaterials.Clear(); _simTextures.Clear(); - _coroutinesCompleted = 0; - // scene.meshes.ForEach(DownloadMesh); - // scene.textures.ForEach(DownloadTexture); StartCoroutine(DownloadAllAssets(scene)); } @@ -115,48 +114,42 @@ private IEnumerator DownloadAllAssets(SimScene scene) Debug.Log($"Downloaded Scene in {(int)timeSpent} ms"); } - IEnumerator DownloadMeshHTTP(SimMesh mesh) + IEnumerator DownloadMesh(SimMesh mesh) { - if (_cachedMeshes.TryGetValue(mesh.dataHash, out Mesh cached)) { - mesh.compiledMesh = cached; - _simMeshes.Add(mesh.name, mesh); - } - else + // if (_cachedMeshes.TryGetValue(mesh.dataHash, out Mesh cached)) { + // mesh.compiledMesh = cached; + // _simMeshes.Add(mesh.name, mesh); + // } + // else + // { + HostInfo serverInfo = _netManager.GetServerInfo(); + string fileUrl = $"http://{serverInfo.ip}:{(int)ServerPort.HTTP}/?asset_tag={mesh.dataHash}"; + using (UnityWebRequest request = UnityWebRequest.Get(fileUrl)) { - HostInfo serverInfo = _netManager.GetServerInfo(); - string fileUrl = $"http://{serverInfo.ip}:{(int)ServerPort.HTTP}/?asset_tag={mesh.dataHash}"; - using (UnityWebRequest request = UnityWebRequest.Get(fileUrl)) + yield return request.SendWebRequest(); + if (request.result != UnityWebRequest.Result.Success) { - float downloadStartTime = Time.realtimeSinceStartup; - Debug.Log($"Downloading mesh data: {mesh.name} at {downloadStartTime}"); - yield return request.SendWebRequest(); - float timeSpent = (Time.realtimeSinceStartup - downloadStartTime) * 1000; - Debug.Log($"Downloaded {mesh.name} in {(int)timeSpent} ms"); - if (request.result != UnityWebRequest.Result.Success) - { - Debug.LogError($"Error downloading mesh data: {request.error}"); - } - else - { - // Debug.Log($"Downloaded mesh data: {mesh.name}"); - downloadStartTime = Time.realtimeSinceStartup; - byte[] byteArray = request.downloadHandler.data; - Span data = new Span(byteArray); - mesh.rawData = new SimMeshData - { - indices = MemoryMarshal.Cast(data.Slice(mesh.indicesLayout[0], mesh.indicesLayout[1] * sizeof(int))).ToArray(), - vertices = MemoryMarshal.Cast(data.Slice(mesh.verticesLayout[0], mesh.verticesLayout[1] * sizeof(float))).ToArray(), - normals = MemoryMarshal.Cast(data.Slice(mesh.normalsLayout[0], mesh.normalsLayout[1] * sizeof(float))).ToArray(), - uvs = MemoryMarshal.Cast(data.Slice(mesh.uvLayout[0], mesh.uvLayout[1] * sizeof(float))).ToArray(), - }; - timeSpent = (Time.realtimeSinceStartup - downloadStartTime) * 1000; - Debug.Log($"Processed {mesh.name} in {timeSpent} ms"); - } + Debug.LogError($"Error downloading mesh data: {request.error}"); + yield break; + } + byte[] byteArray = request.downloadHandler.data; + Span data = new Span(byteArray); + mesh.rawData = new SimMeshData + { + indices = MemoryMarshal.Cast(data.Slice(mesh.indicesLayout[0], mesh.indicesLayout[1] * sizeof(int))).ToArray(), + vertices = MemoryMarshal.Cast(data.Slice(mesh.verticesLayout[0], mesh.verticesLayout[1] * sizeof(float))).ToArray(), + normals = MemoryMarshal.Cast(data.Slice(mesh.normalsLayout[0], mesh.normalsLayout[1] * sizeof(float))).ToArray(), + uvs = MemoryMarshal.Cast(data.Slice(mesh.uvLayout[0], mesh.uvLayout[1] * sizeof(float))).ToArray(), + }; + yield return null; + foreach (var meshFilter in _pendingMesh[mesh.name]) + { + meshFilter.mesh = mesh.compiledMesh; } } } - IEnumerator DownloadTextureHTTP(SimTexture texture) + IEnumerator DownloadTexture(SimTexture texture) { if (_cachedTextures.TryGetValue(texture.dataHash, out Texture cached)){ texture.compiledTexture = cached; @@ -172,43 +165,44 @@ IEnumerator DownloadTextureHTTP(SimTexture texture) if (request.result != UnityWebRequest.Result.Success) { Debug.LogError($"Error downloading mesh data: {request.error}"); + yield break; } - else + texture.textureData = request.downloadHandler.data; + _simTextures.Add(texture.name, texture); + foreach (var visualObj in _pendingTexture[texture.name]) { - // Debug.Log($"Downloaded texture data: {texture.name}"); - texture.textureData = request.downloadHandler.data; - _simTextures.Add(texture.name, texture); + visualObj.GetComponent().material.mainTexture = texture.compiledTexture; } } } } - private void DownloadMesh(SimMesh mesh) { - if (_cachedMeshes.TryGetValue(mesh.dataHash, out Mesh cached)) { - mesh.compiledMesh = cached; - _simMeshes.Add(mesh.name, mesh); - return; - } - Span data = _netManager.RequestBytes("Asset", mesh.dataHash).ToArray(); - mesh.rawData = new SimMeshData - { - indices = MemoryMarshal.Cast(data.Slice(mesh.indicesLayout[0], mesh.indicesLayout[1] * sizeof(int))).ToArray(), - vertices = MemoryMarshal.Cast(data.Slice(mesh.verticesLayout[0], mesh.verticesLayout[1] * sizeof(float))).ToArray(), - normals = MemoryMarshal.Cast(data.Slice(mesh.normalsLayout[0], mesh.normalsLayout[1] * sizeof(float))).ToArray(), - uvs = MemoryMarshal.Cast(data.Slice(mesh.uvLayout[0], mesh.uvLayout[1] * sizeof(float))).ToArray(), - }; - } - - private void DownloadTexture(SimTexture texture) { - if (_cachedTextures.TryGetValue(texture.dataHash, out Texture cached)){ - texture.compiledTexture = cached; - } else { - texture.textureData = _netManager.RequestBytes("Asset", texture.dataHash).ToArray(); - } - - _simTextures.Add(texture.name, texture); - } + // private void DownloadMesh(SimMesh mesh) { + // if (_cachedMeshes.TryGetValue(mesh.dataHash, out Mesh cached)) { + // mesh.compiledMesh = cached; + // _simMeshes.Add(mesh.name, mesh); + // return; + // } + // Span data = _netManager.RequestBytes("Asset", mesh.dataHash).ToArray(); + // mesh.rawData = new SimMeshData + // { + // indices = MemoryMarshal.Cast(data.Slice(mesh.indicesLayout[0], mesh.indicesLayout[1] * sizeof(int))).ToArray(), + // vertices = MemoryMarshal.Cast(data.Slice(mesh.verticesLayout[0], mesh.verticesLayout[1] * sizeof(float))).ToArray(), + // normals = MemoryMarshal.Cast(data.Slice(mesh.normalsLayout[0], mesh.normalsLayout[1] * sizeof(float))).ToArray(), + // uvs = MemoryMarshal.Cast(data.Slice(mesh.uvLayout[0], mesh.uvLayout[1] * sizeof(float))).ToArray(), + // }; + // } + + // private void DownloadTexture(SimTexture texture) { + // if (_cachedTextures.TryGetValue(texture.dataHash, out Texture cached)){ + // texture.compiledTexture = cached; + // } else { + // texture.textureData = _netManager.RequestBytes("Asset", texture.dataHash).ToArray(); + // } + + // _simTextures.Add(texture.name, texture); + // } void Update() { @@ -243,7 +237,7 @@ GameObject CreateObject(Transform root, SimBody body, string name = null) { } SimMesh asset = _simMeshes[visual.mesh]; visualObj = new GameObject(asset.name, typeof(MeshFilter), typeof(MeshRenderer)); - visualObj.GetComponent().mesh = asset.compiledMesh; + _pendingMesh[asset.name] = _pendingMesh.ContainsKey(asset.name) ? _pendingMesh[asset.name] : new List(); break; } case "CUBE": @@ -268,11 +262,12 @@ GameObject CreateObject(Transform root, SimBody body, string name = null) { } Renderer renderer = visualObj.GetComponent(); + renderer.material = new Material(Shader.Find("Standard")); if (visual.material != null) { - renderer.material = GetMaterial(visual.material).compiledMaterial; + _pendingTexture[visual.material] = _pendingTexture.ContainsKey(visual.material) ? _pendingTexture[visual.material] : new List(); + } else { - renderer.material = new Material(Shader.Find("Standard")); if (visual.color[3] < 1) { renderer.material.SetFloat("_Mode", 2); From 24919ff3015f42586b84d4bc8b3593108bb3ce40 Mon Sep 17 00:00:00 2001 From: Xinkai Jiang Date: Sat, 9 Nov 2024 18:19:00 +0100 Subject: [PATCH 3/5] use coroutine for downloading --- Assets/SceneLoader/Scripts/SimData.cs | 26 ++++++++++++------------- Assets/SceneLoader/Scripts/SimLoader.cs | 20 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Assets/SceneLoader/Scripts/SimData.cs b/Assets/SceneLoader/Scripts/SimData.cs index 22c0f62..fc52874 100644 --- a/Assets/SceneLoader/Scripts/SimData.cs +++ b/Assets/SceneLoader/Scripts/SimData.cs @@ -58,7 +58,7 @@ public class SimMeshData { } public class SimMesh : SimAsset { - public string dataHash; + public string hash; public List indicesLayout; public List verticesLayout; @@ -67,16 +67,16 @@ public class SimMesh : SimAsset { public List uvLayout; - [JsonIgnore] - public Mesh compiledMesh; + // [JsonIgnore] + // public Mesh compiledMesh; - [JsonIgnore] - public SimMeshData rawData; + // [JsonIgnore] + // public SimMeshData rawData; } public class SimMaterial : SimAsset { - public string dataHash; + public string hash; public List color; public List emissionColor; public float specular; @@ -85,21 +85,21 @@ public class SimMaterial : SimAsset { public string texture; public List textureSize; - [JsonIgnore] - public Material compiledMaterial; + // [JsonIgnore] + // public Material compiledMaterial; } public class SimTexture : SimAsset { - public string dataHash; + public string hash; public int width; public int height; public string texureType; - [JsonIgnore] - public byte[] textureData; + // [JsonIgnore] + // public byte[] textureData; - [JsonIgnore] - public Texture compiledTexture; + // [JsonIgnore] + // public Texture compiledTexture; } \ No newline at end of file diff --git a/Assets/SceneLoader/Scripts/SimLoader.cs b/Assets/SceneLoader/Scripts/SimLoader.cs index 738a3a1..c095ee8 100644 --- a/Assets/SceneLoader/Scripts/SimLoader.cs +++ b/Assets/SceneLoader/Scripts/SimLoader.cs @@ -116,14 +116,14 @@ private IEnumerator DownloadAllAssets(SimScene scene) IEnumerator DownloadMesh(SimMesh mesh) { - // if (_cachedMeshes.TryGetValue(mesh.dataHash, out Mesh cached)) { + // if (_cachedMeshes.TryGetValue(mesh.hash, out Mesh cached)) { // mesh.compiledMesh = cached; // _simMeshes.Add(mesh.name, mesh); // } // else // { HostInfo serverInfo = _netManager.GetServerInfo(); - string fileUrl = $"http://{serverInfo.ip}:{(int)ServerPort.HTTP}/?asset_tag={mesh.dataHash}"; + string fileUrl = $"http://{serverInfo.ip}:{(int)ServerPort.HTTP}/?asset_tag={mesh.hash}"; using (UnityWebRequest request = UnityWebRequest.Get(fileUrl)) { yield return request.SendWebRequest(); @@ -151,13 +151,13 @@ IEnumerator DownloadMesh(SimMesh mesh) IEnumerator DownloadTexture(SimTexture texture) { - if (_cachedTextures.TryGetValue(texture.dataHash, out Texture cached)){ + if (_cachedTextures.TryGetValue(texture.hash, out Texture cached)){ texture.compiledTexture = cached; } else { HostInfo serverInfo = _netManager.GetServerInfo(); - string fileUrl = $"http://{serverInfo.ip}:{(int)ServerPort.HTTP}/?asset_tag={texture.dataHash}"; + string fileUrl = $"http://{serverInfo.ip}:{(int)ServerPort.HTTP}/?asset_tag={texture.hash}"; using (UnityWebRequest request = UnityWebRequest.Get(fileUrl)) { // Debug.Log($"Downloading texture data: {texture.name}"); @@ -179,12 +179,12 @@ IEnumerator DownloadTexture(SimTexture texture) // private void DownloadMesh(SimMesh mesh) { - // if (_cachedMeshes.TryGetValue(mesh.dataHash, out Mesh cached)) { + // if (_cachedMeshes.TryGetValue(mesh.hash, out Mesh cached)) { // mesh.compiledMesh = cached; // _simMeshes.Add(mesh.name, mesh); // return; // } - // Span data = _netManager.RequestBytes("Asset", mesh.dataHash).ToArray(); + // Span data = _netManager.RequestBytes("Asset", mesh.hash).ToArray(); // mesh.rawData = new SimMeshData // { // indices = MemoryMarshal.Cast(data.Slice(mesh.indicesLayout[0], mesh.indicesLayout[1] * sizeof(int))).ToArray(), @@ -195,10 +195,10 @@ IEnumerator DownloadTexture(SimTexture texture) // } // private void DownloadTexture(SimTexture texture) { - // if (_cachedTextures.TryGetValue(texture.dataHash, out Texture cached)){ + // if (_cachedTextures.TryGetValue(texture.hash, out Texture cached)){ // texture.compiledTexture = cached; // } else { - // texture.textureData = _netManager.RequestBytes("Asset", texture.dataHash).ToArray(); + // texture.textureData = _netManager.RequestBytes("Asset", texture.hash).ToArray(); // } // _simTextures.Add(texture.name, texture); @@ -325,7 +325,7 @@ public void ProcessMesh(SimAsset asset) { mesh.rawData = null; - _cachedMeshes[mesh.dataHash] = mesh.compiledMesh; + _cachedMeshes[mesh.hash] = mesh.compiledMesh; _simMeshes[mesh.name] = mesh; } @@ -362,7 +362,7 @@ public SimAsset ProcessTexture(SimAsset asset) { simTexture.textureData = null; simTexture.compiledTexture = tex; - _cachedTextures[simTexture.dataHash] = simTexture.compiledTexture; + _cachedTextures[simTexture.hash] = simTexture.compiledTexture; return asset; } From bad3cd0fb5450174ea52a5ffdd1c988b5d87b20c Mon Sep 17 00:00:00 2001 From: Xinkai Jiang Date: Mon, 11 Nov 2024 15:49:38 +0100 Subject: [PATCH 4/5] typo --- Assets/IRXRClient/Scripts/IRXRNetManager.cs | 18 +++++++++--------- Assets/SceneLoader/Scripts/SimLoader.cs | 6 ++++++ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Assets/IRXRClient/Scripts/IRXRNetManager.cs b/Assets/IRXRClient/Scripts/IRXRNetManager.cs index 9592526..7bf8e63 100644 --- a/Assets/IRXRClient/Scripts/IRXRNetManager.cs +++ b/Assets/IRXRClient/Scripts/IRXRNetManager.cs @@ -79,16 +79,16 @@ void Awake() { // Default host name if (PlayerPrefs.HasKey("HostName")) { - // The key exists, proceed to get the value - string savedHostName = PlayerPrefs.GetString("HostName"); - _localInfo.name = savedHostName; - Debug.Log($"Find Host Name: {_localInfo.name}"); + // The key exists, proceed to get the value + string savedHostName = PlayerPrefs.GetString("HostName"); + _localInfo.name = savedHostName; + Debug.Log($"Find Host Name: {_localInfo.name}"); } else { - // The key does not exist, handle it accordingly - _localInfo.name = "UnityClient"; - Debug.Log($"Host Name not found, using default name {_localInfo.name}"); + // The key does not exist, handle it accordingly + _localInfo.name = "UnityClient"; + Debug.Log($"Host Name not found, using default name {_localInfo.name}"); } } @@ -100,7 +100,7 @@ void Start() { ConnectionSpin += () => {}; OnDisconnected += StopConnection; lastTimeStamp = -1.0f; - RegisterServiceCallback("ChangeHostName", ChangeHoseName); + RegisterServiceCallback("ChangeHostName", ChangeHostName); } void Update() { @@ -317,7 +317,7 @@ private static bool IsInSameSubnet(IPAddress ip1, IPAddress ip2, IPAddress subne return true; } - public string ChangeHoseName(string name) { + public string ChangeHostName(string name) { _localInfo.name = name; PlayerPrefs.SetString("HostName", name); Debug.Log($"Change Host Name to {_localInfo.name}"); diff --git a/Assets/SceneLoader/Scripts/SimLoader.cs b/Assets/SceneLoader/Scripts/SimLoader.cs index c095ee8..de26a1a 100644 --- a/Assets/SceneLoader/Scripts/SimLoader.cs +++ b/Assets/SceneLoader/Scripts/SimLoader.cs @@ -42,6 +42,12 @@ void Start() { updateAction = () => { }; OnSceneLoaded += () => Debug.Log("Scene Loaded"); OnSceneCleared += () => Debug.Log("Scene Cleared"); + _netManager.RegisterServiceCallback("ClearScene", LoadPointCloud); + } + + private void LoadSimScene(string pointCloudStrData) { + ClearScene(); + } void BuildScene() { From 7fc801bae7e77a588b1cc5ae8e64fd5dad172c18 Mon Sep 17 00:00:00 2001 From: Xinkai Jiang Date: Mon, 11 Nov 2024 21:27:47 +0100 Subject: [PATCH 5/5] simplify the simdata --- Assets/IRXRClient/Scripts/IRXRNetManager.cs | 2 +- Assets/SceneLoader/Scripts/SimData.cs | 30 +- Assets/SceneLoader/Scripts/SimLoader.cs | 325 +++++++------------- 3 files changed, 123 insertions(+), 234 deletions(-) diff --git a/Assets/IRXRClient/Scripts/IRXRNetManager.cs b/Assets/IRXRClient/Scripts/IRXRNetManager.cs index 9c340f6..fda4468 100644 --- a/Assets/IRXRClient/Scripts/IRXRNetManager.cs +++ b/Assets/IRXRClient/Scripts/IRXRNetManager.cs @@ -15,7 +15,6 @@ public enum ServerPort { Discovery = 7720, Service = 7721, Topic = 7722, - HTTP = 7723, } public enum ClientPort { @@ -233,6 +232,7 @@ public void ServiceRespondSpin() { if (!_resSocket.HasIn) return; string messageReceived = _resSocket.ReceiveFrameString(); string[] messageSplit = messageReceived.Split(":", 2); + Debug.Log($"Received service request {messageSplit[0]}"); if (_serviceCallbacks.ContainsKey(messageSplit[0])) { string response = _serviceCallbacks[messageSplit[0]](messageSplit[1]); _resSocket.SendFrame(response); diff --git a/Assets/SceneLoader/Scripts/SimData.cs b/Assets/SceneLoader/Scripts/SimData.cs index e3facd2..736668f 100644 --- a/Assets/SceneLoader/Scripts/SimData.cs +++ b/Assets/SceneLoader/Scripts/SimData.cs @@ -22,12 +22,10 @@ public Vector3 GetScale() { } public class SimVisual { - // public string name; public string type; - public string mesh; - public string material; + public SimMesh mesh; + public SimMaterial material; public SimTransform trans; - public List color; } @@ -53,19 +51,10 @@ public class SimAsset { public class SimMesh : SimAsset { public string hash; public List indicesLayout; - public List verticesLayout; - public List normalsLayout; - public List uvLayout; - // [JsonIgnore] - // public Mesh compiledMesh; - - - // [JsonIgnore] - // public SimMeshData rawData; } public class SimMaterial : SimAsset { @@ -75,24 +64,13 @@ public class SimMaterial : SimAsset { public float specular; public float shininess; public float reflectance; - public string texture; - public List textureSize; - - // [JsonIgnore] - // public Material compiledMaterial; + public SimTexture texture; } public class SimTexture : SimAsset { public string hash; public int width; - public int height; - public string texureType; - - // [JsonIgnore] - // public byte[] textureData; - - // [JsonIgnore] - // public Texture compiledTexture; + public List textureSize; } \ No newline at end of file diff --git a/Assets/SceneLoader/Scripts/SimLoader.cs b/Assets/SceneLoader/Scripts/SimLoader.cs index 5b936a0..28a118b 100644 --- a/Assets/SceneLoader/Scripts/SimLoader.cs +++ b/Assets/SceneLoader/Scripts/SimLoader.cs @@ -13,7 +13,6 @@ public class SceneLoader : MonoBehaviour { - private object updateActionLock = new(); private Action updateAction; public Action OnSceneLoaded; @@ -22,118 +21,73 @@ public class SceneLoader : MonoBehaviour { private GameObject _simSceneObj; private SimScene _simScene; private Dictionary _simObjTrans = new (); - - // private Dictionary _simMeshes; - // private Dictionary _simMaterials; - // private Dictionary _simTextures; - // private Dictionary _cachedMeshes; - // private Dictionary _cachedTextures; - - private Dictionary> _pendingMesh = new (); - private Dictionary> _pendingMaterial = new (); + private Dictionary>> _pendingMesh = new (); + private Dictionary>> _pendingTexture = new (); - void Awake() { - // _simMeshes = new(); - // _simMaterials = new(); - // _simTextures = new(); - - // _cachedTextures = new(); - // _cachedMeshes = new(); - } - void Start() { _netManager = IRXRNetManager.Instance; _netManager.OnDisconnected += ClearScene; - _netManager.OnConnectionStart += DownloadScene; updateAction = () => { }; OnSceneLoaded += () => Debug.Log("Scene Loaded"); OnSceneCleared += () => Debug.Log("Scene Cleared"); - _netManager.RegisterServiceCallback("ClearScene", LoadPointCloud); + _netManager.RegisterServiceCallback("LoadSimScene", LoadSimScene); } - private void LoadSimScene(string pointCloudStrData) { + private string LoadSimScene(string simSceneJsonStr) { ClearScene(); - + _simScene = JsonConvert.DeserializeObject(simSceneJsonStr); + updateAction += BuildScene; + Debug.Log("Downloaded scene json and starting to build scene"); + return "Received Scene"; } void BuildScene() { // Don't include System.Diagnostics, Debug becomes disambiguous + // It is more accurate to use System.Diagnostics.Stopwatch, theoretically var local_watch = new System.Diagnostics.Stopwatch(); local_watch.Start(); Debug.Log("Building Scene"); _simSceneObj = CreateObject(gameObject.transform, _simScene.root); local_watch.Stop(); Debug.Log($"Building Scene in {local_watch.ElapsedMilliseconds} ms"); - OnSceneLoaded.Invoke(); + Task.Run(() => DownloadAssets()); } - private void DownloadScene() { - + public void DownloadAssets() { var local_watch = new System.Diagnostics.Stopwatch(); local_watch.Start(); - - if (!_netManager.CheckServerService("Scene")) { - Debug.LogWarning("Scene Service is not found"); - return; + int totalMeshSize = 0; + int totalTextureSize = 0; + foreach (string hash in _pendingMesh.Keys) + { + byte[] meshData = _netManager.RequestBytes("Asset", hash).ToArray(); + foreach (Tuple pair in _pendingMesh[hash]) + { + RunOnMainThread(() => BuildMesh(pair.Item1, pair.Item2, meshData)); + } + totalMeshSize += meshData.Length; } - - string asset_info = _netManager.RequestString("Scene"); - - if (asset_info == "Invalid Service") { - Debug.LogWarning("Invalid Service"); - return; + foreach (string hash in _pendingTexture.Keys) + { + byte[] texData = _netManager.RequestBytes("Asset", hash).ToArray(); + foreach (Tuple pair in _pendingTexture[hash]) + { + RunOnMainThread(() => BuildTexture(pair.Item1, pair.Item2, texData)); + } + totalTextureSize += texData.Length; } - - _simScene = JsonConvert.DeserializeObject(asset_info); - DownloadAssets(_simScene); + double meshSizeMB = Math.Round(totalMeshSize / Math.Pow(2, 20), 2); + double textureSizeMB = Math.Round(totalTextureSize / Math.Pow(2, 20), 2); local_watch.Stop(); - Debug.Log($"Downloaded Scene in {local_watch.ElapsedMilliseconds} ms"); - updateAction += BuildScene; + _pendingMesh.Clear(); + _pendingTexture.Clear(); + // When debug run in the subthread, it will not send the log to the server + RunOnMainThread(() => Debug.Log($"Downloaded {meshSizeMB}MB meshes, {textureSizeMB}MB textures.")); + RunOnMainThread(() => Debug.Log($"Downloading Asset in {local_watch.ElapsedMilliseconds} ms")); + RunOnMainThread(() => OnSceneLoaded.Invoke()); } - public void DownloadAssets(SimScene scene) { - _simMeshes.Clear(); - _simMaterials.Clear(); - _simTextures.Clear(); - - int textureSizeAcc = 0; - int meshSizeAcc = 0; - - scene.meshes.ForEach(mesh => { - meshSizeAcc += DownloadMesh(mesh); - }); - scene.textures.ForEach(texture => { - textureSizeAcc += DownloadTexture(texture); - }); - scene.materials.ForEach(material => _simMaterials.Add(material.name, material)); - - print($"Downloaded {Math.Round(meshSizeAcc / Math.Pow(2, 20), 2)}MB meshes, {Math.Round(textureSizeAcc / Math.Pow(2, 20), 2)}MB textures, {scene.materials.Count} materials"); - } - - private int DownloadMesh(SimMesh mesh) { - int meshSize = 0; - if (!_cachedMeshes.TryGetValue(mesh.dataHash, out mesh.compiledMesh)) { - byte[] data = _netManager.RequestBytes("Asset", mesh.dataHash).ToArray(); - meshSize += data.Length; - RunOnMainThread(() => ProcessMesh(mesh, data)); - } - _simMeshes.TryAdd(mesh.name, mesh); - return meshSize; - } - - private int DownloadTexture(SimTexture texture) { - int textureSize = 0; - if (!_cachedTextures.TryGetValue(texture.dataHash, out texture.compiledTexture)){ - List data = _netManager.RequestBytes("Asset", texture.dataHash); - textureSize = data.Count; - RunOnMainThread(() => ProcessTexture(texture, data)); - } - _simTextures.TryAdd(texture.name, texture); - return textureSize; - } - - void RunOnMainThread(Action action) { lock(updateActionLock) { updateAction += action; @@ -147,76 +101,63 @@ void Update() { } } - void ApplyTransform(Transform utransform, SimTransform trans) { utransform.localPosition = trans.GetPos(); utransform.localRotation = trans.GetRot(); utransform.localScale = trans.GetScale(); } - GameObject CreateObject(Transform root, SimBody body) { GameObject bodyRoot = new GameObject(body.name); bodyRoot.transform.SetParent(root, false); ApplyTransform(bodyRoot.transform, body.trans); - - GameObject VisualContainer = new GameObject("Visuals"); - VisualContainer.transform.SetParent(bodyRoot.transform, false); - - foreach (SimVisual visual in body.visuals) { - GameObject visualObj; - switch (visual.type) { - case "MESH": { - if (!_simMeshes.ContainsKey(visual.mesh)) { - Debug.LogWarning("Mesh not found, " + visual.mesh); - visualObj = GameObject.CreatePrimitive(PrimitiveType.Sphere); - visualObj.transform.localScale = new Vector3(0.01f, 0.01f, 0.01f); + if (body.visuals.Count != 0) { + GameObject VisualContainer = new GameObject($"{body.name}_Visuals"); + VisualContainer.transform.SetParent(bodyRoot.transform, false); + foreach (SimVisual visual in body.visuals) { + GameObject visualObj; + switch (visual.type) { + case "MESH": { + SimMesh simMesh = visual.mesh; + visualObj = new GameObject(simMesh.hash, typeof(MeshFilter), typeof(MeshRenderer)); + if (!_pendingMesh.ContainsKey(simMesh.hash)) { + _pendingMesh[simMesh.hash] = new(); + } + _pendingMesh[simMesh.hash].Add(new Tuple(simMesh, visualObj.GetComponent())); break; } - SimMesh asset = _simMeshes[visual.mesh]; - visualObj = new GameObject(asset.name, typeof(MeshFilter), typeof(MeshRenderer)); - _pendingMesh[asset.name] = _pendingMesh.ContainsKey(asset.name) ? _pendingMesh[asset.name] : new List(); - break; + case "CUBE": + visualObj = GameObject.CreatePrimitive(PrimitiveType.Cube); + break; + case "PLANE": + visualObj = GameObject.CreatePrimitive(PrimitiveType.Plane); + break; + case "CYLINDER": + visualObj = GameObject.CreatePrimitive(PrimitiveType.Cylinder); + break; + case "CAPSULE": + visualObj = GameObject.CreatePrimitive(PrimitiveType.Capsule); + break; + case "SPHERE": + visualObj = GameObject.CreatePrimitive(PrimitiveType.Sphere); + break; + default: + Debug.LogWarning("Invalid visual, " + visual.type + body.name); + visualObj = GameObject.CreatePrimitive(PrimitiveType.Sphere); + break; } - case "CUBE": - visualObj = GameObject.CreatePrimitive(PrimitiveType.Cube); - break; - case "PLANE": - visualObj = GameObject.CreatePrimitive(PrimitiveType.Plane); - break; - case "CYLINDER": - visualObj = GameObject.CreatePrimitive(PrimitiveType.Cylinder); - break; - case "CAPSULE": - visualObj = GameObject.CreatePrimitive(PrimitiveType.Capsule); - break; - case "SPHERE": - visualObj = GameObject.CreatePrimitive(PrimitiveType.Sphere); - break; - default: - Debug.LogWarning("Invalid visual, " + visual.type + body.name); - visualObj = GameObject.CreatePrimitive(PrimitiveType.Sphere); - break; - } - - Renderer renderer = visualObj.GetComponent(); - renderer.material = new Material(Shader.Find("Standard")); - if (visual.material != null) { - var material = GetMaterial(visual.material); - if (material.compiledMaterial == null) { - ProcessMaterial(material); + Renderer renderer = visualObj.GetComponent(); + if (visual.material != null) { + renderer.material = BuildMaterial(visual.material, body.name); } - renderer.material = material.compiledMaterial; - } - else { - renderer.material = CreateColorMaterial(visual.color); + else { + Debug.LogWarning($"Material of {body.name}_Visuals not found"); + } + visualObj.transform.SetParent(VisualContainer.transform, false); + ApplyTransform(visualObj.transform, visual.trans); } - - visualObj.transform.SetParent(VisualContainer.transform, false); - ApplyTransform(visualObj.transform, visual.trans); } - body.children.ForEach(body => CreateObject(bodyRoot.transform, body)); _simObjTrans.Add(body.name, bodyRoot.transform); return bodyRoot; @@ -225,88 +166,58 @@ GameObject CreateObject(Transform root, SimBody body) { void ClearScene() { OnSceneCleared.Invoke(); if (_simSceneObj != null) Destroy(_simSceneObj); - _simSceneObj = null; + _pendingMesh.Clear(); + _pendingTexture.Clear(); _simObjTrans.Clear(); - _simMeshes.Clear(); - _simMaterials.Clear(); - _simTextures.Clear(); } - public SimMesh GetMesh(string id) => _simMeshes[id]; - public SimTexture GetTexture(string id) => _simTextures[id]; - public SimMaterial GetMaterial(string id) => _simMaterials[id]; - - public Material CreateColorMaterial(List color) { - var material = new Material(Shader.Find("Standard")); - if (color[3] < 1) + public Material BuildMaterial(SimMaterial simMat, string objName) { + Material mat = new Material(Shader.Find("Standard")); + // Transparency + if (simMat.color[3] < 1) { - material.SetFloat("_Mode", 2); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetInt("_ZWrite", 0); - material.DisableKeyword("_ALPHATEST_ON"); - material.EnableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.renderQueue = 3000; + mat.SetFloat("_Mode", 2); + mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); + mat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + mat.SetInt("_ZWrite", 0); + mat.DisableKeyword("_ALPHATEST_ON"); + mat.EnableKeyword("_ALPHABLEND_ON"); + mat.DisableKeyword("_ALPHAPREMULTIPLY_ON"); + mat.renderQueue = 3000; + } + mat.SetColor("_Color", new Color(simMat.color[0], simMat.color[1], simMat.color[2], simMat.color[3])); + if (simMat.emissionColor != null){ + mat.SetColor("_emissionColor", new Color(simMat.emissionColor[0], simMat.emissionColor[1], simMat.emissionColor[2], simMat.emissionColor[3])); + } + mat.SetFloat("_specularHighlights", simMat.specular); + mat.SetFloat("_Smoothness", simMat.shininess); + mat.SetFloat("_GlossyReflections", simMat.reflectance); + if (simMat.texture != null) { + Debug.Log($"Texture found for {objName}"); + SimTexture simTex = simMat.texture; + if (!_pendingTexture.ContainsKey(simTex.hash)) { + _pendingTexture[simTex.hash] = new (); + } + _pendingTexture[simTex.hash].Add(new Tuple(simTex, mat)); } - material.SetColor("_Color", new Color(color[0], color[1], color[2], color[3])); - return material; + return mat; } - public void ProcessMesh(SimAsset asset, byte[] data) { - SimMesh mesh = (SimMesh)asset; - - - mesh.compiledMesh = new Mesh{ - name = asset.name, - vertices = MemoryMarshal.Cast(new ReadOnlySpan(data, mesh.verticesLayout[0], mesh.verticesLayout[1] * sizeof(float))).ToArray(), - normals = MemoryMarshal.Cast(new ReadOnlySpan(data, mesh.normalsLayout[0], mesh.normalsLayout[1] * sizeof(float))).ToArray(), - triangles = MemoryMarshal.Cast(new ReadOnlySpan(data, mesh.indicesLayout[0], mesh.indicesLayout[1] * sizeof(int))).ToArray(), - uv = MemoryMarshal.Cast(new ReadOnlySpan(data, mesh.uvLayout[0], mesh.uvLayout[1] * sizeof(float))).ToArray() + public void BuildMesh(SimMesh simMesh, MeshFilter meshFilter, byte[] meshData) { + meshFilter.mesh = new Mesh{ + vertices = MemoryMarshal.Cast(new ReadOnlySpan(meshData, simMesh.verticesLayout[0], simMesh.verticesLayout[1] * sizeof(float))).ToArray(), + normals = MemoryMarshal.Cast(new ReadOnlySpan(meshData, simMesh.normalsLayout[0], simMesh.normalsLayout[1] * sizeof(float))).ToArray(), + triangles = MemoryMarshal.Cast(new ReadOnlySpan(meshData, simMesh.indicesLayout[0], simMesh.indicesLayout[1] * sizeof(int))).ToArray(), + uv = MemoryMarshal.Cast(new ReadOnlySpan(meshData, simMesh.uvLayout[0], simMesh.uvLayout[1] * sizeof(float))).ToArray() }; - - _cachedMeshes[mesh.hash] = mesh.compiledMesh; - _simMeshes[mesh.name] = mesh; } - public void ProcessMaterial(SimAsset asset) { - SimMaterial material = (SimMaterial)asset; - - Material mat = new Material(Shader.Find("Standard")); - - mat.SetColor("_Color", new Color(material.color[0], material.color[1], material.color[2], material.color[3])); - mat.SetColor("_emissionColor", new Color(material.emissionColor[0], material.emissionColor[1], material.emissionColor[2], material.emissionColor[3])); - mat.SetFloat("_specularHighlights", material.specular); - mat.SetFloat("_Smoothness", material.shininess); - mat.SetFloat("_GlossyReflections", material.reflectance); - - if (material.texture != null) { - SimTexture texture = _simTextures[material.texture]; - - _simTextures[material.texture] = texture; // Just to be shure the texture is updated (investigate) - - mat.mainTexture = texture.compiledTexture; - mat.mainTextureScale = new Vector2(material.textureSize[0], material.textureSize[1]); - } - - material.compiledMaterial = mat; - _simMaterials[material.name] = material; - } - - public SimAsset ProcessTexture(SimAsset asset, List data) { - SimTexture simTexture = (SimTexture)asset; - - byte[] byteData = data.ToArray(); - data.Clear(); - data = null; - - var tex = new Texture2D(simTexture.width, simTexture.height, TextureFormat.RGB24, false); - tex.LoadRawTextureData(byteData); + public void BuildTexture(SimTexture simTex, Material material, byte[] texData) { + Texture2D tex = new Texture2D(simTex.width, simTex.height, TextureFormat.RGB24, false); + tex.LoadRawTextureData(texData); tex.Apply(); - - simTexture.compiledTexture = tex; - _cachedTextures[simTexture.hash] = simTexture.compiledTexture; - return asset; + material.mainTexture = tex; + material.mainTextureScale = new Vector2(simTex.textureSize[0], simTex.textureSize[1]); } public Dictionary GetObjectsTrans() {