Selaa lähdekoodia

some more API changes
+ documentation

Vicente Penades 6 vuotta sitten
vanhempi
sitoutus
40f6e7e2c7

+ 19 - 5
README.md

@@ -1,12 +1,26 @@
-# SharpGLTF
+<p align="center">
+<img src="build/Icons/glTF2Sharp.png" height=128 />
+</p>
 
 
-SharpGLTF is a NetStandard 2.0, C# library designed to parse and create [Khronos Group glTF 2.0](https://github.com/KhronosGroup/glTF) files.
+---
+
+### Overview
+
+SharpGLTF is a NetStandard 2.0, .NET library designed to support
+[Khronos Group glTF 2.0](https://github.com/KhronosGroup/glTF) file format.
 
 
 The current status of the library is preview alpha, but, for some use cases it is already usable.
 The current status of the library is preview alpha, but, for some use cases it is already usable.
 
 
-Prerelease Nuget packages available [here.](https://www.nuget.org/packages/SharpGLTF)
+#### Design
+
+The framework is divided in two packages:
+
+- __SharpGLTF.Core__ provides the core glTF2 schema implementation, read & write operations,
+and low level API access to let direct document manipulation.
+- __SharpGLTF.Toolkit__ provides an abstraction layer over the Core package, adding convenient
+extensions and utilities to help creating meshes, materials and scenes.
 
 
-### Examples
+#### Examples
 
 
 - [Load and save glTF and GLB files.](https://github.com/vpenades/SharpGLTF/blob/3dfe005ba7210c8327867127681a2b39aa567412/tests/SharpGLTF.Tests/Schema2/LoadAndSave/LoadSampleTests.cs#L32)
 - [Load and save glTF and GLB files.](https://github.com/vpenades/SharpGLTF/blob/3dfe005ba7210c8327867127681a2b39aa567412/tests/SharpGLTF.Tests/Schema2/LoadAndSave/LoadSampleTests.cs#L32)
 - [Create a simple triangle.](https://github.com/vpenades/SharpGLTF/blob/3dfe005ba7210c8327867127681a2b39aa567412/tests/SharpGLTF.Tests/Schema2/Authoring/BasicSceneCreationTests.cs#L95)
 - [Create a simple triangle.](https://github.com/vpenades/SharpGLTF/blob/3dfe005ba7210c8327867127681a2b39aa567412/tests/SharpGLTF.Tests/Schema2/Authoring/BasicSceneCreationTests.cs#L95)
@@ -26,7 +40,7 @@ Prerelease Nuget packages available [here.](https://www.nuget.org/packages/Sharp
 - [x] Reading Base64 encoded buffers.
 - [x] Reading Base64 encoded buffers.
 - [x] Support of merging buffers to write one buffer *.glb* files.
 - [x] Support of merging buffers to write one buffer *.glb* files.
 
 
-#### ToDo:
+#### To do:
 - [ ] Writing Base64 encoded buffers.
 - [ ] Writing Base64 encoded buffers.
 - [ ] Scene Evaluation.
 - [ ] Scene Evaluation.
 - [ ] GPU Evaluation.
 - [ ] GPU Evaluation.

+ 1 - 1
src/SharpGLTF.Core/Schema2/gltf.MaterialsFactory.cs

@@ -150,7 +150,7 @@ namespace SharpGLTF.Schema2
             {
             {
                 return new Vector4
                 return new Vector4
                     (
                     (
-                    (float) _metallicFactor.AsValue( _metallicFactorDefault),
+                    (float)_metallicFactor.AsValue( _metallicFactorDefault),
                     (float)_roughnessFactor.AsValue(_roughnessFactorDefault),
                     (float)_roughnessFactor.AsValue(_roughnessFactorDefault),
                     0,
                     0,
                     0
                     0

+ 27 - 27
src/SharpGLTF.Toolkit/Geometry/MeshBuilder.cs

@@ -12,7 +12,7 @@ namespace SharpGLTF.Geometry
     /// <summary>
     /// <summary>
     /// Represents an utility class to help build mesh primitives by adding triangles
     /// Represents an utility class to help build mesh primitives by adding triangles
     /// </summary>
     /// </summary>
-    /// <typeparam name="TMaterial">The material type used by this <see cref="PrimitiveBuilder{TMaterial, TvP, TvM, TvJ}"/> instance.</typeparam>
+    /// <typeparam name="TMaterial">The material type used by this <see cref="PrimitiveBuilder{TMaterial, TvP, TvM, JvS}"/> instance.</typeparam>
     /// <typeparam name="TvP">
     /// <typeparam name="TvP">
     /// The vertex fragment type with Position, Normal and Tangent.
     /// The vertex fragment type with Position, Normal and Tangent.
     /// Valid types are:
     /// Valid types are:
@@ -28,7 +28,7 @@ namespace SharpGLTF.Geometry
     /// <see cref="VertexTexture1"/>,
     /// <see cref="VertexTexture1"/>,
     /// <see cref="VertexColor1Texture1"/>.
     /// <see cref="VertexColor1Texture1"/>.
     /// </typeparam>
     /// </typeparam>
-    /// <typeparam name="TvJ">
+    /// <typeparam name="JvS">
     /// The vertex fragment type with Skin Joint Weights.
     /// The vertex fragment type with Skin Joint Weights.
     /// Valid types are:
     /// Valid types are:
     /// <see cref="VertexEmpty"/>,
     /// <see cref="VertexEmpty"/>,
@@ -37,14 +37,14 @@ namespace SharpGLTF.Geometry
     /// <see cref="VertexJoints16x4"/>,
     /// <see cref="VertexJoints16x4"/>,
     /// <see cref="VertexJoints16x8"/>.
     /// <see cref="VertexJoints16x8"/>.
     /// </typeparam>
     /// </typeparam>
-    public class PrimitiveBuilder<TMaterial, TvP, TvM, TvJ>
+    public class PrimitiveBuilder<TMaterial, TvP, TvM, JvS>
         where TvP : struct, IVertexPosition
         where TvP : struct, IVertexPosition
         where TvM : struct, IVertexMaterial
         where TvM : struct, IVertexMaterial
-        where TvJ : struct, IVertexJoints
+        where JvS : struct, IVertexSkinning
     {
     {
         #region lifecycle
         #region lifecycle
 
 
-        internal PrimitiveBuilder(MeshBuilder<TMaterial, TvP, TvM, TvJ> mesh, TMaterial material, bool strict)
+        internal PrimitiveBuilder(MeshBuilder<TMaterial, TvP, TvM, JvS> mesh, TMaterial material, bool strict)
         {
         {
             this._Scrict = strict;
             this._Scrict = strict;
             this._Mesh = mesh;
             this._Mesh = mesh;
@@ -57,22 +57,22 @@ namespace SharpGLTF.Geometry
 
 
         private readonly bool _Scrict;
         private readonly bool _Scrict;
 
 
-        private readonly MeshBuilder<TMaterial, TvP, TvM, TvJ> _Mesh;
+        private readonly MeshBuilder<TMaterial, TvP, TvM, JvS> _Mesh;
 
 
         private readonly TMaterial _Material;
         private readonly TMaterial _Material;
 
 
-        private readonly VertexList<(TvP, TvM, TvJ)> _Vertices = new VertexList<(TvP, TvM, TvJ)>();
+        private readonly VertexList<(TvP, TvM, JvS)> _Vertices = new VertexList<(TvP, TvM, JvS)>();
         private readonly List<int> _Indices = new List<int>();
         private readonly List<int> _Indices = new List<int>();
 
 
         #endregion
         #endregion
 
 
         #region properties
         #region properties
 
 
-        public MeshBuilder<TMaterial, TvP, TvM, TvJ> Mesh => _Mesh;
+        public MeshBuilder<TMaterial, TvP, TvM, JvS> Mesh => _Mesh;
 
 
         public TMaterial Material => _Material;
         public TMaterial Material => _Material;
 
 
-        public IReadOnlyList<(TvP, TvM, TvJ)> Vertices => _Vertices;
+        public IReadOnlyList<(TvP, TvM, JvS)> Vertices => _Vertices;
 
 
         public IReadOnlyList<int> Indices => _Indices;
         public IReadOnlyList<int> Indices => _Indices;
 
 
@@ -91,7 +91,7 @@ namespace SharpGLTF.Geometry
 
 
         #region API
         #region API
 
 
-        public int UseVertex((TvP, TvM, TvJ) vertex)
+        public int UseVertex((TvP, TvM, JvS) vertex)
         {
         {
             if (_Scrict)
             if (_Scrict)
             {
             {
@@ -103,7 +103,7 @@ namespace SharpGLTF.Geometry
             return _Vertices.Use(vertex);
             return _Vertices.Use(vertex);
         }
         }
 
 
-        public void AddTriangle((TvP, TvM, TvJ) a, (TvP, TvM, TvJ) b, (TvP, TvM, TvJ) c)
+        public void AddTriangle((TvP, TvM, JvS) a, (TvP, TvM, JvS) b, (TvP, TvM, JvS) c)
         {
         {
             var aa = UseVertex(a);
             var aa = UseVertex(a);
             var bb = UseVertex(b);
             var bb = UseVertex(b);
@@ -126,7 +126,7 @@ namespace SharpGLTF.Geometry
             AddTriangle((a.Item1, a.Item2, default), (b.Item1, b.Item2, default), (c.Item1, c.Item2, default));
             AddTriangle((a.Item1, a.Item2, default), (b.Item1, b.Item2, default), (c.Item1, c.Item2, default));
         }
         }
 
 
-        public void AddTriangle((TvP, TvJ) a, (TvP, TvJ) b, (TvP, TvJ) c)
+        public void AddTriangle((TvP, JvS) a, (TvP, JvS) b, (TvP, JvS) c)
         {
         {
             AddTriangle((a.Item1, default, a.Item2), (b.Item1, default, b.Item2), (c.Item1, default, c.Item2));
             AddTriangle((a.Item1, default, a.Item2), (b.Item1, default, b.Item2), (c.Item1, default, c.Item2));
         }
         }
@@ -136,7 +136,7 @@ namespace SharpGLTF.Geometry
             AddTriangle((a, default, default), (b, default, default), (c, default, default));
             AddTriangle((a, default, default), (b, default, default), (c, default, default));
         }
         }
 
 
-        public void AddPolygon(params (TvP, TvM, TvJ)[] points)
+        public void AddPolygon(params (TvP, TvM, JvS)[] points)
         {
         {
             for (int i = 2; i < points.Length; ++i)
             for (int i = 2; i < points.Length; ++i)
             {
             {
@@ -152,7 +152,7 @@ namespace SharpGLTF.Geometry
             }
             }
         }
         }
 
 
-        public void AddPolygon(params (TvP, TvJ)[] points)
+        public void AddPolygon(params (TvP, JvS)[] points)
         {
         {
             for (int i = 2; i < points.Length; ++i)
             for (int i = 2; i < points.Length; ++i)
             {
             {
@@ -168,7 +168,7 @@ namespace SharpGLTF.Geometry
             }
             }
         }
         }
 
 
-        public void AddPrimitive(PrimitiveBuilder<TMaterial, TvP, TvM, TvJ> primitive, Matrix4x4 transform)
+        public void AddPrimitive(PrimitiveBuilder<TMaterial, TvP, TvM, JvS> primitive, Matrix4x4 transform)
         {
         {
             if (primitive == null) throw new ArgumentNullException(nameof(primitive));
             if (primitive == null) throw new ArgumentNullException(nameof(primitive));
 
 
@@ -202,7 +202,7 @@ namespace SharpGLTF.Geometry
     /// <summary>
     /// <summary>
     /// Represents an utility class to help build meshes by adding primitives associated with a given material.
     /// Represents an utility class to help build meshes by adding primitives associated with a given material.
     /// </summary>
     /// </summary>
-    /// <typeparam name="TMaterial">The material type used by this <see cref="PrimitiveBuilder{TMaterial, TvP, TvM, TvJ}"/> instance.</typeparam>
+    /// <typeparam name="TMaterial">The material type used by this <see cref="PrimitiveBuilder{TMaterial, TvP, TvM, JvS}"/> instance.</typeparam>
     /// <typeparam name="TvP">
     /// <typeparam name="TvP">
     /// The vertex fragment type with Position, Normal and Tangent.
     /// The vertex fragment type with Position, Normal and Tangent.
     /// Valid types are:
     /// Valid types are:
@@ -218,7 +218,7 @@ namespace SharpGLTF.Geometry
     /// <see cref="VertexTexture1"/>,
     /// <see cref="VertexTexture1"/>,
     /// <see cref="VertexColor1Texture1"/>.
     /// <see cref="VertexColor1Texture1"/>.
     /// </typeparam>
     /// </typeparam>
-    /// <typeparam name="TvJ">
+    /// <typeparam name="JvS">
     /// The vertex fragment type with Skin Joint Weights.
     /// The vertex fragment type with Skin Joint Weights.
     /// Valid types are:
     /// Valid types are:
     /// <see cref="VertexEmpty"/>,
     /// <see cref="VertexEmpty"/>,
@@ -227,10 +227,10 @@ namespace SharpGLTF.Geometry
     /// <see cref="VertexJoints16x4"/>,
     /// <see cref="VertexJoints16x4"/>,
     /// <see cref="VertexJoints16x8"/>.
     /// <see cref="VertexJoints16x8"/>.
     /// </typeparam>
     /// </typeparam>
-    public class MeshBuilder<TMaterial, TvP, TvM, TvJ>
+    public class MeshBuilder<TMaterial, TvP, TvM, JvS>
         where TvP : struct, IVertexPosition
         where TvP : struct, IVertexPosition
         where TvM : struct, IVertexMaterial
         where TvM : struct, IVertexMaterial
-        where TvJ : struct, IVertexJoints
+        where JvS : struct, IVertexSkinning
     {
     {
         #region lifecycle
         #region lifecycle
 
 
@@ -243,7 +243,7 @@ namespace SharpGLTF.Geometry
 
 
         #region data
         #region data
 
 
-        private readonly Dictionary<TMaterial, PrimitiveBuilder<TMaterial, TvP, TvM, TvJ>> _Primitives = new Dictionary<TMaterial, PrimitiveBuilder<TMaterial, TvP, TvM, TvJ>>();
+        private readonly Dictionary<TMaterial, PrimitiveBuilder<TMaterial, TvP, TvM, JvS>> _Primitives = new Dictionary<TMaterial, PrimitiveBuilder<TMaterial, TvP, TvM, JvS>>();
 
 
         #endregion
         #endregion
 
 
@@ -253,17 +253,17 @@ namespace SharpGLTF.Geometry
 
 
         public string Name { get; set; }
         public string Name { get; set; }
 
 
-        public IReadOnlyCollection<PrimitiveBuilder<TMaterial, TvP, TvM, TvJ>> Primitives => _Primitives.Values;
+        public IReadOnlyCollection<PrimitiveBuilder<TMaterial, TvP, TvM, JvS>> Primitives => _Primitives.Values;
 
 
         #endregion
         #endregion
 
 
         #region API
         #region API
 
 
-        public PrimitiveBuilder<TMaterial, TvP, TvM, TvJ> UsePrimitive(TMaterial material)
+        public PrimitiveBuilder<TMaterial, TvP, TvM, JvS> UsePrimitive(TMaterial material)
         {
         {
-            if (!_Primitives.TryGetValue(material, out PrimitiveBuilder<TMaterial, TvP, TvM, TvJ> primitive))
+            if (!_Primitives.TryGetValue(material, out PrimitiveBuilder<TMaterial, TvP, TvM, JvS> primitive))
             {
             {
-                primitive = new PrimitiveBuilder<TMaterial, TvP, TvM, TvJ>(this, material, StrictMode);
+                primitive = new PrimitiveBuilder<TMaterial, TvP, TvM, JvS>(this, material, StrictMode);
                 _Primitives[material] = primitive;
                 _Primitives[material] = primitive;
             }
             }
 
 
@@ -272,19 +272,19 @@ namespace SharpGLTF.Geometry
 
 
         public IEnumerable<(int, int, int)> GetTriangles(TMaterial material)
         public IEnumerable<(int, int, int)> GetTriangles(TMaterial material)
         {
         {
-            if (_Primitives.TryGetValue(material, out PrimitiveBuilder<TMaterial, TvP, TvM, TvJ> primitive)) return primitive.Triangles;
+            if (_Primitives.TryGetValue(material, out PrimitiveBuilder<TMaterial, TvP, TvM, JvS> primitive)) return primitive.Triangles;
 
 
             return Enumerable.Empty<(int, int, int)>();
             return Enumerable.Empty<(int, int, int)>();
         }
         }
 
 
         public IReadOnlyList<int> GetIndices(TMaterial material)
         public IReadOnlyList<int> GetIndices(TMaterial material)
         {
         {
-            if (_Primitives.TryGetValue(material, out PrimitiveBuilder<TMaterial, TvP, TvM, TvJ> primitive)) return primitive.Indices;
+            if (_Primitives.TryGetValue(material, out PrimitiveBuilder<TMaterial, TvP, TvM, JvS> primitive)) return primitive.Indices;
 
 
             return new int[0];
             return new int[0];
         }
         }
 
 
-        public void AddMesh(MeshBuilder<TMaterial, TvP, TvM, TvJ> mesh, Matrix4x4 transform)
+        public void AddMesh(MeshBuilder<TMaterial, TvP, TvM, JvS> mesh, Matrix4x4 transform)
         {
         {
             foreach (var p in mesh.Primitives)
             foreach (var p in mesh.Primitives)
             {
             {

+ 6 - 6
src/SharpGLTF.Toolkit/Geometry/PackedMeshBuilder.cs

@@ -8,7 +8,7 @@ namespace SharpGLTF.Geometry
     using Schema2;
     using Schema2;
 
 
     /// <summary>
     /// <summary>
-    /// Used internally to convert a <see cref="MeshBuilder{TMaterial, TvP, TvM, TvJ}"/>
+    /// Used internally to convert a <see cref="MeshBuilder{TMaterial, TvP, TvM, JvS}"/>
     /// to <see cref="Schema2.Mesh"/>.
     /// to <see cref="Schema2.Mesh"/>.
     /// </summary>
     /// </summary>
     /// <typeparam name="TMaterial">A material key to split primitives by material.</typeparam>
     /// <typeparam name="TMaterial">A material key to split primitives by material.</typeparam>
@@ -17,19 +17,19 @@ namespace SharpGLTF.Geometry
         #region lifecycle
         #region lifecycle
 
 
         /// <summary>
         /// <summary>
-        /// Converts a collection of <see cref="MeshBuilder{TMaterial, TvP, TvM, TvJ}"/>
+        /// Converts a collection of <see cref="MeshBuilder{TMaterial, TvP, TvM, JvS}"/>
         /// to a collection of <see cref="PackedMeshBuilder{TMaterial}"/>, trying to use
         /// to a collection of <see cref="PackedMeshBuilder{TMaterial}"/>, trying to use
         /// a single vertex buffer and a single index buffer shared by all meshes.
         /// a single vertex buffer and a single index buffer shared by all meshes.
         /// </summary>
         /// </summary>
         /// <typeparam name="TvP">The vertex fragment type with Position, Normal and Tangent.</typeparam>
         /// <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="TvM">The vertex fragment type with Colors and Texture Coordinates.</typeparam>
-        /// <typeparam name="TvJ">The vertex fragment type with Skin Joint Weights.</typeparam>
-        /// <param name="meshBuilders">A collection of <see cref="MeshBuilder{TMaterial, TvP, TvM, TvJ}"/> instances.</param>
+        /// <typeparam name="JvS">The vertex fragment type with Skin Joint Weights.</typeparam>
+        /// <param name="meshBuilders">A collection of <see cref="MeshBuilder{TMaterial, TvP, TvM, JvS}"/> instances.</param>
         /// <returns>A collection of <see cref="PackedMeshBuilder{TMaterial}"/> instances.</returns>
         /// <returns>A collection of <see cref="PackedMeshBuilder{TMaterial}"/> instances.</returns>
-        internal static IEnumerable<PackedMeshBuilder<TMaterial>> PackMeshes<TvP, TvM, TvJ>(IEnumerable<MeshBuilder<TMaterial, TvP, TvM, TvJ>> meshBuilders)
+        internal static IEnumerable<PackedMeshBuilder<TMaterial>> PackMeshes<TvP, TvM, JvS>(IEnumerable<MeshBuilder<TMaterial, TvP, TvM, JvS>> meshBuilders)
             where TvP : struct, VertexTypes.IVertexPosition
             where TvP : struct, VertexTypes.IVertexPosition
             where TvM : struct, VertexTypes.IVertexMaterial
             where TvM : struct, VertexTypes.IVertexMaterial
-            where TvJ : struct, VertexTypes.IVertexJoints
+            where JvS : struct, VertexTypes.IVertexSkinning
         {
         {
             try
             try
             {
             {

+ 3 - 3
src/SharpGLTF.Toolkit/Geometry/StaticMeshBuilder.cs

@@ -26,7 +26,7 @@ namespace SharpGLTF.Geometry
     /// <see cref="VertexTexture1"/>,
     /// <see cref="VertexTexture1"/>,
     /// <see cref="VertexColor1Texture1"/>.
     /// <see cref="VertexColor1Texture1"/>.
     /// </typeparam>
     /// </typeparam>
-    /// <typeparam name="TvJ">
+    /// <typeparam name="JvS">
     /// The vertex fragment type with Skin Joint Weights.
     /// The vertex fragment type with Skin Joint Weights.
     /// Valid types are:
     /// Valid types are:
     /// <see cref="VertexEmpty"/>,
     /// <see cref="VertexEmpty"/>,
@@ -35,10 +35,10 @@ namespace SharpGLTF.Geometry
     /// <see cref="VertexJoints16x4"/>,
     /// <see cref="VertexJoints16x4"/>,
     /// <see cref="VertexJoints16x8"/>.
     /// <see cref="VertexJoints16x8"/>.
     /// </typeparam>
     /// </typeparam>
-    public class MeshBuilder<TvP, TvM, TvJ> : MeshBuilder<Materials.MaterialBuilder, TvP, TvM, TvJ>
+    public class MeshBuilder<TvP, TvM, JvS> : MeshBuilder<Materials.MaterialBuilder, TvP, TvM, JvS>
         where TvP : struct, IVertexPosition
         where TvP : struct, IVertexPosition
         where TvM : struct, IVertexMaterial
         where TvM : struct, IVertexMaterial
-        where TvJ : struct, IVertexJoints
+        where JvS : struct, IVertexSkinning
     {
     {
         public MeshBuilder(string name = null)
         public MeshBuilder(string name = null)
             : base(name) { }
             : base(name) { }

+ 3 - 3
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexColumns.cs

@@ -67,10 +67,10 @@ namespace SharpGLTF.Geometry.VertexTypes
             return cctt;
             return cctt;
         }
         }
 
 
-        public TvJ GetJointsFragment<TvJ>(int index)
-            where TvJ : struct, IVertexJoints
+        public JvS GetJointsFragment<JvS>(int index)
+            where JvS : struct, IVertexSkinning
         {
         {
-            var jjjj = default(TvJ);
+            var jjjj = default(JvS);
 
 
             if (Joints0 != null && Weights0 != null) jjjj.SetJoints(0, Joints0[index], Weights0[index]);
             if (Joints0 != null && Weights0 != null) jjjj.SetJoints(0, Joints0[index], Weights0[index]);
             if (Joints1 != null && Weights1 != null) jjjj.SetJoints(1, Joints1[index], Weights1[index]);
             if (Joints1 != null && Weights1 != null) jjjj.SetJoints(1, Joints1[index], Weights1[index]);

+ 2 - 2
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexEmpty.cs

@@ -5,7 +5,7 @@ using System.Text;
 
 
 namespace SharpGLTF.Geometry.VertexTypes
 namespace SharpGLTF.Geometry.VertexTypes
 {
 {
-    public struct VertexEmpty : IVertexMaterial, IVertexJoints
+    public struct VertexEmpty : IVertexMaterial, IVertexSkinning
     {
     {
         void IVertexMaterial.SetColor(int setIndex, Vector4 color)
         void IVertexMaterial.SetColor(int setIndex, Vector4 color)
         {
         {
@@ -15,7 +15,7 @@ namespace SharpGLTF.Geometry.VertexTypes
         {
         {
         }
         }
 
 
-        void IVertexJoints.SetJoints(int jointSet, Vector4 joints, Vector4 weights)
+        void IVertexSkinning.SetJoints(int jointSet, Vector4 joints, Vector4 weights)
         {
         {
         }
         }
 
 

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

@@ -99,4 +99,93 @@ namespace SharpGLTF.Geometry.VertexTypes
             if (!TexCoord._IsReal()) throw new NotFiniteNumberException(nameof(TexCoord));
             if (!TexCoord._IsReal()) throw new NotFiniteNumberException(nameof(TexCoord));
         }
         }
     }
     }
+
+    /// <summary>
+    /// Defines a Vertex attribute with a Color material and two Texture Coordinates.
+    /// </summary>
+    public struct VertexColor1Texture2 : IVertexMaterial
+    {
+        public VertexColor1Texture2(Vector4 color, Vector2 tex0, Vector2 tex1)
+        {
+            Color = color;
+            TexCoord0 = tex0;
+            TexCoord1 = tex1;
+        }
+
+        [VertexAttribute("COLOR_0", Schema2.EncodingType.UNSIGNED_BYTE, true)]
+        public Vector4 Color;
+
+        [VertexAttribute("TEXCOORD_0")]
+        public Vector2 TexCoord0;
+
+        [VertexAttribute("TEXCOORD_1")]
+        public Vector2 TexCoord1;
+
+        void IVertexMaterial.SetColor(int setIndex, Vector4 color) { if (setIndex == 0) this.Color = color; }
+
+        void IVertexMaterial.SetTexCoord(int setIndex, Vector2 coord)
+        {
+            if (setIndex == 0) this.TexCoord0 = coord;
+            if (setIndex == 1) this.TexCoord1 = coord;
+        }
+
+        public void Validate()
+        {
+            if (!Color._IsReal()) throw new NotFiniteNumberException(nameof(Color));
+            if (!Color.IsInRange(Vector4.Zero, Vector4.One)) throw new IndexOutOfRangeException(nameof(Color));
+
+            if (!TexCoord0._IsReal()) throw new NotFiniteNumberException(nameof(TexCoord0));
+            if (!TexCoord1._IsReal()) throw new NotFiniteNumberException(nameof(TexCoord1));
+        }
+    }
+
+    /// <summary>
+    /// Defines a Vertex attribute with a Color material and two Texture Coordinates.
+    /// </summary>
+    public struct VertexColor2Texture2 : IVertexMaterial
+    {
+        public VertexColor2Texture2(Vector4 color0, Vector4 color1, Vector2 tex0, Vector2 tex1)
+        {
+            Color0 = color0;
+            Color1 = color1;
+            TexCoord0 = tex0;
+            TexCoord1 = tex1;
+        }
+
+        [VertexAttribute("COLOR_0", Schema2.EncodingType.UNSIGNED_BYTE, true)]
+        public Vector4 Color0;
+
+        [VertexAttribute("COLOR_1", Schema2.EncodingType.UNSIGNED_BYTE, true)]
+        public Vector4 Color1;
+
+        [VertexAttribute("TEXCOORD_0")]
+        public Vector2 TexCoord0;
+
+        [VertexAttribute("TEXCOORD_1")]
+        public Vector2 TexCoord1;
+
+        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;
+        }
+
+        public void Validate()
+        {
+            if (!Color0._IsReal()) throw new NotFiniteNumberException(nameof(Color0));
+            if (!Color0.IsInRange(Vector4.Zero, Vector4.One)) throw new IndexOutOfRangeException(nameof(Color0));
+
+            if (!Color1._IsReal()) throw new NotFiniteNumberException(nameof(Color1));
+            if (!Color1.IsInRange(Vector4.Zero, Vector4.One)) throw new IndexOutOfRangeException(nameof(Color1));
+
+            if (!TexCoord0._IsReal()) throw new NotFiniteNumberException(nameof(TexCoord0));
+            if (!TexCoord1._IsReal()) throw new NotFiniteNumberException(nameof(TexCoord1));
+        }
+    }
 }
 }

+ 9 - 9
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexJoints.cs → src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexSkinning.cs

@@ -5,7 +5,7 @@ using System.Text;
 
 
 namespace SharpGLTF.Geometry.VertexTypes
 namespace SharpGLTF.Geometry.VertexTypes
 {
 {
-    public interface IVertexJoints
+    public interface IVertexSkinning
     {
     {
         void SetJoints(int jointSet, Vector4 joints, Vector4 weights);
         void SetJoints(int jointSet, Vector4 joints, Vector4 weights);
 
 
@@ -15,7 +15,7 @@ namespace SharpGLTF.Geometry.VertexTypes
     /// <summary>
     /// <summary>
     /// Defines a Vertex attribute with up to 256 bone joints and 4 weights.
     /// Defines a Vertex attribute with up to 256 bone joints and 4 weights.
     /// </summary>
     /// </summary>
-    public struct VertexJoints8x4 : IVertexJoints
+    public struct VertexJoints8x4 : IVertexSkinning
     {
     {
         #region constructors
         #region constructors
 
 
@@ -45,7 +45,7 @@ namespace SharpGLTF.Geometry.VertexTypes
 
 
         #region API
         #region API
 
 
-        void IVertexJoints.SetJoints(int jointSet, Vector4 joints, Vector4 weights)
+        void IVertexSkinning.SetJoints(int jointSet, Vector4 joints, Vector4 weights)
         {
         {
             if (jointSet == 0) { this.Joints = joints; this.Weights = weights; }
             if (jointSet == 0) { this.Joints = joints; this.Weights = weights; }
         }
         }
@@ -64,7 +64,7 @@ namespace SharpGLTF.Geometry.VertexTypes
     /// <summary>
     /// <summary>
     /// Defines a Vertex attribute with up to 65535 bone joints and 4 weights.
     /// Defines a Vertex attribute with up to 65535 bone joints and 4 weights.
     /// </summary>
     /// </summary>
-    public struct VertexJoints16x4 : IVertexJoints
+    public struct VertexJoints16x4 : IVertexSkinning
     {
     {
         #region constructors
         #region constructors
 
 
@@ -94,7 +94,7 @@ namespace SharpGLTF.Geometry.VertexTypes
 
 
         #region API
         #region API
 
 
-        void IVertexJoints.SetJoints(int jointSet, Vector4 joints, Vector4 weights)
+        void IVertexSkinning.SetJoints(int jointSet, Vector4 joints, Vector4 weights)
         {
         {
             if (jointSet == 0) { this.Joints = joints; this.Weights = weights; }
             if (jointSet == 0) { this.Joints = joints; this.Weights = weights; }
         }
         }
@@ -113,7 +113,7 @@ namespace SharpGLTF.Geometry.VertexTypes
     /// <summary>
     /// <summary>
     /// Defines a Vertex attribute with up to 256 bone joints and 8 weights.
     /// Defines a Vertex attribute with up to 256 bone joints and 8 weights.
     /// </summary>
     /// </summary>
-    public struct VertexJoints8x8 : IVertexJoints
+    public struct VertexJoints8x8 : IVertexSkinning
     {
     {
         #region constructors
         #region constructors
 
 
@@ -153,7 +153,7 @@ namespace SharpGLTF.Geometry.VertexTypes
 
 
         #region API
         #region API
 
 
-        void IVertexJoints.SetJoints(int jointSet, Vector4 joints, Vector4 weights)
+        void IVertexSkinning.SetJoints(int jointSet, Vector4 joints, Vector4 weights)
         {
         {
             if (jointSet == 0) { this.Joints0 = joints; this.Weights0 = weights; }
             if (jointSet == 0) { this.Joints0 = joints; this.Weights0 = weights; }
             if (jointSet == 1) { this.Joints1 = joints; this.Weights1 = weights; }
             if (jointSet == 1) { this.Joints1 = joints; this.Weights1 = weights; }
@@ -177,7 +177,7 @@ namespace SharpGLTF.Geometry.VertexTypes
     /// <summary>
     /// <summary>
     /// Defines a Vertex attribute with up to 65535 bone joints and 8 weights.
     /// Defines a Vertex attribute with up to 65535 bone joints and 8 weights.
     /// </summary>
     /// </summary>
-    public struct VertexJoints16x8 : IVertexJoints
+    public struct VertexJoints16x8 : IVertexSkinning
     {
     {
         #region constructors
         #region constructors
 
 
@@ -217,7 +217,7 @@ namespace SharpGLTF.Geometry.VertexTypes
 
 
         #region API
         #region API
 
 
-        void IVertexJoints.SetJoints(int jointSet, Vector4 joints, Vector4 weights)
+        void IVertexSkinning.SetJoints(int jointSet, Vector4 joints, Vector4 weights)
         {
         {
             if (jointSet == 0) { this.Joints0 = joints; this.Weights0 = weights; }
             if (jointSet == 0) { this.Joints0 = joints; this.Weights0 = weights; }
             if (jointSet == 1) { this.Joints1 = joints; this.Weights1 = weights; }
             if (jointSet == 1) { this.Joints1 = joints; this.Weights1 = weights; }

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

@@ -9,16 +9,16 @@ namespace SharpGLTF.Geometry.VertexTypes
 
 
     static class VertexUtils
     static class VertexUtils
     {
     {
-        public static IEnumerable<MemoryAccessor[]> CreateVertexMemoryAccessors<TvP, TvM, TvJ>(this IEnumerable<IReadOnlyList<(TvP, TvM, TvJ)>> vertexBlocks)
+        public static IEnumerable<MemoryAccessor[]> CreateVertexMemoryAccessors<TvP, TvM, JvS>(this IEnumerable<IReadOnlyList<(TvP, TvM, JvS)>> vertexBlocks)
             where TvP : struct, IVertexPosition
             where TvP : struct, IVertexPosition
             where TvM : struct, IVertexMaterial
             where TvM : struct, IVertexMaterial
-            where TvJ : struct, IVertexJoints
+            where JvS : struct, IVertexSkinning
         {
         {
             // total number of vertices
             // total number of vertices
             var totalCount = vertexBlocks.Sum(item => item.Count);
             var totalCount = vertexBlocks.Sum(item => item.Count);
 
 
             // vertex attributes
             // vertex attributes
-            var attributes = GetVertexAttributes(typeof(TvP), typeof(TvM), typeof(TvJ), totalCount);
+            var attributes = GetVertexAttributes(typeof(TvP), typeof(TvM), typeof(JvS), totalCount);
 
 
             // create master vertex buffer
             // create master vertex buffer
             int byteStride = attributes[0].ByteStride;
             int byteStride = attributes[0].ByteStride;
@@ -35,7 +35,7 @@ namespace SharpGLTF.Geometry.VertexTypes
 
 
                 foreach (var accessor in accessors)
                 foreach (var accessor in accessors)
                 {
                 {
-                    var columnFunc = GetItemValueFunc<TvP, TvM, TvJ>(accessor.Attribute.Name);
+                    var columnFunc = GetItemValueFunc<TvP, TvM, JvS>(accessor.Attribute.Name);
 
 
                     if (accessor.Attribute.Dimensions == Schema2.DimensionType.SCALAR) accessor.Fill(block.GetScalarColumn(columnFunc));
                     if (accessor.Attribute.Dimensions == Schema2.DimensionType.SCALAR) accessor.Fill(block.GetScalarColumn(columnFunc));
                     if (accessor.Attribute.Dimensions == Schema2.DimensionType.VEC2) accessor.Fill(block.GetVector2Column(columnFunc));
                     if (accessor.Attribute.Dimensions == Schema2.DimensionType.VEC2) accessor.Fill(block.GetVector2Column(columnFunc));
@@ -139,7 +139,7 @@ namespace SharpGLTF.Geometry.VertexTypes
             return new MemoryAccessInfo(attribute.Name, 0, 0, 0, dimensions.Value, attribute.Encoding, attribute.Normalized);
             return new MemoryAccessInfo(attribute.Name, 0, 0, 0, dimensions.Value, attribute.Encoding, attribute.Normalized);
         }
         }
 
 
-        private static Func<(TvP, TvM, TvJ), Object> GetItemValueFunc<TvP, TvM, TvJ>(string attributeName)
+        private static Func<(TvP, TvM, JvS), Object> GetItemValueFunc<TvP, TvM, JvS>(string attributeName)
         {
         {
             var finfo = GetVertexField(typeof(TvP), attributeName);
             var finfo = GetVertexField(typeof(TvP), attributeName);
             if (finfo != null) return vertex => finfo.GetValue(vertex.Item1);
             if (finfo != null) return vertex => finfo.GetValue(vertex.Item1);
@@ -147,33 +147,33 @@ namespace SharpGLTF.Geometry.VertexTypes
             finfo = GetVertexField(typeof(TvM), attributeName);
             finfo = GetVertexField(typeof(TvM), attributeName);
             if (finfo != null) return vertex => finfo.GetValue(vertex.Item2);
             if (finfo != null) return vertex => finfo.GetValue(vertex.Item2);
 
 
-            finfo = GetVertexField(typeof(TvJ), attributeName);
+            finfo = GetVertexField(typeof(JvS), attributeName);
             if (finfo != null) return vertex => finfo.GetValue(vertex.Item3);
             if (finfo != null) return vertex => finfo.GetValue(vertex.Item3);
 
 
             throw new NotImplementedException();
             throw new NotImplementedException();
         }
         }
 
 
-        private static Single[] GetScalarColumn<TvP, TvM, TvJ>(this IReadOnlyList<(TvP, TvM, TvJ)> vertices, Func<(TvP, TvM, TvJ), Object> func)
+        private static Single[] GetScalarColumn<TvP, TvM, JvS>(this IReadOnlyList<(TvP, TvM, JvS)> vertices, Func<(TvP, TvM, JvS), Object> func)
         {
         {
-            return GetColumn<TvP, TvM, TvJ, Single>(vertices, func);
+            return GetColumn<TvP, TvM, JvS, Single>(vertices, func);
         }
         }
 
 
-        private static Vector2[] GetVector2Column<TvP, TvM, TvJ>(this IReadOnlyList<(TvP, TvM, TvJ)> vertices, Func<(TvP, TvM, TvJ), Object> func)
+        private static Vector2[] GetVector2Column<TvP, TvM, JvS>(this IReadOnlyList<(TvP, TvM, JvS)> vertices, Func<(TvP, TvM, JvS), Object> func)
         {
         {
-            return GetColumn<TvP, TvM, TvJ, Vector2>(vertices, func);
+            return GetColumn<TvP, TvM, JvS, Vector2>(vertices, func);
         }
         }
 
 
-        private static Vector3[] GetVector3Column<TvP, TvM, TvJ>(this IReadOnlyList<(TvP, TvM, TvJ)> vertices, Func<(TvP, TvM, TvJ), Object> func)
+        private static Vector3[] GetVector3Column<TvP, TvM, JvS>(this IReadOnlyList<(TvP, TvM, JvS)> vertices, Func<(TvP, TvM, JvS), Object> func)
         {
         {
-            return GetColumn<TvP, TvM, TvJ, Vector3>(vertices, func);
+            return GetColumn<TvP, TvM, JvS, Vector3>(vertices, func);
         }
         }
 
 
-        private static Vector4[] GetVector4Column<TvP, TvM, TvJ>(this IReadOnlyList<(TvP, TvM, TvJ)> vertices, Func<(TvP, TvM, TvJ), Object> func)
+        private static Vector4[] GetVector4Column<TvP, TvM, JvS>(this IReadOnlyList<(TvP, TvM, JvS)> vertices, Func<(TvP, TvM, JvS), Object> func)
         {
         {
-            return GetColumn<TvP, TvM, TvJ, Vector4>(vertices, func);
+            return GetColumn<TvP, TvM, JvS, Vector4>(vertices, func);
         }
         }
 
 
-        private static TColumn[] GetColumn<TvP, TvM, TvJ, TColumn>(this IReadOnlyList<(TvP, TvM, TvJ)> vertices, Func<(TvP, TvM, TvJ), Object> func)
+        private static TColumn[] GetColumn<TvP, TvM, JvS, TColumn>(this IReadOnlyList<(TvP, TvM, JvS)> vertices, Func<(TvP, TvM, JvS), Object> func)
         {
         {
             var dst = new TColumn[vertices.Count];
             var dst = new TColumn[vertices.Count];
 
 

+ 56 - 0
src/SharpGLTF.Toolkit/Geometry/VertexTypes/readme.md

@@ -0,0 +1,56 @@
+# Toolkit Vertex API
+
+#### Overview
+
+glTF descrives a vertex buffer as a collection of accessors, where each accessor is described
+with an attribute, a dimension and an encoding.
+
+Also, glTF theoretically allows a huge range of combinations, but in practice, only a very
+narrow number of combinations is valid. this means that glTF runtimes need to carefully
+check the buffers layout.
+
+In order to simplify mesh creation, SharpGLTF Toolkit introduces the concept of
+vertex fragments, not in the sense of OpenGL shaders, but as components that can form
+a full vertex in a vertex buffer.
+
+The table below shows the possible combinations:
+
+|Position|Material|Skinning _(maxBones×weights)_|
+|-|
+|Position|Empty|Empty|
+|Position Normal|Color0|256 ×4
+|Position Normal Tangent|Texture0|256 ×8
+||Color0 Texture0|65536 ×4
+||Color0 Texture0 Texture1|65536 ×8
+||Color0 Color1 Texture0 Texture1|
+
+By using these predefined building blocks, declaring a vertex structure can be
+greatly simplified.
+
+#### Implementation
+
+SharpGLTF Toolkit defines these vertex fragment types
+in `SharpGLTF.Geometry.VertexTypes` namespace:
+  
+- Position
+  - `VertexPosition`
+  - `VertexPositionNormal`
+  - `VertexPositionNormalTangent`
+- Material
+  - `VertexEmpty`
+  - `VertexColor1`
+  - `VertexTexture1`
+  - `VertexColor1Texture1`
+  - `VertexColor1Texture2`
+  - `VertexColor2Texture2`
+- Skinning
+  - `VertexEmpty`
+  - `VertexJoints8x4`
+  - `VertexJoints8x8`
+  - `VertexJoints16x4`
+  - `VertexJoints16x8`
+
+#### Appendix
+
+- [MeshBuilder documentation](../readme.md)
+

+ 95 - 0
src/SharpGLTF.Toolkit/Geometry/readme.md

@@ -0,0 +1,95 @@
+# Toolkit Mesh API
+
+#### Overview
+
+Creating meshes from scratch accessing directly with `SharpGLTF.Schema2`
+namespace API is quite complicated, since it implies creating Buffers,
+Accessors, Primitives and Meshes very carefully.
+
+It's even more complicated if we want to optimize the meshes by arrange
+the vertices in an interleaved layour, or even allowing multiple meshes
+to share a Vertex and Index buffer.
+
+As an alternative to filling meshes directly into the glTF schema,
+SharpGLTF Toolkit provides a MeshBuilder class to simplify mesh creation.
+
+#### Implementation
+
+The most useful class for mesh creation is `class MeshBuilder<TvP, TvM, TvS>`
+where:
+
+- TvP is a Position Vertex Fragment structure.
+- TvM is a Material Vertex Fragment structure.
+- TvS is a Skinning Vertex Fragment structure.
+
+Vertex fragment types are described in [here](VertexTypes/readme.md).
+
+```c#
+// define a Mesh Builder with a Position and a Color.
+var mesh = new MeshBuilder<VertexPosition, VertexColor1, VertexEmpty>("mesh");
+```
+
+`MeshBuilder` groups primitives using a material as a dictionary key.
+The base implementation of `MeshBuilder` allows to pass a templated type as a
+material key:
+
+```c#
+// define a MeshBuilder with "string" material and a vertex with Position and a Color.
+var mesh = new MeshBuilder<String, VertexPosition, VertexColor1, VertexEmpty>("mesh");
+
+mesh.UsePrimitive("Material1").AddTriangle((V1,C1), (V2,C2), (V3,C3));
+mesh.UsePrimitive("Material2").AddTriangle((V1,C1), (V3,C3), (V4,C4));
+```
+
+But the default implementation of `MeshBuilder` uses `MaterialBuilder` as described
+[here](../Materials/readme.md).
+
+```c#
+// define a material:
+var material = new MaterialBuilder("material");
+
+// define a MeshBuilder with a vertex with Position and a Color.
+var mesh = new MeshBuilder<VertexPosition, VertexColor1, VertexEmpty>("mesh");
+
+mesh.UsePrimitive(material).AddTriangle((V1,C1), (V2,C2), (V3,C3));
+mesh.UsePrimitive(material).AddTriangle((V1,C1), (V3,C3), (V4,C4));
+```
+
+Finally, in order to convert a MeshBuilder to a glTF mesh:
+
+```c#
+var mesh1 = new MeshBuilder<VertexPosition, VertexColor1, VertexEmpty>("mesh1");
+// fill mesh1 with geometry
+var mesh2 = new MeshBuilder<VertexPosition, VertexColor1, VertexEmpty>("mesh2");
+// fill mesh2 with geometry
+
+var model = Schema2.ModelRoot.CreateModel();
+
+model.CreateMeshes(mesh1, mesh2);
+```
+
+The interesting thing about `CreateMeshes` is that it is able to batch all the meshes and
+its primitives in a single vertex and index buffer, provided they use equivalent vertex
+structures.
+
+#### Skinning support
+
+Skinning attributes are provided by the third vertex fragment in the `MeshBuilder` definition.
+
+If no skinning is required, a `VertexEmpty` placeholder is used instead.
+
+
+#### Morphing support
+
+Not supported yet.
+
+#### Appendix
+
+- [Vertex Fragments documentation](VertexTypes/readme.md)
+- [Material Builder documentation](../Materials/readme.md)
+
+
+
+
+
+

+ 6 - 2
src/SharpGLTF.Toolkit/Materials/readme.md

@@ -3,7 +3,7 @@
 #### Overview
 #### Overview
 
 
 glTF materials specification has a rather complex architecture,
 glTF materials specification has a rather complex architecture,
-with a number of speciallised objects, plus a good number of extensions.
+with a number of specialized objects, plus a good number of extensions.
 
 
 In order to streamline and simplify access to materials, a Material Build
 In order to streamline and simplify access to materials, a Material Build
 API is provided.
 API is provided.
@@ -23,4 +23,8 @@ element has a different meaning, depending on the kind of channel:
 |BaseColor|Metallic Roughness & Unlit|Red|Green|Blue|Alpha
 |BaseColor|Metallic Roughness & Unlit|Red|Green|Blue|Alpha
 |MetallicRoughness|Metallic Roughness|Metallic Factor|Roughness Factor
 |MetallicRoughness|Metallic Roughness|Metallic Factor|Roughness Factor
 |Diffuse|Specular Glossiness|Diffuse Red|Diffuse Green|Diffuse Blue|Alpha
 |Diffuse|Specular Glossiness|Diffuse Red|Diffuse Green|Diffuse Blue|Alpha
-|SpecularGlossiness|Specular Glossiness|Specular Red|Specular Green|Specular Blue|Glossiness
+|SpecularGlossiness|Specular Glossiness|Specular Red|Specular Green|Specular Blue|Glossiness
+
+#### Implementation
+
+TODO

+ 24 - 24
src/SharpGLTF.Toolkit/Schema2/MeshExtensions.cs

@@ -12,50 +12,50 @@ namespace SharpGLTF.Schema2
     {
     {
         #region meshes
         #region meshes
 
 
-        public static Mesh CreateMesh<TvP, TvM, TvJ>(this ModelRoot root, Geometry.MeshBuilder<Materials.MaterialBuilder, TvP, TvM, TvJ> meshBuilder)
+        public static Mesh CreateMesh<TvP, TvM, JvS>(this ModelRoot root, Geometry.MeshBuilder<Materials.MaterialBuilder, TvP, TvM, JvS> meshBuilder)
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
-            where TvJ : struct, Geometry.VertexTypes.IVertexJoints
+            where JvS : struct, Geometry.VertexTypes.IVertexSkinning
         {
         {
             return root.CreateMeshes(meshBuilder).First();
             return root.CreateMeshes(meshBuilder).First();
         }
         }
 
 
-        public static Mesh CreateMesh<TvP, TvM, TvJ>(this ModelRoot root, Geometry.MeshBuilder<Material, TvP, TvM, TvJ> meshBuilder)
+        public static Mesh CreateMesh<TvP, TvM, JvS>(this ModelRoot root, Geometry.MeshBuilder<Material, TvP, TvM, JvS> meshBuilder)
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
-            where TvJ : struct, Geometry.VertexTypes.IVertexJoints
+            where JvS : struct, Geometry.VertexTypes.IVertexSkinning
         {
         {
             return root.CreateMeshes(meshBuilder).First();
             return root.CreateMeshes(meshBuilder).First();
         }
         }
 
 
-        public static Mesh CreateMesh<TMaterial, TvP, TvM, TvJ>(this ModelRoot root, Func<TMaterial, Material> materialEvaluator, Geometry.MeshBuilder<TMaterial, TvP, TvM, TvJ> meshBuilder)
+        public static Mesh CreateMesh<TMaterial, TvP, TvM, JvS>(this ModelRoot root, Func<TMaterial, Material> materialEvaluator, Geometry.MeshBuilder<TMaterial, TvP, TvM, JvS> meshBuilder)
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
-            where TvJ : struct, Geometry.VertexTypes.IVertexJoints
+            where JvS : struct, Geometry.VertexTypes.IVertexSkinning
         {
         {
             return root.CreateMeshes(materialEvaluator, meshBuilder).First();
             return root.CreateMeshes(materialEvaluator, meshBuilder).First();
         }
         }
 
 
-        public static IReadOnlyList<Mesh> CreateMeshes<TvP, TvM, TvJ>(this ModelRoot root, params Geometry.MeshBuilder<Material, TvP, TvM, TvJ>[] meshBuilders)
+        public static IReadOnlyList<Mesh> CreateMeshes<TvP, TvM, JvS>(this ModelRoot root, params Geometry.MeshBuilder<Material, TvP, TvM, JvS>[] meshBuilders)
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
-            where TvJ : struct, Geometry.VertexTypes.IVertexJoints
+            where JvS : struct, Geometry.VertexTypes.IVertexSkinning
         {
         {
             return root.CreateMeshes(m => m, meshBuilders);
             return root.CreateMeshes(m => m, meshBuilders);
         }
         }
 
 
-        public static IReadOnlyList<Mesh> CreateMeshes<TvP, TvM, TvJ>(this ModelRoot root, params Geometry.MeshBuilder<Materials.MaterialBuilder, TvP, TvM, TvJ>[] meshBuilders)
+        public static IReadOnlyList<Mesh> CreateMeshes<TvP, TvM, JvS>(this ModelRoot root, params Geometry.MeshBuilder<Materials.MaterialBuilder, TvP, TvM, JvS>[] meshBuilders)
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
-            where TvJ : struct, Geometry.VertexTypes.IVertexJoints
+            where JvS : struct, Geometry.VertexTypes.IVertexSkinning
         {
         {
             return root.CreateMeshes(mb => root.CreateMaterial(mb), meshBuilders);
             return root.CreateMeshes(mb => root.CreateMaterial(mb), meshBuilders);
         }
         }
 
 
-        public static IReadOnlyList<Mesh> CreateMeshes<TMaterial, TvP, TvM, TvJ>(this ModelRoot root, Func<TMaterial, Material> materialEvaluator, params Geometry.MeshBuilder<TMaterial, TvP, TvM, TvJ>[] meshBuilders)
+        public static IReadOnlyList<Mesh> CreateMeshes<TMaterial, TvP, TvM, JvS>(this ModelRoot root, Func<TMaterial, Material> materialEvaluator, params Geometry.MeshBuilder<TMaterial, TvP, TvM, JvS>[] meshBuilders)
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
-            where TvJ : struct, Geometry.VertexTypes.IVertexJoints
+            where JvS : struct, Geometry.VertexTypes.IVertexSkinning
         {
         {
             // create a new material for every unique material in the mesh builders.
             // create a new material for every unique material in the mesh builders.
             var mapMaterials = meshBuilders
             var mapMaterials = meshBuilders
@@ -226,7 +226,7 @@ namespace SharpGLTF.Schema2
         public static MeshPrimitive WithVertexAccessors<TVertex, TValues, TJoints>(this MeshPrimitive primitive, IReadOnlyList<(TVertex, TValues, TJoints)> vertices)
         public static MeshPrimitive WithVertexAccessors<TVertex, TValues, TJoints>(this MeshPrimitive primitive, IReadOnlyList<(TVertex, TValues, TJoints)> vertices)
             where TVertex : struct, Geometry.VertexTypes.IVertexPosition
             where TVertex : struct, Geometry.VertexTypes.IVertexPosition
             where TValues : struct, Geometry.VertexTypes.IVertexMaterial
             where TValues : struct, Geometry.VertexTypes.IVertexMaterial
-            where TJoints : struct, Geometry.VertexTypes.IVertexJoints
+            where TJoints : struct, Geometry.VertexTypes.IVertexSkinning
         {
         {
             var memAccessors = Geometry.VertexTypes.VertexUtils.CreateVertexMemoryAccessors(new[] { vertices }).First();
             var memAccessors = Geometry.VertexTypes.VertexUtils.CreateVertexMemoryAccessors(new[] { vertices }).First();
 
 
@@ -277,20 +277,20 @@ namespace SharpGLTF.Schema2
 
 
         #region evaluation
         #region evaluation
 
 
-        public static IEnumerable<((TvP, TvM, TvJ), (TvP, TvM, TvJ), (TvP, TvM, TvJ), Material)> Triangulate<TvP, TvM, TvJ>(this Mesh mesh, Matrix4x4 xform)
+        public static IEnumerable<((TvP, TvM, JvS), (TvP, TvM, JvS), (TvP, TvM, JvS), Material)> Triangulate<TvP, TvM, JvS>(this Mesh mesh, Matrix4x4 xform)
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
-            where TvJ : struct, Geometry.VertexTypes.IVertexJoints
+            where JvS : struct, Geometry.VertexTypes.IVertexSkinning
         {
         {
             var normals = mesh.GetComputedNormals();
             var normals = mesh.GetComputedNormals();
 
 
-            return mesh.Primitives.SelectMany(item => item.Triangulate<TvP, TvM, TvJ>(xform, normals));
+            return mesh.Primitives.SelectMany(item => item.Triangulate<TvP, TvM, JvS>(xform, normals));
         }
         }
 
 
-        public static IEnumerable<((TvP, TvM, TvJ), (TvP, TvM, TvJ), (TvP, TvM, TvJ), Material)> Triangulate<TvP, TvM, TvJ>(this MeshPrimitive prim, Matrix4x4 xform, IReadOnlyDictionary<Vector3, Vector3> defaultNormals)
+        public static IEnumerable<((TvP, TvM, JvS), (TvP, TvM, JvS), (TvP, TvM, JvS), Material)> Triangulate<TvP, TvM, JvS>(this MeshPrimitive prim, Matrix4x4 xform, IReadOnlyDictionary<Vector3, Vector3> defaultNormals)
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
-            where TvJ : struct, Geometry.VertexTypes.IVertexJoints
+            where JvS : struct, Geometry.VertexTypes.IVertexSkinning
         {
         {
             var vertices = prim.GetVertexColumns();
             var vertices = prim.GetVertexColumns();
             if (vertices.Normals == null && defaultNormals != null) vertices.SetNormals(defaultNormals);
             if (vertices.Normals == null && defaultNormals != null) vertices.SetNormals(defaultNormals);
@@ -311,9 +311,9 @@ namespace SharpGLTF.Schema2
                 var bm = vertices.GetMaterialFragment<TvM>(t.Item2);
                 var bm = vertices.GetMaterialFragment<TvM>(t.Item2);
                 var cm = vertices.GetMaterialFragment<TvM>(t.Item3);
                 var cm = vertices.GetMaterialFragment<TvM>(t.Item3);
 
 
-                var aj = vertices.GetJointsFragment<TvJ>(t.Item1);
-                var bj = vertices.GetJointsFragment<TvJ>(t.Item2);
-                var cj = vertices.GetJointsFragment<TvJ>(t.Item3);
+                var aj = vertices.GetJointsFragment<JvS>(t.Item1);
+                var bj = vertices.GetJointsFragment<JvS>(t.Item2);
+                var cj = vertices.GetJointsFragment<JvS>(t.Item3);
 
 
                 yield return ((ap, am, aj), (bp, bm, bj), (cp, cm, cj), prim.Material);
                 yield return ((ap, am, aj), (bp, bm, bj), (cp, cm, cj), prim.Material);
             }
             }
@@ -391,10 +391,10 @@ namespace SharpGLTF.Schema2
             return posnrm;
             return posnrm;
         }
         }
 
 
-        public static void AddMesh<TMaterial, TvP, TvM, TvJ>(this Geometry.MeshBuilder<TMaterial, TvP, TvM, TvJ> meshBuilder, Mesh srcMesh, Matrix4x4 xform, Func<Material, TMaterial> materialFunc)
+        public static void AddMesh<TMaterial, TvP, TvM, JvS>(this Geometry.MeshBuilder<TMaterial, TvP, TvM, JvS> meshBuilder, Mesh srcMesh, Matrix4x4 xform, Func<Material, TMaterial> materialFunc)
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
-            where TvJ : struct, Geometry.VertexTypes.IVertexJoints
+            where JvS : struct, Geometry.VertexTypes.IVertexSkinning
         {
         {
             var normals = srcMesh.GetComputedNormals();
             var normals = srcMesh.GetComputedNormals();
 
 
@@ -402,7 +402,7 @@ namespace SharpGLTF.Schema2
             {
             {
                 var dstPrim = meshBuilder.UsePrimitive(materialFunc(srcPrim.Material));
                 var dstPrim = meshBuilder.UsePrimitive(materialFunc(srcPrim.Material));
 
 
-                foreach (var tri in srcPrim.Triangulate<TvP, TvM, TvJ>(xform, normals))
+                foreach (var tri in srcPrim.Triangulate<TvP, TvM, JvS>(xform, normals))
                 {
                 {
                     dstPrim.AddTriangle(tri.Item1, tri.Item2, tri.Item3);
                     dstPrim.AddTriangle(tri.Item1, tri.Item2, tri.Item3);
                 }
                 }

+ 9 - 9
src/SharpGLTF.Toolkit/Schema2/SceneExtensions.cs

@@ -87,15 +87,15 @@ namespace SharpGLTF.Schema2
         /// </summary>
         /// </summary>
         /// <typeparam name="TvP">The vertex fragment type with Position, Normal and Tangent.</typeparam>
         /// <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="TvM">The vertex fragment type with Colors and Texture Coordinates.</typeparam>
-        /// <typeparam name="TvJ">The vertex fragment type with Skin Joint Weights.</typeparam>
+        /// <typeparam name="JvS">The vertex fragment type with Skin Joint Weights.</typeparam>
         /// <param name="scene">A <see cref="Scene"/> instance.</param>
         /// <param name="scene">A <see cref="Scene"/> instance.</param>
         /// <returns>A collection of triangles in world space.</returns>
         /// <returns>A collection of triangles in world space.</returns>
-        public static IEnumerable<((TvP, TvM, TvJ), (TvP, TvM, TvJ), (TvP, TvM, TvJ), Material)> Triangulate<TvP, TvM, TvJ>(this Scene scene)
+        public static IEnumerable<((TvP, TvM, JvS), (TvP, TvM, JvS), (TvP, TvM, JvS), Material)> Triangulate<TvP, TvM, JvS>(this Scene scene)
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
-            where TvJ : struct, Geometry.VertexTypes.IVertexJoints
+            where JvS : struct, Geometry.VertexTypes.IVertexSkinning
         {
         {
-            return Node.Flatten(scene).SelectMany(item => item.Triangulate<TvP, TvM, TvJ>(true));
+            return Node.Flatten(scene).SelectMany(item => item.Triangulate<TvP, TvM, JvS>(true));
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -104,21 +104,21 @@ namespace SharpGLTF.Schema2
         /// </summary>
         /// </summary>
         /// <typeparam name="TvP">The vertex fragment type with Position, Normal and Tangent.</typeparam>
         /// <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="TvM">The vertex fragment type with Colors and Texture Coordinates.</typeparam>
-        /// <typeparam name="TvJ">The vertex fragment type with Skin Joint Weights.</typeparam>
+        /// <typeparam name="JvS">The vertex fragment type with Skin Joint Weights.</typeparam>
         /// <param name="node">A <see cref="Node"/> instance.</param>
         /// <param name="node">A <see cref="Node"/> instance.</param>
         /// <param name="inWorldSpace">A value indicating whether the returned triangles must be in local (false) or world (true) space.</param>
         /// <param name="inWorldSpace">A value indicating whether the returned triangles must be in local (false) or world (true) space.</param>
         /// <returns>A collection of triangles in local or world space.</returns>
         /// <returns>A collection of triangles in local or world space.</returns>
-        public static IEnumerable<((TvP, TvM, TvJ), (TvP, TvM, TvJ), (TvP, TvM, TvJ), Material)> Triangulate<TvP, TvM, TvJ>(this Node node, bool inWorldSpace)
+        public static IEnumerable<((TvP, TvM, JvS), (TvP, TvM, JvS), (TvP, TvM, JvS), Material)> Triangulate<TvP, TvM, JvS>(this Node node, bool inWorldSpace)
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvP : struct, Geometry.VertexTypes.IVertexPosition
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
             where TvM : struct, Geometry.VertexTypes.IVertexMaterial
-            where TvJ : struct, Geometry.VertexTypes.IVertexJoints
+            where JvS : struct, Geometry.VertexTypes.IVertexSkinning
         {
         {
             var mesh = node.Mesh;
             var mesh = node.Mesh;
-            if (mesh == null) return Enumerable.Empty<((TvP, TvM, TvJ), (TvP, TvM, TvJ), (TvP, TvM, TvJ), Material)>();
+            if (mesh == null) return Enumerable.Empty<((TvP, TvM, JvS), (TvP, TvM, JvS), (TvP, TvM, JvS), Material)>();
 
 
             var xform = inWorldSpace ? node.WorldMatrix : Matrix4x4.Identity;
             var xform = inWorldSpace ? node.WorldMatrix : Matrix4x4.Identity;
 
 
-            return mesh.Triangulate<TvP, TvM, TvJ>(xform);
+            return mesh.Triangulate<TvP, TvM, JvS>(xform);
         }
         }
 
 
         #endregion
         #endregion

+ 31 - 1
tests/SharpGLTF.Tests/AssemblyAPITests.cs

@@ -13,7 +13,37 @@ namespace SharpGLTF
     {
     {
         public class TestClass
         public class TestClass
         {
         {
-            public int xyz(int x, out int y, ref int z) { y = 0; return x + 7; }
+            public int PointerFunc(int x, out int y, ref int z) { y = 0; return x + 7; }
+
+            public void ParamsFunc(int x, params string[] values) { }
+
+            public void MultiArgsFunc(int x, int y=1, int z = 2) { }
+
+            public int[][,][,,] MultiArray;
+
+            public const string Alpha = "Alpha";
+
+            public static readonly string Beta = "Beta";
+
+            public delegate void MyDelegate(int x);
+
+            public MyDelegate DelegateImpl;
+
+            public enum Hello
+            {
+                World = 7
+            }
+
+            public event EventHandler EventX;
+
+            public struct Structure
+            {
+                public int X;
+                public int Y { get; }
+                public int Z { get; set; }
+
+                public System.Numerics.Vector3 Vector;
+            }
         }
         }
 
 
         [Test]
         [Test]

+ 80 - 73
tests/SharpGLTF.Tests/DumpAssemblyAPI.cs

@@ -9,30 +9,16 @@ using static System.FormattableString;
 namespace SharpGLTF
 namespace SharpGLTF
 {
 {
     /// <summary>
     /// <summary>
-    /// Utility class to hopefully compare breaking changes between APIs
+    /// Utility class to dump the public API of an assembly
     /// </summary>
     /// </summary>
     static class DumpAssemblyAPI
     static class DumpAssemblyAPI
     {
     {
         // https://www.hanselman.com/blog/ManagingChangeWithNETAssemblyDiffTools.aspx
         // https://www.hanselman.com/blog/ManagingChangeWithNETAssemblyDiffTools.aspx
 
 
-        // proposed reporting lines:
-
-        // Namespace="" Class="" Method=""
-        // Namespace="" Enum="" Constant=""
-        // Namespace="" Class="" Property=""
-        // Namespace="" Class="" Event=""
-
-        // NS foo.bar { STRUCT name        { FIELD name type       } }
-        // NS foo.bar { ABSTRACTCLASS name { PROPERTYGET name type } }
-        // NS foo.bar { ABSTRACTCLASS name { PROTECTEDPROPERTYSET name type } }
-
-        // NamesPace { Class|Struct { Class|Struct|Method|Field } }
-
-
         public static IEnumerable<String> GetAssemblySignature(Assembly assembly)
         public static IEnumerable<String> GetAssemblySignature(Assembly assembly)
         {
         {
             return assembly.ExportedTypes
             return assembly.ExportedTypes
-                .SelectMany(item => GetTypeSignature(item.GetTypeInfo()).Select(l => "NS " + item.Namespace + " { " + l + " } " ) );
+                .SelectMany(item => GetTypeSignature(item.GetTypeInfo()).Select(l => "NS " + item.Namespace + " { " + l + " }" ) );
         }
         }
 
 
         public static IEnumerable<String> GetTypeSignature(TypeInfo tinfo)
         public static IEnumerable<String> GetTypeSignature(TypeInfo tinfo)
@@ -40,7 +26,7 @@ namespace SharpGLTF
             if (tinfo.IsNestedPrivate) yield break;
             if (tinfo.IsNestedPrivate) yield break;
             if (tinfo.IsNestedAssembly) yield break;
             if (tinfo.IsNestedAssembly) yield break;
 
 
-            string baseName = string.Empty;            
+            string baseName = string.Empty;
 
 
             if (tinfo.IsInterface) baseName = "INTERFACE";
             if (tinfo.IsInterface) baseName = "INTERFACE";
             else if (tinfo.IsEnum) baseName = "ENUM";
             else if (tinfo.IsEnum) baseName = "ENUM";
@@ -61,82 +47,90 @@ namespace SharpGLTF
 
 
             baseName += " " + tinfo.GetQualifiedName();
             baseName += " " + tinfo.GetQualifiedName();
 
 
+            if (tinfo.IsEnum)
+            {
+                foreach(var val in Enum.GetValues(tinfo.AsType()))
+                {
+                    yield return baseName + " { " + val + $"={(int)val}" + " }";
+                }
+
+                yield break;
+            }
+
             if (tinfo.IsClass)
             if (tinfo.IsClass)
             {
             {
                 // base classes
                 // base classes
                 var baseType = tinfo.BaseType;
                 var baseType = tinfo.BaseType;
                 while (baseType != null && baseType != typeof(object))
                 while (baseType != null && baseType != typeof(object))
                 {
                 {
-                    yield return baseName + " { USING " + baseType.GetQualifiedName() + " } ";
+                    yield return baseName + " { USING " + baseType.GetQualifiedName() + " }";
                     baseType = baseType.BaseType;
                     baseType = baseType.BaseType;
                 }
                 }
             }
             }
-
-            foreach(var ifaceType in tinfo.GetInterfaces())
+            
+            foreach (var ifaceType in tinfo.GetInterfaces())
             {
             {
                 if (ifaceType.IsNotPublic) continue;
                 if (ifaceType.IsNotPublic) continue;
 
 
-                yield return baseName + " { USING " + ifaceType.GetQualifiedName() + " } ";
+                yield return baseName + " { USING " + ifaceType.GetQualifiedName() + " }";
             }
             }
 
 
-
-            Object instance = null;
-
-            try { instance = Activator.CreateInstance(tinfo); }
-            catch { }
-
             foreach (var m in tinfo.DeclaredMembers)
             foreach (var m in tinfo.DeclaredMembers)
             {
             {
-                var signatures = GetMemberSignature(instance, m);
+                var signatures = GetMemberSignature(m);
                 if (signatures == null) continue;
                 if (signatures == null) continue;
                 foreach (var s in signatures)
                 foreach (var s in signatures)
                 {
                 {
-                    yield return baseName + " { " +  s + " } ";
+                    yield return baseName + " { " +  s + " }";
                 }
                 }
             }            
             }            
         }
         }
 
 
-        public static IEnumerable<string> GetMemberSignature(Object instance, MemberInfo minfo)
+        public static IEnumerable<String> GetMemberSignature(MemberInfo minfo)
         {
         {
-            if (minfo is FieldInfo finfo) return GetFieldSignature(instance, finfo);
+            if (minfo is FieldInfo finfo) return GetFieldSignature(finfo);
 
 
             if (minfo is TypeInfo tinfo) return GetTypeSignature(tinfo);
             if (minfo is TypeInfo tinfo) return GetTypeSignature(tinfo);
 
 
-            if (minfo is PropertyInfo pinfo) return GetPropertySignature(instance, pinfo);
+            if (minfo is PropertyInfo pinfo) return GetPropertySignature(pinfo);
 
 
-            if (minfo is MethodInfo xinfo) return GetMethodSignature(instance, xinfo);
+            if (minfo is MethodInfo xinfo) return GetMethodSignature(xinfo);
 
 
-            if (minfo is ConstructorInfo cinfo) return GetMethodSignature(instance, cinfo);
+            if (minfo is ConstructorInfo cinfo) return GetMethodSignature(cinfo);
+
+            if (minfo is EventInfo einfo) return GetEventSignature(einfo);
 
 
             return null;
             return null;
         }
         }
 
 
-        public static IEnumerable<string> GetFieldSignature(Object instance, FieldInfo finfo)
+        public static IEnumerable<String> GetFieldSignature(FieldInfo finfo)
         {
         {
             if (!IsVisible(finfo)) yield break;
             if (!IsVisible(finfo)) yield break;
 
 
             var name = "FIELD";
             var name = "FIELD";
 
 
             if (finfo.IsLiteral) name += ":CONST";
             if (finfo.IsLiteral) name += ":CONST";
-            if (finfo.IsStatic) name += ":STATIC";
+            else if (finfo.IsStatic) name += ":STATIC";
+
+            if (finfo.IsInitOnly) name += ":READONLY";
 
 
             name += $" {finfo.Name} {finfo.FieldType.GetQualifiedName()}";
             name += $" {finfo.Name} {finfo.FieldType.GetQualifiedName()}";
 
 
-            if (finfo.IsStatic)
-            {
-                var v = finfo.GetValue(null);
-                if (v != null) name += Invariant($"={v}");
-            }
-            else if (instance != null)
-            {
-                var v = finfo.GetValue(instance);
-                if (v != null) name += Invariant($"={v}");
-            }
+            yield return name;
+        }
+
+        public static IEnumerable<String> GetEventSignature(EventInfo einfo)
+        {
+            // if (!IsVisible(einfo)) yield break;
+
+            var name = "EVENT";
+
+            name += $" {einfo.Name} {einfo.EventHandlerType.GetQualifiedName()}";
 
 
             yield return name;
             yield return name;
         }
         }
 
 
-        public static IEnumerable<string> GetPropertySignature(Object instance, PropertyInfo pinfo)
+        public static IEnumerable<String> GetPropertySignature(PropertyInfo pinfo)
         {
         {
             var pname = $"{pinfo.Name} {pinfo.PropertyType.GetQualifiedName()}";
             var pname = $"{pinfo.Name} {pinfo.PropertyType.GetQualifiedName()}";
 
 
@@ -147,10 +141,8 @@ namespace SharpGLTF
             if (IsVisible(setter, true)) yield return "METHOD:SET"+ GetMethodModifiers(setter) +" " + pname;
             if (IsVisible(setter, true)) yield return "METHOD:SET"+ GetMethodModifiers(setter) +" " + pname;
         }
         }
 
 
-        public static IEnumerable<string> GetMethodSignature(Object instance, MethodBase minfo)
+        public static IEnumerable<String> GetMethodSignature(MethodBase minfo)
         {
         {
-            // TODO: if parameters have default values, dump the same method multiple times with one parameter less each time.
-
             string mname = "METHOD";
             string mname = "METHOD";
 
 
             if (minfo is MethodInfo mminfo)
             if (minfo is MethodInfo mminfo)
@@ -158,7 +150,7 @@ namespace SharpGLTF
                 var isExtension = mminfo.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), true);
                 var isExtension = mminfo.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), true);
 
 
                 if (isExtension) mname += ":EXTENSION";
                 if (isExtension) mname += ":EXTENSION";
-                mname += GetMethodModifiers(minfo);
+                else mname += GetMethodModifiers(minfo);
 
 
                 mname += " ";
                 mname += " ";
 
 
@@ -181,7 +173,7 @@ namespace SharpGLTF
             yield return mname + "(" + string.Join(", ", mparams) + ")";
             yield return mname + "(" + string.Join(", ", mparams) + ")";
         }
         }
 
 
-        public static string GetParameterSignature(ParameterInfo pinfo)
+        public static String GetParameterSignature(ParameterInfo pinfo)
         {
         {
             var prefix = string.Empty;
             var prefix = string.Empty;
 
 
@@ -194,21 +186,18 @@ namespace SharpGLTF
                 else prefix += "ref ";
                 else prefix += "ref ";
             }
             }
 
 
-            return prefix + pinfo.ParameterType.GetQualifiedName();
-        }
+            var postfix = string.Empty;
 
 
-        public static bool IsVisible(FieldInfo finfo)
-        {
-            if (finfo == null) return false;
-
-            if (finfo.IsPrivate) return false;
-            if (finfo.IsAssembly) return false;            
-            if (finfo.IsFamilyOrAssembly) return false;
+            if (pinfo.HasDefaultValue)
+            {
+                if (pinfo.DefaultValue == null) postfix = "=null";
+                else postfix = "=" + pinfo.DefaultValue.ToString();
+            }
 
 
-            return true;
-        }
+            return prefix + pinfo.ParameterType.GetQualifiedName() + postfix;
+        }        
 
 
-        public static bool IsVisible(MethodBase minfo, bool withSpecials = false)
+        public static Boolean IsVisible(MethodBase minfo, Boolean withSpecials = false)
         {
         {
             if (minfo == null) return false;
             if (minfo == null) return false;
 
 
@@ -219,9 +208,20 @@ namespace SharpGLTF
             if (minfo.IsFamilyOrAssembly) return false;
             if (minfo.IsFamilyOrAssembly) return false;
 
 
             return true;
             return true;
-        }        
+        }
 
 
-        public static string GetMethodModifiers(MethodBase minfo)
+        public static Boolean IsVisible(FieldInfo finfo)
+        {
+            if (finfo == null) return false;
+
+            if (finfo.IsPrivate) return false;
+            if (finfo.IsAssembly) return false;
+            if (finfo.IsFamilyOrAssembly) return false;
+
+            return true;
+        }
+
+        public static String GetMethodModifiers(MethodBase minfo)
         {
         {
             if (minfo.IsPrivate) return string.Empty;
             if (minfo.IsPrivate) return string.Empty;
 
 
@@ -236,24 +236,31 @@ namespace SharpGLTF
             return mod;
             return mod;
         }
         }
 
 
-        public static string GetQualifiedName(this Type tinfo)
+        public static String GetQualifiedName(this Type tinfo)
         {
         {
             return tinfo.GetTypeInfo().GetQualifiedName();
             return tinfo.GetTypeInfo().GetQualifiedName();
         }
         }
 
 
-        public static string GetQualifiedName(this System.Reflection.TypeInfo tinfo)
+        public static String GetQualifiedName(this TypeInfo tinfo)
         {
         {
-            if (tinfo.IsArray)
+            var postfix = string.Empty;
+
+            // unwrap jagged array
+            while (tinfo.IsArray)
             {
             {
-                var itemName = tinfo.GetElementType().GetQualifiedName();
-                itemName += "[" + string.Join("", Enumerable.Repeat(",", tinfo.GetArrayRank() - 1)) + "]";
-                return itemName;
+                postfix += "[" + string.Join("", Enumerable.Repeat(",", tinfo.GetArrayRank() - 1)) + "]";
+                tinfo = tinfo.GetElementType().GetTypeInfo();                
             }
             }
 
 
             var name = tinfo.Name;
             var name = tinfo.Name;
 
 
-            name = name.Replace("&", ""); // remove PTR semantics
+            // remove pointer semantics
+            name = name.Replace("&", ""); 
+
+            // add jagged array postfix
+            name += postfix;
 
 
+            // handle generic types
             if (tinfo.IsGenericType || tinfo.IsGenericTypeDefinition)
             if (tinfo.IsGenericType || tinfo.IsGenericTypeDefinition)
             {
             {
                 name = name.Replace("`1", "");
                 name = name.Replace("`1", "");