protected sealed override void InitializeOverride() { var keyFrames = KeyFramesNode.Retrieve() as ICollection <AnimationKeyFrame <TValue> >; if (keyFrames != null) { KeyFrameControlPointViewModel <TValue> previous = null; foreach (var keyFrame in keyFrames) { var node = Editor.Session.AssetNodeContainer.GetOrCreateNode(keyFrame); // create a control point for the current node var controlPoint = CreateControlPoint(node); if (controlPoint != null) { if (previous != null) { // build the double-linked references previous.Next = controlPoint; controlPoint.Previous = previous; } previous = controlPoint; // add at the end of the list controlPoints.Add(controlPoint); } } } }
/// <inheritdoc/> protected override IEnumerable <Vector2> SampleControlPoints(KeyFrameControlPointViewModel <Quaternion> point1, KeyFrameControlPointViewModel <Quaternion> point2) { if (!point1.IsSynchronized || !point2.IsSynchronized) { // During an edit operation, linearize the curve for better performance. // The other alternative would be to create a temporary curve and evaluate it (we cannot use the underlying curve since it is not synchronized). yield return(point1.Point); } else { var curve = UnderlyingCurve; if (curve == null) { yield break; } double start, end, increment; if (!GetSamplingParameters(XAxis, out start, out end, out increment)) { yield break; } // Limit to float precision //if (increment < 1E-6f) // increment = 1E-6f; start = Math.Max(start, point1.ActualKey); end = Math.Min(end, point2.ActualKey); // Make sure the curve is up-to-date curve.UpdateChanges(); // FIXME: instead of evaluating for each quaternion component, optimize by querying the parent curve (that should be a rotation curve that knows all components of a quaternion) for (var t = start; t < end; t += increment) { var ft = (float)t; var sample = curve.Evaluate(ft); switch (Component) { case VectorComponent.X: yield return(new Vector2(ft, sample.X)); break; case VectorComponent.Y: yield return(new Vector2(ft, sample.Y)); break; case VectorComponent.Z: yield return(new Vector2(ft, sample.Z)); break; case VectorComponent.W: yield return(new Vector2(ft, sample.W)); break; default: throw new ArgumentOutOfRangeException(); } } } }
/// <summary> /// Samples the curve between the given control points. /// </summary> /// <param name="point1"></param> /// <param name="point2"></param> /// <returns></returns> protected virtual IEnumerable <Vector2> SampleControlPoints([NotNull] KeyFrameControlPointViewModel <TValue> point1, KeyFrameControlPointViewModel <TValue> point2) { // linear interpolation by default yield return(point1.Point); }