4 using System.Collections.Generic;
5 using SiliconStudio.Core.Collections;
6 using SiliconStudio.Core.Extensions;
8 namespace SiliconStudio.
Paradox.DataModel
17 KeyFrames =
new List<KeyFrameData<float>>();
23 for (keyIndex = 0; keyIndex < KeyFrames.Count - 1; ++keyIndex)
25 if (time < KeyFrames[keyIndex + 1].Time)
32 if (time == KeyFrames[keyIndex].Time)
33 return KeyFrames[keyIndex].Value;
36 long timeStart = KeyFrames[keyIndex + 0].Time.Ticks;
37 long timeEnd = KeyFrames[keyIndex + 1].Time.Ticks;
39 float t = ((float)time.
Ticks - (
float)timeStart) / ((
float)timeEnd - (float)timeStart);
42 evaluator.ValuePrev = KeyFrames[keyIndex > 0 ? keyIndex - 1 : 0];
43 evaluator.ValueStart = KeyFrames[keyIndex + 0];
44 evaluator.ValueEnd = KeyFrames[keyIndex + 1];
45 evaluator.ValueNext = KeyFrames[keyIndex + 2 < KeyFrames.Count ? keyIndex + 2 : KeyFrames.Count - 1];
47 return evaluator.Evaluate(t);
59 private KeyValuePair<CompressedTimeSpan, float> EvaluateError(Func<CompressedTimeSpan, float> originalCurve, Evaluator evaluator,
CompressedTimeSpan stepSize, KeyFrameData<float> keyFrame, KeyFrameData<float> nextKeyFrame)
61 var startTime = keyFrame.Time;
62 var endTime = nextKeyFrame.Time;
64 var biggestDifference = 0.0f;
65 var biggestDifferenceTime = startTime;
70 for (var time = startTime; time < endTime; time += stepSize)
72 var difference = Math.Abs(originalCurve(time) - evaluator.Evaluate(time));
74 if (difference > biggestDifference)
76 biggestDifference = difference;
77 biggestDifferenceTime = time;
80 return new KeyValuePair<CompressedTimeSpan, float>(biggestDifferenceTime, biggestDifference);
83 class ErrorComparer :
IComparer<LinkedListNode<ErrorNode>>
85 public int Compare(LinkedListNode<ErrorNode> x, LinkedListNode<ErrorNode>
y)
87 if (x.Value.Error != y.Value.Error)
88 return Math.Sign(x.Value.Error - y.Value.Error);
90 return x.Value.GetHashCode() - y.Value.GetHashCode();
96 public LinkedListNode<KeyFrameData<float>>
KeyFrame;
103 BiggestDeltaTime = biggestDeltaTime;
115 if (KeyFrames.Count <= 1)
118 var keyFrames =
new LinkedList<KeyFrameData<float>>(this.KeyFrames);
119 var evaluator =
new Evaluator(keyFrames);
122 var errors =
new LinkedList<ErrorNode>();
124 var errorQueue =
new PriorityQueue<LinkedListNode<ErrorNode>>(
new ErrorComparer());
125 foreach (var keyFrame
in keyFrames.EnumerateNodes())
127 if (keyFrame.Next == null)
129 var error = EvaluateError(originalCurve, evaluator, stepSize, keyFrame.Value, keyFrame.Next.Value);
130 var errorNode = errors.AddLast(
new ErrorNode(keyFrame, error.Key, error.Value));
131 errorQueue.Enqueue(errorNode);
143 var highestError = errorQueue.Dequeue();
144 if (highestError.Value.Error <= maxErrorThreshold)
161 var middleTime = highestError.Value.BiggestDeltaTime;
163 var newKeyFrame = keyFrames.AddAfter(highestError.Value.KeyFrame,
new KeyFrameData<float> { Time = middleTime, Value = originalCurve(middleTime) });
167 var highestErrorLastUpdate = newError;
168 if (highestErrorLastUpdate.Next != null)
169 highestErrorLastUpdate = highestErrorLastUpdate.Next;
172 evaluator.InvalidateTime();
175 for (var error = highestError.Previous ?? highestError; error != null; error = error.Next)
177 if (error != highestError && error != newError)
178 errorQueue.Remove(error);
180 var errorInfo = EvaluateError(originalCurve, evaluator, stepSize, error.Value.KeyFrame.Value, error.Value.KeyFrame.Next.Value);
181 error.Value.BiggestDeltaTime = errorInfo.Key;
182 error.Value.Error = errorInfo.Value;
184 errorQueue.Enqueue(error);
186 if (error == highestErrorLastUpdate)
191 KeyFrames =
new List<KeyFrameData<float>>(keyFrames);
194 public List<KeyFrameData<float>> KeyFrames {
get; set; }
202 public string TargetObject {
get; set; }
210 public string TargetProperty {
get; set; }
212 internal static void InitializeAnimation(ref EvaluatorData animationChannel, ref AnimationInitialValues<float> animationValue)
214 animationChannel.ValuePrev = animationValue.Value1;
215 animationChannel.ValueStart = animationValue.Value1;
216 animationChannel.ValueEnd = animationValue.Value1;
217 animationChannel.ValueNext = animationValue.Value2;
221 internal static void UpdateAnimation(ref EvaluatorData animationChannel, ref KeyFrameData<float> animationValue)
223 animationChannel.ValuePrev = animationChannel.ValueStart;
224 animationChannel.ValueStart = animationChannel.ValueEnd;
225 animationChannel.ValueEnd = animationChannel.ValueNext;
226 animationChannel.ValueNext = animationValue;
233 private bool reachedEnd;
235 private IEnumerator<KeyFrameData<float>> currentKeyFrame;
241 this.keyFrames = keyFrames;
251 var startTime = data.ValueStart.Time;
252 var endTime = data.ValueEnd.Time;
254 if (currentTime < startTime || currentTime > endTime)
260 if (currentTime <= startTime)
261 return data.ValueStart.Value;
264 if (currentTime >= endTime)
265 return data.ValueEnd.Value;
268 float factor = (float)(currentTime - startTime).Ticks / (float)(endTime - startTime).Ticks;
269 return data.Evaluate(factor);
276 currentKeyFrame = keyFrames.GetEnumerator();
278 var animationInitialValues =
new AnimationInitialValues<float>();
281 currentKeyFrame.MoveNext();
282 animationInitialValues.Value1 = currentKeyFrame.Current;
283 currentKeyFrame.MoveNext();
284 animationInitialValues.Value2 = currentKeyFrame.Current;
286 currentTime = animationInitialValues.Value1.Time;
288 InitializeAnimation(ref data, ref animationInitialValues);
295 if (timeSpan < currentTime)
300 currentTime = timeSpan;
303 while (!(currentTime >= data.ValueStart.Time && currentTime < data.ValueEnd.Time) && !reachedEnd)
305 var moveNextFrame = currentKeyFrame.MoveNext();
309 UpdateAnimation(ref data, ref data.ValueNext);
310 UpdateAnimation(ref data, ref data.ValueNext);
313 var keyFrame = moveNextFrame ? currentKeyFrame.Current : data.ValueNext;
314 UpdateAnimation(ref data, ref keyFrame);
317 currentTime = timeSpan;
329 float factor0 = -t3 + 2.0f * t2 - t;
330 float factor1 = 3.0f * t3 - 5.0f * t2 + 2.0f;
331 float factor2 = -3.0f * t3 + 4.0f * t2 + t;
332 float factor3 = t3 - t2;
334 return 0.5f * (ValuePrev.Value * factor0
335 + ValueStart.Value * factor1
336 + ValueEnd.Value * factor2
337 + ValueNext.Value * factor3);
Evaluator(IEnumerable< KeyFrameData< float >> keyFrames)
CompressedTimeSpan BiggestDeltaTime
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
KeyFrameData< float > ValueStart
KeyFrameData< float > ValueNext
List of float key frame data applying to a specific property in a node.
KeyFrameData< float > ValuePrev
ErrorNode(LinkedListNode< KeyFrameData< float >> keyFrame, CompressedTimeSpan biggestDeltaTime, float error)
LinkedListNode< KeyFrameData< float > > KeyFrame
float EvaluateCubic(CompressedTimeSpan time)
static readonly CompressedTimeSpan Zero
float Evaluate(CompressedTimeSpan time)
void Fitting(Func< CompressedTimeSpan, float > originalCurve, CompressedTimeSpan stepSize, float maxErrorThreshold)
KeyFrameData< float > ValueEnd