diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs index 003c8063e..8ff75af30 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs @@ -167,7 +167,6 @@ namespace UniGLTF { var inverter = InvertAxis.Create(); - var meshImporter = new MeshImporter(); if (GLTF.meshes.Count > 0) { for (var i = 0; i < GLTF.meshes.Count; ++i) @@ -175,7 +174,7 @@ namespace UniGLTF var index = i; using (MeasureTime("ReadMesh")) { - var meshContext = await awaitCaller.Run(() => meshImporter.ReadMesh(Data, index, inverter)); + var meshContext = await awaitCaller.Run(() => MeshContext.CreateFromGltf(Data, index, inverter)); var meshWithMaterials = await BuildMeshAsync(awaitCaller, MeasureTime, meshContext, index); Meshes.Add(meshWithMaterials); } @@ -290,11 +289,11 @@ namespace UniGLTF return Task.FromResult(null); } - async Task BuildMeshAsync(IAwaitCaller awaitCaller, Func MeasureTime, MeshContext x, int i) + async Task BuildMeshAsync(IAwaitCaller awaitCaller, Func MeasureTime, MeshContext meshContext, int i) { using (MeasureTime("BuildMesh")) { - var meshWithMaterials = await MeshImporter.BuildMeshAsync(awaitCaller, MaterialFactory.GetMaterial, x); + var meshWithMaterials = await meshContext.BuildMeshAsync(awaitCaller, MaterialFactory.GetMaterial); var mesh = meshWithMaterials.Mesh; // mesh name diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshContext.cs index 48e54d0a9..7794c92c2 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshContext.cs @@ -1,14 +1,18 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using UnityEngine; using UnityEngine.Profiling; using UnityEngine.Rendering; +using VRMShaders; namespace UniGLTF { internal class MeshContext { + private const float FrameWeight = 100.0f; + private readonly List _vertices = new List(); private readonly List _skinnedMeshVertices = new List(); private readonly List _indices = new List(); @@ -16,12 +20,60 @@ namespace UniGLTF private readonly List _materialIndices = new List(); private readonly List _blendShapes = new List(); - public IReadOnlyList MaterialIndices => _materialIndices; - public IReadOnlyList BlendShapes => _blendShapes; + private bool HasNormal { get; set; } = true; - public bool HasNormal { get; private set; } = true; + private string Name { get; } - public string Name { get; } + MeshContext(string name, int meshIndex) + { + if (string.IsNullOrEmpty(name)) + { + name = $"UniGLTF import#{meshIndex}"; + } + + Name = name; + } + + private static bool HasSharedVertexBuffer(glTFMesh gltfMesh) + { + glTFAttributes lastAttributes = null; + var sharedAttributes = true; + foreach (var prim in gltfMesh.primitives) + { + if (lastAttributes != null && !prim.attributes.Equals(lastAttributes)) + { + sharedAttributes = false; + break; + } + + lastAttributes = prim.attributes; + } + + return sharedAttributes; + } + + public static MeshContext CreateFromGltf(GltfData data, int meshIndex, IAxisInverter inverter) + { + Profiler.BeginSample("ReadMesh"); + var gltfMesh = data.GLTF.meshes[meshIndex]; + + var meshContext = new MeshContext(gltfMesh.name, meshIndex); + if (HasSharedVertexBuffer(gltfMesh)) + { + meshContext.ImportMeshSharingVertexBuffer(data, gltfMesh, inverter); + } + else + { + meshContext.ImportMeshIndependentVertexBuffer(data, gltfMesh, inverter); + } + + meshContext.RenameBlendShape(gltfMesh); + + meshContext.DropUnusedVertices(); + + Profiler.EndSample(); + return meshContext; + } /// /// * flip triangle @@ -29,7 +81,7 @@ namespace UniGLTF /// /// /// - void PushIndices(BufferAccessor src, int offset) + private void PushIndices(BufferAccessor src, int offset) { switch (src.ComponentType) { @@ -79,7 +131,7 @@ namespace UniGLTF /// 頂点情報をMeshに対して送る /// /// - public void UploadMeshVertices(Mesh mesh) + private void UploadMeshVertices(Mesh mesh) { var vertexAttributeDescriptor = MeshVertex.GetVertexAttributeDescriptor(); @@ -109,7 +161,7 @@ namespace UniGLTF /// インデックス情報をMeshに対して送る /// /// - public void UploadMeshIndices(Mesh mesh) + private void UploadMeshIndices(Mesh mesh) { mesh.SetIndexBufferParams(_indices.Count, IndexFormat.UInt32); mesh.SetIndexBufferData(_indices, 0, 0, _indices.Count); @@ -137,16 +189,6 @@ namespace UniGLTF return blendShape; } - public MeshContext(string name, int meshIndex) - { - if (string.IsNullOrEmpty(name)) - { - name = $"UniGLTF import#{meshIndex}"; - } - - Name = name; - } - private static (float x, float y, float z, float w) NormalizeBoneWeight( (float x, float y, float z, float w) src) { @@ -195,7 +237,7 @@ namespace UniGLTF /// /// /// - public void ImportMeshIndependentVertexBuffer(GltfData data, glTFMesh gltfMesh, IAxisInverter inverter) + private void ImportMeshIndependentVertexBuffer(GltfData data, glTFMesh gltfMesh, IAxisInverter inverter) { (_vertices.Capacity, _indices.Capacity) = GetCapacity(data, gltfMesh); @@ -344,7 +386,7 @@ namespace UniGLTF /// /// /// - public void ImportMeshSharingVertexBuffer(GltfData data, glTFMesh gltfMesh, IAxisInverter inverter) + private void ImportMeshSharingVertexBuffer(GltfData data, glTFMesh gltfMesh, IAxisInverter inverter) { (_vertices.Capacity, _indices.Capacity) = GetCapacity(data, gltfMesh); @@ -478,10 +520,10 @@ namespace UniGLTF } } - public void RenameBlendShape(glTFMesh gltfMesh) + private void RenameBlendShape(glTFMesh gltfMesh) { if (!gltf_mesh_extras_targetNames.TryGet(gltfMesh, out var targetNames)) return; - for (var i = 0; i < BlendShapes.Count; i++) + for (var i = 0; i < _blendShapes.Count; i++) { if (i >= targetNames.Count) { @@ -489,7 +531,7 @@ namespace UniGLTF break; } - BlendShapes[i].Name = targetNames[i]; + _blendShapes[i].Name = targetNames[i]; } } @@ -508,7 +550,7 @@ namespace UniGLTF } } - public void AddDefaultMaterial() + private void AddDefaultMaterial() { if (!_materialIndices.Any()) { @@ -522,7 +564,7 @@ namespace UniGLTF /// /// VertexBuffer の後ろに未使用頂点がある場合に削除する /// - public void DropUnusedVertices() + private void DropUnusedVertices() { Profiler.BeginSample("MeshContext.DropUnusedVertices"); var maxIndex = _indices.Max(); @@ -537,5 +579,107 @@ namespace UniGLTF Profiler.EndSample(); } + + private static async Task BuildBlendShapeAsync(IAwaitCaller awaitCaller, Mesh mesh, BlendShape blendShape, + Vector3[] emptyVertices) + { + Vector3[] positions = null; + Vector3[] normals = null; + await awaitCaller.Run(() => + { + positions = blendShape.Positions.ToArray(); + if (blendShape.Normals != null) + { + normals = blendShape.Normals.ToArray(); + } + }); + + Profiler.BeginSample("MeshImporter.BuildBlendShapeAsync"); + if (blendShape.Positions.Count > 0) + { + if (blendShape.Positions.Count == mesh.vertexCount) + { + mesh.AddBlendShapeFrame(blendShape.Name, FrameWeight, + blendShape.Positions.ToArray(), + normals.Length == mesh.vertexCount && normals.Length == positions.Length ? normals : null, + null + ); + } + else + { + Debug.LogWarningFormat( + "May be partial primitive has blendShape. Require separate mesh or extend blend shape, but not implemented: {0}", + blendShape.Name); + } + } + else + { + // Debug.LogFormat("empty blendshape: {0}.{1}", mesh.name, blendShape.Name); + // add empty blend shape for keep blend shape index + mesh.AddBlendShapeFrame(blendShape.Name, FrameWeight, + emptyVertices, + null, + null + ); + } + + Profiler.EndSample(); + } + + public async Task BuildMeshAsync( + IAwaitCaller awaitCaller, + Func materialFromIndex) + { + Profiler.BeginSample("MeshImporter.BuildMesh"); + AddDefaultMaterial(); + + //Debug.Log(prims.ToJson()); + var mesh = new Mesh + { + name = Name + }; + + UploadMeshVertices(mesh); + await awaitCaller.NextFrame(); + + UploadMeshIndices(mesh); + await awaitCaller.NextFrame(); + + // NOTE: mesh.vertices では自動的に行われていたが、SetVertexBuffer では行われないため、明示的に呼び出す. + mesh.RecalculateBounds(); + await awaitCaller.NextFrame(); + + if (!HasNormal) + { + mesh.RecalculateNormals(); + await awaitCaller.NextFrame(); + } + + mesh.RecalculateTangents(); + await awaitCaller.NextFrame(); + + var result = new MeshWithMaterials + { + Mesh = mesh, + Materials = _materialIndices.Select(materialFromIndex).ToArray() + }; + await awaitCaller.NextFrame(); + + if (_blendShapes.Count > 0) + { + var emptyVertices = new Vector3[mesh.vertexCount]; + foreach (var blendShape in _blendShapes) + { + await BuildBlendShapeAsync(awaitCaller, mesh, blendShape, emptyVertices); + } + } + Profiler.EndSample(); + + Profiler.BeginSample("Mesh.UploadMeshData"); + mesh.UploadMeshData(false); + Profiler.EndSample(); + + return result; + } } -} \ No newline at end of file +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs deleted file mode 100644 index 5fcb06ca1..000000000 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs +++ /dev/null @@ -1,165 +0,0 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using UnityEngine; -using UnityEngine.Profiling; -using VRMShaders; - -namespace UniGLTF -{ - public class MeshImporter - { - private const float FrameWeight = 100.0f; - - private static bool HasSharedVertexBuffer(glTFMesh gltfMesh) - { - glTFAttributes lastAttributes = null; - var sharedAttributes = true; - foreach (var prim in gltfMesh.primitives) - { - if (lastAttributes != null && !prim.attributes.Equals(lastAttributes)) - { - sharedAttributes = false; - break; - } - - lastAttributes = prim.attributes; - } - - return sharedAttributes; - } - - internal MeshContext ReadMesh(GltfData data, int meshIndex, IAxisInverter inverter) - { - Profiler.BeginSample("ReadMesh"); - var gltfMesh = data.GLTF.meshes[meshIndex]; - - var meshContext = new MeshContext(gltfMesh.name, meshIndex); - if (HasSharedVertexBuffer(gltfMesh)) - { - meshContext.ImportMeshSharingVertexBuffer(data, gltfMesh, inverter); - } - else - { - meshContext.ImportMeshIndependentVertexBuffer(data, gltfMesh, inverter); - } - - meshContext.RenameBlendShape(gltfMesh); - - meshContext.DropUnusedVertices(); - - Profiler.EndSample(); - return meshContext; - } - - private static (Mesh, bool) BuildMesh(MeshContext meshContext) - { - meshContext.AddDefaultMaterial(); - - //Debug.Log(prims.ToJson()); - var mesh = new Mesh - { - name = meshContext.Name - }; - - meshContext.UploadMeshVertices(mesh); - meshContext.UploadMeshIndices(mesh); - - // NOTE: mesh.vertices では自動的に行われていたが、SetVertexBuffer では行われないため、明示的に呼び出す. - mesh.RecalculateBounds(); - - if (!meshContext.HasNormal) - { - mesh.RecalculateNormals(); - } - - return (mesh, true); - } - - private static async Task BuildBlendShapeAsync(IAwaitCaller awaitCaller, Mesh mesh, BlendShape blendShape, - Vector3[] emptyVertices) - { - Vector3[] positions = null; - Vector3[] normals = null; - await awaitCaller.Run(() => - { - positions = blendShape.Positions.ToArray(); - if (blendShape.Normals != null) - { - normals = blendShape.Normals.ToArray(); - } - }); - - Profiler.BeginSample("MeshImporter.BuildBlendShapeAsync"); - if (blendShape.Positions.Count > 0) - { - if (blendShape.Positions.Count == mesh.vertexCount) - { - mesh.AddBlendShapeFrame(blendShape.Name, FrameWeight, - blendShape.Positions.ToArray(), - normals.Length == mesh.vertexCount && normals.Length == positions.Length ? normals : null, - null - ); - } - else - { - Debug.LogWarningFormat( - "May be partial primitive has blendShape. Require separate mesh or extend blend shape, but not implemented: {0}", - blendShape.Name); - } - } - else - { - // Debug.LogFormat("empty blendshape: {0}.{1}", mesh.name, blendShape.Name); - // add empty blend shape for keep blend shape index - mesh.AddBlendShapeFrame(blendShape.Name, FrameWeight, - emptyVertices, - null, - null - ); - } - - Profiler.EndSample(); - } - - internal static async Task BuildMeshAsync( - IAwaitCaller awaitCaller, - Func ctx, - MeshContext meshContext) - { - Profiler.BeginSample("MeshImporter.BuildMesh"); - var (mesh, recalculateTangents) = BuildMesh(meshContext); - Profiler.EndSample(); - - if (recalculateTangents) - { - await awaitCaller.NextFrame(); - mesh.RecalculateTangents(); - await awaitCaller.NextFrame(); - } - - // 先にすべてのマテリアルを作成済みなのでテクスチャーは生成済み。Resultを使ってよい - var result = new MeshWithMaterials - { - Mesh = mesh, - Materials = meshContext.MaterialIndices.Select(ctx).ToArray() - }; - - await awaitCaller.NextFrame(); - if (meshContext.BlendShapes.Count > 0) - { - var emptyVertices = new Vector3[mesh.vertexCount]; - foreach (var blendShape in meshContext.BlendShapes) - { - await BuildBlendShapeAsync(awaitCaller, mesh, blendShape, emptyVertices); - } - } - - Profiler.BeginSample("Mesh.UploadMeshData"); - mesh.UploadMeshData(false); - Profiler.EndSample(); - - return result; - } - } -} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs.meta deleted file mode 100644 index 89f3ce9b8..000000000 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/MeshImporter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d9658f6e46942b146ad7e752c6592401 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: