Unity的动作文件关键帧存储格式的问题

问题描述

在试图自己写骨骼的动画播放逻辑的时候,遇到了题述的问题。
我用的是Unity的动画资源,所以必须要对动画文件进行解析。设置之类的不谈,关键帧这里出了问题。那就是,Unity的关键帧是这样的:

// 一个Orientation关键帧的数据
        time: 0
        value: {x: -0.3650968, y: 0.61221385, z: 0.6177848, w: 0.3320251}
        inSlope: {x: -0.042881366, y: -0.003851652, z: -0.010226368, w: -0.021155475}
        outSlope: {x: -0.042881366, y: -0.003851652, z: -0.010226368, w: -0.021155475}
        tangentMode: 0

time表示关键帧的时间,value表示关键帧的orientation。 但是这个inSlope和outSlope令人懵逼。
在Unity中,动画是用EulerAngles的曲线的形式来制作的,EulerAngles有自己的inSlope和outSlope,这个是比较好理解的,三个欧拉角分别按照自己的曲线来Sample即可。但是存储为动画文件的时候,RotationCurve是用Quaternion来表示的。所以问题就是:
欧拉角的inSlope和outSlope,是怎么转变为Quaternion的inSlope和outSlope的?

几个想法

  1. 想过是不是因为Unity还有个EditorCurve和EditorEulerCurve,因此这个RotationCurve不会起作用?
    但是其实删掉了EditorCurve和EditorEulerCurve之后,动作还是像往常一样播放。只是在Unity编辑器中,曲线变得奇怪了——但是在播放的时候,实际的Rotation并不会照着这个奇怪的曲线走。
  2. 想过是不是逐个分量分别有自己的曲线,然后按照自己的曲线进行插值后,再合并为完整Quaternion?
    但是其实试验之后发现,这样得到的结果,和曲线本身代表的含义有一定差距,和用Unity自己的AnimationCurve.Evaluate的的差距也很大。
    比如下图这样的一个曲线,应该是绕着x轴均匀变化的效果:
    Unity的动作文件关键帧存储格式的问题_第1张图片
    实际打印出的结果:
    Unity的动作文件关键帧存储格式的问题_第2张图片
    C列是用Unity的AnimationCurve.Evaluate函数对四个分量采样,然后计算结果所代表的角度,与均匀变化情况下的差距。可以看出这个差距非常小;
    A列是用Hermit插值对四个分量分别采样,然后计算结果所代表的角度,与实际均匀变化的角度之间的差距。这个差距相比于C列而言,大了很多;
    B列是不考虑inSlope和outSlope后,直接线性插值四个分量,得到的角度差距。这个差距在大多数时候甚至好于A列!看来这种分别插值然后合并什么的,肯定不是Unity动作文件所用的方案了。
  3. 问了群里的朋友们,大家教了我很多曲线方面的东西。三问聚聚提到了一个叫做KB Cubic Spine的曲线。看了一下它描述的情形,稍有差别,但是赶脚非常有用。会不会Unity是先把情形转换到KBS描述的情况,然后进行插值,存下来lookup table呢?毕竟按照这个网页描述的结果来看,Unity的AnimationCurve.Evaluate函数就是查找表做的。
    但是,Unity是如何根据这些Vector4的inoutSlope,来生成这个lookup table的呢。。。
    呆总说可以去看看UE4的。。然而没有找到呢 (._.) 。。问了我司的用UE4的童鞋也不知道源码是哪部分。。

更新 (2018.3.8)

今天忽然想起了一个可能的原因。是在考虑“欧拉角曲线转四元数曲线”时想到的。欧拉角曲线的斜率代表它的导数,那么,考虑欧拉角转换到四元数之后,将欧拉角的导数代入公式,岂不是就可以算出四元数各个分量在该点的斜率了?
四元数和欧拉角的转换公式参照这个网页,
刚刚拿纸笔算了下几个数字,果然是这么来的!简直高兴得想哭!回想起群里的诸位聚聚貌似。。是不是。。大概也许好像昨天就这么跟我说了?orz……也许想的不够深入,思想即便到了眼前也抓不住呢……

啊。我耳机里正好在放《Star Fly》,此刻~感觉自己整个人都带上了BGM了呢!~

你可能感兴趣的:(unity)