mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 12:14:17 +01:00
Add submeshless support
This commit is contained in:
parent
dc845b766e
commit
518117b25a
2 changed files with 24 additions and 16 deletions
|
|
@ -34,7 +34,6 @@ public class MeshExporter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: replace bonenamemap with a gltfskeleton
|
|
||||||
public static Mesh Export(MdlFile mdl, byte lod, ushort meshIndex, GltfSkeleton? skeleton)
|
public static Mesh Export(MdlFile mdl, byte lod, ushort meshIndex, GltfSkeleton? skeleton)
|
||||||
{
|
{
|
||||||
var self = new MeshExporter(mdl, lod, meshIndex, skeleton?.Names);
|
var self = new MeshExporter(mdl, lod, meshIndex, skeleton?.Names);
|
||||||
|
|
@ -74,7 +73,7 @@ public class MeshExporter
|
||||||
|
|
||||||
private Dictionary<ushort, int> BuildBoneIndexMap(Dictionary<string, int> boneNameMap)
|
private Dictionary<ushort, int> BuildBoneIndexMap(Dictionary<string, int> boneNameMap)
|
||||||
{
|
{
|
||||||
// todo: BoneTableIndex of 255 means null? if so, it should probably feed into the attributes we assign...
|
// TODO: BoneTableIndex of 255 means null? if so, it should probably feed into the attributes we assign...
|
||||||
var xivBoneTable = _mdl.BoneTables[XivMesh.BoneTableIndex];
|
var xivBoneTable = _mdl.BoneTables[XivMesh.BoneTableIndex];
|
||||||
|
|
||||||
var indexMap = new Dictionary<ushort, int>();
|
var indexMap = new Dictionary<ushort, int>();
|
||||||
|
|
@ -97,20 +96,25 @@ public class MeshExporter
|
||||||
var indices = BuildIndices();
|
var indices = BuildIndices();
|
||||||
var vertices = BuildVertices();
|
var vertices = BuildVertices();
|
||||||
|
|
||||||
// TODO: handle SubMeshCount = 0
|
// 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(indices, vertices, 0, (int)XivMesh.IndexCount)];
|
||||||
|
|
||||||
return _mdl.SubMeshes
|
return _mdl.SubMeshes
|
||||||
.Skip(XivMesh.SubMeshIndex)
|
.Skip(XivMesh.SubMeshIndex)
|
||||||
.Take(XivMesh.SubMeshCount)
|
.Take(XivMesh.SubMeshCount)
|
||||||
.Select(submesh => BuildSubMesh(submesh, indices, vertices))
|
.Select(submesh => BuildMesh(indices, vertices, (int)(submesh.IndexOffset - XivMesh.StartIndex), (int)submesh.IndexCount))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IMeshBuilder<MaterialBuilder> BuildSubMesh(MdlStructs.SubmeshStruct submesh, IReadOnlyList<ushort> indices, IReadOnlyList<IVertexBuilder> vertices)
|
private IMeshBuilder<MaterialBuilder> BuildMesh(
|
||||||
|
IReadOnlyList<ushort> indices,
|
||||||
|
IReadOnlyList<IVertexBuilder> vertices,
|
||||||
|
int indexBase,
|
||||||
|
int indexCount
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Index indices are specified relative to the LOD's 0, but we're reading chunks for each mesh.
|
|
||||||
var startIndex = (int)(submesh.IndexOffset - XivMesh.StartIndex);
|
|
||||||
|
|
||||||
var meshBuilderType = typeof(MeshBuilder<,,,>).MakeGenericType(
|
var meshBuilderType = typeof(MeshBuilder<,,,>).MakeGenericType(
|
||||||
typeof(MaterialBuilder),
|
typeof(MaterialBuilder),
|
||||||
_geometryType,
|
_geometryType,
|
||||||
|
|
@ -131,12 +135,12 @@ public class MeshExporter
|
||||||
var gltfIndices = new List<int>();
|
var gltfIndices = new List<int>();
|
||||||
|
|
||||||
// All XIV meshes use triangle lists.
|
// All XIV meshes use triangle lists.
|
||||||
for (var indexOffset = 0; indexOffset < submesh.IndexCount; indexOffset += 3)
|
for (var indexOffset = 0; indexOffset < indexCount; indexOffset += 3)
|
||||||
{
|
{
|
||||||
var (a, b, c) = primitiveBuilder.AddTriangle(
|
var (a, b, c) = primitiveBuilder.AddTriangle(
|
||||||
vertices[indices[indexOffset + startIndex + 0]],
|
vertices[indices[indexBase + indexOffset + 0]],
|
||||||
vertices[indices[indexOffset + startIndex + 1]],
|
vertices[indices[indexBase + indexOffset + 1]],
|
||||||
vertices[indices[indexOffset + startIndex + 2]]
|
vertices[indices[indexBase + indexOffset + 2]]
|
||||||
);
|
);
|
||||||
gltfIndices.AddRange([a, b, c]);
|
gltfIndices.AddRange([a, b, c]);
|
||||||
}
|
}
|
||||||
|
|
@ -157,8 +161,8 @@ public class MeshExporter
|
||||||
.Take((int)shapeMesh.ShapeValueCount)
|
.Take((int)shapeMesh.ShapeValueCount)
|
||||||
)
|
)
|
||||||
.Where(shapeValue =>
|
.Where(shapeValue =>
|
||||||
shapeValue.BaseIndicesIndex >= startIndex
|
shapeValue.BaseIndicesIndex >= indexBase
|
||||||
&& shapeValue.BaseIndicesIndex < startIndex + submesh.IndexCount
|
&& shapeValue.BaseIndicesIndex < indexBase + indexCount
|
||||||
)
|
)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
|
@ -169,7 +173,7 @@ public class MeshExporter
|
||||||
|
|
||||||
foreach (var shapeValue in shapeValues)
|
foreach (var shapeValue in shapeValues)
|
||||||
morphBuilder.SetVertex(
|
morphBuilder.SetVertex(
|
||||||
primitiveVertices[gltfIndices[shapeValue.BaseIndicesIndex - startIndex]].GetGeometry(),
|
primitiveVertices[gltfIndices[shapeValue.BaseIndicesIndex - indexBase]].GetGeometry(),
|
||||||
vertices[shapeValue.ReplacingVertexIndex].GetGeometry()
|
vertices[shapeValue.ReplacingVertexIndex].GetGeometry()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,17 +73,21 @@ public sealed class ModelManager : SingleTaskQueue, IDisposable
|
||||||
|
|
||||||
public void Execute(CancellationToken cancel)
|
public void Execute(CancellationToken cancel)
|
||||||
{
|
{
|
||||||
|
Penumbra.Log.Debug("Reading skeleton.");
|
||||||
var xivSkeleton = BuildSkeleton(cancel);
|
var xivSkeleton = BuildSkeleton(cancel);
|
||||||
|
|
||||||
|
Penumbra.Log.Debug("Converting model.");
|
||||||
var model = ModelExporter.Export(_mdl, xivSkeleton);
|
var model = ModelExporter.Export(_mdl, xivSkeleton);
|
||||||
|
|
||||||
|
Penumbra.Log.Debug("Building scene.");
|
||||||
var scene = new SceneBuilder();
|
var scene = new SceneBuilder();
|
||||||
model.AddToScene(scene);
|
model.AddToScene(scene);
|
||||||
|
|
||||||
|
Penumbra.Log.Debug("Saving.");
|
||||||
var gltfModel = scene.ToGltf2();
|
var gltfModel = scene.ToGltf2();
|
||||||
gltfModel.SaveGLTF(_outputPath);
|
gltfModel.SaveGLTF(_outputPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this should be moved to a seperate model converter or something
|
|
||||||
private XivSkeleton? BuildSkeleton(CancellationToken cancel)
|
private XivSkeleton? BuildSkeleton(CancellationToken cancel)
|
||||||
{
|
{
|
||||||
if (_sklb == null)
|
if (_sklb == null)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue