mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Add some Additional Information to Mdl display, discard some padding when reading mdl files.
This commit is contained in:
parent
36c77034a4
commit
8df4bb0781
4 changed files with 315 additions and 241 deletions
|
|
@ -30,7 +30,9 @@ public partial class MdlFile
|
||||||
.Concat(Shapes.Select(s => s.ShapeName))
|
.Concat(Shapes.Select(s => s.ShapeName))
|
||||||
.Select(attribute => Write(w, attribute, basePos)).ToList();
|
.Select(attribute => Write(w, attribute, basePos)).ToList();
|
||||||
|
|
||||||
w.Write( ( ushort )0 ); // Seems to always have two additional null-bytes, not padding.
|
var padding = (w.BaseStream.Position & 0b111) > 0 ? (w.BaseStream.Position & ~0b111) + 8 : w.BaseStream.Position;
|
||||||
|
for (var i = w.BaseStream.Position; i < padding; ++i)
|
||||||
|
w.Write((byte)0);
|
||||||
var size = (int)w.BaseStream.Position - basePos;
|
var size = (int)w.BaseStream.Position - basePos;
|
||||||
w.Seek(startPos + 4, SeekOrigin.Begin);
|
w.Seek(startPos + 4, SeekOrigin.Begin);
|
||||||
w.Write((uint)size);
|
w.Write((uint)size);
|
||||||
|
|
@ -110,9 +112,7 @@ public partial class MdlFile
|
||||||
private static void Write(BinaryWriter w, in MdlStructs.VertexDeclarationStruct vertexDecl)
|
private static void Write(BinaryWriter w, in MdlStructs.VertexDeclarationStruct vertexDecl)
|
||||||
{
|
{
|
||||||
foreach (var vertex in vertexDecl.VertexElements)
|
foreach (var vertex in vertexDecl.VertexElements)
|
||||||
{
|
|
||||||
Write(w, vertex);
|
Write(w, vertex);
|
||||||
}
|
|
||||||
|
|
||||||
Write(w, new MdlStructs.VertexElement() { Stream = 255 });
|
Write(w, new MdlStructs.VertexElement() { Stream = 255 });
|
||||||
w.Seek((int)(NumVertices - 1 - vertexDecl.VertexElements.Length) * 8, SeekOrigin.Current);
|
w.Seek((int)(NumVertices - 1 - vertexDecl.VertexElements.Length) * 8, SeekOrigin.Current);
|
||||||
|
|
@ -163,9 +163,7 @@ public partial class MdlFile
|
||||||
private static void Write(BinaryWriter w, MdlStructs.BoneTableStruct bone)
|
private static void Write(BinaryWriter w, MdlStructs.BoneTableStruct bone)
|
||||||
{
|
{
|
||||||
foreach (var index in bone.BoneIndex)
|
foreach (var index in bone.BoneIndex)
|
||||||
{
|
|
||||||
w.Write(index);
|
w.Write(index);
|
||||||
}
|
|
||||||
|
|
||||||
w.Write(bone.BoneCount);
|
w.Write(bone.BoneCount);
|
||||||
w.Write((ushort)0); // 3 bytes padding
|
w.Write((ushort)0); // 3 bytes padding
|
||||||
|
|
@ -206,102 +204,72 @@ public partial class MdlFile
|
||||||
w.Seek((int)FileHeaderSize, SeekOrigin.Begin);
|
w.Seek((int)FileHeaderSize, SeekOrigin.Begin);
|
||||||
|
|
||||||
foreach (var vertexDecl in VertexDeclarations)
|
foreach (var vertexDecl in VertexDeclarations)
|
||||||
{
|
|
||||||
Write(w, vertexDecl);
|
Write(w, vertexDecl);
|
||||||
}
|
|
||||||
|
|
||||||
var offsets = WriteStrings(w);
|
var offsets = WriteStrings(w);
|
||||||
WriteModelHeader(w);
|
WriteModelHeader(w);
|
||||||
|
|
||||||
foreach (var elementId in ElementIds)
|
foreach (var elementId in ElementIds)
|
||||||
{
|
|
||||||
Write(w, elementId);
|
Write(w, elementId);
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var lod in Lods)
|
foreach (var lod in Lods)
|
||||||
{
|
|
||||||
Write(w, lod);
|
Write(w, lod);
|
||||||
}
|
|
||||||
|
|
||||||
if (Flags2.HasFlag(MdlStructs.ModelFlags2.ExtraLodEnabled))
|
if (Flags2.HasFlag(MdlStructs.ModelFlags2.ExtraLodEnabled))
|
||||||
{
|
|
||||||
foreach (var extraLod in ExtraLods)
|
foreach (var extraLod in ExtraLods)
|
||||||
{
|
|
||||||
Write(w, extraLod);
|
Write(w, extraLod);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var mesh in Meshes)
|
foreach (var mesh in Meshes)
|
||||||
{
|
|
||||||
Write(w, mesh);
|
Write(w, mesh);
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < Attributes.Length; ++i)
|
for (var i = 0; i < Attributes.Length; ++i)
|
||||||
{
|
|
||||||
w.Write(offsets[i]);
|
w.Write(offsets[i]);
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var terrainShadowMesh in TerrainShadowMeshes)
|
foreach (var terrainShadowMesh in TerrainShadowMeshes)
|
||||||
{
|
|
||||||
Write(w, terrainShadowMesh);
|
Write(w, terrainShadowMesh);
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var subMesh in SubMeshes)
|
foreach (var subMesh in SubMeshes)
|
||||||
{
|
|
||||||
Write(w, subMesh);
|
Write(w, subMesh);
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var terrainShadowSubMesh in TerrainShadowSubMeshes)
|
foreach (var terrainShadowSubMesh in TerrainShadowSubMeshes)
|
||||||
{
|
|
||||||
Write(w, terrainShadowSubMesh);
|
Write(w, terrainShadowSubMesh);
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < Materials.Length; ++i)
|
for (var i = 0; i < Materials.Length; ++i)
|
||||||
{
|
|
||||||
w.Write(offsets[Attributes.Length + Bones.Length + i]);
|
w.Write(offsets[Attributes.Length + Bones.Length + i]);
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < Bones.Length; ++i)
|
for (var i = 0; i < Bones.Length; ++i)
|
||||||
{
|
|
||||||
w.Write(offsets[Attributes.Length + i]);
|
w.Write(offsets[Attributes.Length + i]);
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var boneTable in BoneTables)
|
foreach (var boneTable in BoneTables)
|
||||||
{
|
|
||||||
Write(w, boneTable);
|
Write(w, boneTable);
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < Shapes.Length; ++i)
|
for (var i = 0; i < Shapes.Length; ++i)
|
||||||
{
|
|
||||||
Write(w, i, offsets);
|
Write(w, i, offsets);
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var shapeMesh in ShapeMeshes)
|
foreach (var shapeMesh in ShapeMeshes)
|
||||||
{
|
|
||||||
Write(w, shapeMesh);
|
Write(w, shapeMesh);
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var shapeValue in ShapeValues)
|
foreach (var shapeValue in ShapeValues)
|
||||||
{
|
|
||||||
Write(w, shapeValue);
|
Write(w, shapeValue);
|
||||||
}
|
|
||||||
|
|
||||||
w.Write(SubMeshBoneMap.Length * 2);
|
w.Write(SubMeshBoneMap.Length * 2);
|
||||||
foreach (var bone in SubMeshBoneMap)
|
foreach (var bone in SubMeshBoneMap)
|
||||||
{
|
|
||||||
w.Write(bone);
|
w.Write(bone);
|
||||||
}
|
|
||||||
|
|
||||||
w.Write( ( byte )0 ); // number of padding bytes, which is 0 for us.
|
var pos = w.BaseStream.Position + 1;
|
||||||
|
var padding = (byte) (pos & 0b111);
|
||||||
|
if (padding > 0)
|
||||||
|
padding = (byte) (8 - padding);
|
||||||
|
w.Write(padding);
|
||||||
|
for (var i = 0; i < padding; ++i)
|
||||||
|
w.Write((byte) (0xDEADBEEFF00DCAFEu >> (8 * (7 - i))));
|
||||||
|
|
||||||
Write(w, BoundingBoxes);
|
Write(w, BoundingBoxes);
|
||||||
Write(w, ModelBoundingBoxes);
|
Write(w, ModelBoundingBoxes);
|
||||||
Write(w, WaterBoundingBoxes);
|
Write(w, WaterBoundingBoxes);
|
||||||
Write(w, VerticalFogBoundingBoxes);
|
Write(w, VerticalFogBoundingBoxes);
|
||||||
foreach (var box in BoneBoundingBoxes)
|
foreach (var box in BoneBoundingBoxes)
|
||||||
{
|
|
||||||
Write(w, box);
|
Write(w, box);
|
||||||
}
|
|
||||||
|
|
||||||
var totalSize = w.BaseStream.Position;
|
var totalSize = w.BaseStream.Position;
|
||||||
var runtimeSize = (uint)(totalSize - StackSize - FileHeaderSize);
|
var runtimeSize = (uint)(totalSize - StackSize - FileHeaderSize);
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,9 @@ public partial class MdlFile : IWritable
|
||||||
for (var i = 0; i < modelHeader.BoneCount; i++)
|
for (var i = 0; i < modelHeader.BoneCount; i++)
|
||||||
BoneBoundingBoxes[i] = MdlStructs.BoundingBoxStruct.Read(r);
|
BoneBoundingBoxes[i] = MdlStructs.BoundingBoxStruct.Read(r);
|
||||||
|
|
||||||
|
var runtimePadding = header.RuntimeSize + FileHeaderSize + header.StackSize - r.BaseStream.Position;
|
||||||
|
if (runtimePadding > 0)
|
||||||
|
r.ReadBytes((int)runtimePadding);
|
||||||
RemainingData = r.ReadBytes((int)(r.BaseStream.Length - r.BaseStream.Position));
|
RemainingData = r.ReadBytes((int)(r.BaseStream.Length - r.BaseStream.Position));
|
||||||
Valid = true;
|
Valid = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -215,10 +215,10 @@ public partial class ModEditWindow
|
||||||
|
|
||||||
if( file.AdditionalData.Length > 0 )
|
if( file.AdditionalData.Length > 0 )
|
||||||
{
|
{
|
||||||
using var t = ImRaii.TreeNode( "Additional Data" );
|
using var t = ImRaii.TreeNode( $"Additional Data (Size: {file.AdditionalData.Length})###AdditionalData" );
|
||||||
if( t )
|
if( t )
|
||||||
{
|
{
|
||||||
ImRaii.TreeNode( string.Join( ' ', file.AdditionalData.Select( c => $"{c:X2}" ) ), ImGuiTreeNodeFlags.Leaf ).Dispose();
|
ImGuiUtil.TextWrapped( string.Join( ' ', file.AdditionalData.Select( c => $"{c:X2}" ) ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
using OtterGui;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
using Penumbra.GameData.Files;
|
using Penumbra.GameData.Files;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Penumbra.UI.Classes;
|
namespace Penumbra.UI.Classes;
|
||||||
|
|
||||||
|
|
@ -26,6 +29,106 @@ public partial class ModEditWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret |= DrawOtherModelDetails( file, disabled );
|
||||||
|
|
||||||
return !disabled && ret;
|
return !disabled && ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool DrawOtherModelDetails( MdlFile file, bool _ )
|
||||||
|
{
|
||||||
|
if( !ImGui.CollapsingHeader( "Further Content" ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
using( var table = ImRaii.Table( "##data", 2, ImGuiTableFlags.SizingFixedFit ) )
|
||||||
|
{
|
||||||
|
if( table )
|
||||||
|
{
|
||||||
|
ImGuiUtil.DrawTableColumn( "Version" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.Version.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Radius" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.Radius.ToString( CultureInfo.InvariantCulture ) );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Model Clip Out Distance" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.ModelClipOutDistance.ToString( CultureInfo.InvariantCulture ) );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Shadow Clip Out Distance" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.ShadowClipOutDistance.ToString( CultureInfo.InvariantCulture ) );
|
||||||
|
ImGuiUtil.DrawTableColumn( "LOD Count" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.LodCount.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Enable Index Buffer Streaming" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.EnableIndexBufferStreaming.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Enable Edge Geometry" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.EnableEdgeGeometry.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Flags 1" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.Flags1.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Flags 2" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.Flags2.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Vertex Declarations" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.VertexDeclarations.Length.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Bone Bounding Boxes" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.BoneBoundingBoxes.Length.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Bone Tables" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.BoneTables.Length.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Element IDs" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.ElementIds.Length.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Extra LoDs" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.ExtraLods.Length.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Meshes" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.Meshes.Length.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Shape Meshes" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.ShapeMeshes.Length.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "LoDs" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.Lods.Length.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Vertex Declarations" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.VertexDeclarations.Length.ToString() );
|
||||||
|
ImGuiUtil.DrawTableColumn( "Stack Size" );
|
||||||
|
ImGuiUtil.DrawTableColumn( file.StackSize.ToString() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using( var attributes = ImRaii.TreeNode( "Attributes", ImGuiTreeNodeFlags.DefaultOpen ) )
|
||||||
|
{
|
||||||
|
if( attributes )
|
||||||
|
{
|
||||||
|
foreach( var attribute in file.Attributes )
|
||||||
|
{
|
||||||
|
ImRaii.TreeNode( attribute, ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using( var bones = ImRaii.TreeNode( "Bones", ImGuiTreeNodeFlags.DefaultOpen ) )
|
||||||
|
{
|
||||||
|
if( bones )
|
||||||
|
{
|
||||||
|
foreach( var bone in file.Bones )
|
||||||
|
{
|
||||||
|
ImRaii.TreeNode( bone, ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using( var shapes = ImRaii.TreeNode( "Shapes", ImGuiTreeNodeFlags.DefaultOpen ) )
|
||||||
|
{
|
||||||
|
if( shapes )
|
||||||
|
{
|
||||||
|
foreach( var shape in file.Shapes )
|
||||||
|
{
|
||||||
|
ImRaii.TreeNode( shape.ShapeName, ImGuiTreeNodeFlags.Leaf ).Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( file.RemainingData.Length > 0 )
|
||||||
|
{
|
||||||
|
using var t = ImRaii.TreeNode( $"Additional Data (Size: {file.RemainingData.Length})###AdditionalData" );
|
||||||
|
if( t )
|
||||||
|
{
|
||||||
|
ImGuiUtil.TextWrapped( string.Join( ' ', file.RemainingData.Select( c => $"{c:X2}" ) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue