mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-05-12 21:45:06 -05:00
Merge pull request #451 from chromee/load-balance-build-mesh
BuildMesh load balancing in ImporterContext
This commit is contained in:
commit
12715778f0
|
|
@ -75,10 +75,18 @@ namespace DepthFirstScheduler
|
|||
#region CoroutineFunctor
|
||||
public class CoroutineFunctor<T> : IFunctor<T>
|
||||
{
|
||||
T m_result;
|
||||
public T GetResult()
|
||||
{
|
||||
return m_result;
|
||||
if (m_last?.Current == null) return default;
|
||||
|
||||
try
|
||||
{
|
||||
return (T)m_last.Current;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
Exception m_error;
|
||||
|
|
@ -87,12 +95,11 @@ namespace DepthFirstScheduler
|
|||
return m_error;
|
||||
}
|
||||
|
||||
Func<T> m_arg;
|
||||
Func<T, IEnumerator> m_starter;
|
||||
Func<IEnumerator> m_starter;
|
||||
Stack<IEnumerator> m_it;
|
||||
public CoroutineFunctor(Func<T> arg, Func<T, IEnumerator> starter)
|
||||
private IEnumerator m_last;
|
||||
public CoroutineFunctor(Func<IEnumerator> starter)
|
||||
{
|
||||
m_arg = arg;
|
||||
m_starter = starter;
|
||||
}
|
||||
|
||||
|
|
@ -100,9 +107,8 @@ namespace DepthFirstScheduler
|
|||
{
|
||||
if (m_it == null)
|
||||
{
|
||||
m_result = m_arg();
|
||||
m_it = new Stack<IEnumerator>();
|
||||
m_it.Push(m_starter(m_result));
|
||||
m_it.Push(m_starter());
|
||||
}
|
||||
|
||||
try
|
||||
|
|
@ -119,7 +125,7 @@ namespace DepthFirstScheduler
|
|||
}
|
||||
else
|
||||
{
|
||||
m_it.Pop();
|
||||
m_last = m_it.Pop();
|
||||
}
|
||||
return ExecutionStatus.Continue;
|
||||
}
|
||||
|
|
@ -139,9 +145,11 @@ namespace DepthFirstScheduler
|
|||
|
||||
public static class CoroutineFunctor
|
||||
{
|
||||
public static CoroutineFunctor<T> Create<T>(Func<T> arg, Func<T, IEnumerator> starter)
|
||||
/// <typeparam name="S">引数の型</typeparam>
|
||||
/// <typeparam name="T">結果の型</typeparam>
|
||||
public static CoroutineFunctor<T> Create<S, T>(Func<S> arg, Func<S, IEnumerator> starter)
|
||||
{
|
||||
return new CoroutineFunctor<T>(arg, starter);
|
||||
return new CoroutineFunctor<T>(() => starter(arg()));
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
|
|
|||
|
|
@ -137,10 +137,10 @@ namespace DepthFirstScheduler
|
|||
return schedulable;
|
||||
}
|
||||
|
||||
public Schedulable<T> AddCoroutine(IScheduler scheduler, Func<IEnumerator> starter)
|
||||
public Schedulable<Unit> AddCoroutine(IScheduler scheduler, Func<IEnumerator> starter)
|
||||
{
|
||||
var func = CoroutineFunctor.Create(() => default(T), _ => starter());
|
||||
var schedulable = new Schedulable<T>(scheduler, func);
|
||||
var func = CoroutineFunctor.Create<Unit, Unit>(() => default(Unit), _ => starter());
|
||||
var schedulable = new Schedulable<Unit>(scheduler, func);
|
||||
AddChild(schedulable);
|
||||
return schedulable;
|
||||
}
|
||||
|
|
@ -168,15 +168,26 @@ namespace DepthFirstScheduler
|
|||
return schedulable;
|
||||
}
|
||||
|
||||
public Schedulable<T> ContinueWithCoroutine(IScheduler scheduler, Func<IEnumerator> starter)
|
||||
public Schedulable<Unit> ContinueWithCoroutine(IScheduler scheduler, Func<IEnumerator> starter)
|
||||
{
|
||||
return ContinueWithCoroutine<Unit>(scheduler, _ => starter());
|
||||
}
|
||||
|
||||
public Schedulable<U> ContinueWithCoroutine<U>(IScheduler scheduler, Func<T, IEnumerator> starter)
|
||||
{
|
||||
if (Parent == null)
|
||||
{
|
||||
throw new NoParentException();
|
||||
}
|
||||
|
||||
var func = CoroutineFunctor.Create(() => default(T), _ => starter());
|
||||
var schedulable = new Schedulable<T>(scheduler, func);
|
||||
Func<T> getResult = null;
|
||||
if (Func != null)
|
||||
{
|
||||
getResult = Func.GetResult;
|
||||
}
|
||||
|
||||
var func = CoroutineFunctor.Create<T, U>(getResult, starter);
|
||||
var schedulable = new Schedulable<U>(scheduler, func);
|
||||
Parent.AddChild(schedulable);
|
||||
return schedulable;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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の法線を元にタンジェントを計算する。
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user