Browse Source

Made some more methods AOT friendly.

vpenades 1 year ago
parent
commit
e5bb7588f5

+ 8 - 26
src/SharpGLTF.Toolkit/Geometry/MeshBuilderToolkit.cs

@@ -74,7 +74,7 @@ namespace SharpGLTF.Geometry
         void Validate();
         void Validate();
     }
     }
 
 
-    static class MeshBuilderToolkit
+    static partial class MeshBuilderToolkit
     {
     {
         public static VertexBuilder<VertexGeometryDelta, VertexMaterialDelta, VertexEmpty>[] GetMorphTargetVertices(this IPrimitiveMorphTargetReader morphTarget, int vertexCount)
         public static VertexBuilder<VertexGeometryDelta, VertexMaterialDelta, VertexEmpty>[] GetMorphTargetVertices(this IPrimitiveMorphTargetReader morphTarget, int vertexCount)
         {
         {
@@ -115,6 +115,7 @@ namespace SharpGLTF.Geometry
 
 
             return maxIndex < 256 ? Schema2.EncodingType.UNSIGNED_BYTE : Schema2.EncodingType.UNSIGNED_SHORT;
             return maxIndex < 256 ? Schema2.EncodingType.UNSIGNED_BYTE : Schema2.EncodingType.UNSIGNED_SHORT;
         }
         }
+
         
         
         public static IMeshBuilder<TMaterial> CreateMeshBuilderFromVertexAttributes
         public static IMeshBuilder<TMaterial> CreateMeshBuilderFromVertexAttributes
             <
             <
@@ -123,31 +124,12 @@ namespace SharpGLTF.Geometry
             #endif
             #endif
             TMaterial>(params string[] vertexAttributes)
             TMaterial>(params string[] vertexAttributes)
         {
         {
-            Type meshType = GetMeshBuilderType(typeof(TMaterial), vertexAttributes);
-
-            var mesh = Activator.CreateInstance(meshType, string.Empty);
-
-            return mesh as IMeshBuilder<TMaterial>;
-        }
-        
-        #if NET6_0_OR_GREATER
-        [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
-        #endif
-        public static Type GetMeshBuilderType
-            (
-            #if NET6_0_OR_GREATER
-            [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
-            #endif
-            Type materialType, string[] vertexAttributes)
-        {
-            var tvg = VertexUtils.GetVertexGeometryType(vertexAttributes);
-            var tvm = VertexUtils.GetVertexMaterialType(vertexAttributes);
-            var tvs = VertexUtils.GetVertexSkinningType(vertexAttributes);
-
-            var meshType = typeof(MeshBuilder<,,,>);
-
-            return meshType.MakeGenericType(materialType, tvg, tvm, tvs);
-        }
+            return VertexUtils
+                .GetVertexBuilderType(vertexAttributes) // get a vertex factory from attributes
+                .BuilderFactory                         
+                .Invoke()                               // create a single vertex
+                .CreateCompatibleMesh<TMaterial>();     // create a mesh with the given vertex format.
+        }        
 
 
         public static IReadOnlyDictionary<Vector3, Vector3> CalculateSmoothNormals<TMaterial>(this IMeshBuilder<TMaterial> srcMesh)
         public static IReadOnlyDictionary<Vector3, Vector3> CalculateSmoothNormals<TMaterial>(this IMeshBuilder<TMaterial> srcMesh)
         {
         {

+ 2 - 0
src/SharpGLTF.Toolkit/Geometry/PrimitiveBuilder.cs

@@ -111,6 +111,8 @@ namespace SharpGLTF.Geometry
         #endif
         #endif
         public Type VertexType => typeof(VertexBuilder<TvG, TvM, TvS>);
         public Type VertexType => typeof(VertexBuilder<TvG, TvM, TvS>);
 
 
+        public Func<IVertexBuilder> VertexFactory => () => new VertexBuilder<TvG, TvM, TvS>();
+
         /// <summary>
         /// <summary>
         /// Gets the list of vertices used by this primitive.
         /// Gets the list of vertices used by this primitive.
         /// </summary>
         /// </summary>

+ 1 - 0
src/SharpGLTF.Toolkit/Geometry/PrimitiveInterfaces.cs

@@ -79,6 +79,7 @@ namespace SharpGLTF.Geometry
         [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)]
         [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)]
         #endif
         #endif
         Type VertexType { get; }
         Type VertexType { get; }
+        Func<IVertexBuilder> VertexFactory { get; }
 
 
         void SetVertexDelta(int morphTargetIndex, int vertexIndex, VertexGeometryDelta geometryDelta, VertexMaterialDelta materialDelta);
         void SetVertexDelta(int morphTargetIndex, int vertexIndex, VertexGeometryDelta geometryDelta, VertexMaterialDelta materialDelta);
 
 

+ 24 - 15
src/SharpGLTF.Toolkit/Geometry/VertexBufferColumns.cs

@@ -169,10 +169,12 @@ namespace SharpGLTF.Geometry
             this.Positions = _IsolateColumn(this.Positions); // Position, normal and tangent can be modified by morphing and skinning
             this.Positions = _IsolateColumn(this.Positions); // Position, normal and tangent can be modified by morphing and skinning
             this.Normals = _IsolateColumn(this.Normals);
             this.Normals = _IsolateColumn(this.Normals);
             this.Tangents = _IsolateColumn(this.Tangents);
             this.Tangents = _IsolateColumn(this.Tangents);
-            this.Colors0 = _IsolateColumn(this.Colors0);     // colors0,1 and texCoords0,1 can be modified by morphing
+            this.Colors0 = _IsolateColumn(this.Colors0);     // colors0,1 and texCoords 0,1,2,3 can be modified by morphing
             this.Colors1 = _IsolateColumn(this.Colors1);
             this.Colors1 = _IsolateColumn(this.Colors1);
             this.TexCoords0 = _IsolateColumn(this.TexCoords0);
             this.TexCoords0 = _IsolateColumn(this.TexCoords0);
             this.TexCoords1 = _IsolateColumn(this.TexCoords1);
             this.TexCoords1 = _IsolateColumn(this.TexCoords1);
+            this.TexCoords2 = _IsolateColumn(this.TexCoords2);
+            this.TexCoords3 = _IsolateColumn(this.TexCoords3);
 
 
             // prepare animation data, if available
             // prepare animation data, if available
 
 
@@ -185,6 +187,8 @@ namespace SharpGLTF.Geometry
             Vector4[] morphColors1 = null;
             Vector4[] morphColors1 = null;
             Vector2[] morphTexcrd0 = null;
             Vector2[] morphTexcrd0 = null;
             Vector2[] morphTexcrd1 = null;
             Vector2[] morphTexcrd1 = null;
+            Vector2[] morphTexcrd2 = null;
+            Vector2[] morphTexcrd3 = null;
 
 
             if (_MorphTargets != null)
             if (_MorphTargets != null)
             {
             {
@@ -195,6 +199,8 @@ namespace SharpGLTF.Geometry
                 if (_MorphTargets.All(item => item.Colors1 != null)) morphColors1 = new Vector4[this.MorphTargets.Count];
                 if (_MorphTargets.All(item => item.Colors1 != null)) morphColors1 = new Vector4[this.MorphTargets.Count];
                 if (_MorphTargets.All(item => item.TexCoords0 != null)) morphTexcrd0 = new Vector2[this.MorphTargets.Count];
                 if (_MorphTargets.All(item => item.TexCoords0 != null)) morphTexcrd0 = new Vector2[this.MorphTargets.Count];
                 if (_MorphTargets.All(item => item.TexCoords1 != null)) morphTexcrd1 = new Vector2[this.MorphTargets.Count];
                 if (_MorphTargets.All(item => item.TexCoords1 != null)) morphTexcrd1 = new Vector2[this.MorphTargets.Count];
+                if (_MorphTargets.All(item => item.TexCoords2 != null)) morphTexcrd2 = new Vector2[this.MorphTargets.Count];
+                if (_MorphTargets.All(item => item.TexCoords3 != null)) morphTexcrd3 = new Vector2[this.MorphTargets.Count];
             }
             }
 
 
             // loop over every vertex
             // loop over every vertex
@@ -252,6 +258,18 @@ namespace SharpGLTF.Geometry
                         _FillMorphData(morphTexcrd1, vc => vc.TexCoords1[i]);
                         _FillMorphData(morphTexcrd1, vc => vc.TexCoords1[i]);
                         TexCoords1[i] = morphMaterial.MorphTexCoord(TexCoords1[i], morphTexcrd1);
                         TexCoords1[i] = morphMaterial.MorphTexCoord(TexCoords1[i], morphTexcrd1);
                     }
                     }
+
+                    if (this.TexCoords2 != null)
+                    {
+                        _FillMorphData(morphTexcrd2, vc => vc.TexCoords2[i]);
+                        TexCoords1[2] = morphMaterial.MorphTexCoord(TexCoords2[i], morphTexcrd2);
+                    }
+
+                    if (this.TexCoords3 != null)
+                    {
+                        _FillMorphData(morphTexcrd3, vc => vc.TexCoords3[i]);
+                        TexCoords3[2] = morphMaterial.MorphTexCoord(TexCoords3[i], morphTexcrd3);
+                    }
                 }
                 }
             }
             }
 
 
@@ -318,11 +336,8 @@ namespace SharpGLTF.Geometry
         #endregion
         #endregion
 
 
         #region API - Vertex indexing
         #region API - Vertex indexing
-
-        #if NET6_0_OR_GREATER
-        [return: System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)]
-        #endif
-        public Type GetCompatibleVertexType()
+        
+        public (Type BuilderType, Func<IVertexBuilder> BuilderFactory) GetCompatibleVertexType()
         {
         {
             var hasNormals = Normals != null;
             var hasNormals = Normals != null;
             var hasTangents = hasNormals && Tangents != null;
             var hasTangents = hasNormals && Tangents != null;
@@ -394,21 +409,15 @@ namespace SharpGLTF.Geometry
             }
             }
 
 
             return s;
             return s;
-        }
+        }        
 
 
-        public IVertexBuilder GetVertex
-            (
-            #if NET6_0_OR_GREATER
-            [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)]
-            #endif
-            Type vertexType,
-            int index)
+        public IVertexBuilder GetVertex(Func<IVertexBuilder> factory, int index)
         {
         {
             var g = GetVertexGeometry<VertexPositionNormalTangent>(index);
             var g = GetVertexGeometry<VertexPositionNormalTangent>(index);
             var m = GetVertexMaterial<VertexColor2Texture2>(index);
             var m = GetVertexMaterial<VertexColor2Texture2>(index);
             var s = GetVertexSkinning<VertexJoints8>(index);
             var s = GetVertexSkinning<VertexJoints8>(index);
 
 
-            return new VertexBuilder(g, m, s).ConvertToType(vertexType);
+            return new VertexBuilder(g, m, s).ConvertToType(factory);
         }
         }
 
 
         public VertexBuilder<TvG, TvM, VertexEmpty> GetVertex<TvG, TvM>(int index)
         public VertexBuilder<TvG, TvM, VertexEmpty> GetVertex<TvG, TvM>(int index)

+ 17 - 10
src/SharpGLTF.Toolkit/Geometry/VertexBuilder.cs

@@ -33,6 +33,9 @@ namespace SharpGLTF.Geometry
         /// </summary>
         /// </summary>
         /// <param name="skinning">A <see cref="IVertexSkinning"/> set.</param>
         /// <param name="skinning">A <see cref="IVertexSkinning"/> set.</param>
         void SetSkinning(IVertexSkinning skinning);
         void SetSkinning(IVertexSkinning skinning);
+
+
+        IMeshBuilder<TMaterial> CreateCompatibleMesh<TMaterial>(string name = null);
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -331,6 +334,11 @@ namespace SharpGLTF.Geometry
             return new MeshBuilder<TvG, TvM, TvS>(name);
             return new MeshBuilder<TvG, TvM, TvS>(name);
         }
         }
 
 
+        IMeshBuilder<TMaterial> IVertexBuilder.CreateCompatibleMesh<TMaterial>(string name)
+        {
+            return new MeshBuilder<TMaterial, TvG, TvM, TvS>(name);
+        }
+
         #pragma warning restore CA1000 // Do not declare static members on generic types
         #pragma warning restore CA1000 // Do not declare static members on generic types
 
 
         readonly IVertexGeometry IVertexBuilder.GetGeometry() { return this.Geometry; }
         readonly IVertexGeometry IVertexBuilder.GetGeometry() { return this.Geometry; }
@@ -449,7 +457,7 @@ namespace SharpGLTF.Geometry
             v.Skinning.SetBindings(sparse);
             v.Skinning.SetBindings(sparse);
 
 
             return v;
             return v;
-        }
+        }        
 
 
         #endregion
         #endregion
     }
     }
@@ -496,17 +504,11 @@ namespace SharpGLTF.Geometry
 
 
         public void SetMaterial(IVertexMaterial material) { this.Material = material; }
         public void SetMaterial(IVertexMaterial material) { this.Material = material; }
 
 
-        public void SetSkinning(IVertexSkinning skinning) { this.Skinning = skinning; }
+        public void SetSkinning(IVertexSkinning skinning) { this.Skinning = skinning; }        
 
 
-        public readonly IVertexBuilder ConvertToType
-            (
-            #if NET6_0_OR_GREATER
-            [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)]
-            #endif
-            Type vertexType
-            )
+        public readonly IVertexBuilder ConvertToType(Func<IVertexBuilder> factory)
         {
         {
-            var v = (IVertexBuilder)Activator.CreateInstance(vertexType);
+            var v = factory.Invoke();
 
 
             v.SetGeometry(Geometry);
             v.SetGeometry(Geometry);
             v.SetMaterial(Material);
             v.SetMaterial(Material);
@@ -515,6 +517,11 @@ namespace SharpGLTF.Geometry
             return v;
             return v;
         }
         }
 
 
+        IMeshBuilder<TMaterial> IVertexBuilder.CreateCompatibleMesh<TMaterial>(string name)
+        {
+            throw new NotImplementedException();
+        }
+
         #endregion
         #endregion
     }
     }
 }
 }

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

@@ -0,0 +1,201 @@
+// ------------------------------------------------------------------------------
+// <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.Linq;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+
+
+
+namespace SharpGLTF.Geometry.VertexTypes
+{
+    partial class VertexUtils
+    {            
+        public static (Type BuilderType, Func<IVertexBuilder> BuilderFactory) GetVertexBuilderType(bool hasNormals, bool hasTangents, int numCols, int numUV, int numJoints)
+        {
+            switch(numJoints)
+            {
+                case 0:
+                switch(numCols)
+                {
+                    case 0:
+                    switch(numUV)
+                    {
+                        case 0:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexEmpty,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexEmpty,VertexEmpty>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexEmpty,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexEmpty,VertexEmpty>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexEmpty,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexEmpty,VertexEmpty>() );
+                        case 1:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture1,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexTexture1,VertexEmpty>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture1,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture1,VertexEmpty>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture1,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture1,VertexEmpty>() );
+                        case 2:
+                            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>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexEmpty>() );
+                        default: throw new ArgumentOutOfRangeException(nameof(numUV));
+                    }
+                    case 1:
+                    switch(numUV)
+                    {
+                        case 0:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexColor1,VertexEmpty>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1,VertexEmpty>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1,VertexEmpty>() );
+                        case 1:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture1,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture1,VertexEmpty>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture1,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture1,VertexEmpty>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture1,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture1,VertexEmpty>() );
+                        case 2:
+                            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>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexEmpty>() );
+                        default: throw new ArgumentOutOfRangeException(nameof(numUV));
+                    }
+                    case 2:
+                    switch(numUV)
+                    {
+                        case 0:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexColor2,VertexEmpty>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2,VertexEmpty>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2,VertexEmpty>() );
+                        case 1:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture1,VertexEmpty>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture1,VertexEmpty>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture1,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture1,VertexEmpty>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture1,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture1,VertexEmpty>() );
+                        case 2:
+                            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>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexEmpty>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexEmpty>() );
+                        default: throw new ArgumentOutOfRangeException(nameof(numUV));
+                    }
+                    default: throw new ArgumentOutOfRangeException(nameof(numCols));
+                }
+                case 4:
+                switch(numCols)
+                {
+                    case 0:
+                    switch(numUV)
+                    {
+                        case 0:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexEmpty,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexEmpty,VertexJoints4>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexEmpty,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexEmpty,VertexJoints4>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexEmpty,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexEmpty,VertexJoints4>() );
+                        case 1:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture1,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexTexture1,VertexJoints4>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture1,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture1,VertexJoints4>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture1,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture1,VertexJoints4>() );
+                        case 2:
+                            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>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexJoints4>() );
+                        default: throw new ArgumentOutOfRangeException(nameof(numUV));
+                    }
+                    case 1:
+                    switch(numUV)
+                    {
+                        case 0:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexColor1,VertexJoints4>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1,VertexJoints4>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1,VertexJoints4>() );
+                        case 1:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture1,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture1,VertexJoints4>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture1,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture1,VertexJoints4>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture1,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture1,VertexJoints4>() );
+                        case 2:
+                            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>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexJoints4>() );
+                        default: throw new ArgumentOutOfRangeException(nameof(numUV));
+                    }
+                    case 2:
+                    switch(numUV)
+                    {
+                        case 0:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexColor2,VertexJoints4>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2,VertexJoints4>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2,VertexJoints4>() );
+                        case 1:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture1,VertexJoints4>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture1,VertexJoints4>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture1,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture1,VertexJoints4>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture1,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture1,VertexJoints4>() );
+                        case 2:
+                            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>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexJoints4>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexJoints4>() );
+                        default: throw new ArgumentOutOfRangeException(nameof(numUV));
+                    }
+                    default: throw new ArgumentOutOfRangeException(nameof(numCols));
+                }
+                case 8:
+                switch(numCols)
+                {
+                    case 0:
+                    switch(numUV)
+                    {
+                        case 0:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexEmpty,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexEmpty,VertexJoints8>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexEmpty,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexEmpty,VertexJoints8>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexEmpty,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexEmpty,VertexJoints8>() );
+                        case 1:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexTexture1,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexTexture1,VertexJoints8>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexTexture1,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexTexture1,VertexJoints8>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture1,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture1,VertexJoints8>() );
+                        case 2:
+                            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>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexTexture2,VertexJoints8>() );
+                        default: throw new ArgumentOutOfRangeException(nameof(numUV));
+                    }
+                    case 1:
+                    switch(numUV)
+                    {
+                        case 0:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexColor1,VertexJoints8>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1,VertexJoints8>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1,VertexJoints8>() );
+                        case 1:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor1Texture1,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexColor1Texture1,VertexJoints8>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor1Texture1,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor1Texture1,VertexJoints8>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture1,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture1,VertexJoints8>() );
+                        case 2:
+                            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>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor1Texture2,VertexJoints8>() );
+                        default: throw new ArgumentOutOfRangeException(nameof(numUV));
+                    }
+                    case 2:
+                    switch(numUV)
+                    {
+                        case 0:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexColor2,VertexJoints8>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2,VertexJoints8>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2,VertexJoints8>() );
+                        case 1:
+                            if (!hasNormals) return (typeof(VertexBuilder<VertexPosition,VertexColor2Texture1,VertexJoints8>), ()=> new VertexBuilder<VertexPosition,VertexColor2Texture1,VertexJoints8>() );
+                            if (!hasTangents) return (typeof(VertexBuilder<VertexPositionNormal,VertexColor2Texture1,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormal,VertexColor2Texture1,VertexJoints8>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture1,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture1,VertexJoints8>() );
+                        case 2:
+                            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>() );
+                            return (typeof(VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexJoints8>), ()=> new VertexBuilder<VertexPositionNormalTangent,VertexColor2Texture2,VertexJoints8>() );
+                        default: throw new ArgumentOutOfRangeException(nameof(numUV));
+                    }
+                    default: throw new ArgumentOutOfRangeException(nameof(numCols));
+                }
+                default: throw new ArgumentOutOfRangeException(nameof(numJoints));
+            }
+            throw new NotImplementedException();
+        }
+    }    
+}

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

@@ -0,0 +1,99 @@
+<#@ 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.Linq;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+
+<#
+
+void WriteAllVertexTypePermutations(string baseTemplate)
+{
+    WriteLine("switch(numJoints)");
+
+    PushIndent("            ");
+
+    WriteLine("{"); PushIndent("    ");
+
+    for (int __jnt = 0; __jnt <= 8; __jnt += 4)
+    {
+        WriteLine("case " + __jnt + ":");
+        WriteLine("switch(numCols)");
+        WriteLine("{"); PushIndent("    ");
+
+        for(int __col = 0; __col <= 2; ++__col)
+        {
+            WriteLine("case " + __col + ":");
+            WriteLine("switch(numUV)");
+            WriteLine("{"); PushIndent("    ");
+
+            for(int __tex = 0; __tex <= 2; ++__tex)
+            {
+                WriteLine("case " + __tex + ":");
+
+                var matType = "VertexEmpty";
+                var jntType = "VertexEmpty";
+
+                if (__col == 0 && __tex != 0) matType = $"VertexTexture{__tex}";
+                if (__col != 0 && __tex == 0) matType = $"VertexColor{__col}";
+                if (__col != 0 && __tex != 0) matType = $"VertexColor{__col}Texture{__tex}";
+
+                if (__jnt == 4) jntType = "VertexJoints4";
+                if (__jnt == 8) jntType = "VertexJoints8";
+
+                var a = $"{baseTemplate}<VertexPosition,{matType},{jntType}>";
+                var b = $"{baseTemplate}<VertexPositionNormal,{matType},{jntType}>";
+                var c = $"{baseTemplate}<VertexPositionNormalTangent,{matType},{jntType}>";
+
+                PushIndent("    ");
+                WriteLine($"if (!hasNormals) return (typeof({a}), ()=> new {a}() );");
+                WriteLine($"if (!hasTangents) return (typeof({b}), ()=> new {b}() );");
+                WriteLine($"return (typeof({c}), ()=> new {c}() );");                       
+                PopIndent();
+            }
+
+            WriteLine("default: throw new ArgumentOutOfRangeException(nameof(numUV));");
+            PopIndent(); WriteLine("}");                        
+        }
+
+        WriteLine("default: throw new ArgumentOutOfRangeException(nameof(numCols));");
+        PopIndent(); WriteLine("}");                    
+    }
+                
+    WriteLine("default: throw new ArgumentOutOfRangeException(nameof(numJoints));");
+    PopIndent(); WriteLine("}");
+
+    WriteLine("throw new NotImplementedException();");
+
+    PopIndent();    
+}
+
+#>
+
+
+namespace SharpGLTF.Geometry.VertexTypes
+{
+    partial class VertexUtils
+    {            
+        public static (Type BuilderType, Func<IVertexBuilder> BuilderFactory) GetVertexBuilderType(bool hasNormals, bool hasTangents, int numCols, int numUV, int numJoints)
+        {
+            <# WriteAllVertexTypePermutations("VertexBuilder"); #>
+        }
+    }    
+}

+ 26 - 100
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexUtils.Builder.cs

@@ -1,5 +1,4 @@
 using System;
 using System;
-using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Linq;
 using System.Numerics;
 using System.Numerics;
 
 
@@ -7,111 +6,38 @@ namespace SharpGLTF.Geometry.VertexTypes
 {
 {
     static partial class VertexUtils
     static partial class VertexUtils
     {
     {
-        #if NET6_0_OR_GREATER
-        [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
-        #endif
-        public static Type GetVertexGeometryType(params string[] vertexAttributes)
+        public static (Type BuilderType, Func<IVertexBuilder> BuilderFactory) GetVertexBuilderType(params string[] vertexAttributes)
         {
         {
-            var t = typeof(VertexPosition);
-            if (vertexAttributes.Contains("NORMAL")) t = typeof(VertexPositionNormal);
-            if (vertexAttributes.Contains("TANGENT")) t = typeof(VertexPositionNormalTangent);
-            return t;
-        }
-
-        #if NET6_0_OR_GREATER
-        [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
-        #endif
-        public static Type GetVertexMaterialType(params string[] vertexAttributes)
-        {
-            var colors = vertexAttributes.Contains("COLOR_0") ? 1 : 0;
-            colors = vertexAttributes.Contains("COLOR_1") ? 2 : colors;
-            colors = vertexAttributes.Contains("COLOR_2") ? 3 : colors;
-            colors = vertexAttributes.Contains("COLOR_3") ? 4 : colors;
-
-            var uvcoords = vertexAttributes.Contains("TEXCOORD_0") ? 1 : 0;
-            uvcoords = vertexAttributes.Contains("TEXCOORD_1") ? 2 : uvcoords;
-            uvcoords = vertexAttributes.Contains("TEXCOORD_2") ? 3 : uvcoords;
-            uvcoords = vertexAttributes.Contains("TEXCOORD_3") ? 4 : uvcoords;
-
-            return GetVertexMaterialType(colors, uvcoords);
-        }
-
-        #if NET6_0_OR_GREATER
-        [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
-        #endif
-        public static Type GetVertexMaterialType(int colors, int uvcoords)
-        {
-            if (colors == 0)
-            {
-                if (uvcoords == 0) return typeof(VertexEmpty);
-                if (uvcoords == 1) return typeof(VertexTexture1);
-                if (uvcoords >= 2) return typeof(VertexTexture2);
-            }
-
-            if (colors == 1)
-            {
-                if (uvcoords == 0) return typeof(VertexColor1);
-                if (uvcoords == 1) return typeof(VertexColor1Texture1);
-                if (uvcoords >= 2) return typeof(VertexColor1Texture2);
-            }
-
-            if (colors >= 2)
-            {
-                if (uvcoords == 0) return typeof(VertexColor2);
-                if (uvcoords == 1) return typeof(VertexColor2Texture1);
-                if (uvcoords >= 2) return typeof(VertexColor2Texture2);
-            }
+            var hasNormals = vertexAttributes.Contains("NORMAL");
+            var hasTangents = vertexAttributes.Contains("TANGENT");
+
+            var colors = 0;
+            if (vertexAttributes.Contains("COLOR_0")) colors = Math.Max(colors, 1);
+            if (vertexAttributes.Contains("COLOR_1")) colors = Math.Max(colors, 2);
+            if (vertexAttributes.Contains("COLOR_2")) colors = Math.Max(colors, 3);
+            if (vertexAttributes.Contains("COLOR_3")) colors = Math.Max(colors, 4);
+            if (vertexAttributes.Contains("COLOR_4")) colors = Math.Max(colors, 5);
+            if (vertexAttributes.Contains("COLOR_5")) colors = Math.Max(colors, 6);
+            if (vertexAttributes.Contains("COLOR_6")) colors = Math.Max(colors, 7);
+            if (vertexAttributes.Contains("COLOR_7")) colors = Math.Max(colors, 8);
+
+            var uvcoords = 0;
+            if (vertexAttributes.Contains("TEXCOORD_0")) uvcoords = Math.Max(uvcoords, 1);
+            if (vertexAttributes.Contains("TEXCOORD_1")) uvcoords = Math.Max(uvcoords, 2);
+            if (vertexAttributes.Contains("TEXCOORD_2")) uvcoords = Math.Max(uvcoords, 3);
+            if (vertexAttributes.Contains("TEXCOORD_3")) uvcoords = Math.Max(uvcoords, 4);
+            if (vertexAttributes.Contains("TEXCOORD_4")) uvcoords = Math.Max(uvcoords, 5);
+            if (vertexAttributes.Contains("TEXCOORD_5")) uvcoords = Math.Max(uvcoords, 6);
+            if (vertexAttributes.Contains("TEXCOORD_6")) uvcoords = Math.Max(uvcoords, 7);
+            if (vertexAttributes.Contains("TEXCOORD_7")) uvcoords = Math.Max(uvcoords, 8);
 
 
-            return typeof(VertexEmpty);
-        }
-
-        #if NET6_0_OR_GREATER
-        [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
-        #endif
-        public static Type GetVertexSkinningType(params string[] vertexAttributes)
-        {
             var joints = vertexAttributes.Contains("JOINTS_0") && vertexAttributes.Contains("WEIGHTS_0") ? 4 : 0;
             var joints = vertexAttributes.Contains("JOINTS_0") && vertexAttributes.Contains("WEIGHTS_0") ? 4 : 0;
             joints = vertexAttributes.Contains("JOINTS_1") && vertexAttributes.Contains("WEIGHTS_1") ? 8 : joints;
             joints = vertexAttributes.Contains("JOINTS_1") && vertexAttributes.Contains("WEIGHTS_1") ? 8 : joints;
 
 
-            if (joints == 4) return typeof(VertexJoints4);
-            if (joints == 8) return typeof(VertexJoints8);
-
-            return typeof(VertexEmpty);
-        }
-
-        #if NET6_0_OR_GREATER
-        [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
-        #endif
-        public static Type GetVertexBuilderType(params string[] vertexAttributes)
-        {
-            var tvg = GetVertexGeometryType(vertexAttributes);
-            var tvm = GetVertexMaterialType(vertexAttributes);
-            var tvs = GetVertexSkinningType(vertexAttributes);
-
-            var vtype = typeof(VertexBuilder<,,>);
+            // WARNING: not all Color x Texture higher values have been defined yet.
 
 
-            return vtype.MakeGenericType(tvg, tvm, tvs);
-        }
-
-        #if NET6_0_OR_GREATER
-        [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
-        #endif
-        public static Type GetVertexBuilderType(bool hasNormals, bool hasTangents, int numCols, int numUV, int numJoints)
-        {
-            var tvg = typeof(VertexPosition);
-            if (hasNormals) tvg = typeof(VertexPositionNormal);
-            if (hasTangents) tvg = typeof(VertexPositionNormalTangent);
-
-            var tvm = GetVertexMaterialType(numCols, numUV);
-
-            var tvs = typeof(VertexEmpty);
-            if (numJoints == 4) tvs = typeof(VertexJoints4);
-            if (numJoints >= 8) tvs = typeof(VertexJoints8);
-
-            var vtype = typeof(VertexBuilder<,,>);
-
-            return vtype.MakeGenericType(tvg, tvm, tvs);
-        }
+            return GetVertexBuilderType(hasNormals, hasTangents, colors, uvcoords, joints);
+        }        
 
 
         public static TvP ConvertToGeometry<TvP>(this IVertexGeometry src)
         public static TvP ConvertToGeometry<TvP>(this IVertexGeometry src)
             where TvP : struct, IVertexGeometry
             where TvP : struct, IVertexGeometry

+ 13 - 12
src/SharpGLTF.Toolkit/Schema2/MeshExtensions.cs

@@ -10,6 +10,7 @@ using SharpGLTF.Geometry.VertexTypes;
 
 
 using MESHXFORM = SharpGLTF.Transforms.IGeometryTransform;
 using MESHXFORM = SharpGLTF.Transforms.IGeometryTransform;
 using JSONEXTRAS = System.Text.Json.Nodes.JsonNode;
 using JSONEXTRAS = System.Text.Json.Nodes.JsonNode;
+using System.Diagnostics.CodeAnalysis;
 
 
 namespace SharpGLTF.Schema2
 namespace SharpGLTF.Schema2
 {
 {
@@ -483,12 +484,12 @@ namespace SharpGLTF.Schema2
             var points = prim.GetPointIndices();
             var points = prim.GetPointIndices();
 
 
             VertexBufferColumns vertices = null;
             VertexBufferColumns vertices = null;
-            Type vtype = null;
+            Func<IVertexBuilder> vtype = null;
 
 
             foreach (var xinst in Transforms.InstancingTransform.Evaluate(xform))
             foreach (var xinst in Transforms.InstancingTransform.Evaluate(xform))
             {
             {
                 vertices ??= prim.GetVertexColumns();
                 vertices ??= prim.GetVertexColumns();
-                vtype ??= vertices.GetCompatibleVertexType();
+                vtype ??= vertices.GetCompatibleVertexType().BuilderFactory;
 
 
                 var xvertices = xinst != null
                 var xvertices = xinst != null
                     ? vertices.WithTransform(xinst)
                     ? vertices.WithTransform(xinst)
@@ -519,7 +520,7 @@ namespace SharpGLTF.Schema2
             if (!lines.Any()) yield break;
             if (!lines.Any()) yield break;
 
 
             var vertices = prim.GetVertexColumns();
             var vertices = prim.GetVertexColumns();
-            var vtype = vertices.GetCompatibleVertexType();
+            var vtype = vertices.GetCompatibleVertexType().BuilderFactory;
 
 
             foreach (var xinst in Transforms.InstancingTransform.Evaluate(xform))
             foreach (var xinst in Transforms.InstancingTransform.Evaluate(xform))
             {
             {
@@ -554,7 +555,7 @@ namespace SharpGLTF.Schema2
             foreach (var xinst in Transforms.InstancingTransform.Evaluate(xform))
             foreach (var xinst in Transforms.InstancingTransform.Evaluate(xform))
             {
             {
                 var xvertices = xinst != null ? vertices.WithTransform(xinst) : vertices;
                 var xvertices = xinst != null ? vertices.WithTransform(xinst) : vertices;
-                var vtype = vertices.GetCompatibleVertexType();
+                var vtype = vertices.GetCompatibleVertexType().BuilderFactory;
 
 
                 foreach (var (ta, tb, tc) in triangles)
                 foreach (var (ta, tb, tc) in triangles)
                 {
                 {
@@ -704,7 +705,7 @@ namespace SharpGLTF.Schema2
 
 
             return srcScene.ToStaticMeshBuilder<Materials.MaterialBuilder, TvG, TvM>(convertMaterial, options, animation, time);
             return srcScene.ToStaticMeshBuilder<Materials.MaterialBuilder, TvG, TvM>(convertMaterial, options, animation, time);
         }
         }
-
+                
         public static IMeshBuilder<Materials.MaterialBuilder> ToMeshBuilder(this Mesh srcMesh)
         public static IMeshBuilder<Materials.MaterialBuilder> ToMeshBuilder(this Mesh srcMesh)
         {
         {
             if (srcMesh == null) return null;
             if (srcMesh == null) return null;
@@ -811,7 +812,7 @@ namespace SharpGLTF.Schema2
 
 
             foreach (var srcPoint in srcPrim.GetPointIndices())
             foreach (var srcPoint in srcPrim.GetPointIndices())
             {
             {
-                var vrt = vertices.GetVertex(dstPrim.VertexType, srcPoint);
+                var vrt = vertices.GetVertex(dstPrim.VertexFactory, srcPoint);
 
 
                 var idx = dstPrim.AddPoint(vrt);
                 var idx = dstPrim.AddPoint(vrt);
 
 
@@ -820,8 +821,8 @@ namespace SharpGLTF.Schema2
 
 
             foreach (var (srcA, srcB) in srcPrim.GetLineIndices())
             foreach (var (srcA, srcB) in srcPrim.GetLineIndices())
             {
             {
-                var vrtA = vertices.GetVertex(dstPrim.VertexType, srcA);
-                var vrtB = vertices.GetVertex(dstPrim.VertexType, srcB);
+                var vrtA = vertices.GetVertex(dstPrim.VertexFactory, srcA);
+                var vrtB = vertices.GetVertex(dstPrim.VertexFactory, srcB);
 
 
                 var (idxA, idxB) = dstPrim.AddLine(vrtA, vrtB);
                 var (idxA, idxB) = dstPrim.AddLine(vrtA, vrtB);
 
 
@@ -831,9 +832,9 @@ namespace SharpGLTF.Schema2
 
 
             foreach (var (srcA, srcB, srcC) in srcPrim.GetTriangleIndices())
             foreach (var (srcA, srcB, srcC) in srcPrim.GetTriangleIndices())
             {
             {
-                var vrtA = vertices.GetVertex(dstPrim.VertexType, srcA);
-                var vrtB = vertices.GetVertex(dstPrim.VertexType, srcB);
-                var vrtC = vertices.GetVertex(dstPrim.VertexType, srcC);
+                var vrtA = vertices.GetVertex(dstPrim.VertexFactory, srcA);
+                var vrtB = vertices.GetVertex(dstPrim.VertexFactory, srcB);
+                var vrtC = vertices.GetVertex(dstPrim.VertexFactory, srcC);
 
 
                 var (idxA, idxB, idxC) = dstPrim.AddTriangle(vrtA, vrtB, vrtC);
                 var (idxA, idxB, idxC) = dstPrim.AddTriangle(vrtA, vrtB, vrtC);
 
 
@@ -850,7 +851,7 @@ namespace SharpGLTF.Schema2
                 {
                 {
                     if (kvp.Value < 0) continue;
                     if (kvp.Value < 0) continue;
 
 
-                    var v = srcTarget.GetVertex(dstPrim.VertexType, kvp.Key);
+                    var v = srcTarget.GetVertex(dstPrim.VertexFactory, kvp.Key);
 
 
                     dstPrim.SetVertexDelta(tidx, kvp.Value,
                     dstPrim.SetVertexDelta(tidx, kvp.Value,
                         new VertexGeometryDelta(v.GetGeometry()), new VertexMaterialDelta(v.GetMaterial()));
                         new VertexGeometryDelta(v.GetGeometry()), new VertexMaterialDelta(v.GetMaterial()));

+ 20 - 1
src/SharpGLTF.Toolkit/SharpGLTF.Toolkit.csproj

@@ -16,6 +16,25 @@
 
 
   <ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\SharpGLTF.Runtime\SharpGLTF.Runtime.csproj" />
     <ProjectReference Include="..\SharpGLTF.Runtime\SharpGLTF.Runtime.csproj" />
-  </ItemGroup> 
+  </ItemGroup>    
+
+  <ItemGroup>
+    <Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <None Update="Geometry\VertexTypes\VertexUtils.Builder.Reflection.tt">
+      <Generator>TextTemplatingFileGenerator</Generator>
+      <LastGenOutput>VertexUtils.Builder.Reflection.cs</LastGenOutput>
+    </None>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Compile Update="Geometry\VertexTypes\VertexUtils.Builder.Reflection.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>VertexUtils.Builder.Reflection.tt</DependentUpon>
+    </Compile>
+  </ItemGroup>
 
 
 </Project>
 </Project>