Files
2026-03-04 10:03:45 +08:00

184 lines
4.6 KiB
C#

using System;
using UnityEngine;
namespace RootMotion
{
[Serializable]
public class BakerHumanoidQT
{
private Transform transform;
private string Qx;
private string Qy;
private string Qz;
private string Qw;
private string Tx;
private string Ty;
private string Tz;
public AnimationCurve rotX;
public AnimationCurve rotY;
public AnimationCurve rotZ;
public AnimationCurve rotW;
public AnimationCurve posX;
public AnimationCurve posY;
public AnimationCurve posZ;
private AvatarIKGoal goal;
private Quaternion lastQ;
private bool lastQSet;
public BakerHumanoidQT(string name)
{
Qx = name + "Q.x";
Qy = name + "Q.y";
Qz = name + "Q.z";
Qw = name + "Q.w";
Tx = name + "T.x";
Ty = name + "T.y";
Tz = name + "T.z";
Reset();
}
public BakerHumanoidQT(Transform transform, AvatarIKGoal goal, string name)
{
this.transform = transform;
this.goal = goal;
Qx = name + "Q.x";
Qy = name + "Q.y";
Qz = name + "Q.z";
Qw = name + "Q.w";
Tx = name + "T.x";
Ty = name + "T.y";
Tz = name + "T.z";
Reset();
}
public void Reset()
{
rotX = new AnimationCurve();
rotY = new AnimationCurve();
rotZ = new AnimationCurve();
rotW = new AnimationCurve();
posX = new AnimationCurve();
posY = new AnimationCurve();
posZ = new AnimationCurve();
lastQ = Quaternion.identity;
lastQSet = false;
}
public void SetIKKeyframes(float time, Avatar avatar, float humanScale, Vector3 bodyPosition, Quaternion bodyRotation)
{
TQ iKGoalTQ = AvatarUtility.GetIKGoalTQ(avatar, humanScale, goal, new TQ(bodyPosition, bodyRotation), new TQ(transform.position, transform.rotation));
Quaternion quaternion = iKGoalTQ.q;
if (lastQSet)
{
quaternion = BakerUtilities.EnsureQuaternionContinuity(lastQ, iKGoalTQ.q);
}
lastQ = quaternion;
lastQSet = true;
rotX.AddKey(time, quaternion.x);
rotY.AddKey(time, quaternion.y);
rotZ.AddKey(time, quaternion.z);
rotW.AddKey(time, quaternion.w);
Vector3 t = iKGoalTQ.t;
posX.AddKey(time, t.x);
posY.AddKey(time, t.y);
posZ.AddKey(time, t.z);
}
public void SetKeyframes(float time, Vector3 pos, Quaternion rot)
{
rotX.AddKey(time, rot.x);
rotY.AddKey(time, rot.y);
rotZ.AddKey(time, rot.z);
rotW.AddKey(time, rot.w);
posX.AddKey(time, pos.x);
posY.AddKey(time, pos.y);
posZ.AddKey(time, pos.z);
}
public void MoveLastKeyframes(float time)
{
MoveLastKeyframe(time, rotX);
MoveLastKeyframe(time, rotY);
MoveLastKeyframe(time, rotZ);
MoveLastKeyframe(time, rotW);
MoveLastKeyframe(time, posX);
MoveLastKeyframe(time, posY);
MoveLastKeyframe(time, posZ);
}
public void SetLoopFrame(float time)
{
BakerUtilities.SetLoopFrame(time, rotX);
BakerUtilities.SetLoopFrame(time, rotY);
BakerUtilities.SetLoopFrame(time, rotZ);
BakerUtilities.SetLoopFrame(time, rotW);
BakerUtilities.SetLoopFrame(time, posX);
BakerUtilities.SetLoopFrame(time, posY);
BakerUtilities.SetLoopFrame(time, posZ);
}
private void MoveLastKeyframe(float time, AnimationCurve curve)
{
Keyframe[] keys = curve.keys;
keys[^1].time = time;
curve.keys = keys;
}
public void MultiplyLength(AnimationCurve curve, float mlp)
{
Keyframe[] keys = curve.keys;
for (int i = 0; i < keys.Length; i++)
{
keys[i].time *= mlp;
}
curve.keys = keys;
}
public void SetCurves(ref AnimationClip clip, float maxError, float lengthMlp)
{
MultiplyLength(rotX, lengthMlp);
MultiplyLength(rotY, lengthMlp);
MultiplyLength(rotZ, lengthMlp);
MultiplyLength(rotW, lengthMlp);
MultiplyLength(posX, lengthMlp);
MultiplyLength(posY, lengthMlp);
MultiplyLength(posZ, lengthMlp);
BakerUtilities.ReduceKeyframes(rotX, maxError);
BakerUtilities.ReduceKeyframes(rotY, maxError);
BakerUtilities.ReduceKeyframes(rotZ, maxError);
BakerUtilities.ReduceKeyframes(rotW, maxError);
BakerUtilities.ReduceKeyframes(posX, maxError);
BakerUtilities.ReduceKeyframes(posY, maxError);
BakerUtilities.ReduceKeyframes(posZ, maxError);
BakerUtilities.SetTangentMode(rotX);
BakerUtilities.SetTangentMode(rotY);
BakerUtilities.SetTangentMode(rotZ);
BakerUtilities.SetTangentMode(rotW);
clip.SetCurve(string.Empty, typeof(Animator), Qx, rotX);
clip.SetCurve(string.Empty, typeof(Animator), Qy, rotY);
clip.SetCurve(string.Empty, typeof(Animator), Qz, rotZ);
clip.SetCurve(string.Empty, typeof(Animator), Qw, rotW);
clip.SetCurve(string.Empty, typeof(Animator), Tx, posX);
clip.SetCurve(string.Empty, typeof(Animator), Ty, posY);
clip.SetCurve(string.Empty, typeof(Animator), Tz, posZ);
}
}
}