Browse Source

toolkit: + vertex types

Vicente Penades 6 years ago
parent
commit
fd30f2358a

+ 7 - 87
src/SharpGLTF.Toolkit/Geometry/InterleavedMeshBuilder.cs

@@ -7,6 +7,7 @@ namespace SharpGLTF.Geometry
 {
     using Collections;
     using Schema2;
+    using VertexTypes;
 
     public class InterleavedMeshBuilder<TVertex, TMaterial>
         where TVertex : struct
@@ -61,7 +62,7 @@ namespace SharpGLTF.Geometry
             var root = dstMesh.LogicalParent;
 
             // get vertex attributes from TVertex type using reflection
-            var attributes = _GetVertexAttributes(_Vertices.Count);
+            var attributes = VertexUtils.GetVertexAttributes(typeof(TVertex), _Vertices.Count);
 
             // create vertex buffer
             int byteStride = attributes[0].ByteStride;
@@ -76,13 +77,13 @@ namespace SharpGLTF.Geometry
             {
                 var accessor = root.CreateAccessor(attribute.Name);
 
-                var attributeType = _GetVertexAttributeType(attribute.Name);
+                var field = VertexUtils.GetVertexField(typeof(TVertex), attribute.Name);
 
-                if (attributeType == typeof(Vector2)) accessor.WithVertexData(vbuffer, attribute.ByteOffset, _GetVector2Column(_Vertices, attribute.Name), attribute.Encoding, attribute.Normalized);
-                if (attributeType == typeof(Vector3)) accessor.WithVertexData(vbuffer, attribute.ByteOffset, _GetVector3Column(_Vertices, attribute.Name), attribute.Encoding, attribute.Normalized);
-                if (attributeType == typeof(Vector4)) accessor.WithVertexData(vbuffer, attribute.ByteOffset, _GetVector4Column(_Vertices, attribute.Name), attribute.Encoding, attribute.Normalized);
+                if (field.FieldType == typeof(Vector2)) accessor.WithVertexData(vbuffer, attribute.ByteOffset, field.GetVector2Column(_Vertices), attribute.Encoding, attribute.Normalized);
+                if (field.FieldType == typeof(Vector3)) accessor.WithVertexData(vbuffer, attribute.ByteOffset, field.GetVector3Column(_Vertices), attribute.Encoding, attribute.Normalized);
+                if (field.FieldType == typeof(Vector4)) accessor.WithVertexData(vbuffer, attribute.ByteOffset, field.GetVector4Column(_Vertices), attribute.Encoding, attribute.Normalized);
 
-                vertexAccessors[attribute.Name.ToUpper()] = accessor;
+                vertexAccessors[attribute.Name] = accessor;
             }
 
             foreach (var kvp in _Indices)
@@ -109,86 +110,5 @@ namespace SharpGLTF.Geometry
         }
 
         #endregion
-
-        #region core
-
-        private Geometry.MemoryAccessInfo[] _GetVertexAttributes(int itemsCount)
-        {
-            var type = typeof(TVertex);
-
-            var attributes = new List<Geometry.MemoryAccessInfo>();
-
-            foreach (var field in type.GetFields())
-            {
-                var attributeName = field.Name;
-                var attributeInfo = Geometry.MemoryAccessInfo.CreateDefaultElement(attributeName.ToUpper());
-                attributes.Add(attributeInfo);
-            }
-
-            var array = attributes.ToArray();
-
-            Geometry.MemoryAccessInfo.SetInterleavedInfo(array, 0, itemsCount);
-
-            return array;
-        }
-
-        private static System.Reflection.FieldInfo _GetVertexField(string fieldName)
-        {
-            foreach (var field in typeof(TVertex).GetFields())
-            {
-                if (field.Name.ToLower() == fieldName.ToLower()) return field;
-            }
-
-            return null;
-        }
-
-        private static Type _GetVertexAttributeType(string fieldName)
-        {
-            return _GetVertexField(fieldName).FieldType;
-        }
-
-        private static Vector2[] _GetVector2Column(IReadOnlyList<TVertex> vertices, string fieldName)
-        {
-            var dst = new Vector2[vertices.Count];
-
-            var finfo = _GetVertexField(fieldName);
-
-            for (int i = 0; i < dst.Length; ++i)
-            {
-                dst[i] = (Vector2)finfo.GetValue(vertices[i]);
-            }
-
-            return dst;
-        }
-
-        private static Vector3[] _GetVector3Column(IReadOnlyList<TVertex> vertices, string fieldName)
-        {
-            var dst = new Vector3[vertices.Count];
-
-            var finfo = _GetVertexField(fieldName);
-
-            for (int i = 0; i < dst.Length; ++i)
-            {
-                dst[i] = (Vector3)finfo.GetValue(vertices[i]);
-            }
-
-            return dst;
-        }
-
-        private static Vector4[] _GetVector4Column(IReadOnlyList<TVertex> vertices, string fieldName)
-        {
-            var dst = new Vector4[vertices.Count];
-
-            var finfo = _GetVertexField(fieldName);
-
-            for (int i = 0; i < dst.Length; ++i)
-            {
-                dst[i] = (Vector4)finfo.GetValue(vertices[i]);
-            }
-
-            return dst;
-        }
-
-        #endregion
     }
 }

+ 40 - 0
src/SharpGLTF.Toolkit/Geometry/VertexTypes/Attributes.cs

@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using System.Text;
+
+namespace SharpGLTF.Geometry.VertexTypes
+{
+    [AttributeUsageAttribute(AttributeTargets.Field, Inherited = true, AllowMultiple = false)]
+    public sealed class VertexAttributeAttribute : Attribute
+    {
+        #region constructors
+
+        public VertexAttributeAttribute(string attributeName)
+        {
+            this.Name = attributeName;
+            this.Encoding = Schema2.ComponentType.FLOAT;
+            this.Normalized = false;
+        }
+
+        public VertexAttributeAttribute(string attributeName, Schema2.ComponentType encoding, Boolean normalized)
+        {
+            this.Name = attributeName;
+            this.Encoding = encoding;
+            this.Normalized = normalized;
+        }
+
+        #endregion
+
+        #region data
+
+        public string Name { get; private set; }
+
+        public Schema2.ComponentType Encoding { get; private set; }
+
+        public Boolean Normalized { get; private set; }
+
+        #endregion
+    }
+}

+ 5 - 0
src/SharpGLTF.Toolkit/Geometry/VertexTypes/SkinnedVertices.cs

@@ -21,8 +21,13 @@ namespace SharpGLTF.Geometry.VertexTypes
             Weights_0 = new Vector4(0.5f, 0.5f, 0, 0);
         }
 
+        [VertexAttribute("POSITION")]
         public Vector3 Position;
+
+        [VertexAttribute("JOINTS_0", Schema2.ComponentType.UNSIGNED_BYTE, false)]
         public Vector4 Joints_0;
+
+        [VertexAttribute("WEIGHTS_0", Schema2.ComponentType.UNSIGNED_BYTE, true)]
         public Vector4 Weights_0;
     }
 }

+ 3 - 0
src/SharpGLTF.Toolkit/Geometry/VertexTypes/StaticVertices.cs

@@ -13,7 +13,10 @@ namespace SharpGLTF.Geometry.VertexTypes
             Normal = Vector3.Normalize(new Vector3(nx, ny, nz));
         }
 
+        [VertexAttribute("POSITION")]
         public Vector3 Position;
+
+        [VertexAttribute("NORMAL")]
         public Vector3 Normal;
     }
 }

+ 117 - 0
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexUtils.cs

@@ -0,0 +1,117 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using System.Text;
+
+namespace SharpGLTF.Geometry.VertexTypes
+{
+    public static class VertexUtils
+    {
+        public static System.Reflection.FieldInfo GetVertexField(Type type, string attributeName)
+        {
+            foreach (var finfo in type.GetFields())
+            {
+                var attribute = _GetAccessor(finfo);
+
+                if (attribute.HasValue)
+                {
+                    if (attribute.Value.Name == attributeName) return finfo;
+                }
+            }
+
+            return null;
+        }
+
+        public static MemoryAccessInfo[] GetVertexAttributes(Type type, int itemsCount)
+        {
+            var attributes = new List<MemoryAccessInfo>();
+
+            foreach (var finfo in type.GetFields())
+            {
+                var attribute = _GetAccessor(finfo);
+
+                if (attribute.HasValue)
+                {
+                    attributes.Add(attribute.Value);
+                }
+            }
+
+            var array = attributes.ToArray();
+
+            MemoryAccessInfo.SetInterleavedInfo(array, 0, itemsCount);
+
+            return array;
+        }
+
+        private static MemoryAccessInfo? _GetAccessor(System.Reflection.FieldInfo finfo)
+        {
+            var attribute = finfo.GetCustomAttributes(true)
+                    .OfType<VertexAttributeAttribute>()
+                    .FirstOrDefault();
+
+            if (attribute == null) return null;
+
+            var dimensions = (Schema2.ElementType?)null;
+
+            if (finfo.FieldType == typeof(Single)) dimensions = Schema2.ElementType.SCALAR;
+            if (finfo.FieldType == typeof(Vector2)) dimensions = Schema2.ElementType.VEC2;
+            if (finfo.FieldType == typeof(Vector3)) dimensions = Schema2.ElementType.VEC3;
+            if (finfo.FieldType == typeof(Vector4)) dimensions = Schema2.ElementType.VEC4;
+            if (finfo.FieldType == typeof(Quaternion)) dimensions = Schema2.ElementType.VEC4;
+            if (finfo.FieldType == typeof(Matrix4x4)) dimensions = Schema2.ElementType.MAT4;
+
+            if (dimensions == null) throw new ArgumentException($"invalid type {finfo.FieldType}");
+
+            return new MemoryAccessInfo(attribute.Name, 0, 0, 0, dimensions.Value, attribute.Encoding, attribute.Normalized);
+        }
+
+        public static Single[] GetScalarColumn<TVertex>(this System.Reflection.FieldInfo finfo, IReadOnlyList<TVertex> vertices)
+        {
+            var dst = new Single[vertices.Count];
+
+            for (int i = 0; i < dst.Length; ++i)
+            {
+                dst[i] = (Single)finfo.GetValue(vertices[i]);
+            }
+
+            return dst;
+        }
+
+        public static Vector2[] GetVector2Column<TVertex>(this System.Reflection.FieldInfo finfo, IReadOnlyList<TVertex> vertices)
+        {
+            var dst = new Vector2[vertices.Count];
+
+            for (int i = 0; i < dst.Length; ++i)
+            {
+                dst[i] = (Vector2)finfo.GetValue(vertices[i]);
+            }
+
+            return dst;
+        }
+
+        public static Vector3[] GetVector3Column<TVertex>(this System.Reflection.FieldInfo finfo, IReadOnlyList<TVertex> vertices)
+        {
+            var dst = new Vector3[vertices.Count];
+
+            for (int i = 0; i < dst.Length; ++i)
+            {
+                dst[i] = (Vector3)finfo.GetValue(vertices[i]);
+            }
+
+            return dst;
+        }
+
+        public static Vector4[] GetVector4Column<TVertex>(this System.Reflection.FieldInfo finfo, IReadOnlyList<TVertex> vertices)
+        {
+            var dst = new Vector4[vertices.Count];
+
+            for (int i = 0; i < dst.Length; ++i)
+            {
+                dst[i] = (Vector4)finfo.GetValue(vertices[i]);
+            }
+
+            return dst;
+        }
+    }
+}

+ 1 - 0
src/SharpGLTF/Geometry/MemoryAccessor.cs

@@ -14,6 +14,7 @@ namespace SharpGLTF.Geometry
     /// <summary>
     /// Defines the pattern in which a <see cref="ArraySegment{Byte}"/> is accessed and decoded to meaningful values.
     /// </summary>
+    [System.Diagnostics.DebuggerDisplay("{Name} {Dimensions}.{Encoding}.{Normalized} {ByteStride}   {ByteOffset} [{ItemsCount}]")]
     public struct MemoryAccessInfo
     {
         #region constructor