mirror of
https://github.com/AssetRipper/AssetRipper.git
synced 2025-12-11 20:15:29 +01:00
218 lines
6.2 KiB
C#
218 lines
6.2 KiB
C#
using SharpGLTF.Geometry.VertexTypes;
|
|
using SharpGLTF.Memory;
|
|
using SharpGLTF.Schema2;
|
|
using System.Numerics;
|
|
|
|
namespace AssetRipper.Export.Modules.Models;
|
|
|
|
/// <summary>
|
|
/// Defines a Vertex attribute with up to 1 color and up to 8 textures.
|
|
/// </summary>
|
|
internal struct VertexVariable : IVertexMaterial, IEquatable<VertexVariable>
|
|
{
|
|
#region constructors
|
|
|
|
public VertexVariable(
|
|
int maxColors,
|
|
int maxTextCoords)
|
|
{
|
|
MaxColors = int.Clamp(maxColors, 0, 1);
|
|
MaxTextCoords = int.Clamp(maxTextCoords, 0, 8);
|
|
}
|
|
|
|
public VertexVariable(
|
|
int maxColors,
|
|
int maxTextCoords,
|
|
Vector4 color = default,
|
|
Vector2 texcoord0 = default,
|
|
Vector2 texcoord1 = default,
|
|
Vector2 texcoord2 = default,
|
|
Vector2 texcoord3 = default,
|
|
Vector2 texcoord4 = default,
|
|
Vector2 texcoord5 = default,
|
|
Vector2 texcoord6 = default,
|
|
Vector2 texcoord7 = default)
|
|
{
|
|
Color = color;
|
|
TexCoord0 = texcoord0;
|
|
TexCoord1 = texcoord1;
|
|
TexCoord2 = texcoord2;
|
|
TexCoord3 = texcoord3;
|
|
TexCoord4 = texcoord4;
|
|
TexCoord5 = texcoord5;
|
|
TexCoord6 = texcoord6;
|
|
TexCoord7 = texcoord7;
|
|
MaxColors = int.Clamp(maxColors, 0, 1);
|
|
MaxTextCoords = int.Clamp(maxTextCoords, 0, 8);
|
|
}
|
|
|
|
public VertexVariable(
|
|
int maxTextCoords,
|
|
Vector2 texcoord0 = default,
|
|
Vector2 texcoord1 = default,
|
|
Vector2 texcoord2 = default,
|
|
Vector2 texcoord3 = default,
|
|
Vector2 texcoord4 = default,
|
|
Vector2 texcoord5 = default,
|
|
Vector2 texcoord6 = default,
|
|
Vector2 texcoord7 = default) : this(0, maxTextCoords, default, texcoord0, texcoord1, texcoord2, texcoord3, texcoord4, texcoord5, texcoord6, texcoord7)
|
|
{
|
|
}
|
|
|
|
public VertexVariable(IVertexMaterial src)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(src);
|
|
Color = 0 < src.MaxColors ? src.GetColor(0) : Vector4.One;
|
|
TexCoord0 = 0 < src.MaxTextCoords ? src.GetTexCoord(0) : Vector2.Zero;
|
|
TexCoord1 = 1 < src.MaxTextCoords ? src.GetTexCoord(1) : Vector2.Zero;
|
|
TexCoord2 = 2 < src.MaxTextCoords ? src.GetTexCoord(2) : Vector2.Zero;
|
|
TexCoord3 = 3 < src.MaxTextCoords ? src.GetTexCoord(3) : Vector2.Zero;
|
|
TexCoord4 = 4 < src.MaxTextCoords ? src.GetTexCoord(4) : Vector2.Zero;
|
|
TexCoord5 = 5 < src.MaxTextCoords ? src.GetTexCoord(5) : Vector2.Zero;
|
|
TexCoord6 = 6 < src.MaxTextCoords ? src.GetTexCoord(6) : Vector2.Zero;
|
|
TexCoord7 = 7 < src.MaxTextCoords ? src.GetTexCoord(7) : Vector2.Zero;
|
|
MaxColors = int.Clamp(src.MaxColors, 0, 1);
|
|
MaxTextCoords = int.Clamp(src.MaxTextCoords, 0, 8);
|
|
}
|
|
#endregion
|
|
|
|
#region data
|
|
|
|
public Vector4 Color;
|
|
public Vector2 TexCoord0;
|
|
public Vector2 TexCoord1;
|
|
public Vector2 TexCoord2;
|
|
public Vector2 TexCoord3;
|
|
public Vector2 TexCoord4;
|
|
public Vector2 TexCoord5;
|
|
public Vector2 TexCoord6;
|
|
public Vector2 TexCoord7;
|
|
|
|
public readonly int MaxColors { get; }
|
|
public readonly int MaxTextCoords { get; }
|
|
|
|
readonly IEnumerable<KeyValuePair<string, AttributeFormat>> IVertexReflection.GetEncodingAttributes()
|
|
{
|
|
if (MaxColors == 1)
|
|
{
|
|
yield return new KeyValuePair<string, AttributeFormat>("COLOR_0", new AttributeFormat(DimensionType.VEC4, EncodingType.UNSIGNED_BYTE, true));
|
|
}
|
|
for (int i = 0; i < MaxTextCoords; i++)
|
|
{
|
|
yield return new KeyValuePair<string, AttributeFormat>($"TEXCOORD_{i}", new AttributeFormat(DimensionType.VEC2));
|
|
}
|
|
}
|
|
|
|
public readonly override int GetHashCode()
|
|
{
|
|
HashCode hash = new();
|
|
hash.Add(Color);
|
|
hash.Add(TexCoord0);
|
|
hash.Add(TexCoord1);
|
|
hash.Add(TexCoord2);
|
|
hash.Add(TexCoord3);
|
|
hash.Add(TexCoord4);
|
|
hash.Add(TexCoord5);
|
|
hash.Add(TexCoord6);
|
|
hash.Add(TexCoord7);
|
|
hash.Add(MaxColors);
|
|
hash.Add(MaxTextCoords);
|
|
return hash.ToHashCode();
|
|
}
|
|
|
|
public readonly override bool Equals(object? obj) { return obj is VertexVariable other ? Equals(other) : false; }
|
|
|
|
public readonly bool Equals(VertexVariable other) { return AreEqual(this, other); }
|
|
|
|
public static bool operator ==(in VertexVariable a, in VertexVariable b) { return AreEqual(a, b); }
|
|
|
|
public static bool operator !=(in VertexVariable a, in VertexVariable b) { return !AreEqual(a, b); }
|
|
|
|
public static bool AreEqual(in VertexVariable a, in VertexVariable b)
|
|
{
|
|
return a.Color == b.Color
|
|
&& a.TexCoord0 == b.TexCoord0
|
|
&& a.TexCoord1 == b.TexCoord1
|
|
&& a.TexCoord2 == b.TexCoord2
|
|
&& a.TexCoord3 == b.TexCoord3
|
|
&& a.TexCoord4 == b.TexCoord4
|
|
&& a.TexCoord5 == b.TexCoord5
|
|
&& a.TexCoord6 == b.TexCoord6
|
|
&& a.TexCoord7 == b.TexCoord7
|
|
&& a.MaxColors == b.MaxColors
|
|
&& a.MaxTextCoords == b.MaxTextCoords;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region API
|
|
|
|
public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
|
|
{
|
|
if (MaxTextCoords <= 4)
|
|
{
|
|
return new()
|
|
{
|
|
Color0Delta = baseValue.MaxColors > 0 ? Color - baseValue.GetColor(0) : default,
|
|
TexCoord0Delta = baseValue.MaxTextCoords > 0 ? TexCoord0 - baseValue.GetTexCoord(0) : default,
|
|
TexCoord1Delta = baseValue.MaxTextCoords > 1 ? TexCoord1 - baseValue.GetTexCoord(1) : default,
|
|
TexCoord2Delta = baseValue.MaxTextCoords > 2 ? TexCoord2 - baseValue.GetTexCoord(2) : default,
|
|
TexCoord3Delta = baseValue.MaxTextCoords > 3 ? TexCoord3 - baseValue.GetTexCoord(3) : default,
|
|
};
|
|
}
|
|
else
|
|
{
|
|
throw new NotSupportedException();
|
|
}
|
|
}
|
|
public void Add(in VertexMaterialDelta delta)
|
|
{
|
|
Color += delta.Color0Delta;
|
|
TexCoord0 += delta.TexCoord0Delta;
|
|
TexCoord1 += delta.TexCoord1Delta;
|
|
TexCoord2 += delta.TexCoord2Delta;
|
|
TexCoord3 += delta.TexCoord3Delta;
|
|
}
|
|
void IVertexMaterial.SetColor(int index, Vector4 color)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNotEqual(index, 0);
|
|
Color = color;
|
|
}
|
|
void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
|
|
{
|
|
switch (index)
|
|
{
|
|
case 0: TexCoord0 = coord; break;
|
|
case 1: TexCoord1 = coord; break;
|
|
case 2: TexCoord2 = coord; break;
|
|
case 3: TexCoord3 = coord; break;
|
|
case 4: TexCoord4 = coord; break;
|
|
case 5: TexCoord5 = coord; break;
|
|
case 6: TexCoord6 = coord; break;
|
|
case 7: TexCoord7 = coord; break;
|
|
}
|
|
}
|
|
public readonly Vector4 GetColor(int index)
|
|
{
|
|
ArgumentOutOfRangeException.ThrowIfNotEqual(index, 0);
|
|
return Color;
|
|
}
|
|
public readonly Vector2 GetTexCoord(int index)
|
|
{
|
|
return index switch
|
|
{
|
|
0 => TexCoord0,
|
|
1 => TexCoord1,
|
|
2 => TexCoord2,
|
|
3 => TexCoord3,
|
|
4 => TexCoord4,
|
|
5 => TexCoord5,
|
|
6 => TexCoord6,
|
|
7 => TexCoord7,
|
|
_ => throw new ArgumentOutOfRangeException(nameof(index)),
|
|
};
|
|
}
|
|
#endregion
|
|
|
|
}
|