load balance BuildMesh

This commit is contained in:
chorome 2020-07-01 14:24:33 +09:00
parent 1b85a49836
commit c50ca1484c
2 changed files with 166 additions and 22 deletions

View File

@ -372,6 +372,9 @@ namespace UniGLTF
#endregion
#region Load. Build unity objects
public bool EnableLoadBalancing;
/// <summary>
/// ReadAllBytes, Parse, Create GameObject
/// </summary>
@ -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<MeshWithMaterials>(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()
{

View File

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