Browse Source

WIP: KHR_mesh_quantization support

Vicente Penades 5 years ago
parent
commit
d68ea62879

+ 3 - 3
src/SharpGLTF.Core/Debug/DebuggerDisplay.cs

@@ -27,7 +27,7 @@ namespace SharpGLTF.Debug
             return attributeName;
             return attributeName;
         }
         }
 
 
-        public static String ToReport(this Memory.MemoryAccessInfo minfo)
+        public static String ToReport(this Memory.MemoryEncoding minfo)
         {
         {
             var txt = GetAttributeShortName(minfo.Name);
             var txt = GetAttributeShortName(minfo.Name);
             if (minfo.ByteOffset != 0) txt += $" Offs:{minfo.ByteOffset}ᴮʸᵗᵉˢ";
             if (minfo.ByteOffset != 0) txt += $" Offs:{minfo.ByteOffset}ᴮʸᵗᵉˢ";
@@ -93,7 +93,7 @@ namespace SharpGLTF.Debug
             if (vcounts.Count() > 1)
             if (vcounts.Count() > 1)
             {
             {
                 var vAccessors = prim.VertexAccessors
                 var vAccessors = prim.VertexAccessors
-                    .OrderBy(item => item.Key, Memory.MemoryAccessInfo.NameComparer)
+                    .OrderBy(item => item.Key, Memory.MemoryEncoding.NameComparer)
                     .Select(item => $"{GetAttributeShortName(item.Key)}={item.Value.ToReportShort()}")
                     .Select(item => $"{GetAttributeShortName(item.Key)}={item.Value.ToReportShort()}")
                     .ToList();
                     .ToList();
 
 
@@ -109,7 +109,7 @@ namespace SharpGLTF.Debug
                 }
                 }
 
 
                 var vAccessors = prim.VertexAccessors
                 var vAccessors = prim.VertexAccessors
-                    .OrderBy(item => item.Key, Memory.MemoryAccessInfo.NameComparer)
+                    .OrderBy(item => item.Key, Memory.MemoryEncoding.NameComparer)
                     .Select(item => toShort(item.Key, item.Value))
                     .Select(item => toShort(item.Key, item.Value))
                     .ToList();
                     .ToList();
 
 

+ 1 - 0
src/SharpGLTF.Core/IO/ReadContext.cs

@@ -225,6 +225,7 @@ namespace SharpGLTF.IO
             try
             try
             {
             {
                 root.Deserialize(ref reader);
                 root.Deserialize(ref reader);
+                root.OnDeserializationCompleted();
             }
             }
             catch (JsonException rex)
             catch (JsonException rex)
             {
             {

+ 130 - 123
src/SharpGLTF.Core/Memory/MemoryAccessor.cs

@@ -9,10 +9,10 @@ using ENCODING = SharpGLTF.Schema2.EncodingType;
 namespace SharpGLTF.Memory
 namespace SharpGLTF.Memory
 {
 {
     /// <summary>
     /// <summary>
-    /// Defines the pattern in which a <see cref="ArraySegment{Byte}"/> is accessed and decoded to meaningful values.
+    /// Defines the memory encoding pattern for an arbitrary <see cref="ArraySegment{Byte}"/>.
     /// </summary>
     /// </summary>
     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
-    public struct MemoryAccessInfo
+    public struct MemoryEncoding
     {
     {
         #region debug
         #region debug
 
 
@@ -25,42 +25,42 @@ namespace SharpGLTF.Memory
 
 
         #region constructor
         #region constructor
 
 
-        public static MemoryAccessInfo[] Create(params string[] attributes)
+        public static MemoryEncoding[] Create(params string[] attributes)
         {
         {
             return attributes.Select(item => CreateDefaultElement(item)).ToArray();
             return attributes.Select(item => CreateDefaultElement(item)).ToArray();
         }
         }
 
 
-        public static MemoryAccessInfo CreateDefaultElement(string attribute)
+        public static MemoryEncoding CreateDefaultElement(string attribute)
         {
         {
             switch (attribute)
             switch (attribute)
             {
             {
-                case "INDEX": return new MemoryAccessInfo("INDEX", 0, 0, 0, DIMENSIONS.SCALAR, ENCODING.UNSIGNED_INT, false);
+                case "INDEX": return new MemoryEncoding("INDEX", 0, 0, 0, DIMENSIONS.SCALAR, ENCODING.UNSIGNED_INT, false);
 
 
-                case "POSITION": return new MemoryAccessInfo("POSITION", 0, 0, 0, DIMENSIONS.VEC3);
-                case "NORMAL": return new MemoryAccessInfo("NORMAL", 0, 0, 0, DIMENSIONS.VEC3);
-                case "TANGENT": return new MemoryAccessInfo("TANGENT", 0, 0, 0, DIMENSIONS.VEC4);
+                case "POSITION": return new MemoryEncoding("POSITION", 0, 0, 0, DIMENSIONS.VEC3);
+                case "NORMAL": return new MemoryEncoding("NORMAL", 0, 0, 0, DIMENSIONS.VEC3);
+                case "TANGENT": return new MemoryEncoding("TANGENT", 0, 0, 0, DIMENSIONS.VEC4);
 
 
-                case "TEXCOORD_0": return new MemoryAccessInfo("TEXCOORD_0", 0, 0, 0, DIMENSIONS.VEC2);
-                case "TEXCOORD_1": return new MemoryAccessInfo("TEXCOORD_1", 0, 0, 0, DIMENSIONS.VEC2);
-                case "TEXCOORD_2": return new MemoryAccessInfo("TEXCOORD_2", 0, 0, 0, DIMENSIONS.VEC2);
-                case "TEXCOORD_3": return new MemoryAccessInfo("TEXCOORD_3", 0, 0, 0, DIMENSIONS.VEC2);
+                case "TEXCOORD_0": return new MemoryEncoding("TEXCOORD_0", 0, 0, 0, DIMENSIONS.VEC2);
+                case "TEXCOORD_1": return new MemoryEncoding("TEXCOORD_1", 0, 0, 0, DIMENSIONS.VEC2);
+                case "TEXCOORD_2": return new MemoryEncoding("TEXCOORD_2", 0, 0, 0, DIMENSIONS.VEC2);
+                case "TEXCOORD_3": return new MemoryEncoding("TEXCOORD_3", 0, 0, 0, DIMENSIONS.VEC2);
 
 
-                case "COLOR_0": return new MemoryAccessInfo("COLOR_0", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE, true);
-                case "COLOR_1": return new MemoryAccessInfo("COLOR_1", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE, true);
-                case "COLOR_2": return new MemoryAccessInfo("COLOR_2", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE, true);
-                case "COLOR_3": return new MemoryAccessInfo("COLOR_3", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE, true);
+                case "COLOR_0": return new MemoryEncoding("COLOR_0", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE, true);
+                case "COLOR_1": return new MemoryEncoding("COLOR_1", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE, true);
+                case "COLOR_2": return new MemoryEncoding("COLOR_2", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE, true);
+                case "COLOR_3": return new MemoryEncoding("COLOR_3", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE, true);
 
 
-                case "JOINTS_0": return new MemoryAccessInfo("JOINTS_0", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE);
-                case "JOINTS_1": return new MemoryAccessInfo("JOINTS_1", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE);
+                case "JOINTS_0": return new MemoryEncoding("JOINTS_0", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE);
+                case "JOINTS_1": return new MemoryEncoding("JOINTS_1", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE);
 
 
-                case "WEIGHTS_0": return new MemoryAccessInfo("WEIGHTS_0", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE, true);
-                case "WEIGHTS_1": return new MemoryAccessInfo("WEIGHTS_1", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE, true);
+                case "WEIGHTS_0": return new MemoryEncoding("WEIGHTS_0", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE, true);
+                case "WEIGHTS_1": return new MemoryEncoding("WEIGHTS_1", 0, 0, 0, DIMENSIONS.VEC4, ENCODING.UNSIGNED_BYTE, true);
             }
             }
 
 
             throw new NotImplementedException();
             throw new NotImplementedException();
         }
         }
 
 
-        public MemoryAccessInfo(string name, int byteOffset, int itemsCount, int byteStride, DIMENSIONS dimensions, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false)
+        public MemoryEncoding(string name, int byteOffset, int itemsCount, int byteStride, DIMENSIONS dimensions, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false)
         {
         {
             this.Name = name;
             this.Name = name;
             this.ByteOffset = byteOffset;
             this.ByteOffset = byteOffset;
@@ -71,9 +71,9 @@ namespace SharpGLTF.Memory
             this.Normalized = normalized;
             this.Normalized = normalized;
         }
         }
 
 
-        public MemoryAccessInfo Slice(int itemStart, int itemCount)
+        public MemoryEncoding Slice(int itemStart, int itemCount)
         {
         {
-            var stride = GetRowByteLength();
+            var stride = _GetRowByteLength();
 
 
             var clone = this;
             var clone = this;
             clone.ByteOffset += itemStart * stride;
             clone.ByteOffset += itemStart * stride;
@@ -96,25 +96,12 @@ namespace SharpGLTF.Memory
 
 
         #endregion
         #endregion
 
 
-        #region API
+        #region properties
 
 
         /// <summary>
         /// <summary>
         /// Gets the number of bytes of the current encoded Item, padded to 4 bytes.
         /// Gets the number of bytes of the current encoded Item, padded to 4 bytes.
         /// </summary>
         /// </summary>
-        public int PaddedByteLength => GetRowByteLength();
-
-        public int GetRowByteLength()
-        {
-            var xlen = Encoding.ByteLength();
-
-            if (Dimensions != Schema2.DimensionType.SCALAR || Name != "INDEX")
-            {
-                xlen *= this.Dimensions.DimCount();
-                xlen = xlen.WordPadded();
-            }
-
-            return Math.Max(ByteStride, xlen);
-        }
+        public int PaddedByteLength => _GetRowByteLength();
 
 
         public Boolean IsValidVertexAttribute
         public Boolean IsValidVertexAttribute
         {
         {
@@ -151,7 +138,24 @@ namespace SharpGLTF.Memory
             }
             }
         }
         }
 
 
-        public static int SetInterleavedInfo(MemoryAccessInfo[] attributes, int byteOffset, int itemsCount)
+        #endregion
+
+        #region API
+
+        private int _GetRowByteLength()
+        {
+            var xlen = Encoding.ByteLength();
+
+            if (Dimensions != Schema2.DimensionType.SCALAR || Name != "INDEX")
+            {
+                xlen *= this.Dimensions.DimCount();
+                xlen = xlen.WordPadded();
+            }
+
+            return Math.Max(ByteStride, xlen);
+        }
+
+        public static int SetInterleavedInfo(MemoryEncoding[] attributes, int byteOffset, int itemsCount)
         {
         {
             Guard.NotNull(attributes, nameof(attributes));
             Guard.NotNull(attributes, nameof(attributes));
 
 
@@ -182,11 +186,11 @@ namespace SharpGLTF.Memory
             return byteStride;
             return byteStride;
         }
         }
 
 
-        public static MemoryAccessInfo[] Slice(MemoryAccessInfo[] attributes, int start, int count)
+        public static MemoryEncoding[] Slice(MemoryEncoding[] attributes, int start, int count)
         {
         {
             Guard.NotNull(attributes, nameof(attributes));
             Guard.NotNull(attributes, nameof(attributes));
 
 
-            var dst = new MemoryAccessInfo[attributes.Length];
+            var dst = new MemoryEncoding[attributes.Length];
 
 
             for (int i = 0; i < dst.Length; ++i)
             for (int i = 0; i < dst.Length; ++i)
             {
             {
@@ -200,34 +204,11 @@ namespace SharpGLTF.Memory
 
 
         #region nested types
         #region nested types
 
 
-        private static int _GetSortingScore(string attribute)
-        {
-            switch (attribute)
-            {
-                case "POSITION": return 0;
-                case "NORMAL": return 1;
-                case "TANGENT": return 2;
-
-                case "COLOR_0": return 10;
-                case "COLOR_1": return 11;
-                case "COLOR_2": return 12;
-                case "COLOR_3": return 13;
-
-                case "TEXCOORD_0": return 20;
-                case "TEXCOORD_1": return 21;
-                case "TEXCOORD_2": return 22;
-                case "TEXCOORD_3": return 23;
-
-                case "JOINTS_0": return 50;
-                case "JOINTS_1": return 51;
-                case "WEIGHTS_0": return 50;
-                case "WEIGHTS_1": return 51;
-                default: return 100;
-            }
-        }
-
         internal static IComparer<string> NameComparer { get; private set; } = new AttributeComparer();
         internal static IComparer<string> NameComparer { get; private set; } = new AttributeComparer();
 
 
+        /// <summary>
+        /// Comparer used to sort attribute names in a friendly order.
+        /// </summary>
         private class AttributeComparer : IComparer<String>
         private class AttributeComparer : IComparer<String>
         {
         {
             public int Compare(string x, string y)
             public int Compare(string x, string y)
@@ -237,6 +218,32 @@ namespace SharpGLTF.Memory
 
 
                 return xx.CompareTo(yy);
                 return xx.CompareTo(yy);
             }
             }
+
+            private static int _GetSortingScore(string attribute)
+            {
+                switch (attribute)
+                {
+                    case "POSITION": return 0;
+                    case "NORMAL": return 1;
+                    case "TANGENT": return 2;
+
+                    case "COLOR_0": return 10;
+                    case "COLOR_1": return 11;
+                    case "COLOR_2": return 12;
+                    case "COLOR_3": return 13;
+
+                    case "TEXCOORD_0": return 20;
+                    case "TEXCOORD_1": return 21;
+                    case "TEXCOORD_2": return 22;
+                    case "TEXCOORD_3": return 23;
+
+                    case "JOINTS_0": return 50;
+                    case "JOINTS_1": return 51;
+                    case "WEIGHTS_0": return 50;
+                    case "WEIGHTS_1": return 51;
+                    default: return 100;
+                }
+            }
         }
         }
 
 
         #endregion
         #endregion
@@ -250,15 +257,15 @@ namespace SharpGLTF.Memory
     {
     {
         #region constructor
         #region constructor
 
 
-        public MemoryAccessor(ArraySegment<Byte> data, MemoryAccessInfo info)
+        public MemoryAccessor(ArraySegment<Byte> data, MemoryEncoding info)
         {
         {
-            this._Attribute = info;
+            this._Encoding = info;
             this._Data = data;
             this._Data = data;
         }
         }
 
 
-        public MemoryAccessor(MemoryAccessInfo info)
+        public MemoryAccessor(MemoryEncoding info)
         {
         {
-            this._Attribute = info;
+            this._Encoding = info;
             this._Data = default;
             this._Data = default;
         }
         }
 
 
@@ -266,10 +273,10 @@ namespace SharpGLTF.Memory
         {
         {
             Guard.NotNull(bottom, nameof(bottom));
             Guard.NotNull(bottom, nameof(bottom));
             Guard.NotNull(topValues, nameof(topValues));
             Guard.NotNull(topValues, nameof(topValues));
-            Guard.IsTrue(bottom._Attribute.Dimensions == topValues._Attribute.Dimensions, nameof(topValues));
-            Guard.IsTrue(topKeys.Count <= bottom._Attribute.ItemsCount, nameof(topKeys));
-            Guard.IsTrue(topKeys.Count == topValues._Attribute.ItemsCount, nameof(topValues));
-            Guard.IsTrue(topKeys.All(item => item < (uint)bottom._Attribute.ItemsCount), nameof(topKeys));
+            Guard.IsTrue(bottom._Encoding.Dimensions == topValues._Encoding.Dimensions, nameof(topValues));
+            Guard.IsTrue(topKeys.Count <= bottom._Encoding.ItemsCount, nameof(topKeys));
+            Guard.IsTrue(topKeys.Count == topValues._Encoding.ItemsCount, nameof(topValues));
+            Guard.IsTrue(topKeys.All(item => item < (uint)bottom._Encoding.ItemsCount), nameof(topKeys));
 
 
             return new SparseArray<Single>(bottom.AsScalarArray(), topValues.AsScalarArray(), topKeys);
             return new SparseArray<Single>(bottom.AsScalarArray(), topValues.AsScalarArray(), topKeys);
         }
         }
@@ -278,10 +285,10 @@ namespace SharpGLTF.Memory
         {
         {
             Guard.NotNull(bottom, nameof(bottom));
             Guard.NotNull(bottom, nameof(bottom));
             Guard.NotNull(topValues, nameof(topValues));
             Guard.NotNull(topValues, nameof(topValues));
-            Guard.IsTrue(bottom._Attribute.Dimensions == topValues._Attribute.Dimensions, nameof(topValues));
-            Guard.IsTrue(topKeys.Count <= bottom._Attribute.ItemsCount, nameof(topKeys));
-            Guard.IsTrue(topKeys.Count == topValues._Attribute.ItemsCount, nameof(topValues));
-            Guard.IsTrue(topKeys.All(item => item < (uint)bottom._Attribute.ItemsCount), nameof(topKeys));
+            Guard.IsTrue(bottom._Encoding.Dimensions == topValues._Encoding.Dimensions, nameof(topValues));
+            Guard.IsTrue(topKeys.Count <= bottom._Encoding.ItemsCount, nameof(topKeys));
+            Guard.IsTrue(topKeys.Count == topValues._Encoding.ItemsCount, nameof(topValues));
+            Guard.IsTrue(topKeys.All(item => item < (uint)bottom._Encoding.ItemsCount), nameof(topKeys));
 
 
             return new SparseArray<Vector2>(bottom.AsVector2Array(), topValues.AsVector2Array(), topKeys);
             return new SparseArray<Vector2>(bottom.AsVector2Array(), topValues.AsVector2Array(), topKeys);
         }
         }
@@ -290,10 +297,10 @@ namespace SharpGLTF.Memory
         {
         {
             Guard.NotNull(bottom, nameof(bottom));
             Guard.NotNull(bottom, nameof(bottom));
             Guard.NotNull(topValues, nameof(topValues));
             Guard.NotNull(topValues, nameof(topValues));
-            Guard.IsTrue(bottom._Attribute.Dimensions == topValues._Attribute.Dimensions, nameof(topValues));
-            Guard.IsTrue(topKeys.Count <= bottom._Attribute.ItemsCount, nameof(topKeys));
-            Guard.IsTrue(topKeys.Count == topValues._Attribute.ItemsCount, nameof(topValues));
-            Guard.IsTrue(topKeys.All(item => item < (uint)bottom._Attribute.ItemsCount), nameof(topKeys));
+            Guard.IsTrue(bottom._Encoding.Dimensions == topValues._Encoding.Dimensions, nameof(topValues));
+            Guard.IsTrue(topKeys.Count <= bottom._Encoding.ItemsCount, nameof(topKeys));
+            Guard.IsTrue(topKeys.Count == topValues._Encoding.ItemsCount, nameof(topValues));
+            Guard.IsTrue(topKeys.All(item => item < (uint)bottom._Encoding.ItemsCount), nameof(topKeys));
 
 
             return new SparseArray<Vector3>(bottom.AsVector3Array(), topValues.AsVector3Array(), topKeys);
             return new SparseArray<Vector3>(bottom.AsVector3Array(), topValues.AsVector3Array(), topKeys);
         }
         }
@@ -302,10 +309,10 @@ namespace SharpGLTF.Memory
         {
         {
             Guard.NotNull(bottom, nameof(bottom));
             Guard.NotNull(bottom, nameof(bottom));
             Guard.NotNull(topValues, nameof(topValues));
             Guard.NotNull(topValues, nameof(topValues));
-            Guard.IsTrue(bottom._Attribute.Dimensions == topValues._Attribute.Dimensions, nameof(topValues));
-            Guard.IsTrue(topKeys.Count <= bottom._Attribute.ItemsCount, nameof(topKeys));
-            Guard.IsTrue(topKeys.Count == topValues._Attribute.ItemsCount, nameof(topValues));
-            Guard.IsTrue(topKeys.All(item => item < (uint)bottom._Attribute.ItemsCount), nameof(topKeys));
+            Guard.IsTrue(bottom._Encoding.Dimensions == topValues._Encoding.Dimensions, nameof(topValues));
+            Guard.IsTrue(topKeys.Count <= bottom._Encoding.ItemsCount, nameof(topKeys));
+            Guard.IsTrue(topKeys.Count == topValues._Encoding.ItemsCount, nameof(topValues));
+            Guard.IsTrue(topKeys.All(item => item < (uint)bottom._Encoding.ItemsCount), nameof(topKeys));
 
 
             return new SparseArray<Vector4>(bottom.AsVector4Array(), topValues.AsVector4Array(), topKeys);
             return new SparseArray<Vector4>(bottom.AsVector4Array(), topValues.AsVector4Array(), topKeys);
         }
         }
@@ -314,10 +321,10 @@ namespace SharpGLTF.Memory
         {
         {
             Guard.NotNull(bottom, nameof(bottom));
             Guard.NotNull(bottom, nameof(bottom));
             Guard.NotNull(topValues, nameof(topValues));
             Guard.NotNull(topValues, nameof(topValues));
-            Guard.IsTrue(bottom._Attribute.Dimensions == topValues._Attribute.Dimensions, nameof(topValues));
-            Guard.IsTrue(topKeys.Count <= bottom._Attribute.ItemsCount, nameof(topKeys));
-            Guard.IsTrue(topKeys.Count == topValues._Attribute.ItemsCount, nameof(topValues));
-            Guard.IsTrue(topKeys.All(item => item < (uint)bottom._Attribute.ItemsCount), nameof(topKeys));
+            Guard.IsTrue(bottom._Encoding.Dimensions == topValues._Encoding.Dimensions, nameof(topValues));
+            Guard.IsTrue(topKeys.Count <= bottom._Encoding.ItemsCount, nameof(topKeys));
+            Guard.IsTrue(topKeys.Count == topValues._Encoding.ItemsCount, nameof(topValues));
+            Guard.IsTrue(topKeys.All(item => item < (uint)bottom._Encoding.ItemsCount), nameof(topKeys));
 
 
             return new SparseArray<Vector4>(bottom.AsColorArray(defaultW), topValues.AsColorArray(defaultW), topKeys);
             return new SparseArray<Vector4>(bottom.AsColorArray(defaultW), topValues.AsColorArray(defaultW), topKeys);
         }
         }
@@ -327,7 +334,7 @@ namespace SharpGLTF.Memory
         #region data
         #region data
 
 
         [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
         [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
-        private MemoryAccessInfo _Attribute;
+        private MemoryEncoding _Encoding;
 
 
         [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
         [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
         private ArraySegment<Byte> _Data;
         private ArraySegment<Byte> _Data;
@@ -336,7 +343,7 @@ namespace SharpGLTF.Memory
 
 
         #region properties
         #region properties
 
 
-        public MemoryAccessInfo Attribute => _Attribute;
+        public MemoryEncoding Attribute => _Encoding;
 
 
         public ArraySegment<Byte> Data => _Data;
         public ArraySegment<Byte> Data => _Data;
 
 
@@ -344,74 +351,74 @@ namespace SharpGLTF.Memory
 
 
         #region API
         #region API
 
 
-        public void Update(ArraySegment<Byte> data, MemoryAccessInfo info)
+        public void Update(ArraySegment<Byte> data, MemoryEncoding info)
         {
         {
-            this._Attribute = info;
+            this._Encoding = info;
             this._Data = data;
             this._Data = data;
         }
         }
 
 
         public IntegerArray AsIntegerArray()
         public IntegerArray AsIntegerArray()
         {
         {
-            Guard.IsTrue(_Attribute.IsValidIndexer, nameof(_Attribute));
-            Guard.IsTrue(_Attribute.Dimensions == DIMENSIONS.SCALAR, nameof(_Attribute));
-            return new IntegerArray(_Data, _Attribute.ByteOffset, _Attribute.ItemsCount, _Attribute.Encoding.ToIndex());
+            Guard.IsTrue(_Encoding.IsValidIndexer, nameof(_Encoding));
+            Guard.IsTrue(_Encoding.Dimensions == DIMENSIONS.SCALAR, nameof(_Encoding));
+            return new IntegerArray(_Data, _Encoding.ByteOffset, _Encoding.ItemsCount, _Encoding.Encoding.ToIndex());
         }
         }
 
 
         public ScalarArray AsScalarArray()
         public ScalarArray AsScalarArray()
         {
         {
-            Guard.IsTrue(_Attribute.IsValidVertexAttribute, nameof(_Attribute));
-            Guard.IsTrue(_Attribute.Dimensions == DIMENSIONS.SCALAR, nameof(_Attribute));
-            return new ScalarArray(_Data, _Attribute.ByteOffset, _Attribute.ItemsCount, _Attribute.ByteStride, _Attribute.Encoding, _Attribute.Normalized);
+            Guard.IsTrue(_Encoding.IsValidVertexAttribute, nameof(_Encoding));
+            Guard.IsTrue(_Encoding.Dimensions == DIMENSIONS.SCALAR, nameof(_Encoding));
+            return new ScalarArray(_Data, _Encoding.ByteOffset, _Encoding.ItemsCount, _Encoding.ByteStride, _Encoding.Encoding, _Encoding.Normalized);
         }
         }
 
 
         public Vector2Array AsVector2Array()
         public Vector2Array AsVector2Array()
         {
         {
-            Guard.IsTrue(_Attribute.IsValidVertexAttribute, nameof(_Attribute));
-            Guard.IsTrue(_Attribute.Dimensions == DIMENSIONS.VEC2, nameof(_Attribute));
-            return new Vector2Array(_Data, _Attribute.ByteOffset, _Attribute.ItemsCount, _Attribute.ByteStride, _Attribute.Encoding, _Attribute.Normalized);
+            Guard.IsTrue(_Encoding.IsValidVertexAttribute, nameof(_Encoding));
+            Guard.IsTrue(_Encoding.Dimensions == DIMENSIONS.VEC2, nameof(_Encoding));
+            return new Vector2Array(_Data, _Encoding.ByteOffset, _Encoding.ItemsCount, _Encoding.ByteStride, _Encoding.Encoding, _Encoding.Normalized);
         }
         }
 
 
         public Vector3Array AsVector3Array()
         public Vector3Array AsVector3Array()
         {
         {
-            Guard.IsTrue(_Attribute.IsValidVertexAttribute, nameof(_Attribute));
-            Guard.IsTrue(_Attribute.Dimensions == DIMENSIONS.VEC3, nameof(_Attribute));
-            return new Vector3Array(_Data, _Attribute.ByteOffset, _Attribute.ItemsCount, _Attribute.ByteStride, _Attribute.Encoding, _Attribute.Normalized);
+            Guard.IsTrue(_Encoding.IsValidVertexAttribute, nameof(_Encoding));
+            Guard.IsTrue(_Encoding.Dimensions == DIMENSIONS.VEC3, nameof(_Encoding));
+            return new Vector3Array(_Data, _Encoding.ByteOffset, _Encoding.ItemsCount, _Encoding.ByteStride, _Encoding.Encoding, _Encoding.Normalized);
         }
         }
 
 
         public Vector4Array AsVector4Array()
         public Vector4Array AsVector4Array()
         {
         {
-            Guard.IsTrue(_Attribute.IsValidVertexAttribute, nameof(_Attribute));
-            Guard.IsTrue(_Attribute.Dimensions == DIMENSIONS.VEC4, nameof(_Attribute));
-            return new Vector4Array(_Data, _Attribute.ByteOffset, _Attribute.ItemsCount, _Attribute.ByteStride, _Attribute.Encoding, _Attribute.Normalized);
+            Guard.IsTrue(_Encoding.IsValidVertexAttribute, nameof(_Encoding));
+            Guard.IsTrue(_Encoding.Dimensions == DIMENSIONS.VEC4, nameof(_Encoding));
+            return new Vector4Array(_Data, _Encoding.ByteOffset, _Encoding.ItemsCount, _Encoding.ByteStride, _Encoding.Encoding, _Encoding.Normalized);
         }
         }
 
 
         public ColorArray AsColorArray(Single defaultW = 1)
         public ColorArray AsColorArray(Single defaultW = 1)
         {
         {
-            Guard.IsTrue(_Attribute.IsValidVertexAttribute, nameof(_Attribute));
-            Guard.IsTrue(_Attribute.Dimensions == DIMENSIONS.VEC3 || _Attribute.Dimensions == DIMENSIONS.VEC4, nameof(_Attribute));
-            return new ColorArray(_Data, _Attribute.ByteOffset, _Attribute.ItemsCount, _Attribute.ByteStride, _Attribute.Dimensions.DimCount(), _Attribute.Encoding, _Attribute.Normalized, defaultW);
+            Guard.IsTrue(_Encoding.IsValidVertexAttribute, nameof(_Encoding));
+            Guard.IsTrue(_Encoding.Dimensions == DIMENSIONS.VEC3 || _Encoding.Dimensions == DIMENSIONS.VEC4, nameof(_Encoding));
+            return new ColorArray(_Data, _Encoding.ByteOffset, _Encoding.ItemsCount, _Encoding.ByteStride, _Encoding.Dimensions.DimCount(), _Encoding.Encoding, _Encoding.Normalized, defaultW);
         }
         }
 
 
         public QuaternionArray AsQuaternionArray()
         public QuaternionArray AsQuaternionArray()
         {
         {
-            Guard.IsTrue(_Attribute.IsValidVertexAttribute, nameof(_Attribute));
-            Guard.IsTrue(_Attribute.Dimensions == DIMENSIONS.VEC4, nameof(_Attribute));
-            return new QuaternionArray(_Data, _Attribute.ByteOffset, _Attribute.ItemsCount, _Attribute.ByteStride, _Attribute.Encoding, _Attribute.Normalized);
+            Guard.IsTrue(_Encoding.IsValidVertexAttribute, nameof(_Encoding));
+            Guard.IsTrue(_Encoding.Dimensions == DIMENSIONS.VEC4, nameof(_Encoding));
+            return new QuaternionArray(_Data, _Encoding.ByteOffset, _Encoding.ItemsCount, _Encoding.ByteStride, _Encoding.Encoding, _Encoding.Normalized);
         }
         }
 
 
         public Matrix4x4Array AsMatrix4x4Array()
         public Matrix4x4Array AsMatrix4x4Array()
         {
         {
-            Guard.IsTrue(_Attribute.IsValidVertexAttribute, nameof(_Attribute));
-            Guard.IsTrue(_Attribute.Dimensions == DIMENSIONS.MAT4, nameof(_Attribute));
-            return new Matrix4x4Array(_Data, _Attribute.ByteOffset, _Attribute.ItemsCount, _Attribute.ByteStride, _Attribute.Encoding, _Attribute.Normalized);
+            Guard.IsTrue(_Encoding.IsValidVertexAttribute, nameof(_Encoding));
+            Guard.IsTrue(_Encoding.Dimensions == DIMENSIONS.MAT4, nameof(_Encoding));
+            return new Matrix4x4Array(_Data, _Encoding.ByteOffset, _Encoding.ItemsCount, _Encoding.ByteStride, _Encoding.Encoding, _Encoding.Normalized);
         }
         }
 
 
         public MultiArray AsMultiArray(int dimensions)
         public MultiArray AsMultiArray(int dimensions)
         {
         {
-            Guard.IsTrue(_Attribute.IsValidVertexAttribute, nameof(_Attribute));
-            Guard.IsTrue(_Attribute.Dimensions == DIMENSIONS.SCALAR, nameof(_Attribute));
-            Guard.IsTrue(_Attribute.ByteStride == 0, nameof(_Attribute));
-            return new MultiArray(_Data, _Attribute.ByteOffset, _Attribute.ItemsCount, _Attribute.ByteStride, dimensions, _Attribute.Encoding, _Attribute.Normalized);
+            Guard.IsTrue(_Encoding.IsValidVertexAttribute, nameof(_Encoding));
+            Guard.IsTrue(_Encoding.Dimensions == DIMENSIONS.SCALAR, nameof(_Encoding));
+            Guard.IsTrue(_Encoding.ByteStride == 0, nameof(_Encoding));
+            return new MultiArray(_Data, _Encoding.ByteOffset, _Encoding.ItemsCount, _Encoding.ByteStride, dimensions, _Encoding.Encoding, _Encoding.Normalized);
         }
         }
 
 
         #endregion
         #endregion

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

@@ -150,7 +150,7 @@ namespace SharpGLTF.Schema2
         internal Memory.MemoryAccessor _GetMemoryAccessor(ROOT root, int count, Accessor baseAccessor)
         internal Memory.MemoryAccessor _GetMemoryAccessor(ROOT root, int count, Accessor baseAccessor)
         {
         {
             var view = root.LogicalBufferViews[this._bufferView];
             var view = root.LogicalBufferViews[this._bufferView];
-            var info = new Memory.MemoryAccessInfo(null, this._byteOffset ?? 0, count, view.ByteStride, baseAccessor.Dimensions, baseAccessor.Encoding, baseAccessor.Normalized);
+            var info = new Memory.MemoryEncoding(null, this._byteOffset ?? 0, count, view.ByteStride, baseAccessor.Dimensions, baseAccessor.Encoding, baseAccessor.Normalized);
             return new Memory.MemoryAccessor(view.Content, info);
             return new Memory.MemoryAccessor(view.Content, info);
         }
         }
 
 

+ 35 - 11
src/SharpGLTF.Core/Schema2/gltf.Accessors.cs

@@ -93,7 +93,7 @@ namespace SharpGLTF.Schema2
         internal MemoryAccessor _GetMemoryAccessor()
         internal MemoryAccessor _GetMemoryAccessor()
         {
         {
             var view = SourceBufferView;
             var view = SourceBufferView;
-            var info = new MemoryAccessInfo(null, ByteOffset, Count, view.ByteStride, Dimensions, Encoding, Normalized);
+            var info = new MemoryEncoding(null, ByteOffset, Count, view.ByteStride, Dimensions, Encoding, Normalized);
             return new MemoryAccessor(view.Content, info);
             return new MemoryAccessor(view.Content, info);
         }
         }
 
 
@@ -431,9 +431,12 @@ namespace SharpGLTF.Schema2
             result = result.GetContext(this);
             result = result.GetContext(this);
 
 
             SourceBufferView.ValidateBufferUsageGPU(result, BufferMode.ARRAY_BUFFER);
             SourceBufferView.ValidateBufferUsageGPU(result, BufferMode.ARRAY_BUFFER);
-            result.CheckLinkMustBeAnyOf(nameof(Normalized), Normalized, false);
-            result.CheckLinkMustBeAnyOf(nameof(Encoding), Encoding, EncodingType.FLOAT);
             result.CheckLinkMustBeAnyOf(nameof(Dimensions), Dimensions, DimensionType.VEC3);
             result.CheckLinkMustBeAnyOf(nameof(Dimensions), Dimensions, DimensionType.VEC3);
+            if (!this.LogicalParent.MeshQuantizationAllowed)
+            {
+                result.CheckLinkMustBeAnyOf(nameof(Normalized), Normalized, false);
+                result.CheckLinkMustBeAnyOf(nameof(Encoding), Encoding, EncodingType.FLOAT);
+            }
 
 
             var positions = this.AsVector3Array();
             var positions = this.AsVector3Array();
 
 
@@ -448,9 +451,17 @@ namespace SharpGLTF.Schema2
             result = result.GetContext(this);
             result = result.GetContext(this);
 
 
             SourceBufferView.ValidateBufferUsageGPU(result, BufferMode.ARRAY_BUFFER);
             SourceBufferView.ValidateBufferUsageGPU(result, BufferMode.ARRAY_BUFFER);
-            result.CheckLinkMustBeAnyOf(nameof(Normalized), Normalized, false);
-            result.CheckLinkMustBeAnyOf(nameof(Encoding), Encoding, EncodingType.FLOAT);
             result.CheckLinkMustBeAnyOf(nameof(Dimensions), Dimensions, DimensionType.VEC3);
             result.CheckLinkMustBeAnyOf(nameof(Dimensions), Dimensions, DimensionType.VEC3);
+            if (!this.LogicalParent.MeshQuantizationAllowed)
+            {
+                result.CheckLinkMustBeAnyOf(nameof(Normalized), Normalized, false);
+                result.CheckLinkMustBeAnyOf(nameof(Encoding), Encoding, EncodingType.FLOAT);
+            }
+            else
+            {
+                if (Normalized) result.CheckLinkMustBeAnyOf(nameof(Encoding), Encoding, EncodingType.BYTE, EncodingType.SHORT);
+                else result.CheckLinkMustBeAnyOf(nameof(Encoding), Encoding, EncodingType.FLOAT);
+            }
 
 
             var normals = this.AsVector3Array();
             var normals = this.AsVector3Array();
 
 
@@ -468,17 +479,30 @@ namespace SharpGLTF.Schema2
             result = result.GetContext(this);
             result = result.GetContext(this);
 
 
             SourceBufferView.ValidateBufferUsageGPU(result, BufferMode.ARRAY_BUFFER);
             SourceBufferView.ValidateBufferUsageGPU(result, BufferMode.ARRAY_BUFFER);
-            result.CheckLinkMustBeAnyOf(nameof(Normalized), Normalized, false);
-            result.CheckLinkMustBeAnyOf(nameof(Encoding), Encoding, EncodingType.FLOAT);
             result.CheckLinkMustBeAnyOf(nameof(Dimensions), Dimensions, DimensionType.VEC3, DimensionType.VEC4);
             result.CheckLinkMustBeAnyOf(nameof(Dimensions), Dimensions, DimensionType.VEC3, DimensionType.VEC4);
+            if (!this.LogicalParent.MeshQuantizationAllowed)
+            {
+                result.CheckLinkMustBeAnyOf(nameof(Normalized), Normalized, false);
+                result.CheckLinkMustBeAnyOf(nameof(Encoding), Encoding, EncodingType.FLOAT);
+            }
+            else
+            {
+                if (Normalized) result.CheckLinkMustBeAnyOf(nameof(Encoding), Encoding, EncodingType.BYTE, EncodingType.SHORT);
+                else result.CheckLinkMustBeAnyOf(nameof(Encoding), Encoding, EncodingType.FLOAT);
+            }
 
 
-            var tangents = this.AsVector4Array();
+            // when Dimensions == VEC3, its morph target tangent deltas
 
 
-            for (int i = 0; i < tangents.Count; ++i)
+            if (Dimensions == DimensionType.VEC4) 
             {
             {
-                if (result.TryFixTangentOrError(i, tangents[i]))
+                var tangents = this.AsVector4Array();
+
+                for (int i = 0; i < tangents.Count; ++i)
                 {
                 {
-                    tangents[i] = tangents[i].SanitizeTangent();
+                    if (result.TryFixTangentOrError(i, tangents[i]))
+                    {
+                        tangents[i] = tangents[i].SanitizeTangent();
+                    }
                 }
                 }
             }
             }
         }
         }

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

@@ -83,6 +83,22 @@ namespace SharpGLTF.Schema2
 
 
     partial class ModelRoot
     partial class ModelRoot
     {
     {
+        #region properties
+
+        public bool MeshQuantizationAllowed { get; private set; }
+
+        #endregion
+
+        #region API
+
+        /// <summary>
+        /// Immediatelly called after deserialization, it assigns
+        /// </summary>
+        private void _FindMeshQuantizationExtension()
+        {
+            MeshQuantizationAllowed = this._extensionsRequired.Contains("KHR_mesh_quantization");
+        }
+
         internal void UpdateExtensionsSupport()
         internal void UpdateExtensionsSupport()
         {
         {
             var used = RetrieveUsedExtensions();
             var used = RetrieveUsedExtensions();
@@ -90,6 +106,16 @@ namespace SharpGLTF.Schema2
             // update the used list
             // update the used list
             this._extensionsUsed.Clear();
             this._extensionsUsed.Clear();
             this._extensionsUsed.AddRange(used);
             this._extensionsUsed.AddRange(used);
+
+            _SetRequiredExtension("KHR_mesh_quantization", MeshQuantizationAllowed);
+        }
+
+        private void _SetRequiredExtension(string extension, bool enabled)
+        {
+            if (!enabled) { this._extensionsRequired.Remove(extension); return; }
+
+            if (this._extensionsRequired.Contains(extension)) return;
+            this._extensionsRequired.Add(extension);
         }
         }
 
 
         internal IEnumerable<ExtraProperties> GetLogicalChildrenFlattened()
         internal IEnumerable<ExtraProperties> GetLogicalChildrenFlattened()
@@ -135,5 +161,7 @@ namespace SharpGLTF.Schema2
 
 
             this._extensionsUsed.Add(id);
             this._extensionsUsed.Add(id);
         }
         }
+
+        #endregion
     }
     }
 }
 }

+ 5 - 0
src/SharpGLTF.Core/Schema2/gltf.Serialization.Read.cs

@@ -198,6 +198,11 @@ namespace SharpGLTF.Schema2
 
 
         #region externals dependencies resolver
         #region externals dependencies resolver
 
 
+        internal void OnDeserializationCompleted()
+        {
+            _FindMeshQuantizationExtension();
+        }
+
         internal void _ResolveSatelliteDependencies(IO.ReadContext context)
         internal void _ResolveSatelliteDependencies(IO.ReadContext context)
         {
         {
             // resolve satellite buffers
             // resolve satellite buffers

+ 1 - 1
src/SharpGLTF.Core/SharpGLTF.Core.csproj

@@ -4,7 +4,7 @@
     <TargetFramework>netstandard2.0</TargetFramework>
     <TargetFramework>netstandard2.0</TargetFramework>
     <AssemblyName>SharpGLTF.Core</AssemblyName>
     <AssemblyName>SharpGLTF.Core</AssemblyName>
     <RootNamespace>SharpGLTF</RootNamespace>
     <RootNamespace>SharpGLTF</RootNamespace>
-    <LangVersion>latest</LangVersion>
+    <LangVersion>7.3</LangVersion>
     <DebugSymbols>true</DebugSymbols>    
     <DebugSymbols>true</DebugSymbols>    
   </PropertyGroup>  
   </PropertyGroup>  
   
   

+ 1 - 1
src/SharpGLTF.Toolkit/Geometry/PrimitiveBuilder.cs

@@ -129,7 +129,7 @@ namespace SharpGLTF.Geometry
             Guard.NotNull(other, nameof(other));
             Guard.NotNull(other, nameof(other));
 
 
             this._Mesh = mesh;
             this._Mesh = mesh;
-            this._Material = material ?? other.Material;
+            this._Material = material != null ? material : other.Material;
             other._Vertices.CopyTo(this._Vertices);
             other._Vertices.CopyTo(this._Vertices);
 
 
             foreach (var otherMT in other._MorphTargets)
             foreach (var otherMT in other._MorphTargets)

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

@@ -244,7 +244,7 @@ namespace SharpGLTF.Geometry.VertexTypes
             var vbuffer = new ArraySegment<byte>(new Byte[byteStride * vertices.Count]);
             var vbuffer = new ArraySegment<byte>(new Byte[byteStride * vertices.Count]);
 
 
             // fill the buffer with the vertex attributes.
             // fill the buffer with the vertex attributes.
-            var accessors = MemoryAccessInfo
+            var accessors = MemoryEncoding
                 .Slice(attributes, 0, vertices.Count)
                 .Slice(attributes, 0, vertices.Count)
                 .Select(item => new MemoryAccessor(vbuffer, item))
                 .Select(item => new MemoryAccessor(vbuffer, item))
                 .ToArray();
                 .ToArray();
@@ -272,7 +272,7 @@ namespace SharpGLTF.Geometry.VertexTypes
         {
         {
             if (indices == null || indices.Count == 0) return null;
             if (indices == null || indices.Count == 0) return null;
 
 
-            var attribute = new MemoryAccessInfo("INDEX", 0, indices.Count, 0, Schema2.DimensionType.SCALAR, encoding);
+            var attribute = new MemoryEncoding("INDEX", 0, indices.Count, 0, Schema2.DimensionType.SCALAR, encoding);
 
 
             // create buffer
             // create buffer
             var ibytes = new Byte[encoding.ByteLength() * indices.Count];
             var ibytes = new Byte[encoding.ByteLength() * indices.Count];
@@ -286,13 +286,13 @@ namespace SharpGLTF.Geometry.VertexTypes
             return accessor;
             return accessor;
         }
         }
 
 
-        public static MemoryAccessInfo[] GetVertexAttributes(this IVertexBuilder firstVertex, int vertexCount, Schema2.EncodingType jointEncoding)
+        public static MemoryEncoding[] GetVertexAttributes(this IVertexBuilder firstVertex, int vertexCount, Schema2.EncodingType jointEncoding)
         {
         {
             var tvg = firstVertex.GetGeometry().GetType();
             var tvg = firstVertex.GetGeometry().GetType();
             var tvm = firstVertex.GetMaterial().GetType();
             var tvm = firstVertex.GetMaterial().GetType();
             var tvs = firstVertex.GetSkinning().GetType();
             var tvs = firstVertex.GetSkinning().GetType();
 
 
-            var attributes = new List<MemoryAccessInfo>();
+            var attributes = new List<MemoryEncoding>();
 
 
             foreach (var finfo in tvg.GetFields())
             foreach (var finfo in tvg.GetFields())
             {
             {
@@ -320,12 +320,12 @@ namespace SharpGLTF.Geometry.VertexTypes
 
 
             var array = attributes.ToArray();
             var array = attributes.ToArray();
 
 
-            MemoryAccessInfo.SetInterleavedInfo(array, 0, vertexCount);
+            MemoryEncoding.SetInterleavedInfo(array, 0, vertexCount);
 
 
             return array;
             return array;
         }
         }
 
 
-        private static MemoryAccessInfo? _GetMemoryAccessInfo(System.Reflection.FieldInfo finfo)
+        private static MemoryEncoding? _GetMemoryAccessInfo(System.Reflection.FieldInfo finfo)
         {
         {
             var attribute = finfo.GetCustomAttributes(true)
             var attribute = finfo.GetCustomAttributes(true)
                     .OfType<VertexAttributeAttribute>()
                     .OfType<VertexAttributeAttribute>()
@@ -344,7 +344,7 @@ namespace SharpGLTF.Geometry.VertexTypes
 
 
             if (dimensions == null) throw new ArgumentException($"invalid type {finfo.FieldType}");
             if (dimensions == null) throw new ArgumentException($"invalid type {finfo.FieldType}");
 
 
-            return new MemoryAccessInfo(attribute.Name, 0, 0, 0, dimensions.Value, attribute.Encoding, attribute.Normalized);
+            return new MemoryEncoding(attribute.Name, 0, 0, 0, dimensions.Value, attribute.Encoding, attribute.Normalized);
         }
         }
 
 
         private static Func<IVertexBuilder, Object> _GetVertexBuilderAttributeFunc(string attributeName)
         private static Func<IVertexBuilder, Object> _GetVertexBuilderAttributeFunc(string attributeName)

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

@@ -4,7 +4,7 @@
     <TargetFramework>netstandard2.0</TargetFramework>
     <TargetFramework>netstandard2.0</TargetFramework>
     <AssemblyName>SharpGLTF.Toolkit</AssemblyName>
     <AssemblyName>SharpGLTF.Toolkit</AssemblyName>
     <RootNamespace>SharpGLTF</RootNamespace>    
     <RootNamespace>SharpGLTF</RootNamespace>    
-    <LangVersion>latest</LangVersion>
+    <LangVersion>7.3</LangVersion>
     <DebugSymbols>true</DebugSymbols>    
     <DebugSymbols>true</DebugSymbols>    
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>    
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>    
   </PropertyGroup>
   </PropertyGroup>

+ 3 - 3
tests/SharpGLTF.Tests/Memory/MemoryAccessorTests.cs

@@ -13,14 +13,14 @@ namespace SharpGLTF.Memory
         [Test]
         [Test]
         public void CreateInterleaved1()
         public void CreateInterleaved1()
         {
         {
-            var pos = MemoryAccessInfo.CreateDefaultElement("POSITION");
-            var nrm = MemoryAccessInfo.CreateDefaultElement("NORMAL");
+            var pos = MemoryEncoding.CreateDefaultElement("POSITION");
+            var nrm = MemoryEncoding.CreateDefaultElement("NORMAL");
 
 
             var attributes = new[] { pos, nrm };
             var attributes = new[] { pos, nrm };
 
 
             const int baseOffset = 8;
             const int baseOffset = 8;
 
 
-            var byteStride = MemoryAccessInfo.SetInterleavedInfo(attributes, baseOffset, 5);
+            var byteStride = MemoryEncoding.SetInterleavedInfo(attributes, baseOffset, 5);
 
 
             pos = attributes[0];
             pos = attributes[0];
             nrm = attributes[1];
             nrm = attributes[1];

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

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 <Project Sdk="Microsoft.NET.Sdk">
 
 
   <PropertyGroup>
   <PropertyGroup>
-    <TargetFrameworks>netcoreapp3.0;net471</TargetFrameworks>
+    <TargetFrameworks>netcoreapp2.1;net471</TargetFrameworks>
 
 
     <IsPackable>false</IsPackable>
     <IsPackable>false</IsPackable>