Quick submesh implementation

This commit is contained in:
ackwell 2023-12-30 18:31:15 +11:00
parent 727fa3c183
commit f7a2c17415
2 changed files with 25 additions and 13 deletions

View file

@ -10,7 +10,7 @@ namespace Penumbra.Import.Modules;
public sealed class MeshConverter public sealed class MeshConverter
{ {
public static IMeshBuilder<MaterialBuilder> ToGltf(MdlFile mdl, byte lod, ushort meshIndex, Dictionary<string, int>? boneNameMap) public static IMeshBuilder<MaterialBuilder>[] ToGltf(MdlFile mdl, byte lod, ushort meshIndex, Dictionary<string, int>? boneNameMap)
{ {
var self = new MeshConverter(mdl, lod, meshIndex, boneNameMap); var self = new MeshConverter(mdl, lod, meshIndex, boneNameMap);
return self.BuildMesh(); return self.BuildMesh();
@ -65,12 +65,23 @@ public sealed class MeshConverter
return indexMap; return indexMap;
} }
// TODO: consider a struct return type private IMeshBuilder<MaterialBuilder>[] BuildMesh()
private IMeshBuilder<MaterialBuilder> BuildMesh()
{ {
var indices = BuildIndices();
var vertices = BuildVertices(); var vertices = BuildVertices();
// TODO: handle submeshCount = 0
return _mdl.SubMeshes
.Skip(Mesh.SubMeshIndex)
.Take(Mesh.SubMeshCount)
.Select(submesh => BuildSubMesh(submesh, vertices))
.ToArray();
}
private IMeshBuilder<MaterialBuilder> BuildSubMesh(MdlStructs.SubmeshStruct submesh, IReadOnlyList<IVertexBuilder> vertices)
{
var indices = BuildIndices(submesh);
var meshBuilderType = typeof(MeshBuilder<,,,>).MakeGenericType( var meshBuilderType = typeof(MeshBuilder<,,,>).MakeGenericType(
typeof(MaterialBuilder), typeof(MaterialBuilder),
_geometryType, _geometryType,
@ -89,7 +100,7 @@ public sealed class MeshConverter
// All XIV meshes use triangle lists. // All XIV meshes use triangle lists.
// TODO: split by submeshes // TODO: split by submeshes
for (var indexOffset = 0; indexOffset < Mesh.IndexCount; indexOffset += 3) for (var indexOffset = 0; indexOffset < submesh.IndexCount; indexOffset += 3)
primitiveBuilder.AddTriangle( primitiveBuilder.AddTriangle(
vertices[indices[indexOffset + 0]], vertices[indices[indexOffset + 0]],
vertices[indices[indexOffset + 1]], vertices[indices[indexOffset + 1]],
@ -99,11 +110,11 @@ public sealed class MeshConverter
return meshBuilder; return meshBuilder;
} }
private IReadOnlyList<ushort> BuildIndices() private IReadOnlyList<ushort> BuildIndices(MdlStructs.SubmeshStruct submesh)
{ {
var reader = new BinaryReader(new MemoryStream(_mdl.RemainingData)); var reader = new BinaryReader(new MemoryStream(_mdl.RemainingData));
reader.Seek(_mdl.IndexOffset[_lod] + Mesh.StartIndex * sizeof(ushort)); reader.Seek(_mdl.IndexOffset[_lod] + submesh.IndexOffset * sizeof(ushort));
return reader.ReadStructuresAsArray<ushort>((int)Mesh.IndexCount); return reader.ReadStructuresAsArray<ushort>((int)submesh.IndexCount);
} }
private IReadOnlyList<IVertexBuilder> BuildVertices() private IReadOnlyList<IVertexBuilder> BuildVertices()

View file

@ -87,12 +87,13 @@ public sealed class ModelManager : SingleTaskQueue, IDisposable
// TODO: consider other types of mesh? // TODO: consider other types of mesh?
for (ushort meshOffset = 0; meshOffset < lod.MeshCount; meshOffset++) for (ushort meshOffset = 0; meshOffset < lod.MeshCount; meshOffset++)
{ {
var meshBuilder = MeshConverter.ToGltf(_mdl, lodIndex, (ushort)(lod.MeshIndex + meshOffset), skeleton?.Names); var meshBuilders = MeshConverter.ToGltf(_mdl, lodIndex, (ushort)(lod.MeshIndex + meshOffset), skeleton?.Names);
// TODO: use a value from the mesh converter for this check, rather than assuming that it has joints // TODO: use a value from the mesh converter for this check, rather than assuming that it has joints
if (skeleton == null) foreach (var meshBuilder in meshBuilders)
scene.AddRigidMesh(meshBuilder, Matrix4x4.Identity); if (skeleton == null)
else scene.AddRigidMesh(meshBuilder, Matrix4x4.Identity);
scene.AddSkinnedMesh(meshBuilder, Matrix4x4.Identity, skeleton?.Joints); else
scene.AddSkinnedMesh(meshBuilder, Matrix4x4.Identity, skeleton?.Joints);
} }
} }