Vicente Penades пре 7 година
родитељ
комит
e7a5d1782e
2 измењених фајлова са 222 додато и 0 уклоњено
  1. 101 0
      src/glTF2Sharp.DOM/Geometry/VertexBuffer.cs
  2. 121 0
      src/glTF2Sharp.DOM/Geometry/VertexElement.cs

+ 101 - 0
src/glTF2Sharp.DOM/Geometry/VertexBuffer.cs

@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Linq;
+using System.Numerics;
+
+namespace glTF2Sharp.Geometry
+{
+    public class VertexBuffer
+    {
+        #region lifecycle
+
+        public VertexBuffer(int count, params string[] attributes)
+        {
+            _Elements = VertexElement.Create(attributes);
+
+            _ByteStride = VertexElement.GetVertexByteSize(_Elements);
+
+            _Buffer = new Byte[_ByteStride * count];
+        }
+
+        public VertexBuffer(int count, params VertexElement[] elements)
+        {
+            _Elements = elements;
+
+            _ByteStride = VertexElement.GetVertexByteSize(_Elements);
+
+            _Buffer = new Byte[_ByteStride * count];
+        }
+
+        #endregion
+
+        #region data
+
+        private VertexElement[] _Elements;
+        private int _ByteStride;
+        private Byte[] _Buffer;
+
+        #endregion
+
+        #region properties
+
+        public IReadOnlyList<VertexElement> Attributes => _Elements;
+
+        public int ByteStride => _ByteStride;
+
+        public Byte[] Data => _Buffer;
+
+        public int Count => _Buffer.Length / _ByteStride;
+
+        #endregion
+
+        #region API
+
+        public Memory.IEncodedArray<Single> GetScalarColumn(String attribute)
+        {
+            return VertexElement.GetScalarColumn(_Buffer, attribute, _Elements);
+        }
+
+        public Memory.IEncodedArray<Vector2> GetVector2Column(String attribute)
+        {
+            return VertexElement.GetVector2Column(_Buffer, attribute, _Elements);
+        }
+
+        public Memory.IEncodedArray<Vector3> GetVector3Column(String attribute)
+        {
+            return VertexElement.GetVector3Column(_Buffer, attribute, _Elements);
+        }
+
+        public Memory.IEncodedArray<Vector4> GetVector4Column(String attribute)
+        {
+            return VertexElement.GetVector4Column(_Buffer, attribute, _Elements);
+        }
+
+        public void SetScalarColumn(String attribute, Single[] values)
+        {
+            var dstColumn = GetScalarColumn(attribute);
+            Memory.EncodedArrayUtils.CopyTo(values, dstColumn);
+        }
+
+        public void SetVector2Column(String attribute, Vector2[] values)
+        {
+            var dstColumn = GetVector2Column(attribute);
+            Memory.EncodedArrayUtils.CopyTo(values, dstColumn);
+        }
+
+        public void SetVector3Column(String attribute, Vector3[] values)
+        {
+            var dstColumn = GetVector3Column(attribute);
+            Memory.EncodedArrayUtils.CopyTo(values, dstColumn);
+        }
+
+        public void SetVector4Column(String attribute, Vector4[] values)
+        {
+            var dstColumn = GetVector4Column(attribute);
+            Memory.EncodedArrayUtils.CopyTo(values, dstColumn);
+        }
+
+        #endregion
+    }
+}

+ 121 - 0
src/glTF2Sharp.DOM/Geometry/VertexElement.cs

@@ -0,0 +1,121 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Linq;
+using System.Numerics;
+
+namespace glTF2Sharp.Geometry
+{
+    using Schema2;    
+
+    public struct VertexElement
+    {
+        #region lifecycle
+
+        public static VertexElement[] Create(params string[] attributes)
+        {
+            return attributes.Select(item => CreateDefaultElement(item)).ToArray();
+        }
+
+        public static VertexElement CreateDefaultElement(string attribute)
+        {
+            switch (attribute)
+            {
+                case "POSITION": return new VertexElement("POSITION", ElementType.VEC3);
+                case "NORMAL": return new VertexElement("NORMAL", ElementType.VEC3);
+                case "TANGENT": return new VertexElement("TANGENT", ElementType.VEC4);
+
+                case "TEXCOORD_0": return new VertexElement("TEXCOORD_0", ElementType.VEC2);
+                case "TEXCOORD_1": return new VertexElement("TEXCOORD_1", ElementType.VEC2);
+                case "TEXCOORD_2": return new VertexElement("TEXCOORD_2", ElementType.VEC2);
+                case "TEXCOORD_3": return new VertexElement("TEXCOORD_3", ElementType.VEC2);
+
+                case "COLOR_0": return new VertexElement("COLOR_0", ElementType.VEC4, ComponentType.UNSIGNED_BYTE, true);
+
+                case "JOINTS_0": return new VertexElement("JOINTS_0", ElementType.VEC4, ComponentType.UNSIGNED_BYTE);
+                case "WEIGHTS_0": return new VertexElement("WEIGHTS_0", ElementType.VEC4, ComponentType.UNSIGNED_BYTE, true);
+            }
+
+            throw new NotImplementedException();
+        }
+
+        public VertexElement(String attr, ElementType dim, ComponentType enc = ComponentType.FLOAT, Boolean nrm = false)
+        {
+            Attribute = attr;
+            Dimensions = dim;
+            Encoding = enc;
+            Normalized = nrm;
+        }
+
+        #endregion
+
+        #region data
+
+        public String Attribute;
+        public ElementType Dimensions;
+        public ComponentType Encoding;
+        public Boolean Normalized;
+
+        #endregion
+
+        #region API
+
+        public int ByteSize => Dimensions.DimCount() * Encoding.ByteLength();
+
+        public static int GetVertexByteSize(params VertexElement[] elements)
+        {
+            return elements.Sum(item => item.ByteSize);
+        }
+
+        public static int GetBufferByteSize(int count, params VertexElement[] elements)
+        {
+            var stride = GetVertexByteSize(elements);
+            return stride * count;
+        }
+
+        public static Memory.IEncodedArray<Single> GetScalarColumn(Byte[] data, string attribute, params VertexElement[] elements)
+        {
+            var column = _GetColumn(data, attribute, elements);
+            if (column.Item3.Dimensions.DimCount() != 1) throw new ArgumentException(nameof(elements));
+            return new Memory.ScalarArray(column.Item1, column.Item2, column.Item3.Encoding, column.Item3.Normalized);
+        }
+
+        public static Memory.IEncodedArray<Vector2> GetVector2Column(Byte[] data, string attribute, params VertexElement[] elements)
+        {
+            var column = _GetColumn(data, attribute, elements);
+            if (column.Item3.Dimensions.DimCount() != 2) throw new ArgumentException(nameof(elements));
+            return new Memory.Vector2Array(column.Item1, column.Item2, column.Item3.Encoding, column.Item3.Normalized);
+        }
+
+        public static Memory.IEncodedArray<Vector3> GetVector3Column(Byte[] data, string attribute, params VertexElement[] elements)
+        {
+            var column = _GetColumn(data, attribute, elements);
+            if (column.Item3.Dimensions.DimCount() != 3) throw new ArgumentException(nameof(elements));
+            return new Memory.Vector3Array(column.Item1, column.Item2, column.Item3.Encoding, column.Item3.Normalized);
+        }
+
+        public static Memory.IEncodedArray<Vector4> GetVector4Column(Byte[] data, string attribute, params VertexElement[] elements)
+        {
+            var column = _GetColumn(data, attribute, elements);
+            if (column.Item3.Dimensions.DimCount() != 4) throw new ArgumentException(nameof(elements));
+            return new Memory.Vector4Array(column.Item1, column.Item2, column.Item3.Encoding, column.Item3.Normalized);
+        }
+
+        private static (ArraySegment<Byte>, int, VertexElement) _GetColumn(Byte[] data, string attribute, params VertexElement[] elements)
+        {
+            var index = Array.FindIndex(elements, item => item.Attribute == attribute);
+            if (index < 0) throw new ArgumentException(nameof(attribute));
+
+            var element = elements[index];
+
+            var byteStride = GetVertexByteSize(elements);
+            var byteOffset = elements.Take(index).Sum(item => item.ByteSize);
+
+            var source = new ArraySegment<Byte>(data, byteOffset, data.Length - byteOffset);
+
+            return (source, byteStride, element);
+        }
+
+        #endregion
+    }
+}