public ICurveAnimationTarget Clone(bool copyKeyframes) { var clone = new FreeControllerAnimationTarget(controller); if (copyKeyframes) { clone.x.keys.AddRange(x.keys); clone.y.keys.AddRange(y.keys); clone.z.keys.AddRange(z.keys); clone.rotX.keys.AddRange(rotX.keys); clone.rotY.keys.AddRange(rotY.keys); clone.rotZ.keys.AddRange(rotZ.keys); clone.rotW.keys.AddRange(rotW.keys); } else { clone.SetKeyframe(0f, GetKeyframePosition(0), GetKeyframeRotation(0), CurveTypeValues.SmoothLocal); clone.SetKeyframe(GetKeyframeTime(x.length - 1), GetKeyframePosition(x.length - 1), GetKeyframeRotation(x.length - 1), CurveTypeValues.SmoothLocal); clone.ComputeCurves(); } return(clone); }
private IEnumerable ExtractFramesWithFpsTechnique(MotionAnimationClip clip, FreeControllerAnimationTarget target, FreeControllerV3 ctrl) { var minPositionDistanceForFlat = 0.01f; var batchStopwatch = Stopwatch.StartNew(); var containingAtom = plugin.containingAtom; var frameLength = 1f / _reduceMaxFramesPerSecondJSON.val; var lastRecordedFrame = float.MinValue; MotionAnimationStep previousStep = null; for (var stepIndex = 0; stepIndex < (clip.steps.Count - (current.loop ? 1 : 0)); stepIndex++) { try { var step = clip.steps[stepIndex]; var time = step.timeStep.Snap(0.01f); if (time - lastRecordedFrame < frameLength) { continue; } var k = ControllerKeyframe.FromStep(time, step, containingAtom, ctrl); target.SetKeyframe(time, k.position, k.rotation); if (previousStep != null && (target.controller.name == "lFootControl" || target.controller.name == "rFootControl") && Vector3.Distance(previousStep.position, step.position) <= minPositionDistanceForFlat) { KeyframeSettings settings; if (target.settings.TryGetValue(previousStep.timeStep.Snap().ToMilliseconds(), out settings)) { target.ChangeCurve(previousStep.timeStep, CurveTypeValues.Linear); } } lastRecordedFrame = time; previousStep = step; } catch (Exception exc) { SuperController.LogError($"VamTimeline.{nameof(MocapScreen)}.{nameof(ImportRecordedCoroutine)}[Step]: {exc}"); yield break; } if (batchStopwatch.ElapsedMilliseconds > 5) { batchStopwatch.Reset(); yield return(0); batchStopwatch.Start(); } } }
protected IEnumerable ProcessController(MotionAnimationClip motClip, FreeControllerAnimationTarget target, FreeControllerV3 ctrl) { var frameLength = 0.001f; var lastRecordedFrame = float.MinValue; // Vector3? previousPosition = null; // var previousTime = 0f; for (var stepIndex = 0; stepIndex < motClip.steps.Count - (clip.loop ? 1 : 0); stepIndex++) { var step = motClip.steps[stepIndex]; var time = step.timeStep.Snap(0.01f); if (time - lastRecordedFrame < frameLength) { continue; } if (time > clip.animationLength) { break; } if (Mathf.Abs(time - clip.animationLength) < 0.001f) { time = clip.animationLength; } var k = ControllerKeyframe.FromStep(time, step, ctrl); target.SetKeyframe(time, k.position, k.rotation, CurveTypeValues.SmoothLocal); // SuperController.LogMessage($"{k.position.x:0.0000}, {k.position.y:0.0000},{k.position.z:0.0000}"); // if (previousPosition.HasValue && (target.controller.name == "lFootControl" || target.controller.name == "rFootControl") && Vector3.Distance(previousPosition.Value, step.position) <= minPositionDistanceForFlat) // { // target.ChangeCurve(previousTime, CurveTypeValues.Linear); // } lastRecordedFrame = time; // previousPosition = step.position; // previousTime = time; } target.AddEdgeFramesIfMissing(clip.animationLength); yield break; }
private IEnumerable ExtractFramesWithReductionTechnique(MotionAnimationClip clip, FreeControllerAnimationTarget target, FreeControllerV3 ctrl) { var minFrameDistance = 1f / _reduceMaxFramesPerSecondJSON.val; var maxIterations = (int)(clip.clipLength * 10); var containingAtom = plugin.containingAtom; var steps = clip.steps .Where(s => s.positionOn || s.rotationOn) .GroupBy(s => s.timeStep.Snap(minFrameDistance).ToMilliseconds()) .Select(g => { var step = g.OrderBy(s => Math.Abs(g.Key - s.timeStep)).First(); return(ControllerKeyframe.FromStep((g.Key / 1000f).Snap(), step, containingAtom, ctrl)); }) .ToList(); if (steps.Count < 2) { yield break; } target.SetKeyframe(0, steps[0].position, steps[0].rotation); target.SetKeyframe(current.animationLength, steps[steps.Count - 1].position, steps[steps.Count - 1].rotation); var buckets = new List <ReducerBucket> { Scan(steps, target, 1, steps.Count - 2) }; for (var iteration = 0; iteration < maxIterations; iteration++) { // Scan for largest difference with curve var bucketWithLargestPositionDistance = -1; var keyWithLargestPositionDistance = -1; var largestPositionDistance = 0f; var bucketWithLargestRotationAngle = -1; var keyWithLargestRotationAngle = -1; var largestRotationAngle = 0f; for (var bucketIndex = 0; bucketIndex < buckets.Count; bucketIndex++) { var bucket = buckets[bucketIndex]; if (bucket.largestPositionDistance > largestPositionDistance) { largestPositionDistance = bucket.largestPositionDistance; keyWithLargestPositionDistance = bucket.keyWithLargestPositionDistance; bucketWithLargestPositionDistance = bucketIndex; } if (bucket.largestRotationAngle > largestRotationAngle) { largestRotationAngle = bucket.largestRotationAngle; keyWithLargestRotationAngle = bucket.keyWithLargestRotationAngle; bucketWithLargestRotationAngle = bucketIndex; } } // Cannot find large enough diffs, exit if (keyWithLargestRotationAngle == -1 || keyWithLargestPositionDistance == -1) { break; } var posInRange = largestPositionDistance >= _reduceMinPosDistanceJSON.val; var rotInRange = largestRotationAngle >= _reduceMinRotationJSON.val; if (!posInRange && !rotInRange) { break; } // This is an attempt to compare translations and rotations var normalizedPositionDistance = largestPositionDistance / 0.4f; var normalizedRotationAngle = largestRotationAngle / 180f; var selectPosOverRot = (normalizedPositionDistance > normalizedRotationAngle) && posInRange; var keyToApply = selectPosOverRot ? keyWithLargestPositionDistance : keyWithLargestRotationAngle; var step = steps[keyToApply]; var key = target.SetKeyframe(step.time, step.position, step.rotation); target.SmoothNeighbors(key); int bucketToSplitIndex; if (selectPosOverRot) { bucketToSplitIndex = bucketWithLargestPositionDistance; } else { bucketToSplitIndex = bucketWithLargestRotationAngle; } if (bucketToSplitIndex > -1) { // Split buckets and exclude the scanned keyframe, we never have to scan it again. var bucketToSplit = buckets[bucketToSplitIndex]; buckets.RemoveAt(bucketToSplitIndex); if (bucketToSplit.to - keyToApply + 1 > 2) { buckets.Insert(bucketToSplitIndex, Scan(steps, target, keyToApply + 1, bucketToSplit.to)); } if (keyToApply - 1 - bucketToSplit.from > 2) { buckets.Insert(bucketToSplitIndex, Scan(steps, target, bucketToSplit.from, keyToApply - 1)); } } yield return(0); } }