Browse Source

removed legacy mesh experiments.
Renamed some enums.
Improved serialization type support.
WIP with extras property.
WIP with materials.

Vicente Penades 6 years ago
parent
commit
3dfe005ba7

+ 1 - 8
SharpGLTF.sln

@@ -21,9 +21,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpGLTF.Tests", "tests\Sh
 EndProject
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{D7D51F42-D08C-4DDA-88DA-AF008F10B644}"
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{D7D51F42-D08C-4DDA-88DA-AF008F10B644}"
 EndProject
 EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MeshBuffers", "src\MeshBuffers\MeshBuffers.csproj", "{1C93D96E-19DD-443B-8818-AAB14FEDA35D}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpGLTF.Toolkit", "src\SharpGLTF.Toolkit\SharpGLTF.Toolkit.csproj", "{41690879-1F91-4555-A40A-F67B01868D7E}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpGLTF.Toolkit", "src\SharpGLTF.Toolkit\SharpGLTF.Toolkit.csproj", "{41690879-1F91-4555-A40A-F67B01868D7E}"
 EndProject
 EndProject
 Global
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -43,10 +41,6 @@ Global
 		{4FCBB910-67D4-4628-9B2B-F5F2C8D92257}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{4FCBB910-67D4-4628-9B2B-F5F2C8D92257}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{4FCBB910-67D4-4628-9B2B-F5F2C8D92257}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{4FCBB910-67D4-4628-9B2B-F5F2C8D92257}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{4FCBB910-67D4-4628-9B2B-F5F2C8D92257}.Release|Any CPU.Build.0 = Release|Any CPU
 		{4FCBB910-67D4-4628-9B2B-F5F2C8D92257}.Release|Any CPU.Build.0 = Release|Any CPU
-		{1C93D96E-19DD-443B-8818-AAB14FEDA35D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{1C93D96E-19DD-443B-8818-AAB14FEDA35D}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{1C93D96E-19DD-443B-8818-AAB14FEDA35D}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{1C93D96E-19DD-443B-8818-AAB14FEDA35D}.Release|Any CPU.Build.0 = Release|Any CPU
 		{41690879-1F91-4555-A40A-F67B01868D7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{41690879-1F91-4555-A40A-F67B01868D7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{41690879-1F91-4555-A40A-F67B01868D7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{41690879-1F91-4555-A40A-F67B01868D7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{41690879-1F91-4555-A40A-F67B01868D7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{41690879-1F91-4555-A40A-F67B01868D7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -59,7 +53,6 @@ Global
 		{E15F8DCC-987D-4FA8-B7B0-1F0614DC93DD} = {D7D51F42-D08C-4DDA-88DA-AF008F10B644}
 		{E15F8DCC-987D-4FA8-B7B0-1F0614DC93DD} = {D7D51F42-D08C-4DDA-88DA-AF008F10B644}
 		{B1DA4F42-AB6A-4021-9989-674B1394E8A2} = {072B725F-773F-4751-9616-E9778897C1D2}
 		{B1DA4F42-AB6A-4021-9989-674B1394E8A2} = {072B725F-773F-4751-9616-E9778897C1D2}
 		{4FCBB910-67D4-4628-9B2B-F5F2C8D92257} = {0CBF510D-D836-40BA-95EC-E93FDBB90632}
 		{4FCBB910-67D4-4628-9B2B-F5F2C8D92257} = {0CBF510D-D836-40BA-95EC-E93FDBB90632}
-		{1C93D96E-19DD-443B-8818-AAB14FEDA35D} = {0CBF510D-D836-40BA-95EC-E93FDBB90632}
 		{41690879-1F91-4555-A40A-F67B01868D7E} = {072B725F-773F-4751-9616-E9778897C1D2}
 		{41690879-1F91-4555-A40A-F67B01868D7E} = {072B725F-773F-4751-9616-E9778897C1D2}
 	EndGlobalSection
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 	GlobalSection(ExtensibilityGlobals) = postSolution

+ 9 - 3
build/SharpGLTF.CodeGen/Program.cs

@@ -73,6 +73,12 @@ namespace SharpGLTF
                 .SetDefaultValue("Vector4.One")
                 .SetDefaultValue("Vector4.One")
                 .SetItemsRange(0);
                 .SetItemsRange(0);
 
 
+            var tex1 = ctx1.FindEnum("LINEAR-NEAREST");
+            tex1.SetValue("DEFAULT",0);
+
+            var tex2 = ctx1.FindEnum("LINEAR-LINEAR_MIPMAP_LINEAR-LINEAR_MIPMAP_NEAREST-NEAREST-NEAREST_MIPMAP_LINEAR-NEAREST_MIPMAP_NEAREST");
+            tex2.SetValue("DEFAULT", 0);
+
             ProcessSchema("gltf.g", ctx1);
             ProcessSchema("gltf.g", ctx1);
         }
         }
 
 
@@ -192,15 +198,15 @@ namespace SharpGLTF
             newEmitter.SetRuntimeName("UNSIGNED_BYTE-UNSIGNED_INT-UNSIGNED_SHORT", "IndexEncodingType");            
             newEmitter.SetRuntimeName("UNSIGNED_BYTE-UNSIGNED_INT-UNSIGNED_SHORT", "IndexEncodingType");            
             newEmitter.SetRuntimeName("BYTE-FLOAT-SHORT-UNSIGNED_BYTE-UNSIGNED_INT-UNSIGNED_SHORT", "EncodingType");            
             newEmitter.SetRuntimeName("BYTE-FLOAT-SHORT-UNSIGNED_BYTE-UNSIGNED_INT-UNSIGNED_SHORT", "EncodingType");            
             newEmitter.SetRuntimeName("MAT2-MAT3-MAT4-SCALAR-VEC2-VEC3-VEC4", "DimensionType");
             newEmitter.SetRuntimeName("MAT2-MAT3-MAT4-SCALAR-VEC2-VEC3-VEC4", "DimensionType");
-            newEmitter.SetRuntimeName("rotation-scale-translation-weights", "PathType");
+            newEmitter.SetRuntimeName("rotation-scale-translation-weights", "PropertyPath");
             newEmitter.SetRuntimeName("ARRAY_BUFFER-ELEMENT_ARRAY_BUFFER", "BufferMode");
             newEmitter.SetRuntimeName("ARRAY_BUFFER-ELEMENT_ARRAY_BUFFER", "BufferMode");
             newEmitter.SetRuntimeName("orthographic-perspective", "CameraType");
             newEmitter.SetRuntimeName("orthographic-perspective", "CameraType");
             newEmitter.SetRuntimeName("BLEND-MASK-OPAQUE", "AlphaMode");
             newEmitter.SetRuntimeName("BLEND-MASK-OPAQUE", "AlphaMode");
             newEmitter.SetRuntimeName("LINE_LOOP-LINE_STRIP-LINES-POINTS-TRIANGLE_FAN-TRIANGLE_STRIP-TRIANGLES", "PrimitiveType");
             newEmitter.SetRuntimeName("LINE_LOOP-LINE_STRIP-LINES-POINTS-TRIANGLE_FAN-TRIANGLE_STRIP-TRIANGLES", "PrimitiveType");
             newEmitter.SetRuntimeName("CUBICSPLINE-LINEAR-STEP", "AnimationInterpolationMode");
             newEmitter.SetRuntimeName("CUBICSPLINE-LINEAR-STEP", "AnimationInterpolationMode");
-            newEmitter.SetRuntimeName("LINEAR-NEAREST", "TextureInterpolationMode");
+            newEmitter.SetRuntimeName("LINEAR-NEAREST", "TextureInterpolationFilter");
             newEmitter.SetRuntimeName("CLAMP_TO_EDGE-MIRRORED_REPEAT-REPEAT", "TextureWrapMode");
             newEmitter.SetRuntimeName("CLAMP_TO_EDGE-MIRRORED_REPEAT-REPEAT", "TextureWrapMode");
-            newEmitter.SetRuntimeName("LINEAR-LINEAR_MIPMAP_LINEAR-LINEAR_MIPMAP_NEAREST-NEAREST-NEAREST_MIPMAP_LINEAR-NEAREST_MIPMAP_NEAREST", "TextureMipMapMode");
+            newEmitter.SetRuntimeName("LINEAR-LINEAR_MIPMAP_LINEAR-LINEAR_MIPMAP_NEAREST-NEAREST-NEAREST_MIPMAP_LINEAR-NEAREST_MIPMAP_NEAREST", "TextureMipMapFilter");
 
 
             newEmitter.SetRuntimeName("KHR_materials_pbrSpecularGlossiness glTF extension", "MaterialPBRSpecularGlossiness");
             newEmitter.SetRuntimeName("KHR_materials_pbrSpecularGlossiness glTF extension", "MaterialPBRSpecularGlossiness");
             newEmitter.SetRuntimeName("KHR_materials_unlit glTF extension", "MaterialUnlit");
             newEmitter.SetRuntimeName("KHR_materials_unlit glTF extension", "MaterialUnlit");

+ 2 - 0
build/SharpGLTF.CodeGen/SchemaReflection/SchemaTypesContext.cs

@@ -53,6 +53,8 @@ namespace SharpGLTF.SchemaReflection
 
 
             public StringType UseString() { return (StringType)_UseOrCreate( new StringType(this) ); }
             public StringType UseString() { return (StringType)_UseOrCreate( new StringType(this) ); }
 
 
+            public EnumType FindEnum(string persistentName) { return Enumerations.FirstOrDefault(item => item.PersistentName == persistentName); }
+
             public ArrayType UseArray(SchemaType elementType) { return (ArrayType)_UseOrCreate( new ArrayType(this, elementType) ); }
             public ArrayType UseArray(SchemaType elementType) { return (ArrayType)_UseOrCreate( new ArrayType(this, elementType) ); }
 
 
             public ClassType FindClass(string persistentName) { return Classes.FirstOrDefault(item => item.PersistentName == persistentName); }
             public ClassType FindClass(string persistentName) { return Classes.FirstOrDefault(item => item.PersistentName == persistentName); }

+ 2 - 2
build/SharpGLTF.CodeGen/SharpGLTF.CodeGen.csproj

@@ -8,8 +8,8 @@
 
 
   <ItemGroup>
   <ItemGroup>
     <PackageReference Include="LibGit2Sharp" Version="0.26.0" />
     <PackageReference Include="LibGit2Sharp" Version="0.26.0" />
-    <PackageReference Include="NJsonSchema.CodeGeneration" Version="9.13.27" />
-    <PackageReference Include="NJsonSchema.CodeGeneration.CSharp" Version="9.13.27" />
+    <PackageReference Include="NJsonSchema.CodeGeneration" Version="9.13.28" />
+    <PackageReference Include="NJsonSchema.CodeGeneration.CSharp" Version="9.13.28" />
   </ItemGroup>
   </ItemGroup>
 
 
 </Project>
 </Project>

+ 0 - 105
src/MeshBuffers/ListSegment.cs

@@ -1,105 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Text;
-
-namespace MeshBuffers
-{
-    struct ListSegment<T> : IList<T>
-    {
-        public ListSegment(IList<T> source) : this(source,0,source.Count) { }
-
-        public ListSegment(IList<T> source, int offset, int count)
-        {
-            if (source == null) throw new ArgumentNullException(nameof(offset));
-            if (offset < 0) throw new ArgumentOutOfRangeException(nameof(offset));
-            if (count < 0) throw new ArgumentOutOfRangeException(nameof(count));
-            if (offset >= source.Count) throw new ArgumentOutOfRangeException(nameof(offset));
-            if (offset+count-1 >= source.Count) throw new ArgumentOutOfRangeException(nameof(count));
-
-            _Source = source;
-            _Offset = offset;
-            _Count = count;
-        }
-
-        private readonly IList<T> _Source;
-        private readonly int _Offset;
-        private int _Count;
-
-        public T this[int index]
-        {
-            get
-            {
-                if (index < 0) throw new ArgumentOutOfRangeException(nameof(index));
-                if (index >= _Count) throw new ArgumentOutOfRangeException(nameof(index));
-                return _Source[_Offset + index];
-            }
-            set
-            {
-                if (index < 0) throw new ArgumentOutOfRangeException(nameof(index));
-                if (index >= _Count) throw new ArgumentOutOfRangeException(nameof(index));
-                _Source[_Offset + index] = value;
-            }
-        }
-
-        public int Count => _Count;
-
-        public bool IsReadOnly => false;
-
-        public void Add(T item)
-        {
-            _Source.Insert(_Offset + _Count, item);
-            ++_Count;
-        }
-
-        public void Clear() { throw new NotImplementedException(); }
-
-        public bool Contains(T item) { throw new NotImplementedException(); }
-
-        public void CopyTo(T[] array, int arrayIndex)
-        {
-            for(int i=0; i < _Count; ++i)
-            {
-                array[i + arrayIndex] = _Source[i + _Offset];
-            }
-        }
-
-        public int IndexOf(T item)
-        {
-            for (int i = 0; i < _Count; ++i)
-            {
-                if (Object.Equals(item, _Source[i + _Offset])) return i;
-            }
-
-            return -1;
-        }
-
-        public void Insert(int index, T item)
-        {
-            if (index < 0) throw new ArgumentOutOfRangeException(nameof(index));
-            if (index >= _Count) throw new ArgumentOutOfRangeException(nameof(index));
-            _Source.Insert(index + _Offset, item);
-            ++_Count;
-        }
-
-        public bool Remove(T item) { throw new NotImplementedException(); }
-
-        public void RemoveAt(int index) { throw new NotImplementedException(); }
-
-        public IEnumerator<T> GetEnumerator()
-        {
-            for (int i = 0; i < _Count; ++i)
-            {
-                yield return _Source[i + _Offset];
-            }
-        }
-
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            for (int i = 0; i < _Count; ++i)
-            {
-                yield return _Source[i + _Offset];
-            }
-        }
-    }
-}

+ 0 - 11
src/MeshBuffers/MeshBuffers.csproj

@@ -1,11 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>netstandard2.0</TargetFramework>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
-  </ItemGroup>
-
-</Project>

+ 0 - 60
src/MeshBuffers/MeshPrimitive.cs

@@ -1,60 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace MeshBuffers
-{
-    class VertexBufferView
-    {
-        private readonly VertexBuffer _Buffer;
-        private readonly int _Offset;
-        private readonly int _Count;
-    }
-
-    class IndexBufferView
-    {
-        private readonly List<int> _Buffer;
-        private readonly int _Offset;
-        private readonly int _Count;
-    }
-
-    class MeshPrimitive
-    {
-        VertexBufferView _Vertices;
-        List<VertexBufferView> _Morphs;
-        IndexBufferView _Indices;
-    }
-
-    /*
-    [TestFixture]
-    public class MeshBuilderTests
-    {
-        [Test]
-        public void CreateVertexBufferTest()
-        {
-            var vbdecl = new VertexDeclaration()
-                .WithVector3("POSITION")
-                .WithVector3("NORMAL");
-
-            Assert.AreEqual(6, vbdecl.Stride);            
-
-            var vertex1 = vbdecl.CreateVertex();
-            var vertex2 = vbdecl.CreateVertex();
-            var vertex3 = vbdecl.CreateVertex();
-
-            var vbuffer = new TriangleBufferBuilder(vbdecl);
-
-            vertex1.Position = new Vector3(1, 2, 3);
-            vertex1.Normal = Vector3.UnitX;
-            vertex2.Position = new Vector3(4, 2, 3);
-            vertex2.Normal = Vector3.UnitY;
-            vertex3.Position = new Vector3(1, 5, 3);
-            vertex3.Normal = Vector3.UnitZ;
-
-            vbuffer.AddTriangle(vertex1, vertex2, vertex3);
-            vbuffer.AddTriangle(vertex1, vertex2, vertex3);            
-
-        }
-
-    }*/
-}

+ 0 - 64
src/MeshBuffers/TriangleBufferBuilder.cs

@@ -1,64 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace MeshBuffers
-{
-    public class TriangleBufferBuilder
-    {
-        #region lifecycle
-
-        public TriangleBufferBuilder(VertexBuffer vbuffer)
-        {
-            _Vertices = vbuffer;
-        }
-
-        public TriangleBufferBuilder(VertexDeclaration declaration)
-        {
-            _Vertices = new VertexBuffer(declaration);
-        }
-
-        #endregion
-
-        #region data        
-
-        private readonly VertexBuffer _Vertices;
-
-        private readonly List<int> _Indices = new List<int>();
-
-        private readonly Dictionary<Vertex, int> _VertexMap = new Dictionary<Vertex, int>();
-
-        #endregion
-
-        #region properties
-
-        public VertexBuffer Vertices => _Vertices;
-
-        public IReadOnlyList<int> Indices => _Indices;
-
-        #endregion
-
-        #region API
-
-        private int UseVertex(Vertex v)
-        {
-            if (_VertexMap.TryGetValue(v, out int index)) return index;
-            index = _Vertices.Count;
-
-            _Vertices.Add(v);
-            v = _Vertices[index];
-            _VertexMap[v] = index;
-
-            return index;
-        }
-
-        public void AddTriangle(Vertex a, Vertex b, Vertex c)
-        {
-            _Indices.Add(UseVertex(a));
-            _Indices.Add(UseVertex(b));
-            _Indices.Add(UseVertex(c));
-        }
-
-        #endregion
-    }
-}

+ 0 - 69
src/MeshBuffers/Vertex.cs

@@ -1,69 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Numerics;
-using System.Linq;
-
-namespace MeshBuffers
-{
-    using ROW = ListSegment<Single>;
-
-    public struct Vertex : IEquatable<Vertex>
-    {
-        #region constructor
-
-        internal Vertex(VertexDeclaration declaration)
-        {
-            _Declaration = declaration;
-            _Data = new ROW(new Single[_Declaration.Stride]);
-        }
-
-        internal Vertex(VertexDeclaration declaration, ROW data)
-        {
-            System.Diagnostics.Debug.Assert(declaration.Stride == data.Count);
-
-            _Declaration = declaration;
-            _Data = data;
-        }
-
-        #endregion
-
-        #region data
-
-        internal readonly VertexDeclaration _Declaration;
-        internal readonly ROW _Data;
-
-        public bool Equals(Vertex other) { return AreEqual(this, other); }
-
-        public static bool AreEqual(Vertex a, Vertex b)
-        {
-            VertexDeclaration.AreEqual(a._Declaration, b._Declaration);
-            return a._Data.SequenceEqual(b._Data);
-        }
-
-        public override int GetHashCode()
-        {
-            return _Declaration.GetHashCode() ^ _Data.Select(item => item.GetHashCode()).Aggregate((a, b) => (a * 17) ^ b);
-        }
-
-        #endregion
-
-        #region properties
-
-        public VertexDeclaration Declaration => _Declaration;
-
-        public Vector3 Position
-        {
-            get => _Declaration.GetPosition(_Data);
-            set => _Declaration.SetPosition(_Data, value);
-        }
-
-        public Vector3 Normal
-        {
-            get => _Declaration.GetNormal(_Data);
-            set => _Declaration.SetNormal(_Data, value);
-        }
-
-        #endregion
-    }
-}

+ 0 - 166
src/MeshBuffers/VertexBuffer.cs

@@ -1,166 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Numerics;
-using System.Text;
-
-namespace MeshBuffers
-{    
-    using ROW = ListSegment<Single>;    
-
-    public class VertexBuffer : IList<Vertex>
-    {
-        #region lifecycle
-
-        public VertexBuffer(VertexDeclaration declaration)
-        {
-            _Declaration = declaration;
-            _Stride = _Declaration.Stride;
-        }
-
-        #endregion
-
-        #region data
-
-        private readonly VertexDeclaration _Declaration;
-
-        private readonly int _Stride;
-
-        private readonly List<Single> _Data = new List<float>();
-
-        #endregion
-
-        #region API
-
-        public VertexDeclaration Declaration => _Declaration;        
-
-        public int Count => _Data.Count / _Stride;
-
-        public bool IsReadOnly => throw new NotImplementedException();
-        
-        public Vertex this[int index]
-        {
-            get => new Vertex(_Declaration, new ROW(_Data, index * _Stride, _Stride));
-            set => throw new NotImplementedException();
-        }
-
-        public void Add(Vertex vertex)
-        {
-            if (!VertexDeclaration.AreEqual(vertex._Declaration, this._Declaration)) throw new ArgumentException(nameof(vertex));
-            if (vertex._Data.Count != _Stride) throw new ArgumentException(nameof(vertex));
-            _Data.AddRange(vertex._Data);
-        }
-
-        public int IndexOf(Vertex item) { throw new NotImplementedException(); }
-
-        public void Insert(int index, Vertex item) { throw new NotImplementedException(); }
-
-        public void RemoveAt(int index) { throw new NotImplementedException(); }
-
-        public void Clear() { _Data.Clear(); }
-
-        public bool Contains(Vertex item) { throw new NotImplementedException(); }
-
-        public void CopyTo(Vertex[] array, int arrayIndex)
-        {
-            for(int i=0; i < Count; ++i)
-            {
-                array[arrayIndex + i] = this[i];
-            }
-        }
-
-        public bool Remove(Vertex item) { throw new NotImplementedException(); }
-
-        public IEnumerator<Vertex> GetEnumerator()
-        {
-            for (int i = 0; i < Count; ++i) yield return this[i];
-        }
-
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            for (int i = 0; i < Count; ++i) yield return this[i];
-        }
-
-        #endregion
-
-        #region extra API
-
-        public Single[] GetScalarColumn(string attribute)
-        {
-            var offset = _Declaration.GetOffset(attribute);
-            if (offset < 0) throw new ArgumentException(nameof(attribute));
-
-            var dst = new Single[this.Count];
-
-            for (int i = 0; i < dst.Length; ++i)
-            {
-                dst[i] = _Data[i * _Stride + offset];
-            }
-
-            return dst;
-        }
-
-        public Vector2[] GetVector2Column(string attribute)
-        {
-            var offset = _Declaration.GetOffset(attribute);
-            if (offset < 0) throw new ArgumentException(nameof(attribute));
-
-            var dst = new Vector2[this.Count];
-
-            for (int i = 0; i < dst.Length; ++i)
-            {
-                dst[i] = new Vector2
-                    (
-                    _Data[i * _Stride + offset + 0],
-                    _Data[i * _Stride + offset + 1]                    
-                    );
-            }
-
-            return dst;
-        }
-
-        public Vector3[] GetVector3Column(string attribute)
-        {
-            var offset = _Declaration.GetOffset(attribute);
-            if (offset < 0) throw new ArgumentException(nameof(attribute));
-
-            var dst = new Vector3[this.Count];
-
-            for(int i=0; i < dst.Length; ++i)
-            {
-                dst[i] = new Vector3
-                    (
-                    _Data[i * _Stride + offset + 0],
-                    _Data[i * _Stride + offset + 1],
-                    _Data[i * _Stride + offset + 2]
-                    );
-            }
-
-            return dst;
-        }
-
-        public Vector4[] GetVector4Column(string attribute)
-        {
-            var offset = _Declaration.GetOffset(attribute);
-            if (offset < 0) throw new ArgumentException(nameof(attribute));
-
-            var dst = new Vector4[this.Count];
-
-            for (int i = 0; i < dst.Length; ++i)
-            {
-                dst[i] = new Vector4
-                    (
-                    _Data[i * _Stride + offset + 0],
-                    _Data[i * _Stride + offset + 1],
-                    _Data[i * _Stride + offset + 2],
-                    _Data[i * _Stride + offset + 3]
-                    );
-            }
-
-            return dst;
-        }
-
-        #endregion
-    }
-}

+ 0 - 156
src/MeshBuffers/VertexDeclaration.cs

@@ -1,156 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Numerics;
-
-namespace MeshBuffers
-{
-    using ROW = ListSegment<Single>;
-
-    struct _VertexElement
-    {
-        public _VertexElement(string attribute, int dim, int offset)
-        {
-            _Attribute = attribute;
-            _Dimensions = dim;
-            _Offset = offset;
-        }
-
-        internal readonly String _Attribute;
-        internal readonly int _Dimensions;
-        internal readonly int _Offset;
-    }
-
-    public class VertexDeclaration : IEquatable<VertexDeclaration>
-    {
-        #region lifecycle
-
-        public VertexDeclaration() { _Elements = new _VertexElement[0]; }
-
-        private VertexDeclaration(_VertexElement[] elements, _VertexElement extra)
-        {
-            _Elements = new _VertexElement[elements.Length + 1];
-            elements.CopyTo(_Elements, 0);
-            _Elements[_Elements.Length - 1] = extra;
-
-            _Stride = _Elements.Sum(item => item._Dimensions);
-
-            _HashCode = _Elements.Select(item => item.GetHashCode()).Aggregate((a, b) => (a * 17) ^ b);
-
-            _PositionV3 = GetOffset("POSITION");
-            _NormalV3 = GetOffset("NORMAL");
-        }        
-
-        public VertexDeclaration WithSingle(string attribute)
-        {
-            var e = new _VertexElement(attribute, 1, Stride);
-
-            return new VertexDeclaration(_Elements, e);
-        }
-
-        public VertexDeclaration WithVector2(string attribute)
-        {
-            var e = new _VertexElement(attribute, 2, Stride);
-
-            return new VertexDeclaration(_Elements, e);
-        }
-
-        public VertexDeclaration WithVector3(string attribute)
-        {
-            var e = new _VertexElement(attribute, 3, Stride);
-
-            return new VertexDeclaration(_Elements, e);
-        }
-
-        public VertexDeclaration WithVector4(string attribute)
-        {
-            var e = new _VertexElement(attribute, 4, Stride);
-
-            return new VertexDeclaration(_Elements, e);
-        }
-
-        #endregion
-
-        #region data
-
-        private readonly _VertexElement[] _Elements;
-        private readonly int _Stride;
-        private readonly int _HashCode;
-
-        private readonly int _PositionV3;
-        private readonly int _NormalV3;
-
-        public bool Equals(VertexDeclaration other) { return AreEqual(this, other); }
-
-        public static bool AreEqual(VertexDeclaration a, VertexDeclaration b)
-        {
-            if (Object.ReferenceEquals(a, b)) return true;
-            return Enumerable.SequenceEqual(a._Elements, b._Elements);
-        }
-
-        public override int GetHashCode() { return _HashCode; }
-
-        #endregion
-
-        #region properties
-
-        public int Stride => _Stride;
-
-        public IEnumerable<string> Attributes => _Elements.Select(item => item._Attribute);
-
-        #endregion
-
-        #region API
-
-        public int GetOffset(string attribute)
-        {
-            var idx = Array.FindIndex(_Elements, item => item._Attribute == attribute);
-            return idx < 0 ? -1 : _Elements[idx]._Offset;
-        }
-
-        public int GetDimensions(string attribute)
-        {
-            var idx = Array.FindIndex(_Elements, item => item._Attribute == attribute);
-            return idx < 0 ? -1 : _Elements[idx]._Dimensions;
-        }
-
-        public Vertex CreateVertex() { return new Vertex(this); }
-
-        internal Vector3 GetPosition(ROW vertex)
-        {
-            return new Vector3
-                (
-                vertex[_PositionV3 + 0],
-                vertex[_PositionV3 + 1],
-                vertex[_PositionV3 + 2]
-                );
-        }
-
-        internal void SetPosition(ROW vertex, Vector3 value)
-        {
-            vertex[_PositionV3 + 0] = value.X;
-            vertex[_PositionV3 + 1] = value.Y;
-            vertex[_PositionV3 + 2] = value.Z;
-        }
-
-        internal Vector3 GetNormal(ROW vertex)
-        {
-            return new Vector3
-                (
-                vertex[_NormalV3 + 0],
-                vertex[_NormalV3 + 1],
-                vertex[_NormalV3 + 2]
-                );
-        }
-
-        internal void SetNormal(ROW vertex, Vector3 value)
-        {
-            vertex[_NormalV3 + 0] = value.X;
-            vertex[_NormalV3 + 1] = value.Y;
-            vertex[_NormalV3 + 2] = value.Z;
-        }
-
-        #endregion
-    }
-}

+ 0 - 362
src/SharpGLTF.Core/Geometry/MeshPrimitive.cs

@@ -1,362 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Numerics;
-using System.Text;
-
-namespace SharpGLTF.Geometry
-{
-    using Memory;
-
-    [Obsolete("Still here for reference, but most probably I'll use these objects for read meshes only")]
-    public abstract class NamedObject
-    {
-        public NamedObject() { }
-
-        public NamedObject(Schema2.LogicalChildOfRoot source)
-        {
-            Name = source.Name;
-        }
-
-        public string Name { get; set; }
-        public Object Extra { get; set; }
-    }
-
-    [System.Diagnostics.DebuggerDisplay("{Name}.{_MemoryAccessor.Attribute.Name} {_MemoryAccessor.Attribute.ItemsCount}")]
-    public class VertexAccessor : NamedObject
-    {
-        #region lifecycle
-
-        public VertexAccessor(string attributeName, Schema2.Accessor accessor)
-            : base(accessor)
-        {
-            _MemoryAccessor = accessor._GetMemoryAccessor();
-            _MemoryAccessor.SetName(attributeName);
-            _Sparse = accessor._GetSparseMemoryAccessor();
-        }
-
-        public VertexAccessor(MemoryAccessInfo info)
-        {
-            _MemoryAccessor = new MemoryAccessor(info);
-        }
-
-        public static VertexAccessor[] CreateAccessors(int itemsCount, params string[] attributes)
-        {
-            var accessors = MemoryAccessInfo
-                .Create(attributes)
-                .Select(item => new VertexAccessor(item))
-                .ToArray();
-
-            int byteOffset = 0;
-            var byteStride = accessors.Sum(item => item._MemoryAccessor.Attribute.ByteLength);
-
-            var data = new ArraySegment<Byte>(new Byte[byteStride * itemsCount]);
-
-            for (int i = 0; i < accessors.Length; ++i)
-            {
-                var a = accessors[i];
-
-                a._MemoryAccessor.SetVertexDataSource(data, byteOffset, itemsCount, byteStride);
-
-                byteOffset += a._MemoryAccessor.Attribute.ByteLength;
-            }
-
-            return accessors;
-        }
-
-        #endregion
-
-        #region data
-
-        private MemoryAccessor _MemoryAccessor;
-        private KeyValuePair<Memory.IntegerArray, MemoryAccessor>? _Sparse;
-
-        #endregion
-
-        #region API
-
-        public void SetValues(int startIndex, params Single[] values)
-        {
-            Memory.EncodedArrayUtils.FillFrom(AsScalarArray(), startIndex, values);
-        }
-
-        public void SetValues(int startIndex, params Vector2[] values)
-        {
-            Memory.EncodedArrayUtils.FillFrom(AsVector2Array(), startIndex, values);
-        }
-
-        public void SetValues(int startIndex, params Vector3[] values)
-        {
-            Memory.EncodedArrayUtils.FillFrom(AsVector3Array(), startIndex, values);
-        }
-
-        public void SetValues(int startIndex, params Vector4[] values)
-        {
-            Memory.EncodedArrayUtils.FillFrom(AsVector4Array(), startIndex, values);
-        }
-
-        public Memory.IEncodedArray<Single> AsScalarArray()
-        {
-            if (!_Sparse.HasValue) return _MemoryAccessor.AsScalarArray();
-
-            return MemoryAccessor.CreateScalarSparseArray(_MemoryAccessor, _Sparse.Value.Key, _Sparse.Value.Value);
-        }
-
-        public Memory.IEncodedArray<Vector2> AsVector2Array()
-        {
-            if (!_Sparse.HasValue) return _MemoryAccessor.AsVector2Array();
-
-            return MemoryAccessor.CreateVector2SparseArray(_MemoryAccessor, _Sparse.Value.Key, _Sparse.Value.Value);
-        }
-
-        public Memory.IEncodedArray<Vector3> AsVector3Array()
-        {
-            if (!_Sparse.HasValue) return _MemoryAccessor.AsVector3Array();
-
-            return MemoryAccessor.CreateVector3SparseArray(_MemoryAccessor, _Sparse.Value.Key, _Sparse.Value.Value);
-        }
-
-        public Memory.IEncodedArray<Vector4> AsVector4Array()
-        {
-            if (!_Sparse.HasValue) return _MemoryAccessor.AsVector4Array();
-
-            return MemoryAccessor.CreateVector4SparseArray(_MemoryAccessor, _Sparse.Value.Key, _Sparse.Value.Value);
-        }
-
-        public void AssignTo(Schema2.MeshPrimitive dstPrim)
-        {
-            var dstAccessor = dstPrim.LogicalParent.LogicalParent.CreateAccessor(this.Name);
-            dstAccessor.SetVertexData(_MemoryAccessor);
-            dstPrim.SetVertexAccessor(this._MemoryAccessor.Attribute.Name, dstAccessor);
-        }
-
-        #endregion
-    }
-
-    [System.Diagnostics.DebuggerDisplay("{Name}.{_MemoryAccessor.Attribute.Name} {_MemoryAccessor.Attribute.ItemsCount}")]
-    public class IndicesAccessor : NamedObject
-    {
-        #region lifecycle
-
-        public IndicesAccessor(Schema2.Accessor accessor)
-            : base(accessor)
-        {
-            _MemoryAccessor = accessor._GetMemoryAccessor();
-            _MemoryAccessor.SetName("INDEX");
-        }
-
-        public IndicesAccessor(MemoryAccessInfo info)
-        {
-            _MemoryAccessor = new MemoryAccessor(info);
-        }
-
-        public static IndicesAccessor CreateAccessors(int itemsCount)
-        {
-            var info = MemoryAccessInfo.CreateDefaultElement("INDEX");
-            info.ItemsCount = itemsCount;
-
-            var data = new ArraySegment<Byte>(new Byte[info.ByteLength * itemsCount]);
-
-            var accessor =  new IndicesAccessor(info);
-
-            accessor._MemoryAccessor.SetIndexDataSource(data, 0, itemsCount);
-
-            return accessor;
-        }
-
-        #endregion
-
-        #region data
-
-        private MemoryAccessor _MemoryAccessor;
-
-        #endregion
-
-        #region API
-
-        public void SetValues(int startIndex, params UInt32[] values)
-        {
-            Memory.EncodedArrayUtils.FillFrom(AsIntegerArray(), startIndex, values);
-        }
-
-        public Memory.IEncodedArray<UInt32> AsIntegerArray()
-        {
-            return _MemoryAccessor.AsIntegerArray();
-        }
-
-        public void AssignToSchema(Schema2.MeshPrimitive dstPrim)
-        {
-            var dstAccessor = dstPrim.LogicalParent.LogicalParent.CreateAccessor(this.Name);
-            dstAccessor.SetIndexData(_MemoryAccessor);
-            dstPrim.IndexAccessor = dstAccessor;
-        }
-
-        #endregion
-    }
-
-    public class MeshPrimitive<TMaterial>
-    {
-        #region lifecycle
-
-        internal MeshPrimitive(Mesh<TMaterial> owner) { _Owner = owner; }
-
-        internal MeshPrimitive(Mesh<TMaterial> owner, Schema2.MeshPrimitive primitive)
-            : this(owner)
-        {
-            _Vertices = primitive.VertexAccessors
-                .Select(kvp => new VertexAccessor(kvp.Key, kvp.Value))
-                .ToArray();
-
-            for (int i = 0; i < primitive.MorphTargetsCount; ++i)
-            {
-                var accessors = primitive.GetMorphTargetAccessors(i)
-                    .Select(kvp => new VertexAccessor(kvp.Key, kvp.Value))
-                    .ToArray();
-
-                _MorphAccessors.Add(accessors);
-            }
-
-            _Indices = primitive.IndexAccessor == null ? null : new IndicesAccessor(primitive.IndexAccessor);
-            _PrimitiveDrawType = primitive.DrawPrimitiveType;
-
-            if (primitive.Material != null)
-            {
-                if (typeof(TMaterial) == typeof(Schema2.Material))
-                {
-                    _Material = (TMaterial)(Object)primitive.Material;
-                }
-
-                if (typeof(TMaterial) == typeof(int?))
-                {
-                    var materialIndex = primitive.Material?.LogicalIndex;
-
-                    _Material = (TMaterial)(Object)materialIndex;
-                }
-            }
-        }
-
-        #endregion
-
-        #region data
-
-        private readonly Mesh<TMaterial> _Owner;
-
-        private VertexAccessor[] _Vertices;
-        private readonly List<VertexAccessor[]> _MorphAccessors = new List<VertexAccessor[]>();
-
-        private IndicesAccessor _Indices;
-
-        private Schema2.PrimitiveType _PrimitiveDrawType;
-
-        private TMaterial _Material;
-
-        #endregion
-
-        #region properties
-
-        public IReadOnlyList<VertexAccessor> Vertices => _Vertices;
-
-        public IndicesAccessor Indices => _Indices;
-
-        public TMaterial Material
-        {
-            get => _Material;
-            set => _Material = value;
-        }
-
-        #endregion
-
-        #region API
-
-        public void AllocateVertices(int itemsCount, params string[] attributes)
-        {
-            _Vertices = VertexAccessor.CreateAccessors(itemsCount, attributes);
-        }
-
-        public void AllocateIndices(int itemsCount, Schema2.PrimitiveType primitiveType)
-        {
-            _PrimitiveDrawType = primitiveType;
-            _Indices = IndicesAccessor.CreateAccessors(itemsCount);
-        }
-
-        internal void CopyTo(Schema2.MeshPrimitive dstPrim)
-        {
-            // TODO: clear primitive
-
-            foreach (var va in this._Vertices)
-            {
-                va.AssignTo(dstPrim);
-            }
-
-            if (this._Indices != null) this._Indices.AssignToSchema(dstPrim);
-
-            dstPrim.DrawPrimitiveType = this._PrimitiveDrawType;
-
-            if (typeof(TMaterial) == typeof(Schema2.Material))
-            {
-                var material = (Schema2.Material)(Object)_Material;
-                dstPrim.Material = material;
-            }
-
-            if (typeof(TMaterial) == typeof(int?))
-            {
-                var materialIndex = (int?)(Object)_Material;
-                var material = materialIndex.HasValue ? dstPrim.LogicalParent.LogicalParent.LogicalMaterials[materialIndex.Value] : null;
-                dstPrim.Material = material;
-            }
-        }
-
-        #endregion
-    }
-
-    [System.Diagnostics.DebuggerDisplay("Mesh {Name}")]
-    public class Mesh<TMaterial> : NamedObject
-    {
-        #region lifecycle
-
-        public Mesh() { }
-
-        /*
-        public Mesh(Schema2.Mesh mesh)
-            : base(mesh)
-        {
-            _Primitives.AddRange(mesh.Primitives, item => new MeshPrimitive(this, item));
-            _MorpthWeights.AddRange(mesh.MorphWeights);
-        }*/
-
-        #endregion
-
-        #region data
-
-        private readonly List<MeshPrimitive<TMaterial>> _Primitives = new List<MeshPrimitive<TMaterial>>();
-        private readonly List<Single> _MorpthWeights = new List<float>();
-
-        #endregion
-
-        #region API
-
-        public MeshPrimitive<TMaterial> CreatePrimitive()
-        {
-            var p = new MeshPrimitive<TMaterial>(this);
-            _Primitives.Add(p);
-
-            return p;
-        }
-
-        public void CopyTo(Schema2.Mesh mesh)
-        {
-            mesh.Name = this.Name;
-
-            foreach (var srcp in this._Primitives)
-            {
-                var dstp = mesh.CreatePrimitive();
-
-                srcp.CopyTo(dstp);
-            }
-
-            // todo: set morph targets
-        }
-
-        #endregion
-    }
-}

+ 31 - 33
src/SharpGLTF.Core/IO/JsonSerializable.cs

@@ -1,5 +1,6 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Linq;
 using System.Numerics;
 using System.Numerics;
 using System.Text;
 using System.Text;
 
 
@@ -141,7 +142,6 @@ namespace SharpGLTF.IO
         protected static void SerializeProperty<T>(JsonWriter writer, string name, IReadOnlyList<T> collection, int? minItems = 1)
         protected static void SerializeProperty<T>(JsonWriter writer, string name, IReadOnlyList<T> collection, int? minItems = 1)
         {
         {
             if (collection == null) return;
             if (collection == null) return;
-
             if (minItems.HasValue && collection.Count < minItems.Value) return;
             if (minItems.HasValue && collection.Count < minItems.Value) return;
 
 
             writer.WritePropertyName(name);
             writer.WritePropertyName(name);
@@ -160,9 +160,8 @@ namespace SharpGLTF.IO
             if (collection == null) return;
             if (collection == null) return;
             if (collection.Count < 1) return;
             if (collection.Count < 1) return;
 
 
-            // a dictionary is serialized as a regular object where every "property" is a key.
-
             writer.WritePropertyName(name);
             writer.WritePropertyName(name);
+
             writer.WriteStartObject();
             writer.WriteStartObject();
             foreach (var item in collection)
             foreach (var item in collection)
             {
             {
@@ -181,11 +180,20 @@ namespace SharpGLTF.IO
 
 
             if (value is String vstr) { writer.WriteValue(vstr); return; }
             if (value is String vstr) { writer.WriteValue(vstr); return; }
             if (value is Boolean vbol) { writer.WriteValue(vbol); return; }
             if (value is Boolean vbol) { writer.WriteValue(vbol); return; }
-            if (value is Int32 vi32) { writer.WriteValue(vi32); return; }
-            if (value is Int64 vi64) { writer.WriteValue(vi64); return; }
-            if (value is Single vfps) { writer.WriteValue(vfps); return; }
-            if (value is Double vfpd) { writer.WriteValue(vfpd); return; }
-            if (value is Decimal vfpx) { writer.WriteValue(vfpx); return; }
+
+            if (value is Byte vu8) { writer.WriteValue(vu8); return; }
+            if (value is UInt16 vu16) { writer.WriteValue(vu16); return; }
+            if (value is UInt32 vu32) { writer.WriteValue(vu32); return; }
+            if (value is UInt64 vu64) { writer.WriteValue(vu64); return; }
+
+            if (value is SByte vs8) { writer.WriteValue(vs8); return; }
+            if (value is Int16 vs16) { writer.WriteValue(vs16); return; }
+            if (value is Int32 vs32) { writer.WriteValue(vs32); return; }
+            if (value is Int64 vs64) { writer.WriteValue(vs64); return; }
+
+            if (value is Single vf32) { writer.WriteValue(vf32); return; }
+            if (value is Double vf64) { writer.WriteValue(vf64); return; }
+            if (value is Decimal vfxx) { writer.WriteValue(vfxx); return; }
 
 
             if (value is Vector2 vvv2) { writer.WriteVector2(vvv2); return; }
             if (value is Vector2 vvv2) { writer.WriteVector2(vvv2); return; }
             if (value is Vector3 vvv3) { writer.WriteVector3(vvv3); return; }
             if (value is Vector3 vvv3) { writer.WriteVector3(vvv3); return; }
@@ -195,36 +203,26 @@ namespace SharpGLTF.IO
 
 
             if (value is JsonSerializable vgltf) { vgltf.Serialize(writer); return; }
             if (value is JsonSerializable vgltf) { vgltf.Serialize(writer); return; }
 
 
-            if (value is IReadOnlyDictionary<String, Int32> vdsi)
+            if (value is System.Collections.IDictionary dict)
             {
             {
-                writer.WriteStartObject();
-                foreach (var item in vdsi)
-                {
-                    writer.WritePropertyName(item.Key);
-                    _Serialize(writer, item.Value);
-                }
-
-                writer.WriteEndObject();
-                return;
-            }
+                if (dict.Count == 0) return;
 
 
-            if (value is IReadOnlyDictionary<String, Object> vdso)
-            {
                 writer.WriteStartObject();
                 writer.WriteStartObject();
-                foreach (var item in vdso)
+                foreach (var key in dict.Keys)
                 {
                 {
-                    writer.WritePropertyName(item.Key);
-                    _Serialize(writer, item.Value);
+                    writer.WritePropertyName(key.ToString());
+                    _Serialize(writer, dict[key]);
                 }
                 }
-
                 writer.WriteEndObject();
                 writer.WriteEndObject();
                 return;
                 return;
             }
             }
 
 
-            if (value is Array array)
+            if (value is System.Collections.IList list)
             {
             {
+                if (list.Count == 0) return;
+
                 writer.WriteStartArray();
                 writer.WriteStartArray();
-                foreach (var item in array)
+                foreach (var item in list)
                 {
                 {
                     _Serialize(writer, item);
                     _Serialize(writer, item);
                 }
                 }
@@ -266,25 +264,25 @@ namespace SharpGLTF.IO
             throw new NotImplementedException();
             throw new NotImplementedException();
         }
         }
 
 
-        protected static Object DeserializeObject(JsonReader reader)
+        protected static Object DeserializeUnknownObject(JsonReader reader)
         {
         {
             if (reader.TokenType == JsonToken.PropertyName) reader.Read();
             if (reader.TokenType == JsonToken.PropertyName) reader.Read();
 
 
             if (reader.TokenType == JsonToken.StartArray)
             if (reader.TokenType == JsonToken.StartArray)
             {
             {
-                var items = new List<Object>();
+                var list = new JsonList();
 
 
                 while (reader.Read() && reader.TokenType != JsonToken.EndArray)
                 while (reader.Read() && reader.TokenType != JsonToken.EndArray)
                 {
                 {
-                    items.Add(DeserializeObject(reader));
+                    list.Add(DeserializeUnknownObject(reader));
                 }
                 }
 
 
-                return items.ToArray();
+                return list;
             }
             }
 
 
             if (reader.TokenType == JsonToken.StartObject)
             if (reader.TokenType == JsonToken.StartObject)
             {
             {
-                var dict = new Dictionary<string, object>();
+                var dict = new JsonDictionary();
 
 
                 while (reader.Read() && reader.TokenType != JsonToken.EndObject)
                 while (reader.Read() && reader.TokenType != JsonToken.EndObject)
                 {
                 {
@@ -292,7 +290,7 @@ namespace SharpGLTF.IO
                     {
                     {
                         var key = reader.Value as String;
                         var key = reader.Value as String;
 
 
-                        dict[key] = DeserializeObject(reader);
+                        dict[key] = DeserializeUnknownObject(reader);
                     }
                     }
                     else
                     else
                     {
                     {

+ 9 - 5
src/SharpGLTF.Core/IO/Unknown.cs

@@ -6,23 +6,27 @@ using Newtonsoft.Json;
 
 
 namespace SharpGLTF.IO
 namespace SharpGLTF.IO
 {
 {
+    public class JsonDictionary : Dictionary<String, Object> { }
+
+    public class JsonList : List<Object> { }
+
     [System.Diagnostics.DebuggerDisplay("Unknown {_Name}")]
     [System.Diagnostics.DebuggerDisplay("Unknown {_Name}")]
-    class Unknown : JsonSerializable
+    class UnknownNode : JsonSerializable
     {
     {
-        public Unknown(string name) { this._Name = name; }
+        public UnknownNode(string name) { this._Name = name; }
 
 
         private readonly string _Name;
         private readonly string _Name;
 
 
-        private readonly Dictionary<string, Object> _Properties = new Dictionary<string, object>();
+        private readonly JsonDictionary _Properties = new JsonDictionary();
 
 
         public string Name => _Name;
         public string Name => _Name;
 
 
-        public IDictionary<String, Object> Properties => _Properties;
+        public JsonDictionary Properties => _Properties;
 
 
         protected override void DeserializeProperty(string property, JsonReader reader)
         protected override void DeserializeProperty(string property, JsonReader reader)
         {
         {
             reader.Read();
             reader.Read();
-            _Properties[property] = DeserializeObject(reader);
+            _Properties[property] = DeserializeUnknownObject(reader);
         }
         }
 
 
         protected override void SerializeProperties(JsonWriter writer)
         protected override void SerializeProperties(JsonWriter writer)

+ 14 - 12
src/SharpGLTF.Core/Schema2/Generated/gltf.g.cs

@@ -68,7 +68,7 @@ namespace SharpGLTF.Schema2
 	/// <summary>
 	/// <summary>
 	/// The name of the node's TRS property to modify, or the "weights" of the Morph Targets it instantiates. For the "translation" property, the values that are provided by the sampler are the translation along the x, y, and z axes. For the "rotation" property, the values are a quaternion in the order (x, y, z, w), where w is the scalar. For the "scale" property, the values are the scaling factors along the x, y, and z axes.
 	/// The name of the node's TRS property to modify, or the "weights" of the Morph Targets it instantiates. For the "translation" property, the values that are provided by the sampler are the translation along the x, y, and z axes. For the "rotation" property, the values are a quaternion in the order (x, y, z, w), where w is the scalar. For the "scale" property, the values are the scaling factors along the x, y, and z axes.
 	/// </summary>
 	/// </summary>
-	public enum PathType
+	public enum PropertyPath
 	{
 	{
 		translation,
 		translation,
 		rotation,
 		rotation,
@@ -137,17 +137,18 @@ namespace SharpGLTF.Schema2
 	/// <summary>
 	/// <summary>
 	/// Magnification filter.
 	/// Magnification filter.
 	/// </summary>
 	/// </summary>
-	public enum TextureInterpolationMode
+	public enum TextureInterpolationFilter
 	{
 	{
 		NEAREST = 9728,
 		NEAREST = 9728,
 		LINEAR = 9729,
 		LINEAR = 9729,
+		DEFAULT = 0,
 	}
 	}
 
 
 
 
 	/// <summary>
 	/// <summary>
 	/// Minification filter.
 	/// Minification filter.
 	/// </summary>
 	/// </summary>
-	public enum TextureMipMapMode
+	public enum TextureMipMapFilter
 	{
 	{
 		NEAREST = 9728,
 		NEAREST = 9728,
 		LINEAR = 9729,
 		LINEAR = 9729,
@@ -155,6 +156,7 @@ namespace SharpGLTF.Schema2
 		LINEAR_MIPMAP_NEAREST = 9985,
 		LINEAR_MIPMAP_NEAREST = 9985,
 		NEAREST_MIPMAP_LINEAR = 9986,
 		NEAREST_MIPMAP_LINEAR = 9986,
 		LINEAR_MIPMAP_LINEAR = 9987,
 		LINEAR_MIPMAP_LINEAR = 9987,
+		DEFAULT = 0,
 	}
 	}
 
 
 
 
@@ -381,7 +383,7 @@ namespace SharpGLTF.Schema2
 	
 	
 		private Int32? _node;
 		private Int32? _node;
 		
 		
-		private PathType _path;
+		private PropertyPath _path;
 		
 		
 	
 	
 		/// <inheritdoc />
 		/// <inheritdoc />
@@ -389,7 +391,7 @@ namespace SharpGLTF.Schema2
 		{
 		{
 			base.SerializeProperties(writer);
 			base.SerializeProperties(writer);
 			SerializeProperty(writer, "node", _node);
 			SerializeProperty(writer, "node", _node);
-			SerializePropertyEnumSymbol<PathType>(writer, "path", _path);
+			SerializePropertyEnumSymbol<PropertyPath>(writer, "path", _path);
 		}
 		}
 	
 	
 		/// <inheritdoc />
 		/// <inheritdoc />
@@ -398,7 +400,7 @@ namespace SharpGLTF.Schema2
 			switch (property)
 			switch (property)
 			{
 			{
 				case "node": _node = DeserializePropertyValue<Int32?>(reader); break;
 				case "node": _node = DeserializePropertyValue<Int32?>(reader); break;
-				case "path": _path = DeserializePropertyValue<PathType>(reader); break;
+				case "path": _path = DeserializePropertyValue<PropertyPath>(reader); break;
 				default: base.DeserializeProperty(property, reader); break;
 				default: base.DeserializeProperty(property, reader); break;
 			}
 			}
 		}
 		}
@@ -1105,9 +1107,9 @@ namespace SharpGLTF.Schema2
 	partial class TextureSampler : LogicalChildOfRoot
 	partial class TextureSampler : LogicalChildOfRoot
 	{
 	{
 	
 	
-		private TextureInterpolationMode? _magFilter;
+		private TextureInterpolationFilter? _magFilter;
 		
 		
-		private TextureMipMapMode? _minFilter;
+		private TextureMipMapFilter? _minFilter;
 		
 		
 		private const TextureWrapMode _wrapSDefault = (TextureWrapMode)10497;
 		private const TextureWrapMode _wrapSDefault = (TextureWrapMode)10497;
 		private TextureWrapMode? _wrapS = _wrapSDefault;
 		private TextureWrapMode? _wrapS = _wrapSDefault;
@@ -1120,8 +1122,8 @@ namespace SharpGLTF.Schema2
 		protected override void SerializeProperties(JsonWriter writer)
 		protected override void SerializeProperties(JsonWriter writer)
 		{
 		{
 			base.SerializeProperties(writer);
 			base.SerializeProperties(writer);
-			SerializePropertyEnumValue<TextureInterpolationMode>(writer, "magFilter", _magFilter);
-			SerializePropertyEnumValue<TextureMipMapMode>(writer, "minFilter", _minFilter);
+			SerializePropertyEnumValue<TextureInterpolationFilter>(writer, "magFilter", _magFilter);
+			SerializePropertyEnumValue<TextureMipMapFilter>(writer, "minFilter", _minFilter);
 			SerializePropertyEnumValue<TextureWrapMode>(writer, "wrapS", _wrapS, _wrapSDefault);
 			SerializePropertyEnumValue<TextureWrapMode>(writer, "wrapS", _wrapS, _wrapSDefault);
 			SerializePropertyEnumValue<TextureWrapMode>(writer, "wrapT", _wrapT, _wrapTDefault);
 			SerializePropertyEnumValue<TextureWrapMode>(writer, "wrapT", _wrapT, _wrapTDefault);
 		}
 		}
@@ -1131,8 +1133,8 @@ namespace SharpGLTF.Schema2
 		{
 		{
 			switch (property)
 			switch (property)
 			{
 			{
-				case "magFilter": _magFilter = DeserializePropertyValue<TextureInterpolationMode>(reader); break;
-				case "minFilter": _minFilter = DeserializePropertyValue<TextureMipMapMode>(reader); break;
+				case "magFilter": _magFilter = DeserializePropertyValue<TextureInterpolationFilter>(reader); break;
+				case "minFilter": _minFilter = DeserializePropertyValue<TextureMipMapFilter>(reader); break;
 				case "wrapS": _wrapS = DeserializePropertyValue<TextureWrapMode>(reader); break;
 				case "wrapS": _wrapS = DeserializePropertyValue<TextureWrapMode>(reader); break;
 				case "wrapT": _wrapT = DeserializePropertyValue<TextureWrapMode>(reader); break;
 				case "wrapT": _wrapT = DeserializePropertyValue<TextureWrapMode>(reader); break;
 				default: base.DeserializeProperty(property, reader); break;
 				default: base.DeserializeProperty(property, reader); break;

+ 18 - 18
src/SharpGLTF.Core/Schema2/gltf.Animations.cs

@@ -54,7 +54,7 @@ namespace SharpGLTF.Schema2
         /// <remarks>
         /// <remarks>
         /// There can only be one <see cref="AnimationChannel"/> for every node and path
         /// There can only be one <see cref="AnimationChannel"/> for every node and path
         /// </remarks>
         /// </remarks>
-        private AnimationChannel _UseChannel(Node node, PathType path)
+        private AnimationChannel _UseChannel(Node node, PropertyPath path)
         {
         {
             Guard.MustShareLogicalParent(this, node, nameof(node));
             Guard.MustShareLogicalParent(this, node, nameof(node));
 
 
@@ -74,7 +74,7 @@ namespace SharpGLTF.Schema2
 
 
             sampler.SetVector3Keys(keyframes);
             sampler.SetVector3Keys(keyframes);
 
 
-            this._UseChannel(node, PathType.scale)
+            this._UseChannel(node, PropertyPath.scale)
                 .SetSampler(sampler);
                 .SetSampler(sampler);
         }
         }
 
 
@@ -84,7 +84,7 @@ namespace SharpGLTF.Schema2
 
 
             sampler.SetVector3Keys(keyframes);
             sampler.SetVector3Keys(keyframes);
 
 
-            this._UseChannel(node, PathType.scale)
+            this._UseChannel(node, PropertyPath.scale)
                 .SetSampler(sampler);
                 .SetSampler(sampler);
         }
         }
 
 
@@ -94,7 +94,7 @@ namespace SharpGLTF.Schema2
 
 
             sampler.SetQuaternionKeys(keyframes);
             sampler.SetQuaternionKeys(keyframes);
 
 
-            this._UseChannel(node, PathType.rotation)
+            this._UseChannel(node, PropertyPath.rotation)
                 .SetSampler(sampler);
                 .SetSampler(sampler);
         }
         }
 
 
@@ -104,7 +104,7 @@ namespace SharpGLTF.Schema2
 
 
             sampler.SetQuaternionKeys(keyframes);
             sampler.SetQuaternionKeys(keyframes);
 
 
-            this._UseChannel(node, PathType.rotation)
+            this._UseChannel(node, PropertyPath.rotation)
                 .SetSampler(sampler);
                 .SetSampler(sampler);
         }
         }
 
 
@@ -114,7 +114,7 @@ namespace SharpGLTF.Schema2
 
 
             sampler.SetVector3Keys(keyframes);
             sampler.SetVector3Keys(keyframes);
 
 
-            this._UseChannel(node, PathType.translation)
+            this._UseChannel(node, PropertyPath.translation)
                 .SetSampler(sampler);
                 .SetSampler(sampler);
         }
         }
 
 
@@ -124,7 +124,7 @@ namespace SharpGLTF.Schema2
 
 
             sampler.SetVector3Keys(keyframes);
             sampler.SetVector3Keys(keyframes);
 
 
-            this._UseChannel(node, PathType.translation)
+            this._UseChannel(node, PropertyPath.translation)
                 .SetSampler(sampler);
                 .SetSampler(sampler);
         }
         }
 
 
@@ -135,7 +135,7 @@ namespace SharpGLTF.Schema2
 
 
         public IReadOnlyDictionary<Single, Vector3> FindScaleChannel(Node node)
         public IReadOnlyDictionary<Single, Vector3> FindScaleChannel(Node node)
         {
         {
-            var channel = _channels.FirstOrDefault(item => item.TargetNode == node && item.TargetNodePath == PathType.scale);
+            var channel = _channels.FirstOrDefault(item => item.TargetNode == node && item.TargetNodePath == PropertyPath.scale);
             if (channel == null) return null;
             if (channel == null) return null;
 
 
             return channel.Sampler.AsVector3KeyFrames();
             return channel.Sampler.AsVector3KeyFrames();
@@ -143,7 +143,7 @@ namespace SharpGLTF.Schema2
 
 
         public IReadOnlyDictionary<Single, Quaternion> FindRotationChannel(Node node)
         public IReadOnlyDictionary<Single, Quaternion> FindRotationChannel(Node node)
         {
         {
-            var channel = _channels.FirstOrDefault(item => item.TargetNode == node && item.TargetNodePath == PathType.rotation);
+            var channel = _channels.FirstOrDefault(item => item.TargetNode == node && item.TargetNodePath == PropertyPath.rotation);
             if (channel == null) return null;
             if (channel == null) return null;
 
 
             return channel.Sampler.AsQuaternionKeyFrames();
             return channel.Sampler.AsQuaternionKeyFrames();
@@ -151,7 +151,7 @@ namespace SharpGLTF.Schema2
 
 
         public IReadOnlyDictionary<Single, Vector3> FindTranslationChannel(Node node)
         public IReadOnlyDictionary<Single, Vector3> FindTranslationChannel(Node node)
         {
         {
-            var channel = _channels.FirstOrDefault(item => item.TargetNode == node && item.TargetNodePath == PathType.translation);
+            var channel = _channels.FirstOrDefault(item => item.TargetNode == node && item.TargetNodePath == PropertyPath.translation);
             if (channel == null) return null;
             if (channel == null) return null;
 
 
             return channel.Sampler.AsVector3KeyFrames();
             return channel.Sampler.AsVector3KeyFrames();
@@ -166,7 +166,7 @@ namespace SharpGLTF.Schema2
 
 
         internal AnimationChannelTarget() { }
         internal AnimationChannelTarget() { }
 
 
-        internal AnimationChannelTarget(Node targetNode, PathType targetPath)
+        internal AnimationChannelTarget(Node targetNode, PropertyPath targetPath)
         {
         {
             _node = targetNode.LogicalIndex;
             _node = targetNode.LogicalIndex;
             _path = targetPath;
             _path = targetPath;
@@ -178,7 +178,7 @@ namespace SharpGLTF.Schema2
 
 
         internal int? _NodeId => this._node;
         internal int? _NodeId => this._node;
 
 
-        internal PathType _NodePath => this._path;
+        internal PropertyPath _NodePath => this._path;
 
 
         #endregion
         #endregion
     }
     }
@@ -189,7 +189,7 @@ namespace SharpGLTF.Schema2
 
 
         internal AnimationChannel() { }
         internal AnimationChannel() { }
 
 
-        internal AnimationChannel(Node targetNode, PathType targetPath)
+        internal AnimationChannel(Node targetNode, PropertyPath targetPath)
         {
         {
             _target = new AnimationChannelTarget(targetNode, targetPath);
             _target = new AnimationChannelTarget(targetNode, targetPath);
             _sampler = -1;
             _sampler = -1;
@@ -229,7 +229,7 @@ namespace SharpGLTF.Schema2
             }
             }
         }
         }
 
 
-        public PathType TargetNodePath => this._target?._NodePath ?? PathType.translation;
+        public PropertyPath TargetNodePath => this._target?._NodePath ?? PropertyPath.translation;
 
 
         public int OutputByteStride
         public int OutputByteStride
         {
         {
@@ -237,10 +237,10 @@ namespace SharpGLTF.Schema2
             {
             {
                 switch (TargetNodePath)
                 switch (TargetNodePath)
                 {
                 {
-                    case PathType.translation: return 3;
-                    case PathType.rotation: return 4;
-                    case PathType.scale: return 3;
-                    case PathType.weights: return TargetNode.MorphWeights.Count;
+                    case PropertyPath.translation: return 3;
+                    case PropertyPath.rotation: return 4;
+                    case PropertyPath.scale: return 3;
+                    case PropertyPath.weights: return TargetNode.MorphWeights.Count;
                     default: throw new NotImplementedException();
                     default: throw new NotImplementedException();
                 }
                 }
             }
             }

+ 28 - 0
src/SharpGLTF.Core/Schema2/gltf.Asset.cs

@@ -44,6 +44,16 @@ namespace SharpGLTF.Schema2
 
 
         #endregion
         #endregion
 
 
+        #region extra properties
+
+        // public String Title { get => _GetExtraInfo("title"); set => _SetExtraInfo("title", value); }
+
+        // public String Author { get => _GetExtraInfo("author"); set => _SetExtraInfo("author", value); }
+
+        // public String License { get => _GetExtraInfo("license"); set => _SetExtraInfo("license", value); }
+
+        #endregion
+
         #region API
         #region API
 
 
         public override IEnumerable<Exception> Validate()
         public override IEnumerable<Exception> Validate()
@@ -59,6 +69,24 @@ namespace SharpGLTF.Schema2
             if (curVer > MAXVERSION) yield return new EXCEPTION(this, $"invalid version number {this.Version} expected {MAXVERSION}");
             if (curVer > MAXVERSION) yield return new EXCEPTION(this, $"invalid version number {this.Version} expected {MAXVERSION}");
         }
         }
 
 
+        private string _GetExtraInfo(string key)
+        {
+            if (this.Extras is IReadOnlyDictionary<string, Object> dict)
+            {
+                return dict.TryGetValue(key, out Object val) ? val as String : null;
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        private void _SetExtraInfo(string key, string val)
+        {
+            throw new NotImplementedException();
+            // if (this.Extras == null) this.Extras = new Dictionary<string, Object>();
+        }
+
         #endregion
         #endregion
     }
     }
 }
 }

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

@@ -115,7 +115,7 @@ namespace SharpGLTF.Schema2
             }
             }
 
 
             // search for unknown extensions
             // search for unknown extensions
-            foreach (var unk in allObjects.SelectMany(item => item.Extensions).OfType<Unknown>())
+            foreach (var unk in allObjects.SelectMany(item => item.Extensions).OfType<UnknownNode>())
             {
             {
                 used.Add(unk.Name);
                 used.Add(unk.Name);
             }
             }

+ 18 - 4
src/SharpGLTF.Core/Schema2/gltf.ExtraProperties.cs

@@ -26,7 +26,7 @@ namespace SharpGLTF.Schema2
         public IReadOnlyCollection<JsonSerializable> Extensions => _extensions;
         public IReadOnlyCollection<JsonSerializable> Extensions => _extensions;
 
 
         /// <summary>
         /// <summary>
-        /// Gets the extras object
+        /// Gets the extras object, where the object can be either an <see cref="Object"/>, a <see cref="JsonList"/> or a <see cref="JsonDictionary"/>
         /// </summary>
         /// </summary>
         public Object Extras => _extras;
         public Object Extras => _extras;
 
 
@@ -85,6 +85,20 @@ namespace SharpGLTF.Schema2
             }
             }
         }
         }
 
 
+        /// <summary>
+        /// Gets the Extras property as a <see cref="JsonDictionary"/>
+        /// </summary>
+        /// <param name="overwrite">true if the current value is to be replaced by a <see cref="JsonDictionary"/> instance.</param>
+        /// <returns>A <see cref="JsonDictionary"/> instance or null.</returns>
+        public JsonDictionary TryUseExtrasAsDictionary(bool overwrite)
+        {
+            if (this._extras is JsonDictionary dict) return dict;
+
+            if (overwrite) this._extras = new JsonDictionary();
+
+            return this._extras as JsonDictionary;
+        }
+
         #endregion
         #endregion
 
 
         #region serialization API
         #region serialization API
@@ -117,7 +131,7 @@ namespace SharpGLTF.Schema2
 
 
                 string key = null;
                 string key = null;
 
 
-                if (val is Unknown unk) key = unk.Name;
+                if (val is UnknownNode unk) key = unk.Name;
                 else key = ExtensionsFactory.Identify(context.GetType(), val.GetType());
                 else key = ExtensionsFactory.Identify(context.GetType(), val.GetType());
 
 
                 if (key == null) continue;
                 if (key == null) continue;
@@ -138,7 +152,7 @@ namespace SharpGLTF.Schema2
             {
             {
                 case "extensions": _DeserializeExtensions(this, reader, _extensions); break;
                 case "extensions": _DeserializeExtensions(this, reader, _extensions); break;
 
 
-                case "extras": _extras = DeserializeObject(reader); break;
+                case "extras": _extras = DeserializeUnknownObject(reader); break;
 
 
                 default: reader.Skip(); break;
                 default: reader.Skip(); break;
             }
             }
@@ -156,7 +170,7 @@ namespace SharpGLTF.Schema2
 
 
                     var val = ExtensionsFactory.Create(parent, key);
                     var val = ExtensionsFactory.Create(parent, key);
 
 
-                    if (val == null) val = new Unknown(key);
+                    if (val == null) val = new UnknownNode(key);
 
 
                     val.Deserialize(reader);
                     val.Deserialize(reader);
                     extensions.Add(val);
                     extensions.Add(val);

+ 28 - 11
src/SharpGLTF.Core/Schema2/gltf.MaterialChannel.cs

@@ -158,6 +158,22 @@ namespace SharpGLTF.Schema2
 
 
         public String Key => _Key;
         public String Key => _Key;
 
 
+        /// <summary>
+        /// Gets a value indicating whether this channel supports a Color factor.
+        /// </summary>
+        public bool IsColorSupported { get; private set; }
+
+        public Vector4 Color
+        {
+            get => _ColorGetter();
+            set => _ColorSetter(value);
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this channel supports textures.
+        /// </summary>
+        public bool IsTextureSupported => _TextureInfo != null;
+
         /// <summary>
         /// <summary>
         /// Gets the <see cref="Texture"/> instance used by this Material, or null.
         /// Gets the <see cref="Texture"/> instance used by this Material, or null.
         /// </summary>
         /// </summary>
@@ -172,22 +188,23 @@ namespace SharpGLTF.Schema2
 
 
         public TextureSampler TextureSampler => Texture?.Sampler;
         public TextureSampler TextureSampler => Texture?.Sampler;
 
 
+        /// <summary>
+        /// Gets a value indicating whether this channel supports texture amount factor.
+        /// </summary>
         public bool IsTextureAmountSupported { get; private set; }
         public bool IsTextureAmountSupported { get; private set; }
 
 
+        /// <summary>
+        /// Gets or sets the Texture weight in the final shader.
+        /// </summary>
+        /// <remarks>
+        /// Not all channels support this property.
+        /// </remarks>
         public Single TextureAmount
         public Single TextureAmount
         {
         {
             get => _AmountGetter();
             get => _AmountGetter();
             set => _AmountSetter(value);
             set => _AmountSetter(value);
         }
         }
 
 
-        public bool IsColorSupported { get; private set; }
-
-        public Vector4 Color
-        {
-            get => _ColorGetter();
-            set => _ColorSetter(value);
-        }
-
         #endregion
         #endregion
 
 
         #region API
         #region API
@@ -203,8 +220,8 @@ namespace SharpGLTF.Schema2
         public void SetTexture(
         public void SetTexture(
             int texCoord,
             int texCoord,
             Image texImg,
             Image texImg,
-            TextureMipMapMode min = TextureMipMapMode.LINEAR_MIPMAP_LINEAR,
-            TextureInterpolationMode mag = TextureInterpolationMode.LINEAR,
+            TextureMipMapFilter min = TextureMipMapFilter.DEFAULT,
+            TextureInterpolationFilter mag = TextureInterpolationFilter.DEFAULT,
             TextureWrapMode ws = TextureWrapMode.REPEAT,
             TextureWrapMode ws = TextureWrapMode.REPEAT,
             TextureWrapMode wt = TextureWrapMode.REPEAT)
             TextureWrapMode wt = TextureWrapMode.REPEAT)
         {
         {
@@ -212,7 +229,7 @@ namespace SharpGLTF.Schema2
 
 
             if (_Material == null) throw new InvalidOperationException();
             if (_Material == null) throw new InvalidOperationException();
 
 
-            var sampler = _Material.LogicalParent.UseSampler(mag, min, ws, wt);
+            var sampler = _Material.LogicalParent.UseSampler(min, mag, ws, wt);
             var texture = _Material.LogicalParent.UseTexture(texImg, sampler);
             var texture = _Material.LogicalParent.UseTexture(texImg, sampler);
 
 
             SetTexture(texCoord, texture);
             SetTexture(texCoord, texture);

+ 36 - 19
src/SharpGLTF.Core/Schema2/gltf.Textures.cs

@@ -6,6 +6,10 @@ using System.Text;
 
 
 namespace SharpGLTF.Schema2
 namespace SharpGLTF.Schema2
 {
 {
+    using TEXLERP = TextureInterpolationFilter;
+    using TEXMIPMAP = TextureMipMapFilter;
+    using TEXWRAP = TextureWrapMode;
+
     [System.Diagnostics.DebuggerDisplay("Texture[{LogicalIndex}] {Name}")]
     [System.Diagnostics.DebuggerDisplay("Texture[{LogicalIndex}] {Name}")]
     public sealed partial class Texture
     public sealed partial class Texture
     {
     {
@@ -52,12 +56,12 @@ namespace SharpGLTF.Schema2
 
 
         internal TextureSampler() { }
         internal TextureSampler() { }
 
 
-        internal TextureSampler(TextureInterpolationMode mag, TextureMipMapMode min, TextureWrapMode ws, TextureWrapMode wt)
+        internal TextureSampler(TEXMIPMAP min, TEXLERP mag, TEXWRAP ws, TEXWRAP wt)
         {
         {
-            _magFilter = mag;
-            _minFilter = min;
-            _wrapS = ws;
-            _wrapT = wt;
+            _magFilter = mag.AsNullable(TEXLERP.DEFAULT);
+            _minFilter = min.AsNullable(TEXMIPMAP.DEFAULT);
+            _wrapS = ws.AsNullable(_wrapSDefault);
+            _wrapT = wt.AsNullable(_wrapTDefault);
         }
         }
 
 
         #endregion
         #endregion
@@ -69,18 +73,29 @@ namespace SharpGLTF.Schema2
         /// </summary>
         /// </summary>
         public int LogicalIndex => this.LogicalParent.LogicalTextureSamplers.IndexOfReference(this);
         public int LogicalIndex => this.LogicalParent.LogicalTextureSamplers.IndexOfReference(this);
 
 
-        public TextureInterpolationMode MagFilter => _magFilter.AsValue(TextureInterpolationMode.LINEAR);
+        public TEXMIPMAP MinFilter => _minFilter.AsValue(TEXMIPMAP.DEFAULT);
 
 
-        public TextureMipMapMode MinFilter => _minFilter.AsValue(TextureMipMapMode.LINEAR);
+        public TEXLERP MagFilter => _magFilter.AsValue(TEXLERP.DEFAULT);
 
 
-        public TextureWrapMode WrapS => _wrapS.AsValue(_wrapSDefault);
+        public TEXWRAP WrapS => _wrapS.AsValue(_wrapSDefault);
 
 
-        public TextureWrapMode WrapT => _wrapT.AsValue(_wrapTDefault);
+        public TEXWRAP WrapT => _wrapT.AsValue(_wrapTDefault);
 
 
         #endregion
         #endregion
-    }
 
 
-    
+        #region API
+
+        internal static bool IsDefault(TEXMIPMAP min, TEXLERP mag, TEXWRAP ws, TEXWRAP wt)
+        {
+            if (min != TEXMIPMAP.DEFAULT) return false;
+            if (mag != TEXLERP.DEFAULT) return false;
+            if (ws != _wrapSDefault) return false;
+            if (wt != _wrapTDefault) return false;
+            return true;
+        }
+
+        #endregion
+    }
 
 
     public partial class ModelRoot
     public partial class ModelRoot
     {
     {
@@ -88,19 +103,21 @@ namespace SharpGLTF.Schema2
         /// Creates or reuses a <see cref="TextureSampler"/> instance
         /// Creates or reuses a <see cref="TextureSampler"/> instance
         /// at <see cref="ModelRoot.LogicalTextureSamplers"/>.
         /// at <see cref="ModelRoot.LogicalTextureSamplers"/>.
         /// </summary>
         /// </summary>
-        /// <param name="mag">A value of <see cref="TextureInterpolationMode"/>.</param>
-        /// <param name="min">A value of <see cref="TextureMipMapMode"/>.</param>
-        /// <param name="ws">The <see cref="TextureWrapMode"/> in the S axis.</param>
-        /// <param name="wt">The <see cref="TextureWrapMode"/> in the T axis.</param>
-        /// <returns>A <see cref="TextureSampler"/> instance.</returns>
-        public TextureSampler UseSampler(TextureInterpolationMode mag, TextureMipMapMode min, TextureWrapMode ws, TextureWrapMode wt)
+        /// <param name="min">A value of <see cref="TEXMIPMAP"/>.</param>
+        /// <param name="mag">A value of <see cref="TEXLERP"/>.</param>
+        /// <param name="ws">The <see cref="TEXWRAP"/> in the S axis.</param>
+        /// <param name="wt">The <see cref="TEXWRAP"/> in the T axis.</param>
+        /// <returns>A <see cref="TextureSampler"/> instance, or null if all the arguments are default values.</returns>
+        public TextureSampler UseSampler(TEXMIPMAP min, TEXLERP mag, TEXWRAP ws, TEXWRAP wt)
         {
         {
+            if (TextureSampler.IsDefault(min, mag, ws, wt)) return null;
+
             foreach (var s in this._samplers)
             foreach (var s in this._samplers)
             {
             {
-                if (s.MagFilter == mag && s.MinFilter == min && s.WrapS == ws && s.WrapT == wt) return s;
+                if (s.MinFilter == min && s.MagFilter == mag && s.WrapS == ws && s.WrapT == wt) return s;
             }
             }
 
 
-            var ss = new TextureSampler(mag, min, ws, wt);
+            var ss = new TextureSampler(min, mag, ws, wt);
 
 
             this._samplers.Add(ss);
             this._samplers.Add(ss);
 
 

+ 4 - 4
src/SharpGLTF.Toolkit/Materials/Texture.cs

@@ -7,8 +7,8 @@ namespace SharpGLTF.Materials
 {
 {
     using BYTES = ArraySegment<Byte>;
     using BYTES = ArraySegment<Byte>;
 
 
-    using TEXLERP = Schema2.TextureInterpolationMode;
-    using TEXMIPMAP = Schema2.TextureMipMapMode;
+    using TEXLERP = Schema2.TextureInterpolationFilter;
+    using TEXMIPMAP = Schema2.TextureMipMapFilter;
     using TEXWRAP = Schema2.TextureWrapMode;
     using TEXWRAP = Schema2.TextureWrapMode;
 
 
     [System.Diagnostics.DebuggerDisplay("Texture {CoordinateSet} {MinFilter} {MagFilter} {WrapS} {WrapT} {Rotation} {Offset} {Scale}")]
     [System.Diagnostics.DebuggerDisplay("Texture {CoordinateSet} {MinFilter} {MagFilter} {WrapS} {WrapT} {Rotation} {Offset} {Scale}")]
@@ -36,9 +36,9 @@ namespace SharpGLTF.Materials
 
 
         public BYTES ImageContent { get; set; }
         public BYTES ImageContent { get; set; }
 
 
-        public TEXMIPMAP MinFilter { get; set; } = TEXMIPMAP.LINEAR;
+        public TEXMIPMAP MinFilter { get; set; } = TEXMIPMAP.DEFAULT;
 
 
-        public TEXLERP MagFilter { get; set; } = TEXLERP.LINEAR;
+        public TEXLERP MagFilter { get; set; } = TEXLERP.DEFAULT;
 
 
         public TEXWRAP WrapS { get; set; } = TEXWRAP.REPEAT;
         public TEXWRAP WrapS { get; set; } = TEXWRAP.REPEAT;
 
 

+ 0 - 80
tests/SharpGLTF.Tests/Geometry/CreateMeshTests.cs

@@ -1,80 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Numerics;
-using System.Text;
-
-using NUnit.Framework;
-
-namespace SharpGLTF.Geometry
-{
-    using Schema2;
-
-    [TestFixture]
-    public class CreateMeshTests
-    {
-        [Test]
-        public void CreateTriangleScene()
-        {
-            // define the data of a triangle:
-
-            var positions = new[]
-            {
-                new Vector3(10,-10,0),
-                new Vector3(0,10,0),
-                new Vector3(-10,-10,0)
-            };
-
-            var normals = new[]
-            {
-                Vector3.UnitZ,
-                Vector3.UnitZ,
-                Vector3.UnitZ
-            };
-
-            var indices = new UInt32[] { 0, 1, 2 };
-
-            // create a new mesh:
-            var srcMesh = new Mesh<int?>();
-
-            // setup a mesh primitive
-            var srcPrimitive = srcMesh.CreatePrimitive();
-            srcPrimitive.AllocateVertices(positions.Length, "POSITION", "NORMAL");  // (#1)
-            srcPrimitive.AllocateIndices(indices.Length, PrimitiveType.TRIANGLES);  // (#2)
-
-            // assign vertices and indices
-            srcPrimitive.Vertices[0].SetValues(0, positions);
-            srcPrimitive.Vertices[1].SetValues(0, normals);
-            srcPrimitive.Indices.SetValues(0, indices);
-            srcPrimitive.Material = 0; // using material with index 0, which will be created later
-
-            // check the values we've set match the input data
-            CollectionAssert.AreEqual(positions, srcPrimitive.Vertices[0].AsVector3Array());
-            CollectionAssert.AreEqual(normals, srcPrimitive.Vertices[1].AsVector3Array());
-            CollectionAssert.AreEqual(indices, srcPrimitive.Indices.AsIntegerArray());
-
-            // Notice that until now, we've been working with objects in the .Geometry namespace.
-
-            // Now we switch to the .Schema2 namespace and we create a new scene:
-
-            var model = ModelRoot.CreateModel();                        
-            var scene = model.UseScene("default");
-            var rnode = scene.CreateNode("main scene");
-
-            var material = model.CreateMaterial("DefaultMaterial")
-                .WithDefault(new Vector4(1, 0, 0, 1))
-                .WithDoubleSide(true);
-
-            rnode.Mesh = model.CreateMesh();
-
-            // this assigns the mesh we've created before to this schema mesh.
-            // Notice that the schema buffers being created will be using the
-            // memory allocated by (#1) and (#2)
-            srcMesh.CopyTo(rnode.Mesh);
-                        
-            model.AttachToCurrentTest("Triangle.gltf");
-            model.AttachToCurrentTest("Triangle.glb");
-
-            TestContext.CurrentContext.AttachShowDirLink();
-        }        
-    }
-}

+ 19 - 16
tests/SharpGLTF.Tests/Schema2/Authoring/BasicSceneCreationTests.cs

@@ -30,40 +30,43 @@ namespace SharpGLTF.Schema2.Authoring
             var root = ModelRoot.CreateModel();
             var root = ModelRoot.CreateModel();
             var scene = root.UseScene("Empty Scene");
             var scene = root.UseScene("Empty Scene");
 
 
-            /*
+            var dict = root.TryUseExtrasAsDictionary(true);
 
 
-            root.Extras["author"] = "me";
+            dict["author"] = "me";
 
 
-            root.Extras["value1"] = 17;
-            root.Extras["array1"] = new Single[] { 1, 2, 3 };
-            root.Extras["dict1"] = new Dictionary<String, Object>
+            dict["value1"] = 17;
+            dict["array1"] = new IO.JsonList { 1, 2, 3 };
+            dict["dict1"] = new IO.JsonDictionary
             {
             {
                 ["A"] = 16,
                 ["A"] = 16,
                 ["B"] = "delta",
                 ["B"] = "delta",
-                ["C"] = new Single[] { 4, 6, 7 },
-                ["D"] = new Dictionary<String, Object> { ["S"]= 1, ["T"] = 2 }
+                ["C"] = new IO.JsonList { 4, 6, 7 },
+                ["D"] = new IO.JsonDictionary { ["S"]= 1, ["T"] = 2 }
             };
             };
 
 
             var json = root.GetJSON(Newtonsoft.Json.Formatting.Indented);
             var json = root.GetJSON(Newtonsoft.Json.Formatting.Indented);
-            var bytes = root.WriteGLB();
 
 
+            var bytes = root.WriteGLB();
             var rootBis = ModelRoot.ParseGLB(bytes);
             var rootBis = ModelRoot.ParseGLB(bytes);
 
 
-            CollectionAssert.AreEqual(root.Extras, rootBis.Extras);
+            var adict = root.TryUseExtrasAsDictionary(false);
+            var bdict = rootBis.TryUseExtrasAsDictionary(false);
 
 
-            Assert.AreEqual(root.Extras["author"], rootBis.Extras["author"]);
-            Assert.AreEqual(root.Extras["value1"], rootBis.Extras["value1"]);
+            CollectionAssert.AreEqual(adict, bdict);
+
+            Assert.AreEqual(adict["author"], bdict["author"]);
+            Assert.AreEqual(adict["value1"], bdict["value1"]);
             CollectionAssert.AreEqual
             CollectionAssert.AreEqual
                 (
                 (
-                root.Extras["array1"] as Array,
-                rootBis.Extras["array1"] as Array
+                adict["array1"] as IO.JsonList,
+                bdict["array1"] as IO.JsonList
                 );
                 );
 
 
             CollectionAssert.AreEqual
             CollectionAssert.AreEqual
                 (
                 (
-                root.Extras["dict1"] as Dictionary<string, Object>,
-                rootBis.Extras["dict1"] as Dictionary<string, Object>
-                );*/
+                adict["dict1"] as IO.JsonDictionary,
+                bdict["dict1"] as IO.JsonDictionary
+                );
         }
         }
 
 
         [Test(Description = "Creates a scene with lights")]
         [Test(Description = "Creates a scene with lights")]

+ 0 - 1
tests/SharpGLTF.Tests/SharpGLTF.Tests.csproj

@@ -16,7 +16,6 @@
   </ItemGroup>
   </ItemGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\..\src\MeshBuffers\MeshBuffers.csproj" />
     <ProjectReference Include="..\..\src\SharpGLTF.Toolkit\SharpGLTF.Toolkit.csproj" />
     <ProjectReference Include="..\..\src\SharpGLTF.Toolkit\SharpGLTF.Toolkit.csproj" />
     <ProjectReference Include="..\..\src\SharpGLTF.Core\SharpGLTF.Core.csproj" />
     <ProjectReference Include="..\..\src\SharpGLTF.Core\SharpGLTF.Core.csproj" />
   </ItemGroup>
   </ItemGroup>