예제 #1
0
        private void ReduceKeyframes(AnimationCurve source)
        {
            var sw = Stopwatch.StartNew();
            var minFrameDistance = 1f / _reduceMaxFramesPerSecondJSON.val;
            var maxIterations    = (int)(source[source.length - 1].time * 10);

            var batchStopwatch = Stopwatch.StartNew();
            var containingAtom = plugin.containingAtom;
            var steps          = source.keys
                                 .GroupBy(s => s.time.Snap(minFrameDistance).ToMilliseconds())
                                 .Select(g =>
            {
                var keyframe = g.OrderBy(s => Math.Abs(g.Key - s.time)).First();
                return(new Keyframe((g.Key / 1000f).Snap(), keyframe.value, 0, 0));
            })
                                 .ToList();

            var target = new AnimationCurve();

            target.FlatFrame(target.AddKey(0, source[0].value));
            target.FlatFrame(target.AddKey(source[source.length - 1].time, source[source.length - 1].value));

            for (var iteration = 0; iteration < maxIterations; iteration++)
            {
                // Scan for largest difference with curve
                // TODO: Use the buckets strategy
                var keyWithLargestDiff = -1;
                var largestDiff        = 0f;
                for (var i = 1; i < steps.Count - 1; i++)
                {
                    var diff = Mathf.Abs(target.Evaluate(steps[i].time) - steps[i].value);

                    if (diff > largestDiff)
                    {
                        largestDiff        = diff;
                        keyWithLargestDiff = i;
                    }
                }

                // Cannot find large enough diffs, exit
                if (keyWithLargestDiff == -1)
                {
                    break;
                }
                var inRange = largestDiff >= _reduceMinPosDistanceJSON.val;
                if (!inRange)
                {
                    break;
                }

                // This is an attempt to compare translations and rotations
                var keyToApply = keyWithLargestDiff;

                var step = steps[keyToApply];
                steps.RemoveAt(keyToApply);
                var key = target.SetKeyframe(step.time, step.value);
                target.FlatFrame(key);
            }

            source.keys = target.keys;
        }