From c50ca1484cdeb75b2be3b18212bcc79d33a4540e Mon Sep 17 00:00:00 2001 From: chorome Date: Wed, 1 Jul 2020 14:24:33 +0900 Subject: [PATCH] load balance BuildMesh --- .../VRM/UniGLTF/Scripts/IO/ImporterContext.cs | 59 +++++--- Assets/VRM/UniGLTF/Scripts/IO/MeshImporter.cs | 129 ++++++++++++++++++ 2 files changed, 166 insertions(+), 22 deletions(-) diff --git a/Assets/VRM/UniGLTF/Scripts/IO/ImporterContext.cs b/Assets/VRM/UniGLTF/Scripts/IO/ImporterContext.cs index d659a1fa9..e1cc1ad69 100644 --- a/Assets/VRM/UniGLTF/Scripts/IO/ImporterContext.cs +++ b/Assets/VRM/UniGLTF/Scripts/IO/ImporterContext.cs @@ -372,6 +372,9 @@ namespace UniGLTF #endregion #region Load. Build unity objects + + public bool EnableLoadBalancing; + /// /// ReadAllBytes, Parse, Create GameObject /// @@ -560,28 +563,7 @@ namespace UniGLTF return meshImporter.ReadMesh(this, index); } }) - .ContinueWith(Scheduler.MainThread, x => - { - using (MeasureTime("BuildMesh")) - { - var meshWithMaterials = MeshImporter.BuildMesh(this, x); - - var mesh = meshWithMaterials.Mesh; - - // mesh name - if (string.IsNullOrEmpty(mesh.name)) - { - mesh.name = string.Format("UniGLTF import#{0}", i); - } - var originalName = mesh.name; - for (int j = 1; Meshes.Any(y => y.Mesh.name == mesh.name); ++j) - { - mesh.name = string.Format("{0}({1})", originalName, j); - } - - return meshWithMaterials; - } - }) + .ContinueWithCoroutine(Scheduler.MainThread, x => BuildMesh(x, index)) .ContinueWith(Scheduler.ThreadPool, x => Meshes.Add(x)) ; } @@ -654,6 +636,39 @@ namespace UniGLTF } yield return null; } + + IEnumerator BuildMesh(MeshImporter.MeshContext x, int i) + { + using (MeasureTime("BuildMesh")) + { + MeshWithMaterials meshWithMaterials; + if (EnableLoadBalancing) + { + var buildMesh = MeshImporter.BuildMeshCoroutine(this, x); + yield return buildMesh; + meshWithMaterials = buildMesh.Current as MeshWithMaterials; + } + else + { + meshWithMaterials = MeshImporter.BuildMesh(this, x); + } + + var mesh = meshWithMaterials.Mesh; + + // mesh name + if (string.IsNullOrEmpty(mesh.name)) + { + mesh.name = string.Format("UniGLTF import#{0}", i); + } + var originalName = mesh.name; + for (int j = 1; Meshes.Any(y => y.Mesh.name == mesh.name); ++j) + { + mesh.name = string.Format("{0}({1})", originalName, j); + } + + yield return meshWithMaterials; + } + } IEnumerator LoadMeshes() { diff --git a/Assets/VRM/UniGLTF/Scripts/IO/MeshImporter.cs b/Assets/VRM/UniGLTF/Scripts/IO/MeshImporter.cs index e233eeacf..ad73e5829 100644 --- a/Assets/VRM/UniGLTF/Scripts/IO/MeshImporter.cs +++ b/Assets/VRM/UniGLTF/Scripts/IO/MeshImporter.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; @@ -656,6 +657,134 @@ namespace UniGLTF return result; } + + public static IEnumerator BuildMeshCoroutine(ImporterContext ctx, MeshImporter.MeshContext meshContext) + { + if (!meshContext.materialIndices.Any()) + { + meshContext.materialIndices.Add(0); + } + + var mesh = new Mesh(); + mesh.name = meshContext.name; + + if (meshContext.positions.Length > UInt16.MaxValue) + { +#if UNITY_2017_3_OR_NEWER + mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; +#else + Debug.LogWarningFormat("vertices {0} exceed 65535. not implemented. Unity2017.3 supports large mesh", + meshContext.positions.Length); +#endif + } + + + mesh.vertices = meshContext.positions; + bool recalculateNormals = false; + if (meshContext.normals != null && meshContext.normals.Length > 0) + { + + mesh.normals = meshContext.normals; + } + else + { + recalculateNormals = true; + } + + if (meshContext.uv != null && meshContext.uv.Length > 0) + { + + mesh.uv = meshContext.uv; + } + + bool recalculateTangents = true; +#if UNIGLTF_IMPORT_TANGENTS + if (meshContext.tangents != null && meshContext.tangents.Length > 0) + { + mesh.tangents = meshContext.tangents; + recalculateTangents = false; + } +#endif + + if (meshContext.colors != null && meshContext.colors.Length > 0) + { + + mesh.colors = meshContext.colors; + } + if (meshContext.boneWeights != null && meshContext.boneWeights.Count > 0) + { + mesh.boneWeights = meshContext.boneWeights.ToArray(); + } + mesh.subMeshCount = meshContext.subMeshes.Count; + for (int i = 0; i < meshContext.subMeshes.Count; ++i) + { + mesh.SetTriangles(meshContext.subMeshes[i], i); + } + + if (recalculateNormals) + { + mesh.RecalculateNormals(); + } + if (recalculateTangents) + { +#if UNITY_5_6_OR_NEWER + yield return null; + mesh.RecalculateTangents(); + yield return null; +#else + CalcTangents(mesh); +#endif + } + + var result = new MeshWithMaterials + { + Mesh = mesh, + Materials = meshContext.materialIndices.Select(x => ctx.GetMaterial(x)).ToArray() + }; + + yield return null; + if (meshContext.blendShapes != null) + { + Vector3[] emptyVertices = null; + + foreach (var blendShape in meshContext.blendShapes) + { + if (blendShape.Positions.Count > 0) + { + if (blendShape.Positions.Count == mesh.vertexCount) + { + mesh.AddBlendShapeFrame(blendShape.Name, FRAME_WEIGHT, + blendShape.Positions.ToArray(), + (meshContext.normals != null && meshContext.normals.Length == mesh.vertexCount && blendShape.Normals.Count() == blendShape.Positions.Count()) ? blendShape.Normals.ToArray() : null, + null + ); + yield return null; + } + else + { + Debug.LogWarningFormat("May be partial primitive has blendShape. Require separate mesh or extend blend shape, but not implemented: {0}", blendShape.Name); + } + } + else + { + if (emptyVertices == null) + { + emptyVertices = new Vector3[mesh.vertexCount]; + } + // Debug.LogFormat("empty blendshape: {0}.{1}", mesh.name, blendShape.Name); + // add empty blend shape for keep blend shape index + mesh.AddBlendShapeFrame(blendShape.Name, FRAME_WEIGHT, + emptyVertices, + null, + null + ); + yield return null; + } + } + } + + yield return result; + } /// /// Meshの法線を元にタンジェントを計算する。