Merge remote-tracking branch 'ackwell/mdl-io-color-attribute'

This commit is contained in:
Ottermandias 2024-01-22 16:54:52 +01:00
commit a2eaa3ed7f
3 changed files with 257 additions and 14 deletions

View file

@ -373,11 +373,11 @@ public class MeshExporter
return materialUsages switch
{
(2, true) => typeof(VertexColor1Texture2),
(2, true) => typeof(VertexTexture2ColorFfxiv),
(2, false) => typeof(VertexTexture2),
(1, true) => typeof(VertexColor1Texture1),
(1, true) => typeof(VertexTexture1ColorFfxiv),
(1, false) => typeof(VertexTexture1),
(0, true) => typeof(VertexColor1),
(0, true) => typeof(VertexColorFfxiv),
(0, false) => typeof(VertexEmpty),
_ => throw new Exception("Unreachable."),
@ -390,16 +390,16 @@ public class MeshExporter
if (_materialType == typeof(VertexEmpty))
return new VertexEmpty();
if (_materialType == typeof(VertexColor1))
return new VertexColor1(ToVector4(attributes[MdlFile.VertexUsage.Color]));
if (_materialType == typeof(VertexColorFfxiv))
return new VertexColorFfxiv(ToVector4(attributes[MdlFile.VertexUsage.Color]));
if (_materialType == typeof(VertexTexture1))
return new VertexTexture1(ToVector2(attributes[MdlFile.VertexUsage.UV]));
if (_materialType == typeof(VertexColor1Texture1))
return new VertexColor1Texture1(
ToVector4(attributes[MdlFile.VertexUsage.Color]),
ToVector2(attributes[MdlFile.VertexUsage.UV])
if (_materialType == typeof(VertexTexture1ColorFfxiv))
return new VertexTexture1ColorFfxiv(
ToVector2(attributes[MdlFile.VertexUsage.UV]),
ToVector4(attributes[MdlFile.VertexUsage.Color])
);
// XIV packs two UVs into a single vec4 attribute.
@ -413,13 +413,13 @@ public class MeshExporter
);
}
if (_materialType == typeof(VertexColor1Texture2))
if (_materialType == typeof(VertexTexture2ColorFfxiv))
{
var uv = ToVector4(attributes[MdlFile.VertexUsage.UV]);
return new VertexColor1Texture2(
ToVector4(attributes[MdlFile.VertexUsage.Color]),
return new VertexTexture2ColorFfxiv(
new Vector2(uv.X, uv.Y),
new Vector2(uv.Z, uv.W)
new Vector2(uv.Z, uv.W),
ToVector4(attributes[MdlFile.VertexUsage.Color])
);
}

View file

@ -0,0 +1,241 @@
using SharpGLTF.Geometry.VertexTypes;
using SharpGLTF.Schema2;
namespace Penumbra.Import.Models.Export;
/*
Yeah, look, I tried to make this file less garbage. It's a little difficult.
Realistically, it will need to stick around until transforms/mutations are built
and there's reason to overhaul the export pipeline.
*/
public struct VertexColorFfxiv : IVertexCustom
{
[VertexAttribute("_FFXIV_COLOR", EncodingType.UNSIGNED_BYTE, false)]
public Vector4 FfxivColor;
public int MaxColors => 0;
public int MaxTextCoords => 0;
private static readonly string[] CustomNames = ["_FFXIV_COLOR"];
public IEnumerable<string> CustomAttributes => CustomNames;
public VertexColorFfxiv(Vector4 ffxivColor)
{
FfxivColor = ffxivColor;
}
public void Add(in VertexMaterialDelta delta)
{
}
public VertexMaterialDelta Subtract(IVertexMaterial baseValue)
=> new VertexMaterialDelta(Vector4.Zero, Vector4.Zero, Vector2.Zero, Vector2.Zero);
public Vector2 GetTexCoord(int index)
=> throw new ArgumentOutOfRangeException(nameof(index));
public void SetTexCoord(int setIndex, Vector2 coord)
{
}
public bool TryGetCustomAttribute(string attributeName, out object? value)
{
switch (attributeName)
{
case "_FFXIV_COLOR":
value = FfxivColor;
return true;
default:
value = null;
return false;
}
}
public void SetCustomAttribute(string attributeName, object value)
{
if (attributeName == "_FFXIV_COLOR" && value is Vector4 valueVector4)
FfxivColor = valueVector4;
}
public Vector4 GetColor(int index)
=> throw new ArgumentOutOfRangeException(nameof(index));
public void SetColor(int setIndex, Vector4 color)
{
}
public void Validate()
{
var components = new[] { FfxivColor.X, FfxivColor.Y, FfxivColor.Z, FfxivColor.W };
if (components.Any(component => component < 0 || component > 1))
throw new ArgumentOutOfRangeException(nameof(FfxivColor));
}
}
public struct VertexTexture1ColorFfxiv : IVertexCustom
{
[VertexAttribute("TEXCOORD_0")]
public Vector2 TexCoord0;
[VertexAttribute("_FFXIV_COLOR", EncodingType.UNSIGNED_BYTE, false)]
public Vector4 FfxivColor;
public int MaxColors => 0;
public int MaxTextCoords => 1;
private static readonly string[] CustomNames = ["_FFXIV_COLOR"];
public IEnumerable<string> CustomAttributes => CustomNames;
public VertexTexture1ColorFfxiv(Vector2 texCoord0, Vector4 ffxivColor)
{
TexCoord0 = texCoord0;
FfxivColor = ffxivColor;
}
public void Add(in VertexMaterialDelta delta)
{
TexCoord0 += delta.TexCoord0Delta;
}
public VertexMaterialDelta Subtract(IVertexMaterial baseValue)
{
return new VertexMaterialDelta(Vector4.Zero, Vector4.Zero, TexCoord0 - baseValue.GetTexCoord(0), Vector2.Zero);
}
public Vector2 GetTexCoord(int index)
=> index switch
{
0 => TexCoord0,
_ => throw new ArgumentOutOfRangeException(nameof(index)),
};
public void SetTexCoord(int setIndex, Vector2 coord)
{
if (setIndex == 0) TexCoord0 = coord;
if (setIndex >= 1) throw new ArgumentOutOfRangeException(nameof(setIndex));
}
public bool TryGetCustomAttribute(string attributeName, out object? value)
{
switch (attributeName)
{
case "_FFXIV_COLOR":
value = FfxivColor;
return true;
default:
value = null;
return false;
}
}
public void SetCustomAttribute(string attributeName, object value)
{
if (attributeName == "_FFXIV_COLOR" && value is Vector4 valueVector4)
FfxivColor = valueVector4;
}
public Vector4 GetColor(int index)
=> throw new ArgumentOutOfRangeException(nameof(index));
public void SetColor(int setIndex, Vector4 color)
{
}
public void Validate()
{
var components = new[] { FfxivColor.X, FfxivColor.Y, FfxivColor.Z, FfxivColor.W };
if (components.Any(component => component < 0 || component > 1))
throw new ArgumentOutOfRangeException(nameof(FfxivColor));
}
}
public struct VertexTexture2ColorFfxiv : IVertexCustom
{
[VertexAttribute("TEXCOORD_0")]
public Vector2 TexCoord0;
[VertexAttribute("TEXCOORD_1")]
public Vector2 TexCoord1;
[VertexAttribute("_FFXIV_COLOR", EncodingType.UNSIGNED_BYTE, false)]
public Vector4 FfxivColor;
public int MaxColors => 0;
public int MaxTextCoords => 2;
private static readonly string[] CustomNames = ["_FFXIV_COLOR"];
public IEnumerable<string> CustomAttributes => CustomNames;
public VertexTexture2ColorFfxiv(Vector2 texCoord0, Vector2 texCoord1, Vector4 ffxivColor)
{
TexCoord0 = texCoord0;
TexCoord1 = texCoord1;
FfxivColor = ffxivColor;
}
public void Add(in VertexMaterialDelta delta)
{
TexCoord0 += delta.TexCoord0Delta;
TexCoord1 += delta.TexCoord1Delta;
}
public VertexMaterialDelta Subtract(IVertexMaterial baseValue)
{
return new VertexMaterialDelta(Vector4.Zero, Vector4.Zero, TexCoord0 - baseValue.GetTexCoord(0), TexCoord1 - baseValue.GetTexCoord(1));
}
public Vector2 GetTexCoord(int index)
=> index switch
{
0 => TexCoord0,
1 => TexCoord1,
_ => throw new ArgumentOutOfRangeException(nameof(index)),
};
public void SetTexCoord(int setIndex, Vector2 coord)
{
if (setIndex == 0) TexCoord0 = coord;
if (setIndex == 1) TexCoord1 = coord;
if (setIndex >= 2) throw new ArgumentOutOfRangeException(nameof(setIndex));
}
public bool TryGetCustomAttribute(string attributeName, out object? value)
{
switch (attributeName)
{
case "_FFXIV_COLOR":
value = FfxivColor;
return true;
default:
value = null;
return false;
}
}
public void SetCustomAttribute(string attributeName, object value)
{
if (attributeName == "_FFXIV_COLOR" && value is Vector4 valueVector4)
FfxivColor = valueVector4;
}
public Vector4 GetColor(int index)
=> throw new ArgumentOutOfRangeException(nameof(index));
public void SetColor(int setIndex, Vector4 color)
{
}
public void Validate()
{
var components = new[] { FfxivColor.X, FfxivColor.Y, FfxivColor.Z, FfxivColor.W };
if (components.Any(component => component < 0 || component > 1))
throw new ArgumentOutOfRangeException(nameof(FfxivColor));
}
}

View file

@ -395,7 +395,9 @@ public class VertexAttribute
public static VertexAttribute Color(Accessors accessors)
{
accessors.TryGetValue("COLOR_0", out var accessor);
// Try to retrieve the custom color attribute we use for export, falling back to the glTF standard name.
if (!accessors.TryGetValue("_FFXIV_COLOR", out var accessor))
accessors.TryGetValue("COLOR_0", out accessor);
var element = new MdlStructs.VertexElement()
{