MeshImporter を整理。機能を ImporterContext と MeshContext に委譲して消滅させた

This commit is contained in:
ousttrue
2022-06-07 16:20:14 +09:00
parent 9ad556abcc
commit 94b0928d5a
4 changed files with 158 additions and 179 deletions

View File

@@ -163,6 +163,47 @@ namespace UniGLTF
await awaitCaller.NextFrame();
}
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;
}
private static 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;
}
protected virtual async Task LoadGeometryAsync(IAwaitCaller awaitCaller, Func<string, IDisposable> MeasureTime)
{
var inverter = InvertAxis.Create();
@@ -174,7 +215,7 @@ namespace UniGLTF
var index = i;
using (MeasureTime("ReadMesh"))
{
var meshContext = await awaitCaller.Run(() => MeshImporter.ReadMesh(Data, index, inverter));
var meshContext = await awaitCaller.Run(() => ReadMesh(Data, index, inverter));
var meshWithMaterials = await BuildMeshAsync(awaitCaller, MeasureTime, meshContext, index);
Meshes.Add(meshWithMaterials);
}
@@ -289,11 +330,11 @@ namespace UniGLTF
return Task.FromResult<object>(null);
}
async Task<MeshWithMaterials> BuildMeshAsync(IAwaitCaller awaitCaller, Func<string, IDisposable> MeasureTime, MeshContext x, int i)
async Task<MeshWithMaterials> BuildMeshAsync(IAwaitCaller awaitCaller, Func<string, IDisposable> 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

View File

@@ -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<MeshVertex> _vertices = new List<MeshVertex>();
private readonly List<SkinnedMeshVertex> _skinnedMeshVertices = new List<SkinnedMeshVertex>();
private readonly List<int> _indices = new List<int>();
@@ -537,5 +541,115 @@ namespace UniGLTF
Profiler.EndSample();
}
private (Mesh, bool) BuildMesh()
{
this.AddDefaultMaterial();
//Debug.Log(prims.ToJson());
var mesh = new Mesh
{
name = this.Name
};
this.UploadMeshVertices(mesh);
this.UploadMeshIndices(mesh);
// NOTE: mesh.vertices では自動的に行われていたが、SetVertexBuffer では行われないため、明示的に呼び出す.
mesh.RecalculateBounds();
if (!this.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();
}
public async Task<MeshWithMaterials> BuildMeshAsync(
IAwaitCaller awaitCaller,
Func<int, Material> ctx)
{
Profiler.BeginSample("MeshImporter.BuildMesh");
var (mesh, recalculateTangents) = this.BuildMesh();
Profiler.EndSample();
if (recalculateTangents)
{
await awaitCaller.NextFrame();
mesh.RecalculateTangents();
await awaitCaller.NextFrame();
}
// 先にすべてのマテリアルを作成済みなのでテクスチャーは生成済み。Resultを使ってよい
var result = new MeshWithMaterials
{
Mesh = mesh,
Materials = this.MaterialIndices.Select(ctx).ToArray()
};
await awaitCaller.NextFrame();
if (this.BlendShapes.Count > 0)
{
var emptyVertices = new Vector3[mesh.vertexCount];
foreach (var blendShape in this.BlendShapes)
{
await BuildBlendShapeAsync(awaitCaller, mesh, blendShape, emptyVertices);
}
}
Profiler.BeginSample("Mesh.UploadMeshData");
mesh.UploadMeshData(false);
Profiler.EndSample();
return result;
}
}
}

View File

@@ -1,165 +0,0 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Profiling;
using VRMShaders;
namespace UniGLTF
{
public static 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 static 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<MeshWithMaterials> BuildMeshAsync(
IAwaitCaller awaitCaller,
Func<int, Material> 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;
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: d9658f6e46942b146ad7e752c6592401
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: