mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Add vertex material types for usages of 2 colour attributes
This commit is contained in:
parent
2b36f39848
commit
8140d08557
2 changed files with 523 additions and 10 deletions
|
|
@ -390,23 +390,30 @@ public class MeshExporter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usages.TryGetValue(MdlFile.VertexUsage.Color, out var colours);
|
||||||
|
var nColors = colours?.Count ?? 0;
|
||||||
|
|
||||||
var materialUsages = (
|
var materialUsages = (
|
||||||
uvCount,
|
uvCount,
|
||||||
usages.ContainsKey(MdlFile.VertexUsage.Color)
|
nColors
|
||||||
);
|
);
|
||||||
|
|
||||||
return materialUsages switch
|
return materialUsages switch
|
||||||
{
|
{
|
||||||
(3, true) => typeof(VertexTexture3ColorFfxiv),
|
(3, 2) => typeof(VertexTexture3Color2Ffxiv),
|
||||||
(3, false) => typeof(VertexTexture3),
|
(3, 1) => typeof(VertexTexture3ColorFfxiv),
|
||||||
(2, true) => typeof(VertexTexture2ColorFfxiv),
|
(3, 0) => typeof(VertexTexture3),
|
||||||
(2, false) => typeof(VertexTexture2),
|
(2, 2) => typeof(VertexTexture2Color2Ffxiv),
|
||||||
(1, true) => typeof(VertexTexture1ColorFfxiv),
|
(2, 1) => typeof(VertexTexture2ColorFfxiv),
|
||||||
(1, false) => typeof(VertexTexture1),
|
(2, 0) => typeof(VertexTexture2),
|
||||||
(0, true) => typeof(VertexColorFfxiv),
|
(1, 2) => typeof(VertexTexture1Color2Ffxiv),
|
||||||
(0, false) => typeof(VertexEmpty),
|
(1, 1) => typeof(VertexTexture1ColorFfxiv),
|
||||||
|
(1, 0) => typeof(VertexTexture1),
|
||||||
|
(0, 2) => typeof(VertexColor2Ffxiv),
|
||||||
|
(0, 1) => typeof(VertexColorFfxiv),
|
||||||
|
(0, 0) => typeof(VertexEmpty),
|
||||||
|
|
||||||
_ => throw _notifier.Exception($"Unhandled UV count of {uvCount} encountered."),
|
_ => throw _notifier.Exception($"Unhandled UV/color count of {uvCount}/{nColors} encountered."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -419,6 +426,12 @@ public class MeshExporter
|
||||||
if (_materialType == typeof(VertexColorFfxiv))
|
if (_materialType == typeof(VertexColorFfxiv))
|
||||||
return new VertexColorFfxiv(ToVector4(GetFirstSafe(attributes, MdlFile.VertexUsage.Color)));
|
return new VertexColorFfxiv(ToVector4(GetFirstSafe(attributes, MdlFile.VertexUsage.Color)));
|
||||||
|
|
||||||
|
if (_materialType == typeof(VertexColor2Ffxiv))
|
||||||
|
{
|
||||||
|
var (color0, color1) = GetBothSafe(attributes, MdlFile.VertexUsage.Color);
|
||||||
|
return new VertexColor2Ffxiv(ToVector4(color0), ToVector4(color1));
|
||||||
|
}
|
||||||
|
|
||||||
if (_materialType == typeof(VertexTexture1))
|
if (_materialType == typeof(VertexTexture1))
|
||||||
return new VertexTexture1(ToVector2(GetFirstSafe(attributes, MdlFile.VertexUsage.UV)));
|
return new VertexTexture1(ToVector2(GetFirstSafe(attributes, MdlFile.VertexUsage.UV)));
|
||||||
|
|
||||||
|
|
@ -428,6 +441,16 @@ public class MeshExporter
|
||||||
ToVector4(GetFirstSafe(attributes, MdlFile.VertexUsage.Color))
|
ToVector4(GetFirstSafe(attributes, MdlFile.VertexUsage.Color))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (_materialType == typeof(VertexTexture1Color2Ffxiv))
|
||||||
|
{
|
||||||
|
var (color0, color1) = GetBothSafe(attributes, MdlFile.VertexUsage.Color);
|
||||||
|
return new VertexTexture1Color2Ffxiv(
|
||||||
|
ToVector2(GetFirstSafe(attributes, MdlFile.VertexUsage.UV)),
|
||||||
|
ToVector4(color0),
|
||||||
|
ToVector4(color1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// XIV packs two UVs into a single vec4 attribute.
|
// XIV packs two UVs into a single vec4 attribute.
|
||||||
|
|
||||||
if (_materialType == typeof(VertexTexture2))
|
if (_materialType == typeof(VertexTexture2))
|
||||||
|
|
@ -448,6 +471,20 @@ public class MeshExporter
|
||||||
ToVector4(GetFirstSafe(attributes, MdlFile.VertexUsage.Color))
|
ToVector4(GetFirstSafe(attributes, MdlFile.VertexUsage.Color))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_materialType == typeof(VertexTexture2Color2Ffxiv))
|
||||||
|
{
|
||||||
|
var uv = ToVector4(GetFirstSafe(attributes, MdlFile.VertexUsage.UV));
|
||||||
|
var (color0, color1) = GetBothSafe(attributes, MdlFile.VertexUsage.Color);
|
||||||
|
|
||||||
|
return new VertexTexture2Color2Ffxiv(
|
||||||
|
new Vector2(uv.X, uv.Y),
|
||||||
|
new Vector2(uv.Z, uv.W),
|
||||||
|
ToVector4(color0),
|
||||||
|
ToVector4(color1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (_materialType == typeof(VertexTexture3))
|
if (_materialType == typeof(VertexTexture3))
|
||||||
{
|
{
|
||||||
// Not 100% sure about this
|
// Not 100% sure about this
|
||||||
|
|
@ -472,6 +509,21 @@ public class MeshExporter
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_materialType == typeof(VertexTexture3Color2Ffxiv))
|
||||||
|
{
|
||||||
|
var uv0 = ToVector4(attributes[MdlFile.VertexUsage.UV][0]);
|
||||||
|
var uv1 = ToVector4(attributes[MdlFile.VertexUsage.UV][1]);
|
||||||
|
var (color0, color1) = GetBothSafe(attributes, MdlFile.VertexUsage.Color);
|
||||||
|
|
||||||
|
return new VertexTexture3Color2Ffxiv(
|
||||||
|
new Vector2(uv0.X, uv0.Y),
|
||||||
|
new Vector2(uv0.Z, uv0.W),
|
||||||
|
new Vector2(uv1.X, uv1.Y),
|
||||||
|
ToVector4(color0),
|
||||||
|
ToVector4(color1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
throw _notifier.Exception($"Unknown material type {_skinningType}");
|
throw _notifier.Exception($"Unknown material type {_skinningType}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -538,6 +590,17 @@ public class MeshExporter
|
||||||
return list[0];
|
return list[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Check that the list has length 2 for any case where this is expected and return both entries. </summary>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
private (T First, T Second) GetBothSafe<T>(IReadOnlyDictionary<MdlFile.VertexUsage, List<T>> attributes, MdlFile.VertexUsage usage)
|
||||||
|
{
|
||||||
|
var list = attributes[usage];
|
||||||
|
if (list.Count != 2)
|
||||||
|
throw _notifier.Exception($"{list.Count} usage indices encountered for {usage}, but expected 2.");
|
||||||
|
|
||||||
|
return (list[0], list[1]);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary> Convert a vertex attribute value to a Vector2. Supported inputs are Vector2, Vector3, and Vector4. </summary>
|
/// <summary> Convert a vertex attribute value to a Vector2. Supported inputs are Vector2, Vector3, and Vector4. </summary>
|
||||||
private static Vector2 ToVector2(object data)
|
private static Vector2 ToVector2(object data)
|
||||||
=> data switch
|
=> data switch
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,103 @@ public struct VertexColorFfxiv(Vector4 ffxivColor) : IVertexCustom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct VertexColor2Ffxiv(Vector4 ffxivColor0, Vector4 ffxivColor1) : IVertexCustom
|
||||||
|
{
|
||||||
|
public IEnumerable<KeyValuePair<string, AttributeFormat>> GetEncodingAttributes()
|
||||||
|
{
|
||||||
|
yield return new KeyValuePair<string, AttributeFormat>("_FFXIV_COLOR_0",
|
||||||
|
new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true));
|
||||||
|
yield return new KeyValuePair<string, AttributeFormat>("_FFXIV_COLOR_1",
|
||||||
|
new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector4 FfxivColor0 = ffxivColor0;
|
||||||
|
public Vector4 FfxivColor1 = ffxivColor1;
|
||||||
|
|
||||||
|
public int MaxColors
|
||||||
|
=> 0;
|
||||||
|
|
||||||
|
public int MaxTextCoords
|
||||||
|
=> 0;
|
||||||
|
|
||||||
|
private static readonly string[] CustomNames = ["_FFXIV_COLOR_0", "_FFXIV_COLOR_1"];
|
||||||
|
|
||||||
|
public IEnumerable<string> CustomAttributes
|
||||||
|
=> CustomNames;
|
||||||
|
|
||||||
|
public void Add(in VertexMaterialDelta delta)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public VertexMaterialDelta Subtract(IVertexMaterial baseValue)
|
||||||
|
=> new(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_0":
|
||||||
|
value = FfxivColor0;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case "_FFXIV_COLOR_1":
|
||||||
|
value = FfxivColor1;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
value = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetCustomAttribute(string attributeName, object value)
|
||||||
|
{
|
||||||
|
switch (attributeName)
|
||||||
|
{
|
||||||
|
case "_FFXIV_COLOR_0" when value is Vector4 valueVector4:
|
||||||
|
FfxivColor0 = valueVector4;
|
||||||
|
break;
|
||||||
|
case "_FFXIV_COLOR_1" when value is Vector4 valueVector4:
|
||||||
|
FfxivColor1 = valueVector4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector4 GetColor(int index)
|
||||||
|
=> throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
|
|
||||||
|
public void SetColor(int setIndex, Vector4 color)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public void Validate()
|
||||||
|
{
|
||||||
|
var components = new[]
|
||||||
|
{
|
||||||
|
FfxivColor0.X,
|
||||||
|
FfxivColor0.Y,
|
||||||
|
FfxivColor0.Z,
|
||||||
|
FfxivColor0.W,
|
||||||
|
};
|
||||||
|
if (components.Any(component => component is < 0 or > 1))
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(FfxivColor0));
|
||||||
|
components =
|
||||||
|
[
|
||||||
|
FfxivColor1.X,
|
||||||
|
FfxivColor1.Y,
|
||||||
|
FfxivColor1.Z,
|
||||||
|
FfxivColor1.W,
|
||||||
|
];
|
||||||
|
if (components.Any(component => component is < 0 or > 1))
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(FfxivColor1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public struct VertexTexture1ColorFfxiv(Vector2 texCoord0, Vector4 ffxivColor) : IVertexCustom
|
public struct VertexTexture1ColorFfxiv(Vector2 texCoord0, Vector4 ffxivColor) : IVertexCustom
|
||||||
{
|
{
|
||||||
public IEnumerable<KeyValuePair<string, AttributeFormat>> GetEncodingAttributes()
|
public IEnumerable<KeyValuePair<string, AttributeFormat>> GetEncodingAttributes()
|
||||||
|
|
@ -172,6 +269,118 @@ public struct VertexTexture1ColorFfxiv(Vector2 texCoord0, Vector4 ffxivColor) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct VertexTexture1Color2Ffxiv(Vector2 texCoord0, Vector4 ffxivColor0, Vector4 ffxivColor1) : IVertexCustom
|
||||||
|
{
|
||||||
|
public IEnumerable<KeyValuePair<string, AttributeFormat>> GetEncodingAttributes()
|
||||||
|
{
|
||||||
|
yield return new KeyValuePair<string, AttributeFormat>("TEXCOORD_0",
|
||||||
|
new AttributeFormat(DimensionType.VEC2, EncodingType.FLOAT, false));
|
||||||
|
yield return new KeyValuePair<string, AttributeFormat>("_FFXIV_COLOR_0",
|
||||||
|
new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true));
|
||||||
|
yield return new KeyValuePair<string, AttributeFormat>("_FFXIV_COLOR_1",
|
||||||
|
new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 TexCoord0 = texCoord0;
|
||||||
|
|
||||||
|
public Vector4 FfxivColor0 = ffxivColor0;
|
||||||
|
public Vector4 FfxivColor1 = ffxivColor1;
|
||||||
|
|
||||||
|
public int MaxColors
|
||||||
|
=> 0;
|
||||||
|
|
||||||
|
public int MaxTextCoords
|
||||||
|
=> 1;
|
||||||
|
|
||||||
|
private static readonly string[] CustomNames = ["_FFXIV_COLOR_0", "_FFXIV_COLOR_1"];
|
||||||
|
|
||||||
|
public IEnumerable<string> CustomAttributes
|
||||||
|
=> CustomNames;
|
||||||
|
|
||||||
|
public void Add(in VertexMaterialDelta delta)
|
||||||
|
{
|
||||||
|
TexCoord0 += delta.TexCoord0Delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VertexMaterialDelta Subtract(IVertexMaterial baseValue)
|
||||||
|
=> new(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_0":
|
||||||
|
value = FfxivColor0;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case "_FFXIV_COLOR_1":
|
||||||
|
value = FfxivColor1;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
value = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetCustomAttribute(string attributeName, object value)
|
||||||
|
{
|
||||||
|
switch (attributeName)
|
||||||
|
{
|
||||||
|
case "_FFXIV_COLOR_0" when value is Vector4 valueVector4:
|
||||||
|
FfxivColor0 = valueVector4;
|
||||||
|
break;
|
||||||
|
case "_FFXIV_COLOR_1" when value is Vector4 valueVector4:
|
||||||
|
FfxivColor1 = valueVector4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector4 GetColor(int index)
|
||||||
|
=> throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
|
|
||||||
|
public void SetColor(int setIndex, Vector4 color)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public void Validate()
|
||||||
|
{
|
||||||
|
var components = new[]
|
||||||
|
{
|
||||||
|
FfxivColor0.X,
|
||||||
|
FfxivColor0.Y,
|
||||||
|
FfxivColor0.Z,
|
||||||
|
FfxivColor0.W,
|
||||||
|
};
|
||||||
|
if (components.Any(component => component is < 0 or > 1))
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(FfxivColor0));
|
||||||
|
components =
|
||||||
|
[
|
||||||
|
FfxivColor1.X,
|
||||||
|
FfxivColor1.Y,
|
||||||
|
FfxivColor1.Z,
|
||||||
|
FfxivColor1.W,
|
||||||
|
];
|
||||||
|
if (components.Any(component => component is < 0 or > 1))
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(FfxivColor1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public struct VertexTexture2ColorFfxiv(Vector2 texCoord0, Vector2 texCoord1, Vector4 ffxivColor) : IVertexCustom
|
public struct VertexTexture2ColorFfxiv(Vector2 texCoord0, Vector2 texCoord1, Vector4 ffxivColor) : IVertexCustom
|
||||||
{
|
{
|
||||||
public IEnumerable<KeyValuePair<string, AttributeFormat>> GetEncodingAttributes()
|
public IEnumerable<KeyValuePair<string, AttributeFormat>> GetEncodingAttributes()
|
||||||
|
|
@ -266,6 +475,124 @@ public struct VertexTexture2ColorFfxiv(Vector2 texCoord0, Vector2 texCoord1, Vec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct VertexTexture2Color2Ffxiv(Vector2 texCoord0, Vector2 texCoord1, Vector4 ffxivColor0, Vector4 ffxivColor1) : IVertexCustom
|
||||||
|
{
|
||||||
|
public IEnumerable<KeyValuePair<string, AttributeFormat>> GetEncodingAttributes()
|
||||||
|
{
|
||||||
|
yield return new KeyValuePair<string, AttributeFormat>("TEXCOORD_0",
|
||||||
|
new AttributeFormat(DimensionType.VEC2, EncodingType.FLOAT, false));
|
||||||
|
yield return new KeyValuePair<string, AttributeFormat>("TEXCOORD_1",
|
||||||
|
new AttributeFormat(DimensionType.VEC2, EncodingType.FLOAT, false));
|
||||||
|
yield return new KeyValuePair<string, AttributeFormat>("_FFXIV_COLOR_0",
|
||||||
|
new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true));
|
||||||
|
yield return new KeyValuePair<string, AttributeFormat>("_FFXIV_COLOR_1",
|
||||||
|
new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 TexCoord0 = texCoord0;
|
||||||
|
public Vector2 TexCoord1 = texCoord1;
|
||||||
|
public Vector4 FfxivColor0 = ffxivColor0;
|
||||||
|
public Vector4 FfxivColor1 = ffxivColor1;
|
||||||
|
|
||||||
|
public int MaxColors
|
||||||
|
=> 0;
|
||||||
|
|
||||||
|
public int MaxTextCoords
|
||||||
|
=> 2;
|
||||||
|
|
||||||
|
private static readonly string[] CustomNames = ["_FFXIV_COLOR_0", "_FFXIV_COLOR_1"];
|
||||||
|
|
||||||
|
public IEnumerable<string> CustomAttributes
|
||||||
|
=> CustomNames;
|
||||||
|
|
||||||
|
public void Add(in VertexMaterialDelta delta)
|
||||||
|
{
|
||||||
|
TexCoord0 += delta.TexCoord0Delta;
|
||||||
|
TexCoord1 += delta.TexCoord1Delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VertexMaterialDelta Subtract(IVertexMaterial baseValue)
|
||||||
|
=> new(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_0":
|
||||||
|
value = FfxivColor0;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case "_FFXIV_COLOR_1":
|
||||||
|
value = FfxivColor1;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
value = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetCustomAttribute(string attributeName, object value)
|
||||||
|
{
|
||||||
|
switch (attributeName)
|
||||||
|
{
|
||||||
|
case "_FFXIV_COLOR_0" when value is Vector4 valueVector4:
|
||||||
|
FfxivColor0 = valueVector4;
|
||||||
|
break;
|
||||||
|
case "_FFXIV_COLOR_1" when value is Vector4 valueVector4:
|
||||||
|
FfxivColor1 = valueVector4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector4 GetColor(int index)
|
||||||
|
=> throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
|
|
||||||
|
public void SetColor(int setIndex, Vector4 color)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public void Validate()
|
||||||
|
{
|
||||||
|
var components = new[]
|
||||||
|
{
|
||||||
|
FfxivColor0.X,
|
||||||
|
FfxivColor0.Y,
|
||||||
|
FfxivColor0.Z,
|
||||||
|
FfxivColor0.W,
|
||||||
|
};
|
||||||
|
if (components.Any(component => component is < 0 or > 1))
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(FfxivColor0));
|
||||||
|
components =
|
||||||
|
[
|
||||||
|
FfxivColor1.X,
|
||||||
|
FfxivColor1.Y,
|
||||||
|
FfxivColor1.Z,
|
||||||
|
FfxivColor1.W,
|
||||||
|
];
|
||||||
|
if (components.Any(component => component is < 0 or > 1))
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(FfxivColor1));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public struct VertexTexture3ColorFfxiv(Vector2 texCoord0, Vector2 texCoord1, Vector2 texCoord2, Vector4 ffxivColor)
|
public struct VertexTexture3ColorFfxiv(Vector2 texCoord0, Vector2 texCoord1, Vector2 texCoord2, Vector4 ffxivColor)
|
||||||
: IVertexCustom
|
: IVertexCustom
|
||||||
{
|
{
|
||||||
|
|
@ -367,3 +694,126 @@ public struct VertexTexture3ColorFfxiv(Vector2 texCoord0, Vector2 texCoord1, Vec
|
||||||
throw new ArgumentOutOfRangeException(nameof(FfxivColor));
|
throw new ArgumentOutOfRangeException(nameof(FfxivColor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct VertexTexture3Color2Ffxiv(Vector2 texCoord0, Vector2 texCoord1, Vector2 texCoord2, Vector4 ffxivColor0, Vector4 ffxivColor1)
|
||||||
|
: IVertexCustom
|
||||||
|
{
|
||||||
|
public IEnumerable<KeyValuePair<string, AttributeFormat>> GetEncodingAttributes()
|
||||||
|
{
|
||||||
|
yield return new KeyValuePair<string, AttributeFormat>("TEXCOORD_0",
|
||||||
|
new AttributeFormat(DimensionType.VEC2, EncodingType.FLOAT, false));
|
||||||
|
yield return new KeyValuePair<string, AttributeFormat>("TEXCOORD_1",
|
||||||
|
new AttributeFormat(DimensionType.VEC2, EncodingType.FLOAT, false));
|
||||||
|
yield return new KeyValuePair<string, AttributeFormat>("_FFXIV_COLOR_0",
|
||||||
|
new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true));
|
||||||
|
yield return new KeyValuePair<string, AttributeFormat>("_FFXIV_COLOR_1",
|
||||||
|
new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_SHORT, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 TexCoord0 = texCoord0;
|
||||||
|
public Vector2 TexCoord1 = texCoord1;
|
||||||
|
public Vector2 TexCoord2 = texCoord2;
|
||||||
|
public Vector4 FfxivColor0 = ffxivColor0;
|
||||||
|
public Vector4 FfxivColor1 = ffxivColor1;
|
||||||
|
|
||||||
|
public int MaxColors
|
||||||
|
=> 0;
|
||||||
|
|
||||||
|
public int MaxTextCoords
|
||||||
|
=> 3;
|
||||||
|
|
||||||
|
private static readonly string[] CustomNames = ["_FFXIV_COLOR_0", "_FFXIV_COLOR_1"];
|
||||||
|
|
||||||
|
public IEnumerable<string> CustomAttributes
|
||||||
|
=> CustomNames;
|
||||||
|
|
||||||
|
public void Add(in VertexMaterialDelta delta)
|
||||||
|
{
|
||||||
|
TexCoord0 += delta.TexCoord0Delta;
|
||||||
|
TexCoord1 += delta.TexCoord1Delta;
|
||||||
|
TexCoord2 += delta.TexCoord2Delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VertexMaterialDelta Subtract(IVertexMaterial baseValue)
|
||||||
|
=> new(Vector4.Zero, Vector4.Zero, TexCoord0 - baseValue.GetTexCoord(0), TexCoord1 - baseValue.GetTexCoord(1));
|
||||||
|
|
||||||
|
public Vector2 GetTexCoord(int index)
|
||||||
|
=> index switch
|
||||||
|
{
|
||||||
|
0 => TexCoord0,
|
||||||
|
1 => TexCoord1,
|
||||||
|
2 => TexCoord2,
|
||||||
|
_ => 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)
|
||||||
|
TexCoord2 = coord;
|
||||||
|
if (setIndex >= 3)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(setIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetCustomAttribute(string attributeName, out object? value)
|
||||||
|
{
|
||||||
|
switch (attributeName)
|
||||||
|
{
|
||||||
|
case "_FFXIV_COLOR_0":
|
||||||
|
value = FfxivColor0;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case "_FFXIV_COLOR_1":
|
||||||
|
value = FfxivColor1;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
value = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetCustomAttribute(string attributeName, object value)
|
||||||
|
{
|
||||||
|
switch (attributeName)
|
||||||
|
{
|
||||||
|
case "_FFXIV_COLOR_0" when value is Vector4 valueVector4:
|
||||||
|
FfxivColor0 = valueVector4;
|
||||||
|
break;
|
||||||
|
case "_FFXIV_COLOR_1" when value is Vector4 valueVector4:
|
||||||
|
FfxivColor1 = valueVector4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector4 GetColor(int index)
|
||||||
|
=> throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
|
|
||||||
|
public void SetColor(int setIndex, Vector4 color)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
public void Validate()
|
||||||
|
{
|
||||||
|
var components = new[]
|
||||||
|
{
|
||||||
|
FfxivColor0.X,
|
||||||
|
FfxivColor0.Y,
|
||||||
|
FfxivColor0.Z,
|
||||||
|
FfxivColor0.W,
|
||||||
|
};
|
||||||
|
if (components.Any(component => component is < 0 or > 1))
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(FfxivColor0));
|
||||||
|
components =
|
||||||
|
[
|
||||||
|
FfxivColor1.X,
|
||||||
|
FfxivColor1.Y,
|
||||||
|
FfxivColor1.Z,
|
||||||
|
FfxivColor1.W,
|
||||||
|
];
|
||||||
|
if (components.Any(component => component is < 0 or > 1))
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(FfxivColor1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue