Przeglądaj źródła

fixed referencing issue when using float[] as curve elements.

Vicente Penades 6 lat temu
rodzic
commit
9002c9039f

+ 36 - 6
src/SharpGLTF.Toolkit/Animations/CurveBuilder.cs

@@ -32,10 +32,31 @@ namespace SharpGLTF.Animations
 
         #region abstract API
 
-        protected abstract bool CheckValue(T value);
-
+        /// <summary>
+        /// Creates a <typeparamref name="T"/> instance from an <see cref="Single"/>[] array.
+        /// </summary>
+        /// <param name="values">An array of floats.</param>
+        /// <returns>A <typeparamref name="T"/> instance.</returns>
         protected abstract T CreateValue(params float[] values);
 
+        /// <summary>
+        /// Ensures that the reference value is only referenced internally.
+        /// </summary>
+        /// <param name="value">A value.</param>
+        /// <returns>A copy of <paramref name="value"/>.</returns>
+        /// <remarks>
+        /// This is required for reference types like float[], where the user
+        /// can add a point using and array, and then reuse the same array to
+        /// define another point, so it can inadvertently overwrite previous
+        /// points already stored in the curve.
+        /// </remarks>
+        protected abstract T IsolateValue(T value);
+
+        /// <summary>
+        /// Samples the curve at a given <paramref name="offset"/>
+        /// </summary>
+        /// <param name="offset">The curve offset to sample.</param>
+        /// <returns>A curve <typeparamref name="T"/> point.</returns>
         public abstract T GetPoint(float offset);
 
         protected abstract T GetTangent(T fromValue, T toValue);
@@ -48,9 +69,18 @@ namespace SharpGLTF.Animations
 
         public void SetPoint(float offset, T value, bool isLinear = true)
         {
-            Guard.IsTrue(CheckValue(value), nameof(value));
+            value = IsolateValue(value);
+
+            if (_Keys.TryGetValue(offset, out _CurveNode<T> existing))
+            {
+                existing.Point = value;
+            }
+            else
+            {
+                existing = new _CurveNode<T>(value, isLinear);
+            }
 
-            _Keys[offset] = new _CurveNode<T>(value, isLinear);
+            _Keys[offset] = existing;
         }
 
         /// <summary>
@@ -61,7 +91,7 @@ namespace SharpGLTF.Animations
         public void SetIncomingTangent(float offset, T tangent)
         {
             Guard.IsTrue(_Keys.ContainsKey(offset), nameof(offset));
-            Guard.IsTrue(CheckValue(tangent), nameof(tangent));
+            tangent = IsolateValue(tangent);
 
             offset -= float.Epsilon;
 
@@ -87,7 +117,7 @@ namespace SharpGLTF.Animations
         public void SetOutgoingTangent(float offset, T tangent)
         {
             Guard.IsTrue(_Keys.ContainsKey(offset), nameof(offset));
-            Guard.IsTrue(CheckValue(tangent), nameof(tangent));
+            tangent = IsolateValue(tangent);
 
             var offsets = SamplerFactory.FindPairContainingOffset(_Keys.Keys, offset);
 

+ 13 - 7
src/SharpGLTF.Toolkit/Animations/CurveFactory.cs

@@ -20,9 +20,9 @@ namespace SharpGLTF.Animations
     [System.Diagnostics.DebuggerTypeProxy(typeof(Debug._CurveBuilderDebugProxyVector3))]
     sealed class Vector3CurveBuilder : CurveBuilder<Vector3>, ICurveSampler<Vector3>
     {
-        protected override bool CheckValue(Vector3 value)
+        protected override Vector3 IsolateValue(Vector3 value)
         {
-            return true;
+            return value;
         }
 
         protected override Vector3 CreateValue(params float[] values)
@@ -66,9 +66,9 @@ namespace SharpGLTF.Animations
     [System.Diagnostics.DebuggerTypeProxy(typeof(Debug._CurveBuilderDebugProxyQuaternion))]
     sealed class QuaternionCurveBuilder : CurveBuilder<Quaternion>, ICurveSampler<Quaternion>
     {
-        protected override bool CheckValue(Quaternion value)
+        protected override Quaternion IsolateValue(Quaternion value)
         {
-            return true;
+            return value;
         }
 
         protected override Quaternion CreateValue(params float[] values)
@@ -115,13 +115,19 @@ namespace SharpGLTF.Animations
         // the first "CheckValue" will fix any further calls to this value.
         private int _ValueLength = 0;
 
-        protected override bool CheckValue(Single[] value)
+        protected override Single[] IsolateValue(Single[] value)
         {
-            if (value == null || value.Length == 0) return false;
+            Guard.NotNull(value, nameof(value));
+            Guard.MustBeGreaterThan(value.Length, 0, nameof(value));
 
             if (_ValueLength == 0) _ValueLength = value.Length;
 
-            return value.Length == _ValueLength;
+            Guard.MustBeBetweenOrEqualTo(value.Length, _ValueLength, _ValueLength, nameof(value));
+
+            var clone = new Single[_ValueLength];
+            value.CopyTo(clone, 0);
+
+            return clone;
         }
 
         protected override Single[] CreateValue(params Single[] values)