public static int Bake(ref Keyframe[] keys, float frameRate, InterpolationMode mode = InterpolationMode.Auto) { var nativeKeys = new NativeArray <Keyframe>(keys, Allocator.Temp); float duration = keys[keys.Length - 1].time - keys[0].time; int frameCount = (int)math.ceil(frameRate * duration); var bakedKeys = new NativeArray <Keyframe>(frameCount, Allocator.Temp); ThreadSafe.Bake(nativeKeys, frameRate, bakedKeys, new SampleRange() { startFrameIndex = 0, numFrames = frameCount }); switch (mode) { case InterpolationMode.Linear: KeyframeUtilities.AlignTangentsLinear(bakedKeys); break; case InterpolationMode.Auto: KeyframeUtilities.AlignTangentsSmooth(bakedKeys); break; case InterpolationMode.ClampedAuto: KeyframeUtilities.AlignTangentsClamped(bakedKeys); break; default: throw new System.InvalidOperationException("Not Implemented"); } keys = bakedKeys.ToArray(); bakedKeys.Dispose(); return(frameCount); }
static public float ReduceWithMaximumAbsoluteError(ref Keyframe[] keyframes, float maxError) { int numKeys = keyframes.Length; var newKeyFrames = new List <Keyframe>(numKeys); int prevKeyIndex = 0; int currentKeyIndex = 1; int nextKeyIndex = 2; float conversionError = 0.0f; newKeyFrames.Add(keyframes[0]); while (nextKeyIndex < (numKeys)) { Keyframe prev = keyframes[prevKeyIndex]; Keyframe next = keyframes[nextKeyIndex]; for (int i = currentKeyIndex; i > prevKeyIndex; i--) { Keyframe test = keyframes[i]; float value = KeyframeUtilities.Evaluate(test.time, prev, next); float error = math.abs(value - test.value); if (error >= maxError) { newKeyFrames.Add(keyframes[currentKeyIndex]); prevKeyIndex = currentKeyIndex; } } currentKeyIndex++; nextKeyIndex++; } newKeyFrames.Add(keyframes[numKeys - 1]); keyframes = newKeyFrames.ToArray(); return(conversionError); }
public static int Bake(AnimationCurve curve, float frameRate, InterpolationMode mode) { var keys = new NativeArray <Keyframe>(curve.keys, Allocator.Temp); float duration = keys[keys.Length - 1].time - keys[0].time; int frameCount = (int)math.ceil(frameRate * duration); var bakedKeys = new NativeArray <Keyframe>(frameCount, Allocator.Temp); switch (mode) { case InterpolationMode.Linear: KeyframeUtilities.AlignTangentsLinear(bakedKeys); break; case InterpolationMode.Auto: KeyframeUtilities.AlignTangentsSmooth(bakedKeys); break; case InterpolationMode.ClampedAuto: KeyframeUtilities.AlignTangentsClamped(bakedKeys); break; default: throw new System.InvalidOperationException("Not Implemented"); } curve.keys = bakedKeys.ToArray(); keys.Dispose(); bakedKeys.Dispose(); return(frameCount); }
public void Bake_Keyframes_IsAccurateInBetweenKeys() { var frames = new Keyframe[] { new Keyframe(0, 0), new Keyframe(1, 1), new Keyframe(2, 2), new Keyframe(3, 3), new Keyframe(4, 4), new Keyframe(5, 5) }; var newFrames = new Keyframe[6]; frames.CopyTo(newFrames, 0); AnimationCurveBake.Bake(ref newFrames, 30); int index1 = 0; int index2 = 0; float deltaTime = 5 / 900; for (int i = 0; i < 900; i++) { float actual = KeyframeUtilities.Evaluate(i * deltaTime, ref index1, newFrames); float expected = KeyframeUtilities.Evaluate(i * deltaTime, ref index2, frames); Assert.AreEqual(expected, actual); } }
public void Bake_Keyframes_IsAccurateOnBakedKeys() { var frames = new Keyframe[] { new Keyframe(0, 0), new Keyframe(1, 1), new Keyframe(2, 2), new Keyframe(3, 3), new Keyframe(4, 4), new Keyframe(5, 5) }; var newFrames = new Keyframe[6]; frames.CopyTo(newFrames, 0); AnimationCurveBake.Bake(ref newFrames, 30); int seekIndex = 0; for (int i = 0; i < newFrames.Length; i++) { float actual = KeyframeUtilities.Evaluate(newFrames[i].time, ref i, newFrames); float expected = KeyframeUtilities.Evaluate(newFrames[i].time, ref seekIndex, frames); Assert.AreEqual(expected, actual, 0.000001f); } }
public void Bake_LinearCurve_IsAccurate(AnimationCurveBake.InterpolationMode mode) { float frameRate = 7; float sampleRate = 30; var sourceCurve = AnimationCurve.Linear(0, 0, 5, 5); var curveKeys = sourceCurve.keys; var destCurve = new AnimationCurve(curveKeys); float start = KeyframeUtilities.StartTime(curveKeys); float end = KeyframeUtilities.EndTime(curveKeys); float duration = end - start; AnimationCurveBake.Bake(destCurve, frameRate, mode); float delta = (end - start) / sampleRate; int numSamples = (int)math.ceil(duration * frameRate) + 1; for (int i = 0; i <= numSamples; i++) { float time = math.clamp(start + i * delta, start, end); float expected = sourceCurve.Evaluate(time); float actual = destCurve.Evaluate(time); } }
public void Seek_Forward(float time, int index, int expected, string message) { var frames = new Keyframe[] { new Keyframe(0, 0), new Keyframe(1, 1), new Keyframe(2, 2), new Keyframe(3, 3), new Keyframe(4, 4), new Keyframe(5, 5), }; Assert.AreEqual(expected, KeyframeUtilities.Seek(time, index, frames), message); }
public void AlignTangents_Smooth_ProducesSame_LinearCurve(float start, float startValue, float end, float endValue) { var curve = AnimationCurve.Linear(start, startValue, end, endValue); var keys = new NativeArray <Keyframe>(30, Allocator.Temp); for (int i = 0; i < 30; i++) { float time = 1 / 30 * i; keys[i] = new Keyframe(time, curve.Evaluate(time)); } KeyframeUtilities.AlignTangentsSmooth(keys); var alignedCurve = new AnimationCurve(keys.ToArray()); for (int i = 0; i < 60; i++) { float time = 1 / 60 * i; Assert.AreEqual(curve.Evaluate(time), alignedCurve.Evaluate(time)); } keys.Dispose(); }