Kaynağa Gözat

+progress with morph targets API

Vicente Penades 6 yıl önce
ebeveyn
işleme
2d5a0669f8

+ 5 - 3
src/SharpGLTF.Toolkit/Geometry/MeshBuilderToolkit.cs

@@ -23,13 +23,15 @@ namespace SharpGLTF.Geometry
 
 
     static class MeshBuilderToolkit
     static class MeshBuilderToolkit
     {
     {
-        public static IReadOnlyList<IVertexBuilder> GetMorphTargetVertices(this IMorphTargetReader morphTarget, int targetIndex, int vertexCount)
+        public static VertexBuilder<VertexGeometryDelta, VertexEmpty, VertexEmpty>[] GetMorphTargetVertices(this IPrimitiveMorphTargetReader morphTarget, int vertexCount, int targetIndex)
         {
         {
-            var c = new IVertexBuilder[vertexCount];
+            var c = new VertexBuilder<VertexGeometryDelta, VertexEmpty, VertexEmpty>[vertexCount];
 
 
             for (int i = 0; i < vertexCount; ++i)
             for (int i = 0; i < vertexCount; ++i)
             {
             {
-                c[i] = morphTarget.GetVertexDisplacement(targetIndex, i);
+                var delta = morphTarget.GetVertexDelta(targetIndex, i);
+
+                c[i] = new VertexBuilder<VertexGeometryDelta, VertexEmpty, VertexEmpty>(delta);
             }
             }
 
 
             return c;
             return c;

+ 70 - 62
src/SharpGLTF.Toolkit/Geometry/MorphTargetBuilder.cs

@@ -8,20 +8,31 @@ using SharpGLTF.Geometry.VertexTypes;
 
 
 namespace SharpGLTF.Geometry
 namespace SharpGLTF.Geometry
 {
 {
-    public interface IMorphTargetReader
+    public interface IPrimitiveMorphTargetReader
     {
     {
         int TargetsCount { get; }
         int TargetsCount { get; }
 
 
+        /// <summary>
+        /// Gets the collection of vertex indices that have deltas.
+        /// </summary>
+        /// <param name="morphTargetIndex">The morph target to query.</param>
+        /// <returns>A collection of vertex indices.</returns>
         IReadOnlyCollection<int> GetTargetIndices(int morphTargetIndex);
         IReadOnlyCollection<int> GetTargetIndices(int morphTargetIndex);
 
 
-        IVertexBuilder GetVertexDisplacement(int morphTargetIndex, int vertexIndex);
+        /// <summary>
+        /// Gets the <see cref="VertexGeometryDelta"/> of a given vertex for a given morph target.
+        /// </summary>
+        /// <param name="morphTargetIndex"></param>
+        /// <param name="vertexIndex"></param>
+        /// <returns></returns>
+        VertexGeometryDelta GetVertexDelta(int morphTargetIndex, int vertexIndex);
     }
     }
 
 
-    public class MorphTargetBuilder<TvG> : IMorphTargetReader
+    public class PrimitiveMorphTargetBuilder<TvG> : IPrimitiveMorphTargetReader
         where TvG : struct, IVertexGeometry
         where TvG : struct, IVertexGeometry
     {
     {
         #region lifecycle
         #region lifecycle
-        internal MorphTargetBuilder(Func<int, TvG> baseVertexFunc)
+        internal PrimitiveMorphTargetBuilder(Func<int, TvG> baseVertexFunc)
         {
         {
             _BaseVertexFunc = baseVertexFunc;
             _BaseVertexFunc = baseVertexFunc;
         }
         }
@@ -40,8 +51,6 @@ namespace SharpGLTF.Geometry
 
 
         public int TargetsCount => _Targets.Count;
         public int TargetsCount => _Targets.Count;
 
 
-        public Boolean AbsoluteMode => true;
-
         #endregion
         #endregion
 
 
         #region API
         #region API
@@ -51,60 +60,42 @@ namespace SharpGLTF.Geometry
             return morphTargetIndex < _Targets.Count ? _Targets[morphTargetIndex].Keys : (IReadOnlyCollection<int>)Array.Empty<int>();
             return morphTargetIndex < _Targets.Count ? _Targets[morphTargetIndex].Keys : (IReadOnlyCollection<int>)Array.Empty<int>();
         }
         }
 
 
-        IVertexBuilder IMorphTargetReader.GetVertexDisplacement(int morphTargetIndex, int vertexIndex)
-        {
-            var g = _GetVertexDisplacement(morphTargetIndex, vertexIndex);
-
-            return new VertexBuilder<TvG, VertexEmpty, VertexEmpty>(g);
-        }
-
-        TvG GetVertexDisplacement(int morphTargetIndex, int vertexIndex)
-        {
-            return _GetVertexDisplacement(morphTargetIndex, vertexIndex);
-        }
-
-        private TvG _GetVertexDisplacement(int morphTargetIndex, int vertexIndex)
+        public VertexGeometryDelta GetVertexDelta(int morphTargetIndex, int vertexIndex)
         {
         {
             var target = _Targets[morphTargetIndex];
             var target = _Targets[morphTargetIndex];
 
 
             if (target.TryGetValue(vertexIndex, out TvG value))
             if (target.TryGetValue(vertexIndex, out TvG value))
             {
             {
-                if (this.AbsoluteMode) value = (TvG)value.ToDisplaceMorph(_BaseVertexFunc(vertexIndex));
-
-                return value;
+                return value.Subtract(_BaseVertexFunc(vertexIndex));
             }
             }
 
 
             return default;
             return default;
         }
         }
 
 
-        public TvG GetVertex(int morphTargetIndex, int vertexIndex)
+        public void SetVertexDelta(int morphTargetIndex, int vertexIndex, VertexGeometryDelta value)
         {
         {
-            var target = _Targets[morphTargetIndex];
-
-            if (target.TryGetValue(vertexIndex, out TvG value))
+            if (object.Equals(value, default(VertexGeometryDelta)))
             {
             {
-                if (!this.AbsoluteMode) value = (TvG)value.ToAbsoluteMorph(_BaseVertexFunc(vertexIndex));
-
-                return value;
+                _RemoveVertex(morphTargetIndex, vertexIndex);
+                return;
             }
             }
 
 
-            return _BaseVertexFunc(vertexIndex);
+            var vertex = _BaseVertexFunc(vertexIndex);
+            vertex.Add(value);
+
+            _SetVertex(morphTargetIndex, vertexIndex, vertex);
         }
         }
 
 
-        public void SetVertexDisplacement(int morphTargetIndex, int vertexIndex, TvG value)
+        public TvG GetVertex(int morphTargetIndex, int vertexIndex)
         {
         {
-            if (object.Equals(value, default(TvG)))
-            {
-                _RemoveVertex(morphTargetIndex, vertexIndex);
-                return;
-            }
+            var target = _Targets[morphTargetIndex];
 
 
-            if (this.AbsoluteMode)
+            if (target.TryGetValue(vertexIndex, out TvG value))
             {
             {
-                value = (TvG)value.ToAbsoluteMorph(_BaseVertexFunc(vertexIndex));
+                return value;
             }
             }
 
 
-            _SetVertex(morphTargetIndex, vertexIndex, value);
+            return _BaseVertexFunc(vertexIndex);
         }
         }
 
 
         public void SetVertex(int morphTargetIndex, int vertexIndex, TvG value)
         public void SetVertex(int morphTargetIndex, int vertexIndex, TvG value)
@@ -115,11 +106,6 @@ namespace SharpGLTF.Geometry
                 return;
                 return;
             }
             }
 
 
-            if (!this.AbsoluteMode)
-            {
-                value = (TvG)value.ToDisplaceMorph(_BaseVertexFunc(vertexIndex));
-            }
-
             _SetVertex(morphTargetIndex, vertexIndex, value);
             _SetVertex(morphTargetIndex, vertexIndex, value);
         }
         }
 
 
@@ -161,7 +147,7 @@ namespace SharpGLTF.Geometry
             }
             }
         }
         }
 
 
-        internal void SetMorphTargets(MorphTargetBuilder<TvG> other, IReadOnlyDictionary<int, int> vertexMap, Func<TvG, TvG> vertexFunc)
+        internal void SetMorphTargets(PrimitiveMorphTargetBuilder<TvG> other, IReadOnlyDictionary<int, int> vertexMap, Func<TvG, TvG> vertexFunc)
         {
         {
             for (int tidx = 0; tidx < other.TargetsCount; ++tidx)
             for (int tidx = 0; tidx < other.TargetsCount; ++tidx)
             {
             {
@@ -198,34 +184,56 @@ namespace SharpGLTF.Geometry
             _Mesh = mesh;
             _Mesh = mesh;
             _MorphTargetIndex = morphTargetIndex;
             _MorphTargetIndex = morphTargetIndex;
 
 
-            _Positions = _Mesh.Primitives
-                .SelectMany(item => item.Vertices)
-                .Select(item => item.Position)
-                .Distinct()
-                .ToArray();
+            foreach (var prim in _Mesh.Primitives)
+            {
+                for (int vidx = 0; vidx < prim.Vertices.Count; ++vidx)
+                {
+                    var key = prim.Vertices[vidx].Geometry;
+
+                    if (!_Vertices.TryGetValue(key, out List<(PrimitiveBuilder<TMaterial, TvG, TvM, TvS>, int)> val))
+                    {
+                        _Vertices[key] = val = new List<(PrimitiveBuilder<TMaterial, TvG, TvM, TvS>, int)>();
+                    }
+
+                    val.Add((prim, vidx));
+
+                    if (!_Positions.TryGetValue(key.GetPosition(), out List<TvG> geos))
+                    {
+                        _Positions[key.GetPosition()] = geos = new List<TvG>();
+                    }
+
+                    geos.Add(key);
+                }
+            }
+
         }
         }
 
 
         private readonly MeshBuilder<TMaterial, TvG, TvM, TvS> _Mesh;
         private readonly MeshBuilder<TMaterial, TvG, TvM, TvS> _Mesh;
         private readonly int _MorphTargetIndex;
         private readonly int _MorphTargetIndex;
 
 
-        private readonly Vector3[] _Positions;
+        private readonly Dictionary<TvG, List<(PrimitiveBuilder<TMaterial, TvG, TvM, TvS>, int)>> _Vertices = new Dictionary<TvG, List<(PrimitiveBuilder<TMaterial, TvG, TvM, TvS>, int)>>();
 
 
-        public IReadOnlyList<Vector3> Positions => _Positions;
+        private readonly Dictionary<Vector3, List<TvG>> _Positions = new Dictionary<Vector3, List<TvG>>();
 
 
-        public void SetVertexDisplacement(Vector3 key, Vector3 displacement)
-        {
-            var g = default(TvG);
+        public IReadOnlyCollection<Vector3> Positions => _Positions.Keys;
 
 
-            g.SetPosition(displacement);
+        public IReadOnlyCollection<TvG> Vertices => _Vertices.Keys;
 
 
-            foreach (var p in _Mesh.Primitives)
+        public void SetVertexDelta(Vector3 key, VertexGeometryDelta delta)
+        {
+            if (_Positions.TryGetValue(key, out List<TvG> geos))
             {
             {
-                for (int i = 0; i < p.Vertices.Count; ++i)
+                foreach (var g in geos) SetVertexDisplacement(g, delta);
+            }
+        }
+
+        public void SetVertexDisplacement(TvG vertex, VertexGeometryDelta delta)
+        {
+            if (_Vertices.TryGetValue(vertex, out List<(PrimitiveBuilder<TMaterial, TvG, TvM, TvS>, int)> val))
+            {
+                foreach (var entry in val)
                 {
                 {
-                    if (p.Vertices[i].Position == key)
-                    {
-                        p.MorphTargets.SetVertexDisplacement(_MorphTargetIndex, i, g);
-                    }
+                    entry.Item1.MorphTargets.SetVertexDelta(_MorphTargetIndex, entry.Item2, delta);
                 }
                 }
             }
             }
         }
         }

+ 31 - 10
src/SharpGLTF.Toolkit/Geometry/PackedPrimitiveBuilder.cs

@@ -88,22 +88,21 @@ namespace SharpGLTF.Geometry
 
 
         public void SetMorphTargets(IPrimitiveReader<TMaterial> srcPrim)
         public void SetMorphTargets(IPrimitiveReader<TMaterial> srcPrim)
         {
         {
-            var vAccessors = new List<Memory.MemoryAccessor>();
+            bool hasPositions = _VertexAccessors.Any(item => item.Attribute.Name == "POSITION");
+            bool hasNormals = _VertexAccessors.Any(item => item.Attribute.Name == "NORMAL");
+            bool hasTangents = _VertexAccessors.Any(item => item.Attribute.Name == "TANGENT");
+
+            if (!hasPositions) throw new InvalidOperationException("Set vertices before morph targets.");
 
 
             for (int i = 0; i < srcPrim.MorphTargets.TargetsCount; ++i)
             for (int i = 0; i < srcPrim.MorphTargets.TargetsCount; ++i)
             {
             {
-                var mtv = srcPrim.MorphTargets.GetMorphTargetVertices(i, srcPrim.Vertices.Count);
+                var mtv = srcPrim.MorphTargets.GetMorphTargetVertices(srcPrim.Vertices.Count, i);
 
 
-                vAccessors.Clear();
+                var pAccessor = VertexTypes.VertexUtils.CreateVertexMemoryAccessor(mtv, "POSITIONDELTA", EncodingType.UNSIGNED_SHORT);
 
 
-                var pAccessor = VertexTypes.VertexUtils.CreateVertexMemoryAccessor(mtv, "POSITION", EncodingType.UNSIGNED_SHORT);
-                if (pAccessor != null) vAccessors.Add(pAccessor);
+                var nAccessor = !hasNormals ? null : VertexTypes.VertexUtils.CreateVertexMemoryAccessor(mtv, "NORMALDELTA", EncodingType.UNSIGNED_SHORT);
 
 
-                var nAccessor = VertexTypes.VertexUtils.CreateVertexMemoryAccessor(mtv, "NORMAL", EncodingType.UNSIGNED_SHORT);
-                if (nAccessor != null) vAccessors.Add(nAccessor);
-
-                var tAccessor = VertexTypes.VertexUtils.CreateVertexMemoryAccessor(mtv, "MORPHTANGENT", EncodingType.UNSIGNED_SHORT);
-                if (tAccessor != null) vAccessors.Add(tAccessor);
+                var tAccessor = !hasTangents ? null : VertexTypes.VertexUtils.CreateVertexMemoryAccessor(mtv, "TANGENTDELTA", EncodingType.UNSIGNED_SHORT);
 
 
                 AddMorphTarget(pAccessor, nAccessor, tAccessor);
                 AddMorphTarget(pAccessor, nAccessor, tAccessor);
             }
             }
@@ -113,9 +112,31 @@ namespace SharpGLTF.Geometry
         {
         {
             morphTarget = morphTarget.Where(item => item != null).ToArray();
             morphTarget = morphTarget.Where(item => item != null).ToArray();
 
 
+            foreach (var accessor in morphTarget)
+            {
+                if (accessor.Attribute.Dimensions != DimensionType.VEC3) throw new InvalidOperationException();
+            }
+
+            morphTarget = morphTarget
+                .Select(item => _RemoveDelta(item))
+                .ToArray();
+
             _MorphTargets.Add(morphTarget);
             _MorphTargets.Add(morphTarget);
         }
         }
 
 
+        private static Memory.MemoryAccessor _RemoveDelta(Memory.MemoryAccessor accessor)
+        {
+            var name = accessor.Attribute.Name;
+            if (!name.EndsWith("DELTA", StringComparison.Ordinal)) throw new InvalidOperationException();
+
+            name = name.Substring(0, name.Length - 5);
+
+            var attr = accessor.Attribute;
+            attr.Name = name;
+
+            return new SharpGLTF.Memory.MemoryAccessor(accessor.Data, attr);
+        }
+
         internal void CopyToMesh(Mesh dstMesh, Func<TMaterial, Material> materialEvaluator)
         internal void CopyToMesh(Mesh dstMesh, Func<TMaterial, Material> materialEvaluator)
         {
         {
             if (_VerticesPerPrimitive < 1 || _VerticesPerPrimitive > 3) return;
             if (_VerticesPerPrimitive < 1 || _VerticesPerPrimitive > 3) return;

+ 9 - 14
src/SharpGLTF.Toolkit/Geometry/PrimitiveBuilder.cs

@@ -32,7 +32,7 @@ namespace SharpGLTF.Geometry
         /// </summary>
         /// </summary>
         IReadOnlyList<IVertexBuilder> Vertices { get; }
         IReadOnlyList<IVertexBuilder> Vertices { get; }
 
 
-        IMorphTargetReader MorphTargets { get; }
+        IPrimitiveMorphTargetReader MorphTargets { get; }
 
 
         /// <summary>
         /// <summary>
         /// Gets the indices of all points, given that <see cref="VerticesPerPrimitive"/> is 1.
         /// Gets the indices of all points, given that <see cref="VerticesPerPrimitive"/> is 1.
@@ -68,7 +68,7 @@ namespace SharpGLTF.Geometry
         /// </summary>
         /// </summary>
         Type VertexType { get; }
         Type VertexType { get; }
 
 
-        void SetVertexDisplacement(int morphTargetIndex, int vertexIndex, IVertexGeometry vertex);
+        void SetVertexDelta(int morphTargetIndex, int vertexIndex, VertexGeometryDelta delta);
 
 
         int AddPoint(IVertexBuilder a);
         int AddPoint(IVertexBuilder a);
 
 
@@ -121,7 +121,7 @@ namespace SharpGLTF.Geometry
             this._Mesh = mesh;
             this._Mesh = mesh;
             this._Material = material;
             this._Material = material;
 
 
-            this._MorphTargets = new MorphTargetBuilder<TvG>( idx => _Vertices[idx].Geometry );
+            this._MorphTargets = new PrimitiveMorphTargetBuilder<TvG>( idx => _Vertices[idx].Geometry );
         }
         }
 
 
         #endregion
         #endregion
@@ -134,7 +134,7 @@ namespace SharpGLTF.Geometry
 
 
         private readonly VertexListWrapper _Vertices = new VertexListWrapper();
         private readonly VertexListWrapper _Vertices = new VertexListWrapper();
 
 
-        private readonly MorphTargetBuilder<TvG> _MorphTargets;
+        private readonly PrimitiveMorphTargetBuilder<TvG> _MorphTargets;
 
 
         #endregion
         #endregion
 
 
@@ -166,9 +166,9 @@ namespace SharpGLTF.Geometry
 
 
         public virtual IReadOnlyList<(int, int, int, int?)> Surfaces => Array.Empty<(int, int, int, int?)>();
         public virtual IReadOnlyList<(int, int, int, int?)> Surfaces => Array.Empty<(int, int, int, int?)>();
 
 
-        public MorphTargetBuilder<TvG> MorphTargets => _MorphTargets;
+        public PrimitiveMorphTargetBuilder<TvG> MorphTargets => _MorphTargets;
 
 
-        IMorphTargetReader IPrimitiveReader<TMaterial>.MorphTargets => _MorphTargets;
+        IPrimitiveMorphTargetReader IPrimitiveReader<TMaterial>.MorphTargets => _MorphTargets;
 
 
         #endregion
         #endregion
 
 
@@ -204,14 +204,9 @@ namespace SharpGLTF.Geometry
             return _Vertices.Use(vertex);
             return _Vertices.Use(vertex);
         }
         }
 
 
-        void IPrimitiveBuilder.SetVertexDisplacement(int morphTargetIndex, int vertexIndex, IVertexGeometry vertex)
+        void IPrimitiveBuilder.SetVertexDelta(int morphTargetIndex, int vertexIndex, VertexGeometryDelta delta)
         {
         {
-            Guard.NotNull(vertex, nameof(vertex));
-
-            var v = vertex.ConvertToGeometry<TvG>();
-            System.Diagnostics.Debug.Assert(v.GetPosition() == vertex.GetPosition());
-
-            this._MorphTargets.SetVertexDisplacement(morphTargetIndex, vertexIndex, v);
+            this._MorphTargets.SetVertexDelta(morphTargetIndex, vertexIndex, delta);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -399,7 +394,7 @@ namespace SharpGLTF.Geometry
         {
         {
             throw new NotSupportedException("Quadrangles are not supported for this primitive");
             throw new NotSupportedException("Quadrangles are not supported for this primitive");
         }
         }
-        
+
         #endregion
         #endregion
 
 
         #region helper types
         #region helper types

+ 62 - 36
src/SharpGLTF.Toolkit/Geometry/VertexBuilder.cs

@@ -69,12 +69,73 @@ namespace SharpGLTF.Geometry
     /// <see cref="VertexJoints4"/>,
     /// <see cref="VertexJoints4"/>,
     /// <see cref="VertexJoints8"/>.
     /// <see cref="VertexJoints8"/>.
     /// </typeparam>
     /// </typeparam>
-    [System.Diagnostics.DebuggerDisplay("Vertex 𝐏:{Position} {_GetDebugWarnings()}")]
+    [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
     public partial struct VertexBuilder<TvG, TvM, TvS> : IVertexBuilder
     public partial struct VertexBuilder<TvG, TvM, TvS> : IVertexBuilder
         where TvG : struct, IVertexGeometry
         where TvG : struct, IVertexGeometry
         where TvM : struct, IVertexMaterial
         where TvM : struct, IVertexMaterial
         where TvS : struct, IVertexSkinning
         where TvS : struct, IVertexSkinning
     {
     {
+        #region debug
+
+        internal string _GetDebuggerDisplay()
+        {
+            var txt = "Vertex ";
+
+            txt += " " + _GetDebuggerDisplayTextFrom(Geometry);
+            txt += " " + _GetDebuggerDisplayTextFrom(Material);
+            txt += " " + _GetDebuggerDisplayTextFrom(Skinning);
+
+            return txt;
+        }
+
+        private static string _GetDebuggerDisplayTextFrom(Object o)
+        {
+            var bindings = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance;
+
+            var method = o.GetType().GetMethod("_GetDebuggerDisplay", bindings);
+
+            if (method == null) return string.Empty;
+
+            return method.Invoke(o, Array.Empty<Object>()) as string;
+        }
+
+        private String _GetDebugWarnings()
+        {
+            var sb = new StringBuilder();
+
+            if (Geometry.TryGetNormal(out Vector3 n))
+            {
+                if (!n.IsValidNormal()) sb.Append($" ❌𝚴:{n}");
+            }
+
+            if (Geometry.TryGetTangent(out Vector4 t))
+            {
+                if (!t.IsValidTangent()) sb.Append($" ❌𝚻:{t}");
+            }
+
+            for (int i = 0; i < Material.MaxColors; ++i)
+            {
+                var c = Material.GetColor(i);
+                if (!c._IsFinite() | !c.IsInRange(Vector4.Zero, Vector4.One)) sb.Append($" ❌𝐂{i}:{c}");
+            }
+
+            for (int i = 0; i < Material.MaxTextCoords; ++i)
+            {
+                var uv = Material.GetTexCoord(i);
+                if (!uv._IsFinite()) sb.Append($" ❌𝐔𝐕{i}:{uv}");
+            }
+
+            for (int i = 0; i < Skinning.MaxBindings; ++i)
+            {
+                var jw = Skinning.GetJointBinding(i);
+                if (!jw.Item2._IsFinite() || jw.Item2 < 0 || jw.Item1 < 0) sb.Append($" ❌𝐉𝐖{i} {jw.Item1}:{jw.Item2}");
+            }
+
+            return sb.ToString();
+        }
+
+        #endregion
+
         #region constructors
         #region constructors
 
 
         public VertexBuilder(TvG g, TvM m, TvS s)
         public VertexBuilder(TvG g, TvM m, TvS s)
@@ -308,41 +369,6 @@ namespace SharpGLTF.Geometry
             return new MeshBuilder<TvG, TvM, TvS>(name);
             return new MeshBuilder<TvG, TvM, TvS>(name);
         }
         }
 
 
-        private String _GetDebugWarnings()
-        {
-            var sb = new StringBuilder();
-
-            if (Geometry.TryGetNormal(out Vector3 n))
-            {
-                if (!n.IsValidNormal()) sb.Append($" ❌𝚴:{n}");
-            }
-
-            if (Geometry.TryGetTangent(out Vector4 t))
-            {
-                if (!t.IsValidTangent()) sb.Append($" ❌𝚻:{t}");
-            }
-
-            for (int i = 0; i < Material.MaxColors; ++i)
-            {
-                var c = Material.GetColor(i);
-                if (!c._IsFinite() | !c.IsInRange(Vector4.Zero, Vector4.One)) sb.Append($" ❌𝐂{i}:{c}");
-            }
-
-            for (int i = 0; i < Material.MaxTextCoords; ++i)
-            {
-                var uv = Material.GetTexCoord(i);
-                if (!uv._IsFinite()) sb.Append($" ❌𝐔𝐕{i}:{uv}");
-            }
-
-            for (int i = 0; i < Skinning.MaxBindings; ++i)
-            {
-                var jw = Skinning.GetJointBinding(i);
-                if (!jw.Item2._IsFinite() || jw.Item2 < 0 || jw.Item1 < 0) sb.Append($" ❌𝐉𝐖{i} {jw.Item1}:{jw.Item2}");
-            }
-
-            return sb.ToString();
-        }
-
         IVertexGeometry IVertexBuilder.GetGeometry() { return this.Geometry; }
         IVertexGeometry IVertexBuilder.GetGeometry() { return this.Geometry; }
 
 
         IVertexMaterial IVertexBuilder.GetMaterial() { return this.Material; }
         IVertexMaterial IVertexBuilder.GetMaterial() { return this.Material; }

+ 108 - 41
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexGeometry.cs

@@ -19,8 +19,9 @@ namespace SharpGLTF.Geometry.VertexTypes
 
 
         void ApplyTransform(Matrix4x4 xform);
         void ApplyTransform(Matrix4x4 xform);
 
 
-        IVertexGeometry ToAbsoluteMorph(IVertexGeometry baseValue);
-        IVertexGeometry ToDisplaceMorph(IVertexGeometry baseValue);
+        VertexGeometryDelta Subtract(IVertexGeometry baseValue);
+
+        void Add(VertexGeometryDelta delta);
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -75,16 +76,14 @@ namespace SharpGLTF.Geometry.VertexTypes
 
 
         void IVertexGeometry.SetTangent(Vector4 tangent) { }
         void IVertexGeometry.SetTangent(Vector4 tangent) { }
 
 
-        IVertexGeometry IVertexGeometry.ToAbsoluteMorph(IVertexGeometry baseValue)
+        public VertexGeometryDelta Subtract(IVertexGeometry baseValue)
         {
         {
-            var bv = (VertexPosition)baseValue;
-            return new VertexPosition(this.Position + bv.Position);
+            return new VertexGeometryDelta((VertexPosition)baseValue, this);
         }
         }
 
 
-        IVertexGeometry IVertexGeometry.ToDisplaceMorph(IVertexGeometry baseValue)
+        public void Add(VertexGeometryDelta delta)
         {
         {
-            var bv = (VertexPosition)baseValue;
-            return new VertexPosition(this.Position - bv.Position);
+            this.Position += delta.PositionDelta;
         }
         }
 
 
         public Vector3 GetPosition() { return this.Position; }
         public Vector3 GetPosition() { return this.Position; }
@@ -162,16 +161,15 @@ namespace SharpGLTF.Geometry.VertexTypes
 
 
         void IVertexGeometry.SetTangent(Vector4 tangent) { }
         void IVertexGeometry.SetTangent(Vector4 tangent) { }
 
 
-        IVertexGeometry IVertexGeometry.ToAbsoluteMorph(IVertexGeometry baseValue)
+        public VertexGeometryDelta Subtract(IVertexGeometry baseValue)
         {
         {
-            var bv = (VertexPositionNormal)baseValue;
-            return new VertexPositionNormal(this.Position + bv.Position, this.Normal + bv.Normal);
+            return new VertexGeometryDelta((VertexPositionNormal)baseValue, this);
         }
         }
 
 
-        IVertexGeometry IVertexGeometry.ToDisplaceMorph(IVertexGeometry baseValue)
+        public void Add(VertexGeometryDelta delta)
         {
         {
-            var bv = (VertexPositionNormal)baseValue;
-            return new VertexPositionNormal(this.Position - bv.Position, this.Normal - bv.Normal);
+            this.Position += delta.PositionDelta;
+            this.Normal += delta.NormalDelta;
         }
         }
 
 
         public Vector3 GetPosition() { return this.Position; }
         public Vector3 GetPosition() { return this.Position; }
@@ -249,16 +247,16 @@ namespace SharpGLTF.Geometry.VertexTypes
 
 
         void IVertexGeometry.SetTangent(Vector4 tangent) { this.Tangent = tangent; }
         void IVertexGeometry.SetTangent(Vector4 tangent) { this.Tangent = tangent; }
 
 
-        IVertexGeometry IVertexGeometry.ToAbsoluteMorph(IVertexGeometry baseValue)
+        public VertexGeometryDelta Subtract(IVertexGeometry baseValue)
         {
         {
-            var bv = (VertexPositionNormalTangent)baseValue;
-            return new VertexPositionNormalTangent(this.Position + bv.Position, this.Normal + bv.Normal, this.Tangent + bv.Tangent);
+            return new VertexGeometryDelta((VertexPositionNormalTangent)baseValue, this);
         }
         }
 
 
-        IVertexGeometry IVertexGeometry.ToDisplaceMorph(IVertexGeometry baseValue)
+        public void Add(VertexGeometryDelta delta)
         {
         {
-            var bv = (VertexPositionNormalTangent)baseValue;
-            return new VertexPositionNormalTangent(this.Position - bv.Position, this.Normal - bv.Normal, this.Tangent - bv.Tangent);
+            this.Position += delta.PositionDelta;
+            this.Normal += delta.NormalDelta;
+            this.Tangent += new Vector4(delta.TangentDelta, 0);
         }
         }
 
 
         public Vector3 GetPosition() { return this.Position; }
         public Vector3 GetPosition() { return this.Position; }
@@ -286,53 +284,122 @@ namespace SharpGLTF.Geometry.VertexTypes
     /// Defines a Vertex attribute with a Position, a Normal and a Tangent.
     /// Defines a Vertex attribute with a Position, a Normal and a Tangent.
     /// </summary>
     /// </summary>
     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
     [System.Diagnostics.DebuggerDisplay("{_GetDebuggerDisplay(),nq}")]
-    struct VertexPositionNormalTangentDisplacement : IVertexGeometry
+    public struct VertexGeometryDelta : IVertexGeometry
     {
     {
         #region debug
         #region debug
 
 
-        private string _GetDebuggerDisplay() => $"𝐏:{Position} 𝚴:{Normal} 𝚻:{Tangent}";
+        private string _GetDebuggerDisplay() => $"Δ𝐏:{PositionDelta} Δ𝚴:{NormalDelta} Δ𝚻:{TangentDelta}";
 
 
         #endregion
         #endregion
 
 
-        #region data
+        #region constructors
 
 
-        [VertexAttribute("POSITION")]
-        public Vector3 Position;
+        public static implicit operator VertexGeometryDelta(Vector3 position)
+        {
+            return new VertexGeometryDelta(position, Vector3.Zero, Vector3.Zero);
+        }
 
 
-        [VertexAttribute("NORMAL")]
-        public Vector3 Normal;
+        public static implicit operator VertexGeometryDelta((Vector3, Vector3) tuple)
+        {
+            return new VertexGeometryDelta(tuple.Item1, tuple.Item2, Vector3.Zero);
+        }
 
 
-        [VertexAttribute("TANGENT")]
-        public Vector3 Tangent;
+        public static implicit operator VertexGeometryDelta((Vector3, Vector3, Vector3) tuple)
+        {
+            return new VertexGeometryDelta(tuple.Item1, tuple.Item2, tuple.Item3);
+        }
 
 
-        #endregion
+        public VertexGeometryDelta(IVertexGeometry src)
+        {
+            Guard.NotNull(src, nameof(src));
 
 
-        #region API
+            this.PositionDelta = src.GetPosition();
+            src.TryGetNormal(out this.NormalDelta);
+            src.TryGetTangent(out Vector4 t);
 
 
-        void IVertexGeometry.SetPosition(Vector3 position) { this.Position = position; }
+            this.TangentDelta = new Vector3(t.X, t.Y, t.Z);
+        }
 
 
-        void IVertexGeometry.SetNormal(Vector3 normal) { this.Normal = normal; }
+        public VertexGeometryDelta(Vector3 p, Vector3 n, Vector3 t)
+        {
+            this.PositionDelta = p;
+            this.NormalDelta = n;
+            this.TangentDelta = t;
+        }
+
+        internal VertexGeometryDelta(VertexPosition rootVal, VertexPosition morphVal)
+        {
+            PositionDelta = morphVal.Position - rootVal.Position;
+            NormalDelta = Vector3.Zero;
+            TangentDelta = Vector3.Zero;
+        }
 
 
-        void IVertexGeometry.SetTangent(Vector4 tangent) { this.Tangent = new Vector3(tangent.X, tangent.Y, tangent.Z); }
+        internal VertexGeometryDelta(VertexPositionNormal rootVal, VertexPositionNormal morphVal)
+        {
+            PositionDelta = morphVal.Position - rootVal.Position;
+            NormalDelta = morphVal.Normal - rootVal.Normal;
+            TangentDelta = Vector3.Zero;
+        }
 
 
-        IVertexGeometry IVertexGeometry.ToAbsoluteMorph(IVertexGeometry baseValue)
+        internal VertexGeometryDelta(VertexPositionNormalTangent rootVal, VertexPositionNormalTangent morphVal)
         {
         {
-            throw new NotSupportedException();
+            PositionDelta = morphVal.Position - rootVal.Position;
+            NormalDelta = morphVal.Normal - rootVal.Normal;
+
+            var dt = morphVal.Tangent - rootVal.Tangent;
+            TangentDelta = new Vector3(dt.X, dt.Y, dt.Z);
         }
         }
 
 
-        IVertexGeometry IVertexGeometry.ToDisplaceMorph(IVertexGeometry baseValue)
+        internal VertexGeometryDelta(VertexGeometryDelta rootVal, VertexGeometryDelta morphVal)
         {
         {
-            throw new NotSupportedException();
+            PositionDelta = morphVal.PositionDelta - rootVal.PositionDelta;
+            NormalDelta = morphVal.NormalDelta - rootVal.NormalDelta;
+            TangentDelta = morphVal.TangentDelta - rootVal.TangentDelta;
         }
         }
 
 
-        public Vector3 GetPosition() { return this.Position; }
+        #endregion
 
 
-        public bool TryGetNormal(out Vector3 normal) { normal = this.Normal; return true; }
+        #region data
+
+        [VertexAttribute("POSITIONDELTA")]
+        public Vector3 PositionDelta;
+
+        [VertexAttribute("NORMALDELTA")]
+        public Vector3 NormalDelta;
+
+        [VertexAttribute("TANGENTDELTA")]
+        public Vector3 TangentDelta;
+
+        #endregion
 
 
-        public bool TryGetTangent(out Vector4 tangent) { tangent = new Vector4(this.Tangent, 0); return true; }
+        #region API
+
+        void IVertexGeometry.SetPosition(Vector3 position) { this.PositionDelta = position; }
+
+        void IVertexGeometry.SetNormal(Vector3 normal) { this.NormalDelta = normal; }
+
+        void IVertexGeometry.SetTangent(Vector4 tangent) { this.TangentDelta = new Vector3(tangent.X, tangent.Y, tangent.Z); }
+
+        public Vector3 GetPosition() { return this.PositionDelta; }
+
+        public bool TryGetNormal(out Vector3 normal) { normal = this.NormalDelta; return true; }
+
+        public bool TryGetTangent(out Vector4 tangent) { tangent = new Vector4(this.TangentDelta, 0); return true; }
 
 
         public void ApplyTransform(Matrix4x4 xform) { throw new NotSupportedException(); }
         public void ApplyTransform(Matrix4x4 xform) { throw new NotSupportedException(); }
 
 
+        public VertexGeometryDelta Subtract(IVertexGeometry baseValue)
+        {
+            return new VertexGeometryDelta((VertexGeometryDelta)baseValue, this);
+        }
+
+        public void Add(VertexGeometryDelta delta)
+        {
+            this.PositionDelta += delta.PositionDelta;
+            this.NormalDelta += delta.NormalDelta;
+            this.TangentDelta += delta.TangentDelta;
+        }
+
         public void Validate() { }
         public void Validate() { }
 
 
         #endregion
         #endregion

+ 42 - 0
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexMaterial.cs

@@ -28,6 +28,12 @@ namespace SharpGLTF.Geometry.VertexTypes
     [System.Diagnostics.DebuggerDisplay("𝐂:{Color}")]
     [System.Diagnostics.DebuggerDisplay("𝐂:{Color}")]
     public struct VertexColor1 : IVertexMaterial
     public struct VertexColor1 : IVertexMaterial
     {
     {
+        #region debug
+
+        private string _GetDebuggerDisplay() => $"𝐂:{Color}";
+
+        #endregion
+
         #region constructors
         #region constructors
 
 
         public VertexColor1(Vector4 color)
         public VertexColor1(Vector4 color)
@@ -90,6 +96,12 @@ namespace SharpGLTF.Geometry.VertexTypes
     [System.Diagnostics.DebuggerDisplay("𝐂₀:{Color0} 𝐂₁:{Color1}")]
     [System.Diagnostics.DebuggerDisplay("𝐂₀:{Color0} 𝐂₁:{Color1}")]
     public struct VertexColor2 : IVertexMaterial
     public struct VertexColor2 : IVertexMaterial
     {
     {
+        #region debug
+
+        private string _GetDebuggerDisplay() => $"𝐂₀:{Color0} 𝐂₁:{Color1}";
+
+        #endregion
+
         #region constructors
         #region constructors
 
 
         public VertexColor2(Vector4 color0, Vector4 color1)
         public VertexColor2(Vector4 color0, Vector4 color1)
@@ -159,6 +171,12 @@ namespace SharpGLTF.Geometry.VertexTypes
     [System.Diagnostics.DebuggerDisplay("𝐔𝐕:{TexCoord}")]
     [System.Diagnostics.DebuggerDisplay("𝐔𝐕:{TexCoord}")]
     public struct VertexTexture1 : IVertexMaterial
     public struct VertexTexture1 : IVertexMaterial
     {
     {
+        #region debug
+
+        private string _GetDebuggerDisplay() => $"𝐔𝐕:{TexCoord}";
+
+        #endregion
+
         #region constructors
         #region constructors
 
 
         public VertexTexture1(Vector2 uv)
         public VertexTexture1(Vector2 uv)
@@ -221,6 +239,12 @@ namespace SharpGLTF.Geometry.VertexTypes
     [System.Diagnostics.DebuggerDisplay("𝐔𝐕₀:{TexCoord0} 𝐔𝐕₁:{TexCoord1}")]
     [System.Diagnostics.DebuggerDisplay("𝐔𝐕₀:{TexCoord0} 𝐔𝐕₁:{TexCoord1}")]
     public struct VertexTexture2 : IVertexMaterial
     public struct VertexTexture2 : IVertexMaterial
     {
     {
+        #region debug
+
+        private string _GetDebuggerDisplay() => $"𝐔𝐕₀:{TexCoord0} 𝐔𝐕₁:{TexCoord1}";
+
+        #endregion
+
         #region constructors
         #region constructors
 
 
         public VertexTexture2(Vector2 uv0, Vector2 uv1)
         public VertexTexture2(Vector2 uv0, Vector2 uv1)
@@ -293,6 +317,12 @@ namespace SharpGLTF.Geometry.VertexTypes
     [System.Diagnostics.DebuggerDisplay("𝐂:{Color} 𝐔𝐕:{TexCoord}")]
     [System.Diagnostics.DebuggerDisplay("𝐂:{Color} 𝐔𝐕:{TexCoord}")]
     public struct VertexColor1Texture1 : IVertexMaterial
     public struct VertexColor1Texture1 : IVertexMaterial
     {
     {
+        #region debug
+
+        private string _GetDebuggerDisplay() => $"𝐂:{Color} 𝐔𝐕:{TexCoord}";
+
+        #endregion
+
         #region constructors
         #region constructors
 
 
         public VertexColor1Texture1(Vector4 color, Vector2 tex)
         public VertexColor1Texture1(Vector4 color, Vector2 tex)
@@ -361,6 +391,12 @@ namespace SharpGLTF.Geometry.VertexTypes
     [System.Diagnostics.DebuggerDisplay("𝐂:{Color} 𝐔𝐕₀:{TexCoord0} 𝐔𝐕₁:{TexCoord1}")]
     [System.Diagnostics.DebuggerDisplay("𝐂:{Color} 𝐔𝐕₀:{TexCoord0} 𝐔𝐕₁:{TexCoord1}")]
     public struct VertexColor1Texture2 : IVertexMaterial
     public struct VertexColor1Texture2 : IVertexMaterial
     {
     {
+        #region debug
+
+        private string _GetDebuggerDisplay() => $"𝐂:{Color} 𝐔𝐕₀:{TexCoord0} 𝐔𝐕₁:{TexCoord1}";
+
+        #endregion
+
         #region constructors
         #region constructors
 
 
         public VertexColor1Texture2(Vector4 color, Vector2 tex0, Vector2 tex1)
         public VertexColor1Texture2(Vector4 color, Vector2 tex0, Vector2 tex1)
@@ -442,6 +478,12 @@ namespace SharpGLTF.Geometry.VertexTypes
     [System.Diagnostics.DebuggerDisplay("𝐂₀:{Color0} 𝐂₁:{Color1} 𝐔𝐕₀:{TexCoord0} 𝐔𝐕₁:{TexCoord1}")]
     [System.Diagnostics.DebuggerDisplay("𝐂₀:{Color0} 𝐂₁:{Color1} 𝐔𝐕₀:{TexCoord0} 𝐔𝐕₁:{TexCoord1}")]
     public struct VertexColor2Texture2 : IVertexMaterial
     public struct VertexColor2Texture2 : IVertexMaterial
     {
     {
+        #region debug
+
+        private string _GetDebuggerDisplay() => $"𝐂₀:{Color0} 𝐂₁:{Color1} 𝐔𝐕₀:{TexCoord0} 𝐔𝐕₁:{TexCoord1}";
+
+        #endregion
+
         #region constructors
         #region constructors
 
 
         public VertexColor2Texture2(Vector4 color0, Vector4 color1, Vector2 tex0, Vector2 tex1)
         public VertexColor2Texture2(Vector4 color0, Vector4 color1, Vector2 tex0, Vector2 tex1)

+ 5 - 14
src/SharpGLTF.Toolkit/Geometry/VertexTypes/VertexUtils.cs

@@ -215,14 +215,10 @@ namespace SharpGLTF.Geometry.VertexTypes
             // determine the vertex attributes from the first vertex.
             // determine the vertex attributes from the first vertex.
             var attributes = GetVertexAttributes(vertices[0], vertices.Count, jointEncoding);
             var attributes = GetVertexAttributes(vertices[0], vertices.Count, jointEncoding);
 
 
-            var isMorphTangent = attributeName == "MORPHTANGENT";
-            if (isMorphTangent) attributeName = "TANGENT";
-
             var attribute = attributes.FirstOrDefault(item => item.Name == attributeName);
             var attribute = attributes.FirstOrDefault(item => item.Name == attributeName);
             if (attribute.Name == null) return null;
             if (attribute.Name == null) return null;
             attribute.ByteOffset = 0;
             attribute.ByteOffset = 0;
             attribute.ByteStride = 0;
             attribute.ByteStride = 0;
-            if (isMorphTangent) attribute.Dimensions = Schema2.DimensionType.VEC3;
 
 
             // create a buffer
             // create a buffer
             var vbuffer = new ArraySegment<byte>(new Byte[attribute.PaddedByteLength * vertices.Count]);
             var vbuffer = new ArraySegment<byte>(new Byte[attribute.PaddedByteLength * vertices.Count]);
@@ -230,15 +226,7 @@ namespace SharpGLTF.Geometry.VertexTypes
             // fill the buffer with the vertex attributes.
             // fill the buffer with the vertex attributes.
             var accessor = new MemoryAccessor(vbuffer, attribute);
             var accessor = new MemoryAccessor(vbuffer, attribute);
 
 
-            if (isMorphTangent)
-            {
-                var columnFunc = _GetVertexBuilderAttributeFunc("MORPHTANGENT");
-                accessor.AsVector3Array().Fill(vertices._GetColumn<TVertex, Vector3>(columnFunc));
-            }
-            else
-            {
-                accessor.FillAccessor(vertices);
-            }
+            accessor.FillAccessor(vertices);
 
 
             return accessor;
             return accessor;
         }
         }
@@ -364,7 +352,10 @@ namespace SharpGLTF.Geometry.VertexTypes
             if (attributeName == "POSITION") return v => v.GetGeometry().GetPosition();
             if (attributeName == "POSITION") return v => v.GetGeometry().GetPosition();
             if (attributeName == "NORMAL") return v => { return v.GetGeometry().TryGetNormal(out Vector3 n) ? n : Vector3.Zero; };
             if (attributeName == "NORMAL") return v => { return v.GetGeometry().TryGetNormal(out Vector3 n) ? n : Vector3.Zero; };
             if (attributeName == "TANGENT") return v => { return v.GetGeometry().TryGetTangent(out Vector4 t) ? t : Vector4.Zero; };
             if (attributeName == "TANGENT") return v => { return v.GetGeometry().TryGetTangent(out Vector4 t) ? t : Vector4.Zero; };
-            if (attributeName == "MORPHTANGENT") return v => { return v.GetGeometry().TryGetTangent(out Vector4 t) ? new Vector3(t.X, t.Y, t.Z) : Vector3.Zero; };
+
+            if (attributeName == "POSITIONDELTA") return v => v.GetGeometry().GetPosition();
+            if (attributeName == "NORMALDELTA") return v => { return v.GetGeometry().TryGetNormal(out Vector3 n) ? n : Vector3.Zero; };
+            if (attributeName == "TANGENTDELTA") return v => { return v.GetGeometry().TryGetTangent(out Vector4 t) ? new Vector3(t.X, t.Y, t.Z) : Vector3.Zero; };
 
 
             if (attributeName == "COLOR_0") return v => { var m = v.GetMaterial(); return m.MaxColors <= 0 ? Vector4.One : m.GetColor(0); };
             if (attributeName == "COLOR_0") return v => { var m = v.GetMaterial(); return m.MaxColors <= 0 ? Vector4.One : m.GetColor(0); };
             if (attributeName == "COLOR_1") return v => { var m = v.GetMaterial(); return m.MaxColors <= 1 ? Vector4.One : m.GetColor(1); };
             if (attributeName == "COLOR_1") return v => { var m = v.GetMaterial(); return m.MaxColors <= 1 ? Vector4.One : m.GetColor(1); };

+ 1 - 1
src/SharpGLTF.Toolkit/Schema2/MeshExtensions.cs

@@ -780,7 +780,7 @@ namespace SharpGLTF.Schema2
 
 
                     var v = srcTarget.GetVertex(dstPrim.VertexType, kvp.Key);
                     var v = srcTarget.GetVertex(dstPrim.VertexType, kvp.Key);
 
 
-                    dstPrim.SetVertexDisplacement(tidx, kvp.Value, v.GetGeometry());
+                    dstPrim.SetVertexDelta(tidx, kvp.Value, new VertexGeometryDelta(v.GetGeometry()) );
                 }
                 }
             }
             }
         }
         }

+ 8 - 0
tests/SharpGLTF.Tests/Geometry/VertexTypes/VertexSkinningTests.cs

@@ -10,6 +10,14 @@ namespace SharpGLTF.Geometry.VertexTypes
     [Category("Toolkit")]
     [Category("Toolkit")]
     public class VertexSkinningTests
     public class VertexSkinningTests
     {
     {
+        [Test]
+        public void TestVertexBuilderDebuggerDisplay()
+        {
+            var v = new VertexBuilder<VertexPositionNormalTangent, VertexColor1Texture1, VertexJoints4>();
+
+            var txt = v._GetDebuggerDisplay();
+        }
+
         [Test]
         [Test]
         public void TestVertexSkinningDowngradeFrom8To4Joints()
         public void TestVertexSkinningDowngradeFrom8To4Joints()
         {
         {

+ 4 - 4
tests/SharpGLTF.Tests/Scenes/SceneBuilderTests.cs

@@ -461,10 +461,10 @@ namespace SharpGLTF.Scenes
 
 
             var morphBuilder = mesh2.UseMorphTarget(0);
             var morphBuilder = mesh2.UseMorphTarget(0);
 
 
-            morphBuilder.SetVertexDisplacement(morphBuilder.Positions[0], Vector3.UnitY);
-            morphBuilder.SetVertexDisplacement(morphBuilder.Positions[1], Vector3.UnitY);
-            morphBuilder.SetVertexDisplacement(morphBuilder.Positions[2], Vector3.UnitY);
-            morphBuilder.SetVertexDisplacement(morphBuilder.Positions[3], Vector3.UnitY);
+            morphBuilder.SetVertexDelta(morphBuilder.Positions.ElementAt(0), (Vector3.UnitY, Vector3.Zero));
+            morphBuilder.SetVertexDelta(morphBuilder.Positions.ElementAt(1), (Vector3.UnitY, Vector3.Zero));
+            morphBuilder.SetVertexDelta(morphBuilder.Positions.ElementAt(2), (Vector3.UnitY, Vector3.Zero));
+            morphBuilder.SetVertexDelta(morphBuilder.Positions.ElementAt(3), (Vector3.UnitY, Vector3.Zero));
 
 
             inst2.Content.UseMorphing().Value = Transforms.SparseWeight8.Create(1);
             inst2.Content.UseMorphing().Value = Transforms.SparseWeight8.Create(1);