Skip to content

第11章 动画系统

引擎中的角色**动画系统(character animation system)**负责为角色灌输自然的动作。

1. 角色动画的类型

(1) 赛璐璐动画

游戏动画技术的前身是传统动画(traditional animation)手绘动画(hand-drawn animation)。快速连续显示一串静止图片产生动感,这些图片称为帧(frame)。实时三维动画可想象为传统动画的电子形式,把一串静止的全屏影像不断地向观众展示,以产生动感。

**赛璐璐动画(cel animation)**是传统动画的一个种类。把含动画的赛璐璐放置于静态背景之上,无需重复绘画静态背景。

赛璐璐动画的电子版本称为精灵动画(sprite animation)技术。精灵是一张细小的位图,叠在全屏背景影像之上,通常由专门的图形硬件绘画。精灵是二维游戏时代最主要的技术。一组帧被设计成就算不断重复播放也会显得流畅——这种动画称为循环动画(looping animation)。角色通常有多组循环动画周期,包括多种闲置周期(idle cycle)、步行周期(walk cycle)及跑步周期(run cycle)。

自三维图形技术的来临,精灵技术开始失去其吸引力。用面向摄像机的四边形,每个四边形贴上一连串纹理位图(称为动画纹理/animated texture)以产生动感。这种技术今天仍然用于低分辨率或远距离物体。

(2) 刚性层阶式动画

实现三维角色动画最初的方法称为刚性阶层式动画(rigid hierarchical animation)。此方法中,角色由一堆刚性部分建模而成。这些刚性部分以层阶形式彼此约束,类似哺乳动物以关节连接骨骼。

人形角色:

Pelvis (髋关节/骨盘) Torso (躯干) UpperRightArm (右上臂) LowerRightArm (右前臂) RightHand (右手) UpperLeftArm (左上臂) LowerLeftArm (左前臂) LeftHand (左手) Head (头) UpperRightLeg (右大腿) LowerRightLeg (右小腿) RightFoot (右脚) UpperLeftLeg (左大腿) LowerLeftLeg (左小腿) LeftFoot (左脚)

刚性层阶技术最大的问题在于,角色的身体会在关节位置产生“裂缝”。

(3) 每顶点动画及变形目标

我们希望能移动每个顶点,使三角形拉伸以产生更自然生动的动作。

方法之一是使用称为**每顶点动画(per-vertex animation)**的蛮力技术。此方法需要动画师为网格顶点添加动画。这是一种数据密集的技术,因为每个顶点随时间改变的动作信息都需要储存下来。

此技术的一个变种变形目标动画(morph target animation)。此方法仅制作相对少量的固定极端姿势(extreme pose)。在运行时把两个或以上的这些姿势混合,就能生成动画。每个顶点的位置是简单地把每个极端姿势的顶点位置线性插值(linear interpolation, LERP)而得。

变形目标技术常用于面部动画(facial animation)。动画师能使用变形目标动画去完全控制脸上的每个顶点,制作出细微及极端的移动,模拟面部肌肉。

(4) 蒙皮动画

**蒙皮动画(skinned animation)**含有许多每顶点动画及变形目标动画的优点,允许组成网格的三角形做出变形。但蒙皮动画也有刚性层阶式动画的高效性能及内存使用量特性。蒙皮动画能产生相当接近真实的皮肤和衣着移动。

**骨骼(skeleton)是由刚性的“骨头(bone)”所构建而成,这与刚性层阶动画是一样的。然而,这些刚性的部件始终是隐藏起来的。称为皮肤(skin)**的圆滑三角形网格会绑定于骨骼上,其顶点会追踪关节(joint)的移动。蒙皮上每个顶点可按权重绑定至多个关节,因此当关节移动时,蒙皮可以自然地拉伸。

(5) 把动画方法视为数据压缩技术

最有弹性的动画系统,可以想象成动画师能控制物体表面上无穷多的点。这种方法制作动画,结果回事无穷大量的数据。简化的版本是控制三角形网格的顶点,那么实际上,我们是把描述动画的信息加以压缩,限制了只能移动顶点。而变形目标动画可像想为更进一步的压缩,其压缩方法是在系统中加入更多的约束——顶点只能在一组固定数目的预定义顶点位置间的线性路径中移动。骨骼动画也是另一种通过加入约束来压缩顶点动画的方法。在此方法中,相对大量的顶点只能跟随相对少量的骨骼关节移动。

一般来说,我们选择动画技术的目标,是能提供最佳压缩而又不会产生不能接受的视觉瑕疵。

2. 骨骼

骨骼(skeleton)由刚性关节(joint)层阶结构所构成。在游戏业界,“关节”和“骨头(bone)”这两个术语通常会交替使用,但骨头一词其实名不副实。技术上说,关节是动画师直接控制的物体,而骨头只是关节之间的空位。游戏引擎并不在意骨头,只在乎关节。

(1) 骨骼层阶结构

骨骼的关节形成层阶结构,也即树结构。蒙皮动画所用的关节层阶结构,通常和刚性层阶相同。

我们通常会把每个关节赋予0~N-1的索引。因为每个关节有且只有一个父关节,只要在每个关节存储其父关节的索引,即能表示整个骨骼层阶结构。

(2) 在内存中表示骨骼

骨骼通常由一个细小的顶层数据结构表示,该结构含有关节数组。关节的储存次序通常会保证每个子关节都位于其父关节之后。这也意味着,数组中首个关节总是骨骼的根关节。

在动画数据结构中,通常会使用**关节索引(joint index)**引用关节。例如,子关节通常以索引引用其父关节。在蒙皮三角形网格中,每个顶点使用索引引用其绑定关节。使用索引引用关节,无论在储存空间上或查找引用关节的时间上,都比使用关节名字高效得多。

每个关节的数据结构通常含以下信息。

  • 关节名字,可以是字符串或32位字符串散列标识符。
  • 骨骼中其节点的索引
  • 关节的绑定姿势之逆变换(inverse bind pose transform)。关节的绑定姿势是指蒙皮网格顶点绑定至骨骼时,关节的位置、定向及缩放。我们通常会储存此变换之逆矩阵。

3. 姿势

把关节任意旋转、平移,甚至缩放,就能为骨骼摆出各种姿势。一个关节的**姿势(pose)**定义为关节相对某参考系(frame of reference)的位置、定向和缩放。关节的姿势通常以4×4或4×3矩阵表示,或表示为SQT数据结构(缩放/scale、四元数旋转/quaternion即矢量平移/translation)。骨骼姿势是其所有关节的姿势之集合,并通常简单地以SQT数组表示。

(1) 绑定姿势

绑定姿势(bind pose),有时候叫作参考姿势(reference pose)放松姿势(rest pose)。这是三维网格绑定至骨骼之前的姿势,因而得名。换句话说,这就是把网格当做正常、没有蒙皮、完全不涉及骨骼的三角形网格来渲染的姿势。绑定姿势又叫T姿势(T-pose)。特别选定此姿势,是因为此姿势中的四肢远离身体,较容易把顶点绑定至关节。

(2) 局部姿势

关节姿势最常见是相对于父关节来指定的。相对父关节的姿势能令关节自然地移动。我们有时候用局部姿势(local pose)描述相对父的姿势。局部姿势几乎都储存为SQT格式。

图形表达上,许多三维制作软件会把关节表示为小球,然而,关节含旋转及缩放,不仅限于平移。事实上,每个关节定义了一个坐标空间,因此,最好把关节显示为一组笛卡尔坐标轴。

数学上,关节姿势就是一个仿射变换(affine transformation)。第j个关节可表示为4×4仿射变换矩阵Pj,此矩阵由一个平移矢量Tj、3×3对角缩放矩阵Sj,及3×3旋转矩阵Rj所构成。整个骨骼的姿势Pskel可写成所有姿势Pj的集合,当中j的范围是0~N-1:

Pj=[SjRj0Tj1]Pskel={Pj}|j=0N1

a. 关节缩放

  • 有些游戏引擎不容许关节缩放,那么就会忽略Sj,把它假定为单位矩阵。

  • 有些引擎假设若使用缩放,其必须为统一缩放。此情况下,缩放能用单个标量sj表示。

  • 有些引擎甚至支持非统一缩放,那么缩放可以紧凑地表示为3个元素的矢量sj=[sjxsjysjz]。矢量sj的元素对应3×3缩放矩阵Sj的对角元素,本身并不是真正的矢量。

  • 游戏引擎几乎不会容许切变(shear),因此Sj几乎不会以3×3缩放/切变矩阵表示。

在姿势或动画中忽略或限制缩放有许多好处。

  • 使用较低维度的缩放表示法能节省内存。
  • 能确保包围球不会变换成椭球体(ellipsoid)。避免了椭球体就能大幅度简化按每关节计算的平截头体剔除及碰撞测试。

b. 在内存中表示关节姿势

关节姿势通常表示为SQT格式。

c. 把关节姿势当做基的变更

当把关节姿势变换Pj施以关节j坐标系表示的点或矢量时,其变换结果是以父关节空间表示的该点或矢量。

因为关节姿势能把点及矢量从子关节的空间(C)变换至其父关节的空间(P),我们会把此变换写成(PCP)j。另一个方式是引入一个函数p(j),它会回传关节j的父索引,那么就可以把关节j的局部姿势写成Pjp(j)

偶尔我们要由父关节的空间变换至子关节的空间。此变换就是局部关节姿势的逆变换。数学上表示为Pp(j)j=(Pjp(j))1

(3) 全局姿势

有时候,把关节姿势表示为模型空间或世界空间会很方便。这称为全局姿势(global pose)。有些引擎用矩阵表示全局姿势,有些引擎则使用SQT格式。

任何关节j的全局姿势(关节至模型空间的变换)可写成:

PjM=i=j0Pip(i)

当中,每次乘法迭代意味着i变成p(i),并且p(0)M

4. 动画片段

游戏是互动体验,玩家能控制其角色,通常也能控制部分摄像机行为。游戏的动画几乎都不可能制作成一串很长的、连续的帧。取而代之,游戏角色的移动都必须拆分为大量小粒度的动作。我们称这些个别的动作为动画片段(animation clip),有时或简称动画(animation)

Released under the MIT License.