mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-02-21 23:37:47 +01:00
Export attributes
This commit is contained in:
parent
64aed56f7c
commit
182550ce15
1 changed files with 36 additions and 12 deletions
|
|
@ -13,20 +13,31 @@ namespace Penumbra.Import.Models.Export;
|
||||||
|
|
||||||
public class MeshExporter
|
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)
|
public void AddToScene(SceneBuilder scene)
|
||||||
{
|
{
|
||||||
foreach (var mesh in meshes)
|
foreach (var data in meshes)
|
||||||
{
|
{
|
||||||
if (joints == null)
|
var instance = joints != null
|
||||||
scene.AddRigidMesh(mesh, Matrix4x4.Identity);
|
? scene.AddSkinnedMesh(data.Mesh, Matrix4x4.Identity, joints)
|
||||||
else
|
: scene.AddRigidMesh(data.Mesh, Matrix4x4.Identity);
|
||||||
scene.AddSkinnedMesh(mesh, Matrix4x4.Identity, joints);
|
|
||||||
|
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)
|
public static Mesh Export(MdlFile mdl, byte lod, ushort meshIndex, MaterialBuilder[] materials, GltfSkeleton? skeleton)
|
||||||
{
|
{
|
||||||
var self = new MeshExporter(mdl, lod, meshIndex, materials, skeleton?.Names);
|
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>
|
/// <summary> Build glTF meshes for this XIV mesh. </summary>
|
||||||
private IMeshBuilder<MaterialBuilder>[] BuildMeshes()
|
private MeshData[] BuildMeshes()
|
||||||
{
|
{
|
||||||
var indices = BuildIndices();
|
var indices = BuildIndices();
|
||||||
var vertices = BuildVertices();
|
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.
|
// 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)
|
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
|
return _mdl.SubMeshes
|
||||||
.Skip(XivMesh.SubMeshIndex)
|
.Skip(XivMesh.SubMeshIndex)
|
||||||
.Take(XivMesh.SubMeshCount)
|
.Take(XivMesh.SubMeshCount)
|
||||||
.WithIndex()
|
.WithIndex()
|
||||||
.Select(subMesh => BuildMesh($"mesh {_meshIndex}.{subMesh.Index}", indices, vertices,
|
.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();
|
.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>
|
/// <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,
|
string name,
|
||||||
IReadOnlyList<ushort> indices,
|
IReadOnlyList<ushort> indices,
|
||||||
IReadOnlyList<IVertexBuilder> vertices,
|
IReadOnlyList<IVertexBuilder> vertices,
|
||||||
int indexBase,
|
int indexBase,
|
||||||
int indexCount
|
int indexCount,
|
||||||
|
uint attributeMask
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var meshBuilderType = typeof(MeshBuilder<,,,>).MakeGenericType(
|
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>()
|
meshBuilder.Extras = JsonContent.CreateFrom(new Dictionary<string, object>()
|
||||||
{
|
{
|
||||||
{ "targetNames", shapeNames },
|
{ "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>
|
/// <summary> Read in the indices for this mesh. </summary>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue