diff --git a/Penumbra/Import/Models/Export/MeshExporter.cs b/Penumbra/Import/Models/Export/MeshExporter.cs index 03734db8..1c266e52 100644 --- a/Penumbra/Import/Models/Export/MeshExporter.cs +++ b/Penumbra/Import/Models/Export/MeshExporter.cs @@ -375,9 +375,9 @@ public class MeshExporter { (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. diff --git a/Penumbra/Import/Models/Export/VertexFragment.cs b/Penumbra/Import/Models/Export/VertexFragment.cs index 234844d8..27d2ab10 100644 --- a/Penumbra/Import/Models/Export/VertexFragment.cs +++ b/Penumbra/Import/Models/Export/VertexFragment.cs @@ -3,24 +3,173 @@ 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 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 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 { - 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)] + [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]; + private static readonly string[] CustomNames = ["_FFXIV_COLOR"]; public IEnumerable CustomAttributes => CustomNames; public VertexTexture2ColorFfxiv(Vector2 texCoord0, Vector2 texCoord1, Vector4 ffxivColor) @@ -60,7 +209,7 @@ public struct VertexTexture2ColorFfxiv : IVertexCustom { switch (attributeName) { - case FFXIV_COLOR: + case "_FFXIV_COLOR": value = FfxivColor; return true; @@ -72,7 +221,7 @@ public struct VertexTexture2ColorFfxiv : IVertexCustom public void SetCustomAttribute(string attributeName, object value) { - if (attributeName == FFXIV_COLOR && value is Vector4 valueVector4) + if (attributeName == "_FFXIV_COLOR" && value is Vector4 valueVector4) FfxivColor = valueVector4; }