mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 12:14:17 +01:00
Add material file parsing and writing.
This commit is contained in:
parent
5ac3a903f6
commit
5e9cb77415
2 changed files with 229 additions and 0 deletions
133
Penumbra.GameData/Files/MtrlFile.cs
Normal file
133
Penumbra.GameData/Files/MtrlFile.cs
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Lumina.Data.Parsing;
|
||||
using Lumina.Extensions;
|
||||
|
||||
namespace Penumbra.GameData.Files;
|
||||
|
||||
public partial class MtrlFile
|
||||
{
|
||||
public struct ColorSet
|
||||
{
|
||||
public string Name;
|
||||
public ushort Index;
|
||||
}
|
||||
|
||||
public struct Texture
|
||||
{
|
||||
public string Path;
|
||||
public ushort Flags;
|
||||
}
|
||||
|
||||
public struct Constant
|
||||
{
|
||||
public uint Id;
|
||||
public uint Value;
|
||||
}
|
||||
|
||||
public struct ShaderPackageData
|
||||
{
|
||||
public string Name;
|
||||
public ShaderKey[] ShaderKeys;
|
||||
public Constant[] Constants;
|
||||
public Sampler[] Samplers;
|
||||
public float[] ShaderValues;
|
||||
public uint Unk;
|
||||
}
|
||||
|
||||
|
||||
public uint Version;
|
||||
|
||||
public Texture[] Textures;
|
||||
public ColorSet[] UvColorSets;
|
||||
public ColorSet[] ColorSets;
|
||||
public ushort[] ColorSetData;
|
||||
public ShaderPackageData ShaderPackage;
|
||||
public byte[] AdditionalData;
|
||||
|
||||
public MtrlFile( byte[] data )
|
||||
{
|
||||
using var stream = new MemoryStream( data );
|
||||
using var r = new BinaryReader( stream );
|
||||
|
||||
Version = r.ReadUInt32();
|
||||
r.ReadUInt16(); // file size
|
||||
var dataSetSize = r.ReadUInt16();
|
||||
var stringTableSize = r.ReadUInt16();
|
||||
var shaderPackageNameOffset = r.ReadUInt16();
|
||||
var textureCount = r.ReadByte();
|
||||
var uvSetCount = r.ReadByte();
|
||||
var colorSetCount = r.ReadByte();
|
||||
var additionalDataSize = r.ReadByte();
|
||||
|
||||
Textures = ReadTextureOffsets( r, textureCount, out var textureOffsets );
|
||||
UvColorSets = ReadColorSetOffsets( r, uvSetCount, out var uvOffsets );
|
||||
ColorSets = ReadColorSetOffsets( r, colorSetCount, out var colorOffsets );
|
||||
|
||||
var strings = r.ReadBytes( stringTableSize );
|
||||
for( var i = 0; i < textureCount; ++i )
|
||||
{
|
||||
Textures[ i ].Path = UseOffset( strings, textureOffsets[ i ] );
|
||||
}
|
||||
|
||||
for( var i = 0; i < uvSetCount; ++i )
|
||||
{
|
||||
UvColorSets[ i ].Name = UseOffset( strings, uvOffsets[ i ] );
|
||||
}
|
||||
|
||||
for( var i = 0; i < colorSetCount; ++i )
|
||||
{
|
||||
ColorSets[ i ].Name = UseOffset( strings, colorOffsets[ i ] );
|
||||
}
|
||||
|
||||
ShaderPackage.Name = UseOffset( strings, shaderPackageNameOffset );
|
||||
|
||||
AdditionalData = r.ReadBytes( additionalDataSize );
|
||||
ColorSetData = r.ReadStructuresAsArray< ushort >( dataSetSize / 2 );
|
||||
|
||||
var shaderValueListSize = r.ReadUInt16();
|
||||
var shaderKeyCount = r.ReadUInt16();
|
||||
var constantCount = r.ReadUInt16();
|
||||
var samplerCount = r.ReadUInt16();
|
||||
ShaderPackage.Unk = r.ReadUInt32();
|
||||
|
||||
ShaderPackage.ShaderKeys = r.ReadStructuresAsArray< ShaderKey >( shaderKeyCount );
|
||||
ShaderPackage.Constants = r.ReadStructuresAsArray< Constant >( constantCount );
|
||||
ShaderPackage.Samplers = r.ReadStructuresAsArray< Sampler >( samplerCount );
|
||||
ShaderPackage.ShaderValues = r.ReadStructuresAsArray< float >( shaderValueListSize / 4 );
|
||||
}
|
||||
|
||||
private static Texture[] ReadTextureOffsets( BinaryReader r, int count, out ushort[] offsets )
|
||||
{
|
||||
var ret = new Texture[count];
|
||||
offsets = new ushort[count];
|
||||
for( var i = 0; i < count; ++i )
|
||||
{
|
||||
offsets[ i ] = r.ReadUInt16();
|
||||
ret[ i ].Flags = r.ReadUInt16();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static ColorSet[] ReadColorSetOffsets( BinaryReader r, int count, out ushort[] offsets )
|
||||
{
|
||||
var ret = new ColorSet[count];
|
||||
offsets = new ushort[count];
|
||||
for( var i = 0; i < count; ++i )
|
||||
{
|
||||
offsets[ i ] = r.ReadUInt16();
|
||||
ret[ i ].Index = r.ReadUInt16();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static string UseOffset( ReadOnlySpan< byte > strings, ushort offset )
|
||||
{
|
||||
strings = strings[ offset.. ];
|
||||
var end = strings.IndexOf( ( byte )'\0' );
|
||||
return Encoding.UTF8.GetString( strings[ ..end ] );
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue