瀏覽代碼

code cleanup

Vicente Penades 6 年之前
父節點
當前提交
379465bb8b

+ 0 - 55
src/SharpGLTF.Toolkit/Geometry/PackedMeshBuilder.cs

@@ -16,61 +16,6 @@ namespace SharpGLTF.Geometry
     {
         #region lifecycle
 
-        /// <summary>
-        /// Converts a collection of <see cref="MeshBuilder{TMaterial, TvP, TvM, TvS}"/>
-        /// to a collection of <see cref="PackedMeshBuilder{TMaterial}"/>, trying to use
-        /// a single vertex buffer and a single index buffer shared by all meshes.
-        /// </summary>
-        /// <typeparam name="TvP">The vertex fragment type with Position, Normal and Tangent.</typeparam>
-        /// <typeparam name="TvM">The vertex fragment type with Colors and Texture Coordinates.</typeparam>
-        /// <typeparam name="TvS">The vertex fragment type with Skin Joint Weights.</typeparam>
-        /// <param name="meshBuilders">A collection of <see cref="MeshBuilder{TMaterial, TvP, TvM, TvS}"/> instances.</param>
-        /// <returns>A collection of <see cref="PackedMeshBuilder{TMaterial}"/> instances.</returns>
-        internal static IEnumerable<PackedMeshBuilder<TMaterial>> PackMeshes<TvP, TvM, TvS>(IEnumerable<MeshBuilder<TMaterial, TvP, TvM, TvS>> meshBuilders)
-            where TvP : struct, VertexTypes.IVertexGeometry
-            where TvM : struct, VertexTypes.IVertexMaterial
-            where TvS : struct, VertexTypes.IVertexSkinning
-        {
-            try
-            {
-                foreach (var m in meshBuilders) m.Validate();
-            }
-            catch (Exception ex)
-            {
-                throw new ArgumentException(ex.Message, nameof(meshBuilders), ex);
-            }
-
-            var vertexBlocks = VertexTypes.VertexUtils.CreateVertexMemoryAccessors
-                (
-                meshBuilders
-                .SelectMany(item => item.Primitives)
-                .Select(item => item.Vertices)
-                ).ToList();
-
-            var indexBlocks = VertexTypes.VertexUtils.CreateIndexMemoryAccessors
-                (
-                meshBuilders
-                .SelectMany(item => item.Primitives)
-                .Select(item => item.Indices)
-                ).ToList();
-
-            int idx = 0;
-
-            foreach (var meshBuilder in meshBuilders)
-            {
-                var dstMesh = new PackedMeshBuilder<TMaterial>(meshBuilder.Name);
-
-                foreach (var primitiveBuilder in meshBuilder.Primitives)
-                {
-                    dstMesh.AddPrimitive(primitiveBuilder.Material, primitiveBuilder.VerticesPerPrimitive, vertexBlocks[idx], indexBlocks[idx]);
-
-                    ++idx;
-                }
-
-                yield return dstMesh;
-            }
-        }
-
         /// <summary>
         /// Converts a collection of <see cref="MeshBuilder{TMaterial, TvP, TvM, TvS}"/>
         /// to a collection of <see cref="PackedMeshBuilder{TMaterial}"/>, trying to use

+ 15 - 133
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexUtils.cs

@@ -49,11 +49,13 @@ namespace SharpGLTF.Geometry.VertexTypes
             return true;
         }
 
-        public static IEnumerable<MemoryAccessor[]> CreateVertexMemoryAccessors(this IEnumerable<IReadOnlyList<IVertexBuilder>> vertexBlocks)
+        public static IEnumerable<MemoryAccessor[]> CreateVertexMemoryAccessors<TVertex>(this IEnumerable<IReadOnlyList<TVertex>> vertexBlocks)
+            where TVertex : IVertexBuilder
         {
             // total number of vertices
             var totalCount = vertexBlocks.Sum(item => item.Count);
 
+            // determine the vertex attributes from the first vertex.
             var firstVertex = vertexBlocks
                 .First(item => item.Count > 0)
                 .First();
@@ -61,53 +63,13 @@ namespace SharpGLTF.Geometry.VertexTypes
             var tvg = firstVertex.GetGeometry().GetType();
             var tvm = firstVertex.GetMaterial().GetType();
             var tvs = firstVertex.GetSkinning().GetType();
-
-            // vertex attributes
-            var attributes = GetVertexAttributes(tvg, tvm, tvs, totalCount);
+            var attributes = _GetVertexAttributes(tvg, tvm, tvs, totalCount);
 
             // create master vertex buffer
             int byteStride = attributes[0].ByteStride;
             var vbuffer = new ArraySegment<byte>(new Byte[byteStride * totalCount]);
 
-            var baseVertexIndex = 0;
-
-            foreach (var block in vertexBlocks)
-            {
-                var accessors = MemoryAccessInfo
-                    .Slice(attributes, baseVertexIndex, block.Count)
-                    .Select(item => new MemoryAccessor(vbuffer, item))
-                    .ToArray();
-
-                foreach (var accessor in accessors)
-                {
-                    var columnFunc = GetVertexBuilderAttributeFunc(accessor.Attribute.Name);
-
-                    if (accessor.Attribute.Dimensions == Schema2.DimensionType.SCALAR) accessor.AsScalarArray().Fill(block.GetColumn<float>(columnFunc));
-                    if (accessor.Attribute.Dimensions == Schema2.DimensionType.VEC2) accessor.AsVector2Array().Fill(block.GetColumn<Vector2>(columnFunc));
-                    if (accessor.Attribute.Dimensions == Schema2.DimensionType.VEC3) accessor.AsVector3Array().Fill(block.GetColumn<Vector3>(columnFunc));
-                    if (accessor.Attribute.Dimensions == Schema2.DimensionType.VEC4) accessor.AsVector4Array().Fill(block.GetColumn<Vector4>(columnFunc));
-                }
-
-                yield return accessors;
-
-                baseVertexIndex += block.Count;
-            }
-        }
-
-        public static IEnumerable<MemoryAccessor[]> CreateVertexMemoryAccessors<TvG, TvM, TvS>(this IEnumerable<IReadOnlyList<VertexBuilder<TvG, TvM, TvS>>> vertexBlocks)
-            where TvG : struct, IVertexGeometry
-            where TvM : struct, IVertexMaterial
-            where TvS : struct, IVertexSkinning
-        {
-            // total number of vertices
-            var totalCount = vertexBlocks.Sum(item => item.Count);
-
-            // vertex attributes
-            var attributes = GetVertexAttributes(typeof(TvG), typeof(TvM), typeof(TvS), totalCount);
-
-            // create master vertex buffer
-            int byteStride = attributes[0].ByteStride;
-            var vbuffer = new ArraySegment<byte>( new Byte[byteStride * totalCount] );
+            // fill the buffer with the vertex blocks.
 
             var baseVertexIndex = 0;
 
@@ -120,12 +82,12 @@ namespace SharpGLTF.Geometry.VertexTypes
 
                 foreach (var accessor in accessors)
                 {
-                    var columnFunc = GetVertexBuilderAttributeFunc<TvG, TvM, TvS>(accessor.Attribute.Name);
+                    var columnFunc = _GetVertexBuilderAttributeFunc(accessor.Attribute.Name);
 
-                    if (accessor.Attribute.Dimensions == Schema2.DimensionType.SCALAR) accessor.AsScalarArray().Fill(block.GetScalarColumn(columnFunc));
-                    if (accessor.Attribute.Dimensions == Schema2.DimensionType.VEC2) accessor.AsVector2Array().Fill(block.GetVector2Column(columnFunc));
-                    if (accessor.Attribute.Dimensions == Schema2.DimensionType.VEC3) accessor.AsVector3Array().Fill(block.GetVector3Column(columnFunc));
-                    if (accessor.Attribute.Dimensions == Schema2.DimensionType.VEC4) accessor.AsVector4Array().Fill(block.GetVector4Column(columnFunc));
+                    if (accessor.Attribute.Dimensions == Schema2.DimensionType.SCALAR) accessor.AsScalarArray().Fill(block._GetColumn<TVertex, float>(columnFunc));
+                    if (accessor.Attribute.Dimensions == Schema2.DimensionType.VEC2) accessor.AsVector2Array().Fill(block._GetColumn<TVertex, Vector2>(columnFunc));
+                    if (accessor.Attribute.Dimensions == Schema2.DimensionType.VEC3) accessor.AsVector3Array().Fill(block._GetColumn<TVertex, Vector3>(columnFunc));
+                    if (accessor.Attribute.Dimensions == Schema2.DimensionType.VEC4) accessor.AsVector4Array().Fill(block._GetColumn<TVertex, Vector4>(columnFunc));
                 }
 
                 yield return accessors;
@@ -158,22 +120,7 @@ namespace SharpGLTF.Geometry.VertexTypes
             }
         }
 
-        private static System.Reflection.FieldInfo GetVertexField(Type vertexType, string attributeName)
-        {
-            foreach (var finfo in vertexType.GetFields())
-            {
-                var attribute = _GetMemoryAccessInfo(finfo);
-
-                if (attribute.HasValue)
-                {
-                    if (attribute.Value.Name == attributeName) return finfo;
-                }
-            }
-
-            return null;
-        }
-
-        private static MemoryAccessInfo[] GetVertexAttributes(Type vertexType, Type valuesType, Type jointsType, int itemsCount)
+        private static MemoryAccessInfo[] _GetVertexAttributes(Type vertexType, Type valuesType, Type jointsType, int itemsCount)
         {
             var attributes = new List<MemoryAccessInfo>();
 
@@ -224,24 +171,7 @@ namespace SharpGLTF.Geometry.VertexTypes
             return new MemoryAccessInfo(attribute.Name, 0, 0, 0, dimensions.Value, attribute.Encoding, attribute.Normalized);
         }
 
-        private static Func<VertexBuilder<TvG, TvM, TvS>, Object> GetVertexBuilderAttributeFunc<TvG, TvM, TvS>(string attributeName)
-            where TvG : struct, IVertexGeometry
-            where TvM : struct, IVertexMaterial
-            where TvS : struct, IVertexSkinning
-        {
-            var finfo = GetVertexField(typeof(TvG), attributeName);
-            if (finfo != null) return vertex => finfo.GetValue(vertex.Geometry);
-
-            finfo = GetVertexField(typeof(TvM), attributeName);
-            if (finfo != null) return vertex => finfo.GetValue(vertex.Material);
-
-            finfo = GetVertexField(typeof(TvS), attributeName);
-            if (finfo != null) return vertex => finfo.GetValue(vertex.Skinning);
-
-            throw new NotImplementedException();
-        }
-
-        private static Func<IVertexBuilder, Object> GetVertexBuilderAttributeFunc(string attributeName)
+        private static Func<IVertexBuilder, Object> _GetVertexBuilderAttributeFunc(string attributeName)
         {
             if (attributeName == "POSITION") return v => v.GetGeometry().GetPosition();
             if (attributeName == "NORMAL") return v => { return v.GetGeometry().TryGetNormal(out Vector3 n) ? n : Vector3.Zero; };
@@ -266,56 +196,8 @@ namespace SharpGLTF.Geometry.VertexTypes
             throw new NotImplementedException();
         }
 
-        private static Single[] GetScalarColumn<TvG, TvM, TvS>(this IReadOnlyList<VertexBuilder<TvG, TvM, TvS>> vertices, Func<VertexBuilder<TvG, TvM, TvS>, Object> func)
-            where TvG : struct, IVertexGeometry
-            where TvM : struct, IVertexMaterial
-            where TvS : struct, IVertexSkinning
-        {
-            return GetColumn<TvG, TvM, TvS, Single>(vertices, func);
-        }
-
-        private static Vector2[] GetVector2Column<TvG, TvM, TvS>(this IReadOnlyList<VertexBuilder<TvG, TvM, TvS>> vertices, Func<VertexBuilder<TvG, TvM, TvS>, Object> func)
-            where TvG : struct, IVertexGeometry
-            where TvM : struct, IVertexMaterial
-            where TvS : struct, IVertexSkinning
-        {
-            return GetColumn<TvG, TvM, TvS, Vector2>(vertices, func);
-        }
-
-        private static Vector3[] GetVector3Column<TvG, TvM, TvS>(this IReadOnlyList<VertexBuilder<TvG, TvM, TvS>> vertices, Func<VertexBuilder<TvG, TvM, TvS>, Object> func)
-            where TvG : struct, IVertexGeometry
-            where TvM : struct, IVertexMaterial
-            where TvS : struct, IVertexSkinning
-        {
-            return GetColumn<TvG, TvM, TvS, Vector3>(vertices, func);
-        }
-
-        private static Vector4[] GetVector4Column<TvG, TvM, TvS>(this IReadOnlyList<VertexBuilder<TvG, TvM, TvS>> vertices, Func<VertexBuilder<TvG, TvM, TvS>, Object> func)
-            where TvG : struct, IVertexGeometry
-            where TvM : struct, IVertexMaterial
-            where TvS : struct, IVertexSkinning
-        {
-            return GetColumn<TvG, TvM, TvS, Vector4>(vertices, func);
-        }
-
-        private static TColumn[] GetColumn<TvG, TvM, TvS, TColumn>(this IReadOnlyList<VertexBuilder<TvG, TvM, TvS>> vertices, Func<VertexBuilder<TvG, TvM, TvS>, Object> func)
-            where TvG : struct, IVertexGeometry
-            where TvM : struct, IVertexMaterial
-            where TvS : struct, IVertexSkinning
-        {
-            var dst = new TColumn[vertices.Count];
-
-            for (int i = 0; i < dst.Length; ++i)
-            {
-                var v = vertices[i];
-
-                dst[i] = (TColumn)func(v);
-            }
-
-            return dst;
-        }
-
-        private static TColumn[] GetColumn<TColumn>(this IReadOnlyList<IVertexBuilder> vertices, Func<IVertexBuilder, Object> func)
+        private static TColumn[] _GetColumn<TVertex, TColumn>(this IReadOnlyList<TVertex> vertices, Func<IVertexBuilder, Object> func)
+            where TVertex : IVertexBuilder
         {
             var dst = new TColumn[vertices.Count];
 
@@ -421,6 +303,6 @@ namespace SharpGLTF.Geometry.VertexTypes
             }
 
             return dst;
-        }        
+        }
     }
 }

+ 50 - 97
src/SharpGLTF.Toolkit/Schema2/MeshExtensions.cs

@@ -14,50 +14,22 @@ namespace SharpGLTF.Schema2
     {
         #region meshes
 
-        public static Mesh CreateMesh<TvP, TvM, TvS>(this ModelRoot root, MeshBuilder<Materials.MaterialBuilder, TvP, TvM, TvS> meshBuilder)
-            where TvP : struct, IVertexGeometry
-            where TvM : struct, IVertexMaterial
-            where TvS : struct, IVertexSkinning
-        {
-            return root.CreateMeshes(meshBuilder).First();
-        }
-
-        public static Mesh CreateMesh<TvP, TvM, TvS>(this ModelRoot root, MeshBuilder<Material, TvP, TvM, TvS> meshBuilder)
-            where TvP : struct, IVertexGeometry
-            where TvM : struct, IVertexMaterial
-            where TvS : struct, IVertexSkinning
-        {
-            return root.CreateMeshes(meshBuilder).First();
-        }
-
-        public static Mesh CreateMesh<TMaterial, TvP, TvM, TvS>(this ModelRoot root, Func<TMaterial, Material> materialEvaluator, MeshBuilder<TMaterial, TvP, TvM, TvS> meshBuilder)
-            where TvP : struct, IVertexGeometry
-            where TvM : struct, IVertexMaterial
-            where TvS : struct, IVertexSkinning
+        public static Mesh CreateMesh(this ModelRoot root, IMeshBuilder<Materials.MaterialBuilder> mesh)
         {
-            return root.CreateMeshes(materialEvaluator, meshBuilder).First();
+            return root.CreateMeshes(mesh).First();
         }
 
-        public static IReadOnlyList<Mesh> CreateMeshes<TvP, TvM, TvS>(this ModelRoot root, params MeshBuilder<Material, TvP, TvM, TvS>[] meshBuilders)
-            where TvP : struct, IVertexGeometry
-            where TvM : struct, IVertexMaterial
-            where TvS : struct, IVertexSkinning
+        public static Mesh CreateMesh<TMaterial>(this ModelRoot root, Func<TMaterial, Material> materialEvaluator, IMeshBuilder<TMaterial> mesh)
         {
-            return root.CreateMeshes(m => m, meshBuilders);
+            return root.CreateMeshes<TMaterial>(materialEvaluator, mesh).First();
         }
 
-        public static IReadOnlyList<Mesh> CreateMeshes<TvP, TvM, TvS>(this ModelRoot root, params MeshBuilder<Materials.MaterialBuilder, TvP, TvM, TvS>[] meshBuilders)
-            where TvP : struct, IVertexGeometry
-            where TvM : struct, IVertexMaterial
-            where TvS : struct, IVertexSkinning
+        public static IReadOnlyList<Mesh> CreateMeshes(this ModelRoot root, params IMeshBuilder<Materials.MaterialBuilder>[] meshBuilders)
         {
             return root.CreateMeshes(mb => root.CreateMaterial(mb), meshBuilders);
         }
 
-        public static IReadOnlyList<Mesh> CreateMeshes<TMaterial, TvP, TvM, TvS>(this ModelRoot root, Func<TMaterial, Material> materialEvaluator, params MeshBuilder<TMaterial, TvP, TvM, TvS>[] meshBuilders)
-            where TvP : struct, IVertexGeometry
-            where TvM : struct, IVertexMaterial
-            where TvS : struct, IVertexSkinning
+        public static IReadOnlyList<Mesh> CreateMeshes<TMaterial>(this ModelRoot root, Func<TMaterial, Material> materialEvaluator, params IMeshBuilder<TMaterial>[] meshBuilders)
         {
             Guard.NotNull(root, nameof(root));
             Guard.NotNull(materialEvaluator, nameof(materialEvaluator));
@@ -89,46 +61,38 @@ namespace SharpGLTF.Schema2
             return dstMeshes;
         }
 
-        public static IReadOnlyList<Mesh> CreateMeshes(this ModelRoot root, params IMeshBuilder<Materials.MaterialBuilder>[] meshBuilders)
-        {
-            return root.CreateMeshes(mb => root.CreateMaterial(mb), meshBuilders);
-        }
+        #endregion
 
-        public static IReadOnlyList<Mesh> CreateMeshes<TMaterial>(this ModelRoot root, Func<TMaterial, Material> materialEvaluator, params IMeshBuilder<TMaterial>[] meshBuilders)
-        {
-            Guard.NotNull(root, nameof(root));
-            Guard.NotNull(materialEvaluator, nameof(materialEvaluator));
-            Guard.NotNull(meshBuilders, nameof(meshBuilders));
+        #region accessors
 
-            foreach (var m in meshBuilders) m.Validate();
+        public static MeshPrimitive WithIndicesAutomatic(this MeshPrimitive primitive, PrimitiveType primitiveType)
+        {
+            var root = primitive.LogicalParent.LogicalParent;
 
-            // create a new material for every unique material in the mesh builders.
-            var mapMaterials = meshBuilders
-                .SelectMany(item => item.Primitives)
-                .Select(item => item.Material)
-                .Distinct()
-                .ToDictionary(m => m, m => materialEvaluator(m));
+            primitive.DrawPrimitiveType = primitiveType;
+            primitive.SetIndexAccessor(null);
 
-            // creates meshes and primitives using MemoryAccessors using a single, shared vertex and index buffer
-            var srcMeshes = PackedMeshBuilder<TMaterial>
-                .PackMeshes(meshBuilders)
-                .ToList();
+            return primitive;
+        }
 
-            var dstMeshes = new List<Mesh>();
+        public static MeshPrimitive WithIndicesAccessor(this MeshPrimitive primitive, PrimitiveType primitiveType, IReadOnlyList<Int32> values)
+        {
+            var root = primitive.LogicalParent.LogicalParent;
 
-            foreach (var srcMesh in srcMeshes)
-            {
-                var dstMesh = srcMesh.CreateSchema2Mesh(root, m => mapMaterials[m]);
+            // create an index buffer and fill it
+            var view = root.UseBufferView(new Byte[4 * values.Count], 0, null, 0, BufferMode.ELEMENT_ARRAY_BUFFER);
+            var array = new IntegerArray(view.Content);
+            array.Fill(values);
 
-                dstMeshes.Add(dstMesh);
-            }
+            var accessor = root.CreateAccessor();
 
-            return dstMeshes;
-        }
+            accessor.SetIndexData(view, 0, values.Count, IndexEncodingType.UNSIGNED_INT);
 
-        #endregion
+            primitive.DrawPrimitiveType = primitiveType;
+            primitive.SetIndexAccessor(accessor);
 
-        #region accessors
+            return primitive;
+        }
 
         public static MeshPrimitive WithVertexAccessor(this MeshPrimitive primitive, string attribute, IReadOnlyList<Single> values)
         {
@@ -200,62 +164,51 @@ namespace SharpGLTF.Schema2
             return primitive;
         }
 
-        public static MeshPrimitive WithIndicesAutomatic(this MeshPrimitive primitive, PrimitiveType primitiveType)
+        public static MeshPrimitive WithVertexAccessors(this MeshPrimitive primitive, IReadOnlyList<VertexPosition> vertices)
         {
-            var root = primitive.LogicalParent.LogicalParent;
-
-            primitive.DrawPrimitiveType = primitiveType;
-            primitive.SetIndexAccessor(null);
+            var xvertices = vertices
+                .Select(item => new VertexBuilder<VertexPosition, VertexEmpty, VertexEmpty>(item))
+                .ToList();
 
-            return primitive;
+            return primitive.WithVertexAccessors(xvertices);
         }
 
-        public static MeshPrimitive WithIndicesAccessor(this MeshPrimitive primitive, PrimitiveType primitiveType, IReadOnlyList<Int32> values)
+        public static MeshPrimitive WithVertexAccessors(this MeshPrimitive primitive, IReadOnlyList<VertexPositionNormal> vertices)
         {
-            var root = primitive.LogicalParent.LogicalParent;
-
-            // create an index buffer and fill it
-            var view = root.UseBufferView(new Byte[4 * values.Count], 0, null, 0, BufferMode.ELEMENT_ARRAY_BUFFER);
-            var array = new IntegerArray(view.Content);
-            array.Fill(values);
-
-            var accessor = root.CreateAccessor();
-
-            accessor.SetIndexData(view, 0, values.Count, IndexEncodingType.UNSIGNED_INT);
-
-            primitive.DrawPrimitiveType = primitiveType;
-            primitive.SetIndexAccessor(accessor);
+            var xvertices = vertices
+                .Select(item => new VertexBuilder<VertexPositionNormal, VertexEmpty, VertexEmpty>(item))
+                .ToList();
 
-            return primitive;
+            return primitive.WithVertexAccessors(xvertices);
         }
 
-        public static MeshPrimitive WithVertexAccessors<TvP>(this MeshPrimitive primitive, IReadOnlyList<TvP> vertices)
-            where TvP : struct, Geometry.VertexTypes.IVertexGeometry
+        public static MeshPrimitive WithVertexAccessors<TvP, TvM>(this MeshPrimitive primitive, IReadOnlyList<(TvP, TvM)> vertices)
+            where TvP : struct, IVertexGeometry
+            where TvM : struct, IVertexMaterial
         {
             var xvertices = vertices
-                .Select(item => new Geometry.VertexBuilder<TvP, Geometry.VertexTypes.VertexEmpty, Geometry.VertexTypes.VertexEmpty>(item))
+                .Select(item => new VertexBuilder<TvP, TvM, VertexEmpty>(item.Item1, item.Item2))
                 .ToList();
 
             return primitive.WithVertexAccessors(xvertices);
         }
 
-        public static MeshPrimitive WithVertexAccessors<TvP, TvM>(this MeshPrimitive primitive, IReadOnlyList<(TvP, TvM)> vertices)
-            where TvP : struct, Geometry.VertexTypes.IVertexGeometry
-            where TvM : struct, Geometry.VertexTypes.IVertexMaterial
+        public static MeshPrimitive WithVertexAccessors<TvP, TvM, TvS>(this MeshPrimitive primitive, IReadOnlyList<(TvP, TvM, TvS)> vertices)
+            where TvP : struct, IVertexGeometry
+            where TvM : struct, IVertexMaterial
+            where TvS : struct, IVertexSkinning
         {
             var xvertices = vertices
-                .Select(item => new Geometry.VertexBuilder<TvP, TvM, Geometry.VertexTypes.VertexEmpty>(item.Item1, item.Item2))
+                .Select(item => new VertexBuilder<TvP, TvM, TvS>(item.Item1, item.Item2, item.Item3))
                 .ToList();
 
             return primitive.WithVertexAccessors(xvertices);
         }
 
-        public static MeshPrimitive WithVertexAccessors<TvP, TvM, TvS>(this MeshPrimitive primitive, IReadOnlyList<Geometry.VertexBuilder<TvP, TvM, TvS>> vertices)
-            where TvP : struct, Geometry.VertexTypes.IVertexGeometry
-            where TvM : struct, Geometry.VertexTypes.IVertexMaterial
-            where TvS : struct, Geometry.VertexTypes.IVertexSkinning
+        public static MeshPrimitive WithVertexAccessors<TVertex>(this MeshPrimitive primitive, IReadOnlyList<TVertex> vertices)
+            where TVertex : IVertexBuilder
         {
-            var memAccessors = Geometry.VertexTypes.VertexUtils.CreateVertexMemoryAccessors(new[] { vertices }).First();
+            var memAccessors = VertexUtils.CreateVertexMemoryAccessors(new[] { vertices }).First();
 
             return primitive.WithVertexAccessors(memAccessors);
         }