Home > 程序/算法 > 骨骼动画的数据压缩(一)

骨骼动画的数据压缩(一)

这里说的骨骼动画数据,是指美术用Max,Maya或者XSI之类的3d工具制作的角色动画,通常要导出成引擎可以读取的特殊格式,为游戏所用。对于目前越来越强调动作感的网络游戏来说,动画资源占整个安装包尺寸的比例在不断上升,动画数据的压缩也在变得原来越重要,更不用说采用大量实时渲染过场动画的次世代Console游戏了。

每个引擎都有自己独特的动画文件格式,但里面的内容都大同小异。所谓动画,就是一系列关键帧的集合,每个关键帧可以描述了角色整个骨架的完整姿态信息,也就是每一块骨骼在3d空间中的位置和方向。

假设我们有一个包含50块骨骼的骨架,采用30fps的帧率,一个长度为两秒的动画需要占用多大的空间呢?我们来计算一下。我们知道空间的方位可以用一个矩阵来描述,一个矩阵包含4 x 4 = 16个浮点数,也就是64字节;我们有50块骨骼,那么每个关键帧就需要50 x 64 = 3200字节,另外关键帧还需要一个4字节的时间值,那么就是3204字节;两秒的30fps动画一共包含60个关键帧,于是可以算出最终的大小是3204 x 60 = 192240字节,不到200k的样子。这就是未经压缩的数据大小,当然这里忽略了一些诸如骨骼名字之类的信息,和我们要讨论的动画压缩关系不大,就不算在内了。

有哪些手段可以压缩这些数据呢?我们可以从多个方面入手。

首先,描述一个空间方位真的需要64字节那么多数据吗?一般来说,我们的动画不会包含象“切变”这样的变换,我们只需要旋转,平移和缩放就足够了,所以我们可以用两个表示平移和缩放的vector3(3个浮点数),以及一个表示旋转的四元数(quaternion,4个浮点数)就可以描述一个骨骼方位,( 3 + 3 +4 )x sizeof(float) = 40,每块骨骼一下省掉了24个字节。从矩阵中抽取平移,旋转和缩放信息的函数每个3d数学库都会有,不在这里讨论。

其次我们会发现,某些骨骼在整个动画过程中都没有动过(这里要引入一个绝对变换和相对变换的概念,下文详述),这样等于在每个关键帧里描述这些骨骼方位的数据都是一样的,无疑是一个很大的浪费。为了解决这个问题,我们可以修改一下数据结构,让每个骨骼分别保存自己的关键帧数据,这样一来不同骨骼的关键帧数量可以不同,对于那些始终保持不动的骨骼,可以只保存一个关键帧,这样就省多了。但是要注意,骨骼数据分开以后每个骨骼的关键帧都要记录自己的时间,所以这方面的空间占用反而会增加,但通常来说总体上是划算的。

顺着这个思路,对于同一块骨骼,可能某一类变换(比如缩放)在整个动画过程中都不会有变化,于是我们再改进一下数据结构,把每块骨骼的不同类型变换的关键帧也分开存储,也就是分成平移关键帧,旋转关键帧和缩放关键帧。这样一来我们就会欣喜地发现,对于角色动画,大部分骨骼都只有旋转的动画,一般只有根骨骼会有平移动画,缩放一般都不会用到。其实这从常识角度很容易理解,一般的生物(除了软体动物)骨骼都只能旋转,哪有能随便改变长度(平移)的,缩放就更不用说了。

现在比较理想的情况是,每块骨骼只需要

  • 1个平移关键帧:12字节vector3加4字节time
  • 1个缩放关键帧:12字节vector3加4字节time(如果整个动画都没有用到缩放,可以把这个都省掉,所有骨骼的缩放都默认为单位向量)
  • 60个旋转关键帧:16字节quaternion加4字节time

一共是16 + 16 + 20 * 60 =  1232字节,一共50块骨骼就是61600字节,不到原始数据(近200k)的1/3了!

睡觉,待续。

阅读下一篇《骨骼动画的数据压缩(二)》

Categories: 程序/算法 Tags: , ,
  1. No comments yet.

 

Spam Protection by WP-SpamFree