第二十二章:动画和仿真
动画和仿真
上节课主要说到了模拟各种运动的各种知识,比如定义一个物体的速度、加速度,就自然能算出来物体在某个时刻出现在某个位置。
这节课从上节课的概念出发,说一下具体的解法,怎么计算物体在不同时间出现的位置。
本节课的主要内容:
单粒子模拟
欧拉方法
解决不稳定的提高的若干办法
刚体模拟
流体模拟
单粒子模拟
模拟物体的运动即规定一个物体在任何时刻的速度,同时知道开始出现的位置,就求解在某个时间后物体出现在哪里。
如果是匀速的,在 t0 时刻出现在某个位置,在 t1 时刻出现的位置即为 t0 的位置加上速度乘时间。
但大多数时候没有这么简单,比如要模拟一个粒子在速度场中的运动。
速度场和光场、磁场类似,表示空间中速度的分布。任意一个粒子的运动可以由一个速度场决定,该速度场是位置和时间的函数。
先从简单的出发,研究一个粒子的运动,后面再提高到很多粒子去考虑。
求解一个例子的速度即求解一个一阶常微分方程:
一阶表示知道一个量的微分是多少,希望推出这个量是多少
常微分方程表示不存在对其他变量的微分(对应于偏微分可能存在对多个变量的微分)
求解这个常微分方程,给定粒子的初始位置 x₀,用积分求解这个粒子在时间 t 的位置,得到粒子的运动轨迹。
怎么求解?可以把时间细分成很多小块,计算每个小块(比如时间 t+ 步长 Δt)粒子的位置的变化,在时间上做离散。
欧拉方法(a.k.a. 前向欧拉、显式欧拉)
下一帧的位置是上一帧的位置加 Δt 乘速度,下一帧的速度是上一帧的速度加 Δt 乘加速度
始终都是用上一时刻的量计算下一时刻的量(也可以用计算出来的下一时刻的量计算下一时刻的量,比如用计算出来的下一时刻的速度来计算下一时刻的位置,但这种方法就不是欧拉方法)
欧拉方法的问题:
不准确,且稳定性上会出问题,迅速地变得不稳定。
对于不准确的问题:步长分的越细,就模拟得越精确。
对于稳定性的问题:
如果速度场是螺旋形的,任何时刻都有一个和位置方向垂直的速度,物体应该是按照圆周运动来运动的。但用欧拉方法无论取多大的步长,无论如何得到的线都不可能沿着这个螺旋形走,最后都会飞出去。
如果是下面这幅图的情况下,正常的运动是从左到右走到中间那条线上,但是欧拉方法 Δt 的会让运动轨迹上下震荡走越偏越远。
这种情况在信号处理上被称为正反馈,即一旦出现问题,这个问题会被无限放大。
误差和不稳定性
一些用数值微分方法解决的问题都会遇到这些问题:
误差
- 每一步计算都会有误差,最后累加起来会变成更大的误差。但是可以通过用更小的步长降低误差
- 误差在图形学应用中影响大,因为主要关注看起来效果怎么样,不要求物理上的完全一致
不稳定
- 有任何一个模拟方法,不管怎么去模拟最后得到的结果都会和正确的结果差的很远,且越来越发散
- 不稳定是模拟中一种不能被忽视的非常基础的问题
解决不稳定性的方法
中点法
自适应改变步长
隐式方法
不基于物理的方法,Verlet 积分
中点法
假设有一个点用欧拉方法模拟经过 Δt 从原始点到 a 点,取原始点到 a 点的中点 b 点,再回到原始点,应用 b 点的速度重新算一遍欧拉方法,达到 c 点,这样计算出来的结果就会比欧拉方法更准确。
中点法之所以更准确,是因为中点法比欧拉方法多出了一个二次项,得到了一个类似抛物线的运动轨迹。原本欧拉方法是一个局部线性的估计模型,中点法算出了一个局部的二次模型。
Adaptive Step Size
应用两次 Δt/2 和应用一次 Δt 的结果进行比较,如果应用两次 Δt/2 计算的结果更准确,则把时间拆分得更短一点。
隐式欧拉方法
隐式欧拉又叫做后向欧拉。
用下一帧的速度,下一帧的加速度去乘 Δt,解一个方程组。如果速度和加速度不是简单的按照线性方法叠加,这个方程就不是很好解。
假设当前位置知道,下一个时刻的加速度也知道,就可以解出来下一个时刻的位置和下一个时刻的速度。
- 可以用一些数值优化求根算法,比如牛顿方法
- 有非常好的稳定性
怎么定义一个方法是不是稳定的
用局部截断误差( 每一步会产生的误差)和最后累积起来误差来衡量稳定性
研究这两个数字没有意义,应该研究他们的阶。即研究这两个数字和取的 Δt 的关系,误差是如何随着更小的 Δt 减小的
隐式的欧拉方法是一阶的,即:
- 局部的误差是 O(h2)的
- 全局的误差是 O(h)的
h 表示步长(即 Δt),h 越小,误差越小。O(h)表示:
- 如果把 h 减小一半,得到的误差也会减小到一半。阶数越高越好,如果是 2 阶的,假如 h 减少一半,那误差就会减少到 1/4。
Runge-Kutta 方法
一类用于解决常微分方程的解法
- 特别擅长解非线性常微分方程
- 有一个用得特别广泛的方法,叫做 RK4,是一个四阶的解法。
y 相当于位置,h 相当于 Δt,k 相当于速度场在不同的位置和不同时间的值(相当于一个扩展的中点法)
更多的数值计算方法可以看数值分析的课程
Position-Based/Verlet Integration
不是基于物理的方法,主要做法是:
通过调整粒子的不同位置,使得结果能满足某一种限制,来防止出现发散的不稳定的行为。
使用约束的位置来计算速度。
这些方法都会消耗能量,稳定性好。
优缺点:
- 速度很快
- 不能保证能量守恒
例子:比如说一个弹簧,被拉开后立刻回到原点,即被拉开后,会立刻调整两个端点的位置使得他们回到原点。这个是不符合真实物理的,是通过一种非物理的简化方式直接改变位置。
刚体模拟
不会发生形变,让内部所有点按同一种方式运动,就类似于一个粒子的运动
只是刚体要考虑更多的属性,比如:刚体的位置、朝向(旋转角度)、速度、角速度
torque:扭矩; I:转动惯量
用欧拉方法或者其他数值方法,可以求出任何一个时间 t 之后刚体对应的位置和旋转。
流体模拟
position-based 方法的例子:通过模拟形成整个水体的小球的位置来模拟浪花的运动
首先认为整个水体是由不可压缩的刚体(小球)组成,只要能模拟出小球的位置就能模拟出浪的运动(模拟和渲染是分开的)
假设水在任何地方都是不会被压缩的,即在任何时刻任何位置的密度都是一样的
给任何一个时刻小球分布的位置,都可以知道任何一个地方的密度。如果有任何一个地方的密度和之前平静的水不一样的情况,就需要把这个密度修正过来。通过移动小球的位置来进行修正。
要做这个修正需要知道任何一个点的密度对所有小球的位置的梯度是多少。一个点的密度会受到周围小球的位置的影响,任何一个点的密度都是任何一个其他小球的位置的函数。
任何一个位置,要让不正确的密度变成正确的密度,且知道如何调整各个小球的位置使其密度朝向正确的方向去。这个过程就是梯度下降的过程。
这个修正会导致停不下来,所以实际模拟过程中会考虑能量损失。
在物理模拟中模拟大规模的物质用到两个不同思路:
质点法:模拟水,认为水是由很多小水滴组成,逐个模拟,最后得到的结果就是正确的。这种方式被称为拉格朗日方法(也叫质点法)
欧拉方法:和常微分方程的欧拉方法不是一回事。这里是指如何看待模拟一系列大规模的物体,把整个空间分成不同的网格,考虑网格随着不同的时间怎么变化。
Material Point Method(物质点方法)
混合型的方法,即考虑拉格朗日,又考虑欧拉方法。
- 认为不同的粒子都具有材质属性
- 用格子模拟融化的过程,把信息都记录在格子上
- 再把格子里的信息写回粒子上
下面怎么深入学习:
《realtime rendering》、微分几何、离散几何、《games201》
广告:
《高质量实时渲染》
https://www.bilibili.com/video/BV1YK4y1T7yY/?spm_id_from=333.337.search-card.all.click&vd_source=d6c15f5bd49b1cdbb4227e5dc29a5666
离线渲染《高级图像合成》