2023-11-06 14:49:18 +08:00
|
|
|
|
---
|
|
|
|
|
title: UE5动画重定向核心逻辑笔记
|
|
|
|
|
date: 2023-08-18 18:08:12
|
|
|
|
|
excerpt:
|
|
|
|
|
tags:
|
|
|
|
|
rating: ⭐
|
|
|
|
|
---
|
|
|
|
|
# 前言
|
2023-11-06 17:34:19 +08:00
|
|
|
|
最近研究过了一下UE的重定向逻辑,所以写点笔记作为记录。(IK部分没有去看)
|
|
|
|
|
|
|
|
|
|
- FIKRetargetBatchOperation::RunRetarget():编辑器调用的重定向函数。主要是复制对应需要重定向资产并且进行重定向,之后通知UI。
|
|
|
|
|
- FIKRetargetBatchOperation::RetargetAssets():重定向资产逻辑。
|
|
|
|
|
- 复制所有曲线轨道(不含数值)。
|
|
|
|
|
- 设置Skeleton与PreviewMesh资产。
|
|
|
|
|
- 提前调用重定向资产的PostEditChange(),以避免编辑后钩子函数被调用,产生依赖顺序问题。
|
|
|
|
|
- ConvertAnimation()
|
|
|
|
|
- 替换动画蓝图并且编译。
|
2023-11-06 14:49:18 +08:00
|
|
|
|
# ConvertAnimation()
|
2023-11-06 17:34:19 +08:00
|
|
|
|
一开始是一些初始化逻辑,主要的是调用UIKRetargetProcessor的Initialize()。里面初始化了
|
|
|
|
|
- SourceSkeleton & TargetSkeleton:用于重定向计算用的数据载体,存储了骨骼链、骨骼、当前重定向Pose等数据。
|
|
|
|
|
- RootRetargeter:根骨骼重定向器。
|
|
|
|
|
- ChainPairsIK、ChainPairsFK:用于FK与IK的骨骼链数据。
|
|
|
|
|
- UIKRigProcessor:IK重定向处理器。
|
|
|
|
|
- 所有FIKRigGoal
|
|
|
|
|
|
|
|
|
|
从FRetargetSkeleton& SourceSkeleton & FTargetSkeleton& TargetSkeleton获取对应参数来进行之后的动画资产重定向循环,循环逻辑如下:
|
|
|
|
|
- 获取动画帧数,并且重新构建骨骼动画数据轨道。
|
|
|
|
|
- 取得速度曲线。
|
|
|
|
|
- 之后对每一帧Pose进行重定向,主要是的逻辑是:
|
|
|
|
|
- 取得当前帧Pose,并将其转化WorldSpace。
|
|
|
|
|
- UIKRetargetProcessor Processor->RunRetargeter()
|
|
|
|
|
- 将重定向完的结果转化成LocalSpace,并且将每个骨骼的数据放入对应骨骼动画数据轨道。
|
|
|
|
|
- 调用IAnimationDataController的AddBoneTrack() & SetBoneTrackKeys()给资产设置上关键帧。
|
|
|
|
|
|
|
|
|
|
# RunRetargeter()
|
|
|
|
|
此为核心重定向逻辑,分为RunRootRetarget()、RunFKRetarget()、RunIKRetarget()、RunPoleVectorMatching()。
|
|
|
|
|
|
|
|
|
|
重定向数据会直接修改TargetSkeleton的Pose数据。Root与FK重定向执行完之后会调用UpdateGlobalTransformsBelowBone()更新后续骨骼的WorldSpace Transform。
|
2023-11-06 14:49:18 +08:00
|
|
|
|
|
|
|
|
|
## RunRootRetarget()
|
|
|
|
|
FRootRetargeter::EncodePose():
|
|
|
|
|
取得输入的根骨骼Transform数据并给`FRootSource Source`赋值。
|
|
|
|
|
|
|
|
|
|
FRootRetargeter::DecodePose():
|
|
|
|
|
```c++
|
2023-11-06 22:17:01 +08:00
|
|
|
|
FVector Position;
|
|
|
|
|
{
|
|
|
|
|
// 关键:InitialTransform 为重定向Pose计算出的数值,通过比值计算出Target的Current数值
|
|
|
|
|
const FVector RetargetedPosition = Source.CurrentPositionNormalized * Target.InitialHeight;
|
|
|
|
|
// 根据RetargetSetting中设置的BlendToSourceWeights与BlendToSource,与SourcePosition进行混合。
|
|
|
|
|
Position = FMath::Lerp(RetargetedPosition, Source.CurrentPosition, Settings.BlendToSource*Settings.BlendToSourceWeights);
|
|
|
|
|
|
|
|
|
|
// 应用vertical / horizontal的缩放
|
|
|
|
|
FVector ScaledRetargetedPosition = Position;
|
|
|
|
|
ScaledRetargetedPosition.Z *= Settings.ScaleVertical;
|
|
|
|
|
const FVector HorizontalOffset = (ScaledRetargetedPosition - Target.InitialPosition) * FVector(Settings.ScaleHorizontal, Settings.ScaleHorizontal, 1.0f);
|
|
|
|
|
Position = Target.InitialPosition + HorizontalOffset;
|
|
|
|
|
// 应用RetargetSetting中Position偏移。
|
|
|
|
|
Position += Settings.TranslationOffset;
|
|
|
|
|
|
|
|
|
|
// blend with alpha
|
|
|
|
|
Position = FMath::Lerp(Target.InitialPosition, Position, Settings.TranslationAlpha);
|
|
|
|
|
|
|
|
|
|
// 记录偏差
|
|
|
|
|
Target.RootTranslationDelta = Position - RetargetedPosition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FQuat Rotation;
|
|
|
|
|
{
|
|
|
|
|
// calc offset between initial source/target root rotations
|
|
|
|
|
const FQuat RotationDelta = Source.CurrentRotation * Source.InitialRotation.Inverse();
|
|
|
|
|
// add retarget pose delta to the current source rotation
|
|
|
|
|
const FQuat RetargetedRotation = RotationDelta * Target.InitialRotation;
|
|
|
|
|
|
|
|
|
|
// add static rotation offset
|
|
|
|
|
Rotation = RetargetedRotation * Settings.RotationOffset.Quaternion();
|
|
|
|
|
|
|
|
|
|
// blend with alpha
|
|
|
|
|
Rotation = FQuat::FastLerp(Target.InitialRotation, Rotation, Settings.RotationAlpha);
|
|
|
|
|
Rotation.Normalize();
|
|
|
|
|
|
|
|
|
|
// record the delta created by all the modifications made to the root rotation
|
|
|
|
|
Target.RootRotationDelta = RetargetedRotation * Target.InitialRotation.Inverse();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// apply to target
|
|
|
|
|
FTransform& TargetRootTransform = OutTargetGlobalPose[Target.BoneIndex];
|
|
|
|
|
TargetRootTransform.SetTranslation(Position);
|
|
|
|
|
TargetRootTransform.SetRotation(Rotation);
|
2023-11-06 14:49:18 +08:00
|
|
|
|
```
|
|
|
|
|
## RunFKRetarget()
|
|
|
|
|
FChainEncoderFK::EncodePose():
|
|
|
|
|
从骨骼链拷贝全局输入到CurrentGlobalTransforms
|
|
|
|
|
|
|
|
|
|
FChainDecoderFK::DecodePose():
|
|
|
|
|
|