Selaa lähdekoodia

Added color and texture morph targets to runtime mesh decoder

Vicente Penades 3 vuotta sitten
vanhempi
sitoutus
63d1b38005

+ 83 - 7
src/SharpGLTF.Core/Runtime/MeshDecoder.Schema2.cs

@@ -321,6 +321,13 @@ namespace SharpGLTF.Runtime
             return XY.Zero;
         }
 
+        public IReadOnlyList<XY> GetTextureCoordDeltas(int vertexIndex, int texCoordSet)
+        {
+            return MorphTargetsCount > 0
+                ? (IReadOnlyList<XY>)new _MorphTargetTexCoordSlice(_MorphTargets, vertexIndex, texCoordSet)
+                : Array.Empty<XY>();
+        }
+
         public XYZW GetColor(int vertexIndex, int set)
         {
             if (set == 0 && _Color0 != null) return _Color0[vertexIndex];
@@ -329,6 +336,13 @@ namespace SharpGLTF.Runtime
             return XYZW.One;
         }
 
+        public IReadOnlyList<XYZW> GetColorDeltas(int vertexIndex, int colorSet)
+        {
+            return MorphTargetsCount > 0
+                ? (IReadOnlyList<XYZW>)new _MorphTargetColorSlice(_MorphTargets, vertexIndex, colorSet)
+                : Array.Empty<XYZW>();
+        }
+
         public Transforms.SparseWeight8 GetSkinWeights(int vertexIndex)
         {
             if (_Weights0 == null) return default;
@@ -378,7 +392,6 @@ namespace SharpGLTF.Runtime
         #region properties
 
         public int VertexCount => _Positions?.Count ?? 0;
-
         public bool HasNormals => _Normals != null;
         public bool HasTangents => _Tangents != null;
 
@@ -394,6 +407,8 @@ namespace SharpGLTF.Runtime
 
         public XY GetTextureCoord(int vertexIndex, int set) { return _Owner.GetTextureCoord(vertexIndex, set); }
 
+        public XYZW GetColor(int vertexIndex, int set) { return _Owner.GetColor(vertexIndex, set); }
+
         #endregion
 
         #region Support methods for VertexNormalsFactory and VertexTangentsFactory
@@ -406,13 +421,11 @@ namespace SharpGLTF.Runtime
         XYZ VertexTangentsFactory.IMeshPrimitive.GetVertexPosition(int idx) { return GetPosition(idx); }
         XYZ VertexTangentsFactory.IMeshPrimitive.GetVertexNormal(int idx) { return GetNormal(idx); }
         XY VertexTangentsFactory.IMeshPrimitive.GetVertexTexCoord(int idx) { return GetTextureCoord(idx, 0); }
-
         void VertexNormalsFactory.IMeshPrimitive.SetVertexNormal(int idx, XYZ normal)
         {
             if (_Normals == null) _Normals = _GeneratedNormals = new XYZ[VertexCount];
             if (_GeneratedNormals != null) _GeneratedNormals[idx] = normal;
         }
-
         void VertexTangentsFactory.IMeshPrimitive.SetVertexTangent(int idx, XYZW tangent)
         {
             if (_Tangents == null) _Tangents = _GeneratedTangents = new XYZW[VertexCount];
@@ -439,17 +452,27 @@ namespace SharpGLTF.Runtime
 
             if (morphs.TryGetValue("POSITION", out SCHEMA2ACCESSOR pAccessor))
             {
-                _PositionsDeltas = pAccessor.AsVector3Array() as IReadOnlyList<Vector3>;
+                _PositionsDeltas = pAccessor.AsVector3Array() as IReadOnlyList<XYZ>;
             }
 
             if (morphs.TryGetValue("NORMAL", out SCHEMA2ACCESSOR nAccessor))
             {
-                _NormalsDeltas = nAccessor.AsVector3Array() as IReadOnlyList<Vector3>;
+                _NormalsDeltas = nAccessor.AsVector3Array() as IReadOnlyList<XYZ>;
             }
 
             if (morphs.TryGetValue("TANGENT", out SCHEMA2ACCESSOR tAccessor))
             {
-                _TangentsDeltas = tAccessor.AsVector3Array() as IReadOnlyList<Vector3>;
+                _TangentsDeltas = tAccessor.AsVector3Array() as IReadOnlyList<XYZ>;
+            }
+
+            if (morphs.TryGetValue("TEXCOORD_0", out SCHEMA2ACCESSOR uv0Accessor))
+            {
+                _TexCoordDeltas = uv0Accessor.AsVector2Array() as IReadOnlyList<XY>;
+            }
+
+            if (morphs.TryGetValue("COLOR_0", out SCHEMA2ACCESSOR c0Accessor))
+            {
+                _ColorDeltas = c0Accessor.AsVector4Array() as IReadOnlyList<XYZW>;
             }
         }
 
@@ -463,6 +486,12 @@ namespace SharpGLTF.Runtime
         private IReadOnlyList<XYZ> _NormalsDeltas;
         private IReadOnlyList<XYZ> _TangentsDeltas;
 
+        // morph target deltas for uv set 0
+        private IReadOnlyList<XY> _TexCoordDeltas;
+
+        // morph target deltas for color set 0
+        private IReadOnlyList<XYZW> _ColorDeltas;
+
         private XYZ[] _GeneratedNormals;
         private XYZ[] _GeneratedTangents;
 
@@ -471,9 +500,10 @@ namespace SharpGLTF.Runtime
         #region properties
 
         public int VertexCount => _PositionsDeltas?.Count ?? 0;
-
         public bool HasNormals => _NormalsDeltas != null;
         public bool HasTangents => _TangentsDeltas != null;
+        public bool HasTexCoord(int set) => set == 0 && _TexCoordDeltas != null;
+        public bool HasColor(int set) => set == 0 && _ColorDeltas != null;
 
         #endregion
 
@@ -493,6 +523,12 @@ namespace SharpGLTF.Runtime
 
         public XY GetTextureCoord(int vertexIndex, int set) { return _Geometry.GetTextureCoord(vertexIndex, set); }
 
+        public XY GetTextureCoordDelta(int vertexIndex, int set) { return set != 0? XY.Zero : _TexCoordDeltas[vertexIndex]; }
+
+        public XYZW GetColor(int vertexIndex, int set) { return _Geometry.GetColor(vertexIndex, set); }
+
+        public XYZW GetColorDelta(int vertexIndex, int set) { return set != 0 ? XYZW.Zero : _ColorDeltas[vertexIndex]; }
+
         #endregion
 
         #region Support methods for VertexNormalsFactory and VertexTangentsFactory
@@ -583,4 +619,44 @@ namespace SharpGLTF.Runtime
         public IEnumerator<XYZ> GetEnumerator() { throw new NotImplementedException(); }
         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
     }
+
+    [System.Diagnostics.DebuggerDisplay("Vertex {_VertexIndex} Tangents deltas")]
+    readonly struct _MorphTargetTexCoordSlice : IReadOnlyList<XY>
+    {
+        public _MorphTargetTexCoordSlice(IReadOnlyList<_MorphTargetDecoder> ggg, int idx, int set)
+        {
+            _Geometries = ggg;
+            _VertexIndex = idx;
+            _TexCoordSet = set;
+        }
+
+        private readonly IReadOnlyList<_MorphTargetDecoder> _Geometries;
+        private readonly int _VertexIndex;
+        private readonly int _TexCoordSet;
+
+        public XY this[int index] => _Geometries[index].GetTextureCoordDelta(_VertexIndex, _TexCoordSet);
+        public int Count => _Geometries.Count;
+        public IEnumerator<XY> GetEnumerator() { throw new NotImplementedException(); }
+        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
+    }
+
+    [System.Diagnostics.DebuggerDisplay("Vertex {_VertexIndex} Tangents deltas")]
+    readonly struct _MorphTargetColorSlice : IReadOnlyList<XYZW>
+    {
+        public _MorphTargetColorSlice(IReadOnlyList<_MorphTargetDecoder> ggg, int idx, int set)
+        {
+            _Geometries = ggg;
+            _VertexIndex = idx;
+            _ColorSet = set;
+        }
+
+        private readonly IReadOnlyList<_MorphTargetDecoder> _Geometries;
+        private readonly int _VertexIndex;
+        private readonly int _ColorSet;
+
+        public XYZW this[int index] => _Geometries[index].GetColorDelta(_VertexIndex, _ColorSet);
+        public int Count => _Geometries.Count;
+        public IEnumerator<XYZW> GetEnumerator() { throw new NotImplementedException(); }
+        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
+    }
 }

+ 28 - 4
src/SharpGLTF.Core/Runtime/MeshDecoder.cs

@@ -9,6 +9,13 @@ using XYZW = System.Numerics.Vector4;
 
 namespace SharpGLTF.Runtime
 {
+    /// <summary>
+    /// Exposes an API to allow decoding a geometry mesh.
+    /// </summary>
+    /// <typeparam name="TMaterial">The primitive's material type</typeparam>
+    /// <remarks>
+    /// Implemented by <see cref="_MeshDecoder{TMaterial}"/>
+    /// </remarks>
     public interface IMeshDecoder<TMaterial>
         where TMaterial : class
     {
@@ -18,6 +25,12 @@ namespace SharpGLTF.Runtime
         IReadOnlyList<IMeshPrimitiveDecoder<TMaterial>> Primitives { get; }
     }
 
+    /// <summary>
+    /// Exposes an API to get geometry data from a mesh primitive
+    /// </summary>
+    /// <remarks>
+    /// Implemented by <see cref="_MeshPrimitiveDecoder"/>
+    /// </remarks>
     public interface IMeshPrimitiveDecoder
     {
         #region properties
@@ -70,21 +83,32 @@ namespace SharpGLTF.Runtime
 
         XYZW GetTangent(int vertexIndex);
 
+        XY GetTextureCoord(int vertexIndex, int textureSetIndex);
+
+        XYZW GetColor(int vertexIndex, int colorSetIndex);
+
+        Transforms.SparseWeight8 GetSkinWeights(int vertexIndex);
+
         IReadOnlyList<XYZ> GetPositionDeltas(int vertexIndex);
 
         IReadOnlyList<XYZ> GetNormalDeltas(int vertexIndex);
 
         IReadOnlyList<XYZ> GetTangentDeltas(int vertexIndex);
 
-        XY GetTextureCoord(int vertexIndex, int textureSetIndex);
-
-        XYZW GetColor(int vertexIndex, int colorSetIndex);
+        IReadOnlyList<XY> GetTextureCoordDeltas(int vertexIndex, int textureSetIndex);
 
-        Transforms.SparseWeight8 GetSkinWeights(int vertexIndex);
+        IReadOnlyList<XYZW> GetColorDeltas(int vertexIndex, int colorSetIndex);
 
         #endregion
     }
 
+    /// <summary>
+    /// Exposes an API to get geometry data from a mesh primitive
+    /// </summary>
+    /// <typeparam name="TMaterial">The material type used by the primitive</typeparam>
+    /// <remarks>
+    /// Implemented by <see cref="_MeshPrimitiveDecoder{TMaterial}"/>
+    /// </remarks>
     public interface IMeshPrimitiveDecoder<TMaterial> : IMeshPrimitiveDecoder
         where TMaterial : class
     {