/// <summary> /// Calculates the transform that moves from A to B /// </summary> /// <param name="b"></param> /// <param name="a"></param> /// <returns></returns> public static Transform Subtract(Transform b, Transform a) { return new Transform { Scale = b.Scale - a.Scale, Translation = b.Translation - a.Translation, Rotation = b.Rotation * Quaternion.Inverse(a.Rotation) }; }
public void Update(TimeSpan elapsedTime, out Transform rootDelta) { rootDelta = Transform.Identity; // Update the animation position. ElapsedTime += TimeSpan.FromSeconds(elapsedTime.TotalSeconds * TimeFactor); if (ElapsedTime >= Animation.Duration) { if (!Loop) return; Animation.Start(); Restart(); } for (int i = 0; i < Animation.ChannelCount; i++) { IChannel channel = Animation.GetChannel(i); //Advance frame number _channelFrames[i] = channel.SeekToTimestamp(ElapsedTime, _channelFrames[i]); //save root bone transform if (Animation.RootBoneIndex == i) { var oldTransform = _transforms[i]; //Calculate new transform for this channel CalculateTransform(channel, out _transforms[i]); //Calculate the delta of the root bone rootDelta = Transform.Subtract(_transforms[i], oldTransform); } else { //Calculate new transform for this channel CalculateTransform(channel, out _transforms[i]); } } }
public void Interpolate(ref Transform b, float amount, out Transform result) { result.Translation = Vector3.Lerp(Translation, b.Translation, amount); Rotation.Nlerp(ref b.Rotation, amount, out result.Rotation); result.Scale = Vector3.Lerp(Scale, b.Scale, amount); }
public Transform Interpolate(Transform b, float amount) { Transform result; Interpolate(ref b, amount, out result); return result; }
private void UpdateActiveAnimations(TimeSpan dt, out Transform fadingInRootDelta, out Transform fadingOutRootDelta) { fadingInRootDelta = Transform.Identity; fadingOutRootDelta = Transform.Identity; if (_fadingOut == null && _fadingIn == null) InterruptClip(NextClip(), false); if (_fadingOut == null && _fadingIn != null) { //DO NOT merge this into the if check above. //The above can change the state of _fadingOut so we do need to check it twice! _fadingOut = _fadingIn; _fadingIn = null; } if (_fadingOut != null) { _fadingOut.Update(dt, out fadingOutRootDelta); //Check if this animation is entering it's final phase. If so, look for another animation in the queue to start playing if (_fadingIn == null && _fadingOut.ElapsedTime >= _fadingOut.Animation.Duration - _fadingOut.FadeOutTime && (_animationQueue.Count > 0 || !_fadingOut.Loop)) InterruptClip(NextClip(), false); } if (_fadingIn != null) { _fadingIn.Update(dt, out fadingInRootDelta); _crossfadeElapsed += dt; _crossfadeProgress = (float)_crossfadeElapsed.TotalSeconds / (float)_crossfadeDuration.TotalSeconds; if (_crossfadeElapsed >= _crossfadeDuration) { _fadingOut = _fadingIn; _fadingIn = null; } } }
private void CalculateRootBoneDelta(ref Transform fadingOutRootDelta, ref Transform fadingInRootDelta) { if (_fadingOut != null && _fadingIn != null) { RootBoneTransfomationDelta = fadingOutRootDelta.Interpolate(fadingInRootDelta, _crossfadeProgress); } else if (_fadingOut != null) { RootBoneTransfomationDelta = fadingOutRootDelta; } else if (_fadingIn != null) { RootBoneTransfomationDelta = fadingInRootDelta; } else { throw new InvalidOperationException("No root bone motion found"); } }
private void BuildRootBoneMatrix(ref Transform transform, out Matrix m) { if (!EnableRootBoneTranslationX || !EnableRootBoneTranslationY || !EnableRootBoneTranslationZ || !EnableRootBoneScale || !EnableRootBoneRotation) { m = (EnableRootBoneScale ? Matrix.CreateScale(transform.Scale) : Matrix.Identity) * (EnableRootBoneRotation ? Matrix.CreateFromQuaternion(transform.Rotation) : Matrix.Identity) * Matrix.CreateTranslation(new Vector3( EnableRootBoneTranslationX ? transform.Translation.X : 0, EnableRootBoneTranslationY ? transform.Translation.Y : 0, EnableRootBoneTranslationZ ? transform.Translation.Z : 0 ) ); } else { transform.ToMatrix(out m); } }
private void CalculateTransform(IChannel channel, out Transform transform) { int frameIndex = _channelFrames[channel.BoneIndex]; //frame which is greater than or equal to the current time Keyframe b = channel.BoneTransform(frameIndex); if (b.Time == ElapsedTime) { transform = b.Transform; return; } //Previous frame Keyframe a = channel.BoneTransform(frameIndex - 1); //Interpolation factor between frames var t = (float) ((ElapsedTime.TotalSeconds - a.Time.TotalSeconds) / (b.Time.TotalSeconds - a.Time.TotalSeconds)); //Convert linear interpolation into some other easing function var t2 = PlaybackParameters.Interpolator(t); //Linearly interpolate frames transform = a.Transform.Interpolate(b.Transform, t2); }
public void Interpolate(ref Transform b, float amount, out Transform result) { Vector3.Lerp(ref Translation, ref b.Translation, amount, out result.Translation); Rotation.Nlerp(ref b.Rotation, amount, out result.Rotation); Vector3.Lerp(ref Scale, ref b.Scale, amount, out result.Scale); }