소스 검색

VertexMaterial now generated with a template, expanded VertexMaterial types to support 4 textures.

vpenades 1 년 전
부모
커밋
95fbd6df0a

+ 1835 - 0
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexMaterial.Permutations.cs

@@ -0,0 +1,1835 @@
+// ------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version: 17.0.0.0
+//  
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+// ------------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Numerics;
+using System.Text;
+
+
+using ENCODING = SharpGLTF.Schema2.EncodingType;
+
+
+
+namespace SharpGLTF.Geometry.VertexTypes
+{
+        
+         /// <summary>
+     /// Defines a Vertex attribute with a material Color.
+     /// </summary>
+     #if NET6_0_OR_GREATER
+     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
+     #endif
+     [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+     [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+     public partial struct VertexTexture1 : IVertexMaterial, IEquatable<VertexTexture1>
+     {
+         #region diagnostics
+
+         private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
+         #endregion
+
+         #region constructors
+
+         public VertexTexture1(Vector2 texcoord)
+         {
+             TexCoord = texcoord;
+         }
+         public VertexTexture1(IVertexMaterial src)
+         {
+             Guard.NotNull(src, nameof(src));
+             this.TexCoord = 0 < src.MaxTextCoords ? src.GetTexCoord(0) : Vector2.Zero;
+         }
+         #endregion
+
+         #region data
+
+         [VertexAttribute("TEXCOORD_0")]
+         public Vector2 TexCoord;
+
+         public readonly int MaxColors => 0;
+
+         public readonly int MaxTextCoords => 1;
+
+         public readonly override int GetHashCode()
+         {
+             #if !NETSTANDARD2_0
+             return HashCode.Combine(TexCoord);
+             #else
+             return TexCoord.GetHashCode();
+             #endif
+         }
+
+         public readonly override bool Equals(Object obj) { return obj is VertexTexture1 other ? Equals(other) : false; }
+
+         public readonly bool Equals(VertexTexture1 other) { return AreEqual(this, other); }
+
+         public static bool operator ==(in VertexTexture1 a, in VertexTexture1 b) { return AreEqual(a, b); }
+
+         public static bool operator !=(in VertexTexture1 a, in VertexTexture1 b) { return !AreEqual(a, b); }
+
+         public static bool AreEqual(in VertexTexture1 a, in VertexTexture1 b)
+         {
+             if (a.TexCoord != b.TexCoord) return false;
+             return true;
+         }
+
+         #endregion
+
+         #region API
+
+         public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
+         {
+             return new VertexMaterialDelta((VertexTexture1)baseValue, this);
+         }
+         public void Add(in VertexMaterialDelta delta)
+         {
+             this.TexCoord += delta.TexCoord0Delta;
+         }
+         void IVertexMaterial.SetColor(int index, Vector4 color)
+         {
+         }
+         void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
+         {
+             if (index == 0) this.TexCoord = coord;
+         }
+         public readonly Vector4 GetColor(int index)
+         {
+             switch (index)
+             {
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         public readonly Vector2 GetTexCoord(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.TexCoord;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         #endregion
+
+     }
+
+
+         /// <summary>
+     /// Defines a Vertex attribute with a material Color.
+     /// </summary>
+     #if NET6_0_OR_GREATER
+     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
+     #endif
+     [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+     [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+     public partial struct VertexTexture2 : IVertexMaterial, IEquatable<VertexTexture2>
+     {
+         #region diagnostics
+
+         private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
+         #endregion
+
+         #region constructors
+
+         public VertexTexture2(Vector2 texcoord0, Vector2 texcoord1)
+         {
+             TexCoord0 = texcoord0;
+             TexCoord1 = texcoord1;
+         }
+         public VertexTexture2(IVertexMaterial src)
+         {
+             Guard.NotNull(src, nameof(src));
+             this.TexCoord0 = 0 < src.MaxTextCoords ? src.GetTexCoord(0) : Vector2.Zero;
+             this.TexCoord1 = 1 < src.MaxTextCoords ? src.GetTexCoord(1) : Vector2.Zero;
+         }
+         #endregion
+
+         #region data
+
+         [VertexAttribute("TEXCOORD_0")]
+         public Vector2 TexCoord0;
+
+         [VertexAttribute("TEXCOORD_1")]
+         public Vector2 TexCoord1;
+
+         public readonly int MaxColors => 0;
+
+         public readonly int MaxTextCoords => 2;
+
+         public readonly override int GetHashCode()
+         {
+             #if !NETSTANDARD2_0
+             return HashCode.Combine(TexCoord0, TexCoord1);
+             #else
+             return TexCoord0.GetHashCode()+TexCoord1.GetHashCode();
+             #endif
+         }
+
+         public readonly override bool Equals(Object obj) { return obj is VertexTexture2 other ? Equals(other) : false; }
+
+         public readonly bool Equals(VertexTexture2 other) { return AreEqual(this, other); }
+
+         public static bool operator ==(in VertexTexture2 a, in VertexTexture2 b) { return AreEqual(a, b); }
+
+         public static bool operator !=(in VertexTexture2 a, in VertexTexture2 b) { return !AreEqual(a, b); }
+
+         public static bool AreEqual(in VertexTexture2 a, in VertexTexture2 b)
+         {
+             if (a.TexCoord0 != b.TexCoord0) return false;
+             if (a.TexCoord1 != b.TexCoord1) return false;
+             return true;
+         }
+
+         #endregion
+
+         #region API
+
+         public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
+         {
+             return new VertexMaterialDelta((VertexTexture2)baseValue, this);
+         }
+         public void Add(in VertexMaterialDelta delta)
+         {
+             this.TexCoord0 += delta.TexCoord0Delta;
+             this.TexCoord1 += delta.TexCoord1Delta;
+         }
+         void IVertexMaterial.SetColor(int index, Vector4 color)
+         {
+         }
+         void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
+         {
+             if (index == 0) this.TexCoord0 = coord;
+             if (index == 1) this.TexCoord1 = coord;
+         }
+         public readonly Vector4 GetColor(int index)
+         {
+             switch (index)
+             {
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         public readonly Vector2 GetTexCoord(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.TexCoord0;
+                 case 1: return this.TexCoord1;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         #endregion
+
+     }
+
+
+         /// <summary>
+     /// Defines a Vertex attribute with a material Color.
+     /// </summary>
+     #if NET6_0_OR_GREATER
+     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
+     #endif
+     [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+     [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+     public partial struct VertexTexture3 : IVertexMaterial, IEquatable<VertexTexture3>
+     {
+         #region diagnostics
+
+         private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
+         #endregion
+
+         #region constructors
+
+         public VertexTexture3(Vector2 texcoord0, Vector2 texcoord1, Vector2 texcoord2)
+         {
+             TexCoord0 = texcoord0;
+             TexCoord1 = texcoord1;
+             TexCoord2 = texcoord2;
+         }
+         public VertexTexture3(IVertexMaterial src)
+         {
+             Guard.NotNull(src, nameof(src));
+             this.TexCoord0 = 0 < src.MaxTextCoords ? src.GetTexCoord(0) : Vector2.Zero;
+             this.TexCoord1 = 1 < src.MaxTextCoords ? src.GetTexCoord(1) : Vector2.Zero;
+             this.TexCoord2 = 2 < src.MaxTextCoords ? src.GetTexCoord(2) : Vector2.Zero;
+         }
+         #endregion
+
+         #region data
+
+         [VertexAttribute("TEXCOORD_0")]
+         public Vector2 TexCoord0;
+
+         [VertexAttribute("TEXCOORD_1")]
+         public Vector2 TexCoord1;
+
+         [VertexAttribute("TEXCOORD_2")]
+         public Vector2 TexCoord2;
+
+         public readonly int MaxColors => 0;
+
+         public readonly int MaxTextCoords => 3;
+
+         public readonly override int GetHashCode()
+         {
+             #if !NETSTANDARD2_0
+             return HashCode.Combine(TexCoord0, TexCoord1, TexCoord2);
+             #else
+             return TexCoord0.GetHashCode()+TexCoord1.GetHashCode()+TexCoord2.GetHashCode();
+             #endif
+         }
+
+         public readonly override bool Equals(Object obj) { return obj is VertexTexture3 other ? Equals(other) : false; }
+
+         public readonly bool Equals(VertexTexture3 other) { return AreEqual(this, other); }
+
+         public static bool operator ==(in VertexTexture3 a, in VertexTexture3 b) { return AreEqual(a, b); }
+
+         public static bool operator !=(in VertexTexture3 a, in VertexTexture3 b) { return !AreEqual(a, b); }
+
+         public static bool AreEqual(in VertexTexture3 a, in VertexTexture3 b)
+         {
+             if (a.TexCoord0 != b.TexCoord0) return false;
+             if (a.TexCoord1 != b.TexCoord1) return false;
+             if (a.TexCoord2 != b.TexCoord2) return false;
+             return true;
+         }
+
+         #endregion
+
+         #region API
+
+         public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
+         {
+             return new VertexMaterialDelta((VertexTexture3)baseValue, this);
+         }
+         public void Add(in VertexMaterialDelta delta)
+         {
+             this.TexCoord0 += delta.TexCoord0Delta;
+             this.TexCoord1 += delta.TexCoord1Delta;
+         }
+         void IVertexMaterial.SetColor(int index, Vector4 color)
+         {
+         }
+         void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
+         {
+             if (index == 0) this.TexCoord0 = coord;
+             if (index == 1) this.TexCoord1 = coord;
+             if (index == 2) this.TexCoord2 = coord;
+         }
+         public readonly Vector4 GetColor(int index)
+         {
+             switch (index)
+             {
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         public readonly Vector2 GetTexCoord(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.TexCoord0;
+                 case 1: return this.TexCoord1;
+                 case 2: return this.TexCoord2;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         #endregion
+
+     }
+
+
+         /// <summary>
+     /// Defines a Vertex attribute with a material Color.
+     /// </summary>
+     #if NET6_0_OR_GREATER
+     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
+     #endif
+     [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+     [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+     public partial struct VertexTexture4 : IVertexMaterial, IEquatable<VertexTexture4>
+     {
+         #region diagnostics
+
+         private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
+         #endregion
+
+         #region constructors
+
+         public VertexTexture4(Vector2 texcoord0, Vector2 texcoord1, Vector2 texcoord2, Vector2 texcoord3)
+         {
+             TexCoord0 = texcoord0;
+             TexCoord1 = texcoord1;
+             TexCoord2 = texcoord2;
+             TexCoord3 = texcoord3;
+         }
+         public VertexTexture4(IVertexMaterial src)
+         {
+             Guard.NotNull(src, nameof(src));
+             this.TexCoord0 = 0 < src.MaxTextCoords ? src.GetTexCoord(0) : Vector2.Zero;
+             this.TexCoord1 = 1 < src.MaxTextCoords ? src.GetTexCoord(1) : Vector2.Zero;
+             this.TexCoord2 = 2 < src.MaxTextCoords ? src.GetTexCoord(2) : Vector2.Zero;
+             this.TexCoord3 = 3 < src.MaxTextCoords ? src.GetTexCoord(3) : Vector2.Zero;
+         }
+         #endregion
+
+         #region data
+
+         [VertexAttribute("TEXCOORD_0")]
+         public Vector2 TexCoord0;
+
+         [VertexAttribute("TEXCOORD_1")]
+         public Vector2 TexCoord1;
+
+         [VertexAttribute("TEXCOORD_2")]
+         public Vector2 TexCoord2;
+
+         [VertexAttribute("TEXCOORD_3")]
+         public Vector2 TexCoord3;
+
+         public readonly int MaxColors => 0;
+
+         public readonly int MaxTextCoords => 4;
+
+         public readonly override int GetHashCode()
+         {
+             #if !NETSTANDARD2_0
+             return HashCode.Combine(TexCoord0, TexCoord1, TexCoord2, TexCoord3);
+             #else
+             return TexCoord0.GetHashCode()+TexCoord1.GetHashCode()+TexCoord2.GetHashCode()+TexCoord3.GetHashCode();
+             #endif
+         }
+
+         public readonly override bool Equals(Object obj) { return obj is VertexTexture4 other ? Equals(other) : false; }
+
+         public readonly bool Equals(VertexTexture4 other) { return AreEqual(this, other); }
+
+         public static bool operator ==(in VertexTexture4 a, in VertexTexture4 b) { return AreEqual(a, b); }
+
+         public static bool operator !=(in VertexTexture4 a, in VertexTexture4 b) { return !AreEqual(a, b); }
+
+         public static bool AreEqual(in VertexTexture4 a, in VertexTexture4 b)
+         {
+             if (a.TexCoord0 != b.TexCoord0) return false;
+             if (a.TexCoord1 != b.TexCoord1) return false;
+             if (a.TexCoord2 != b.TexCoord2) return false;
+             if (a.TexCoord3 != b.TexCoord3) return false;
+             return true;
+         }
+
+         #endregion
+
+         #region API
+
+         public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
+         {
+             return new VertexMaterialDelta((VertexTexture4)baseValue, this);
+         }
+         public void Add(in VertexMaterialDelta delta)
+         {
+             this.TexCoord0 += delta.TexCoord0Delta;
+             this.TexCoord1 += delta.TexCoord1Delta;
+         }
+         void IVertexMaterial.SetColor(int index, Vector4 color)
+         {
+         }
+         void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
+         {
+             if (index == 0) this.TexCoord0 = coord;
+             if (index == 1) this.TexCoord1 = coord;
+             if (index == 2) this.TexCoord2 = coord;
+             if (index == 3) this.TexCoord3 = coord;
+         }
+         public readonly Vector4 GetColor(int index)
+         {
+             switch (index)
+             {
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         public readonly Vector2 GetTexCoord(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.TexCoord0;
+                 case 1: return this.TexCoord1;
+                 case 2: return this.TexCoord2;
+                 case 3: return this.TexCoord3;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         #endregion
+
+     }
+
+
+     
+         /// <summary>
+     /// Defines a Vertex attribute with a material Color.
+     /// </summary>
+     #if NET6_0_OR_GREATER
+     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
+     #endif
+     [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+     [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+     public partial struct VertexColor1 : IVertexMaterial, IEquatable<VertexColor1>
+     {
+         #region diagnostics
+
+         private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
+         #endregion
+
+         #region constructors
+
+         public VertexColor1(Vector4 color)
+         {
+             Color = color;
+         }
+         public VertexColor1(IVertexMaterial src)
+         {
+             Guard.NotNull(src, nameof(src));
+             this.Color = 0 < src.MaxColors  ? src.GetColor(0) : Vector4.One;
+         }
+         #endregion
+
+         #region data
+
+         [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color;
+
+         public readonly int MaxColors => 1;
+
+         public readonly int MaxTextCoords => 0;
+
+         public readonly override int GetHashCode()
+         {
+             #if !NETSTANDARD2_0
+             return HashCode.Combine(Color);
+             #else
+             return Color.GetHashCode();
+             #endif
+         }
+
+         public readonly override bool Equals(Object obj) { return obj is VertexColor1 other ? Equals(other) : false; }
+
+         public readonly bool Equals(VertexColor1 other) { return AreEqual(this, other); }
+
+         public static bool operator ==(in VertexColor1 a, in VertexColor1 b) { return AreEqual(a, b); }
+
+         public static bool operator !=(in VertexColor1 a, in VertexColor1 b) { return !AreEqual(a, b); }
+
+         public static bool AreEqual(in VertexColor1 a, in VertexColor1 b)
+         {
+             if (a.Color != b.Color) return false;
+             return true;
+         }
+
+         #endregion
+
+         #region API
+
+         public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
+         {
+             return new VertexMaterialDelta((VertexColor1)baseValue, this);
+         }
+         public void Add(in VertexMaterialDelta delta)
+         {
+             this.Color += delta.Color0Delta;
+         }
+         void IVertexMaterial.SetColor(int index, Vector4 color)
+         {
+             if (index == 0) this.Color = color;
+         }
+         void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
+         {
+         }
+         public readonly Vector4 GetColor(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.Color;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         public readonly Vector2 GetTexCoord(int index)
+         {
+             switch (index)
+             {
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         #endregion
+
+     }
+
+
+         /// <summary>
+     /// Defines a Vertex attribute with a material Color.
+     /// </summary>
+     #if NET6_0_OR_GREATER
+     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
+     #endif
+     [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+     [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+     public partial struct VertexColor1Texture1 : IVertexMaterial, IEquatable<VertexColor1Texture1>
+     {
+         #region diagnostics
+
+         private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
+         #endregion
+
+         #region constructors
+
+         public VertexColor1Texture1(Vector4 color, Vector2 texcoord)
+         {
+             Color = color;
+             TexCoord = texcoord;
+         }
+         public VertexColor1Texture1(IVertexMaterial src)
+         {
+             Guard.NotNull(src, nameof(src));
+             this.Color = 0 < src.MaxColors  ? src.GetColor(0) : Vector4.One;
+             this.TexCoord = 0 < src.MaxTextCoords ? src.GetTexCoord(0) : Vector2.Zero;
+         }
+         #endregion
+
+         #region data
+
+         [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color;
+
+         [VertexAttribute("TEXCOORD_0")]
+         public Vector2 TexCoord;
+
+         public readonly int MaxColors => 1;
+
+         public readonly int MaxTextCoords => 1;
+
+         public readonly override int GetHashCode()
+         {
+             #if !NETSTANDARD2_0
+             return HashCode.Combine(Color, TexCoord);
+             #else
+             return Color.GetHashCode()+TexCoord.GetHashCode();
+             #endif
+         }
+
+         public readonly override bool Equals(Object obj) { return obj is VertexColor1Texture1 other ? Equals(other) : false; }
+
+         public readonly bool Equals(VertexColor1Texture1 other) { return AreEqual(this, other); }
+
+         public static bool operator ==(in VertexColor1Texture1 a, in VertexColor1Texture1 b) { return AreEqual(a, b); }
+
+         public static bool operator !=(in VertexColor1Texture1 a, in VertexColor1Texture1 b) { return !AreEqual(a, b); }
+
+         public static bool AreEqual(in VertexColor1Texture1 a, in VertexColor1Texture1 b)
+         {
+             if (a.Color != b.Color) return false;
+             if (a.TexCoord != b.TexCoord) return false;
+             return true;
+         }
+
+         #endregion
+
+         #region API
+
+         public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
+         {
+             return new VertexMaterialDelta((VertexColor1Texture1)baseValue, this);
+         }
+         public void Add(in VertexMaterialDelta delta)
+         {
+             this.Color += delta.Color0Delta;
+             this.TexCoord += delta.TexCoord0Delta;
+         }
+         void IVertexMaterial.SetColor(int index, Vector4 color)
+         {
+             if (index == 0) this.Color = color;
+         }
+         void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
+         {
+             if (index == 0) this.TexCoord = coord;
+         }
+         public readonly Vector4 GetColor(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.Color;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         public readonly Vector2 GetTexCoord(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.TexCoord;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         #endregion
+
+     }
+
+
+         /// <summary>
+     /// Defines a Vertex attribute with a material Color.
+     /// </summary>
+     #if NET6_0_OR_GREATER
+     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
+     #endif
+     [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+     [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+     public partial struct VertexColor1Texture2 : IVertexMaterial, IEquatable<VertexColor1Texture2>
+     {
+         #region diagnostics
+
+         private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
+         #endregion
+
+         #region constructors
+
+         public VertexColor1Texture2(Vector4 color, Vector2 texcoord0, Vector2 texcoord1)
+         {
+             Color = color;
+             TexCoord0 = texcoord0;
+             TexCoord1 = texcoord1;
+         }
+         public VertexColor1Texture2(IVertexMaterial src)
+         {
+             Guard.NotNull(src, nameof(src));
+             this.Color = 0 < src.MaxColors  ? src.GetColor(0) : Vector4.One;
+             this.TexCoord0 = 0 < src.MaxTextCoords ? src.GetTexCoord(0) : Vector2.Zero;
+             this.TexCoord1 = 1 < src.MaxTextCoords ? src.GetTexCoord(1) : Vector2.Zero;
+         }
+         #endregion
+
+         #region data
+
+         [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color;
+
+         [VertexAttribute("TEXCOORD_0")]
+         public Vector2 TexCoord0;
+
+         [VertexAttribute("TEXCOORD_1")]
+         public Vector2 TexCoord1;
+
+         public readonly int MaxColors => 1;
+
+         public readonly int MaxTextCoords => 2;
+
+         public readonly override int GetHashCode()
+         {
+             #if !NETSTANDARD2_0
+             return HashCode.Combine(Color, TexCoord0, TexCoord1);
+             #else
+             return Color.GetHashCode()+TexCoord0.GetHashCode()+TexCoord1.GetHashCode();
+             #endif
+         }
+
+         public readonly override bool Equals(Object obj) { return obj is VertexColor1Texture2 other ? Equals(other) : false; }
+
+         public readonly bool Equals(VertexColor1Texture2 other) { return AreEqual(this, other); }
+
+         public static bool operator ==(in VertexColor1Texture2 a, in VertexColor1Texture2 b) { return AreEqual(a, b); }
+
+         public static bool operator !=(in VertexColor1Texture2 a, in VertexColor1Texture2 b) { return !AreEqual(a, b); }
+
+         public static bool AreEqual(in VertexColor1Texture2 a, in VertexColor1Texture2 b)
+         {
+             if (a.Color != b.Color) return false;
+             if (a.TexCoord0 != b.TexCoord0) return false;
+             if (a.TexCoord1 != b.TexCoord1) return false;
+             return true;
+         }
+
+         #endregion
+
+         #region API
+
+         public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
+         {
+             return new VertexMaterialDelta((VertexColor1Texture2)baseValue, this);
+         }
+         public void Add(in VertexMaterialDelta delta)
+         {
+             this.Color += delta.Color0Delta;
+             this.TexCoord0 += delta.TexCoord0Delta;
+             this.TexCoord1 += delta.TexCoord1Delta;
+         }
+         void IVertexMaterial.SetColor(int index, Vector4 color)
+         {
+             if (index == 0) this.Color = color;
+         }
+         void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
+         {
+             if (index == 0) this.TexCoord0 = coord;
+             if (index == 1) this.TexCoord1 = coord;
+         }
+         public readonly Vector4 GetColor(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.Color;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         public readonly Vector2 GetTexCoord(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.TexCoord0;
+                 case 1: return this.TexCoord1;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         #endregion
+
+     }
+
+
+         /// <summary>
+     /// Defines a Vertex attribute with a material Color.
+     /// </summary>
+     #if NET6_0_OR_GREATER
+     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
+     #endif
+     [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+     [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+     public partial struct VertexColor1Texture3 : IVertexMaterial, IEquatable<VertexColor1Texture3>
+     {
+         #region diagnostics
+
+         private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
+         #endregion
+
+         #region constructors
+
+         public VertexColor1Texture3(Vector4 color, Vector2 texcoord0, Vector2 texcoord1, Vector2 texcoord2)
+         {
+             Color = color;
+             TexCoord0 = texcoord0;
+             TexCoord1 = texcoord1;
+             TexCoord2 = texcoord2;
+         }
+         public VertexColor1Texture3(IVertexMaterial src)
+         {
+             Guard.NotNull(src, nameof(src));
+             this.Color = 0 < src.MaxColors  ? src.GetColor(0) : Vector4.One;
+             this.TexCoord0 = 0 < src.MaxTextCoords ? src.GetTexCoord(0) : Vector2.Zero;
+             this.TexCoord1 = 1 < src.MaxTextCoords ? src.GetTexCoord(1) : Vector2.Zero;
+             this.TexCoord2 = 2 < src.MaxTextCoords ? src.GetTexCoord(2) : Vector2.Zero;
+         }
+         #endregion
+
+         #region data
+
+         [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color;
+
+         [VertexAttribute("TEXCOORD_0")]
+         public Vector2 TexCoord0;
+
+         [VertexAttribute("TEXCOORD_1")]
+         public Vector2 TexCoord1;
+
+         [VertexAttribute("TEXCOORD_2")]
+         public Vector2 TexCoord2;
+
+         public readonly int MaxColors => 1;
+
+         public readonly int MaxTextCoords => 3;
+
+         public readonly override int GetHashCode()
+         {
+             #if !NETSTANDARD2_0
+             return HashCode.Combine(Color, TexCoord0, TexCoord1, TexCoord2);
+             #else
+             return Color.GetHashCode()+TexCoord0.GetHashCode()+TexCoord1.GetHashCode()+TexCoord2.GetHashCode();
+             #endif
+         }
+
+         public readonly override bool Equals(Object obj) { return obj is VertexColor1Texture3 other ? Equals(other) : false; }
+
+         public readonly bool Equals(VertexColor1Texture3 other) { return AreEqual(this, other); }
+
+         public static bool operator ==(in VertexColor1Texture3 a, in VertexColor1Texture3 b) { return AreEqual(a, b); }
+
+         public static bool operator !=(in VertexColor1Texture3 a, in VertexColor1Texture3 b) { return !AreEqual(a, b); }
+
+         public static bool AreEqual(in VertexColor1Texture3 a, in VertexColor1Texture3 b)
+         {
+             if (a.Color != b.Color) return false;
+             if (a.TexCoord0 != b.TexCoord0) return false;
+             if (a.TexCoord1 != b.TexCoord1) return false;
+             if (a.TexCoord2 != b.TexCoord2) return false;
+             return true;
+         }
+
+         #endregion
+
+         #region API
+
+         public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
+         {
+             return new VertexMaterialDelta((VertexColor1Texture3)baseValue, this);
+         }
+         public void Add(in VertexMaterialDelta delta)
+         {
+             this.Color += delta.Color0Delta;
+             this.TexCoord0 += delta.TexCoord0Delta;
+             this.TexCoord1 += delta.TexCoord1Delta;
+         }
+         void IVertexMaterial.SetColor(int index, Vector4 color)
+         {
+             if (index == 0) this.Color = color;
+         }
+         void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
+         {
+             if (index == 0) this.TexCoord0 = coord;
+             if (index == 1) this.TexCoord1 = coord;
+             if (index == 2) this.TexCoord2 = coord;
+         }
+         public readonly Vector4 GetColor(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.Color;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         public readonly Vector2 GetTexCoord(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.TexCoord0;
+                 case 1: return this.TexCoord1;
+                 case 2: return this.TexCoord2;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         #endregion
+
+     }
+
+
+         /// <summary>
+     /// Defines a Vertex attribute with a material Color.
+     /// </summary>
+     #if NET6_0_OR_GREATER
+     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
+     #endif
+     [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+     [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+     public partial struct VertexColor1Texture4 : IVertexMaterial, IEquatable<VertexColor1Texture4>
+     {
+         #region diagnostics
+
+         private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
+         #endregion
+
+         #region constructors
+
+         public VertexColor1Texture4(Vector4 color, Vector2 texcoord0, Vector2 texcoord1, Vector2 texcoord2, Vector2 texcoord3)
+         {
+             Color = color;
+             TexCoord0 = texcoord0;
+             TexCoord1 = texcoord1;
+             TexCoord2 = texcoord2;
+             TexCoord3 = texcoord3;
+         }
+         public VertexColor1Texture4(IVertexMaterial src)
+         {
+             Guard.NotNull(src, nameof(src));
+             this.Color = 0 < src.MaxColors  ? src.GetColor(0) : Vector4.One;
+             this.TexCoord0 = 0 < src.MaxTextCoords ? src.GetTexCoord(0) : Vector2.Zero;
+             this.TexCoord1 = 1 < src.MaxTextCoords ? src.GetTexCoord(1) : Vector2.Zero;
+             this.TexCoord2 = 2 < src.MaxTextCoords ? src.GetTexCoord(2) : Vector2.Zero;
+             this.TexCoord3 = 3 < src.MaxTextCoords ? src.GetTexCoord(3) : Vector2.Zero;
+         }
+         #endregion
+
+         #region data
+
+         [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color;
+
+         [VertexAttribute("TEXCOORD_0")]
+         public Vector2 TexCoord0;
+
+         [VertexAttribute("TEXCOORD_1")]
+         public Vector2 TexCoord1;
+
+         [VertexAttribute("TEXCOORD_2")]
+         public Vector2 TexCoord2;
+
+         [VertexAttribute("TEXCOORD_3")]
+         public Vector2 TexCoord3;
+
+         public readonly int MaxColors => 1;
+
+         public readonly int MaxTextCoords => 4;
+
+         public readonly override int GetHashCode()
+         {
+             #if !NETSTANDARD2_0
+             return HashCode.Combine(Color, TexCoord0, TexCoord1, TexCoord2, TexCoord3);
+             #else
+             return Color.GetHashCode()+TexCoord0.GetHashCode()+TexCoord1.GetHashCode()+TexCoord2.GetHashCode()+TexCoord3.GetHashCode();
+             #endif
+         }
+
+         public readonly override bool Equals(Object obj) { return obj is VertexColor1Texture4 other ? Equals(other) : false; }
+
+         public readonly bool Equals(VertexColor1Texture4 other) { return AreEqual(this, other); }
+
+         public static bool operator ==(in VertexColor1Texture4 a, in VertexColor1Texture4 b) { return AreEqual(a, b); }
+
+         public static bool operator !=(in VertexColor1Texture4 a, in VertexColor1Texture4 b) { return !AreEqual(a, b); }
+
+         public static bool AreEqual(in VertexColor1Texture4 a, in VertexColor1Texture4 b)
+         {
+             if (a.Color != b.Color) return false;
+             if (a.TexCoord0 != b.TexCoord0) return false;
+             if (a.TexCoord1 != b.TexCoord1) return false;
+             if (a.TexCoord2 != b.TexCoord2) return false;
+             if (a.TexCoord3 != b.TexCoord3) return false;
+             return true;
+         }
+
+         #endregion
+
+         #region API
+
+         public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
+         {
+             return new VertexMaterialDelta((VertexColor1Texture4)baseValue, this);
+         }
+         public void Add(in VertexMaterialDelta delta)
+         {
+             this.Color += delta.Color0Delta;
+             this.TexCoord0 += delta.TexCoord0Delta;
+             this.TexCoord1 += delta.TexCoord1Delta;
+         }
+         void IVertexMaterial.SetColor(int index, Vector4 color)
+         {
+             if (index == 0) this.Color = color;
+         }
+         void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
+         {
+             if (index == 0) this.TexCoord0 = coord;
+             if (index == 1) this.TexCoord1 = coord;
+             if (index == 2) this.TexCoord2 = coord;
+             if (index == 3) this.TexCoord3 = coord;
+         }
+         public readonly Vector4 GetColor(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.Color;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         public readonly Vector2 GetTexCoord(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.TexCoord0;
+                 case 1: return this.TexCoord1;
+                 case 2: return this.TexCoord2;
+                 case 3: return this.TexCoord3;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         #endregion
+
+     }
+
+
+     
+         /// <summary>
+     /// Defines a Vertex attribute with a material Color.
+     /// </summary>
+     #if NET6_0_OR_GREATER
+     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
+     #endif
+     [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+     [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+     public partial struct VertexColor2 : IVertexMaterial, IEquatable<VertexColor2>
+     {
+         #region diagnostics
+
+         private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
+         #endregion
+
+         #region constructors
+
+         public VertexColor2(Vector4 color0, Vector4 color1)
+         {
+             Color0 = color0;
+             Color1 = color1;
+         }
+         public VertexColor2(IVertexMaterial src)
+         {
+             Guard.NotNull(src, nameof(src));
+             this.Color0 = 0 < src.MaxColors  ? src.GetColor(0) : Vector4.One;
+             this.Color1 = 1 < src.MaxColors  ? src.GetColor(1) : Vector4.One;
+         }
+         #endregion
+
+         #region data
+
+         [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color0;
+
+         [VertexAttribute("COLOR_1", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color1;
+
+         public readonly int MaxColors => 2;
+
+         public readonly int MaxTextCoords => 0;
+
+         public readonly override int GetHashCode()
+         {
+             #if !NETSTANDARD2_0
+             return HashCode.Combine(Color0, Color1);
+             #else
+             return Color0.GetHashCode()+Color1.GetHashCode();
+             #endif
+         }
+
+         public readonly override bool Equals(Object obj) { return obj is VertexColor2 other ? Equals(other) : false; }
+
+         public readonly bool Equals(VertexColor2 other) { return AreEqual(this, other); }
+
+         public static bool operator ==(in VertexColor2 a, in VertexColor2 b) { return AreEqual(a, b); }
+
+         public static bool operator !=(in VertexColor2 a, in VertexColor2 b) { return !AreEqual(a, b); }
+
+         public static bool AreEqual(in VertexColor2 a, in VertexColor2 b)
+         {
+             if (a.Color0 != b.Color0) return false;
+             if (a.Color1 != b.Color1) return false;
+             return true;
+         }
+
+         #endregion
+
+         #region API
+
+         public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
+         {
+             return new VertexMaterialDelta((VertexColor2)baseValue, this);
+         }
+         public void Add(in VertexMaterialDelta delta)
+         {
+             this.Color0 += delta.Color0Delta;
+             this.Color1 += delta.Color1Delta;
+         }
+         void IVertexMaterial.SetColor(int index, Vector4 color)
+         {
+             if (index == 0) this.Color0 = color;
+             if (index == 1) this.Color1 = color;
+         }
+         void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
+         {
+         }
+         public readonly Vector4 GetColor(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.Color0;
+                 case 1: return this.Color1;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         public readonly Vector2 GetTexCoord(int index)
+         {
+             switch (index)
+             {
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         #endregion
+
+     }
+
+
+         /// <summary>
+     /// Defines a Vertex attribute with a material Color.
+     /// </summary>
+     #if NET6_0_OR_GREATER
+     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
+     #endif
+     [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+     [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+     public partial struct VertexColor2Texture1 : IVertexMaterial, IEquatable<VertexColor2Texture1>
+     {
+         #region diagnostics
+
+         private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
+         #endregion
+
+         #region constructors
+
+         public VertexColor2Texture1(Vector4 color0, Vector4 color1, Vector2 texcoord)
+         {
+             Color0 = color0;
+             Color1 = color1;
+             TexCoord = texcoord;
+         }
+         public VertexColor2Texture1(IVertexMaterial src)
+         {
+             Guard.NotNull(src, nameof(src));
+             this.Color0 = 0 < src.MaxColors  ? src.GetColor(0) : Vector4.One;
+             this.Color1 = 1 < src.MaxColors  ? src.GetColor(1) : Vector4.One;
+             this.TexCoord = 0 < src.MaxTextCoords ? src.GetTexCoord(0) : Vector2.Zero;
+         }
+         #endregion
+
+         #region data
+
+         [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color0;
+
+         [VertexAttribute("COLOR_1", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color1;
+
+         [VertexAttribute("TEXCOORD_0")]
+         public Vector2 TexCoord;
+
+         public readonly int MaxColors => 2;
+
+         public readonly int MaxTextCoords => 1;
+
+         public readonly override int GetHashCode()
+         {
+             #if !NETSTANDARD2_0
+             return HashCode.Combine(Color0, Color1, TexCoord);
+             #else
+             return Color0.GetHashCode()+Color1.GetHashCode()+TexCoord.GetHashCode();
+             #endif
+         }
+
+         public readonly override bool Equals(Object obj) { return obj is VertexColor2Texture1 other ? Equals(other) : false; }
+
+         public readonly bool Equals(VertexColor2Texture1 other) { return AreEqual(this, other); }
+
+         public static bool operator ==(in VertexColor2Texture1 a, in VertexColor2Texture1 b) { return AreEqual(a, b); }
+
+         public static bool operator !=(in VertexColor2Texture1 a, in VertexColor2Texture1 b) { return !AreEqual(a, b); }
+
+         public static bool AreEqual(in VertexColor2Texture1 a, in VertexColor2Texture1 b)
+         {
+             if (a.Color0 != b.Color0) return false;
+             if (a.Color1 != b.Color1) return false;
+             if (a.TexCoord != b.TexCoord) return false;
+             return true;
+         }
+
+         #endregion
+
+         #region API
+
+         public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
+         {
+             return new VertexMaterialDelta((VertexColor2Texture1)baseValue, this);
+         }
+         public void Add(in VertexMaterialDelta delta)
+         {
+             this.Color0 += delta.Color0Delta;
+             this.Color1 += delta.Color1Delta;
+             this.TexCoord += delta.TexCoord0Delta;
+         }
+         void IVertexMaterial.SetColor(int index, Vector4 color)
+         {
+             if (index == 0) this.Color0 = color;
+             if (index == 1) this.Color1 = color;
+         }
+         void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
+         {
+             if (index == 0) this.TexCoord = coord;
+         }
+         public readonly Vector4 GetColor(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.Color0;
+                 case 1: return this.Color1;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         public readonly Vector2 GetTexCoord(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.TexCoord;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         #endregion
+
+     }
+
+
+         /// <summary>
+     /// Defines a Vertex attribute with a material Color.
+     /// </summary>
+     #if NET6_0_OR_GREATER
+     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
+     #endif
+     [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+     [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+     public partial struct VertexColor2Texture2 : IVertexMaterial, IEquatable<VertexColor2Texture2>
+     {
+         #region diagnostics
+
+         private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
+         #endregion
+
+         #region constructors
+
+         public VertexColor2Texture2(Vector4 color0, Vector4 color1, Vector2 texcoord0, Vector2 texcoord1)
+         {
+             Color0 = color0;
+             Color1 = color1;
+             TexCoord0 = texcoord0;
+             TexCoord1 = texcoord1;
+         }
+         public VertexColor2Texture2(IVertexMaterial src)
+         {
+             Guard.NotNull(src, nameof(src));
+             this.Color0 = 0 < src.MaxColors  ? src.GetColor(0) : Vector4.One;
+             this.Color1 = 1 < src.MaxColors  ? src.GetColor(1) : Vector4.One;
+             this.TexCoord0 = 0 < src.MaxTextCoords ? src.GetTexCoord(0) : Vector2.Zero;
+             this.TexCoord1 = 1 < src.MaxTextCoords ? src.GetTexCoord(1) : Vector2.Zero;
+         }
+         #endregion
+
+         #region data
+
+         [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color0;
+
+         [VertexAttribute("COLOR_1", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color1;
+
+         [VertexAttribute("TEXCOORD_0")]
+         public Vector2 TexCoord0;
+
+         [VertexAttribute("TEXCOORD_1")]
+         public Vector2 TexCoord1;
+
+         public readonly int MaxColors => 2;
+
+         public readonly int MaxTextCoords => 2;
+
+         public readonly override int GetHashCode()
+         {
+             #if !NETSTANDARD2_0
+             return HashCode.Combine(Color0, Color1, TexCoord0, TexCoord1);
+             #else
+             return Color0.GetHashCode()+Color1.GetHashCode()+TexCoord0.GetHashCode()+TexCoord1.GetHashCode();
+             #endif
+         }
+
+         public readonly override bool Equals(Object obj) { return obj is VertexColor2Texture2 other ? Equals(other) : false; }
+
+         public readonly bool Equals(VertexColor2Texture2 other) { return AreEqual(this, other); }
+
+         public static bool operator ==(in VertexColor2Texture2 a, in VertexColor2Texture2 b) { return AreEqual(a, b); }
+
+         public static bool operator !=(in VertexColor2Texture2 a, in VertexColor2Texture2 b) { return !AreEqual(a, b); }
+
+         public static bool AreEqual(in VertexColor2Texture2 a, in VertexColor2Texture2 b)
+         {
+             if (a.Color0 != b.Color0) return false;
+             if (a.Color1 != b.Color1) return false;
+             if (a.TexCoord0 != b.TexCoord0) return false;
+             if (a.TexCoord1 != b.TexCoord1) return false;
+             return true;
+         }
+
+         #endregion
+
+         #region API
+
+         public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
+         {
+             return new VertexMaterialDelta((VertexColor2Texture2)baseValue, this);
+         }
+         public void Add(in VertexMaterialDelta delta)
+         {
+             this.Color0 += delta.Color0Delta;
+             this.Color1 += delta.Color1Delta;
+             this.TexCoord0 += delta.TexCoord0Delta;
+             this.TexCoord1 += delta.TexCoord1Delta;
+         }
+         void IVertexMaterial.SetColor(int index, Vector4 color)
+         {
+             if (index == 0) this.Color0 = color;
+             if (index == 1) this.Color1 = color;
+         }
+         void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
+         {
+             if (index == 0) this.TexCoord0 = coord;
+             if (index == 1) this.TexCoord1 = coord;
+         }
+         public readonly Vector4 GetColor(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.Color0;
+                 case 1: return this.Color1;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         public readonly Vector2 GetTexCoord(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.TexCoord0;
+                 case 1: return this.TexCoord1;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         #endregion
+
+     }
+
+
+         /// <summary>
+     /// Defines a Vertex attribute with a material Color.
+     /// </summary>
+     #if NET6_0_OR_GREATER
+     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
+     #endif
+     [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+     [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+     public partial struct VertexColor2Texture3 : IVertexMaterial, IEquatable<VertexColor2Texture3>
+     {
+         #region diagnostics
+
+         private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
+         #endregion
+
+         #region constructors
+
+         public VertexColor2Texture3(Vector4 color0, Vector4 color1, Vector2 texcoord0, Vector2 texcoord1, Vector2 texcoord2)
+         {
+             Color0 = color0;
+             Color1 = color1;
+             TexCoord0 = texcoord0;
+             TexCoord1 = texcoord1;
+             TexCoord2 = texcoord2;
+         }
+         public VertexColor2Texture3(IVertexMaterial src)
+         {
+             Guard.NotNull(src, nameof(src));
+             this.Color0 = 0 < src.MaxColors  ? src.GetColor(0) : Vector4.One;
+             this.Color1 = 1 < src.MaxColors  ? src.GetColor(1) : Vector4.One;
+             this.TexCoord0 = 0 < src.MaxTextCoords ? src.GetTexCoord(0) : Vector2.Zero;
+             this.TexCoord1 = 1 < src.MaxTextCoords ? src.GetTexCoord(1) : Vector2.Zero;
+             this.TexCoord2 = 2 < src.MaxTextCoords ? src.GetTexCoord(2) : Vector2.Zero;
+         }
+         #endregion
+
+         #region data
+
+         [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color0;
+
+         [VertexAttribute("COLOR_1", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color1;
+
+         [VertexAttribute("TEXCOORD_0")]
+         public Vector2 TexCoord0;
+
+         [VertexAttribute("TEXCOORD_1")]
+         public Vector2 TexCoord1;
+
+         [VertexAttribute("TEXCOORD_2")]
+         public Vector2 TexCoord2;
+
+         public readonly int MaxColors => 2;
+
+         public readonly int MaxTextCoords => 3;
+
+         public readonly override int GetHashCode()
+         {
+             #if !NETSTANDARD2_0
+             return HashCode.Combine(Color0, Color1, TexCoord0, TexCoord1, TexCoord2);
+             #else
+             return Color0.GetHashCode()+Color1.GetHashCode()+TexCoord0.GetHashCode()+TexCoord1.GetHashCode()+TexCoord2.GetHashCode();
+             #endif
+         }
+
+         public readonly override bool Equals(Object obj) { return obj is VertexColor2Texture3 other ? Equals(other) : false; }
+
+         public readonly bool Equals(VertexColor2Texture3 other) { return AreEqual(this, other); }
+
+         public static bool operator ==(in VertexColor2Texture3 a, in VertexColor2Texture3 b) { return AreEqual(a, b); }
+
+         public static bool operator !=(in VertexColor2Texture3 a, in VertexColor2Texture3 b) { return !AreEqual(a, b); }
+
+         public static bool AreEqual(in VertexColor2Texture3 a, in VertexColor2Texture3 b)
+         {
+             if (a.Color0 != b.Color0) return false;
+             if (a.Color1 != b.Color1) return false;
+             if (a.TexCoord0 != b.TexCoord0) return false;
+             if (a.TexCoord1 != b.TexCoord1) return false;
+             if (a.TexCoord2 != b.TexCoord2) return false;
+             return true;
+         }
+
+         #endregion
+
+         #region API
+
+         public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
+         {
+             return new VertexMaterialDelta((VertexColor2Texture3)baseValue, this);
+         }
+         public void Add(in VertexMaterialDelta delta)
+         {
+             this.Color0 += delta.Color0Delta;
+             this.Color1 += delta.Color1Delta;
+             this.TexCoord0 += delta.TexCoord0Delta;
+             this.TexCoord1 += delta.TexCoord1Delta;
+         }
+         void IVertexMaterial.SetColor(int index, Vector4 color)
+         {
+             if (index == 0) this.Color0 = color;
+             if (index == 1) this.Color1 = color;
+         }
+         void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
+         {
+             if (index == 0) this.TexCoord0 = coord;
+             if (index == 1) this.TexCoord1 = coord;
+             if (index == 2) this.TexCoord2 = coord;
+         }
+         public readonly Vector4 GetColor(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.Color0;
+                 case 1: return this.Color1;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         public readonly Vector2 GetTexCoord(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.TexCoord0;
+                 case 1: return this.TexCoord1;
+                 case 2: return this.TexCoord2;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         #endregion
+
+     }
+
+
+         /// <summary>
+     /// Defines a Vertex attribute with a material Color.
+     /// </summary>
+     #if NET6_0_OR_GREATER
+     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
+     #endif
+     [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+     [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+     public partial struct VertexColor2Texture4 : IVertexMaterial, IEquatable<VertexColor2Texture4>
+     {
+         #region diagnostics
+
+         private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
+         #endregion
+
+         #region constructors
+
+         public VertexColor2Texture4(Vector4 color0, Vector4 color1, Vector2 texcoord0, Vector2 texcoord1, Vector2 texcoord2, Vector2 texcoord3)
+         {
+             Color0 = color0;
+             Color1 = color1;
+             TexCoord0 = texcoord0;
+             TexCoord1 = texcoord1;
+             TexCoord2 = texcoord2;
+             TexCoord3 = texcoord3;
+         }
+         public VertexColor2Texture4(IVertexMaterial src)
+         {
+             Guard.NotNull(src, nameof(src));
+             this.Color0 = 0 < src.MaxColors  ? src.GetColor(0) : Vector4.One;
+             this.Color1 = 1 < src.MaxColors  ? src.GetColor(1) : Vector4.One;
+             this.TexCoord0 = 0 < src.MaxTextCoords ? src.GetTexCoord(0) : Vector2.Zero;
+             this.TexCoord1 = 1 < src.MaxTextCoords ? src.GetTexCoord(1) : Vector2.Zero;
+             this.TexCoord2 = 2 < src.MaxTextCoords ? src.GetTexCoord(2) : Vector2.Zero;
+             this.TexCoord3 = 3 < src.MaxTextCoords ? src.GetTexCoord(3) : Vector2.Zero;
+         }
+         #endregion
+
+         #region data
+
+         [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color0;
+
+         [VertexAttribute("COLOR_1", ENCODING.UNSIGNED_BYTE, true)]
+         public Vector4 Color1;
+
+         [VertexAttribute("TEXCOORD_0")]
+         public Vector2 TexCoord0;
+
+         [VertexAttribute("TEXCOORD_1")]
+         public Vector2 TexCoord1;
+
+         [VertexAttribute("TEXCOORD_2")]
+         public Vector2 TexCoord2;
+
+         [VertexAttribute("TEXCOORD_3")]
+         public Vector2 TexCoord3;
+
+         public readonly int MaxColors => 2;
+
+         public readonly int MaxTextCoords => 4;
+
+         public readonly override int GetHashCode()
+         {
+             #if !NETSTANDARD2_0
+             return HashCode.Combine(Color0, Color1, TexCoord0, TexCoord1, TexCoord2, TexCoord3);
+             #else
+             return Color0.GetHashCode()+Color1.GetHashCode()+TexCoord0.GetHashCode()+TexCoord1.GetHashCode()+TexCoord2.GetHashCode()+TexCoord3.GetHashCode();
+             #endif
+         }
+
+         public readonly override bool Equals(Object obj) { return obj is VertexColor2Texture4 other ? Equals(other) : false; }
+
+         public readonly bool Equals(VertexColor2Texture4 other) { return AreEqual(this, other); }
+
+         public static bool operator ==(in VertexColor2Texture4 a, in VertexColor2Texture4 b) { return AreEqual(a, b); }
+
+         public static bool operator !=(in VertexColor2Texture4 a, in VertexColor2Texture4 b) { return !AreEqual(a, b); }
+
+         public static bool AreEqual(in VertexColor2Texture4 a, in VertexColor2Texture4 b)
+         {
+             if (a.Color0 != b.Color0) return false;
+             if (a.Color1 != b.Color1) return false;
+             if (a.TexCoord0 != b.TexCoord0) return false;
+             if (a.TexCoord1 != b.TexCoord1) return false;
+             if (a.TexCoord2 != b.TexCoord2) return false;
+             if (a.TexCoord3 != b.TexCoord3) return false;
+             return true;
+         }
+
+         #endregion
+
+         #region API
+
+         public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
+         {
+             return new VertexMaterialDelta((VertexColor2Texture4)baseValue, this);
+         }
+         public void Add(in VertexMaterialDelta delta)
+         {
+             this.Color0 += delta.Color0Delta;
+             this.Color1 += delta.Color1Delta;
+             this.TexCoord0 += delta.TexCoord0Delta;
+             this.TexCoord1 += delta.TexCoord1Delta;
+         }
+         void IVertexMaterial.SetColor(int index, Vector4 color)
+         {
+             if (index == 0) this.Color0 = color;
+             if (index == 1) this.Color1 = color;
+         }
+         void IVertexMaterial.SetTexCoord(int index, Vector2 coord)
+         {
+             if (index == 0) this.TexCoord0 = coord;
+             if (index == 1) this.TexCoord1 = coord;
+             if (index == 2) this.TexCoord2 = coord;
+             if (index == 3) this.TexCoord3 = coord;
+         }
+         public readonly Vector4 GetColor(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.Color0;
+                 case 1: return this.Color1;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         public readonly Vector2 GetTexCoord(int index)
+         {
+             switch (index)
+             {
+                 case 0: return this.TexCoord0;
+                 case 1: return this.TexCoord1;
+                 case 2: return this.TexCoord2;
+                 case 3: return this.TexCoord3;
+                 default: throw new ArgumentOutOfRangeException(nameof(index));
+             }
+         }
+         #endregion
+
+     }
+
+
+     
+         
+    partial struct VertexMaterialDelta
+    {
+
+         
+         internal VertexMaterialDelta(in VertexTexture1 rootVal, in VertexTexture1 morphVal)
+         {
+             MaxColors = 0;
+             MaxTextCoords = 1;
+             Color0Delta = Vector4.Zero;
+             Color1Delta = Vector4.Zero;
+             TexCoord0Delta = morphVal.TexCoord - rootVal.TexCoord;
+             TexCoord1Delta = Vector2.Zero;
+         }
+         internal VertexMaterialDelta(in VertexTexture2 rootVal, in VertexTexture2 morphVal)
+         {
+             MaxColors = 0;
+             MaxTextCoords = 2;
+             Color0Delta = Vector4.Zero;
+             Color1Delta = Vector4.Zero;
+             TexCoord0Delta = morphVal.TexCoord0 - rootVal.TexCoord0;
+             TexCoord1Delta = morphVal.TexCoord1 - rootVal.TexCoord1;
+         }
+         internal VertexMaterialDelta(in VertexTexture3 rootVal, in VertexTexture3 morphVal)
+         {
+             MaxColors = 0;
+             MaxTextCoords = 2;
+             Color0Delta = Vector4.Zero;
+             Color1Delta = Vector4.Zero;
+             TexCoord0Delta = morphVal.TexCoord0 - rootVal.TexCoord0;
+             TexCoord1Delta = morphVal.TexCoord1 - rootVal.TexCoord1;
+         }
+         internal VertexMaterialDelta(in VertexTexture4 rootVal, in VertexTexture4 morphVal)
+         {
+             MaxColors = 0;
+             MaxTextCoords = 2;
+             Color0Delta = Vector4.Zero;
+             Color1Delta = Vector4.Zero;
+             TexCoord0Delta = morphVal.TexCoord0 - rootVal.TexCoord0;
+             TexCoord1Delta = morphVal.TexCoord1 - rootVal.TexCoord1;
+         }
+         
+         internal VertexMaterialDelta(in VertexColor1 rootVal, in VertexColor1 morphVal)
+         {
+             MaxColors = 1;
+             MaxTextCoords = 0;
+             Color0Delta = morphVal.Color - rootVal.Color;
+             Color1Delta = Vector4.Zero;
+             TexCoord0Delta = Vector2.Zero;
+             TexCoord1Delta = Vector2.Zero;
+         }
+         internal VertexMaterialDelta(in VertexColor1Texture1 rootVal, in VertexColor1Texture1 morphVal)
+         {
+             MaxColors = 1;
+             MaxTextCoords = 1;
+             Color0Delta = morphVal.Color - rootVal.Color;
+             Color1Delta = Vector4.Zero;
+             TexCoord0Delta = morphVal.TexCoord - rootVal.TexCoord;
+             TexCoord1Delta = Vector2.Zero;
+         }
+         internal VertexMaterialDelta(in VertexColor1Texture2 rootVal, in VertexColor1Texture2 morphVal)
+         {
+             MaxColors = 1;
+             MaxTextCoords = 2;
+             Color0Delta = morphVal.Color - rootVal.Color;
+             Color1Delta = Vector4.Zero;
+             TexCoord0Delta = morphVal.TexCoord0 - rootVal.TexCoord0;
+             TexCoord1Delta = morphVal.TexCoord1 - rootVal.TexCoord1;
+         }
+         internal VertexMaterialDelta(in VertexColor1Texture3 rootVal, in VertexColor1Texture3 morphVal)
+         {
+             MaxColors = 1;
+             MaxTextCoords = 2;
+             Color0Delta = morphVal.Color - rootVal.Color;
+             Color1Delta = Vector4.Zero;
+             TexCoord0Delta = morphVal.TexCoord0 - rootVal.TexCoord0;
+             TexCoord1Delta = morphVal.TexCoord1 - rootVal.TexCoord1;
+         }
+         internal VertexMaterialDelta(in VertexColor1Texture4 rootVal, in VertexColor1Texture4 morphVal)
+         {
+             MaxColors = 1;
+             MaxTextCoords = 2;
+             Color0Delta = morphVal.Color - rootVal.Color;
+             Color1Delta = Vector4.Zero;
+             TexCoord0Delta = morphVal.TexCoord0 - rootVal.TexCoord0;
+             TexCoord1Delta = morphVal.TexCoord1 - rootVal.TexCoord1;
+         }
+         
+         internal VertexMaterialDelta(in VertexColor2 rootVal, in VertexColor2 morphVal)
+         {
+             MaxColors = 2;
+             MaxTextCoords = 0;
+             Color0Delta = morphVal.Color0 - rootVal.Color0;
+             Color1Delta = morphVal.Color1 - rootVal.Color1;
+             TexCoord0Delta = Vector2.Zero;
+             TexCoord1Delta = Vector2.Zero;
+         }
+         internal VertexMaterialDelta(in VertexColor2Texture1 rootVal, in VertexColor2Texture1 morphVal)
+         {
+             MaxColors = 2;
+             MaxTextCoords = 1;
+             Color0Delta = morphVal.Color0 - rootVal.Color0;
+             Color1Delta = morphVal.Color1 - rootVal.Color1;
+             TexCoord0Delta = morphVal.TexCoord - rootVal.TexCoord;
+             TexCoord1Delta = Vector2.Zero;
+         }
+         internal VertexMaterialDelta(in VertexColor2Texture2 rootVal, in VertexColor2Texture2 morphVal)
+         {
+             MaxColors = 2;
+             MaxTextCoords = 2;
+             Color0Delta = morphVal.Color0 - rootVal.Color0;
+             Color1Delta = morphVal.Color1 - rootVal.Color1;
+             TexCoord0Delta = morphVal.TexCoord0 - rootVal.TexCoord0;
+             TexCoord1Delta = morphVal.TexCoord1 - rootVal.TexCoord1;
+         }
+         internal VertexMaterialDelta(in VertexColor2Texture3 rootVal, in VertexColor2Texture3 morphVal)
+         {
+             MaxColors = 2;
+             MaxTextCoords = 2;
+             Color0Delta = morphVal.Color0 - rootVal.Color0;
+             Color1Delta = morphVal.Color1 - rootVal.Color1;
+             TexCoord0Delta = morphVal.TexCoord0 - rootVal.TexCoord0;
+             TexCoord1Delta = morphVal.TexCoord1 - rootVal.TexCoord1;
+         }
+         internal VertexMaterialDelta(in VertexColor2Texture4 rootVal, in VertexColor2Texture4 morphVal)
+         {
+             MaxColors = 2;
+             MaxTextCoords = 2;
+             Color0Delta = morphVal.Color0 - rootVal.Color0;
+             Color1Delta = morphVal.Color1 - rootVal.Color1;
+             TexCoord0Delta = morphVal.TexCoord0 - rootVal.TexCoord0;
+             TexCoord1Delta = morphVal.TexCoord1 - rootVal.TexCoord1;
+         }
+         
+
+    }
+
+    
+}

+ 297 - 0
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexMaterial.Permutations.tt

@@ -0,0 +1,297 @@
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ output extension=".cs" #>
+// ------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version: 17.0.0.0
+//  
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+// ------------------------------------------------------------------------------
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Numerics;
+using System.Text;
+
+
+using ENCODING = SharpGLTF.Schema2.EncodingType;
+
+<#
+
+void WriteVertexMaterialPermutation(int colorCount, int textureCount)
+{
+    string vertexTypeName = "Vertex";
+    if (colorCount > 0) vertexTypeName += $"Color{colorCount}";
+    if (textureCount > 0) vertexTypeName += $"Texture{textureCount}";    
+
+    var colorsSet = new List<string>();    
+    if (colorCount == 1) colorsSet.Add("Color");    
+    else if (colorCount > 1) { for(int i=0; i < colorCount; ++i) colorsSet.Add($"Color{i}"); }    
+
+    var texcrdSet = new List<string>();
+    if (textureCount == 1) texcrdSet.Add("TexCoord");
+    else if (textureCount > 1) { for(int i=0; i < textureCount; ++i) texcrdSet.Add($"TexCoord{i}"); }       
+
+    var currentSet = new List<(string Type, string Arg, string Param)>();
+    foreach(var cset in colorsSet) currentSet.Add(("Vector4", cset.ToLower(), $"{cset}"));
+    foreach(var tset in texcrdSet) currentSet.Add(("Vector2", tset.ToLower(), $"{tset}"));
+
+    var attributeArgs = string.Join(", ", currentSet.Select(item => $"{item.Type} {item.Arg}") );    
+    var attributeParams = string.Join(", ", currentSet.Select(item => item.Param));
+
+    
+    
+    WriteLine("/// <summary>");
+    WriteLine("/// Defines a Vertex attribute with a material Color.");
+    WriteLine("/// </summary>");
+    WriteLine("#if NET6_0_OR_GREATER");
+    WriteLine("[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]");
+    WriteLine("#endif");
+    WriteLine("[System.CodeDom.Compiler.GeneratedCodeAttribute(\"Microsoft.VisualStudio.TextTemplating\", \"17.0.0.0\")]");
+    WriteLine("[System.Diagnostics.DebuggerDisplay(\"{_GetDebuggerDisplay(),nq}\")]");
+    WriteLine("[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]");
+
+    WriteLine($"public partial struct {vertexTypeName} : IVertexMaterial, IEquatable<{vertexTypeName}>");   
+    WriteLine("{"); PushIndent("    ");
+
+    // diagnostics
+
+    WriteLine("#region diagnostics"); WriteLine("");
+
+    WriteLine("private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);");
+
+    WriteLine("#endregion"); WriteLine("");
+
+    // constructors
+
+    WriteLine("#region constructors"); WriteLine("");
+
+    WriteLine($"public {vertexTypeName}({attributeArgs})");      
+    WriteLine("{"); PushIndent("    ");
+    foreach(var item in currentSet) { WriteLine($"{item.Param} = {item.Arg};"); }
+    PopIndent(); WriteLine("}");    
+
+    WriteLine($"public {vertexTypeName}(IVertexMaterial src)");   
+    WriteLine("{"); PushIndent("    ");
+    WriteLine("Guard.NotNull(src, nameof(src));");
+    for(int i=0; i < colorCount; ++i)   { WriteLine($"this.{colorsSet[i]} = {i} < src.MaxColors  ? src.GetColor({i}) : Vector4.One;"); }
+    for(int i=0; i < textureCount; ++i) { WriteLine($"this.{texcrdSet[i]} = {i} < src.MaxTextCoords ? src.GetTexCoord({i}) : Vector2.Zero;"); }
+    PopIndent(); WriteLine("}");
+
+    WriteLine("#endregion"); WriteLine("");
+    
+    // data       
+    
+    WriteLine("#region data"); WriteLine("");
+
+    for(int i=0; i < colorCount; ++i)
+    {
+        WriteLine($"[VertexAttribute(\"COLOR_{i}\", ENCODING.UNSIGNED_BYTE, true)]");
+        WriteLine($"public Vector4 {colorsSet[i]};");
+        WriteLine("");
+    }
+
+    for(int i=0; i < textureCount; ++i)
+    {
+        WriteLine($"[VertexAttribute(\"TEXCOORD_{i}\")]");
+        WriteLine($"public Vector2 {texcrdSet[i]};");
+        WriteLine("");
+    }
+
+    WriteLine($"public readonly int MaxColors => {colorCount};");
+    WriteLine("");
+
+    WriteLine($"public readonly int MaxTextCoords => {textureCount};");
+    WriteLine("");
+
+    WriteLine($"public readonly override int GetHashCode()");
+    WriteLine("{"); PushIndent("    ");
+    WriteLine("#if !NETSTANDARD2_0");
+    WriteLine($"return HashCode.Combine({attributeParams});");
+    WriteLine("#else");
+    var hashParams = string.Join("+", currentSet.Select(item => $"{item.Param}.GetHashCode()"));
+    WriteLine($"return {hashParams};");
+    WriteLine("#endif");
+    PopIndent(); WriteLine("}");
+    WriteLine("");
+
+    WriteLine($"public readonly override bool Equals(Object obj) {{ return obj is {vertexTypeName} other ? Equals(other) : false; }}");
+    WriteLine("");
+
+    WriteLine($"public readonly bool Equals({vertexTypeName} other) {{ return AreEqual(this, other); }}");
+    WriteLine("");
+
+    WriteLine($"public static bool operator ==(in {vertexTypeName} a, in {vertexTypeName} b) {{ return AreEqual(a, b); }}");
+    WriteLine("");
+
+    WriteLine($"public static bool operator !=(in {vertexTypeName} a, in {vertexTypeName} b) {{ return !AreEqual(a, b); }}");
+    WriteLine("");
+
+    WriteLine($"public static bool AreEqual(in {vertexTypeName} a, in {vertexTypeName} b)");
+    WriteLine("{"); PushIndent("    ");
+    foreach(var attr in currentSet) { WriteLine($"if (a.{attr.Param} != b.{attr.Param}) return false;"); }    
+    WriteLine("return true;");
+    PopIndent(); WriteLine("}");
+    WriteLine("");
+
+    WriteLine("#endregion"); WriteLine("");
+
+    // API    
+
+    WriteLine("#region API"); WriteLine("");
+
+    WriteLine("public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)");
+    WriteLine("{"); PushIndent("    ");
+    WriteLine($"return new VertexMaterialDelta(({vertexTypeName})baseValue, this);");
+    PopIndent(); WriteLine("}");
+
+    WriteLine("public void Add(in VertexMaterialDelta delta)");
+    WriteLine("{"); PushIndent("    ");    
+
+    foreach(var attr in currentSet)    
+    {
+        var src = $"{attr.Param}Delta";
+        if (src == "ColorDelta") src= "Color0Delta";
+        if (src == "TexCoordDelta") src= "TexCoord0Delta";
+
+        if (src.EndsWith("2Delta")) continue;
+        if (src.EndsWith("3Delta")) continue;
+
+        WriteLine($"this.{attr.Param} += delta.{src};");
+    }    
+    PopIndent(); WriteLine("}");
+
+
+    WriteLine("void IVertexMaterial.SetColor(int index, Vector4 color)");
+    WriteLine("{"); PushIndent("    ");
+    for(int i=0; i < colorCount; ++i) { WriteLine($"if (index == {i}) this.{colorsSet[i]} = color;"); }        
+    PopIndent(); WriteLine("}");
+
+    WriteLine("void IVertexMaterial.SetTexCoord(int index, Vector2 coord)");
+    WriteLine("{"); PushIndent("    ");
+    for(int i=0; i < textureCount; ++i) { WriteLine($"if (index == {i}) this.{texcrdSet[i]} = coord;"); }    
+    PopIndent(); WriteLine("}");
+
+    WriteLine("public readonly Vector4 GetColor(int index)");
+    WriteLine("{"); PushIndent("    ");
+    WriteLine("switch (index)");
+    WriteLine("{"); PushIndent("    ");
+    for(int i=0; i < colorCount; ++i) { WriteLine($"case {i}: return this.{colorsSet[i]};"); }        
+    WriteLine("default: throw new ArgumentOutOfRangeException(nameof(index));");
+    PopIndent(); WriteLine("}");
+    PopIndent(); WriteLine("}");
+
+    WriteLine("public readonly Vector2 GetTexCoord(int index)");
+    WriteLine("{"); PushIndent("    ");
+    WriteLine("switch (index)");
+    WriteLine("{"); PushIndent("    ");
+    for(int i=0; i < textureCount; ++i) { WriteLine($"case {i}: return this.{texcrdSet[i]};"); }    
+    WriteLine("default: throw new ArgumentOutOfRangeException(nameof(index));");
+    PopIndent(); WriteLine("}");
+    PopIndent(); WriteLine("}");
+
+    WriteLine("#endregion"); WriteLine("");
+
+    // closing
+
+    PopIndent(); WriteLine("}");
+
+    WriteLine("");
+    WriteLine("");    
+}
+
+void WriteVertexSubtractPermutation(int colorCount, int textureCount)
+{
+    string vertexTypeName = "Vertex";
+    if (colorCount > 0) vertexTypeName += $"Color{colorCount}";
+    if (textureCount > 0) vertexTypeName += $"Texture{textureCount}";  
+    
+    WriteLine($"internal VertexMaterialDelta(in {vertexTypeName} rootVal, in {vertexTypeName} morphVal)");
+    WriteLine("{"); PushIndent("    ");
+
+    // we don't support all the channels yet
+    colorCount = Math.Min(2,colorCount);
+    textureCount = Math.Min(2,textureCount);
+
+    WriteLine($"MaxColors = {colorCount};");
+    WriteLine($"MaxTextCoords = {textureCount};");
+
+    for(int i=0; i< 2; ++i)
+    {
+        var name = colorCount == 1 ? "Color" : $"Color{i}";
+
+        if (colorCount > i) WriteLine($"Color{i}Delta = morphVal.{name} - rootVal.{name};");
+        else WriteLine($"Color{i}Delta = Vector4.Zero;");    
+    }
+
+    for(int i=0; i< 2; ++i)
+    {
+        var name = textureCount == 1 ? "TexCoord" : $"TexCoord{i}";
+
+        if (textureCount > i) WriteLine($"TexCoord{i}Delta = morphVal.{name} - rootVal.{name};");
+        else WriteLine($"TexCoord{i}Delta = Vector2.Zero;");    
+    }
+
+    PopIndent(); WriteLine("}");
+}
+
+#>
+
+
+namespace SharpGLTF.Geometry.VertexTypes
+{
+    <# PushIndent("     "); #>
+    
+    <# WriteVertexMaterialPermutation(0, 1); #>
+    <# WriteVertexMaterialPermutation(0, 2); #>
+    <# WriteVertexMaterialPermutation(0, 3); #>
+    <# WriteVertexMaterialPermutation(0, 4); #>
+
+    <# WriteVertexMaterialPermutation(1, 0); #>
+    <# WriteVertexMaterialPermutation(1, 1); #>
+    <# WriteVertexMaterialPermutation(1, 2); #>
+    <# WriteVertexMaterialPermutation(1, 3); #>
+    <# WriteVertexMaterialPermutation(1, 4); #>
+
+    <# WriteVertexMaterialPermutation(2, 0); #>
+    <# WriteVertexMaterialPermutation(2, 1); #>
+    <# WriteVertexMaterialPermutation(2, 2); #>
+    <# WriteVertexMaterialPermutation(2, 3); #>
+    <# WriteVertexMaterialPermutation(2, 4); #>
+
+    <# PopIndent(); #>
+
+    partial struct VertexMaterialDelta
+    {
+
+<# PushIndent("         "); #>
+
+<# WriteVertexSubtractPermutation(0, 1); #>
+<# WriteVertexSubtractPermutation(0, 2); #>
+<# WriteVertexSubtractPermutation(0, 3); #>
+<# WriteVertexSubtractPermutation(0, 4); #>
+
+<# WriteVertexSubtractPermutation(1, 0); #>
+<# WriteVertexSubtractPermutation(1, 1); #>
+<# WriteVertexSubtractPermutation(1, 2); #>
+<# WriteVertexSubtractPermutation(1, 3); #>
+<# WriteVertexSubtractPermutation(1, 4); #>
+
+<# WriteVertexSubtractPermutation(2, 0); #>
+<# WriteVertexSubtractPermutation(2, 1); #>
+<# WriteVertexSubtractPermutation(2, 2); #>
+<# WriteVertexSubtractPermutation(2, 3); #>
+<# WriteVertexSubtractPermutation(2, 4); #>
+
+<# ClearIndent(); #>
+
+    }
+
+    
+}

+ 42 - 954
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexMaterial.cs

@@ -83,898 +83,75 @@ namespace SharpGLTF.Geometry.VertexTypes
         void Add(in VertexMaterialDelta delta);
         void Add(in VertexMaterialDelta delta);
     }
     }
 
 
-    /// <summary>
-    /// Defines a Vertex attribute with a material Color.
-    /// </summary>
-    #if NET6_0_OR_GREATER
-    [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
-    #endif
-    [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
-    public struct VertexColor1 : IVertexMaterial, IEquatable<VertexColor1>
-    {
-        #region debug
-
-        private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
-
-        #endregion
-
-        #region constructors
-
-        public VertexColor1(Vector4 color)
-        {
-            Color = color;
-        }
-
-        public VertexColor1(IVertexMaterial src)
-        {
-            Guard.NotNull(src, nameof(src));
-
-            this.Color = src.MaxColors > 0 ? src.GetColor(0) : Vector4.One;
-        }
-
-        public static implicit operator VertexColor1(Vector4 color)
-        {
-            return new VertexColor1(color);
-        }
-
-        #endregion
-
-        #region data
-
-        [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
-        public Vector4 Color;
-
-        /// <inheritdoc/>
-        public readonly int MaxColors => 1;
-
-        /// <inheritdoc/>
-        public readonly int MaxTextCoords => 0;
-
-        /// <inheritdoc/>
-        public readonly override int GetHashCode() { return Color.GetHashCode(); }
-
-        /// <inheritdoc/>
-        public readonly override bool Equals(object obj) { return obj is VertexColor1 other && AreEqual(this, other); }
-
-        /// <inheritdoc/>
-        public readonly bool Equals(VertexColor1 other) { return AreEqual(this, other); }
-        public static bool operator ==(in VertexColor1 a, in VertexColor1 b) { return AreEqual(a, b); }
-        public static bool operator !=(in VertexColor1 a, in VertexColor1 b) { return !AreEqual(a, b); }
-
-        public static bool AreEqual(in VertexColor1 a, in VertexColor1 b)
-        {
-            return a.Color == b.Color;
-        }        
-
-        #endregion
-
-        #region API
-
-        /// <inheritdoc/>
-        public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
-        {
-            return new VertexMaterialDelta((VertexColor1)baseValue, this);
-        }
-
-        /// <inheritdoc/>
-        public void Add(in VertexMaterialDelta delta)
-        {
-            this.Color += delta.Color0Delta;
-        }
-
-        void IVertexMaterial.SetColor(int setIndex, Vector4 color) { if (setIndex == 0) this.Color = color; }
-
-        readonly void IVertexMaterial.SetTexCoord(int setIndex, Vector2 coord) { }
-
-        /// <inheritdoc/>
-        public readonly Vector4 GetColor(int index)
-        {
-            if (index != 0) throw new ArgumentOutOfRangeException(nameof(index));
-            return Color;
-        }
-
-        /// <inheritdoc/>
-        public readonly Vector2 GetTexCoord(int index)
-        {
-            throw new NotSupportedException();
-        }
-
-        #endregion
-    }
-
-    /// <summary>
-    /// Defines a Vertex attribute with a two material Colors.
-    /// </summary>
-    #if NET6_0_OR_GREATER
-    [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
-    #endif
-    [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
-    public struct VertexColor2 : IVertexMaterial, IEquatable<VertexColor2>
-    {
-        #region debug
-
-        private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
-
-        #endregion
-
-        #region constructors
-
-        public VertexColor2(Vector4 color0, Vector4 color1)
-        {
-            Color0 = color0;
-            Color1 = color1;
-        }
-
-        public VertexColor2(IVertexMaterial src)
-        {
-            Guard.NotNull(src, nameof(src));
-
-            this.Color0 = src.MaxColors > 0 ? src.GetColor(0) : Vector4.One;
-            this.Color1 = src.MaxColors > 1 ? src.GetColor(1) : Vector4.One;
-        }
-
-        public static implicit operator VertexColor2((Vector4 Color0, Vector4 Color1) tuple)
-        {
-            return new VertexColor2(tuple.Color0, tuple.Color1);
-        }
-
-        #endregion
-
-        #region data
-
-        [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
-        public Vector4 Color0;
-
-        [VertexAttribute("COLOR_1", ENCODING.UNSIGNED_BYTE, true)]
-        public Vector4 Color1;
-
-        /// <inheritdoc/>
-        public readonly int MaxColors => 2;
-
-        /// <inheritdoc/>
-        public readonly int MaxTextCoords => 0;
-
-        /// <inheritdoc/>
-        public readonly override int GetHashCode() { return Color0.GetHashCode() ^ Color1.GetHashCode(); }
-
-        /// <inheritdoc/>
-        public readonly override bool Equals(object obj) { return obj is VertexColor2 other && AreEqual(this, other); }
-
-        /// <inheritdoc/>
-        public readonly bool Equals(VertexColor2 other) { return AreEqual(this, other); }
-        public static bool operator ==(in VertexColor2 a, in VertexColor2 b) { return AreEqual(a, b); }
-        public static bool operator !=(in VertexColor2 a, in VertexColor2 b) { return !AreEqual(a, b); }
-        public static bool AreEqual(in VertexColor2 a, in VertexColor2 b)
-        {
-            return a.Color0 == b.Color0 && a.Color1 == b.Color1;
-        }        
-
-        #endregion
-
-        #region API
-
-        /// <inheritdoc/>
-        public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
-        {
-            return new VertexMaterialDelta((VertexColor2)baseValue, this);
-        }
-
-        /// <inheritdoc/>
-        public void Add(in VertexMaterialDelta delta)
-        {
-            this.Color0 += delta.Color0Delta;
-            this.Color1 += delta.Color1Delta;
-        }
-
-        void IVertexMaterial.SetColor(int setIndex, Vector4 color)
-        {
-            if (setIndex == 0) this.Color0 = color;
-            if (setIndex == 1) this.Color1 = color;
-        }
-
-        readonly void IVertexMaterial.SetTexCoord(int setIndex, Vector2 coord) { }
-
-        /// <inheritdoc/>
-        public readonly Vector4 GetColor(int index)
-        {
-            if (index == 0) return Color0;
-            if (index == 1) return Color1;
-            throw new ArgumentOutOfRangeException(nameof(index));
-        }
-
-        /// <inheritdoc/>
-        public readonly Vector2 GetTexCoord(int index) { throw new NotSupportedException(); }
-
-        #endregion
-    }
-
-    /// <summary>
-    /// Defines a Vertex attribute with a Texture Coordinate.
-    /// </summary>
-    #if NET6_0_OR_GREATER
-    [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
-    #endif
-    [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
-    public struct VertexTexture1 : IVertexMaterial, IEquatable<VertexTexture1>
-    {
-        #region debug
-
-        private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
-
-        #endregion
-
-        #region constructors
-
-        public VertexTexture1(Vector2 uv)
-        {
-            TexCoord = uv;
-        }
-
-        public VertexTexture1(IVertexMaterial src)
-        {
-            Guard.NotNull(src, nameof(src));
-
-            this.TexCoord = src.MaxTextCoords > 0 ? src.GetTexCoord(0) : Vector2.Zero;
-        }
-
-        public static implicit operator VertexTexture1(Vector2 uv)
-        {
-            return new VertexTexture1(uv);
-        }
-
-        #endregion
-
-        #region data
-
-        [VertexAttribute("TEXCOORD_0")]
-        public Vector2 TexCoord;
-
-        /// <inheritdoc/>
-        public readonly int MaxColors => 0;
-
-        /// <inheritdoc/>
-        public readonly int MaxTextCoords => 1;
-
-        /// <inheritdoc/>
-        public readonly override int GetHashCode() { return TexCoord.GetHashCode(); }
-
-        /// <inheritdoc/>
-        public readonly override bool Equals(object obj) { return obj is VertexTexture1 other && AreEqual(this, other); }
-
-        /// <inheritdoc/>
-        public readonly bool Equals(VertexTexture1 other) { return AreEqual(this, other); }
-        public static bool operator ==(in VertexTexture1 a, in VertexTexture1 b) { return AreEqual(a, b); }
-        public static bool operator !=(in VertexTexture1 a, in VertexTexture1 b) { return !AreEqual(a, b); }
-        public static bool AreEqual(in VertexTexture1 a, in VertexTexture1 b)
-        {
-            return a.TexCoord == b.TexCoord;
-        }        
-
-        #endregion
-
-        #region API
-
-        /// <inheritdoc/>
-        public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
-        {
-            return new VertexMaterialDelta((VertexTexture1)baseValue, this);
-        }
-
-        /// <inheritdoc/>
-        public void Add(in VertexMaterialDelta delta)
-        {
-            this.TexCoord += delta.TexCoord0Delta;
-        }
-
-        readonly void IVertexMaterial.SetColor(int setIndex, Vector4 color) { }
-
-        void IVertexMaterial.SetTexCoord(int setIndex, Vector2 coord) { if (setIndex == 0) this.TexCoord = coord; }
-
-        /// <inheritdoc/>
-        public readonly Vector4 GetColor(int index)
-        {
-            throw new NotSupportedException();
-        }
-
-        /// <inheritdoc/>
-        public readonly Vector2 GetTexCoord(int index)
-        {
-            if (index != 0) throw new ArgumentOutOfRangeException(nameof(index));
-            return TexCoord;
-        }
-
-        #endregion
-    }
-
-    /// <summary>
-    /// Defines a Vertex attribute with two Texture Coordinates.
-    /// </summary>
-    #if NET6_0_OR_GREATER
-    [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
-    #endif
-    [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
-    public struct VertexTexture2 : IVertexMaterial, IEquatable<VertexTexture2>
-    {
-        #region debug
-
-        private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
-
-        #endregion
-
-        #region constructors
-
-        public VertexTexture2(Vector2 uv0, Vector2 uv1)
-        {
-            TexCoord0 = uv0;
-            TexCoord1 = uv1;
-        }
-
-        public VertexTexture2(IVertexMaterial src)
-        {
-            Guard.NotNull(src, nameof(src));
-
-            this.TexCoord0 = src.MaxTextCoords > 0 ? src.GetTexCoord(0) : Vector2.Zero;
-            this.TexCoord1 = src.MaxTextCoords > 1 ? src.GetTexCoord(1) : Vector2.Zero;
-        }
-
-        public static implicit operator VertexTexture2((Vector2 Tex0, Vector2 Tex1) tuple)
-        {
-            return new VertexTexture2(tuple.Tex0, tuple.Tex1);
-        }
-
-        #endregion
-
-        #region data
-
-        [VertexAttribute("TEXCOORD_0")]
-        public Vector2 TexCoord0;
-
-        [VertexAttribute("TEXCOORD_1")]
-        public Vector2 TexCoord1;
-
-        /// <inheritdoc/>
-        public readonly int MaxColors => 0;
-
-        /// <inheritdoc/>
-        public readonly int MaxTextCoords => 2;
-
-        /// <inheritdoc/>
-        public readonly override int GetHashCode() { return TexCoord0.GetHashCode() ^ TexCoord1.GetHashCode(); }
-
-        /// <inheritdoc/>
-        public readonly override bool Equals(object obj) { return obj is VertexTexture2 other && AreEqual(this, other); }
-
-        /// <inheritdoc/>
-        public readonly bool Equals(VertexTexture2 other) { return AreEqual(this, other); }
-        public static bool operator ==(in VertexTexture2 a, in VertexTexture2 b) { return AreEqual(a, b); }
-        public static bool operator !=(in VertexTexture2 a, in VertexTexture2 b) { return !AreEqual(a, b); }
-        public static bool AreEqual(in VertexTexture2 a, in VertexTexture2 b)
-        {
-            return a.TexCoord0 == b.TexCoord0 && a.TexCoord1 == b.TexCoord1;
-        }        
-
-        #endregion
-
-        #region API
-
-        /// <inheritdoc/>
-        public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
-        {
-            return new VertexMaterialDelta((VertexTexture2)baseValue, this);
-        }
-
-        /// <inheritdoc/>
-        public void Add(in VertexMaterialDelta delta)
-        {
-            this.TexCoord0 += delta.TexCoord0Delta;
-            this.TexCoord1 += delta.TexCoord1Delta;
-        }
-
-        readonly void IVertexMaterial.SetColor(int setIndex, Vector4 color) { }
-
-        void IVertexMaterial.SetTexCoord(int setIndex, Vector2 coord)
-        {
-            if (setIndex == 0) this.TexCoord0 = coord;
-            if (setIndex == 1) this.TexCoord1 = coord;
-        }
-
-        /// <inheritdoc/>
-        public readonly Vector4 GetColor(int index)
-        {
-            throw new NotSupportedException();
-        }
-
-        /// <inheritdoc/>
-        public readonly Vector2 GetTexCoord(int index)
-        {
-            if (index == 0) return TexCoord0;
-            if (index == 1) return TexCoord1;
-            throw new ArgumentOutOfRangeException(nameof(index));
-        }
-
-        #endregion
-    }
-
-    /// <summary>
-    /// Defines a Vertex attribute with a Color material and a Texture Coordinate.
-    /// </summary>
-    #if NET6_0_OR_GREATER
-    [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
-    #endif
-    [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
-    public struct VertexColor1Texture1 : IVertexMaterial, IEquatable<VertexColor1Texture1>
-    {
-        #region debug
-
-        private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
-
-        #endregion
-
-        #region constructors
-
-        public VertexColor1Texture1(Vector4 color, Vector2 tex)
-        {
-            Color = color;
-            TexCoord = tex;
-        }
-
-        public VertexColor1Texture1(IVertexMaterial src)
-        {
-            Guard.NotNull(src, nameof(src));
-
-            this.Color = src.MaxColors > 0 ? src.GetColor(0) : Vector4.One;
-            this.TexCoord = src.MaxTextCoords > 0 ? src.GetTexCoord(0) : Vector2.Zero;
-        }
-
-        public static implicit operator VertexColor1Texture1((Vector4 Color, Vector2 Tex) tuple)
-        {
-            return new VertexColor1Texture1(tuple.Color, tuple.Tex);
-        }
-
-        #endregion
-
-        #region data
-
-        [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
-        public Vector4 Color;
-
-        [VertexAttribute("TEXCOORD_0")]
-        public Vector2 TexCoord;
-
-        /// <inheritdoc/>
-        public readonly int MaxColors => 1;
-
-        /// <inheritdoc/>
-        public readonly int MaxTextCoords => 1;
-
-        /// <inheritdoc/>
-        public readonly override int GetHashCode() { return TexCoord.GetHashCode() ^ Color.GetHashCode(); }
-
-        /// <inheritdoc/>
-        public readonly override bool Equals(object obj) { return obj is VertexColor1Texture1 other && AreEqual(this, other); }
-
-        /// <inheritdoc/>
-        public readonly bool Equals(VertexColor1Texture1 other) { return AreEqual(this, other); }
-        public static bool operator ==(in VertexColor1Texture1 a, in VertexColor1Texture1 b) { return AreEqual(a, b); }
-        public static bool operator !=(in VertexColor1Texture1 a, in VertexColor1Texture1 b) { return !AreEqual(a, b); }
-        public static bool AreEqual(in VertexColor1Texture1 a, in VertexColor1Texture1 b)
-        {
-            return a.TexCoord == b.TexCoord && a.Color == b.Color;
-        }        
-
-        #endregion
-
-        #region API
-
-        /// <inheritdoc/>
-        public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
-        {
-            return new VertexMaterialDelta((VertexColor1Texture1)baseValue, this);
-        }
-
-        /// <inheritdoc/>
-        public void Add(in VertexMaterialDelta delta)
-        {
-            this.Color += delta.Color0Delta;
-            this.TexCoord += delta.TexCoord0Delta;
-        }
-
-        void IVertexMaterial.SetColor(int setIndex, Vector4 color) { if (setIndex == 0) this.Color = color; }
-
-        void IVertexMaterial.SetTexCoord(int setIndex, Vector2 coord) { if (setIndex == 0) this.TexCoord = coord; }
-
-        /// <inheritdoc/>
-        public readonly Vector4 GetColor(int index)
-        {
-            if (index != 0) throw new ArgumentOutOfRangeException(nameof(index));
-            return Color;
-        }
-
-        /// <inheritdoc/>
-        public readonly Vector2 GetTexCoord(int index)
-        {
-            if (index != 0) throw new ArgumentOutOfRangeException(nameof(index));
-            return TexCoord;
-        }
-
-        #endregion
-    }
-
-    /// <summary>
-    /// Defines a Vertex attribute with a material Colors and two Texture Coordinates.
-    /// </summary>
-    #if NET6_0_OR_GREATER
-    [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
-    #endif
-    [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
-    public struct VertexColor1Texture2 : IVertexMaterial, IEquatable<VertexColor1Texture2>
-    {
-        #region debug
-
-        private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
-
-        #endregion
-
-        #region constructors
-
-        public VertexColor1Texture2(Vector4 color, Vector2 tex0, Vector2 tex1)
-        {
-            Color = color;
-            TexCoord0 = tex0;
-            TexCoord1 = tex1;
-        }
-
-        public VertexColor1Texture2(IVertexMaterial src)
-        {
-            Guard.NotNull(src, nameof(src));
-
-            this.Color = src.MaxColors > 0 ? src.GetColor(0) : Vector4.One;
-            this.TexCoord0 = src.MaxTextCoords > 0 ? src.GetTexCoord(0) : Vector2.Zero;
-            this.TexCoord1 = src.MaxTextCoords > 1 ? src.GetTexCoord(1) : Vector2.Zero;
-        }
-
-        public static implicit operator VertexColor1Texture2((Vector4 Color, Vector2 Tex0, Vector2 Tex1) tuple)
-        {
-            return new VertexColor1Texture2(tuple.Color, tuple.Tex0, tuple.Tex1);
-        }
-
-        #endregion
-
-        #region data
-
-        [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
-        public Vector4 Color;
-
-        [VertexAttribute("TEXCOORD_0")]
-        public Vector2 TexCoord0;
-
-        [VertexAttribute("TEXCOORD_1")]
-        public Vector2 TexCoord1;
-
-        /// <inheritdoc/>
-        public readonly int MaxColors => 1;
 
 
-        /// <inheritdoc/>
-        public readonly int MaxTextCoords => 2;
-
-        /// <inheritdoc/>
-        public readonly override int GetHashCode() { return Color.GetHashCode() ^ TexCoord0.GetHashCode() ^ TexCoord1.GetHashCode(); }
-
-        /// <inheritdoc/>
-        public readonly override bool Equals(object obj) { return obj is VertexColor1Texture2 other && AreEqual(this, other); }
-
-        /// <inheritdoc/>
-        public readonly bool Equals(VertexColor1Texture2 other) { return AreEqual(this, other); }
-        public static bool operator ==(in VertexColor1Texture2 a, in VertexColor1Texture2 b) { return AreEqual(a, b); }
-        public static bool operator !=(in VertexColor1Texture2 a, in VertexColor1Texture2 b) { return !AreEqual(a, b); }
-        public static bool AreEqual(in VertexColor1Texture2 a, in VertexColor1Texture2 b)
-        {
-            return a.Color == b.Color && a.TexCoord0 == b.TexCoord0 && a.TexCoord1 == b.TexCoord1;
-        }        
-
-        #endregion
-
-        #region API
-
-        /// <inheritdoc/>
-        public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
-        {
-            return new VertexMaterialDelta((VertexColor1Texture2)baseValue, this);
-        }
-
-        /// <inheritdoc/>
-        public void Add(in VertexMaterialDelta delta)
+    public partial struct VertexColor1
+    {
+        public static implicit operator VertexColor1(Vector4 color)
         {
         {
-            this.Color += delta.Color0Delta;
-            this.TexCoord0 += delta.TexCoord0Delta;
-            this.TexCoord1 += delta.TexCoord1Delta;
+            return new VertexColor1(color);
         }
         }
+    }
 
 
-        void IVertexMaterial.SetColor(int setIndex, Vector4 color) { if (setIndex == 0) this.Color = color; }
-
-        void IVertexMaterial.SetTexCoord(int setIndex, Vector2 coord)
+    public partial struct VertexColor2
+    {
+        public static implicit operator VertexColor2((Vector4 Color0, Vector4 Color1) tuple)
         {
         {
-            if (setIndex == 0) this.TexCoord0 = coord;
-            if (setIndex == 1) this.TexCoord1 = coord;
+            return new VertexColor2(tuple.Color0, tuple.Color1);
         }
         }
+    }
 
 
-        /// <inheritdoc/>
-        public readonly Vector4 GetColor(int index)
+    
+    public partial struct VertexTexture1
+    {
+        public static implicit operator VertexTexture1(Vector2 uv)
         {
         {
-            if (index != 0) throw new ArgumentOutOfRangeException(nameof(index));
-            return Color;
+            return new VertexTexture1(uv);
         }
         }
+    }
 
 
-        /// <inheritdoc/>
-        public readonly Vector2 GetTexCoord(int index)
+    
+    public partial struct VertexTexture2
+    {
+        public static implicit operator VertexTexture2((Vector2 Tex0, Vector2 Tex1) tuple)
         {
         {
-            switch (index)
-            {
-                case 0: return this.TexCoord0;
-                case 1: return this.TexCoord1;
-                default: throw new ArgumentOutOfRangeException(nameof(index));
-            }
+            return new VertexTexture2(tuple.Tex0, tuple.Tex1);
         }
         }
-
-        #endregion
     }
     }
 
 
-    /// <summary>
-    /// Defines a Vertex attribute with two material Colors and two Texture Coordinates.
-    /// </summary>
-    #if NET6_0_OR_GREATER
-    [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
-    #endif
-    [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
-    public struct VertexColor2Texture1 : IVertexMaterial, IEquatable<VertexColor2Texture1>
+    
+    public partial struct VertexColor1Texture1
     {
     {
-        #region debug
-
-        private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
-
-        #endregion
-
-        #region constructors
-
-        public VertexColor2Texture1(Vector4 color0, Vector4 color1, Vector2 tex)
+        public static implicit operator VertexColor1Texture1((Vector4 Color, Vector2 Tex) tuple)
         {
         {
-            Color0 = color0;
-            Color1 = color1;
-            TexCoord = tex;
+            return new VertexColor1Texture1(tuple.Color, tuple.Tex);
         }
         }
+    }
 
 
-        public VertexColor2Texture1(IVertexMaterial src)
+    
+    public partial struct VertexColor1Texture2
+    {
+        public static implicit operator VertexColor1Texture2((Vector4 Color, Vector2 Tex0, Vector2 Tex1) tuple)
         {
         {
-            Guard.NotNull(src, nameof(src));
-
-            this.Color0 = src.MaxColors > 0 ? src.GetColor(0) : Vector4.One;
-            this.Color1 = src.MaxColors > 1 ? src.GetColor(1) : Vector4.One;
-            this.TexCoord = src.MaxTextCoords > 0 ? src.GetTexCoord(0) : Vector2.Zero;
+            return new VertexColor1Texture2(tuple.Color, tuple.Tex0, tuple.Tex1);
         }
         }
+    }
 
 
+    
+    public partial struct VertexColor2Texture1
+    {
         public static implicit operator VertexColor2Texture1((Vector4 Color0, Vector4 Color1, Vector2 Tex) tuple)
         public static implicit operator VertexColor2Texture1((Vector4 Color0, Vector4 Color1, Vector2 Tex) tuple)
         {
         {
             return new VertexColor2Texture1(tuple.Color0, tuple.Color1, tuple.Tex);
             return new VertexColor2Texture1(tuple.Color0, tuple.Color1, tuple.Tex);
         }
         }
-
-        #endregion
-
-        #region data
-
-        [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
-        public Vector4 Color0;
-
-        [VertexAttribute("COLOR_1", ENCODING.UNSIGNED_BYTE, true)]
-        public Vector4 Color1;
-
-        [VertexAttribute("TEXCOORD_0")]
-        public Vector2 TexCoord;
-
-        /// <inheritdoc/>
-        public readonly int MaxColors => 2;
-
-        /// <inheritdoc/>
-        public readonly int MaxTextCoords => 1;
-
-        /// <inheritdoc/>
-        public readonly override int GetHashCode() { return Color0.GetHashCode() ^ Color1.GetHashCode() ^ TexCoord.GetHashCode(); }
-
-        /// <inheritdoc/>
-        public readonly override bool Equals(object obj) { return obj is VertexColor2Texture1 other && AreEqual(this, other); }
-
-        /// <inheritdoc/>
-        public readonly bool Equals(VertexColor2Texture1 other) { return AreEqual(this, other); }
-        public static bool operator ==(in VertexColor2Texture1 a, in VertexColor2Texture1 b) { return AreEqual(a, b); }
-        public static bool operator !=(in VertexColor2Texture1 a, in VertexColor2Texture1 b) { return !AreEqual(a, b); }
-        public static bool AreEqual(in VertexColor2Texture1 a, in VertexColor2Texture1 b)
-        {
-            return a.Color0 == b.Color0 && a.Color1 == b.Color1 && a.TexCoord == b.TexCoord;
-        }        
-
-        #endregion
-
-        #region API
-
-        /// <inheritdoc/>
-        public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
-        {
-            return new VertexMaterialDelta((VertexColor2Texture1)baseValue, this);
-        }
-
-        /// <inheritdoc/>
-        public void Add(in VertexMaterialDelta delta)
-        {
-            this.Color0 += delta.Color0Delta;
-            this.Color1 += delta.Color1Delta;
-            this.TexCoord += delta.TexCoord0Delta;
-        }
-
-        void IVertexMaterial.SetColor(int setIndex, Vector4 color)
-        {
-            if (setIndex == 0) this.Color0 = color;
-            if (setIndex == 1) this.Color1 = color;
-        }
-
-        void IVertexMaterial.SetTexCoord(int setIndex, Vector2 coord)
-        {
-            if (setIndex == 0) this.TexCoord = coord;
-        }
-
-        /// <inheritdoc/>
-        public readonly Vector4 GetColor(int index)
-        {
-            switch (index)
-            {
-                case 0: return this.Color0;
-                case 1: return this.Color1;
-                default: throw new ArgumentOutOfRangeException(nameof(index));
-            }
-        }
-
-        /// <inheritdoc/>
-        public readonly Vector2 GetTexCoord(int index)
-        {
-            switch (index)
-            {
-                case 0: return this.TexCoord;
-                default: throw new ArgumentOutOfRangeException(nameof(index));
-            }
-        }
-
-        #endregion
     }
     }
 
 
-    /// <summary>
-    /// Defines a Vertex attribute with two material Colors and two Texture Coordinates.
-    /// </summary>
-    #if NET6_0_OR_GREATER
-    [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
-    #endif
-    [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
-    public struct VertexColor2Texture2 : IVertexMaterial, IEquatable<VertexColor2Texture2>
+    
+    public partial struct VertexColor2Texture2
     {
     {
-        #region debug
-
-        private readonly string _GetDebuggerDisplay() => VertexUtils._GetDebuggerDisplay(this);
-
-        #endregion
-
-        #region constructors
-
-        public VertexColor2Texture2(Vector4 color0, Vector4 color1, Vector2 tex0, Vector2 tex1)
-        {
-            Color0 = color0;
-            Color1 = color1;
-            TexCoord0 = tex0;
-            TexCoord1 = tex1;
-        }
-
-        public VertexColor2Texture2(IVertexMaterial src)
-        {
-            Guard.NotNull(src, nameof(src));
-
-            this.Color0 = src.MaxColors > 0 ? src.GetColor(0) : Vector4.One;
-            this.Color1 = src.MaxColors > 1 ? src.GetColor(1) : Vector4.One;
-            this.TexCoord0 = src.MaxTextCoords > 0 ? src.GetTexCoord(0) : Vector2.Zero;
-            this.TexCoord1 = src.MaxTextCoords > 1 ? src.GetTexCoord(1) : Vector2.Zero;
-        }
-
         public static implicit operator VertexColor2Texture2((Vector4 Color0, Vector4 Color1, Vector2 Tex0, Vector2 Tex1) tuple)
         public static implicit operator VertexColor2Texture2((Vector4 Color0, Vector4 Color1, Vector2 Tex0, Vector2 Tex1) tuple)
         {
         {
             return new VertexColor2Texture2(tuple.Color0, tuple.Color1, tuple.Tex0, tuple.Tex1);
             return new VertexColor2Texture2(tuple.Color0, tuple.Color1, tuple.Tex0, tuple.Tex1);
         }
         }
-
-        #endregion
-
-        #region data
-
-        [VertexAttribute("COLOR_0", ENCODING.UNSIGNED_BYTE, true)]
-        public Vector4 Color0;
-
-        [VertexAttribute("COLOR_1", ENCODING.UNSIGNED_BYTE, true)]
-        public Vector4 Color1;
-
-        [VertexAttribute("TEXCOORD_0")]
-        public Vector2 TexCoord0;
-
-        [VertexAttribute("TEXCOORD_1")]
-        public Vector2 TexCoord1;
-
-        /// <inheritdoc/>
-        public readonly int MaxColors => 2;
-
-        /// <inheritdoc/>
-        public readonly int MaxTextCoords => 2;
-
-        /// <inheritdoc/>
-        public readonly override int GetHashCode() { return Color0.GetHashCode() ^ Color1.GetHashCode() ^ TexCoord0.GetHashCode() ^ TexCoord1.GetHashCode(); }
-
-        /// <inheritdoc/>
-        public readonly override bool Equals(object obj) { return obj is VertexColor2Texture2 other && AreEqual(this, other); }
-
-        /// <inheritdoc/>
-        public readonly bool Equals(VertexColor2Texture2 other) { return AreEqual(this, other); }
-        public static bool operator ==(in VertexColor2Texture2 a, in VertexColor2Texture2 b) { return AreEqual(a, b); }
-        public static bool operator !=(in VertexColor2Texture2 a, in VertexColor2Texture2 b) { return !AreEqual(a, b); }
-        public static bool AreEqual(in VertexColor2Texture2 a, in VertexColor2Texture2 b)
-        {
-            return a.Color0 == b.Color0 && a.Color1 == b.Color1 && a.TexCoord0 == b.TexCoord0 && a.TexCoord1 == b.TexCoord1;
-        }        
-
-        #endregion
-
-        #region API
-
-        /// <inheritdoc/>
-        public readonly VertexMaterialDelta Subtract(IVertexMaterial baseValue)
-        {
-            return new VertexMaterialDelta((VertexColor2Texture2)baseValue, this);
-        }
-
-        /// <inheritdoc/>
-        public void Add(in VertexMaterialDelta delta)
-        {
-            this.Color0 += delta.Color0Delta;
-            this.Color1 += delta.Color1Delta;
-            this.TexCoord0 += delta.TexCoord0Delta;
-            this.TexCoord1 += delta.TexCoord1Delta;
-        }
-
-        void IVertexMaterial.SetColor(int setIndex, Vector4 color)
-        {
-            if (setIndex == 0) this.Color0 = color;
-            if (setIndex == 1) this.Color1 = color;
-        }
-
-        void IVertexMaterial.SetTexCoord(int setIndex, Vector2 coord)
-        {
-            if (setIndex == 0) this.TexCoord0 = coord;
-            if (setIndex == 1) this.TexCoord1 = coord;
-        }
-
-        /// <inheritdoc/>
-        public readonly Vector4 GetColor(int index)
-        {
-            switch (index)
-            {
-                case 0: return this.Color0;
-                case 1: return this.Color1;
-                default: throw new ArgumentOutOfRangeException(nameof(index));
-            }
-        }
-
-        /// <inheritdoc/>
-        public readonly Vector2 GetTexCoord(int index)
-        {
-            switch (index)
-            {
-                case 0: return this.TexCoord0;
-                case 1: return this.TexCoord1;
-                default: throw new ArgumentOutOfRangeException(nameof(index));
-            }
-        }
-
-        #endregion
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -984,7 +161,8 @@ namespace SharpGLTF.Geometry.VertexTypes
     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
     [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields)]
     #endif
     #endif
     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
-    public struct VertexMaterialDelta : IVertexMaterial, IEquatable<VertexMaterialDelta>
+    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
+    public partial struct VertexMaterialDelta : IVertexMaterial, IEquatable<VertexMaterialDelta>
     {
     {
         #region debug
         #region debug
 
 
@@ -1049,101 +227,11 @@ namespace SharpGLTF.Geometry.VertexTypes
             TexCoord0Delta = texCoord0Delta;
             TexCoord0Delta = texCoord0Delta;
             TexCoord1Delta = texCoord1Delta;
             TexCoord1Delta = texCoord1Delta;
         }
         }
-
-        internal VertexMaterialDelta(in VertexColor1 rootVal, in VertexColor1 morphVal)
-        {
-            MaxColors = 1;
-            MaxTextCoords = 0;
-
-            Color0Delta = morphVal.Color - rootVal.Color;
-            Color1Delta = Vector4.Zero;
-            TexCoord0Delta = Vector2.Zero;
-            TexCoord1Delta = Vector2.Zero;
-        }
-
-        internal VertexMaterialDelta(in VertexColor2 rootVal, in VertexColor2 morphVal)
-        {
-            MaxColors = 2;
-            MaxTextCoords = 0;
-
-            Color0Delta = morphVal.Color0 - rootVal.Color0;
-            Color1Delta = morphVal.Color1 - rootVal.Color1;
-            TexCoord0Delta = Vector2.Zero;
-            TexCoord1Delta = Vector2.Zero;
-        }
-
-        internal VertexMaterialDelta(in VertexTexture1 rootVal, in VertexTexture1 morphVal)
-        {
-            MaxColors = 0;
-            MaxTextCoords = 1;
-
-            Color0Delta = Vector4.Zero;
-            Color1Delta = Vector4.Zero;
-            TexCoord0Delta = morphVal.TexCoord - rootVal.TexCoord;
-            TexCoord1Delta = Vector2.Zero;
-        }
-
-        internal VertexMaterialDelta(in VertexTexture2 rootVal, in VertexTexture2 morphVal)
-        {
-            MaxColors = 0;
-            MaxTextCoords = 2;
-
-            Color0Delta = Vector4.Zero;
-            Color1Delta = Vector4.Zero;
-            TexCoord0Delta = morphVal.TexCoord0 - rootVal.TexCoord0;
-            TexCoord1Delta = morphVal.TexCoord1 - rootVal.TexCoord1;
-        }
-
-        internal VertexMaterialDelta(in VertexColor1Texture1 rootVal, in VertexColor1Texture1 morphVal)
-        {
-            MaxColors = 1;
-            MaxTextCoords = 1;
-
-            Color0Delta = morphVal.Color - rootVal.Color;
-            Color1Delta = Vector4.Zero;
-            TexCoord0Delta = morphVal.TexCoord - rootVal.TexCoord;
-            TexCoord1Delta = Vector2.Zero;
-        }
-
-        internal VertexMaterialDelta(in VertexColor2Texture1 rootVal, in VertexColor2Texture1 morphVal)
-        {
-            MaxColors = 2;
-            MaxTextCoords = 1;
-
-            Color0Delta = morphVal.Color0 - rootVal.Color0;
-            Color1Delta = morphVal.Color1 - rootVal.Color1;
-            TexCoord0Delta = morphVal.TexCoord - rootVal.TexCoord;
-            TexCoord1Delta = Vector2.Zero;
-        }
-
-        internal VertexMaterialDelta(in VertexColor1Texture2 rootVal, in VertexColor1Texture2 morphVal)
-        {
-            MaxColors = 1;
-            MaxTextCoords = 2;
-
-            Color0Delta = morphVal.Color - rootVal.Color;
-            Color1Delta = Vector4.Zero;
-            TexCoord0Delta = morphVal.TexCoord0 - rootVal.TexCoord0;
-            TexCoord1Delta = morphVal.TexCoord1 - rootVal.TexCoord1;
-        }
-
-        internal VertexMaterialDelta(in VertexColor2Texture2 rootVal, in VertexColor2Texture2 morphVal)
-        {
-            MaxColors = 2;
-            MaxTextCoords = 2;
-
-            Color0Delta = morphVal.Color0 - rootVal.Color0;
-            Color1Delta = morphVal.Color1 - rootVal.Color1;
-            TexCoord0Delta = morphVal.TexCoord0 - rootVal.TexCoord0;
-            TexCoord1Delta = morphVal.TexCoord1 - rootVal.TexCoord1;
-        }
-
+        
         internal VertexMaterialDelta(in VertexMaterialDelta rootVal, in VertexMaterialDelta morphVal)
         internal VertexMaterialDelta(in VertexMaterialDelta rootVal, in VertexMaterialDelta morphVal)
         {
         {
-            if (rootVal.MaxColors != morphVal.MaxColors)
-                throw new ArgumentException("MaxColors do not match!");
-            if (rootVal.MaxTextCoords != morphVal.MaxTextCoords)
-                throw new ArgumentException("MaxTextCoords do not match!");
+            if (rootVal.MaxColors != morphVal.MaxColors) throw new ArgumentException("MaxColors do not match!");
+            if (rootVal.MaxTextCoords != morphVal.MaxTextCoords) throw new ArgumentException("MaxTextCoords do not match!");
 
 
             MaxColors = rootVal.MaxColors;
             MaxColors = rootVal.MaxColors;
             MaxTextCoords = rootVal.MaxTextCoords;
             MaxTextCoords = rootVal.MaxTextCoords;

+ 72 - 0
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexUtils.Builder.Reflection.cs

@@ -43,6 +43,14 @@ namespace SharpGLTF.Geometry.VertexTypes
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture2,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexTexture2,VertexEmpty>() );
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture2,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexTexture2,VertexEmpty>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture2,VertexEmpty>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture2,VertexEmpty>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexEmpty>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexEmpty>() );
+                        case 3:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture3,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexTexture3,VertexEmpty>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture3,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture3,VertexEmpty>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture3,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture3,VertexEmpty>() );
+                        case 4:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture4,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexTexture4,VertexEmpty>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture4,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture4,VertexEmpty>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture4,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture4,VertexEmpty>() );
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                     }
                     }
                     case 1:
                     case 1:
@@ -60,6 +68,14 @@ namespace SharpGLTF.Geometry.VertexTypes
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture2,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture2,VertexEmpty>() );
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture2,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture2,VertexEmpty>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture2,VertexEmpty>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture2,VertexEmpty>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexEmpty>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexEmpty>() );
+                        case 3:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture3,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture3,VertexEmpty>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture3,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture3,VertexEmpty>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture3,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture3,VertexEmpty>() );
+                        case 4:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture4,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture4,VertexEmpty>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture4,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture4,VertexEmpty>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture4,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture4,VertexEmpty>() );
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                     }
                     }
                     case 2:
                     case 2:
@@ -77,6 +93,14 @@ namespace SharpGLTF.Geometry.VertexTypes
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture2,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture2,VertexEmpty>() );
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture2,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture2,VertexEmpty>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture2,VertexEmpty>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture2,VertexEmpty>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexEmpty>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexEmpty>() );
+                        case 3:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture3,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture3,VertexEmpty>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture3,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture3,VertexEmpty>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture3,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture3,VertexEmpty>() );
+                        case 4:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture4,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture4,VertexEmpty>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture4,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture4,VertexEmpty>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture4,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture4,VertexEmpty>() );
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                     }
                     }
                     default: throw new ArgumentOutOfRangeException(nameof(numCols));
                     default: throw new ArgumentOutOfRangeException(nameof(numCols));
@@ -99,6 +123,14 @@ namespace SharpGLTF.Geometry.VertexTypes
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture2,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexTexture2,VertexJoints4>() );
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture2,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexTexture2,VertexJoints4>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture2,VertexJoints4>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture2,VertexJoints4>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexJoints4>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexJoints4>() );
+                        case 3:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture3,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexTexture3,VertexJoints4>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture3,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture3,VertexJoints4>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture3,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture3,VertexJoints4>() );
+                        case 4:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture4,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexTexture4,VertexJoints4>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture4,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture4,VertexJoints4>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture4,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture4,VertexJoints4>() );
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                     }
                     }
                     case 1:
                     case 1:
@@ -116,6 +148,14 @@ namespace SharpGLTF.Geometry.VertexTypes
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture2,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture2,VertexJoints4>() );
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture2,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture2,VertexJoints4>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture2,VertexJoints4>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture2,VertexJoints4>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexJoints4>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexJoints4>() );
+                        case 3:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture3,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture3,VertexJoints4>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture3,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture3,VertexJoints4>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture3,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture3,VertexJoints4>() );
+                        case 4:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture4,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture4,VertexJoints4>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture4,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture4,VertexJoints4>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture4,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture4,VertexJoints4>() );
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                     }
                     }
                     case 2:
                     case 2:
@@ -133,6 +173,14 @@ namespace SharpGLTF.Geometry.VertexTypes
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture2,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture2,VertexJoints4>() );
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture2,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture2,VertexJoints4>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture2,VertexJoints4>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture2,VertexJoints4>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexJoints4>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexJoints4>() );
+                        case 3:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture3,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture3,VertexJoints4>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture3,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture3,VertexJoints4>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture3,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture3,VertexJoints4>() );
+                        case 4:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture4,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture4,VertexJoints4>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture4,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture4,VertexJoints4>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture4,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture4,VertexJoints4>() );
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                     }
                     }
                     default: throw new ArgumentOutOfRangeException(nameof(numCols));
                     default: throw new ArgumentOutOfRangeException(nameof(numCols));
@@ -155,6 +203,14 @@ namespace SharpGLTF.Geometry.VertexTypes
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture2,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexTexture2,VertexJoints8>() );
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture2,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexTexture2,VertexJoints8>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture2,VertexJoints8>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture2,VertexJoints8>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexJoints8>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexJoints8>() );
+                        case 3:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture3,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexTexture3,VertexJoints8>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture3,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture3,VertexJoints8>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture3,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture3,VertexJoints8>() );
+                        case 4:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture4,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexTexture4,VertexJoints8>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture4,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture4,VertexJoints8>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture4,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture4,VertexJoints8>() );
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                     }
                     }
                     case 1:
                     case 1:
@@ -172,6 +228,14 @@ namespace SharpGLTF.Geometry.VertexTypes
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture2,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture2,VertexJoints8>() );
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture2,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture2,VertexJoints8>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture2,VertexJoints8>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture2,VertexJoints8>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexJoints8>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexJoints8>() );
+                        case 3:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture3,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture3,VertexJoints8>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture3,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture3,VertexJoints8>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture3,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture3,VertexJoints8>() );
+                        case 4:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture4,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture4,VertexJoints8>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture4,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture4,VertexJoints8>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture4,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture4,VertexJoints8>() );
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                     }
                     }
                     case 2:
                     case 2:
@@ -189,6 +253,14 @@ namespace SharpGLTF.Geometry.VertexTypes
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture2,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture2,VertexJoints8>() );
                             if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture2,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture2,VertexJoints8>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture2,VertexJoints8>() );
                             if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture2,VertexJoints8>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexJoints8>() );
                             return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexJoints8>() );
+                        case 3:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture3,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture3,VertexJoints8>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture3,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture3,VertexJoints8>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture3,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture3,VertexJoints8>() );
+                        case 4:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture4,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture4,VertexJoints8>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture4,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture4,VertexJoints8>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture4,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture4,VertexJoints8>() );
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                         default: throw new ArgumentOutOfRangeException(nameof(numUV));
                     }
                     }
                     default: throw new ArgumentOutOfRangeException(nameof(numCols));
                     default: throw new ArgumentOutOfRangeException(nameof(numCols));

+ 1 - 1
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexUtils.Builder.Reflection.tt

@@ -43,7 +43,7 @@ void WriteAllVertexTypePermutations(string baseTemplate)
             WriteLine("switch(numUV)");
             WriteLine("switch(numUV)");
             WriteLine("{"); PushIndent("    ");
             WriteLine("{"); PushIndent("    ");
 
 
-            for(int __tex = 0; __tex <= 2; ++__tex)
+            for(int __tex = 0; __tex <= 4; ++__tex)
             {
             {
                 WriteLine("case " + __tex + ":");
                 WriteLine("case " + __tex + ":");
 
 

+ 15 - 0
src/SharpGLTF.Toolkit/SharpGLTF.Toolkit.csproj

@@ -37,4 +37,19 @@
     </Compile>
     </Compile>
   </ItemGroup>
   </ItemGroup>
 
 
+  <ItemGroup>
+    <None Update="Geometry\VertexTypes\VertexMaterial.Permutations.tt">
+      <Generator>TextTemplatingFileGenerator</Generator>
+      <LastGenOutput>VertexMaterial.Permutations.cs</LastGenOutput>
+    </None>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Compile Update="Geometry\VertexTypes\VertexMaterial.Permutations.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>VertexMaterial.Permutations.tt</DependentUpon>
+    </Compile>
+  </ItemGroup>
+
 </Project>
 </Project>