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);
                }
            }
Пример #7
0
            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);
            }
Пример #8
0
            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();
            }