Browse Source

Moving some utilities from core to tookit

Vicente Penades 6 years ago
parent
commit
a1269f98c0

+ 6 - 5
src/SharpGLTF.Toolkit/Geometry/InterleavedMeshBuilder.cs

@@ -97,9 +97,9 @@ namespace SharpGLTF.Geometry
 
 
                 var field = VertexUtils.GetVertexField(typeof(TVertex), attribute.Name);
                 var field = VertexUtils.GetVertexField(typeof(TVertex), attribute.Name);
 
 
-                if (field.FieldType == typeof(Vector2)) accessor.WithVertexData(vbuffer, attribute.ByteOffset, field.GetVector2Column(_Vertices), attribute.Encoding, attribute.Normalized);
-                if (field.FieldType == typeof(Vector3)) accessor.WithVertexData(vbuffer, attribute.ByteOffset, field.GetVector3Column(_Vertices), attribute.Encoding, attribute.Normalized);
-                if (field.FieldType == typeof(Vector4)) accessor.WithVertexData(vbuffer, attribute.ByteOffset, field.GetVector4Column(_Vertices), attribute.Encoding, attribute.Normalized);
+                if (field.FieldType == typeof(Vector2)) accessor.SetVertexData(vbuffer, attribute.ByteOffset, field.GetVector2Column(_Vertices), attribute.Encoding, attribute.Normalized);
+                if (field.FieldType == typeof(Vector3)) accessor.SetVertexData(vbuffer, attribute.ByteOffset, field.GetVector3Column(_Vertices), attribute.Encoding, attribute.Normalized);
+                if (field.FieldType == typeof(Vector4)) accessor.SetVertexData(vbuffer, attribute.ByteOffset, field.GetVector4Column(_Vertices), attribute.Encoding, attribute.Normalized);
 
 
                 vertexAccessors[attribute.Name] = accessor;
                 vertexAccessors[attribute.Name] = accessor;
             }
             }
@@ -111,8 +111,9 @@ namespace SharpGLTF.Geometry
                 var ibuffer = root.UseBufferView(new ArraySegment<byte>(ibytes), 0, BufferMode.ELEMENT_ARRAY_BUFFER);
                 var ibuffer = root.UseBufferView(new ArraySegment<byte>(ibytes), 0, BufferMode.ELEMENT_ARRAY_BUFFER);
 
 
                 var indices = root
                 var indices = root
-                    .CreateAccessor("Indices")
-                    .WithIndexData(ibuffer, 0, kvp.Value);
+                    .CreateAccessor("Indices");
+
+                indices.SetIndexData(ibuffer, 0, kvp.Value);
 
 
                 // create mesh primitive
                 // create mesh primitive
                 var prim = dstMesh.CreatePrimitive();
                 var prim = dstMesh.CreatePrimitive();

+ 10 - 0
src/SharpGLTF.Toolkit/Schema2/AccessorExtensions.cs

@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace SharpGLTF.Schema2
+{
+    public static partial class Toolkit
+    {
+    }
+}

+ 51 - 0
src/SharpGLTF.Toolkit/Schema2/AnimationExtensions.cs

@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using System.Text;
+
+namespace SharpGLTF.Schema2
+{
+    public static partial class Toolkit
+    {
+        public static Animation UseAnimation(this ModelRoot root, string name)
+        {
+            var animation = root.LogicalAnimations.FirstOrDefault(item => item.Name == name);
+
+            return animation ?? root.CreateAnimation(name);
+        }
+
+        public static Node WithScaleAnimation(this Node node, string animationName, IReadOnlyDictionary<Single, Vector3> keyframes)
+        {
+            var root = node.LogicalParent;
+
+            var animation = root.UseAnimation(animationName);
+
+            animation.CreateScaleChannel(node, keyframes);
+
+            return node;
+        }
+
+        public static Node WithRotationAnimation(this Node node, string animationName, IReadOnlyDictionary<Single, Quaternion> keyframes)
+        {
+            var root = node.LogicalParent;
+
+            var animation = root.UseAnimation(animationName);
+
+            animation.CreateRotationChannel(node, keyframes);
+
+            return node;
+        }
+
+        public static Node WithTranslationAnimation(this Node node, string animationName, IReadOnlyDictionary<Single, Vector3> keyframes)
+        {
+            var root = node.LogicalParent;
+
+            var animation = root.UseAnimation(animationName);
+
+            animation.CreateTranslationChannel(node, keyframes);
+
+            return node;
+        }
+    }
+}

+ 68 - 0
src/SharpGLTF.Toolkit/Schema2/MaterialExtensions.cs

@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Numerics;
+using System.Text;
+
+namespace SharpGLTF.Schema2
+{
+    public static partial class Toolkit
+    {
+        /// <summary>
+        /// Initializes this <see cref="Material"/> instance with default material attributes.
+        /// </summary>
+        /// <param name="material">The <see cref="Material"/> instance to set.</param>
+        /// <returns>This <see cref="Material"/> instance.</returns>
+        public static Material WithDefault(this Material material)
+        {
+            return material.WithPBRMetallicRoughness();
+        }
+
+        /// <summary>
+        /// Initializes this <see cref="Material"/> instance with default material attributes.
+        /// </summary>
+        /// <param name="material">The <see cref="Material"/> instance to set.</param>
+        /// <param name="diffuseColor">A <see cref="Vector4"/> color where X=Red, Y=Green, Z=Blue, W=Alpha.</param>
+        /// <returns>This <see cref="Material"/> instance.</returns>
+        public static Material WithDefault(this Material material, Vector4 diffuseColor)
+        {
+            material.WithPBRMetallicRoughness()
+                .FindChannel("BaseColor")
+                .SetFactor(diffuseColor);
+
+            return material;
+        }
+
+        /// <summary>
+        /// Initializes this <see cref="Material"/> instance with PBR Metallic Roughness attributes.
+        /// </summary>
+        /// <param name="material">The <see cref="Material"/> instance to set.</param>
+        /// <returns>This <see cref="Material"/> instance.</returns>
+        public static Material WithPBRMetallicRoughness(this Material material)
+        {
+            material.InitializePBRMetallicRoughness();
+            return material;
+        }
+
+        /// <summary>
+        /// Initializes this <see cref="Material"/> instance with PBR Specular Glossiness attributes.
+        /// </summary>
+        /// <param name="material">The <see cref="Material"/> instance to set.</param>
+        /// <returns>This <see cref="Material"/> instance.</returns>
+        public static Material WithPBRSpecularGlossiness(this Material material)
+        {
+            material.InitializePBRSpecularGlossiness();
+            return material;
+        }
+
+        /// <summary>
+        /// Initializes this <see cref="Material"/> instance with Unlit attributes.
+        /// </summary>
+        /// <param name="material">The <see cref="Material"/> instance to set.</param>
+        /// <returns>This <see cref="Material"/> instance.</returns>
+        public static Material WithUnlit(this Material material)
+        {
+            material.InitializeUnlit();
+            return material;
+        }
+    }
+}

+ 77 - 0
src/SharpGLTF.Toolkit/Schema2/MeshExtensions.cs

@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Generic;
+using System.Numerics;
+using System.Text;
+
+namespace SharpGLTF.Schema2
+{
+    using Memory;
+
+    public static partial class Toolkit
+    {
+        public static MeshPrimitive WithVertexAccessor(this MeshPrimitive primitive, string attribute, IReadOnlyList<Vector2> values)
+        {
+            var root = primitive.LogicalParent.LogicalParent;
+
+            // create a vertex buffer and fill it
+            var view = root.UseBufferView(new Byte[8 * values.Count], 0, null, 0, BufferMode.ARRAY_BUFFER);
+            var array = new Vector2Array(view.Content);
+            array.FillFrom(0, values);
+
+            var accessor = root.CreateAccessor();
+
+            accessor.SetVertexData(view, 0, values.Count, DimensionType.VEC2, EncodingType.FLOAT, false);
+
+            primitive.SetVertexAccessor(attribute, accessor);
+
+            return primitive;
+        }
+
+        public static MeshPrimitive WithVertexAccessor(this MeshPrimitive primitive, string attribute, IReadOnlyList<Vector3> values)
+        {
+            var root = primitive.LogicalParent.LogicalParent;
+
+            // create a vertex buffer and fill it
+            var view = root.UseBufferView(new Byte[12 * values.Count], 0, null, 0, BufferMode.ARRAY_BUFFER);
+            var array = new Vector3Array(view.Content);
+            array.FillFrom(0, values);
+
+            var accessor = root.CreateAccessor();
+
+            accessor.SetVertexData(view, 0, values.Count, DimensionType.VEC3, EncodingType.FLOAT, false);
+
+            primitive.SetVertexAccessor(attribute, accessor);
+
+            return primitive;
+        }
+
+        public static MeshPrimitive WithIndicesAutomatic(this MeshPrimitive primitive, PrimitiveType primitiveType)
+        {
+            var root = primitive.LogicalParent.LogicalParent;
+
+            primitive.DrawPrimitiveType = primitiveType;
+            primitive.SetIndexAccessor(null);
+
+            return primitive;
+        }
+
+        public static MeshPrimitive WithIndicesAccessor(this MeshPrimitive primitive, PrimitiveType primitiveType, IReadOnlyList<Int32> values)
+        {
+            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.FillFrom(0, values);
+
+            var accessor = root.CreateAccessor();
+
+            accessor.SetIndexData(view, 0, values.Count, IndexEncodingType.UNSIGNED_INT);
+
+            primitive.DrawPrimitiveType = primitiveType;
+            primitive.SetIndexAccessor(accessor);
+
+            return primitive;
+        }
+    }
+}

+ 37 - 0
src/SharpGLTF.Toolkit/Schema2/SceneExtensions.cs

@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Numerics;
+using System.Text;
+
+namespace SharpGLTF.Schema2
+{
+    public static partial class Toolkit
+    {
+        public static Node WithLocalTranslation(this Node node, Vector3 translation)
+        {
+            var xform = node.LocalTransform;
+            xform.Translation = translation;
+            node.LocalTransform = xform;
+
+            return node;
+        }
+
+        public static Node WithLocalRotation(this Node node, Quaternion rotation)
+        {
+            var xform = node.LocalTransform;
+            xform.Rotation = rotation;
+            node.LocalTransform = xform;
+
+            return node;
+        }
+
+        public static Node WithLocalScale(this Node node, Vector3 scale)
+        {
+            var xform = node.LocalTransform;
+            xform.Scale = scale;
+            node.LocalTransform = xform;
+
+            return node;
+        }
+    }
+}

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

@@ -51,8 +51,16 @@
     <AdditionalFiles Include="..\..\stylecop.json" />
     <AdditionalFiles Include="..\..\stylecop.json" />
   </ItemGroup>
   </ItemGroup>
 
 
+  <ItemGroup>
+    <Compile Include="..\SharpGLTF\Debug\Guard.cs" Link="Debug\Guard.cs" />
+  </ItemGroup>
+
   <ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\SharpGLTF\SharpGLTF.csproj" />
     <ProjectReference Include="..\SharpGLTF\SharpGLTF.csproj" />
   </ItemGroup>
   </ItemGroup>
 
 
+  <ItemGroup>
+    <Folder Include="Debug\" />
+  </ItemGroup>
+
 </Project>
 </Project>

+ 2 - 2
src/SharpGLTF/Geometry/MeshPrimitive.cs

@@ -123,7 +123,7 @@ namespace SharpGLTF.Geometry
         public void AssignTo(Schema2.MeshPrimitive dstPrim)
         public void AssignTo(Schema2.MeshPrimitive dstPrim)
         {
         {
             var dstAccessor = dstPrim.LogicalParent.LogicalParent.CreateAccessor(this.Name);
             var dstAccessor = dstPrim.LogicalParent.LogicalParent.CreateAccessor(this.Name);
-            dstAccessor.WithVertexData(_MemoryAccessor);
+            dstAccessor.SetVertexData(_MemoryAccessor);
             dstPrim.SetVertexAccessor(this._MemoryAccessor.Attribute.Name, dstAccessor);
             dstPrim.SetVertexAccessor(this._MemoryAccessor.Attribute.Name, dstAccessor);
         }
         }
 
 
@@ -184,7 +184,7 @@ namespace SharpGLTF.Geometry
         public void AssignToSchema(Schema2.MeshPrimitive dstPrim)
         public void AssignToSchema(Schema2.MeshPrimitive dstPrim)
         {
         {
             var dstAccessor = dstPrim.LogicalParent.LogicalParent.CreateAccessor(this.Name);
             var dstAccessor = dstPrim.LogicalParent.LogicalParent.CreateAccessor(this.Name);
-            dstAccessor.WithIndexData(_MemoryAccessor);
+            dstAccessor.SetIndexData(_MemoryAccessor);
             dstPrim.IndexAccessor = dstAccessor;
             dstPrim.IndexAccessor = dstAccessor;
         }
         }
 
 

+ 39 - 52
src/SharpGLTF/Schema2/gltf.Accessors.cs

@@ -126,137 +126,124 @@ namespace SharpGLTF.Schema2
 
 
         #region Index Buffer API
         #region Index Buffer API
 
 
-        public Accessor WithIndexData(Geometry.MemoryAccessor src)
+        public void SetIndexData(Geometry.MemoryAccessor src)
         {
         {
             var bv = this.LogicalParent.UseBufferView(src.Data, src.Attribute.ByteStride, BufferMode.ELEMENT_ARRAY_BUFFER);
             var bv = this.LogicalParent.UseBufferView(src.Data, src.Attribute.ByteStride, BufferMode.ELEMENT_ARRAY_BUFFER);
-            return this.WithIndexData(bv, src.Attribute.ByteOffset, src.Attribute.ItemsCount, src.Attribute.Encoding.ToIndex());
+            SetIndexData(bv, src.Attribute.ByteOffset, src.Attribute.ItemsCount, src.Attribute.Encoding.ToIndex());
         }
         }
 
 
-        public Accessor WithIndexData(BufferView buffer, int byteOffset, IReadOnlyList<Int32> items, IndexEncodingType encoding = IndexEncodingType.UNSIGNED_INT)
+        public void SetIndexData(BufferView buffer, int byteOffset, IReadOnlyList<Int32> items, IndexEncodingType encoding = IndexEncodingType.UNSIGNED_INT)
         {
         {
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
 
 
-            WithIndexData(buffer, byteOffset, items.Count, encoding)
-                .AsIndicesArray()
-                .FillFrom(0, items);
+            SetIndexData(buffer, byteOffset, items.Count, encoding);
 
 
-            this.UpdateBounds();
+            AsIndicesArray().FillFrom(0, items);
 
 
-            return this;
+            this.UpdateBounds();
         }
         }
 
 
-        public Accessor WithIndexData(BufferView buffer, int byteOffset, IReadOnlyList<UInt32> items, IndexEncodingType encoding = IndexEncodingType.UNSIGNED_INT)
+        public void SetIndexData(BufferView buffer, int byteOffset, IReadOnlyList<UInt32> items, IndexEncodingType encoding = IndexEncodingType.UNSIGNED_INT)
         {
         {
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
 
 
-            WithIndexData(buffer, byteOffset, items.Count, encoding)
-                .AsIndicesArray()
-                .FillFrom(0, items);
+            SetIndexData(buffer, byteOffset, items.Count, encoding);
 
 
-            this.UpdateBounds();
+            AsIndicesArray().FillFrom(0, items);
 
 
-            return this;
+            this.UpdateBounds();
         }
         }
 
 
-        public Accessor WithIndexData(BufferView buffer, int byteOffset, int itemCount, IndexEncodingType encoding)
+        public void SetIndexData(BufferView buffer, int byteOffset, int itemCount, IndexEncodingType encoding)
         {
         {
             Guard.NotNull(buffer, nameof(buffer));
             Guard.NotNull(buffer, nameof(buffer));
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
 
 
             if (buffer.DeviceBufferTarget.HasValue) Guard.IsTrue(buffer.DeviceBufferTarget.Value == BufferMode.ELEMENT_ARRAY_BUFFER, nameof(buffer));
             if (buffer.DeviceBufferTarget.HasValue) Guard.IsTrue(buffer.DeviceBufferTarget.Value == BufferMode.ELEMENT_ARRAY_BUFFER, nameof(buffer));
 
 
-            return WithData(buffer, byteOffset, itemCount, DimensionType.SCALAR, encoding.ToComponent(), false);
+            WithData(buffer, byteOffset, itemCount, DimensionType.SCALAR, encoding.ToComponent(), false);
         }
         }
 
 
-        public Memory.IntegerArray AsIndicesArray()
+        public IntegerArray AsIndicesArray()
         {
         {
             Guard.IsFalse(this.IsSparse, nameof(IsSparse));
             Guard.IsFalse(this.IsSparse, nameof(IsSparse));
             Guard.IsTrue(this.Dimensions == DimensionType.SCALAR, nameof(Dimensions));
             Guard.IsTrue(this.Dimensions == DimensionType.SCALAR, nameof(Dimensions));
 
 
-            return new Memory.IntegerArray(SourceBufferView.Content, this.ByteOffset, this._count, this.Encoding.ToIndex());
+            return new IntegerArray(SourceBufferView.Content, this.ByteOffset, this._count, this.Encoding.ToIndex());
         }
         }
 
 
         #endregion
         #endregion
 
 
         #region Vertex Buffer API
         #region Vertex Buffer API
 
 
-        public Accessor WithVertexData(Geometry.MemoryAccessor src)
+        public void SetVertexData(Geometry.MemoryAccessor src)
         {
         {
             var bv = this.LogicalParent.UseBufferView(src.Data, src.Attribute.ByteStride, BufferMode.ARRAY_BUFFER);
             var bv = this.LogicalParent.UseBufferView(src.Data, src.Attribute.ByteStride, BufferMode.ARRAY_BUFFER);
-            return this.WithVertexData(bv, src.Attribute.ByteOffset, src.Attribute.ItemsCount, src.Attribute.Dimensions, src.Attribute.Encoding, src.Attribute.Normalized);
+
+            SetVertexData(bv, src.Attribute.ByteOffset, src.Attribute.ItemsCount, src.Attribute.Dimensions, src.Attribute.Encoding, src.Attribute.Normalized);
         }
         }
 
 
-        public Accessor WithVertexData(BufferView buffer, int bufferByteOffset, IReadOnlyList<Single> items, EncodingType encoding = EncodingType.FLOAT, Boolean normalized = false)
+        public void SetVertexData(BufferView buffer, int bufferByteOffset, IReadOnlyList<Single> items, EncodingType encoding = EncodingType.FLOAT, Boolean normalized = false)
         {
         {
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
             Guard.MustBePositiveAndMultipleOf(DimensionType.SCALAR.DimCount() * encoding.ByteLength(), 4, nameof(encoding));
             Guard.MustBePositiveAndMultipleOf(DimensionType.SCALAR.DimCount() * encoding.ByteLength(), 4, nameof(encoding));
 
 
-            WithVertexData(buffer, bufferByteOffset, items.Count, DimensionType.SCALAR, encoding, normalized)
-                .AsScalarArray()
-                .FillFrom(0, items);
+            SetVertexData(buffer, bufferByteOffset, items.Count, DimensionType.SCALAR, encoding, normalized);
 
 
-            this.UpdateBounds();
+            AsScalarArray().FillFrom(0, items);
 
 
-            return this;
+            this.UpdateBounds();
         }
         }
 
 
-        public Accessor WithVertexData(BufferView buffer, int bufferByteOffset, IReadOnlyList<Vector2> items, EncodingType encoding = EncodingType.FLOAT, Boolean normalized = false)
+        public void SetVertexData(BufferView buffer, int bufferByteOffset, IReadOnlyList<Vector2> items, EncodingType encoding = EncodingType.FLOAT, Boolean normalized = false)
         {
         {
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
             Guard.MustBePositiveAndMultipleOf(DimensionType.VEC2.DimCount() * encoding.ByteLength(), 4, nameof(encoding));
             Guard.MustBePositiveAndMultipleOf(DimensionType.VEC2.DimCount() * encoding.ByteLength(), 4, nameof(encoding));
 
 
-            WithVertexData(buffer, bufferByteOffset, items.Count, DimensionType.VEC2, encoding, normalized)
-                .AsVector2Array()
-                .FillFrom(0, items);
+            SetVertexData(buffer, bufferByteOffset, items.Count, DimensionType.VEC2, encoding, normalized);
 
 
-            this.UpdateBounds();
+            AsVector2Array().FillFrom(0, items);
 
 
-            return this;
+            this.UpdateBounds();
         }
         }
 
 
-        public Accessor WithVertexData(BufferView buffer, int bufferByteOffset, IReadOnlyList<Vector3> items, EncodingType encoding = EncodingType.FLOAT, Boolean normalized = false)
+        public void SetVertexData(BufferView buffer, int bufferByteOffset, IReadOnlyList<Vector3> items, EncodingType encoding = EncodingType.FLOAT, Boolean normalized = false)
         {
         {
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
             Guard.MustBePositiveAndMultipleOf(DimensionType.VEC3.DimCount() * encoding.ByteLength(), 4, nameof(encoding));
             Guard.MustBePositiveAndMultipleOf(DimensionType.VEC3.DimCount() * encoding.ByteLength(), 4, nameof(encoding));
 
 
-            WithVertexData(buffer, bufferByteOffset, items.Count, DimensionType.VEC3, encoding, normalized)
-                .AsVector3Array()
-                .FillFrom(0, items);
+            SetVertexData(buffer, bufferByteOffset, items.Count, DimensionType.VEC3, encoding, normalized);
 
 
-            this.UpdateBounds();
+            AsVector3Array().FillFrom(0, items);
 
 
-            return this;
+            this.UpdateBounds();
         }
         }
 
 
-        public Accessor WithVertexData(BufferView buffer, int bufferByteOffset, IReadOnlyList<Vector4> items, EncodingType encoding = EncodingType.FLOAT, Boolean normalized = false)
+        public void SetVertexData(BufferView buffer, int bufferByteOffset, IReadOnlyList<Vector4> items, EncodingType encoding = EncodingType.FLOAT, Boolean normalized = false)
         {
         {
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
             Guard.MustBePositiveAndMultipleOf(DimensionType.VEC4.DimCount() * encoding.ByteLength(), 4, nameof(encoding));
             Guard.MustBePositiveAndMultipleOf(DimensionType.VEC4.DimCount() * encoding.ByteLength(), 4, nameof(encoding));
 
 
-            WithVertexData(buffer, bufferByteOffset, items.Count, DimensionType.VEC4, encoding, normalized)
-                .AsVector4Array()
-                .FillFrom(0, items);
+            SetVertexData(buffer, bufferByteOffset, items.Count, DimensionType.VEC4, encoding, normalized);
 
 
-            this.UpdateBounds();
+            AsVector4Array().FillFrom(0, items);
 
 
-            return this;
+            this.UpdateBounds();
         }
         }
 
 
-        public Accessor WithVertexData(BufferView buffer, int bufferByteOffset, IReadOnlyList<Quaternion> items, EncodingType encoding = EncodingType.FLOAT, Boolean normalized = false)
+        public void SetVertexData(BufferView buffer, int bufferByteOffset, IReadOnlyList<Quaternion> items, EncodingType encoding = EncodingType.FLOAT, Boolean normalized = false)
         {
         {
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
             Guard.MustBePositiveAndMultipleOf(DimensionType.VEC4.DimCount() * encoding.ByteLength(), 4, nameof(encoding));
             Guard.MustBePositiveAndMultipleOf(DimensionType.VEC4.DimCount() * encoding.ByteLength(), 4, nameof(encoding));
 
 
-            WithVertexData(buffer, bufferByteOffset, items.Count, DimensionType.VEC4, encoding, normalized)
-                .AsQuaternionArray()
-                .FillFrom(0, items);
+            SetVertexData(buffer, bufferByteOffset, items.Count, DimensionType.VEC4, encoding, normalized);
 
 
-            this.UpdateBounds();
+            AsQuaternionArray().FillFrom(0, items);
 
 
-            return this;
+            this.UpdateBounds();
         }
         }
 
 
-        public Accessor WithVertexData(BufferView buffer, int bufferByteOffset, int itemCount, DimensionType dimensions = DimensionType.VEC3, EncodingType encoding = EncodingType.FLOAT, Boolean normalized = false)
+        public void SetVertexData(BufferView buffer, int bufferByteOffset, int itemCount, DimensionType dimensions = DimensionType.VEC3, EncodingType encoding = EncodingType.FLOAT, Boolean normalized = false)
         {
         {
             Guard.NotNull(buffer, nameof(buffer));
             Guard.NotNull(buffer, nameof(buffer));
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
             Guard.MustShareLogicalParent(this, buffer, nameof(buffer));
@@ -264,7 +251,7 @@ namespace SharpGLTF.Schema2
 
 
             if (buffer.DeviceBufferTarget.HasValue) Guard.IsTrue(buffer.DeviceBufferTarget.Value == BufferMode.ARRAY_BUFFER, nameof(buffer));
             if (buffer.DeviceBufferTarget.HasValue) Guard.IsTrue(buffer.DeviceBufferTarget.Value == BufferMode.ARRAY_BUFFER, nameof(buffer));
 
 
-            return WithData(buffer, bufferByteOffset, itemCount, dimensions, encoding, normalized);
+            WithData(buffer, bufferByteOffset, itemCount, dimensions, encoding, normalized);
         }
         }
 
 
         public IEncodedArray<float> AsScalarArray()
         public IEncodedArray<float> AsScalarArray()

+ 29 - 33
src/SharpGLTF/Schema2/gltf.Animations.cs

@@ -70,56 +70,62 @@ namespace SharpGLTF.Schema2
 
 
         public void CreateScaleChannel(Node node, IReadOnlyDictionary<Single, Vector3> keyframes, bool linear = true)
         public void CreateScaleChannel(Node node, IReadOnlyDictionary<Single, Vector3> keyframes, bool linear = true)
         {
         {
-            var sampler = this._CreateSampler(linear ? AnimationInterpolationMode.LINEAR : AnimationInterpolationMode.STEP)
-                .WithVector3Keys(keyframes);
+            var sampler = this._CreateSampler(linear ? AnimationInterpolationMode.LINEAR : AnimationInterpolationMode.STEP);
+
+            sampler.SetVector3Keys(keyframes);
 
 
             this._UseChannel(node, PathType.scale)
             this._UseChannel(node, PathType.scale)
-                .WithSampler(sampler);
+                .SetSampler(sampler);
         }
         }
 
 
         public void CreateScaleChannel(Node node, IReadOnlyDictionary<Single, (Vector3, Vector3, Vector3)> keyframes)
         public void CreateScaleChannel(Node node, IReadOnlyDictionary<Single, (Vector3, Vector3, Vector3)> keyframes)
         {
         {
-            var sampler = this._CreateSampler(AnimationInterpolationMode.CUBICSPLINE)
-                .WithVector3Keys(keyframes);
+            var sampler = this._CreateSampler(AnimationInterpolationMode.CUBICSPLINE);
+
+            sampler.SetVector3Keys(keyframes);
 
 
             this._UseChannel(node, PathType.scale)
             this._UseChannel(node, PathType.scale)
-                .WithSampler(sampler);
+                .SetSampler(sampler);
         }
         }
 
 
         public void CreateRotationChannel(Node node, IReadOnlyDictionary<Single, Quaternion> keyframes, bool linear = true)
         public void CreateRotationChannel(Node node, IReadOnlyDictionary<Single, Quaternion> keyframes, bool linear = true)
         {
         {
-            var sampler = this._CreateSampler(linear ? AnimationInterpolationMode.LINEAR : AnimationInterpolationMode.STEP)
-                .WithQuaternionKeys(keyframes);
+            var sampler = this._CreateSampler(linear ? AnimationInterpolationMode.LINEAR : AnimationInterpolationMode.STEP);
+
+            sampler.SetQuaternionKeys(keyframes);
 
 
             this._UseChannel(node, PathType.rotation)
             this._UseChannel(node, PathType.rotation)
-                .WithSampler(sampler);
+                .SetSampler(sampler);
         }
         }
 
 
         public void CreateRotationChannel(Node node, IReadOnlyDictionary<Single, (Quaternion, Quaternion, Quaternion)> keyframes)
         public void CreateRotationChannel(Node node, IReadOnlyDictionary<Single, (Quaternion, Quaternion, Quaternion)> keyframes)
         {
         {
-            var sampler = this._CreateSampler(AnimationInterpolationMode.CUBICSPLINE)
-                .WithQuaternionKeys(keyframes);
+            var sampler = this._CreateSampler(AnimationInterpolationMode.CUBICSPLINE);
+
+            sampler.SetQuaternionKeys(keyframes);
 
 
             this._UseChannel(node, PathType.rotation)
             this._UseChannel(node, PathType.rotation)
-                .WithSampler(sampler);
+                .SetSampler(sampler);
         }
         }
 
 
         public void CreateTranslationChannel(Node node, IReadOnlyDictionary<Single, Vector3> keyframes, bool linear = true)
         public void CreateTranslationChannel(Node node, IReadOnlyDictionary<Single, Vector3> keyframes, bool linear = true)
         {
         {
-            var sampler = this._CreateSampler(linear ? AnimationInterpolationMode.LINEAR : AnimationInterpolationMode.STEP)
-                .WithVector3Keys(keyframes);
+            var sampler = this._CreateSampler(linear ? AnimationInterpolationMode.LINEAR : AnimationInterpolationMode.STEP);
+
+            sampler.SetVector3Keys(keyframes);
 
 
             this._UseChannel(node, PathType.translation)
             this._UseChannel(node, PathType.translation)
-                .WithSampler(sampler);
+                .SetSampler(sampler);
         }
         }
 
 
         public void CreateTranslationChannel(Node node, IReadOnlyDictionary<Single, (Vector3, Vector3, Vector3)> keyframes)
         public void CreateTranslationChannel(Node node, IReadOnlyDictionary<Single, (Vector3, Vector3, Vector3)> keyframes)
         {
         {
-            var sampler = this._CreateSampler(AnimationInterpolationMode.CUBICSPLINE)
-                .WithVector3Keys(keyframes);
+            var sampler = this._CreateSampler(AnimationInterpolationMode.CUBICSPLINE);
+
+            sampler.SetVector3Keys(keyframes);
 
 
             this._UseChannel(node, PathType.translation)
             this._UseChannel(node, PathType.translation)
-                .WithSampler(sampler);
+                .SetSampler(sampler);
         }
         }
 
 
         public void CreateMorphChannel(Node node, AnimationInterpolationMode mode, IReadOnlyDictionary<Single, Single[]> keyframes)
         public void CreateMorphChannel(Node node, AnimationInterpolationMode mode, IReadOnlyDictionary<Single, Single[]> keyframes)
@@ -189,14 +195,12 @@ namespace SharpGLTF.Schema2
             _sampler = -1;
             _sampler = -1;
         }
         }
 
 
-        internal AnimationChannel WithSampler(AnimationSampler sampler)
+        internal void SetSampler(AnimationSampler sampler)
         {
         {
             Guard.NotNull(sampler, nameof(sampler));
             Guard.NotNull(sampler, nameof(sampler));
             Guard.IsTrue(this.LogicalParent == sampler.LogicalParent, nameof(sampler));
             Guard.IsTrue(this.LogicalParent == sampler.LogicalParent, nameof(sampler));
 
 
             _sampler = sampler.LogicalIndex;
             _sampler = sampler.LogicalIndex;
-
-            return this;
         }
         }
 
 
         #endregion
         #endregion
@@ -368,40 +372,32 @@ namespace SharpGLTF.Schema2
             return (keys, vals);
             return (keys, vals);
         }
         }
 
 
-        public AnimationSampler WithVector3Keys(IReadOnlyDictionary<Single, Vector3> keyframes)
+        public void SetVector3Keys(IReadOnlyDictionary<Single, Vector3> keyframes)
         {
         {
             var kv = _Split(keyframes);
             var kv = _Split(keyframes);
             _input = this._CreateInputAccessor(kv.Item1).LogicalIndex;
             _input = this._CreateInputAccessor(kv.Item1).LogicalIndex;
             _output = this._CreateOutputAccessor(kv.Item2).LogicalIndex;
             _output = this._CreateOutputAccessor(kv.Item2).LogicalIndex;
-
-            return this;
         }
         }
 
 
-        public AnimationSampler WithVector3Keys(IReadOnlyDictionary<Single, (Vector3, Vector3, Vector3)> keyframes)
+        public void SetVector3Keys(IReadOnlyDictionary<Single, (Vector3, Vector3, Vector3)> keyframes)
         {
         {
             var kv = _Split(keyframes);
             var kv = _Split(keyframes);
             _input = this._CreateInputAccessor(kv.Item1).LogicalIndex;
             _input = this._CreateInputAccessor(kv.Item1).LogicalIndex;
             _output = this._CreateOutputAccessor(kv.Item2).LogicalIndex;
             _output = this._CreateOutputAccessor(kv.Item2).LogicalIndex;
-
-            return this;
         }
         }
 
 
-        public AnimationSampler WithQuaternionKeys(IReadOnlyDictionary<Single, Quaternion> keyframes)
+        public void SetQuaternionKeys(IReadOnlyDictionary<Single, Quaternion> keyframes)
         {
         {
             var kv = _Split(keyframes);
             var kv = _Split(keyframes);
             _input = this._CreateInputAccessor(kv.Item1).LogicalIndex;
             _input = this._CreateInputAccessor(kv.Item1).LogicalIndex;
             _output = this._CreateOutputAccessor(kv.Item2).LogicalIndex;
             _output = this._CreateOutputAccessor(kv.Item2).LogicalIndex;
-
-            return this;
         }
         }
 
 
-        public AnimationSampler WithQuaternionKeys(IReadOnlyDictionary<Single, (Quaternion, Quaternion, Quaternion)> keyframes)
+        public void SetQuaternionKeys(IReadOnlyDictionary<Single, (Quaternion, Quaternion, Quaternion)> keyframes)
         {
         {
             var kv = _Split(keyframes);
             var kv = _Split(keyframes);
             _input = this._CreateInputAccessor(kv.Item1).LogicalIndex;
             _input = this._CreateInputAccessor(kv.Item1).LogicalIndex;
             _output = this._CreateOutputAccessor(kv.Item2).LogicalIndex;
             _output = this._CreateOutputAccessor(kv.Item2).LogicalIndex;
-
-            return this;
         }
         }
 
 
         public IReadOnlyDictionary<Single, Vector3> AsVector3KeyFrames()
         public IReadOnlyDictionary<Single, Vector3> AsVector3KeyFrames()

+ 3 - 35
src/SharpGLTF/Schema2/gltf.MaterialsFactory.cs

@@ -10,65 +10,33 @@ namespace SharpGLTF.Schema2
     {
     {
         #region API
         #region API
 
 
-        /// <summary>
-        /// Initializes this <see cref="Material"/> instance with default material attributes.
-        /// </summary>
-        /// <param name="diffuseColor">A <see cref="Vector4"/> color where X=Red, Y=Green, Z=Blue, W=Alpha.</param>
-        /// <returns>This <see cref="Material"/> instance.</returns>
-        public Material WithDefault(Vector4 diffuseColor)
-        {
-            this.WithPBRMetallicRoughness()
-                .FindChannel("BaseColor")
-                .SetFactor(diffuseColor);
-
-            return this;
-        }
-
-        /// <summary>
-        /// Initializes this <see cref="Material"/> instance with default material attributes.
-        /// </summary>
-        /// <returns>This <see cref="Material"/> instance.</returns>
-        public Material WithDefault()
-        {
-            return this.WithPBRMetallicRoughness();
-        }
-
         /// <summary>
         /// <summary>
         /// Initializes this <see cref="Material"/> instance with PBR Metallic Roughness attributes.
         /// Initializes this <see cref="Material"/> instance with PBR Metallic Roughness attributes.
         /// </summary>
         /// </summary>
-        /// <returns>This <see cref="Material"/> instance.</returns>
-        public Material WithPBRMetallicRoughness()
+        public void InitializePBRMetallicRoughness()
         {
         {
             this._pbrMetallicRoughness = new MaterialPBRMetallicRoughness();
             this._pbrMetallicRoughness = new MaterialPBRMetallicRoughness();
 
 
             this.RemoveExtensions<MaterialPBRSpecularGlossiness>();
             this.RemoveExtensions<MaterialPBRSpecularGlossiness>();
             this.RemoveExtensions<MaterialUnlit>();
             this.RemoveExtensions<MaterialUnlit>();
-
-            return this;
         }
         }
 
 
         /// <summary>
         /// <summary>
         /// Initializes this <see cref="Material"/> instance with PBR Specular Glossiness attributes.
         /// Initializes this <see cref="Material"/> instance with PBR Specular Glossiness attributes.
         /// </summary>
         /// </summary>
-        /// <returns>This <see cref="Material"/> instance.</returns>
-        public Material WithPBRSpecularGlossiness()
+        public void InitializePBRSpecularGlossiness()
         {
         {
             this.RemoveExtensions<MaterialUnlit>();
             this.RemoveExtensions<MaterialUnlit>();
             this.SetExtension(new MaterialPBRSpecularGlossiness(this));
             this.SetExtension(new MaterialPBRSpecularGlossiness(this));
-
-            return this;
         }
         }
 
 
         /// <summary>
         /// <summary>
         /// Initializes this <see cref="Material"/> instance with Unlit attributes.
         /// Initializes this <see cref="Material"/> instance with Unlit attributes.
         /// </summary>
         /// </summary>
-        /// <returns>This <see cref="Material"/> instance.</returns>
-        public Material WithUnlit()
+        public void InitializeUnlit()
         {
         {
             this.RemoveExtensions<MaterialPBRSpecularGlossiness>();
             this.RemoveExtensions<MaterialPBRSpecularGlossiness>();
             this.SetExtension(new MaterialUnlit(this));
             this.SetExtension(new MaterialUnlit(this));
-
-            return this;
         }
         }
 
 
         private IEnumerable<MaterialChannelView> _GetChannels()
         private IEnumerable<MaterialChannelView> _GetChannels()

+ 0 - 27
src/SharpGLTF/Schema2/gltf.Scene.cs

@@ -57,33 +57,6 @@ namespace SharpGLTF.Schema2
 
 
         #region properties - transform
         #region properties - transform
 
 
-        public Node WithLocalTranslation(Vector3 translation)
-        {
-            var xform = this.LocalTransform;
-            xform.Translation = translation;
-            this.LocalTransform = xform;
-
-            return this;
-        }
-
-        public Node WithLocalRotation(Quaternion rotation)
-        {
-            var xform = this.LocalTransform;
-            xform.Rotation = rotation.Sanitized();
-            this.LocalTransform = xform;
-
-            return this;
-        }
-
-        public Node WithLocalScale(Vector3 scale)
-        {
-            var xform = this.LocalTransform;
-            xform.Scale = scale;
-            this.LocalTransform = xform;
-
-            return this;
-        }
-
         /// <summary>
         /// <summary>
         /// Gets or sets the local transform <see cref="Matrix4x4"/> of this <see cref="Node"/>.
         /// Gets or sets the local transform <see cref="Matrix4x4"/> of this <see cref="Node"/>.
         /// </summary>
         /// </summary>

+ 1 - 1
src/SharpGLTF/Transforms/AffineTransform.cs

@@ -59,7 +59,7 @@ namespace SharpGLTF.Transforms
                 return
                 return
                     Matrix4x4.CreateScale(Scale)
                     Matrix4x4.CreateScale(Scale)
                     *
                     *
-                    Matrix4x4.CreateFromQuaternion(Rotation)
+                    Matrix4x4.CreateFromQuaternion(Rotation.Sanitized())
                     *
                     *
                     Matrix4x4.CreateTranslation(Translation);
                     Matrix4x4.CreateTranslation(Translation);
             }
             }

+ 3 - 3
tests/SharpGLTF.Tests/Geometry/CreateMeshTests.cs

@@ -7,7 +7,7 @@ using NUnit.Framework;
 
 
 namespace SharpGLTF.Geometry
 namespace SharpGLTF.Geometry
 {
 {
-    using Memory;
+    using Schema2;
 
 
     [TestFixture]
     [TestFixture]
     public class CreateMeshTests
     public class CreateMeshTests
@@ -39,7 +39,7 @@ namespace SharpGLTF.Geometry
             // setup a mesh primitive
             // setup a mesh primitive
             var srcPrimitive = srcMesh.CreatePrimitive();
             var srcPrimitive = srcMesh.CreatePrimitive();
             srcPrimitive.AllocateVertices(positions.Length, "POSITION", "NORMAL");          // (#1)
             srcPrimitive.AllocateVertices(positions.Length, "POSITION", "NORMAL");          // (#1)
-            srcPrimitive.AllocateIndices(indices.Length, Schema2.PrimitiveType.TRIANGLES);  // (#2)
+            srcPrimitive.AllocateIndices(indices.Length, PrimitiveType.TRIANGLES);  // (#2)
 
 
             // assign vertices and indices
             // assign vertices and indices
             srcPrimitive.Vertices[0].SetValues(0, positions);
             srcPrimitive.Vertices[0].SetValues(0, positions);
@@ -56,7 +56,7 @@ namespace SharpGLTF.Geometry
 
 
             // Now we switch to the .Schema2 namespace and we create a new scene:
             // Now we switch to the .Schema2 namespace and we create a new scene:
 
 
-            var model = Schema2.ModelRoot.CreateModel();                        
+            var model = ModelRoot.CreateModel();                        
             var scene = model.UseScene("default");
             var scene = model.UseScene("default");
             var rnode = scene.CreateNode("main scene");
             var rnode = scene.CreateNode("main scene");
 
 

+ 31 - 62
tests/SharpGLTF.Tests/Schema2/Authoring/CreateModelTests.cs

@@ -106,35 +106,21 @@ namespace SharpGLTF.Schema2.Authoring
             // create mesh
             // create mesh
             var rmesh = rnode.Mesh = model.CreateMesh("Triangle Mesh");
             var rmesh = rnode.Mesh = model.CreateMesh("Triangle Mesh");
 
 
-            // create a vertex buffer with positions and fill it
-            var positionsView = model.UseBufferView(new Byte[12 * 3], 0, null, 0, BufferMode.ARRAY_BUFFER);
-            var positionsArray = new Memory.Vector3Array(positionsView.Content);
-            positionsArray[0] = new Vector3(0, 10, 0);
-            positionsArray[1] = new Vector3(-10, -10, 0);
-            positionsArray[2] = new Vector3(10, -10, 0);
-
-            // create an index buffer and fill it
-            var indicesView = model.UseBufferView(new Byte[4 * 3], 0, null, 0, BufferMode.ELEMENT_ARRAY_BUFFER);
-            var indicesArray = new Memory.IntegerArray(indicesView.Content);
-            indicesArray[0] = 0;
-            indicesArray[1] = 1;
-            indicesArray[2] = 2;
-
-            // create a positions accessor
-            var positionsAccessor = model
-                .CreateAccessor()
-                .WithVertexData(positionsView, 0, 3, DimensionType.VEC3, EncodingType.FLOAT, false);
-
-            // create an indices accessor
-            var indicesAccessor = model
-                .CreateAccessor()
-                .WithIndexData(indicesView, 0, 3, IndexEncodingType.UNSIGNED_INT);
-            
+            var positionsArray = new[]
+            {
+                new Vector3(0, 10, 0),
+                new Vector3(-10, -10, 0),
+                new Vector3(10, -10, 0),
+            };
+
+            // create an index buffer and fill it            
+            var indicesArray = new[] { 0, 1, 2 };
+
             // create mesh primitive
             // create mesh primitive
-            var primitive = rmesh.CreatePrimitive();
-            primitive.DrawPrimitiveType = PrimitiveType.TRIANGLES;
-            primitive.SetVertexAccessor("POSITION", positionsAccessor);
-            primitive.IndexAccessor = indicesAccessor;
+            var primitive = rmesh.CreatePrimitive()
+                .WithVertexAccessor("POSITION", positionsArray)
+                .WithIndicesAccessor(PrimitiveType.TRIANGLES, indicesArray);
+
             primitive.Material = model.CreateMaterial("Default").WithDefault(new Vector4(0, 1, 0, 1));
             primitive.Material = model.CreateMaterial("Default").WithDefault(new Vector4(0, 1, 0, 1));
             primitive.Material.DoubleSided = true;
             primitive.Material.DoubleSided = true;
 
 
@@ -158,7 +144,7 @@ namespace SharpGLTF.Schema2.Authoring
             var rmesh = rnode.Mesh = model.CreateMesh("Triangle Mesh");
             var rmesh = rnode.Mesh = model.CreateMesh("Triangle Mesh");
 
 
             // define the triangle positions
             // define the triangle positions
-            var sourcePositions = new[]
+            var positions = new[]
             {
             {
                 new Vector3(0, 10, 0),
                 new Vector3(0, 10, 0),
                 new Vector3(-10, -10, 0),
                 new Vector3(-10, -10, 0),
@@ -166,32 +152,18 @@ namespace SharpGLTF.Schema2.Authoring
             };
             };
 
 
             // define the triangle UV coordinates
             // define the triangle UV coordinates
-            var sourceTextures = new[]
+            var texCoords = new[]
             {
             {
                 new Vector2(0.5f, -0.8f),
                 new Vector2(0.5f, -0.8f),
                 new Vector2(-0.5f, 1.2f),
                 new Vector2(-0.5f, 1.2f),
                 new Vector2(1.5f, 1.2f)
                 new Vector2(1.5f, 1.2f)
             };
             };
-
-            // create a vertex buffer
-            int byteStride = (3 + 2) * 4;
-            var vbuffer = model.UseBufferView(new Byte[byteStride * 3], byteStride, BufferMode.ARRAY_BUFFER);
-
-            // create positions accessor and fill it
-            var vpositions = model
-                .CreateAccessor("Triangle Positions")
-                .WithVertexData(vbuffer, 0, sourcePositions);
-
-            // create texcoord accessor and fill it
-            var vtextures = model
-                .CreateAccessor("Triangle texture coords")
-                .WithVertexData(vbuffer, 12, sourceTextures);
-
+            
             // create a mesh primitive and assgin the accessors and other properties
             // create a mesh primitive and assgin the accessors and other properties
-            var primitive = rmesh.CreatePrimitive();
-            primitive.SetVertexAccessor("POSITION", vpositions);
-            primitive.SetVertexAccessor("TEXCOORD_0", vtextures);
-            primitive.DrawPrimitiveType = PrimitiveType.TRIANGLES;
+            var primitive = rmesh.CreatePrimitive()
+                .WithVertexAccessor("POSITION", positions)
+                .WithVertexAccessor("TEXCOORD_0", texCoords)
+                .WithIndicesAutomatic(PrimitiveType.TRIANGLES);
 
 
             // create and assign a material
             // create and assign a material
             primitive.Material = model
             primitive.Material = model
@@ -335,10 +307,19 @@ namespace SharpGLTF.Schema2.Authoring
             var scene = model.UseScene("Default");
             var scene = model.UseScene("Default");
             var snode = scene.CreateNode("RootNode");
             var snode = scene.CreateNode("RootNode");
 
 
+            // create animation sequence with 4 frames
+            var keyframes = new Dictionary<Single, Quaternion>
+            {
+                [1] = Quaternion.Identity,
+                [2] = Quaternion.CreateFromYawPitchRoll(0, 1, 0),
+                [3] = Quaternion.CreateFromYawPitchRoll(0, 0, 1),
+                [4] = Quaternion.Identity,
+            };
+
             // create the three joints that will affect the mesh
             // create the three joints that will affect the mesh
             var skelet = scene.CreateNode("Skeleton");
             var skelet = scene.CreateNode("Skeleton");
             var jnode1 = skelet.CreateNode("Joint 1").WithLocalTranslation(new Vector3(0, 0, 0));
             var jnode1 = skelet.CreateNode("Joint 1").WithLocalTranslation(new Vector3(0, 0, 0));
-            var jnode2 = jnode1.CreateNode("Joint 2").WithLocalTranslation(new Vector3(0, 40, 0));
+            var jnode2 = jnode1.CreateNode("Joint 2").WithLocalTranslation(new Vector3(0, 40, 0)).WithRotationAnimation("Base Track", keyframes);
             var jnode3 = jnode2.CreateNode("Joint 3").WithLocalTranslation(new Vector3(0, 40, 0));
             var jnode3 = jnode2.CreateNode("Joint 3").WithLocalTranslation(new Vector3(0, 40, 0));
 
 
             // setup skin
             // setup skin
@@ -385,18 +366,6 @@ namespace SharpGLTF.Schema2.Authoring
             // fill our node with the mesh
             // fill our node with the mesh
             meshBuilder.CopyToNode(snode, createMaterialForColor);
             meshBuilder.CopyToNode(snode, createMaterialForColor);
 
 
-            // create animation sequence with 4 frames
-            var keyframes = new Dictionary<Single, Quaternion>
-            {
-                [1] = Quaternion.Identity,
-                [2] = Quaternion.CreateFromYawPitchRoll(0, 1, 0),
-                [3] = Quaternion.CreateFromYawPitchRoll(0, 0, 1),
-                [4] = Quaternion.Identity,
-            };
-
-            model.CreateAnimation("Animation")
-                .CreateRotationChannel(jnode2, keyframes);
-            
             model.AttachToCurrentTest("result.glb");
             model.AttachToCurrentTest("result.glb");
             model.AttachToCurrentTest("result.gltf");
             model.AttachToCurrentTest("result.gltf");
         }
         }

+ 5 - 27
tests/SharpGLTF.Tests/Schema2/Authoring/SimpleMeshBuilder.cs

@@ -64,36 +64,14 @@ namespace SharpGLTF.Schema2.Authoring
 
 
         public void CopyToMesh(Mesh dstMesh, Func<TMaterial,Material> materialEvaluator)
         public void CopyToMesh(Mesh dstMesh, Func<TMaterial,Material> materialEvaluator)
         {
         {
-            var root = dstMesh.LogicalParent;            
-
-            // create vertex buffer
-            const int byteStride = 12 * 2;
-
-            var vbuffer = root.UseBufferView(new Byte[byteStride * _Positions.Count], byteStride, BufferMode.ARRAY_BUFFER);
-
-            var positions = root
-                .CreateAccessor("Positions")
-                .WithVertexData(vbuffer, 0, _Positions);
-
-            var normals = root
-                .CreateAccessor("Normals")
-                .WithVertexData(vbuffer, 12, _CalculateNormals());            
+            var root = dstMesh.LogicalParent;
 
 
             foreach (var kvp in _Indices)
             foreach (var kvp in _Indices)
             {
             {
-                // create index buffer
-                var ibuffer = root.UseBufferView(new Byte[4 * kvp.Value.Count], 0, BufferMode.ELEMENT_ARRAY_BUFFER);
-
-                var indices = root
-                    .CreateAccessor("Indices")
-                    .WithIndexData(ibuffer, 0, kvp.Value);
-
-                // create mesh primitive
-                var prim = dstMesh.CreatePrimitive();
-                prim.SetVertexAccessor("POSITION", positions);
-                prim.SetVertexAccessor("NORMAL", normals);
-                prim.SetIndexAccessor(indices);
-                prim.DrawPrimitiveType = PrimitiveType.TRIANGLES;
+                var prim = dstMesh.CreatePrimitive()
+                    .WithVertexAccessor("POSITION", _Positions)
+                    .WithVertexAccessor("NORMAL", _CalculateNormals())
+                    .WithIndicesAccessor(PrimitiveType.TRIANGLES,kvp.Value);                
 
 
                 prim.Material = materialEvaluator(kvp.Key);
                 prim.Material = materialEvaluator(kvp.Key);
             }
             }

+ 2 - 0
tests/SharpGLTF.Tests/TestFiles.cs

@@ -87,6 +87,8 @@ namespace SharpGLTF
         {
         {
             var dirPath = System.IO.Path.Combine(paths);
             var dirPath = System.IO.Path.Combine(paths);
 
 
+            if (dirPath.EndsWith(".zip")) dirPath = dirPath.Substring(0, dirPath.Length-4);
+
             if (!System.IO.Path.IsPathFullyQualified(dirPath)) throw new ArgumentException(nameof(dirPath));
             if (!System.IO.Path.IsPathFullyQualified(dirPath)) throw new ArgumentException(nameof(dirPath));
 
 
             var gltf = System.IO.Directory.GetFiles(dirPath, "*.gltf", System.IO.SearchOption.AllDirectories);
             var gltf = System.IO.Directory.GetFiles(dirPath, "*.gltf", System.IO.SearchOption.AllDirectories);

+ 0 - 2
tests/SharpGLTF.Tests/TestUtils.cs

@@ -166,8 +166,6 @@ namespace SharpGLTF
                     var extractPath = System.IO.Path.Combine(dir, System.IO.Path.GetFileNameWithoutExtension(localFilePath));
                     var extractPath = System.IO.Path.Combine(dir, System.IO.Path.GetFileNameWithoutExtension(localFilePath));
 
 
                     System.IO.Compression.ZipFile.ExtractToDirectory(localFilePath, extractPath);
                     System.IO.Compression.ZipFile.ExtractToDirectory(localFilePath, extractPath);
-
-                    return extractPath;
                 }
                 }
 
 
                 return localFilePath;
                 return localFilePath;