From d2f93f85625d789189938ad4b0200b759779e722 Mon Sep 17 00:00:00 2001 From: ackwell Date: Wed, 10 Jan 2024 20:33:24 +1100 Subject: [PATCH] Import material names --- Penumbra/Import/Models/Import/MeshImporter.cs | 8 +++++ .../Import/Models/Import/ModelImporter.cs | 33 ++++++++++++++++--- .../Import/Models/Import/SubMeshImporter.cs | 7 ++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/Penumbra/Import/Models/Import/MeshImporter.cs b/Penumbra/Import/Models/Import/MeshImporter.cs index 95eede2b..00663e43 100644 --- a/Penumbra/Import/Models/Import/MeshImporter.cs +++ b/Penumbra/Import/Models/Import/MeshImporter.cs @@ -10,6 +10,8 @@ public class MeshImporter(IEnumerable nodes) public MdlStructs.MeshStruct MeshStruct; public List SubMeshStructs; + public string? Material; + public MdlStructs.VertexDeclarationStruct VertexDeclaration; public IEnumerable VertexBuffer; @@ -35,6 +37,8 @@ public class MeshImporter(IEnumerable nodes) private readonly List _subMeshes = []; + private string? _material; + private MdlStructs.VertexDeclarationStruct? _vertexDeclaration; private byte[]? _strides; private ushort _vertexCount; @@ -74,6 +78,7 @@ public class MeshImporter(IEnumerable nodes) BoneTableIndex = 0, }, SubMeshStructs = _subMeshes, + Material = _material, VertexDeclaration = _vertexDeclaration.Value, VertexBuffer = _streams[0].Concat(_streams[1]).Concat(_streams[2]), Indices = _indices, @@ -105,6 +110,9 @@ public class MeshImporter(IEnumerable nodes) var subMeshName = node.Name ?? node.Mesh.Name; + // TODO: Record a warning if there's a mismatch between current and incoming, as we can't support multiple materials per mesh. + _material ??= subMesh.Material; + // Check that vertex declarations match - we need to combine the buffers, so a mismatch would take a whole load of resolution. if (_vertexDeclaration == null) _vertexDeclaration = subMesh.VertexDeclaration; diff --git a/Penumbra/Import/Models/Import/ModelImporter.cs b/Penumbra/Import/Models/Import/ModelImporter.cs index abe87934..d5d4bb53 100644 --- a/Penumbra/Import/Models/Import/ModelImporter.cs +++ b/Penumbra/Import/Models/Import/ModelImporter.cs @@ -19,6 +19,8 @@ public partial class ModelImporter(ModelRoot _model) private readonly List _meshes = []; private readonly List _subMeshes = []; + private readonly List _materials = []; + private readonly List _vertexDeclarations = []; private readonly List _vertexBuffer = []; @@ -37,6 +39,8 @@ public partial class ModelImporter(ModelRoot _model) BuildMeshForGroup(subMeshNodes); // Now that all the meshes have been built, we can build some of the model-wide metadata. + var materials = _materials.Count > 0 ? _materials : ["/NO_MATERIAL"]; + var shapes = new List(); var shapeMeshes = new List(); foreach (var (keyName, keyMeshes) in _shapeMeshes) @@ -86,8 +90,7 @@ public partial class ModelImporter(ModelRoot _model) }, ], - // TODO: Would be good to populate from gltf material names. - Materials = ["/NO_MATERIAL"], + Materials = [.. materials], // TODO: Would be good to calculate all of this up the tree. Radius = 1, @@ -130,15 +133,20 @@ public partial class ModelImporter(ModelRoot _model) var mesh = MeshImporter.Import(subMeshNodes); var meshStartIndex = (uint)(mesh.MeshStruct.StartIndex + indexOffset); + ushort materialIndex = 0; + if (mesh.Material != null) + materialIndex = GetMaterialIndex(mesh.Material); + // If no bone table is used for a mesh, the index is set to 255. - var boneTableIndex = 255; + ushort boneTableIndex = 255; if (mesh.Bones != null) boneTableIndex = BuildBoneTable(mesh.Bones); _meshes.Add(mesh.MeshStruct with { + MaterialIndex = materialIndex, SubMeshIndex = (ushort)(mesh.MeshStruct.SubMeshIndex + subMeshOffset), - BoneTableIndex = (ushort)boneTableIndex, + BoneTableIndex = boneTableIndex, StartIndex = meshStartIndex, VertexBufferOffset = mesh.MeshStruct.VertexBufferOffset .Select(offset => (uint)(offset + vertexOffset)) @@ -173,6 +181,23 @@ public partial class ModelImporter(ModelRoot _model) } } + private ushort GetMaterialIndex(string materialName) + { + // If we already have this material, grab the current one + var index = _materials.IndexOf(materialName); + if (index >= 0) + return (ushort)index; + + // If there's already 4 materials, we can't add any more. + // TODO: permit, with a warning to reduce, and validation in MdlTab. + var count = _materials.Count; + if (count >= 4) + return 0; + + _materials.Add(materialName); + return (ushort)count; + } + private ushort BuildBoneTable(List boneNames) { var boneIndices = new List(); diff --git a/Penumbra/Import/Models/Import/SubMeshImporter.cs b/Penumbra/Import/Models/Import/SubMeshImporter.cs index 5dec4384..0d1dafb3 100644 --- a/Penumbra/Import/Models/Import/SubMeshImporter.cs +++ b/Penumbra/Import/Models/Import/SubMeshImporter.cs @@ -10,6 +10,8 @@ public class SubMeshImporter { public MdlStructs.SubmeshStruct SubMeshStruct; + public string? Material; + public MdlStructs.VertexDeclarationStruct VertexDeclaration; public ushort VertexCount; @@ -81,6 +83,10 @@ public class SubMeshImporter ArgumentNullException.ThrowIfNull(_attributes); ArgumentNullException.ThrowIfNull(_shapeValues); + var material = _primitive.Material.Name; + if (material == "") + material = null; + return new SubMesh() { SubMeshStruct = new MdlStructs.SubmeshStruct() @@ -93,6 +99,7 @@ public class SubMeshImporter BoneStartIndex = 0, BoneCount = 0, }, + Material = material, VertexDeclaration = new MdlStructs.VertexDeclarationStruct() { VertexElements = _attributes.Select(attribute => attribute.Element).ToArray(),