动画源自拉丁语 anima,意思是赋予生命、兴趣、精神、运动或活动的行为、过程或结果。动作是生命的定义属性,动画的真正艺术是关于如何通过动作来讲述故事,表达情感,甚至表达人类性格的微妙细节。计算机是实现这些目标的次要工具——一个熟练的动画师可以用它来帮助更快地得到他想要的结果,而不必把注意力集中在他不感兴趣的技术上。 没有电脑的动画,现在通常被称为“传统”动画,有悠久而丰富的历史,数百名仍然活跃在这门艺术中的人不断地写着。正如在任何已建立的领域一样,一些经过时间考验的规则已经具体化,这些规则对某些事情应该如何做以及应该避免什么提供了一般的高级指导。 传统动画的这些原则同样适用于计算机动画,我们将在本章中讨论其中的一些原则。
然而,计算机不仅仅是一个工具。除了让动画师的主要任务变得不那么乏味之外,电脑还添加了一些真正独特的能力,这些能力是以前根本无法获得或极其难以获得的。 现代建模工具允许相对容易地创建详细的三维模型,渲染算法可以产生令人印象深刻的外观,从完全逼真到高度风格化,强大的数值模拟算法可以帮助为特别难以动画的对象产生所需的基于物理的运动,运动捕捉系统提供了记录和使用真实运动的能力。 这些发展导致了计算机动画技术在电影和广告、汽车设计和建筑、医学和科学研究以及许多其他领域的爆炸式使用。全新的领域和应用也出现了,包括全电脑动画电影、虚拟/增强现实系统,当然还有电脑游戏。
本书的其他章节更直接地涵盖了上面提到的许多发展(例如,几何建模和渲染)。在这里,我们将只提供直接用于创建和操纵运动的技术和算法的概述。
特别地,我们将大致区分并简要描述四种主要的计算机动画方法:
- 关键帧为动画师提供了最直接的控制,动画师在某些时刻提供必要的数据,计算机填充其余部分
- 程序动画包括定制的动画,这些通常是通过经验,数学函数和程序来制作的,其输出类似于某些特定的动作。•
- 基于物理的技术解决运动微分方程。•
- 动作捕捉使用特殊的设备或技术来记录真实世界的运动,然后将这种运动转移到计算机模型中。
在他 1987 年开创性的 SIGGRAPH 论文中,约翰·拉塞特将早在 20 世纪 30 年代由沃尔特·迪斯尼工作室的传统动画师开发的关键原理引入了当时刚刚起步的计算机动画社区。 他提出了 12 个原则(动画 12 原则):挤压和拉伸、时间点、预期、跟进和重叠动作、慢进和慢出、舞台、弧线、次级动作、直接前进和姿势到姿势的动作、夸张、扎实的绘画技巧和吸引力。 近二十年后,这些经过时间考验的规则依然重要,它们可以区分自然而有趣的动画和机械而无聊的动画。 此外,对于计算机动画来说,充分利用计算机的能力,给予动画师平衡控制和灵活性是非常重要的。虽然这些原则是众所周知的,但许多因素影响着人们在实践中对这些规则的关注程度。虽然制作故事片的角色动画师可能会花很多时间来遵循这些原则,但许多游戏设计师倾向于认为他们的时间应该花在其他地方。
时间,或者说动作的速度,是任何动画的核心。事情发生的速度会影响动作的意义、情绪状态,甚至涉及到物体的感知重量。 根据动作速度的不同,角色的头部从左向右转动可能意味着被重物击中后的反应,也可能是在书架上慢慢找书或伸展颈部肌肉。为手头的具体行动设定合适的时机是非常重要的。动作应该占用足够的时间以引起注意,同时避免过于缓慢和潜在的无聊动作。
对于涉及录制声音的计算机动画项目,声音提供了一个自然的定时锚。事实上,在大多数制作中,演员的声音是首先录制的,然后完整的动画与此录音同步。 由于大而重的物体往往比小而轻的物体移动得慢(更准确地说,加速度更小),所以时间可以用来提供关于物体重量的重要信息。
在动画的任何时刻,应当向观众清晰的表达动画的想法(动作、情绪、表情)。好的舞台或高层次的行动计划,应该引导观众的眼睛到重要的行动目前集中的地方,有效地告诉他“看这个,现在,看这个”,而不用任何语言。 对人类感知的一些熟悉的先验知识可以帮助我们完成这项艰巨的任务。由于人类的视觉系统主要对刺激物的相对变化作出反应,而不是对刺激物的绝对值作出反应,因此静止环境中的突然运动或繁忙场景中某些部分的缺乏运动自然会引起人们的注意。 与正面布局相比,呈现相同的动作,物体的轮廓会发生变化,这通常会让动作更加显眼。
动作的布局(视角)很重要,在左边两张图中,左上的角色抬起左臂很明显,相反,对于左下的角色,观众很可能意识不到她有抬起左臂。
在较低的层次上,每个行动可以分成三个部分:预期(行动的准备)、行动本身和后续行动(行动的结束)。在许多情况下,行动本身是最短的部分,在某种意义上,也是最无趣的部分。 例如,踢球可能涉及到踢球者的大量准备工作和对离开的球的长时间“视觉跟踪”,并有充分的机会显示踢球者的压力、情绪状态,甚至是对动作预期结果的反应。动作本身(腿踢球的动作)相当简单,在这种情况下只需要几分之一秒。
动作的预期的目标是观众,目的是让观众对即将发生的动作有所准备。如果动作本身非常快、或者对动画的叙事很重要时,动画预期的作用就显得很重要了。 创建对此类行动的更广泛的动画预期有助于突出这些动作,并在快速事件的情况下确保观众不会穿过它们。
在现实生活中,主要动作往往会引起一个或多个其他重叠动作。对象的不同附件或松散部分通常拖到主引导部分的后面(附件相对于主动作有一定的延迟),并在主动作之后继续移动一段时间。 此外,下一次行动往往在前一次行动完全结束之前就开始了。球员可以在他还在追踪他刚才踢的球的时候就开始奔跑。忽视这种自然流动通常被认为是动作之间有停顿,并可能导致类似机器人的机械运动。 虽然重叠是必要的,以保持运动的自然,但动画制作人经常添加辅助动作,以使运动更有趣,并实现动画的逼真复杂性。更重要的是,不要让次要行动主导主要行动。
可以使用几种特定的技术来使运动看起来更自然。最重要的可能是挤压和拉伸,它建议在移动的物体移动时以特定的方式改变其形状。人们通常会沿运动方向拉伸物体,并在施加力时将其挤压。 以上这是一个弹跳球的经典动画。保存总体积是很重要的,因为这恰好避免了物体增大或缩小的影响。运动速度(或力)越大,伸展(或挤压)就越多。
使用这种变形有几个原因。 对于非常快的运动,对象可以在两个连续的帧之间快速移动,以至于在当前帧和前一帧的对象之间没有重叠,这可能会导致选频闪(Strobing)(伪影的一种变体)。让物体朝运动方向拉长可以确保更好的重叠,并帮助眼睛对抗这种令人不快的影响。 拉伸/挤压也可以用来显示对象的灵活性,更多的变形应用于更柔韧的材质。如果对象要显示为刚性,则其形状在移动时故意保持不变。
自然运动很少沿着直线发生,因此在动画中通常应该避免这种情况,而应该使用圆弧。 同样,现实世界中的任何运动都不能立即改变其速度——这将需要对对象施加无限大的力。在动画中也希望避免这样的情况。特别是,运动应该逐渐开始和结束(慢进和慢出)。 手绘动画有时是通过直接的动作完成的,动画师从第一帧开始,按顺序绘制一帧又一帧,直到结束。而姿势到姿势的动作,也称为关键帧,更适合于计算机动画。在这种技术中,动画是通过一系列相对稀疏的关键帧精心规划的,其余的动画(中间帧)只有在设置关键帧后才填充。 这允许更精确的设定时机,并且可以通过下一节中介绍的算法来接管过程中最繁琐的部分——创建中间帧。
上面概述的几乎所有技巧都可以通过合理的夸张来达到更好的艺术效果,或者强调动作或角色的某些特定性质。最终目标是实现一些观众想要看到的东西,一些吸引人的东西。极端复杂或过于对称的角色或动作往往不那么吸引人。 要创造出好的效果,传统的动画师需要扎实的绘画技能。类似地,计算机动画师当然应该理解计算机图形学,并对他使用的工具有扎实的知识。
在传统动画中,动画师完全控制着制作过程的所有方面,正如在所有地方计划好的细节,没有什么能影响最后的成品效果。为这种灵活性付出的代价是,每一帧都是手工创建的,导致极其耗时和耗力。 在计算机动画中,则有更多的权衡:一方面如果让动画师对结果有更直接的控制,这时就要求他付出更多的工作;另一方面,如果依赖更多的自动化技术,这些技术也许只需要设置几个输入参数就能得到效果,但几乎不能控制结果的某些属性。 一个好的算法应该提供足够的灵活性,同时只要求动画师提供直观、容易提供的信息,以及他自己认为达到预期效果所必需的信息。虽然在实践中完全遵守这一要求是不太可能的,因为这可能需要某种接近读心机的东西,但我们确实鼓励读者从提供这种平衡的角度来评估任何计算机动画技术。
当术语”关键帧“被应用在 3D 计算机动画中时可能被误解,毕竟它并非图像那样完整的一帧。 在任何给定的时刻,要动画的 3D 场景由一组数字指定:所有对象的中心位置、它们的 RGB 颜色、应用于每个轴上每个对象的缩放量、对复杂对象的不同部分之间的建模转换、相机位置和方向、光源强度等。 为了对场景进行动画处理,这些值的某些子集必须随时间变化。当然,人们可以直接在每一帧设置这些值,但这不是一种高效的做法。我们有一种简化的方法:选择在时间轴上的一些重要时刻(关键帧),为这个时刻确定特定属性的值(键值)。我们将帧和值的组合 (tk, fk) 称为键。 对于不同的参数,关键帧不必相同,但至少为其中一些同时设置键通常是合乎逻辑的。例如,为特定对象的 x、y 和 z 坐标选择的关键帧可能设置在同一帧上,形成单个位置向量键 (tk, pk)。 然而,这些关键帧可能与为对象方向或颜色选择的那些完全不同。关键帧越接近彼此,动画师对结果的控制就越多。然而,我们必须权衡设置更多关键帧带来的工作上的成本。因此,在相对简单的动作上设置较少的关键帧,而在拥有复杂动画的地方设置更多的关键帧。
一旦动画器设置键值对 (tk, fk),系统必须为所有其他帧计算值。尽管我们最终只对一组离散的值感兴趣,但将其视为通过一组离散点拟合连续动画曲线 f (t) 的经典插值问题会很容易理解。 由于动画师最初只提供键而不是导数(切线),直接从键计算所有必要信息的方法更适合动画插值。沿曲线参数变化的速度由曲线相对于 time 的导数给出。因此,为了避免速度突然跳跃,通常需要 C1 连续性。 动画曲线通常不需要更高程度的连续性,因为对应于加速度或施加力的二阶导数可以在现实世界中经历非常突然的变化(击中固体墙的球),并且较高的导数并不直接对应于物理运动的任何参数(较高阶数的导数没什么物理意义)。这些考虑使得 Catmull-Rom 样条成为创建动画曲线的最佳选择之一。
大多数动画系统为动画师提供了对该初始曲线进行交互式微调的能力,包括插入更多的键、调整现有键或修改自动计算的切线。 另一种有助于调整曲线形状的有用技术称为 TCB 控制(TCB 代表张力 T、连续性 C 和偏差 B)。这个想法是引入三个新参数,通过调整关键点的两个切线(进切线和出切线)来修改关键点附近曲线的形状。对于在时间轴上均匀间隔 Δt 的键,关键帧上输入切向和输出切向在标准 Catmull-Rom 表达式中可以写成(C1 连续): 张力参数 t 通过缩放传入和传出的切线来控制键附近曲线的锐度。较大的切线(较低的张力)导致键附近的平坦曲线形状。 偏差 b 允许选择性地增加键邻居键的权重,局部拉近连接键与其左(b 接近 1,是“超调”动作)或右(b 接近 -1,则是“下冲”动作)邻居键的直线。 连续性 c 的非零值使传入和传出切线不同,允许动画师在键值的曲线中创建扭结。 实际上,TCB 参数的有用值通常仅限于区间 [−1; 1],默认值 t = c = b = 0 对应于原始 Catmull-Rom 样条。
到目前为止,我们已经讲了如何通过设定键的位置和微调键处的切线值来控制动画曲线的形状。然而,当人们想要同时控制物体运动的位置和速度时,这通常是不够的。 给定空间中的一组位置作为键,自动曲线拟合技术可以通过它们拟合曲线,但产生的运动轨迹仅受到强制对象到达相应关键帧 tk 处的指定关键点位置 pk 的约束,并且没有直接包含关于键之间的运动速度。 这可能会产生问题。例如,如果一个对象沿 x 轴移动,首先以每秒 11 米的速度移动一秒,然后以每秒 1 米的速度移动 9 秒,它将在 10 秒后到达位置 x = 20,从而满足动画师的键 (0,0) 和 (10, 20)。然而实际上,我们并不希望这种抖动运动,或许速度为 2 米/秒的均匀运动可能更接近动画师的期望。 虽然通常不会展示出这种极端的行为,由标准拟合过程产生的多项式曲线有时会显示出关键点之间的运动速度不均匀,如图 16.7 所示。 虽然在一定容忍范围内,人类的视觉系统对某些参数的微小变化感知不明显(例如颜色和旋转上的变化),但我们必须确定好位置和速度的属性,其中速度直接对应于日常经验。
我们将首先区分在拟合过程中使用的曲线参数化和用于动画的曲线参数化。
当曲线通过位置键进行拟合时,我们将结果写成某个参数 u 的函数 p(U),它描述曲线在空间中的几何形状。弧长 S 是曲线的物理长度。
动画师控制沿现有曲线运动的一种自然方法是指定额外的函数 s(t),该函数对应于对象在任何给定时间应该沿曲线走多远。
为了得到空间中的实际位置,我们还需要一个辅助函数 u(s),它计算给定弧长 S 的参数值 u。然后通过组合这些函数给出计算给定时间 t 的物体位置的完整过程:
有几个标准函数可以用作 距离-时间 函数 s(t)。 其中最简单的是对应于恒定速度的线性函数:s(t)= vt,是常值。另一个常见的例子是具有恒定加速度 a(和初始速度 vo)的运动,它由抛物线 s(t)= V0 t + at^2/2 来描述。由于速度在这里是逐渐变化的,所以这个函数可以帮助建模理想的缓进和缓出行为。更一般地,如果 s(t)的斜率为负,那么它对应于沿着曲线向后的运动。 为了实现最大的灵活性, 交互式编辑 s(t)通常由动画系统提供给动画师。距离-时间函数并不是控制运动的唯一方法。在某些情况下,用户指定速度-时间函数 v(t)甚至加速度-时间函数 a(t)可能更方便。由于它们对应的是 s(t)的一阶导数和二阶导数,为了使用这些类型的控制,系统首先通过积分用户输入(在 a(t)的情况下两次)来恢复距离-时间函数。
曲线参数 u 与弧长 s 之间的关系由系统自动建立。 在实际中,系统首先根据参数 u(即反函数 s(u))确定弧长。使用这个函数,对于任何给定的 S,都可以解出方程 S (u)−S = 0 而未知的 u(S)。对于大多数曲线,函数 s(u)没有解析解,必须进行数值积分。标准的数值求根程序例如牛顿法可以直接用于解方程 s(u)−s = 0。
另一种方法是将曲线本身近似为点 pi 之间的一组线性的线段,这些线段是在一组足够密集的参数值 ui 上计算得到的。然后创建一个近似弧长表: 由于 s(u)是 u 的非递减函数,因此可以通过简单地搜索表找到包含值 s 的区间。然后对找到的区间进行线性插值,最终求出 u(S)。如果需要更高的精度,则可以应用以该值为起点的牛顿求解法的几个迭代循环。
上面介绍的技术可以用来为描述场景的大多数参数插入一组键的集合。 三维旋转是一个重要的运动,更专门的插值方法和表示是常见的。设计专门的插值法的原因是,将标准技术应用于 3D 旋转通常会导致严重的问题。 旋转(改变物体的朝向)是除了平移之外唯一保持物体形状不变的运动。它在刚性物体的动画中起着特殊的作用。
有几种方法可以指定对象的朝向。首先,可以使用第 6 章中描述的变换矩阵。不幸的是,原始的(元素到元素)旋转插值矩阵无法显示出正确的结果。 例如,在顺时针旋转 90 度和逆时针旋转 90 度之间“半程”的旋转矩阵是 0 矩阵,实际上应该是单位矩阵(0 度旋转,不旋转): 当然,正确的结果是对应于无旋转的单位矩阵。 其次,可以将任意旋转朝向指定为围绕特定顺序选择坐标轴做恰好三次旋转的序列。这些轴可以固定在空间中(固定角度表示法),也可以嵌入到对象中(局部坐标,每次旋转后都会发生变化)。这三个旋转角度可以通过标准关键帧直接设置动画。 但一个被称为万向节锁的问题出现了。如果三个旋转轴中的一个在旋转过程中意外地与另一个轴对齐,则会发生万向节锁定,从而使物理设备的可用自由度减少一个。这种效果比人们想象的要普遍得多——向右(或向左)转弯 90 度就有可能将物体置于万向节锁中。
最后,可以通过在空间中选择合适的轴以及围绕该轴的旋转角度来指定任何方向。虽然此表示中的动画相对简单,但组合两个“轴-角”旋转矩阵并不是容易的事情。 为此(“轴-角”旋转)开发了一种特殊的数学工具——四元数,使这种表示法既适合于将几个旋转组合成一个单独的旋转,也适合于动画。
给出一个三维向量 v=(x,y,2)和一个标量 S,将两者组合成一个四分量向量可以形成一个四元数 Q:Q=[s x y z]=[s v]。接下来为四元数定义几个新的操作(加法、数乘、乘积):
上式中的 X 表示向量叉积。很容易看出,四元数乘法是满足结合律的,但不满足交换律(类似于矩阵)。
对于四元数的归一化——缩放它们,使得四元数的长度($\vert q\vert=\sqrt{s^2+v^2}$)为 1。最后是逆四元数:
在球面上等距离的插值是最准确的,但是很难。 在 4D 空间线性插值再做归一化,虽然不准确,但是很简单,而且在大部分场景下都已经足够了。
虽然对象变形技术可能被视为建模工具会更恰当一些,但传统上它们是与动画方法一起讨论的。 关于改变对象形状的操作,最简单的例子可能是非均匀缩放。更一般地说,一些函数可以应用于指定对象的所有点的局部坐标(即三角形网格的顶点或样条曲面的控制多边形),重新定位这些点并创建一个新形状:p ' = f (p, γ),其中 γ 是变形函数使用的参数向量。选择不同的 f(可以有多个变形函数组合在一起)可以帮助创建非常有趣的变形。 有用的简单函数的例子包括如图 16.13 所示的弯曲、扭转和锥度。在这种情况下,通过对变形函数的参数进行关键帧化,用动画控制形状的变化会非常容易。 然而,这种技术的缺点包括难以为一些非标准变形选择数学函数,并且所产生的变形是全局的,即整个对象而不仅仅是它的一部分。
为了在局部变形对象的同时提供对结果的更直接的控制,可以选择一个顶点,将其移动到一个新的位置,并且邻近的顶点会在一定程度上跟随它。受变形影响的区域和物体不同部分的具体位移量由衰减函数控制,衰减函数随着距离(通常在物体表面上计算)到种子顶点的距离增加而减小。种子顶点运动可以通过关键帧来产生动画形状变化。 一种更普遍的变形技术被称为自由形式变形(FFD) 。 首先建立一个局部坐标网格(晶格)来封装待变形对象的部分,并计算所有相关点相对于晶格的坐标(s, t, u)。然后,用户可以自由地改变晶格中点的位置。最后使用 3 次贝塞尔插值计算变形后的任意坐标: 式中 L、M、N 为各维格点的最大索引。 实际上,晶格是物体用作变形的低分辨率版本,允许任意复杂物体的平滑形状变化,通过相对较少的直观参数调整。 FFD 晶格本身可以被系统视为规则对象,并且可以被变换、模拟,甚至在必要时进一步变形,从而导致晶格所附接的对象的相应变化。 例如,移动由原始晶格和扭曲晶格组成的变形工具(表示对象上的凸起)会导致凸起在对象上移动。
为关节角色创建动画,常常通过关键帧和专门的变形技术的组合来执行。 用于动画的角色模型通常至少由两个主要层组成。代表角色外壳或皮肤的高度细节表面的运动是观众最终想看到的。它下面的骨架是一个关节的层次结构(树),它提供了一个角色的运动学模型,专门用于动画。 在某些情况下,在骨骼和皮肤之间插入大致对应于肌肉的附加中间层。
骨骼的每个关节都充当其下方层次的父对象。根节点代表整个角色直接位于世界坐标系中。如果存在与关节相关联的局部变换矩阵,则可以通过简单地沿着从根到关节的路径,将路径上所有关节的局部变换组合起来,得到与世界系统相关联的变换。 为了评估整个骨架(即,找到关节的位置和方向),执行对完整关节树的深度优先遍历(DFS)。用来存放变换矩阵的栈(Stack)是一个有用的数据结构。 当向下遍历树时,当前复合矩阵被压入堆栈,并且通过将当前矩阵与存储在关节处的矩阵相乘来创建新的复合矩阵。当回溯到父级时,应该在访问另一个分支之前删除本分支上的变换矩阵;这可以通过简单地弹出堆栈来轻松完成。
尽管在整个计算机图形学中都在使用这种用于计算层次的通用而简单的技术,但在动画领域中,它被赋予了一个特殊的名称——正向运动学 FK。 虽然可以使用变换矩阵的通用表示方法,但通常会使用特定的参数集(如关节长度和角度)来指定骨架。为了使用正向运动学设置动画,可以直接操纵关节的旋转参数。这项技术还允许动画师改变关节之间的距离(链接长度)。但人们应该意识到,这与肢体伸展相对应,通常看起来相当不自然(人的肢体不应该过分的变长或缩短)。 正向运动学要求用户为运动中涉及的所有关节设置参数。然而,这些关节中的大多数属于层次的内部节点,它们的运动通常不是动画师想要关心的事情。 在大多数情况下,动画师只是想让它们自然地移动,而人们更感兴趣的是指定关节链端点的行为,这通常对应于执行特定的动作,如脚踝或指尖。动画制作者更愿意让系统根据端点的运动来自动确定所有内部关节的参数。 反向运动学(IK)使我们能够做到这一点。
设 x 是端点的位置,alpha 是指定从根到最终关节的链上的所有内部关节所需的参数向量。
有时,最终关节的方向也是由动画制作人直接设置的,在这种情况下,我们假设相应的变量包含在向量 x 中(x 包含了已知的位置和旋转)。但是,为简单起见,我们将为向量编写所有特定的表达式:
不幸的是,上述的方程通常没有解析解,而且在大多数情况下它是欠约束的,即未知的内部关节参数的数目超过向量 x 中的变量的数目。这意味着端点的运动可能对应多种骨架的运动。 如下图所示,对于两端固定的骨骼,存在多种可能的解。 在上述多解的状况下寻找特定解的方法是存在的,包括那些自然约束(例如,人体的手臂关节只能向一侧弯折)。我们还应该记住,计算的 Jacobian 矩阵 只对一个特定的状态有效,并且它必须随着骨架的移动而更新。 完整的 IK 计算框架在图 16.19 中展示。当然,IK 的根不必是整个层次结构的根,并且复数的 IK 解算器可以被应用在骨架的独立部分上。例如,可以在手脚上都安装独立的 IK 解算器,每个解算器都有自己独立的根节点。
通常将 IK 和 FK 结合在一起来为骨架设置动画。许多常见的动作(走路、抓握、触摸等)在关节上显示出明显的规律模式,这使得利用上述“切片”的库,我们可以快速的创建自然的动作。然后动画师调整角色的物理参数,赋予它更多的个性。
当一个骨架改变它的位置时,它就像一个特殊类型的变形器应用到角色的蒙皮上。通过将每个蒙皮顶点分配一个(刚性蒙皮)或多个(光滑蒙皮)关节作为驱动器,将运动传递到该表面上。 在第一种情况下,皮肤顶点被简单地冻结在相应关节的局部空间中,在这种情况下,关节可以是空间中最近的一个,也可以是用户直接选择的一个。然后,该顶点复刻该关节经历的任何运动,其在世界坐标中的位置由标准 FK 过程确定。 虽然它很简单,但刚性的蒙皮使得在关节附近的区域很难获得足够光滑的蒙皮变形,也很难获得更微妙的效果,如呼吸或肌肉运动。额外的专用变形器称为屈肌,可用于此目的。
在光滑蒙皮中,多个关节可以根据动画师分配的一组权重影响蒙皮顶点,从而对结果提供更详细的控制。最终的位移向量是由来自不同关节的变换根据它们的对该点的权重加权平均得到。归一化权重(∑wi = 1)是最常见的,但不是必要的。 设置平滑的蒙皮权重以达到预期的效果并不容易,需要富有经验的动画师。
骨骼非常适合创建角色身体的大多数动作,但它们不太适合用于逼真的面部动画。原因是人类面部的皮肤是由直接附着在它上面的肌肉来移动的,与身体其他部位相反。在人体的其他部位,肌肉的主要目的是移动骨骼,任何皮肤变形都是次要的结果。 这种面部解剖安排的结果是一套非常丰富的动态面部表情,人类使用它作为主要的交流工具之一。我们都受过很好的训练,可以识别这种面部变化,很容易注意到任何不自然的外表。(不好翻译) 这不仅对动画师提出了特殊的要求,而且还需要一个高分辨率的面部几何模型,如果想要真实感,还需要精确的皮肤反射属性和纹理。
虽然可以逐顶点设置面部的关键姿势,并在它们之间进行插值,或者使用基于物理的技术直接模拟潜在肌肉结构的行为,但也存在更专业的高级方法。 特定面部的静态形状可以通过一组相对较小的所谓构象参数来表征(简单理解就是游戏中用来捏脸的参数),这些参数用于将通用面部模型转变为具有个人特征的面部模型。 一组额外的参数可以用来描述动态形状的脸的动画。例子包括头部的刚性旋转、眼睛睁得有多开、某些特征点从静态位置偏移的距离等等。确定这些参数,以便通过一些参数的组合来获得大多数有趣的表情,因此,这些参数允许通过标准关键帧对面部进行动画。 为了达到更高的控制水平,人们可以使用参数来创建一组与常见情绪(中性、悲伤、快乐、愤怒、惊讶等)相对应的表情,然后将这些关键姿势混合在一起,得到一张“略带悲伤”或“愤怒惊讶”的脸。 类似的技术也可以用于对口型动画,但在这种情况下,关键姿势对应于不同的音素。
面部动作编码系统(FACS)不是使用一系列静态表情来描述动态表情,而是将动态面部表情直接分解为称为动作单元(au)的基本动作的总和。这套动作是基于广泛的心理学研究,包括抬起内眉、皱起鼻子、伸展嘴唇等动作。组合 au 可以用来合成一个必要的表达式。
即使在上述技术的帮助下,从头开始创建逼真的角色动画仍然是一项艰巨的任务。因此,人们很自然地把注意力集中在记录现实世界中演员的动作,然后将其应用于计算机生成的角色的技术上。这种动作捕捉(MC)技术主要有两类:电磁和光学。
在电磁运动捕捉中,电磁传感器直接在 3D 中测量其所在的位置(可能还有方向),通常实时提供捕获结果。 这种技术的缺点包括设备成本高,可能受到附近金属物体的干扰,以及传感器和电池的尺寸,这可能成为执行大幅度运动的障碍。 在光学 MC 中,使用小的彩色标记代替主动传感器。在最基本的配置中,运动由两个校准的摄像机记录,并使用简单的三角测量来提取标记的三维位置。 用于精确跟踪视频中的多个标记的更高级的计算机视觉算法在计算上是昂贵的,因此,在大多数情况下,这种处理是离线完成的。
光学跟踪的鲁棒性通常不如电磁跟踪。某些帧中标记的遮挡,标记的错误识别以及图像中的噪声,只是必须解决的几个常见问题。 引入更多的摄像机从不同的方向观察运动,提高了准确性和鲁棒性,但这种方法更昂贵,处理这些数据需要更长的时间。随着可用计算能力的提高和更好的计算机视觉算法的发展,光学 MC 变得越来越有吸引力。 由于标记物对演员影响小的特性,光学方法适用于精细的面部动作捕捉,也可以用于除人类以外的物体,例如动物甚至风中的树枝。
通过在表演者身上安装几个传感器或标记,可以记录一些点集合的一组与时间相关的 3D 位置。这些跟踪位置通常选择在关节附近,但是,当然,它们仍然位于皮肤表面,而不是真正的骨骼连接点。因此,需要一些额外的处理来将记录的位置转换为物理骨架关节的位置。 例如,在肘部或脚踝的两侧放置两个标记,系统可以通过平均两个标记的位置来获得更好的关节位置。如果没有这种额外的处理,由于关节位置偏移以及固有噪声和测量精度不足,可能会出现非常明显的伪影。 由于在运动过程中的物理不准确,例如,角色的四肢在行走或抓取过程中可能会与他们应该接触的物体失去接触,像骨骼滑动这样的问题可能会发生。 大多数这些问题可以通过使用反向运动学技术来纠正,该技术可以明确地强制肢体端点的行为。
恢复的关节位置现在可以直接应用于计算机生成角色的骨架。此过程假定角色的物理尺寸与表演者的物理尺寸相同。将记录的动作重定位到不同的角色上,更一般地称,编辑 MC 数据,需要非常小心地满足必要的约束(例如保持脚在地面上或不允许肘部向后弯曲),并保持修改后动作的整体自然。 一般来说,期望的改变越大,保持结果质量的可能性就越小。解决这个问题的一个有趣的方法是记录大量的运动,并将这些运动中的短片段拼接在一起,以获得所需的运动。虽然这个主题目前是一个非常活跃的研究领域,但有对记录下来的动作的调整(以满足动画师的需要)十分有限,仍然是动作捕捉技术的主要缺点之一。
我们周围的世界是由物理定律支配的,其中许多定律可以被形式化为一组偏微分方程,或者在一些更简单的情况下,可以被形式化为常微分方程。 计算机最初的应用之一就是(现在仍然是)求解这样的方程。因此,尝试使用过去几十年来发展起来的数值技术来获得计算机动画的逼真运动是很自然的选择。
由于其相对复杂性和巨大的成本,基于物理的动画最常用于其他技术不可用或不能产生足够逼真的结果的情况。主要的例子包括流体的动画,布料模拟,刚体运动和弹性物体的精确变形。 控制方程和常用数值方法的细节在每种情况下都是不同的,但许多基本思想仍然适用于各种应用。存在许多数值求解常微分方程和偏微分方程的方法。 我们将在这里简要地提到有限差分方法——概念上最简单和最流行的算法之一,它已经应用于动画中遇到的大多数微分方程。
ODE:常微分方程 PDE:偏微分方程
这种方法的关键思想是用离散的——差分方程——来代替微分方程。连续域由一组有限的点来表示,并在这些点上计算解。 在最简单的情况下,这些是在如图所示的均匀矩形网格上定义的。每一个点的微分值由该点所在原始网格上的差分值代替。 一种方法是将给定点的函数值从网格上相邻点的函数值中减去: 当然,这些表达并不是唯一的方法。例如,可以用 f (t−Δt)代替上面的 f (t)并除以 2Δt(中值差分替代向前/向后差分)。 对于包含时间导数的方程,现在可以通过求解未知 f (t + Δt)的差分方程系统(每个空间位置上有一个这样的方程),以 Δt-size 步骤的序列在时间上向前求解未知函数的值。 一些初始条件,如,未知函数在初始时刻的值,对于启动整个求解过程是必要的。其他信息,例如在边界上的值,有时也需要指定。
对于所谓的显式格式(显式欧拉法求解微分方程),当所有其它值都取在当前时刻,并且相应差分方程 f(t + At)中唯一的未知值由这些已知值表示时,可以很容易地计算 f(t + At)。 隐式方程(隐式欧拉求解法)混合了当前和未来的值,例如,: 在这种情况下,我们只能通过数值解法来迭代的求解方程。
差分格式的选择会极大地影响算法的各个方面。其中最明显的是准确性。 在$\triangle t\to 0\space or\space \triangle x\to 0$的情况下,方程(显式格式)中的表达式是精确的,但对于有限步长的情况,一些格式可以更好地逼近导数。 差分格式的稳定性与数值误差随时间增长的速度有关,数值误差在实际中总是存在的。对于稳定的方案,这种增长是有界的,而对于不稳定的方案,这种增长是指数的,并且可能很快就会大过我们所要的答案。 重要的是要认识到,解决方案中的某些不准确性是可以容忍的(事实上,动画很少需要物理和工程上所要求的精度),但不稳定的结果是完全没有意义的,应该避免使用不稳定的方案。 通常,显式格式是不稳定的,或者在更大的步长下变得不稳定,而隐式格式是无条件稳定的。隐式格式允许更大的步长(因此,步数更少)。这就是为什么它们很受欢迎,尽管每一步都需要求解一组代数方程。 显式格式之所以吸引人,是因为如果它们的稳定性条件能够得到满足,则它们是简单的。为特定问题开发一个好的差分格式和相应的算法并非易事,对于大多数标准情况,最好使用现有的方法。
我们应该记住,在很多情况下,仅仅计算方程中的所有必要项本身就是一项困难且耗时的任务。例如,在刚体或布料模拟中,作用在系统上的大部分力是由于物体之间的碰撞。因此,在动画过程中的每一步,都必须解决一个纯粹几何的,但非常重要的碰撞检测问题。在这种情况下,需要较少评估这种力的方案可能会节省大量的计算资源。
虽然求解适当的时相关方程的结果给出了非常真实的运动,但这种方法有其局限性。首先,基于物理的动画效果很难控制。这些方程的基本数学性质表明,一旦初始条件被设定,解是唯一定义的。这没有给动画师留下太多的操作空间,如果由于某种原因结果不令人满意,那么就只有几个选择了。 它们大多局限于调整所使用的初始条件,改变系统的物理属性,甚至通过引入人工变量来修改方程式本身,从而将解决方案“驱动”到动画师想要的方向。 做出这样的改变需要很高的技能和对基础物理的理解,理想情况下,还需要数值方法。如果没有这些知识,基于物理的动画所提供的真实感可能会被破坏,或者可能出现严重的数值问题。
想象一下,一个人可以编写一个数学函数,在动画师的指导下精确地输出期望的运动。 上面概述的基于物理的技术可以被视为这种方法的特殊情况,当涉及的“函数”是解决特定微分方程的过程,而“指导”是初始条件和边界条件的集合,额外的方程项等。
然而,如果我们只关心最终结果,我们就不必遵循基于物理的方法。 例如,一个简单的表面恒定振幅波可以直接由应用 f (x, t) = cos(ωt−kx +φ)在恒定的频率 ω,波矢 k 和相位 φ 来得到在时间 t 上的 2d 位移。这样一组带有随机参数的波的叠加,可以制作出非常真实的水面效果,而不使用任何的流体方程。 事实证明,其他相当简单的数学函数也可以创建非常有趣的花纹或对象。在第 11.5 节中描述了几个这样的函数,其中大多数基于晶格噪声。 将时间参数添加到这些函数中,使我们能够比基于物理的技术更容易和更便宜地制作某些复杂现象的动画,同时保持结果的高视觉质量。 如果 noise(x)是底层的花纹生成函数,则可以通过在晶格中移动参数位置来创建它的时间相关变体。 最简单的例子是晶格匀速运动:timenoise(x, t) =noise(x + vt),。其他通过晶格更复杂运动实现的噪声也是可能的,而且实际上更常见。 上图显示了一个这样的螺旋路径。 另一种方法是为生成这些噪声的参数设置动画。如果外观随时间发生显著变化,例如云变得更加动荡,这种方法尤其适用。通过这种方式,我们可以使用生成静态云的函数来模拟云的动态形成过程。
对于一些程序技术,时间依赖性是一个更重要的组成部分。 最简单的元胞自动机在二维矩形网格上运行,其中每个位置(单元格)存储一个二进制值。为了创建时变的花纹,需要重复应用一些由用户提供的用于修改这些值的规则。规则通常涉及一组关于当前值和单元格相邻值的条件。例如,流行的 2D 生命游戏元胞自动机的规则是由英国数学家 John Conway 于 1970 年发明的:
- 一个死细胞(即,给定位置的二进制值为 0)恰好有三个活邻居成为一个活细胞(即,其值设为 1)。
- 一个活细胞如果有两个或三个活的邻居,它就会活下去。
- 在所有其他情况下,细胞死亡或保持死亡状态。
一旦将规则应用于所有网格位置,就会创建一个新的花纹,并开始一个新的进化周期。更复杂的自动机同时在几个可能为浮点值的三维网格上操作,并可用于云和其他气体现象或生物系统的动力学建模。 复杂的花纹可以从几个精心选择的规则中产生,但是如何编写这样的规则来创建所需的行为通常并不简单。这是程序技术的一个共同问题:关于如何创建新程序或甚至调整现有程序的参数,只有有限的指导(教程很少)。因此,通常需要通过试错(“通过经验”)进行大量调整和学习,以释放程序化方法的全部潜力。
另一种有趣的方法最初也是用来描述生物物体的,它被称为 L-系统。 这种方法基于用于重写符号字符串的语法或递归规则集。有两种类型的符号:终端符号表示我们想用语法表示的元素。根据其含义,语法可以描述树木和灌木的结构,建筑物和整个城市,或程序和自然语言。 在动画中,L-系统最常用来表示植物,相应的终端是对几何建模系统的指令:将叶子(或树枝)放在当前位置(我们将使用符号@并画一个圆圈),将当前位置向前移动一些单位(符号 f),将当前方向绕世界 z 轴旋转 60 度(符号+),弹出(符号[)或推动(符号])当前位置/方向,等等。(看不懂。。。)
辅助非终结符号(用大写字母表示)只有语义意义,没有任何直接意义。它们的目的是最终通过终端重写。 我们从特殊的非终结符 S 开始,继续并行地将语法规则应用于当前字符串,即替换当前存在的所有非终结符以获得新字符串,直到我们最终得到一个只包含终结符的字符串,因此不可能再进行替换。这串建模指令然后用于输出实际的几何图形。(看不懂。。。)
如上所示,对于相同的非终结符通常有许多不同的结果,从而允许使用相同的语法生成许多不同的对象。应用哪条规则的选择可以取决于被替换的符号旁边有哪些符号(上下文敏感),或者可以随机执行,为每个规则分配一些概率(随机 L-系统)。更复杂的规则可以为与环境的交互建模,比如修剪成特定的形状,参数可以与符号相关联,以控制发出的几何命令。
L-系统已经捕获了植物拓扑结构随时间的变化:在重写过程中获得的每个中间字符串都可以被解释为植物的“年轻”版本。对于更重要的变化,不同的产品可以在不同的时间有效,使植物的结构随着它的生长而发生显著变化。例如,一棵小树会长出许多新枝,而一棵老树只会长出一些新枝。
用 L-系统创建了非常逼真的植物模型。然而,与大多数过程技术一样,需要一些经验才能有意义地应用现有的 L-系统,而编写新的语法来获得某些期望的效果当然不容易。
当然,要使多个对象动起来,只需简单地将本章迄今为止描述的标准技术应用于每个对象。这对于运动已知的中等数量的已知物体非常有效。 然而,在许多情况下,在动态环境中采取某种协调行动是必要的。如果只涉及几个对象,动画师可以使用基于人工智能(AI)的系统,根据某个高级目标自动确定每个对象的即时任务,计划必要的运动,并执行计划。许多现代游戏使用这种自主对象来创造智能怪物或玩家的合作者。
有趣的是,当一个群体中的物体数量从几个增加到几十个、数百个和数千个时,群体中的个人成员必须只有非常有限的“智力”,才能使整个群体展示出看起来像是协调一致的目标驱动的运动。
事实证明,这种群聚是一种紧急行为,它可能是由于群体成员与他们最亲密的几个邻居之间的有限互动而产生的。任何观察到一群鸟或一群鱼令人着迷的同步运动的人都应该熟悉集群。
这项技术还可以用来控制成群的动物在地形上移动,甚至在人群中移动。
在任何给定的时刻,一组成员的运动,当应用于羊群时,通常称为 boid,是几个相互矛盾的趋势平衡的结果,其中的每一项都暗示着它自己的速度矢量。首先,作用在物体上的外部物理力 F,如重力或风。由这些力产生的新速度可以通过牛顿定律直接计算为
一旦确定了所有新的速度矢量,最终的向量将根据它们之间的优先级进行协商。避免碰撞和速度匹配通常具有更高的优先级。 使用加速度分配策略,而不是简单地平均期望的速度矢量,因为这可能导致取消冲动和不自然的“无处移动”行为。为一个物体提供一些固定的总加速度,并按优先顺序将其中的一部分分配给每个冲动。如果总可用加速度耗尽,则一些较低优先级的冲动对运动的影响较小或被完全忽略。 我们希望,一旦当前最重要的任务(在大多数情况下避免碰撞)完成,其他任务可以在不久的将来得到照顾。 尊重真实物体的一些物理限制也很重要,例如,将过高的加速度或速度钳制到一些现实值。根据鸟群成员的内部复杂性,动画的最后阶段可能是将协商的速度矢量转换为一组特定的参数(鸟的翅膀位置,平面模型在空间中的方向,腿部骨骼配置),用于控制机器人的运动。
一个更简单,但仍然非常有用的群体控制版本是由粒子系统实现的。一个系统中的粒子数量通常比一群粒子的数量要大得多,可以是数万或数十万,甚至更多。此外,在动画过程中,粒子的确切数量会随着新粒子的诞生和一些旧粒子的破坏而波动。 粒子通常完全独立于彼此,而忽视一个粒子的邻居,只通过经历外力和与物体的碰撞来与环境互动,而不是像羊群那样拥有避免碰撞的机制。 在动画过程中的每一步,系统首先用一些初始参数创建新的粒子,然后删除旧的粒子,然后根据牛顿定律计算必要的力并更新剩余粒子的速度和位置。 粒子系统的所有参数(粒子数量、粒子寿命、初始速度和粒子位置等)通常在动画师的直接控制下。粒子系统的主要应用包括对烟花、爆炸、喷洒液体、烟雾和火灾或其他没有清晰边界的模糊对象和现象进行建模。 要获得逼真的外观,重要的是为所有参数引入一些随机性,例如,在每个步骤中生成(和销毁)随机数量的粒子,其速度根据某种分布生成。 除了设置适当的初始参数外,控制粒子系统的运动通常是通过在空间中创建特定的力模式来完成的——例如,当粒子到达某个特定位置时,向新方向吹气或添加吸引力中心。 人们应该记住,尽管粒子系统的所有优点、实现的简单性和易于控制是主要的优点,但它通常不能提供真正基于物理的相同现象模拟所具有的真实感特征。