diff --git a/Penumbra/Import/Models/Export/MeshExporter.cs b/Penumbra/Import/Models/Export/MeshExporter.cs index 928c8670..03734db8 100644 --- a/Penumbra/Import/Models/Export/MeshExporter.cs +++ b/Penumbra/Import/Models/Export/MeshExporter.cs @@ -373,7 +373,7 @@ public class MeshExporter return materialUsages switch { - (2, true) => typeof(VertexColor1Texture2), + (2, true) => typeof(VertexTexture2ColorFfxiv), (2, false) => typeof(VertexTexture2), (1, true) => typeof(VertexColor1Texture1), (1, false) => typeof(VertexTexture1), @@ -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]) ); } diff --git a/Penumbra/Import/Models/Export/VertexFragment.cs b/Penumbra/Import/Models/Export/VertexFragment.cs new file mode 100644 index 00000000..234844d8 --- /dev/null +++ b/Penumbra/Import/Models/Export/VertexFragment.cs @@ -0,0 +1,92 @@ +using SharpGLTF.Geometry.VertexTypes; +using SharpGLTF.Schema2; + +namespace Penumbra.Import.Models.Export; + +public struct VertexTexture2ColorFfxiv : IVertexCustom +{ + public const string FFXIV_COLOR = "_FFXIV_COLOR"; + + [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 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)); + } +} diff --git a/Penumbra/Import/Models/Import/VertexAttribute.cs b/Penumbra/Import/Models/Import/VertexAttribute.cs index b73f6a89..b8576108 100644 --- a/Penumbra/Import/Models/Import/VertexAttribute.cs +++ b/Penumbra/Import/Models/Import/VertexAttribute.cs @@ -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() {