
动画
动画入门
- 让物体活过来
- 将场景中的模型放在时间维度上去展示
- 电影: 每秒24帧
- 视频: 每秒30帧
- 虚拟现实: 每秒90帧
动画的历史关键时期
- 壁画
- 圆盘
- 科研用电影
- 手绘剧场版
- 早期计算机动画
- 侏罗纪公园: 恐龙由电脑生成动画
- 玩具总动员: 整个由电脑生成
- 2009年
- 2019年
关键帧动画
- 艺术家绘制关键帧,计算机生成插值
- 插值不一定是线性,有可能是曲线
物理模拟
- 牛顿定律: F = ma
- 基于物理的动画: 抛物线,衣服摆动
质点弹簧系统
- 是一系列连接的质点和弹簧
- a点受到往b方向的力: Fa->b = ks(b-a),Fb->a = -Fa->b,ks为弹簧系数(胡克定律)
- 正常弹簧不可能没有长度,假设弹簧完全松弛的长度为l,则Fa->b = ks(b-a)*(|b-a|-l)/(|b-a|)
- 存在的问题: 由于能量守恒,会永远的运动下去,加入摩擦力即可
- 物理模拟中常用记法,如果x表示位置,则x上加一个点,则表示速度,加2个点则表示加速度
- 假设b表示物体的位置,b'表示速度向量,则摩擦力 f = -kd * b',kd为摩擦系数
- 存在的问题: 会减慢所有的运动,如果弹簧两个点从高空落下,则会越落越慢,表示不了弹簧内部的摩擦力
- 弹簧内部的摩擦力一定是让弹簧回归松弛状态的,如果b的速度要比a速度快,则b上的摩擦力一定越大
- 另外由于速度的方向并不一定都是沿着ab方向,所以计算b和a的相对速度的时候,再与ba单位向量做一次点积,可以得到相对速度在ba方向上的投影向量长度,再与ba单位向量相乘,可得投影向量,该向量即是与摩擦力相关
- 考虑弹簧上的b点的摩擦力: fb = -kd * ((b - a) / |b - a|) * (b' - a') * ((b - a) / |b - a|),fb最终表示的是一个与ba相对速度相反的向量
- 摩擦力与弹簧长度无关
- 布料模拟,存在的问题,以及解决方案:
- 布料对角线拉伸是不会发生切变的: 给对角线的两个点连线,该线也计算为弹簧
- 布料不能被折叠: 给相隔的水平或者垂直的两点连线,该线也计算为弹簧,但弹性系数较小
- 有限元方法FEM: 用于车子碰撞
粒子系统
- 大量例子的合集,给每一个粒子定义一个力
- 粒子越多,渲染越慢,但越精细
- 粒子越少,渲染越快
- 可以模拟雾,烟尘,流体
- 粒子与粒子之间可能有斥力也有引力
- 算法:
- 如果需要,创建新粒子
- 计算每一个粒子的作用力
- 更新每个粒子的位置和速度
- 如果需要,移除死去的粒子
- 渲染粒子
- 粒子之间的作用力:
- 引力: 电磁力,弹簧力,排斥力
- 摩擦力: 粘滞力,空气阻力
- 碰撞: 跟墙,容器碰撞,角色身体不能穿模
- 万有引力: FG = G * m1m2/d^2
- 鸟群模拟:
- 每个个体都是往群体聚集
- 个体与个体之间存在最小距离,可以理解为斥力
- 每个个体一定是往一个大部队的方向飞
运动学
- 骨骼类型:
- pin: 1D,骨骼被钉在某个点,只能在平面内旋转
- ball: 2D,可以在一个球内旋转
- prismatic joint: 不仅可以旋转,还可以移动
- 调整各个骨骼的旋转角度,计算尖端位置
逆运动学
- 调整尖端的位置,自动计算出各个骨骼的旋转角度
- 存在的问题: 有可能有多个解,也可能无解
Rigging
- 类似木偶操纵,提线来控制动作和造型
Blend Shapes
- 定义关键帧,使用插值来做动画
动作捕捉
- 可以得到大量的真实数据
- 准备起来麻烦
- 数据是否可用
- 常用的还是身上贴一些标记,如小球,贴片之类的,通过多角度摄像机来捕获
- 恐怖谷效应
动画生产流水线
- pre-production:
- 有个想法
- 描述story
- 原画师画几幅关键的图
- 播放原画幻灯片
- 设计师设计具体场景
- production:
- 场景布置
- 建模
- 纹理材质
- rigging
- 做成动画
- 准备光照,VFX
- 渲染
- post-production:
- 场景组合
- 2D VFX
- 调色修复细节问题
- final output
单一粒子模拟
- 速度场: v(x, t),在任意时间任一点的速度函数
- 常微分方程: 单变量的微分方程,dx/dt = x' = v(x, t),已知速度,反推任意时刻的位置
- 欧拉方法:
- 所有的量都用上一帧的,估计下一帧的值
- x[t+dt] = x[t] + dt * x'[t]
- x'[t+dt] = x'[t] + dt * x''[t]
- 误差: dt越小误差越小
- 不稳定性: 稳定性上会出问题,迅速变得不稳定,在圆形速度场中,位置会越来越偏离圆心
- 中点法,修正欧拉方法
- 先用欧拉方法计算dt之后的目标点a的位置
- 取中点b: x[mid] = x[t] + dt/2 * v(x[t], t)
- 用中点b的速度来更新位置: x[t+dt] = x[t] + dt * v(x[mid], t)
- 自适应改变步长的方法
- 先用欧拉方法计算dt之后的目标点a的位置
- 取中点b,再从b计算dt/2之后的目标点c的位置
- 如果a和c距离足够近,则dt可行,如果很远,则缩减dt的一半循环一次
- 隐式欧拉方法
- 以未来的速度和加速度来计算
- x[t+dt] = x[t] + dt * x'[t+dt]
- x'[t+dt] = x[t] + dt * x''[t+dt]
- 只有已知未来的加速度的时候才能解出来
- 如果是非线性变化,也不好解
- 提供了非常好的稳定性
- 如何决定稳定性: 计算每一步的误差和整体误差来衡量,整体误差与每一步误差的阶数,隐式方法阶数为1
- 每一步误差为O(h^2),整体误差为O(h)
- h代表dt,如果dt变为一半,则隐式方法的整体误差也减小一半
- 阶数越高,越稳定
- 龙格库塔方法: 一系列方法非常擅长解ODE的,特别是对于非线性的情况,有一个4阶的方法应用非常广,简称RK4
- 初始条件: dy/dt = f(t,y), y(t0) = y0
- y(n+1) = yn + h*(k1 + 2k2 + 2k3 + k4)/6
- k1 = f(tn,yn)
- k2 = f(tn + h/2, yn + k1 * h/2)
- k3 = f(tn + h/2, yn + k2 * h/2)
- k4 = f(tn + h, yn + k3 * h)
- 《数值分析》了解更多
- 基于位置的方法: 不需要经过物理模拟,直接调节位置,快速简单,无法保证能量守恒
刚体的模拟
- d(x, a, x', w)/dt = (x', w, F/m, w/dt),其中x为位置,对位置求导是速度,其中a为转动角度,对转动角度求导为角速度,其中x'为速度,对速度求导为加速度,其中w为角速度,对角速度求导为角加速度
流体模拟
- 假设水体是有大量的不可压缩的刚体小球组成的
- 假设水在任何时刻任何位置都不可被压缩,即密度不变
- 因此,任何位置密度发生变化,我们需要调整粒子的位置来修正密度
- 我们需要知道任意粒子所在的位置的密度
- 梯度下降法
- 一般不会停下来,实际过程中会增加能量衰减来让流体停下来
欧拉方法 vs 拉格朗日方法
- 两种不同的视角来模拟大量的粒子: 模拟小鸟移动
- 质点法(拉格朗日方法): 盯着每一只小鸟,正确模拟每一只小鸟在dt时间的位置
- 网格法(欧拉方法): 将空间分成网格,盯着每一个网格随着dt时间的变化
- 混合方法: 模拟物体融化
- 首先认为每个粒子都携带材质属性
- 在空间划分格子,每个格子记录粒子的变化
- 把格子里面的信息写回粒子上