Skip to content

games101 八、动画

关键帧动画

先准备几个关键帧,计算机根据这些关键帧自动生成中间帧,这些中间帧的生成过程称为插值(interpolation)。

物理仿真

Physical Simulation

物理仿真是通过物理定律来模拟物体的运动,比如重力、碰撞、流体等。

质点弹簧系统

理想弹簧系统

particle-spring-system.png

\[ f_{a\to b}=k_s(b-a) \]
\[ f_{b\to a}=-f_{a\to b} \]

\(f_{a\to b}\) 表示 a 点受到的向 b 点方向的力,\(a\)\(b\) 是两个向量,分别代表两个点的位置。

理想的弹簧长度为 0,它被拉伸多长,就产生多大的力来拉回去。

\(k_s\) 为劲度系数,根据胡克定律,弹簧的劲度系数越大,弹簧越难被拉伸。

一般弹簧系统

\[ f_{a\to b}=k_s\frac{b-a}{\|b-a\|}\left(\|b-a\|-l\right) \]

l 表示弹簧的自然长度。

物理仿真中的微分表示

物理仿真中一般是在字母上方加一个点来表示微分,例如,\(x\)\(\dot{x}\)\(\ddot{x}\) 分别表示位置、速度、加速度。

阻尼弹簧系统

给弹簧引入一个内部阻尼:

\[ f_b=-k_d\frac{b-a}{\|b-a\|}(\dot{b}-\dot{a})\cdot\frac{b-a}{\|b-a\|} \]

其中,\(k_d\) 为阻尼系数,\(\frac{b-a}{\|b-a\|}(\dot{b}-\dot{a})\) 是个标量,它是 ab 方向的单位向量和 a 和 b 的相对速度的点积,表示 a 和 b 之间的相对速度在 ab 方向上的分量。

用质点弹簧系统做物理模拟

structure-of-springs.png

由最简单的质点弹簧系统可以组成更复杂的结构,可以用这样的结构去模拟布料、毛发等物体的运动。

其他方法:有限元方法(Finite Element Method,FEM)

有限元方法是一种数值方法,也可以用于物理仿真中。

粒子系统

Particle System.

要生成一帧粒子动画:

  1. 生成一些粒子。
  2. 计算粒子之间的作用力(引力和斥力、阻力、碰撞等)。
  3. 根据作用力更新粒子的位置和速度。
  4. 移除死亡粒子。
  5. 渲染粒子。

粒子并不一定是一个微粒,如果我们一堆粒子看做一个鸟群,那么每个粒子就代表一只鸟,这时粒子系统就可以用来模拟鸟群的运动了。

运动学

正运动学(Forward Kinematics, FK)和逆运动学(Inverse Kinematics, IK)。

关节骨骼(Articulated Skeleton)是由多个关节组成的结构,每个关节都有一个旋转轴和一个旋转角度,关节之间通过父子关系连接起来,形成一个树状结构。

有三种不同的关节(Joint)类型:

  • Pin:可以在一个平面内旋转。
  • Ball:可以在球面上旋转。
  • Prismatic:可以位移。

运动学研究的是如何根据关节的旋转角度来计算出骨骼的姿态,这就是正运动学;逆运动学则是根据骨骼的姿态来计算出关节的旋转角度。

逆运动学有很多解甚至无解,求解逆运动学实际上是个优化问题,可以通过数值方法来求解。

绑定

Rigging.

为了让物体能够像动画一样运行和变形,需要给物体搭建一套控制系统,这个过程叫做绑定(Rigging)。

blend shape 是一种常用的绑定方法,它通过在物体上添加一些控制点来控制物体的变形,这些控制点有点类似动画的关键帧,可以以这些控制点为基准,通过插值来得到其他点的位置,从而实现物体的变形。

动作捕捉

Motion Capture.

动作捕捉相当于把控制点绑定到真人上,然后将控制点的运动映射到虚拟角色上,这样就可以让虚拟角色的运动和真人的运动一致了。

粒子模拟

单个粒子模拟

假设一个粒子位于一个速度场 \(v(x, t)\) 中。

粒子的位置、时间和速度可以写成一个常微分方程(Ordinary Differential Equation,ODE):

\[ \frac{dx}{dt} = \dot{x} = v(x, t) \]

已知速度场和起始位置 \(x_0\),求粒子在任意时刻 \(t\) 的位置 \(x\)

欧拉方法(Euler Method)是一种数值方法,可以用来求解这个常微分方程:

\[ x^{t+\Delta t}=x^t+\Delta t\,\dot{x}^t \]
\[ \dot{x}^{t+\Delta t}=\dot{x}^t+\Delta t\,\ddot{x}^t \]

即,下一个时刻的位置和速度都通过上一时刻的位置和速度来计算得到。

欧拉方法存在一定误差,\(\Delta t\) 越小,误差越小。

欧拉方法的问题是不稳定,模拟的结果可能完全失真(diverge)。

有很多解决不稳定的方法。

中点法(Midpoint Method):

先用欧拉方法计算下一时刻的位置,然后取当前时刻和下一时刻位置中点的速度,然后用这个速度重新计算下一时刻的位置。

自适应步长(Adaptive Time Step):

根据模拟的情况动态调整 \(\Delta t\) 的大小,当模拟比较稳定时,\(\Delta t\) 可以较大;当模拟比较不稳定时,\(\Delta t\) 需要较小。如何判断模拟是否稳定呢?可以用较大的 \(\Delta t\) 和较小的 \(\Delta t\) 分别计算下一时刻的位置,如果两者的结果相差较大,那么就说明模拟不稳定,比如,先用较大的 \(\Delta t\) 计算一次,再用减半的 \(\Delta t\) 连续计算两次,将得到的位置进行比较。

隐式欧拉方法(Implicit Euler Method):

也叫后向欧拉方法(Backward Euler Method),它使用下一时刻的速度和加速度来计算下一时刻的位置:

\[ x^{t+\Delta t}=x^t+\Delta t\,\dot{x}^{t+\Delta t} \]
\[ \dot{x}^{t+\Delta t}=\dot{x}^t+\Delta t\,\ddot{x}^{t+\Delta t} \]

需要解一个非线性方程组,解起来比较麻烦,但它是稳定的。

稳定性是用整体稳定性和局部稳定性(每一步的误差)来衡量的,一般会把稳定性描述为步长的函数,比如隐式欧拉方法的局部稳定性和整体稳定性分别为 \(O(h^2)\)\(O(h)\)\(h\) 是步长,隐式欧拉方法是 1 阶方法,因为它的整体稳定性是 1 阶的。

我们通常希望方法的阶数越高越好,因为阶数越高,误差越小,降低步长时误差会更快地降低。

龙格-库塔方法(Runge-Kutta Method,RK),它是一类方法,使用最广泛的是一个四阶方法(RK4)。

初始条件(\(f\) 相当于是速度场,\(y\) 相当于是位置):

\[ \frac{dy}{dt}=f(t,y),\quad y(t_0)=y_0. \]

RK4 的计算过程:

\[ y_{n+1}=y_n+\frac{h}{6}(k_1+2k_2+2k_3+k_4)\\ t_{n+1}=t_n+h \]
\[ k_1=f(t_n,y_n)\\ k_2=f\left(t_n+\frac{h}{2},y_n+\frac{h}{2}k_1\right)\\ k_3=f\left(t_n+\frac{h}{2},y_n+\frac{h}{2}k_2\right)\\ k_4=f(t_n+h,y_n+hk_3) \]

刚体模拟

Rigid Body Simulation.

刚体模拟实际上就是对粒子模拟的扩展。

\[ \frac{d}{dt} \begin{pmatrix} X \\ \theta \\ \dot{X} \\ \omega \end{pmatrix} = \begin{pmatrix} \dot{X} \\ \omega \\ F/M \\ \Gamma/I \end{pmatrix} \]
X : 位置(positions)
θ : 旋转角度(rotation angle)
ω : 角速度(angular velocity)
F : 力(forces)
Γ : 力矩(torque)
I : 转动惯量(moment of inertia)

流体模拟

Fluid Simulation.

基于位置的方法(Position Based Method)

这个方法把整个水体看做由一个个刚体小球组成,把这些小球的位置模拟出来,就能得到整个水体。

如果发现水体的密度变了,就说明水体发生了变形,根据水体的密度变化来调整小球的位置,把水体的密度修正回去,这样就能模拟出水体的运动了。

修正密度采用的是梯度下降的方法,计算每个小球的密度,根据密度的误差来调整小球的位置,直到密度误差足够小。

两种物理模拟的思路:

质点法(拉格朗日方法,Lagrangian Method):比如,把水体看做由一个个小球组成,只要把每个小球的运动模拟正确,水体也就模拟出来了。

网格法(欧拉方法,Eulerian Method):把空间划分成一个网格,把每个格子内的运动模拟好,就能模拟出整个水体了。

Material Point Method(MPM)方法:结合了质点法和网格法,既能模拟出水体的运动,又能保持水体的连续性。