mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-14 06:50:19 -05:00
MeshImporter を整理。機能を ImporterContext と MeshContext に委譲して消滅させた
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d9658f6e46942b146ad7e752c6592401
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user