Browse Source

Moved MemoryAccessorInfo to its own file

Vicente Penades Armengot 5 months ago
parent
commit
49d837ae77

+ 0 - 298
src/SharpGLTF.Core/Memory/MemoryAccessor.cs

@@ -11,304 +11,6 @@ using ENCODING = SharpGLTF.Schema2.EncodingType;
 
 namespace SharpGLTF.Memory
 {
-    /// <summary>
-    /// Defines the memory encoding pattern for an arbitrary <see cref="BYTES"/>.
-    /// </summary>
-    [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
-    public struct MemoryAccessInfo
-    {
-        #region debug
-
-        internal readonly string _GetDebuggerDisplay()
-        {
-            return Diagnostics.DebuggerDisplay.ToReport(this);
-        }
-
-        #endregion
-
-        #region constructor
-
-        public static MemoryAccessInfo[] Create(params string[] attributes)
-        {
-            return attributes.Select(item => CreateDefaultElement(item)).ToArray();
-        }
-
-        public static MemoryAccessInfo CreateDefaultElement(string attribute)
-        {
-            switch (attribute)
-            {
-                case "INDEX": return new MemoryAccessInfo("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 "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 "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 "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 "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);
-            }
-
-            throw new NotImplementedException();
-        }
-
-        public MemoryAccessInfo(string name, int byteOffset, int itemsCount, int byteStride, AttributeFormat format)
-        {
-            this.Name = name;
-            this.ByteOffset = byteOffset;
-            this.ItemsCount = itemsCount;
-            this.ByteStride = byteStride;
-            this.Dimensions = format.Dimensions;
-            this.Encoding = format.Encoding;
-            this.Normalized = format.Normalized;
-        }
-
-        public MemoryAccessInfo(string name, int byteOffset, int itemsCount, int byteStride, DIMENSIONS dimensions, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false)
-        {
-            this.Name = name;
-            this.ByteOffset = byteOffset;
-            this.ItemsCount = itemsCount;
-            this.ByteStride = byteStride;
-            this.Dimensions = dimensions;
-            this.Encoding = encoding;
-            this.Normalized = normalized;
-        }
-
-        public readonly MemoryAccessInfo Slice(int itemStart, int itemCount)
-        {
-            var stride = _GetRowByteLength();
-
-            var clone = this;
-            clone.ByteOffset += itemStart * stride;
-            clone.ItemsCount = Math.Min(clone.ItemsCount, itemCount);
-
-            return clone;
-        }
-
-        #endregion
-
-        #region data
-
-        /// <summary>
-        /// If set, it can be used to identify the data with an attribute name: POSITION, NORMAL, etc
-        /// </summary>
-        public String Name;
-
-        /// <summary>
-        /// number of bytes to advance to the beginning of the first item.
-        /// </summary>
-        public int ByteOffset;
-
-        /// <summary>
-        /// Total number of items
-        /// </summary>
-        public int ItemsCount;
-
-        /// <summary>
-        /// number of bytes to advance to the beginning of the next item
-        /// </summary>
-        public int ByteStride;
-
-        /// <summary>
-        /// number of sub-elements of each item.
-        /// </summary>
-        public DIMENSIONS Dimensions;
-
-        /// <summary>
-        /// byte encoding of sub-elements of each item.
-        /// </summary>
-        public ENCODING Encoding;
-
-        /// <summary>
-        /// normalization of sub-elements of each item.
-        /// </summary>
-        public Boolean Normalized;
-
-        #endregion
-
-        #region properties
-
-        /// <summary>
-        /// number of bytes to advance to the next item.
-        /// </summary>
-        public readonly int StepByteLength => _GetRowByteLength();
-
-        public readonly int ItemByteLength => _GetItemByteLength();
-
-        public readonly Boolean IsValidVertexAttribute
-        {
-            get
-            {
-                if (this.ItemsCount < 0) return false;
-
-                if (this.ByteOffset < 0) return false;
-                if (!this.ByteOffset.IsMultipleOf(4)) return false;
-
-                if (this.ByteStride < 0) return false;
-                if (!this.ByteStride.IsMultipleOf(4)) return false;
-
-                if (this.ByteStride > 0 && this.ByteStride < this.StepByteLength) return false;
-
-                return true;
-            }
-        }
-
-        /// <summary>
-        /// returns true if this type can be used as a joint index.
-        /// </summary>
-        public readonly Boolean IsValidIndexer
-        {
-            get
-            {
-                if (this.ByteOffset < 0) return false;
-                if (this.ItemsCount < 0) return false;
-                if (this.ByteStride < 0) return false;
-                if (this.Dimensions != DIMENSIONS.SCALAR) return false;
-                if (this.Normalized) return false;
-                if (this.ByteStride == 0) return true;
-                if (this.ByteStride == 1) return true;
-                if (this.ByteStride == 2) return true;
-                if (this.ByteStride == 4) return true;
-                return false;
-            }
-        }
-
-        #endregion
-
-        #region API
-
-        private readonly int _GetItemByteLength()
-        {
-            var xlen = Encoding.ByteLength();
-
-            if (Dimensions != DIMENSIONS.SCALAR || Name != "INDEX")
-            {
-                xlen *= this.Dimensions.DimCount();
-                xlen = xlen.WordPadded();
-            }
-
-            return xlen;
-        }
-
-        private readonly int _GetRowByteLength()
-        {
-            return Math.Max(ByteStride, _GetItemByteLength());
-        }
-
-        /// <summary>
-        /// Assuming that <paramref name="attributes"/> are sequential and adyacent,
-        /// it modifies the <see cref="ByteOffset"/> of each item of <paramref name="attributes"/> to ensure
-        /// the offsets are sequential.
-        /// </summary>
-        /// <param name="attributes">A list of attributes to fix.</param>
-        /// <param name="byteOffset">The initial byteoffset.</param>
-        /// <param name="itemsCount">the default items count.</param>
-        /// <returns>The byte stride.</returns>
-        public static int SetInterleavedInfo(MemoryAccessInfo[] attributes, int byteOffset, int itemsCount)
-        {
-            Guard.NotNull(attributes, nameof(attributes));
-
-            var byteStride = 0;
-
-            for (int i = 0; i < attributes.Length; ++i)
-            {
-                var a = attributes[i];
-
-                a.ByteOffset = byteOffset;
-                a.ItemsCount = itemsCount;
-
-                var step = a.StepByteLength;
-
-                byteStride += step;
-                byteOffset += step;
-
-                attributes[i] = a;
-            }
-
-            for (int i = 0; i < attributes.Length; ++i)
-            {
-                var a = attributes[i];
-                a.ByteStride = byteStride;
-                attributes[i] = a;
-            }
-
-            return byteStride;
-        }
-
-        public static MemoryAccessInfo[] Slice(MemoryAccessInfo[] attributes, int start, int count)
-        {
-            Guard.NotNull(attributes, nameof(attributes));
-
-            var dst = new MemoryAccessInfo[attributes.Length];
-
-            for (int i = 0; i < dst.Length; ++i)
-            {
-                dst[i] = attributes[i].Slice(start, count);
-            }
-
-            return dst;
-        }
-
-        #endregion
-
-        #region nested types
-
-        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>
-        {
-            public int Compare(string x, string y)
-            {
-                var xx = _GetSortingScore(x);
-                var yy = _GetSortingScore(y);
-
-                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
-    }
-
     /// <summary>
     /// Wraps a <see cref="BYTES"/> decoding it and exposing its content as arrays of different types.
     /// </summary>

+ 313 - 0
src/SharpGLTF.Core/Memory/MemoryAccessorInfo.cs

@@ -0,0 +1,313 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using System.Reflection;
+
+using BYTES = System.ArraySegment<System.Byte>;
+
+using DIMENSIONS = SharpGLTF.Schema2.DimensionType;
+using ENCODING = SharpGLTF.Schema2.EncodingType;
+
+namespace SharpGLTF.Memory
+{
+    /// <summary>
+    /// Defines the memory encoding pattern for an arbitrary <see cref="BYTES"/>.
+    /// </summary>
+    [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
+    public struct MemoryAccessInfo
+    {
+        #region debug
+
+        internal readonly string _GetDebuggerDisplay()
+        {
+            return Diagnostics.DebuggerDisplay.ToReport(this);
+        }
+
+        #endregion
+
+        #region constructor
+
+        public static MemoryAccessInfo[] Create(params string[] attributes)
+        {
+            return attributes.Select(item => CreateDefaultElement(item)).ToArray();
+        }
+
+        public static MemoryAccessInfo CreateDefaultElement(string attribute)
+        {
+            switch (attribute)
+            {
+                case "INDEX": return new MemoryAccessInfo("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 "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 "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 "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 "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);
+            }
+
+            throw new NotImplementedException();
+        }
+
+        public MemoryAccessInfo(string name, int byteOffset, int itemsCount, int byteStride, AttributeFormat format)
+        {
+            this.Name = name;
+            this.ByteOffset = byteOffset;
+            this.ItemsCount = itemsCount;
+            this.ByteStride = byteStride;
+            this.Dimensions = format.Dimensions;
+            this.Encoding = format.Encoding;
+            this.Normalized = format.Normalized;
+        }
+
+        public MemoryAccessInfo(string name, int byteOffset, int itemsCount, int byteStride, DIMENSIONS dimensions, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false)
+        {
+            this.Name = name;
+            this.ByteOffset = byteOffset;
+            this.ItemsCount = itemsCount;
+            this.ByteStride = byteStride;
+            this.Dimensions = dimensions;
+            this.Encoding = encoding;
+            this.Normalized = normalized;
+        }
+
+        public readonly MemoryAccessInfo Slice(int itemStart, int itemCount)
+        {
+            var stride = _GetRowByteLength();
+
+            var clone = this;
+            clone.ByteOffset += itemStart * stride;
+            clone.ItemsCount = Math.Min(clone.ItemsCount, itemCount);
+
+            return clone;
+        }
+
+        #endregion
+
+        #region data
+
+        /// <summary>
+        /// If set, it can be used to identify the data with an attribute name: POSITION, NORMAL, etc
+        /// </summary>
+        public String Name;
+
+        /// <summary>
+        /// number of bytes to advance to the beginning of the first item.
+        /// </summary>
+        public int ByteOffset;
+
+        /// <summary>
+        /// Total number of items
+        /// </summary>
+        public int ItemsCount;
+
+        /// <summary>
+        /// number of bytes to advance to the beginning of the next item
+        /// </summary>
+        public int ByteStride;
+
+        /// <summary>
+        /// number of sub-elements of each item.
+        /// </summary>
+        public DIMENSIONS Dimensions;
+
+        /// <summary>
+        /// byte encoding of sub-elements of each item.
+        /// </summary>
+        public ENCODING Encoding;
+
+        /// <summary>
+        /// normalization of sub-elements of each item.
+        /// </summary>
+        public Boolean Normalized;
+
+        #endregion
+
+        #region properties
+
+        public AttributeFormat Format => new AttributeFormat(this.Dimensions, this.Encoding, this.Normalized);
+
+        /// <summary>
+        /// number of bytes to advance to the next item.
+        /// </summary>
+        public readonly int StepByteLength => _GetRowByteLength();
+
+        public readonly int ItemByteLength => _GetItemByteLength();
+
+        public readonly Boolean IsValidVertexAttribute
+        {
+            get
+            {
+                if (this.ItemsCount < 0) return false;
+
+                if (this.ByteOffset < 0) return false;
+                if (!this.ByteOffset.IsMultipleOf(4)) return false;
+
+                if (this.ByteStride < 0) return false;
+                if (!this.ByteStride.IsMultipleOf(4)) return false;
+
+                if (this.ByteStride > 0 && this.ByteStride < this.StepByteLength) return false;
+
+                return true;
+            }
+        }
+
+        /// <summary>
+        /// returns true if this type can be used as a joint index.
+        /// </summary>
+        public readonly Boolean IsValidIndexer
+        {
+            get
+            {
+                if (this.ByteOffset < 0) return false;
+                if (this.ItemsCount < 0) return false;
+                if (this.ByteStride < 0) return false;
+                if (this.Dimensions != DIMENSIONS.SCALAR) return false;
+                if (this.Normalized) return false;
+                if (this.ByteStride == 0) return true;
+                if (this.ByteStride == 1) return true;
+                if (this.ByteStride == 2) return true;
+                if (this.ByteStride == 4) return true;
+                return false;
+            }
+        }
+
+        #endregion
+
+        #region API
+
+        private readonly int _GetItemByteLength()
+        {
+            var xlen = Encoding.ByteLength();
+
+            if (Dimensions != DIMENSIONS.SCALAR || Name != "INDEX")
+            {
+                xlen *= this.Dimensions.DimCount();
+                xlen = xlen.WordPadded();
+            }
+
+            return xlen;
+        }
+
+        private readonly int _GetRowByteLength()
+        {
+            return Math.Max(ByteStride, _GetItemByteLength());
+        }
+
+        /// <summary>
+        /// Assuming that <paramref name="attributes"/> are sequential and adyacent,
+        /// it modifies the <see cref="ByteOffset"/> of each item of <paramref name="attributes"/> to ensure
+        /// the offsets are sequential.
+        /// </summary>
+        /// <param name="attributes">A list of attributes to fix.</param>
+        /// <param name="byteOffset">The initial byteoffset.</param>
+        /// <param name="itemsCount">the default items count.</param>
+        /// <returns>The byte stride.</returns>
+        public static int SetInterleavedInfo(MemoryAccessInfo[] attributes, int byteOffset, int itemsCount)
+        {
+            Guard.NotNull(attributes, nameof(attributes));
+
+            var byteStride = 0;
+
+            for (int i = 0; i < attributes.Length; ++i)
+            {
+                var a = attributes[i];
+
+                a.ByteOffset = byteOffset;
+                a.ItemsCount = itemsCount;
+
+                var step = a.StepByteLength;
+
+                byteStride += step;
+                byteOffset += step;
+
+                attributes[i] = a;
+            }
+
+            for (int i = 0; i < attributes.Length; ++i)
+            {
+                var a = attributes[i];
+                a.ByteStride = byteStride;
+                attributes[i] = a;
+            }
+
+            return byteStride;
+        }
+
+        public static MemoryAccessInfo[] Slice(MemoryAccessInfo[] attributes, int start, int count)
+        {
+            Guard.NotNull(attributes, nameof(attributes));
+
+            var dst = new MemoryAccessInfo[attributes.Length];
+
+            for (int i = 0; i < dst.Length; ++i)
+            {
+                dst[i] = attributes[i].Slice(start, count);
+            }
+
+            return dst;
+        }
+
+        #endregion
+
+        #region nested types
+
+        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>
+        {
+            public int Compare(string x, string y)
+            {
+                var xx = _GetSortingScore(x);
+                var yy = _GetSortingScore(y);
+
+                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
+    }
+}