关键帧动画来源很久,在wiki上查的话可以得到很多的示例,主要集中在2D方面的。很多早期的动画形式,都是用这种方式做出来。甚至是在业界,资深的美术师都是进行关键帧的创作,其他细节(插值)都是由其他美工制作或者计算机辅助设计。下图是2D的关键帧技术示例:灰色底部分是关键帧,白底部分的是非关键帧(图像资源来源于网络)。
3D关键帧动画跟2D的关键帧动画是紧密相连的,因为它们的核心概念都一样。创作者在创作动画的时候,只对组成一系列动画至关重要的帧(frame)进行创作加工。举例来说,如果创作者创作一个两秒的动画,按他对该动画的理解(和相关设计软件的功能性),他可能只需要创作10个关键帧就可以了。如果把这10个帧放到纸上,每一帧都包含了一个静态的画面,这个画面表示了在某个时间,动画中的每个顶点会进行到的一个位置。到此为止,创作者的工作也就完成了。在产生动画的时候,美术师或者是软件会根据这些关键帧和时间信息把每两个关键帧之间的帧绘画或者计算出来,从而产生连续的动画。这个新的帧产生的方式,在计算机上,我们叫“插值”。也正因为这个过程,所以前期资深美术师创作的那些帧就至关重要(因为它们包含了动画的框架走向),所以在术语上被称作为“关键帧”。
对理解关键帧动画来说,使用MD2文件格式是非常方便的。这个格式得益于卡马克(John Carmack)的大名和他的Quake引擎,在很多建模软件中都能找到支持。而事实上,这种早期的文件格式,就像当初微软的位图格式一样,都奉行一个文件头再加各个细节段的形式。如果对微软的bitmap熟悉(只要是未压缩的就可以),那么读取MD2文件就非常的容易。当然,如果不熟悉,也很容易。
在开始解析MD2文件前面,我们可以预见的是,既然把MD2放在关键帧动画文件格式里面讲,那么该格式肯定是典型的关键帧做法,也就是说,文件里面必定包含很多关键帧信息,每个帧中有相同数量的顶点,但是顶点的位置随着帧的变化而变化。好吧,这些就是关键帧的最关键的部分了。事实上也如我们预测,来看一下MD2文件格式中相关的部分:
1、在文件头读取后,文件头中可以得到关键帧开始的文件位置和一共包含多少个关键帧;对每一帧来说,
2、最开始12个字节是缩放信息,就是x、y、z方向各缩放多少单位;
3、紧跟的12个字节是位移信息;
4、后面16个字节的名字信息,给每个帧一个名字,这样容易辨别特定的动画;
5、再紧跟的就是顶点信息,每个顶点有4个字节,分别表示x、y、z和1个字节的保留位;
这样就得到了所有的帧信息。至于面、物体的组成,这里忽略。因为它们无非是对关键帧中的顶点的索引而已,只要理解了关键帧,物体的变化是很自然的。
实际应用中,我们需要对每个顶点都跟缩放因子和位移因子先做好计算,因为为了节省空间,最初读出的顶点信息是被归入0~255的值的(这样一个字节就能存入,如果按照3D常用的float存入,需要4个字节),真正的值需要通过组合缩放和位移因子才能得到。得到这些值后的关键帧,就相当于我们在文章开头的图中,得到了那些灰底的图像。实时动画过程中,要做的就是根据时间信息得到动画时间进行到了哪两个关键帧中(如果正好在关键帧上,就取关键帧本身的值),然后根据相关的插值算法得到这个中间的帧的值(顶点值)。关键帧动画的插值方法遵循线性插值法。
原理大致如此,关键帧动画相对于另外一种骨骼动画来说,很容易理解,而且很容易编码解析和控制,只不过最大的缺陷就是顶点数量在每一帧都是一样多的,对GPU不是很友好(另外一种动画,骨骼动画,用GPU来操作是天生有优势的,因为顶点初始就是定下来的,可以预先传入(upload)到GPU中)。
示例代码包含了读取一个md2,并播放整个动画的过程。看客如果需要,可以下载并进行一番hack,上述提到的概念都在keyframe类中实现。
附录:
1、关键帧动画代码