UE4源码阅读_骨骼模型与动画系统_动画压缩

0. 写在前面

本文为个人学习的笔记整理,如有错误,望不吝指出。

1. UE4动画压缩方案

在这里插入图片描述
默认使用移除线性关键帧压缩

1.1 无损压缩 Least Destructive

在这里插入图片描述

  1. 设置平移数据(Translation)的压缩格式:ACF_None,不压缩
  2. 设置旋转数据(Rotation)的压缩格式:ACF_Float96NoW,3个32位Float来存旋转数据。骨骼旋转数据是用四元数存的,这里去掉w分量。
  3. 进行位压缩

1.2 位压缩 Bitwise Compress Only

  1. Key和Track:
    Key :关键帧数据,描述某一特定时间下单根骨骼的位置和旋转的数据。
    Track :描述单根骨骼随着时间进行运动的一组关键帧。

  2. 对每根骨骼,将原始动画数据提取到平移、旋转、缩放三个Track中
    SeparateRawDataIntoTracks( CompressibleAnimData.RawAnimationData, CompressibleAnimData.SequenceLength, TranslationData, RotationData, ScaleData );

  3. 去除冗余的Track数据:当一根骨骼的Track数据没有发生变化时(即该骨骼在这个动画下不参与平移或旋转或缩放,除了第一帧其他全部去掉。
    FilterTrivialKeys,分别调用FilterTrivialRotationKeys、FilterTrivialPositionKeys、FilterTrivialScaleKeys检查旋转、平移、缩放数据是否有发生过变化,如果有发生过变化,则整个Track保留,如果没有,则只保留第一帧数据。

  4. 根据面板设置,指定平移、旋转、缩放的编码格式:AnimationFormat_SetInterfaceLinks
    ACF_None
    ACF_Float96NoW
    ACF_Fixed48NoW
    ACF_IntervalFixed32NoW
    ACF_Fixed32NoW
    ACF_Float32NoW
    ACF_Identity

  5. 进行按位压缩:BitwiseCompressAnimationTracks
    Simple quantization简单量化算法
    即对浮点数在某个范围内对其进行归一化,并将其缩放到N位整数的范围,再四舍五入转为N位的整数

    • ACF_None:不压缩,如果是平移数据,用332位float。如果是旋转数据,用432位float(包含w分量)
    • ACF_Float96NoW:对应CompressTranslation_Uncompressed算法,用3*32位float,不包含w分量
    • ACF_Fixed48NoW:对应CompressTranslation_16_16_16算法,将332位float数据压缩到3uint16。
      在这里插入图片描述
    • ACF_IntervalFixed32NoW:对应CompressTranslation_10_11_11算法,将332位float数据压缩到1uint32.
      将XYZ数据进行映射,先计算Track中数据的最小值MinX、MinY和MinZ,以及Track中数据的范围Range(Max-Min)
      通过value = (V - Vmin)/ Range进行映射
      再共同存到一个32位int数据,其中21-31位存Z, 10-20位存Y, 0-9位存X

1.3 移除琐碎帧压缩 Remove Trivial Keys

琐碎帧:对没有变化的冗余Track数据,只保留第一帧,实际上并不会删除关键帧信息,只是对相同的数据仅保留一份。基本上其他压缩方案都会先处理琐碎帧。

  1. SeparateRawDataIntoTracks:将原始数据分离到3个Track
  2. FilterTrivialKeys:去除琐碎帧
  3. AnimationFormat_SetInterfaceLinks:设置压缩编码格式,这里都用的不压缩
  4. BitwiseCompressAnimationTracks:进行按位压缩

1.4 隔帧移除压缩 Remove Every Second Key

在移除琐碎帧的基础上多了一个隔帧移除,可以指定间隔多少帧移除,也可以指定多少帧后才开始执行移除
FilterIntermittentKeys,分别调用
FilterIntermittentRotationKeys(RotationTracks, StartIndex, Interval);
FilterIntermittentPositionKeys(PositionTracks, StartIndex, Interval);
在这里插入图片描述
对position的每个track,遍历关键帧,按一定间隔步进,加入到新的Track。Rotation同理
最后调用按用户设置的编码格式进行按位压缩

1.5 移除线性帧压缩 Remove Linear Keys

删除可以通过临帧的线性插值得到的关键帧
原理:

  1. 选择一个关键帧
  2. 计算从它的两个邻居线性插值得到的值
  3. 如果产生的轨迹误差是可以接受的就移除这个键

在上述第一步中选择关键帧的算法可以是多样的,且会产生不同的压缩结果(UE4是怎样的?)
第三步在UE4中是MaxPosDiff、MaxAngleDiff和MaxScaleDiff,UE4还提供了3个参数,MaxEffectorDiff、MinEffectorDiff和EffectorDiffSocket,因为UE4除了检查插值出来的某根骨骼的某个关键帧和原始数据的差距之外,还检查假如应用了这个数据之后,对末端骨骼的影响,即末端骨骼的误差。

相关参数:
在这里插入图片描述
详细流程:

  1. SeparateRawDataIntoTracks:
    分离Track数据

  2. FilterBeforeMainKeyRemoval:
    调用FilterTrivialKeys删除琐碎帧

  3. CompressUsingUnderlyingCompressor
    调用BitwiseCompressAnimationTracks在过滤线性帧前先进行一次位压缩

  4. ProcessAnimationTracks:去除可以用线性插值近似的关键帧
    主要逻辑在FilterLinearKeysTemplate
    过滤规则:
    ① 定义LowKey,从第二帧(下标为1)开始遍历
    ② 定义GoodHighKey、BadHighKey两个移动下标,在LowKey到帧末划出一个窗口
    ③ 定义HighKey为Good和Bad的中间下标,从LowKey的下一个帧开始继续向HighKey在位置遍历(二分法)
    ④ 第三步中遍历到的KeyValue,通过Alpha变量和临帧值(LowKey、HighKeyValue)计算一个插值数据,比较插值数据和原始数据,如果小于配置的允许误差值,则继续检查该骨骼影响的末端骨骼数据误差。
    计算末端骨骼的数据误差,转换到世界坐标(全局姿势)做比较(之前是比较局部姿势),记录误差最大的值,检查是否大于配置的末端最大误差。
    Alpha的计算:
    在这里插入图片描述
    假如要计算Key(3)位置的线性插值数据,则可以Key(3)的邻居计算Alpha=(3-2)/(4-2)=0.5,插值后的Value=lerp(0.35, 0.85, alpha) = 0.6
    在这里插入图片描述
    ⑤ 如果第四步遍历完没有遇到误差过大的情况,则将GoodHighKey的值更新为HighKey,说明从LowKey到HighKey之前的数据都是可以通过线性插值得到的。如果第四步中有遇到误差过大的情况,则将BadHighKey的值更新为HighKey,然后回到第三步,重新计算HighKey。
    ⑥ 在第三步到第五步逐渐的缩小GoodHighKey和BadHighKey的窗口,直到窗口足够小时停止,然后将GoodHighKey所对应的数据加入到一个新的Track(记录TimeValue和KeyValue),这个Track保存的就是去掉可以通过线性插值得到的帧之后的数据

    ProcessAnimationTracks函数会对每个骨骼的三个Track(平移、旋转、缩放)都执行FilterLinearKeysTemplate进行过滤

  5. 在去除线性近似帧之后,对最终剩下的数据再次进行位压缩:CompressUsingUnderlyingCompressor

1.6 独立轨道压缩 Compress each track independently

按照不同的Track单独进行压缩,继承于移除线性帧压缩的类,直接调用UAnimCompress_RemoveLinearKeys::DoReduction,对RemoveLinearKeys的一些关键函数进行重写,即在线性压缩的基础上做额外处理

相关参数:
LinearKeyRemoval和线性压缩的作用一致
在这里插入图片描述
1. FilterBeforeMainKeyRemoval
a. ResampleKeys:对原动画数据进行重新采样
如果勾选了Resampling,并且动画关键帧采样数据大于MinKeysForResampling,就会根据设置的采样帧间隔对原数据进行重新采样。
b. CalculateTrackHeights和TallyErrorsFromPerturbation:
勾选AdaptiveError或AdaptiveError2时的处理,暂略。
以上三种配置默认都是不处理的
c. FilterTrivialKeys:删除琐碎帧
2. CompressUsingUnderlyingCompressor

2. 参考资料

http://nfrechette.github.io/2016/10/21/anim_compression_toc/

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值