基于物理的动画/物理模拟

Physically Based Animation

今天我和李乐游给大家讲一下基于物理的动画这个题目。首先我们来解释一下这个题目,这个动画指的不是一部动画片的那个动画,是指在动画片/视效制作中的一个环节,也是计算机图形学的三个大方向之一:建模Modeling、动画Animation、渲染Rendering。也就是驱动我们的模型动起来的过程——那么怎样驱动我们的模型动起来呢。大家最熟悉的一种方式就是Key关键帧,比如大家建了一个肖翱的模型,要驱动我去运动,那自然是要把我绑定到骨骼上,对每个关节去打关键帧,比如把我的手十秒后挪到这里。但是呢,不是所有的动画都适合用关键帧来驱动,比如窗外雪花飘飘、一辆车跌落悬崖、瀑布飞流直下,这样的镜头如果用Key关键帧的方法去完成,那就不是Key我身上的几十个关节这么“容易”的事了。但这种物理现象往往是遵循物理规律的,我们想让他看起来真实,那么我们就可以用物理规律去驱动它运动;又或者是一个非自然的物理现象,我们也可以创造非自然的物理规律去驱动它运动。这样的动画方法我们称之为基于物理的动画,也称为物理模拟,也有人将模拟Simulation单独作为图形学的第四个方向。下面我们说到这两个词大家知道都是指同一个东西就行了。

那么基于物理的动画,在我们的电影中能做出什么样的效果呢,我们剪了一段经典影片中的Showreel给大家欣赏一下。然后我们将从发展历史、基本概念出发,介绍影视制作中的物理模拟制作流程、几种系统的算法原理与实现、展示一些我们自己制作的和经典影片中的基于物理的动画镜头,最后对物理模拟这项技术的未来再做一个分析和展望。

发展历史

1940年代和1950年代

基于物理的动画来源于计算机模拟技术。它的首次大规模开发是著名的曼哈顿计划中的一个重要部分。在第二次世界大战中,为了模拟核爆炸的过程,人们应用蒙特·卡罗方法用12个坚球模型进行了模拟。计算机模拟最初被作为其他的方面研究的补充,但当人们发现它的重要性之后,它便作为一门单独的课题被使用得相当广泛。 之后便逐渐应用于军事和制造业。但在很长一段时间内,计算机计算非常昂贵,通常只有军事会使用这项技术。

20世纪70年代和80年代初

计算机图像生成技术兴起,1972年,第一部计算机生成的动画《A Computer Animated Hand》诞生,其中的一部分在1976年的电影《未来世界》中出现。这是电影第一次使用计算机生成图像。1982年《星际迷航II:可汗之怒》中的“创世纪”片段被普遍认为是VFX和计算机图形学的里程碑。这个片段首次使用了粒子系统,用CG的形式表现了爆炸效果。它是SIGGRAPH军事研究和电影工业早期交叉的产物之一。

20世纪80年代初至90年代

20世纪80年代的技术进步使电脑比前几十年更便宜、功能更强,这促进了Xbox游戏等的兴起。1985年,任天堂发布了任天堂娱乐系统(NES),NES成为视频游戏史上最畅销的游戏机之一。20世纪90年代,随着模拟人生、命令与征服等游戏的发布,以及台式电脑的不断增强,电脑游戏变得越来越流行。

1993年,电影《侏罗纪公园》成为第一部广泛使用计算机生成图形的电影,将计算机模拟的模拟恐龙几乎无缝地融入到实景中,这一事件改变了电影业。1995年,《玩具总动员》是第一部只使用计算机生成图像的电影,1998年,《蚁哥正传》第一次在动画中使用流体模拟。到了21世纪,计算机生成图像成为电影特效的主要选择。

21世纪初至今

计算机图形学技术走向成熟,游戏和电影领域普遍使用基于物理的动画,在虚拟世界中模拟真实世界中物体之间的相互作用。

基本概念

讲完发展历史,我们要开始正式进入基于物理的动画的世界。我把影视制作中基于物理的动画的制作归结为:“在计算机系统中、建立一定的物理模型、模拟生成动画并渲染成画面”。那么我们就需要首先了解一些基本概念。

物理学的运动

在进入计算机之前,我们就需要把我们想要表现的画面、或者说想要模拟的现象,依据物理定律建构为物理模型。所以我们所有模拟首先要依赖于物理定律,由于目前影视制作的物理特效还很少涉及微观物理世界和超宏观物理世界(《蚁人2》、《星际穿越》这样的影片也仅仅是通过物理学家作为顾问来补齐一些“科幻设定”),所以我们使用的物理定律主要还是一般宏观视角的规律,如牛顿三大运动定律、各种守恒:

  • 牛顿运动定律
    • 第一定律 假若施加于某物体的外力为零,则该物体的运动速度不变(惯性定律)【力是改变物体运动状态的原因】
    • 第二定律 \(F = ma\) 【核心】
    • 第三定律 当两个物体相互作用于对方时,彼此施加于对方的力,其大小相等、方向相反(作用力与反作用力定律)
  • 三大守恒
    • 质量守恒
    • 动量守恒 \(\dfrac{d}{dt}mv=0\Rightarrow mv={\bf constant}\) 【来源自牛二定律】
    • 能量守恒 在力学模拟中常常体现为机械能守恒 \(\dfrac{1}{2}mv^2+mgh+\dfrac{1}{2}k\Delta x^2(\Delta x=\int adt)+\dots={\bf constant}\)

有了基本定律,我们就可以考虑要建构怎样的模型了。不同性质的物体,所形成的物理模型显然是不同的,典型的物体性质按材料分有刚体、软体、流体等等,针对不同的物体,我们有不同的物理模型,用各种系统去做模拟方法,第二节课我们就会说到其中一些代表性的模拟系统。

计算机的离散系统

计算机与真实的物理世界最大的不同在于离散与连续。真实世界是一个连续的世界,我手在空中划过,我可以任取无数个时间点、我的手所在的位置,我的手的运动轨迹上的每一个点都是存在的。而如果在计算机系统中,这就是不可能的,我的手在计算机中一定会有一个计算精度,导致大量的点是不存在的,我手的运动其实是一次次“瞬移”组合而成的。这种离散化体现在两个方面:空间上和时间上。

空间上的离散化

两种基本的观察视点

我们在观测一个物理现象时,一般有两种观察的方法:一种是盯着某个物体,观察物体的运动,视线随着物体走;一种是盯着某个区域,观察物体在这个区域的运动。到计算机中离散存储空间运动时,也需要用这两种观察方法:记录物体、把物体的状态信息存储在物体上,即拉格朗日视点;把空间网格化,记录某一位置是否有物体、物体的属性是什么,即欧拉视点(需要强调,这里的欧拉与前面的欧拉法解线性方程并不一样,我们伟大的数学、物理学家的名字可不能只用在一种地方啊)。

  • 拉格朗日视点
  • 欧拉视点
视效工作中常用的三种表达方法

我们再具体一点,在视效工作中,离散化一个物理系统通常有以下几种:

  • 粒子 Particle 粒子就是把物体作为一个个“质点”的组合,假设还是观察挥手这个动作,那么把我的手当成一群点组成的点集(大家可以理解为细胞?或者我手上的所有分子?),追溯每一个点的位置、速度、加速度,对每一个点去迭代。这是一个很典型的拉格朗日视点方法。
  • 物体网格 Mesh (粒子的复合体) 第二种大家应该是比较熟悉的。我们在雪松老师的建模课上、在MAYA中处理的大多数模型都是这种离散化方法。用一个个的面去组成我们的风车、无人机、甲壳虫,再如我的手。而我们建模课上,雪松老师无数次强调要用“四边面”来方便进一步细分曲面处理,但无论是四边面还是最终渲染管线中的三角面,都是由一个个的点组成的。我们在模拟迭代计算时,仍然考虑点的状态,因此这也是一种拉格朗日视点的方法。
  • 空间网格/体素 Grid/Voxel 现在大家考虑把我手的运动的这个区域框成一个空间,把这个空间网格化,这个过程可以类比二维情况下的像素化,我们称为“体素”,以1mm*1mm*1mm的立方体作为一个体素来描述这个空间。我的手从左到右挥过这个空间,首先是左边的空间有物体存在,然后中间,最后右边。我们记录每一个体素上是否有物体、物体的运动速度、加速度等信息,来迭代。这种方法就是欧拉视点的方法了。

在后面我们的具体方法介绍中,大多数都使用的拉格朗日视点的方法,到流体部分会涉及到欧拉视点和两种视点混合的新型方法。

时间上的离散化

时间维度上,我们用“时间步”的概念来离散化我们的物理模型,每一次需要计算的“点”称为一个时间步。假定我们的时间步长是1/24s,那么我们就会对相应物理模型每1/24s做一次计算(这个1/24s是物理模型的1/24s,不是我计算花的时间,事实上计算一个时间步所花的时间一般要比时间步长长得多),例如我的手花了1s挥过,那么我只计算其中的24个点、我的手位于什么位置,最终组合成一个动画。

而离散化的多种方法主要是来源于考虑基于“何时”的状态来做下一步的计算。我们要计算当前时刻物体的位置,即上一个已知位置之后发生的位移,那么我们理应得到速度发生的变化,对其积分得到总的位置,但现在我们只知道上一个时间步的位置和速度,那么显而易见的,我们可以直接用上一个时间步的参数来计算——这就是我们所谓的显式时间积分;但显式时间积分很容易出问题:容易发生发散、不收敛的现象,导致数值爆炸,但如果我们硬要用当前时间步的状态,数值就稳定了,但我们的当前状态是“隐藏的”——因此要称为隐式时间积分

  • 显式时间积分
    • 前向欧拉 \(v_{t+1}=v_t+a_t\Delta t \\ x_{t+1}=x_t+v_t\Delta t\) 这就是完全使用前一时间步的速度、加速度来计算
    • 半隐式欧拉 \(v_{t+1}=v_t+a_t\Delta t \\ x_{t+1}=x_t+v_{t+1}\Delta t\) 这里,我们先算出了当前时间步的速度,这样我们就可以用当前时间步的速度来计算了,称之为“半隐式”是因为速度这个参数确实是隐藏的,但其确实是通过前一个时间步的加速度“顺着”算出来的,本质上仍然是一个明显的量,所以本质上还是显示的时间积分方法。那么什么样是“不明显的”呢,我们接着看。
  • 隐式时间积分
    • 后向欧拉 \(v_{t+1}=v_t+a_{t+1}\Delta t \\ x_{t+1}=x_t+v_{t+1}\Delta t\) 可以看到我们这里把加速度也换成当前时间步的加速度了,除了上一时间步的位置作为初值,不再有使用前一时间步的任何状态参数,那么怎么求解呢?我们把这个公式替换、变形、泰勒展开,最终得到了 \([{\bf I}-\Delta t^2 {\bf M}^{-1}\dfrac{\partial f(x_t)}{\partial x}]v_{t+1}=v_t+\Delta t{\bf M}^{-1}{\bf f}(x_t)\) ,形如 \(Ax=b\) 的一个线性方程:至于怎么解线性方程,大家大一是学过其中的数值解法的,也即Gauss消元、三角分解这些,但这些方法在解这样庞大、复杂的方程显得无能为力。因此我们引入迭代法去求解,也即再把式子做一些变形,得到一个满足迭代条件的结构,任给其一个初值,去不断重复计算,来逼近真实的解——迭代次数越多,越精准。经典的迭代方法有牛顿迭代法、Jacobi迭代法、共轭梯度法等等。这里就不再展开了。

有了这些基本概念,我们终于可以进入到具体的基于物理的动画的介绍中了。接下来,我们会轻松一会,远离数理概念一段时间,介绍在一个电影制作流程中、一家影视视效公司里,基于物理的动画、或者说物理模拟工作的制作流程、分工。然后我们会就粒子系统、刚体系统、流体系统三种物理模拟系统来给大家介绍一些物理模拟的基本算法与效果。