mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-05-11 21:14:19 -05:00
Merge pull request #1598 from ousttrue/fix10/divided_migration
Fix10/divided migration
This commit is contained in:
commit
ac9994ebbe
|
|
@ -10,7 +10,12 @@ namespace UniVRM10
|
|||
{
|
||||
/// <summary>
|
||||
/// 座標系を変換した Model により、Mesh, Node, BindMatrices を更新する。
|
||||
/// buffer, bufferAccessor の更新もある。
|
||||
///
|
||||
/// * gltf.images の参照する bufferView
|
||||
/// * gltf.meshes の参照する index, VERTEX, MorphTarget の accessor, bufferView
|
||||
/// * gltf.nodes の参照する skin の inverseBindMatrices 向けの accessor, bufferView
|
||||
///
|
||||
/// を詰め込みなすことで bin を再構築する
|
||||
/// </summary>
|
||||
class MeshUpdater
|
||||
{
|
||||
|
|
@ -19,12 +24,23 @@ namespace UniVRM10
|
|||
List<glTFBufferView> _bufferViews = new List<glTFBufferView>();
|
||||
List<glTFAccessor> _accessors = new List<glTFAccessor>();
|
||||
|
||||
public MeshUpdater(GltfData data)
|
||||
MeshUpdater(GltfData data)
|
||||
{
|
||||
_data = data;
|
||||
_buffer = new ArrayByteBuffer(new byte[data.Bin.Length]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// data を model で更新する
|
||||
/// </summary>
|
||||
/// <param name="data">更新前のオリジナル</param>
|
||||
/// <param name="model">座標系の変換などの操作済み</param>
|
||||
/// <returns></returns>
|
||||
public static (glTF, ArraySegment<byte>) Execute(GltfData data, VrmLib.Model model)
|
||||
{
|
||||
return new MeshUpdater(data).Update(model);
|
||||
}
|
||||
|
||||
int AddBuffer(NativeArray<byte> bytes)
|
||||
{
|
||||
var bufferView = _buffer.Extend(bytes);
|
||||
|
|
@ -64,7 +80,12 @@ namespace UniVRM10
|
|||
public int? Normal;
|
||||
};
|
||||
|
||||
public (glTF, ArraySegment<byte>) Update(VrmLib.Model model)
|
||||
/// <summary>
|
||||
/// bufferView, accessor を push することで bin を再構築する
|
||||
/// </summary>
|
||||
/// <param name="model">meshの右手左手変換結果</param>
|
||||
/// <returns></returns>
|
||||
(glTF, ArraySegment<byte>) Update(VrmLib.Model model)
|
||||
{
|
||||
var gltf = _data.GLTF;
|
||||
|
||||
|
|
@ -75,74 +96,14 @@ namespace UniVRM10
|
|||
image.bufferView = AddBuffer(bytes);
|
||||
}
|
||||
|
||||
// update Mesh
|
||||
foreach (var (gltfMesh, mesh) in Enumerable.Zip(gltf.meshes, model.MeshGroups, (l, r) => (l, r.Meshes[0])))
|
||||
// copy mesh
|
||||
if (model.MeshGroups.All(x => x.Meshes.Count == 1))
|
||||
{
|
||||
NativeArray<uint> indices;
|
||||
switch (mesh.IndexBuffer.Stride)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
// byte
|
||||
var byte_indices = mesh.IndexBuffer.GetSpan<byte>();
|
||||
indices = _data.NativeArrayManager.Convert(byte_indices, (byte x) => (uint)x);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
// ushort
|
||||
var ushort_indices = mesh.IndexBuffer.GetSpan<ushort>();
|
||||
indices = _data.NativeArrayManager.Convert(ushort_indices, (ushort x) => (uint)x);
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
// uint
|
||||
indices = mesh.IndexBuffer.GetSpan<uint>();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
var position = AddAccessor<Vector3>(mesh.VertexBuffer.Positions);
|
||||
var normal = AddAccessor<Vector3>(mesh.VertexBuffer.Normals);
|
||||
var uv = AddAccessor<Vector2>(mesh.VertexBuffer.TexCoords);
|
||||
var weights = AddAccessor<Vector4>(mesh.VertexBuffer.Weights);
|
||||
var joints = AddAccessor<UShort4>(mesh.VertexBuffer.Joints);
|
||||
var color = AddAccessor<Vector4>(mesh.VertexBuffer.Colors);
|
||||
|
||||
var morphTargets = new MorphAccessor[] { };
|
||||
if (mesh.MorphTargets != null)
|
||||
{
|
||||
morphTargets = mesh.MorphTargets.Select(x => new MorphAccessor
|
||||
{
|
||||
Position = AddAccessor<Vector3>(x.VertexBuffer.Positions),
|
||||
Normal = AddAccessor<Vector3>(x.VertexBuffer.Normals),
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
foreach (var (gltfPrim, submesh) in Enumerable.Zip(gltfMesh.primitives, mesh.Submeshes, (l, r) => (l, r)))
|
||||
{
|
||||
var subIndices = indices.GetSubArray(submesh.Offset, submesh.DrawCount);
|
||||
gltfPrim.indices = AddAccessor(subIndices);
|
||||
gltfPrim.attributes.POSITION = position.Value;
|
||||
gltfPrim.attributes.NORMAL = normal.GetValueOrDefault(-1); // たぶん、ありえる
|
||||
gltfPrim.attributes.TANGENT = -1;
|
||||
gltfPrim.attributes.COLOR_0 = color.GetValueOrDefault(-1);
|
||||
gltfPrim.attributes.TEXCOORD_0 = uv.GetValueOrDefault(-1); // ありえる?
|
||||
gltfPrim.attributes.TEXCOORD_1 = -1;
|
||||
gltfPrim.attributes.WEIGHTS_0 = weights.GetValueOrDefault(-1);
|
||||
gltfPrim.attributes.JOINTS_0 = joints.GetValueOrDefault(-1);
|
||||
foreach (var (gltfMorph, morph) in Enumerable.Zip(gltfPrim.targets, morphTargets, (l, r) => (l, r)))
|
||||
{
|
||||
gltfMorph.POSITION = morph.Position.GetValueOrDefault(-1);
|
||||
gltfMorph.NORMAL = morph.Normal.GetValueOrDefault(-1);
|
||||
gltfMorph.TANGENT = -1;
|
||||
}
|
||||
}
|
||||
UpdateSharedVertexBuffer(model);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateDividedVertexBuffer(model);
|
||||
}
|
||||
|
||||
// update nodes and remove unused skin
|
||||
|
|
@ -212,6 +173,167 @@ namespace UniVRM10
|
|||
gltf.accessors = _accessors;
|
||||
|
||||
return (gltf, _buffer.Bytes);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// model はひとつのノードに複数の mesh をぶら下げることができる(meshGroup)
|
||||
/// gltf.meshes[i].primitives[j] <-> model.meshGroups[i].meshes[0].submeshes[j]
|
||||
/// </summary>
|
||||
void UpdateSharedVertexBuffer(VrmLib.Model model)
|
||||
{
|
||||
var gltf = _data.GLTF;
|
||||
|
||||
// gltfMeshes[i] <=> MeshGroups[i].Meshes[0] ( MeshGroups[i].Meshes.Count == 1 )
|
||||
foreach (var (gltfMesh, mesh) in Enumerable.Zip(gltf.meshes, model.MeshGroups, (l, r) => (l, r.Meshes[0])))
|
||||
{
|
||||
NativeArray<uint> indices;
|
||||
switch (mesh.IndexBuffer.Stride)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
// byte
|
||||
var byte_indices = mesh.IndexBuffer.GetSpan<byte>();
|
||||
indices = _data.NativeArrayManager.Convert(byte_indices, (byte x) => (uint)x);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
// ushort
|
||||
var ushort_indices = mesh.IndexBuffer.GetSpan<ushort>();
|
||||
indices = _data.NativeArrayManager.Convert(ushort_indices, (ushort x) => (uint)x);
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
// uint
|
||||
indices = mesh.IndexBuffer.GetSpan<uint>();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
var position = AddAccessor<Vector3>(mesh.VertexBuffer.Positions);
|
||||
var normal = AddAccessor<Vector3>(mesh.VertexBuffer.Normals);
|
||||
var uv = AddAccessor<Vector2>(mesh.VertexBuffer.TexCoords);
|
||||
var weights = AddAccessor<Vector4>(mesh.VertexBuffer.Weights);
|
||||
var joints = AddAccessor<UShort4>(mesh.VertexBuffer.Joints);
|
||||
var color = AddAccessor<Vector4>(mesh.VertexBuffer.Colors);
|
||||
|
||||
var morphTargets = new MorphAccessor[] { };
|
||||
if (mesh.MorphTargets != null)
|
||||
{
|
||||
morphTargets = mesh.MorphTargets.Select(x => new MorphAccessor
|
||||
{
|
||||
Position = AddAccessor<Vector3>(x.VertexBuffer.Positions),
|
||||
Normal = AddAccessor<Vector3>(x.VertexBuffer.Normals),
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
// gltfPrim[j] <=> mesh.Submeshes[j]
|
||||
foreach (var (gltfPrim, submesh) in Enumerable.Zip(gltfMesh.primitives, mesh.Submeshes, (l, r) => (l, r)))
|
||||
{
|
||||
var subIndices = indices.GetSubArray(submesh.Offset, submesh.DrawCount);
|
||||
gltfPrim.indices = AddAccessor(subIndices);
|
||||
gltfPrim.attributes.POSITION = position.Value;
|
||||
gltfPrim.attributes.NORMAL = normal.GetValueOrDefault(-1); // たぶん、ありえる
|
||||
gltfPrim.attributes.TANGENT = -1;
|
||||
gltfPrim.attributes.COLOR_0 = color.GetValueOrDefault(-1);
|
||||
gltfPrim.attributes.TEXCOORD_0 = uv.GetValueOrDefault(-1); // ありえる?
|
||||
gltfPrim.attributes.TEXCOORD_1 = -1;
|
||||
gltfPrim.attributes.WEIGHTS_0 = weights.GetValueOrDefault(-1);
|
||||
gltfPrim.attributes.JOINTS_0 = joints.GetValueOrDefault(-1);
|
||||
foreach (var (gltfMorph, morph) in Enumerable.Zip(gltfPrim.targets, morphTargets, (l, r) => (l, r)))
|
||||
{
|
||||
gltfMorph.POSITION = morph.Position.GetValueOrDefault(-1);
|
||||
gltfMorph.NORMAL = morph.Normal.GetValueOrDefault(-1);
|
||||
gltfMorph.TANGENT = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// model はひとつのノードに複数の mesh をぶら下げることができる(meshGroup)
|
||||
/// gltf.meshes[i].primitives[j] <-> model.meshGroups[i].meshes[j].submeshes[0]
|
||||
/// </summary>
|
||||
void UpdateDividedVertexBuffer(VrmLib.Model model)
|
||||
{
|
||||
var gltf = _data.GLTF;
|
||||
|
||||
// gltfMesh[i] <=> meshGroups[i]
|
||||
foreach (var (gltfMesh, meshGroup) in Enumerable.Zip(gltf.meshes, model.MeshGroups, (l, r) => (l, r)))
|
||||
{
|
||||
// gltfPrimitives[j] <=> meshGroup.Meshes[j] (meshGroup.Meshes[j].Submeshes.Count==1)
|
||||
foreach (var (gltfPrim, mesh) in Enumerable.Zip(gltfMesh.primitives, meshGroup.Meshes, (l, r) => (l, r)))
|
||||
{
|
||||
NativeArray<uint> indices;
|
||||
switch (mesh.IndexBuffer.Stride)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
// byte
|
||||
var byte_indices = mesh.IndexBuffer.GetSpan<byte>();
|
||||
indices = _data.NativeArrayManager.Convert(byte_indices, (byte x) => (uint)x);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
// ushort
|
||||
var ushort_indices = mesh.IndexBuffer.GetSpan<ushort>();
|
||||
indices = _data.NativeArrayManager.Convert(ushort_indices, (ushort x) => (uint)x);
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
// uint
|
||||
indices = mesh.IndexBuffer.GetSpan<uint>();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
var position = AddAccessor<Vector3>(mesh.VertexBuffer.Positions);
|
||||
var normal = AddAccessor<Vector3>(mesh.VertexBuffer.Normals);
|
||||
var uv = AddAccessor<Vector2>(mesh.VertexBuffer.TexCoords);
|
||||
var weights = AddAccessor<Vector4>(mesh.VertexBuffer.Weights);
|
||||
var joints = AddAccessor<UShort4>(mesh.VertexBuffer.Joints);
|
||||
var color = AddAccessor<Vector4>(mesh.VertexBuffer.Colors);
|
||||
|
||||
var morphTargets = new MorphAccessor[] { };
|
||||
if (mesh.MorphTargets != null)
|
||||
{
|
||||
morphTargets = mesh.MorphTargets.Select(x => new MorphAccessor
|
||||
{
|
||||
Position = AddAccessor<Vector3>(x.VertexBuffer.Positions),
|
||||
Normal = AddAccessor<Vector3>(x.VertexBuffer.Normals),
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
gltfPrim.indices = AddAccessor(indices);
|
||||
gltfPrim.attributes.POSITION = position.Value;
|
||||
gltfPrim.attributes.NORMAL = normal.GetValueOrDefault(-1); // たぶん、ありえる
|
||||
gltfPrim.attributes.TANGENT = -1;
|
||||
gltfPrim.attributes.COLOR_0 = color.GetValueOrDefault(-1);
|
||||
gltfPrim.attributes.TEXCOORD_0 = uv.GetValueOrDefault(-1); // ありえる?
|
||||
gltfPrim.attributes.TEXCOORD_1 = -1;
|
||||
gltfPrim.attributes.WEIGHTS_0 = weights.GetValueOrDefault(-1);
|
||||
gltfPrim.attributes.JOINTS_0 = joints.GetValueOrDefault(-1);
|
||||
foreach (var (gltfMorph, morph) in Enumerable.Zip(gltfPrim.targets, morphTargets, (l, r) => (l, r)))
|
||||
{
|
||||
gltfMorph.POSITION = morph.Position.GetValueOrDefault(-1);
|
||||
gltfMorph.NORMAL = morph.Normal.GetValueOrDefault(-1);
|
||||
gltfMorph.TANGENT = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ namespace UniVRM10
|
|||
// Unity -> VRM1
|
||||
model.ConvertCoordinate(VrmLib.Coordinates.Vrm1);
|
||||
|
||||
var (gltf, bin) = new MeshUpdater(data).Update(model);
|
||||
var (gltf, bin) = MeshUpdater.Execute(data, model);
|
||||
gltf.extensions = null;
|
||||
return MigrateVrm(gltf, bin, data.Json.ParseAsJson()["extensions"]["VRM"]);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user