Export attributes

This commit is contained in:
ackwell 2024-01-11 00:34:18 +11:00
parent 64aed56f7c
commit 182550ce15

View file

@ -13,20 +13,31 @@ namespace Penumbra.Import.Models.Export;
public class MeshExporter
{
public class Mesh(IEnumerable<IMeshBuilder<MaterialBuilder>> meshes, NodeBuilder[]? joints)
public class Mesh(IEnumerable<MeshData> meshes, NodeBuilder[]? joints)
{
public void AddToScene(SceneBuilder scene)
{
foreach (var mesh in meshes)
foreach (var data in meshes)
{
if (joints == null)
scene.AddRigidMesh(mesh, Matrix4x4.Identity);
else
scene.AddSkinnedMesh(mesh, Matrix4x4.Identity, joints);
var instance = joints != null
? scene.AddSkinnedMesh(data.Mesh, Matrix4x4.Identity, joints)
: scene.AddRigidMesh(data.Mesh, Matrix4x4.Identity);
var extras = new Dictionary<string, object>();
foreach (var attribute in data.Attributes)
extras.Add(attribute, true);
instance.WithExtras(JsonContent.CreateFrom(extras));
}
}
}
public struct MeshData
{
public IMeshBuilder<MaterialBuilder> Mesh;
public string[] Attributes;
}
public static Mesh Export(MdlFile mdl, byte lod, ushort meshIndex, MaterialBuilder[] materials, GltfSkeleton? skeleton)
{
var self = new MeshExporter(mdl, lod, meshIndex, materials, skeleton?.Names);
@ -103,31 +114,33 @@ public class MeshExporter
}
/// <summary> Build glTF meshes for this XIV mesh. </summary>
private IMeshBuilder<MaterialBuilder>[] BuildMeshes()
private MeshData[] BuildMeshes()
{
var indices = BuildIndices();
var vertices = BuildVertices();
// NOTE: Index indices are specified relative to the LOD's 0, but we're reading chunks for each mesh, so we're specifying the index base relative to the mesh's base.
if (XivMesh.SubMeshCount == 0)
return [BuildMesh($"mesh {_meshIndex}", indices, vertices, 0, (int)XivMesh.IndexCount)];
return [BuildMesh($"mesh {_meshIndex}", indices, vertices, 0, (int)XivMesh.IndexCount, 0)];
return _mdl.SubMeshes
.Skip(XivMesh.SubMeshIndex)
.Take(XivMesh.SubMeshCount)
.WithIndex()
.Select(subMesh => BuildMesh($"mesh {_meshIndex}.{subMesh.Index}", indices, vertices,
(int)(subMesh.Value.IndexOffset - XivMesh.StartIndex), (int)subMesh.Value.IndexCount))
(int)(subMesh.Value.IndexOffset - XivMesh.StartIndex), (int)subMesh.Value.IndexCount,
subMesh.Value.AttributeIndexMask))
.ToArray();
}
/// <summary> Build a mesh from the provided indices and vertices. A subset of the full indices may be built by providing an index base and count. </summary>
private IMeshBuilder<MaterialBuilder> BuildMesh(
private MeshData BuildMesh(
string name,
IReadOnlyList<ushort> indices,
IReadOnlyList<IVertexBuilder> vertices,
int indexBase,
int indexCount
int indexCount,
uint attributeMask
)
{
var meshBuilderType = typeof(MeshBuilder<,,,>).MakeGenericType(
@ -190,12 +203,23 @@ public class MeshExporter
}
}
// Named morph targets aren't part of the specification, however `MESH.extras.targetNames`
// is a commonly-accepted means of providing the data.
meshBuilder.Extras = JsonContent.CreateFrom(new Dictionary<string, object>()
{
{ "targetNames", shapeNames },
});
return meshBuilder;
var attributes = Enumerable.Range(0, 32)
.Where(index => ((attributeMask >> index) & 1) == 1)
.Select(index => _mdl.Attributes[index])
.ToArray();
return new MeshData
{
Mesh = meshBuilder,
Attributes = attributes,
};
}
/// <summary> Read in the indices for this mesh. </summary>