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の法線を元にタンジェントを計算する。