Chapter 1 绪论
什么是动画:视觉暂留效应
关于视觉暂留原理:
- 人眼看到一幅画面或一个物体后,大约在 0.05~0.1 秒内不会消失。
 - 利用这个原理,在前一幅画面还没消失前播放下一画面,可使人形成流畅的视觉变化感觉
 
常见帧率:电影播放 24fps;电视 25fps。因此需降低制作成本,可采取的操作:一拍二(即两帧重复同一画面);一拍三(日本动画)
动画的发展与分类
按技术原理分,动画可分为:
- 关键帧动画
 - 路径动画
 - 变形动画
 - 角色动画
 - 动力学动画
 
动画12原则
- 挤压与拉伸(squash and stretch):形变现象,指的是物体变长或变宽(延展与拉伸),通过夸大自然界中物理现象,用来强调物体的质感和重量。
 - 预备动作(Anticipantion):当一个角色为下一个动作做准备时,加入一个反向的动作
- 以加强正向动作张力
 - 有助于为观众准备将要发生的事情,它具有使对象的动作更逼真的效果
 - 有时起到意料之外的效果
 
 - 演出布局设计(Staging):动画中所有动作、时间、构图、运镜、走位都需要仔细的设计安排,避免在同一时间又过多琐碎的动作与变化.
- 控制观众视线
 - 避免同时发生多个动作
 
 - 连贯动作法和关键动作法
- 连贯动作法(顺画法、直线前进动画):以清晰的思路依次设计着每一个动作,直到完成最后一个动作为止。
 - 关键动作法(定点画法、原动画法、关键帧动画):设计师设计主要动作的开始和结束,助理设计师完成过渡帧动画
 
 - 跟随动作与重叠动作:
- “跟随动作”指的是身体静止后身体部件由于惯性还在继续运动;
 - “重叠动作”指的是主体和其他部件的时间错开,产生了重叠效果。
 
 - 渐入与渐出(Slow in,slow out):几乎所有运动都是缓慢开始,之后加速,最后缓慢结束
 - 弧线运动(Arcs):大部分的自然动作趋向于跟随拱形轨迹
 - 次要动作/附属动作(Secondary Action):当角色进行主要动作时,附属于角色的部分,例如触须、尾巴等,会以附属动作来点缀主要动作的效果。
 - 时间控制(Timing)
 - 夸张(Exaggeration):夸张的程度取决于动画追求的效果
 - 扎实绘图(Solid drawing)
 - 吸引力(Appeal)
 
Chapter 2 数学与图形表示
坐标系统
- 空间直角坐标系(x,y,z)
 - 笛卡尔坐标系(包括直角坐标系和斜坐标系)
 - 极坐标系(r,θ)
 - 柱坐标系(r,θ,h )
 - 球坐标系(r,θ,φ )
 
左手系/右手系
左手坐标系:让左手拇指指向x轴的正方向,食指指向y轴的正方向,如果中指能指向z轴的正方向,则为左手直角坐标系。反之则是右手直角坐标系.
不存在对应的旋转操作可将左手轴坐标系统转换为右手轴坐标系统

局部/世界坐标系
对象空间是一种局部坐标系,相关数据围绕其原点建立,且通常位于某一标准范围内,如[-1,1]。
世界空间内,对象被组合并生成可见的场景环境。
相机坐标系
观察参数包括位置和方向数据。观察位置也称作相机位置或眼睛位置。方向由视见方向和up向量确定。

向量运算
基础的不说了.
向量叉积:垂直于v1和v2向量构成平面的法向量

向量运算的几种几何应用
Q.如何计算一个向量方向?
A:标准化矢量:单位向量、或法线
Q.如何估算两个方向的相似程度?
A:方向相似性/余弦相似性.利用两个矢量的点积(点乘、内积).两个矢量的“相似”程度:结果越大,越相近
- 当度,有, V1与V2垂直。
 - 当度,有
 
Q.如何计算一个向量在另一个方向的投影?
A:
Q.给定一个三角形,如何判断其法线方向?
A:选择一个顶点,计算其与相邻顶点的向量,取这两个向量的叉积
Q.给定一个三角形的三点坐标,如何计算其面积?
A:S=|V1×V2|/2

同理,拓展到多边形中:
其中×表示向量的叉积运算,表示第i个顶点,表示第i+1个顶点,n表示多边形的边数.
矩阵运算
矩阵运算主要用来描述两个坐标系统之间的关系。通过定义一种运算而将一个坐标系中的矢量转换到另一个坐标系。
对角矩阵:对角线上的元素不为零,其余元素为零的矩阵。
单位矩阵:对角线上的元素为 1,其余元素为零的矩阵。
矩阵的逆:对于一个 n 阶方阵 A,如果存在一个 n 阶方阵 B,使得 AB=BA=E,则称 A 是可逆的,B 是 A 的逆矩阵,记作。其中E表示单位矩阵。
正交矩阵:如果一个矩阵 A 满足 ,则称 A 是正交矩阵。
正交矩阵的几何意义:正交矩阵的行(列)向量是单位向量,且两两正交。给出一个正交矩阵 AA,则 AA 的行(列)向量构成了一个正交基.
几何变换(仿射变换的计算)
绕x轴旋转:
绕y轴旋转:
绕z轴旋转:
缩放(以原点为中心):
Q.已知点A(1, 0), B(0, 0), C(0, 1)在仿射变换T下变为A’(2, 2), B’(1, 1), C’(2, 1)
(1) 写出仿射变换T的表达式 (2) 计算D(1, 2)在仿射变换(Affine Transformation)以后映射到的点D’的坐标
A:列方程求解仿射矩阵.
Q.求四边形 ABCD 绕 P(5,4)旋转 45°的变换矩阵和端点坐标,四边形四个顶点坐标分别为:A(4,1),B(7,3),C(7,7),D(1,4)画出变换后的图形。
A:将点P(5,4)平移到原点(0,0)→绕原点(0,0)旋转45度→将原点(0,0)平移回(5,4),接下来按顺序执行这三个变换:
颜色模型
RGB
RGB颜色模型通常用于彩色阴极射线管等彩色光栅图形显示设备中,它采用三维直角坐标系,红、绿、蓝为原色,各个原色混合在一起可以产生复合色.

CMYK
以红、绿、蓝的补色**青(Cyan)、洋红(Magenta)、黄(Yellow)**为原色构成的CMYK颜色模型,常用于从白光中滤去某种颜色,又被称为减性原色系统。


洋红色加黄色会形成红色;洋红色加青色形成蓝色;青色加黄色形成绿色。理论上只用上述三种颜色相加就可以形成包含黑色在内101³共1,030,301色(0~100%模式),但实际印刷时,料本身并非真正纯色,三色等量相加之后只能形成一种类黑色,由于色而非黑色;实际偏色程度依不同厂牌色料配方而有不同差异。
RGB到CMYK的转换:
转换公式 K = min((255-R),(255-G),(255-B)); C = 255- R –K; M = 255 - G –K; Y = 255 -B – K。
HSV
HSV(Hue,Saturation, Value)颜色模型是面向用户的,该模型对应于圆柱坐标系的一个圆锥形子集
HSV颜色模型对应于画家的配色的方法。画家用改变色浓(饱和度)和色深(亮度)的方法来从某种纯色获得不同色调的颜色。
其做法是:在一种纯色中加入白色以改变色浓,加入黑色以改变色深,同时加入不同比例的白色,黑色即可得到不同色调的颜色


RGB 到 HSV 的转换
Chapter 3 路径动画
路径动画定义
路径动画是一种动画技术,用于为一个在场景中沿着既定路径移动的对象设置动画
旋转变换动画的离散计算方案
假设月球绕z轴旋转,可以用旋转矩阵计算月球表面的点随时间的变化 假设:每次循环沿逆时针旋转∆θ=5°
- 
方案1:使用了基于delta值的z轴转换矩阵作用于月球的各个顶点上。其中,各delta值表示一帧内移动的角度值(步进)

 - 
方案2:不断调整转换矩阵, 并使对象空间顶点转换至世界空间位置。

 - 
将向累积角变量添加delta值, 且根据角参数构造z轴旋转矩阵,并于随后 与x轴转换矩阵执行乘法操作,结果矩阵将作用于对象空间内的原月球顶点上

 
方位描述
方位(Orientation):描述物体的朝向..方位是通过相对已知方位的旋转来描述的。旋转的量称为角位移。即,在数学上描述方位就等价于描述角位移.
矩阵形式
描述坐标系中方位的一种方法就是列出这个坐标系的基向量,这些基向量使用其他坐标系来描述。
用这些基向量构成一个3×3矩阵,然后就能用矩阵形式来描述方位;换句话说,能用一个旋转矩阵来描述这两个坐标系之间的相对方位。这个旋转矩阵用于把一个坐标系中的向量转换到另外一个坐标系中。
方位是使用矩阵来描述的,矩阵表示的是旋转后的基向量。其是通过描述一个坐标系到另一个坐标系的旋转来确定一个方位。
优点:
- 被图形 API 广泛支持。图形 API 使用矩阵来描述角位移;但若选择了非矩阵形式来描述,必须在渲染管道的某处将其转换成矩阵。
 - 可以立即进行向量的旋转。
 - 支持多个角位移连接。即,如果知道了 A 关于 B 的方位,又知道了 B 关于 C 的方位,使用矩阵可以求得 A 关于 C 的方位。
 - 用矩阵表达角位移时,逆矩阵就是“反”角位移。由于旋转矩阵是正交的,所以“反”角位移计算只是简单的矩阵转置运算。
 
缺点:
- 不直观。人类考虑方位的直观方法是角度,而矩阵使用的是向量。
 - 空间开销大。用 9 个数字表示方位,若需保存大量方位,会占大量额外空间。
 - 矩阵可能病态。如对于浮点运算,大量矩阵相乘导致病态矩阵
 
欧拉角
基本思想:让一开始与“标准”方位对齐,然后按一定顺序分别沿三个坐标轴方向进行旋转,最后达到想要的物体方位。
欧拉角是一种描述方位的方法,它使用三个角度来描述一个坐标系相对于另一个坐标系的方位。这三个角度分别称为滚转角(Roll)、俯仰角(Pitch)和偏航角(Yaw)。
先定义坐标轴组合和顺序,再给出具体旋转,旋转步骤如下:
- 物体绕全局的z轴旋转α角(偏航角)
 - 继续绕自己的x轴旋转β角(x,y的步骤可以互换)(滚转角)
 - 最后绕自己的y轴旋转γ角(x,y的步骤可以互换)(俯仰角)
 
不同的欧拉角
上述定义方式被称为ZYX欧拉角,是绕物体坐标系旋转的过程 一开始所说的滚转角(Roll)、俯仰角(Pitch)和偏航角(Yaw)是RPY欧拉角,这种定义方式是先对全局X旋转,然后对全局Y旋转,然后对全局Z旋转
欧拉证明了一个旋转序列等价于单个旋转。
example: 绕旋转轴顺序 x-y-z,如 (10,45,90)则有
优点:
- 仅用三个数表示方位,表示简洁,省空间。
 - 比矩阵和四元数易于使用,更直观。当需要显示方位和键盘输入方位时,欧拉角是唯一选择。
 - 任意三个数都可以描述欧拉角,表示方位。不过,矩阵和四元数可能存在非法的描述。
 
缺点:
- 
不可传递:旋转的顺序影响旋转的结果,不同的应用又可能使用不同的旋转顺序,旋转顺序无法统一
 - 
给定方位的表达方式不唯一,存在多个方位描述它,这称为别名问题:如一个角度上加上 360 度的倍数时,就出现形式最简单的别名问题,即,值虽然变了,但方位未变。所以要限制欧拉角范围。
万向锁问题:当俯仰角为 90 度时,绕z轴和绕x轴的旋转轴重合,此时绕z轴旋转的角度就会影响绕x轴旋转的角度,反之亦然。这种情况称为万向锁问题。所以,一旦选择俯仰角为 90 度,就要限制绕z轴的旋转角度为 0 度,或者限制绕x轴的旋转角度为 0 度。
 - 
有插值问题:无限制地使用欧拉角,会导致出现插值问题。比如,选择角度45°和720°,它们实际上只差了45°,但是插值时,会多绕很多圈.
我觉得这个某种程度上也是别名问题
 
四元数
四元数能表示四维空间,由一个实数单位1和三个虚数单位i,j,k组成,通常表示为
具有以下性质:
- 为了方便,通常写成一个实数和一个向量组合:,
 
优点:
- 可平滑的球面线性插值,比欧拉角方法的直接插值产生更平滑连续的旋转
 - 可连接多次旋转
 - 可快速连接和角位移求逆
 - 能和矩阵形式快速转换
 - 仅用四个数表示
 
缺点:
- 不直观
 - 比欧拉角存储空间大
 
四元数运算法则:
线性插值与三次曲线插值
为什么常用三次曲线来控制路径
一般三维参数曲线形式

参数空间中每一个t对应于曲线上一个点Q(t),图形学中,参数空间通常是有限区间,此时参数曲线称为参数曲线段


为什么使用三次参数曲线:
- 线性插值比较简单,但无法表示光滑曲线。
 - 多项式插值的次数会比较高,有的时候某些点的微小改变,都会对整个曲线形状产生较大影响。这样就产生了病态问题,也叫做龙格现象。
 - 三次曲线是二阶可导的,意味着它能够表示速度和加速度连续的运动。
 
Hermite曲线
目标:我们期望用两个关键帧的位置和速度来控制路径动画
Hermite曲线的约束:
- 
两个端点P1和P4
 - 
两个端点处的切向量R1和R4
 
四个约束条件分别是:

根据这四个约束条件进行求解,得到Hermite曲线定义

例:假设小球在t=0和t=1时刻的位置分别为(1,4,5)和(3,1,4),沿x,y,z轴的速度分别为(2,3,1)和(1,1,1),请(根据hermite曲线公式)写出小球在t=0.5时刻的位置和速度.

Bézier曲线
Bézier曲线的控制条件为四个控制点:
- 
两个端点P1和P4
 - 
另外两个控制点(用于间接指定P1和P4处的切向量R1和R4)

 
根据这四个约束条件进行求解,得到Bézier曲线定义

Bernstein多项式
Bernstein多项式的定义(代入n=3得到Bézier曲线的基矩阵):

因此,贝塞尔曲线也可以表示为:
其中,是控制点,是基函数(也就是伯恩斯坦多项式),n是阶数(也就是多少段现控制,上文的贝塞尔曲线就是三阶)
同理的,Hermite曲线也有对应的公式表达:
如果规定 Hermite 曲线的基函数为:
则,这是[0,1]上的三次 Hermite 曲线
例:假设Bézier曲线的四个控制点按顺序为(30,0),(60,10),(80,30),(90,60),请给出该曲线在t=0.3处的位置。(给控制点找位置)

例:假设Bézier曲线的在t=0,0.3,0.5,1时刻分别经过(30,0),(54.3,11.7),(67.5,22.5),(90,60),请给出该曲线的四个控制点。(给位置找控制点)

复杂路径曲线
如何建立一条经过多个控制点的复杂曲线?利用高阶多项式(比如将Bézier升阶),但会产生如下问题:
- 龙格现象:在一组等间插值点上使用具有高次多项式的多项式插值时出现的区间边缘处的振荡问题
 - 缺少局部控制,牵一发而动全身
 
复杂路径曲线的表示:样条(spline)
样条:分段定义的多项式参数曲线,通常采用三次多项式
- 构造简单,使用方便,拟合准确
 - 样条插值通常比多项式插值好用
- 用低阶的样条插值能产生和高阶的多项式插值类似的效果
 - 避免龙格现象(数值不稳定)的出现
 
 
样条插值是多个低阶多项式,而多项式插值是单个高阶多项式; 上文中的三次曲线插值是样条插值的一种,因此贝塞尔曲线和Hermite曲线都是一种样条曲线
样条性质:
- 连续性
 - 局部控制
 - 插值
 
C0,C1,C2连续性
连续性是样条的性质之一
- C0连续性
- 指曲线的几何位置连接,即第一个曲线段的终点与第二个曲线段的起点x,y,z值相等
 
 - C1连续性
- 在C0的基础上,该始末点的导数相等
 
 - C2连续性
- 在C1的基础上,该始末点的二阶导相等
 
 
三次样条插值
指定n+1个数据点且这些数据点互不重合,有,样条曲线S(x)应满足:
- S(x)在每个小区间上均为三次多项式
 - S(x)在两个相邻的小区间的连接出拥有C2连续性
 - S(x)经过所有给定的数据点,即
 
按照如上约束条件列写方程组,然后求解每个子区间的曲线参数.
但目前该曲线的参数变化与曲线上对应距离的关系是位置的,也就是在t时刻物体在曲线上具体哪个位置B(t)是未知的.
因此需要运动控制即构建相关方法,以满足等量增加时的曲线步进效果。随后获得对应方案并实现曲线上的加速和减速状态
弧长计算:解析求解法、前向差分估算弧长

可以看出,曲线上的速度并不是均匀的.因此为了保证获得固定的速度,插值函数应根据弧长,即插值曲线上的距离值实施重参数化过程.
需要重新设计时间参数,找出这个时间猜数映射到曲线上点的函数映射
1.解析求解:
其实就是很实在的数学方法,对参数曲线的参数求导(速度)后在积分回来(距离),实际上就是物理计算.

2.前向差分估算:
即计算邻接顶点间的线性距离:
- 假设P(0.00)和P(0.05)形成一条线段,其弧长可近似为|P(0.05)-P(0.00)|
 - 可以创建弧长表,记录从起点到每个点处的弧长
 

其实可以算一种微分,用极小距离之间的线性距离代替弧长.
例:

方位控制:根据指定路径曲线计算方位变化
首先一个问题是:路径动画中如何控制方位?
- 局部坐标系(u,v,w)
- 坐标原点在曲线P(u)上,记作POS
 - w代表对象的朝向
 - v代表对象的up向量
 - u与上述坐标轴垂直
 
 
Frenet坐标系是一种基于参数曲线的坐标系统,通常用于无人驾驶
Frenet坐标系定义为标准化正交向量:
- 
w为一阶导数方向(P’(u))
 - 
v正交于w且为二阶导数方向(P”(u))

 
例:

Chapter 4 变形动画
变形动画:模型发生形变,为模型赋予生命感
变形(Deformation)与渐变(Morphing)
变形技术:物体从一个形态变化到另一个形态的视觉效果
- 作为建模工具: 调整模型形状 → 变形(Deformation)
 - 作为动画工具: 模型物体随时间改变形状 → 渐变(Morphing)
 
变形(Deformation)是指将几何对象的形状作某种扭曲、形变,使它形成到动画师所需的形状。所以,有效控制很重要!
与渐变(Morphing)不同,空间变形更具某种随意性,所以空间变形也常称为自由变形(Free Form Deformation)。自由变形不受固定骨骼结构或预设路径的限制,而是可以由用户自由地、直接地控制变形区域和变形效果
直接变形:方法步骤、如何控制每个顶点的移动
直接选择模型物体上的一个顶点或一簇顶点(拾取),直接对其进行拖拽平移操作(拖拽),并带动邻近顶点产生随动,这是最直接的变形方式。

问题1:谁动:偏移某一顶点(种子顶点)或者该对象的顶点组

问题2:怎么动动多少:点移动距离变化应该是逐渐衰减的
我们可以直接定义每个顶点的移动位移为:
- 和是该顶点在变形前后的位置
 - 是种子顶点在变形中所发生的位移
 - 是顶点移动幅度的控制函数,起到控制衰减程度的作用
 
那么如何定义S(i)呢?有如下几种方法
控制函数设计
幂函数定义思路:当前顶点离种子顶点越远,则S(i)越小.假设d度量当前顶点到种子顶点的距离,且取值范围为[0,1]

不同的距离度量也会有不同的效果
- 
按顶点之间的几何距离(线性距离):
 - 
按顶点之间沿曲面的距离:d=测地距离
测地线可以定义为空间中两点的局域最短路径
但是测地线不容易计算,因此可以用三角网格表面路径长度近似

 
其他直接变形方法:基于拉普拉斯微分坐标的Mesh变形方法
间接变形
直接变形手动交互量大,效率低→使用间接变形提高效率
基本思想:根据模型物体的自身特点建立变形工具,通过调整变形工具上控制顶点的位置,带动模型物体产生间接变形。
优点:
- 与模型物体的表示方式无关,对多边形网格模型,参数曲面模型以及细分曲面模型等各类常用3D模型都适用
 - 只需调整少量变形控制顶点,就可以是目标模型物体产生光滑且合理的变形,效率高
 
变形算子
Barr提出的整体和局部变形是空间变形中最早的方法。他提出把整体和局部变形作为新的算子。他提出的算子有:
- Twisting(螺旋)
 - Bending(弯曲)
 - Tapering(渐细)
 

缩放变化就是最简单的变形算子
可以看见,Barr提出的三个算子中,每个顶点的变换都是不同的,变换矩阵随不同的顶点而变化,因此变换是物体顶点位置的函数F(x)
变形算子:渐细 沿z轴的渐细变形Tapering为:
当f’(z)>0时,变形物体的大小沿z轴逐渐增大; 当f’(z)<0时,变形物体的大小沿z轴逐渐变小。
变形算子:使成螺旋形
该变换旋转其中两个坐标分量而不改变第三个坐标分量:
其中,
变形算子:弯曲变形
沿y轴的弯曲变形(Bending):设变形的区域为,中心为, 弯曲的曲率半径为1/k,则有,其中
即弯曲角θ在变形区域外为常数,在中间区域为线性变化,变形中中心线长度保持不变
设,则变形函数为:

在时,
间接变形的通用方法:步骤算法
间接变形技术的可以分为四类:
- 
基于体素的变形
 - 
基于曲面的变形
 - 
基于曲线的变形
 - 
基于点的变形

 
间接变形的通用方法:
- 创建变形工具
- 用户首先定义变形工具的初始控制顶点
 
 - 建立约束关系
- 建立物体顶点与变形工具之间的约束关系(绑定)
 
 - 移动变形工具的顶点
- 用户根据自己的需求来移动变形工具的控制顶点来改变变形工具的形状
 
 - 改变目标物体的形状
- 根据被改变后的变形工具的控制顶点和物体顶点之间的约束关系,计算出目标物体顶点的新位置
 
 
自由变形技术(Free-Form Deformation)
自由变形技术(Free-Form Deformation)是一种基于体素的变形方法.并不是直接操作几何模型,而是把几何模型嵌入到变形空间,然后通过操作变形空间来使得嵌入其中的几何模型发生变形
用双线性插值计算新顶点坐标,根据上述通用方法的步骤:
- 
创建变形工具
- 
构建和坐标系平行的包围盒
 - 
均匀划分x,y形成网格

 
 - 
 - 
建立约束关系
- 每个网格单元记录包含的顶点
 - 网格对应一个二维数组
 
 - 
移动变形工具的顶点
- 记录改变后的每个网格顶点坐标
 

 - 
改变目标物体的形状
- 对每个网格单元,通过新、旧顶点建立插值函数
 - 计算该单元内的每个顶点坐标
 - 将新顶点依次相连后绘制
 

 
双线性插值计算过程需要现在原始状态下计算出插值权重,沿用该权重到新的空间中

实际上的FFD算法使用,伯恩斯坦多项式计算新顶点坐标(贝塞尔曲线系数).
在二维变形中,可以使用双三次贝塞尔曲面:
其实是对双线性插值的拓展.
相对的,三维变形中,再拓展一个维度,使用双三三次贝塞尔超曲面:
这个Bezier体由64个控制顶点来指定

回到四步通用方法,使用伯恩斯坦多项式构建的FFD是如下四步:
- 
创建变形工具(不变)
 - 
建立约束关系
- 构造局部坐标系STU
 - 计算每个模型顶点的局部坐标(s,t,u)
 


 - 
移动变形工具的顶点(不变)
 - 
改变目标物体的形状
- 利用Bernstein多项式计算每个顶点坐标
 - 将新顶点依次相连后绘制
 
 
优点:
- 与物体的几何表示无关
 - 直观
 - 高效
 
缺点
- Lattice为平行六面体
 - 难以控制复杂变形
 - 细节很难被保持
 - 不遵循物理
 
基于曲线的变形,利用一条或者多条曲线作为变形工具,该方法比较适用于扭曲或者裁剪坐标轴,或者沿着骨架曲线变形的物体。
流程:
- 创建变形工具。按照目标模型的初始形态,设置一条初始参数曲线C(s)做变形控制器
 - 建立约束关系:对于目标模型上的一个顶点V,找出其在初始参数曲线上的对应点C(s)上的最近点C(s0)
 
找最近点的方法:离散化,建立 Frenet 标架。
但作为局部坐标系,Frenet 标架的缺点:
- 直线段部分不存在法向量
 - 在曲线的拐点处法向量会发生反转,导致变形结果出现不合理扭曲
 - 法向量会出现不合理的旋转,导致变形结果出现不合理扭曲
 
改进:最小旋转标架
二维图像渐变
基本方法步骤
warping表示单幅图像的扭曲变形.为了实现两幅图像的morphing过程,首先要通过简单的几何元建立图像特征之间的对应关系.
几何元可以为网格节点、线段、曲线、点等,然后由这些特征对应关系计算出morphing所需的几何变换,几何变换定义了两幅图象上点之间的几何对应关系.然后根据对应关系进行插值渐变.


基于网格的Morphing
为了实现图像之间的彼此转换,可在两幅图像中定义一个曲线网络.用户负责定义网络,即在两幅图像中制定同等数量的网格

网格通常为双三次样条曲面,如Bezier样条曲面、Catmull-Rom样条曲面等
如何获得时刻t的图像:
- 
网格插值得到中间网格
 - 
两幅图像置入中间网格
 - 
在两幅图像之间实施过渡

 
每一步中间帧图像可以经历下面四个步骤来生成:
- 
线性插值网络M_S和M_D,得到网格M
 - 
应用由网格和定义的变换,使源图像扭曲变形到.
假设对应的曲面为,M对应的曲面为,则图像的计算过程为,对上每一个像素,由计算出满足该公式的参数,则I_0上点的颜色值为图像上点
 - 
应用由网格和M定义的变换,使目标图像变形到
 - 
对图像和进行线性插值,得到中间帧图像
 
针对人脸的渐变方法步骤
- 网格插值得到中间网格
- 检测人脸特征点(81个特征点和8个图像边界点)
 - 对这些特征点进行Delaunay三角剖分
 - 为每对对应三角形计算仿射变换Ti
 
 - 两幅图像置入中间网格
 - 在两幅图像之间实施过渡
 
在前面讨论的morphing过程中,我们采用的是均匀过渡,即中间帧图像各部分之间的过渡速度相同。如果允许用一非线性函数来决定图像扭曲和颜色插值的速度,则可以得到许多有戏剧性的视觉效果。
基于线对的morphing
由一对直线确定的变换:两幅图像之间的变换可以用一对直线来指定。 设为源图像,为目标图像。若先在源图像中定义一条有向直线段,再在目标图像中定义一条有向线段,那么这一对直线段定义了一个从一幅图像到另一幅图像的映射,该映射把一条直线映为另一条直线。
设从的映射为,A为X在PQ上的投影,u为PA与PQ的比,v为XA的长度,如左图所示


若只有一对直线段,则图像变换的过程可描述如下:对于任一X∈ID,计算u, v, X’的值,然后把源图象在X’处的颜色值赋给目标图象的X象素,即:
如何得到中间图像?
- 设这两幅图像为IS和ID,先在两幅图像中定义控制变形的对应直线对,通过插值得到中间图像I的直线。
 - 插值方法有两种:
- 对直线端点进行线性插值。该方法的缺点是对于旋转的直线对可能得到缩短的插值直线。
 - 对直线的中点、朝向和长度进行插值,通常这一方法效果较好。
 
 - 由IS→I的直线对变换可得到一幅变形图像I1;由ID→I的直线对变换可得到I2。对交溶参数作动画,把I1和I2进行交溶处理得到中间的变形图像I。
 
三维渐变的几种方法思路
3D形状morphing:指将一个三维物体光滑连续地变换为另一个三维物体
有以下几种方法思路:
- 直接插值渐变
 - 基于星形多面体的形状渐变
 - 基于球面参数化的形变
 
直接插值
当给定两个物体的顶点数和拓扑结构都相同时,只需对对应顶点进行插值便可实现三维morphing过程。
但通常这个条件并不满足,因而需要寻找一些更一般的三维morphing方法。
基于星形多面体
其实还是找对应关系
合并一对三维多面体模型的拓扑结构,使它们拥有相同的顶点、边、面结构,然后对相应的顶点进行插值:

如何合并两个模型的拓扑结构?星形物体,是指物体中至少有一点,从该点可见多面体的所有顶点。显然,凸体是星形物体的特例,而星形物体则可以是凹体。


- 把两个多面体投影到单位球面上
 - 将投影在单位球面上的两个拓扑结构合并在一起构成一个新的拓扑结构
 - 将新的拓扑结构重新映射回原来的两个多面体
 
如何合并两个模型的拓扑结构:拓扑合并算法(很复杂)

基于球面参数化
依旧是找顶点与顶点之间的对应关系,然后执行顶点到顶点的插值(位置、颜色……)
Chapter 5 角色动画
运动层次结构
物体层次+相对运动=运动层次
- 各个组件表示为物理连接的对象,称作链接附件/链接
 - 通常描述对象之间的相对运动
 - 运动行为通常收到限制
 
关节
有一个自由度概念:指的是完全指定一个物体运动所需的最小坐标数目
单一DoF关节
- 转动关节(Revolute Joint)
- 某以链接体围绕另一链接图的固定轴旋转(角度坐标)
 
 - 移动关节(Prismatic Joint)
- 链接体彼此之间可呈现为平移状态(长度/位置坐标)
 

 
复杂关节链接:包含多余一个自由度结构
- 平面关节
- 一个链接体可以在另一个链接体表面滑动(位置坐标,二维)
 
 - 球窝关节
- 三个自由度,比如人体关节
 
 - 铰链关节,鞍状关节等
 
n个自由度的复杂关节可看成由n个自由度为1的关节通过n-1个长度为0的连杆相连
人体模型的自由度:
- 根节点(Root): 3 translational DOF + 3 rotational DOF
 - 人体模型通常用旋转关节(Rotational joints)
 - 每个关节至多有3个自由度
- 肩关节(Shoulder): 3 DOF
 - 腕关节(Wrist): 2 DOF
 - 膝关节(Knee): 1 DOF
 
 
层次结构建模
关节角色通常利用层次结构建模方法,表示为一系列通过关节(joints)相连接的连杆(links)

层次连杆可以用树状结构来表示
- 根节点——对应与物体的根部,其位置在世界坐标系中给出
 - 其他节点——相对于根节点来表示
 - 叶节点
 
层次结构与树中间的映射
- 
节点——表示物体部件
 - 
连接弧——表示层次结构中应用与物体部件之间的关节或变换

 
层次结构的运动变换
考虑一个二维3连接例子:

对该结构进行旋转变换:


双肢体就是对每个肢体单独计算(root上的不同分支)
上述示例的展开讲解
在这个例子中,我们有一个包含三个连杆的机器人系统:Link0(根部)、Link1和Link1.1。我们的目标是计算每个连杆上的点在世界坐标系中的位置。
- Link0是整个系统的根部,它的全局位置和方位由表示,对于Link0上的一个点,其世界坐标可以通过计算:. 这里,T0包含了Link0的平移和旋转信息.
 - Link1相对于Link0的变换由表示.图上表示,在上还包含了一个旋转变换,其中是Link1相对于Link0的旋转角度.因此,Link1上一个点的世界坐标为
 
- 计算过程:
 
- 首先,通过旋转
 - 然后通过变换到Link0的坐标系
 - 最后通过变换到世界坐标系
 - Link1.1相对于Link1的变换由表示,同样包含一个旋转。Link1.1上一个点的世界坐标为:.
 
- 计算过程:
 
- 首先通过旋转
 - 然后通过变换到Link1的坐标系
 - 再通过旋转到Link0的坐标系
 - 接着通过变换
 - 最后通过变换到世界坐标系
 
前向运动学
运动学前有两个对应的概念:
- 关节空间:由关节角度组成的空间,可以对所有关节进行细微控制
 - 笛卡尔空间:三维空间(xyz),指定环境的相互作用
 
所以前向运动学就是从关节空间映射到笛卡尔空间,动画设计人员在各关节处定义旋转参数,用于控制物体运动,用角度求解三维空间位置

我们还要区分一下运动学和动力学(因为后面还有动力学动画):
- 运动学
- 主要研究物体的运动,而不研究导致运动的力
 - 关注运动的几何性质,比如位置速度加速度时间之间的关系
 - 通常用于描述物体运动路径,分析机器人关节运动,控制角色或物体移动
 
 - 动力学
- 顾名思义是研究运动的原因:力,主要关注作用在物体上的力及其对运动的影响
 - 涉及物体的质量,力,能量动量等因素
 - 通常用于计算力对物体运动的影响,设计机械系统中的动力传递
 
 
运动学研究“如何运动”:描述运动的形式和路径,不涉及力和质量 动力学研究“为什么运动”:分析力和质量如何影响运动
三角几何建模
例:已知各关节的旋转角度,如何计算下面物体的末端位置?

如果所有关节只在二维平面上运动,可以采用三角几何建模方法
树形结构遍历
对树形结构遍历,从根节点到叶节点的深度优先遍历,重复如下步骤直到所有节点和连接弧都被访问过:
- 对树进行回溯,直到遇到一个未被访问过的向下连接弧
 - 对向下连接弧进行遍历
 
在实现阶段需要堆栈存储变换
例:已知根关节的位置和旋转, 关节在局部坐标系下的旋转和, 以及在局部坐标系下, 子关节相对于父关节的偏移量,求出P1,P2,P3在全局坐标系下的位置.

首先计算P1在全局坐标系下的位置,有
再计算P2的位置,有
再计算P3的位置,有
逆向运动学
逆向运动学:给定初始姿态向量和目标姿态向量,计算关节向量的值,使得物体满足所需的姿势,可以有0个,1个,多个解.因此涉及约束过渡/约束不充分问题

一旦得到关节向量值后,我们可对角色的初始姿势和最终姿势的关节向量值进行插值,从而得到角色的动画,但是如果这样就有插值的普遍问题,如果初始和最终姿势向量有很大差异时,动画效果可能并不好。
解决办法就是插值姿态向量,对每一个得到的插值姿态向量进行IK计算,得到中间某一时刻的关节向量值
如何求解逆向运动学?解析求解或逆向雅可比(牛顿迭代法)
解析求解法
只有当关节链非常简单时,才存在解析解.
考虑二维二连杆手臂,其旋转DOF定义为2,链接体长度分别为L1和L2。假设第一个关节处的手臂基本位置固定于原点。期望位置的坐标为(X,Y)




更复杂的关节结构则整个求解过程更加复杂.由此可见稍微复杂一些的结构用解析求解法便非常困难,而且不一定有解析解.但解析求解法的优点是计算速度快、便于实时控制等.
逆向雅可比方法
逆向雅可比方法是数值求解法的一种,能找到一个结果就行,不需要解析解
用渐进的方式进行数值求解有以下几种方式:
- 逆向雅可比方法
 - 循环坐标下降法
 - 基于优化的方法
 - 基于样例的方法
 
雅可比矩阵
在向量微积分中,雅可比矩阵是一阶偏导数以一定方式排列成的矩阵,其行列式称为雅可比行列式。
回顾上文的例子:

雅可比矩阵的数学意义是:从其关节速度到末端位置变化速度的映射关系.换句话说,雅可比矩阵反映了,在当前时刻下,各关节值的微小变化会引起末端位置的何种变化。
注意:雅可比矩阵并不是常量矩阵,而是随时间变化的。
如果我们把所有关节值表示为向量,末端位置状态表示为向量X,它们相对于时间变量t的梯度记为和V,运动学模型表示为:
那么雅可比矩阵可以表示为:
雅克比矩阵为n×m的矩阵,它把θ的微分(dθ)与X的微分相关联(dX):
所以雅克比矩阵把关节空间的速度映射到笛卡尔空间的速度
如何利用雅可比矩阵求IK问题
根据刚才的运动学模型,我们可以构建逆雅可比问题

雅克比矩阵把关节空间的速度映射到笛卡尔空间的速度,自然,逆雅可比问题就能让笛卡尔空间→关节空间.
通过一系列增量步骤,迭代到所需要的位置
- 
迭代变化关节角,使得末端影响器朝目标位置和方向前进
 - 
对于每一步k, 通过上述公式得到关节的角速度 ,然后执行

 
角色绑定
在计算机动画中,数字角色通常是动的。如何让角色动起来?那需要用到一种称为Rigging,中文称为角色绑定的技术.
刚体变换
假设一个数字角色的手臂用前臂和后臂来模拟,我们要对手臂设置动画。
若采用刚体变换设置动画,则肘关节处不像真实手臂。因为我们采用了两个分离的物体来模拟手臂,在肘关节处有重叠部分。

顶点混合

顶点混合(Vertex Blending):最简单方法就是前臂和后臂仍单独设置动画,但关节处用一柔性的“skin”来连接。
柔性部分的一部分顶点由前臂的矩阵来变换,另一部分由后臂的矩阵来变换。即:一个三角形的顶点可以由不同的矩阵来变换,而不是一个矩阵。这种基本技术有时也称为“Stitching”。
进一步推广下去一个顶点可以由几个不同的矩阵进行加权变换;实施方法:在物体上放置关节骨架,每个骨架按用户给定的权因子影响顶点。
当然,连接处可以是柔性的,那么整个手臂自然也可以都是柔性的.所有的顶点可以由多个矩阵影响。整个多边形网格常称为骨架上的“skin”(外皮)

线性混合蒙皮
对每个顶点来说,其被绑定到的每个关节对他的影响程度不同,设定每个关节的权重,就可以通过加权算出顶点受这些关节共同影响后的位置.

对于顶点P在时刻t的位置u(t)有:
P为变换前的顶点,u(t)为变换后的顶点,n为影响P的关节数目 Mi:把第i个关节骨架的局部坐标系变换到世界坐标系 Bi(t):第i个关节随时间变化的世界变换,通常是一系列矩阵的连乘 wi: 第i个关节骨架作用于P的权因子
那么如何决定权因子呢?
- 
如果顶点v在骨骼i的中间,则,且;
 - 
如果顶点靠近骨骼i和骨骼i+1的边缘,则逐渐减少到0,逐渐增加到1;
 - 
如果顶点受到>=3个骨骼的影响,其权因子可根据顶点到骨骼的距离来决定

 
但这样也不是没有问题.当某些关节旋转到一些极端角的时候,网格模型的体积会损失,这个叫做”关节塌陷”或”糖果包裹”

关节塌陷的原因:

解决办法:把球面线性插值取代上述公式中的线性插值(四元数插值)
或者可以添加修改骨骼(实际上是将真实骨骼的体积性质表现出来)

但最终这种强行模拟的效果依旧差强人意,因此有blendshape.还是使用顶点动画的方法,建模师提前制作多个不同关节运动角度时的肌肉模型,之后在骨骼运动时读取这个结果
骨架自动绑定
主要思想:首先在未知的三维模型中嵌入骨架,然后计算骨骼对表面网格上每个顶点的影响权值,并将表面皮肤依附在骨骼上。

那么如何从多边形模型中自动计算出骨架呢?可以利用物体的中轴,或者通过球体拟合来计算


离散骨架嵌入:从给定的骨架模型建立一个简化的骨架,该骨架包含原骨架的端点和分叉关节点,把简化的骨架拟合到角色图(Character graph)中,使离散惩罚函数最小化,得到一个嵌入的骨架,再进行优化

运动捕获
运动捕获(MoCAP, Motion Capture)采用软硬件系统记录表演者的真实运动信息,并把动作过程复制到一个虚拟的人或动物上。
运动捕获可以获取表演者动作的个性和运动细节,是生成逼真人体动画最实用、最有效的方法,因而在影视特技、游戏、动画、机器人控制中被广泛采用。
包含人脸、手指、表情等变化的捕捉方式叫做表演捕捉(Performance Capture)
为什么需要运动捕获?因为算数太难太假
运动捕获系统分类
自动估计三维位置、方位、速度、加速度
- 电磁捕获系统(Electromagnetic)
 - 机电捕获系统(Electromechanical)
 - 光纤捕获系统(Fiber optic)
 - 光学捕获系统(Optical)
 - 基于视频的捕获系统(Video-based Mocap)
 
光学运动捕获
使用多个固定在墙上并朝向舞台中心的摄像机,通常是高对比度的高级摄像机。在运动捕捉的时候,角色要穿上贴有多个小白球(叫做marker)的衣服,摄像机可以捕捉到这些marker的运动,然后通过三角测量可以计算出marker三维位置。
marker有主动和被动类型,前者发射红外光,后者反射光。摄像机数目越多,系统月精确和稳定。


电磁运动捕获
和光学系统工作原理类似,但电磁运动捕捉系统是将传感器绑定到角色四肢上,传感器可以在低频磁场中测量传感器的位置和朝向。优点是除了传感器的位置信息以外,还可以得到朝向信息,可以很方便地应用到实时运动捕捉中。

视觉运动捕捉系统
视觉运动捕捉技术是一种通过计算机视觉技术,从输入图像或视频中检测并识别出人体的关键点,进而推断出人体的姿态信息的技术。

运动捕获主要思路与流水线
主要思路:
- 跟踪参考点的运动
 - 把参考点的信息转化为关节角度
 - 用关节角驱动关节模型
 - 结合运动轨迹,进行角色的控制
 
根据以上思路,可以设计出一款通用的流水线过程:
- 规划(Planning)
- 确定运动捕捉的目标、范围和方法
 - 选择合适的捕捉技术(如光学、惯性或电磁系统),定义要捕捉的动作类型,以及准备捕捉环境和所需的任何设备
 
 - 标定(Calibration)
- 设置捕捉设备(如摄像头或传感器),并对其进行校准,以确保它们能够精确地测量空间中的位置
 - 标定可能包括确定摄像头的位置和方向、设置捕捉空间的坐标系统以及校准捕捉设备的时间同步。
 
 - 捕获(Capture)
- 参与者会执行预定的动作,而捕捉系统会记录他们的运动
 - 捕获的数据通常是时间序列的,记录了每个标记在每一帧的位置。
 
 - 三维位置重建(3D Position Reconstruction)
- 使用多个视角的数据和三角测量原理来实现
 - 将二维数据转换成三维空间中的位置
 
 - 拟合到骨架(Fitting to the Skeleton)
- 将这些位置数据映射到一个虚拟的骨架
 
 - 后处理(Post Processing)
- 对捕捉到的数据进行清理和优化
 - 包括去除噪声、平滑数据、填补缺失的数据点、修正错误以及调整运动轨迹以更好地符合预期的动作
 
 
运动捕获的优点不言而喻,相比于之前的物理模拟,从真实情况出发的运动捕获绝对是最真实最细节的.但同时缺点也很明显,就是不容易控制与编辑,而且贵.
运动捕获的数据和使用
运动捕获数据的处理一般需要经过以下几种操作
- 运动信号处理和运动变形(Motion warping)
 - 运动数据的重定向
- 把运动映射到不匹配的虚拟角色上,并满足一些重要的约束条件
 - 通常具有相同的结构(with the same structure)
 
 - 运动数据的合并
- 把短的运动片段合并成长的运动序列
 
 
同时还存在一个运动信号(大概是计算机问题逃不开的部分)处理的问题,信号同时还代表了运动数据的语义:
- 考虑信号频率如何刻画各种运动
- 低频部分:表示基本运动(如走路)
 - 高频部分:特质运动(跛行)
 
 - 把运动看成多维信号
- 低通滤波:去噪
 - 高通滤波:风格的变换
 
 - 高频信息可能是运动细节,而非噪声
 - 通过滤波来进行运动的修改并非易事
- 物理约束(关节约束, 地面接触)
 - 运动的自然性?
 
 
运动重定向
捕获的数据一般具有局限性,身高185的成年男性运动数据放在135的小孩身上就会造成十分大的误差与不真实感,因此需要**运动重定向:**把捕获的运动数据映射到不匹配的虚拟角色上,并满足一些重要的约束:
- 不能穿模(穿透场景,自身穿透),避免走路时的打滑
 
因此需要生成一个与原始运动尽可能接近的新的运动,并强制满足约束条件

运动混合
把两段或多段运动叠加在一起,实际上是插值(逐帧操作)
运动过渡
运动捕获得到的通常是小的运动片段,因此需要把他们连接起来.
- 
如果运动是相近的,则很容易

 - 
如果运动相差较远,则比较困难

 
Chapter 6 基于物理的动画
粒子系统
粒子系统是一种在计算机图形学中广泛应用的技术,主要用于模拟和渲染那些难以精确建模的模糊对象,如火焰、云朵和水体等。
粒子系统的基本思想是将许多简单形状的微小粒子作为基本元素聚集起来形成一个不规则的模糊物体,每个粒子均经历出生、成长、衰老和死亡的过程,与粒子有关的每一个参数均将受到一个随机过程的控制。
假设:
- 粒子一般与其它粒子不碰撞
 - 除非处于聚集状态,粒子不向其它粒子投射阴影
 - 粒子只向其它环境投射阴影
 - 粒子不反射光
 - 粒子通常有有限的生命周期
 
每一帧中,需要对如下内容进行重新计算:
- 生成新的粒子并加入系统中;
 - 赋予每一新粒子以一定的属性;
 - 删除那些已经超过其生命周期的粒子
 - 根据粒子的动态属性对粒子进行移动和变换;
 - 绘制并显示由有生命的粒子组成的图形。
 
粒子生成与属性
设置粒子属性可以获得完全不同的粒子效果,一个粒子(质点)的属性可以包括:位置,速度,大小,质量,力累加器,生命周期,绘制属性…
粒子属性初始化
对于每一帧,根据一个控制的随机过程生成粒子:
- 
用户可以控制每帧的平均粒子数和其概率分布
 - 
粒子数可以是时间的函数
粒子数n=m+v*rand():其中,m为平均粒子数;rand()返回一个[-1,1]之间的随机数;v为变化幅度;
 
粒子生命周期
在每一新帧,每个粒子的生命周期减1,当该属性变成0时,把该粒子从系统中删除

当如下情景发生时,粒子将被销毁:
- 
生命周期结束
 - 
淡出:当粒子的颜色/不透明度小于一用户给定的阈值时,该粒子不可见并将被销毁。
 - 
移走:不在视域。

 
粒子系统的特点
粒子系统呈现的特点:
- 物体并不由一系列基本的面元素如多面形或色块所呈现,且它的边界也不为这些元素所定义,而是借助基本粒子组成的云团来定义它的体积;
 - 粒子系统并不是确切的实体,它的粒子随着时间的变化而改变外观,粒子新旧更替。
 - 由粒子系统所呈现的物体的外形并不被明确规定,因此其不具确定性。此外,随机处理被用于生成和改变物体的外观。
 
粒子绘制
根据具体目标有多种绘制方式:
- 
把每个粒子当成一个点光源
- 把每个粒子绘制成一个小的图元 ;
 - 把映射到同一像素的颜色相加;
 

 - 
把每个粒子建模为一个带纹理的广告牌(textured billboard)
- 纹理多边形面向视点
 

 - 
把每个粒子看成元球,绘制整个元球系统(用于模拟水等液态效果):元球相互靠近到一定距离产生变形,再进一步靠近时则融合成光滑表面.
 

基于物理的运动
基于物理的模拟选取一个基于物理的模型,以及一些初始条件,然后尝试判断物体行为如何随时间变化
牛顿定律公式
- 惯性
 - F=ma
 - 反作用力:方向相反大小相等
 
以及速度和加速度公式
重力,空气阻力,风力
重力:F=mg
假设物体只是一个点,并且是接近地面的,则重力会施加往下且近乎常数的力.
起始条件:开始时球是静止的且位于100单位高,v0=0, x0=100,g=10

对重力数值积分算法:

当前状态=初始状态;
t=0;
while t<tmax do
	获取当前状态下的力;
	
	使用牛顿第二定律计算加速度a=1/m*F
	新状态=使用时步h对加速度进行积分;
	当前状态=新状态;
	t=t+h;
end
空气阻力
真实的空气阻力实际上是非常复杂的物理效果,因此我们要用简化模型来模拟阻力效果:阻力受到两个因素影响:
- 速度:速度越快空气阻力越大
 - 一个阻力系数d:表示影响阻力的整体因素(如几何形状)
 
因此
例:小球的初始速度 ,初始位置,重力加速度为g=10(),空气阻力为,,求小球在t=1,2,3,4时刻的位置

风力
风力可以如空气阻力般处理.风往静止物体的某个方向吹,等同于该物体以相反方向往静止空气移动.因此,风力可写作
考虑重力、空气阻力、风力,整体的加速度为:
其中是物体相对于风的速度 复合起来,一个最终的示例为:小球的初始速度 ,初始位置,重力加速度为,空气阻力为风速为,求小球在t=1,2,3,4时刻的位置

弹簧力,阻尼力
上述三种力都是一元力,也就是只考虑单个物体(单个粒子)的力
而弹簧力和阻尼力都是n元力:依赖于n个粒子的力称为n元力

- 
如果粒子比其平衡位置(静止位置)远,则弹簧力需要把它拉回
 - 
如果粒子比起平衡位置近,则弹簧力需要把它推开
 - 
结合上述两种情况:
 
阻尼力则类似
- 
阻尼力/粘性阻力使粒子系统在外力消失后,渐渐回到静止状态
 - 
如果两个粒子正在远离,阻尼力会把他们拉回
 - 
结合这两种情形:
 
运动方程求解
基于物理规律,生成一个系统的状态系列:

然后使用一系列微分方程描述这个过程

粒子系统模拟的例子
瀑布模拟

定义粒子属性如下:
- 粒子的运动速度v
 - 粒子与X轴和Y轴所成的角dirx和diry
 - 粒子的质量m
 - 粒子的坐标位置 p
 - 粒子下落的高度h
 - 粒子淡化的alpha值
 - 在 Y 轴方向粒子受到重力加速度 g 以及空气阻力 f 的影响
 
粒子运动:令重力方向为Y轴,建立瀑布所在空间的笛卡尔坐标系;假设风与 XZ 平面平行,则在 XZ 平面粒子只受风力的作用;而在 Y 轴方向粒子到受重力加速度 g 以及空气阻力 f 的影响;因此在任一时刻 t 粒子的速度 V(Vx,Vy,Vz) 和空间位置 P(x,y,z) :

瀑布粒子的碰撞检测:瀑布在下落的过程中将会与大量的障碍物进行碰撞形成水花飞溅的现象。为了模拟这种效果,在粒子和障碍物之间须进行碰撞检测。

粒子的消亡:粒子系统中粒子的生存期以帧为单位,在粒子的运动过程中,其生存期不断地缩减,当其生存期减至零时,该粒子即消亡。显然,在瀑布粒子系统中当粒子碰到水面或其alpha值减小到零时粒子自动消亡.
粒子的绘制:
- 采用标准图形系统中的线元作为基本绘制单元。用线元连接水珠在相邻时刻的位置能够模拟水珠的运行轨迹,使人产生水珠聚束的视觉效果。
 - 为模拟水花粒子晶莹透亮的效果,采用了逐渐淡化融合的技术来绘制粒子,即粒子在运动过程中不断减小其透明度值,当粒子与障碍物碰撞时加快其透明度值的减少,使其淡化消失。这与水珠与障碍物碰撞时形成的水雾相吻合。
 
弹簧质量/布料模型
瀑布模拟可以算作一种流体动力学,而弹簧质量模型,布料模型可以算作一种柔体力学.弹簧质量模型就是由弹簧和质量点(质点)组成的网格模型。物体的轮廓被离散化为三角面片,其中边是由弹簧组成,点是质量点。



往年题目解析
2023年
一 . 简答题
Q.动画形成原理
动画形成的原理是视觉暂留效应,人眼看到的图像会保持0.05到0.1秒不消失,利用这段时间连续播放画面,在前一个画面还没消失的时播放下一个画面就能形成连贯的视觉效果.Q.三维动画的制作步骤
A.脚本编写→分镜头设计→概念设计→三维建模→角色绑定与蒙皮→动画制作→灯光和渲染→合成与特效→音效与配乐→输出Q.欧拉角的概念和优缺点
A.欧拉角是一种方位的表示方式,是使用三次旋转表示一个坐标系相对于另一个坐标系的方位.三个角度分别是滚转角Roll,俯仰角Pitch,偏航角Yaw,分别对应沿物体坐标系x轴旋转,沿物体坐标系y轴旋转,沿世界坐标系z轴旋转.假设欧拉角旋转方式是顺序是zyx,则依次为偏航角→俯仰角→滚转角的顺序将位于坐标原点的物体旋转为当前方位. 欧拉角的优点有: - 相对于矩阵形式存储的内容更少; - 比四元数更加直观; - 当需要键盘输入的时候欧拉角是唯一的选择 缺点有: - 别名问题,给定表达方式不统一; - 不可传递,因为存在旋转顺序问题,因此不同的欧拉角是不能传递的,旋转顺序不统一; - 万向锁问题,当俯仰角为90度时滚转角和偏航角的轴重合,导致失去一个维度(或者说有一个维度多余),因此要限制任意一个角度为0; - 插值问题,选择角度45°和720°,它们实际上只差了45°,但是插值时,会多绕很多圈.Q.基于点的间接变形原理
A.定义控制点是一组独立于网格外的点集,约束关系是点位置的插值计算,计算每个顶点与控制点之间插值关系,以此作为约束关系;改变控制点的位置后利用约束关系的插值公式计算顶点新的位置.Q.三维的轴向切片法渐变步骤
A.(这个22级貌似没讲) 1. 获取三维数据 - 通常从 3D 医学影像数据(如 MRI、CT 等)或其他三维数据源获取三维数据。 - 三维数据可以表示为一个三维数组,每个元素对应一个三维空间中的体素。 2. 定义切片平面 - 确定三个正交的切片平面:轴向(axial)、冠状(coronal)和矢状(sagittal)。 - 可以手动设置这些切片平面的位置和方向,以获得所需的切片视图。 3. 沿切片平面提取 2D 切片 - 遍历三维数据,沿每个切片平面提取 2D 切片图像。 - 对于轴向切片,沿 Z 轴提取切片;对于冠状切片,沿 Y 轴提取;对于矢状切片,沿 X 轴提取。 4. 保存 2D 切片 - 将提取的 2D 切片图像保存为图片文件,如 PNG 格式。 - 可以根据需要调整切片图像的大小和分辨率。 5. 渐变过渡 - 通过在相邻切片之间进行插值,可以实现平滑的渐变过渡效果。 - 插值方法可以是线性插值、双线性插值或其他高阶插值算法。 6. 优化切片质量 - 可以通过调整切片厚度或采用交错切片的方式来提高切片质量,减少锯齿感。 - 但这可能会增加图像噪声,需要权衡考虑。Q.弹簧模型,布料的变形步骤
A.布料参数初始化→建立弹簧质点模型→计算质点内部外部力→求解运动微分方程获得质点动态位置→约束弹簧拉伸上限后更新质点的动态位置→碰撞检测和相应后更新质点的动态位置Q.三维物体模型的表示方式
A.(这个也不在22级范围内)三维物体模型有多种常见的表示方式,包括:1. 点云表示 (Point Cloud Representation):
    <li>- 由大量离散的三维坐标点组成,描述物体表面的几何形状。</li>
    <li>- 适合用于表示复杂的三维形状,但缺乏拓扑结构信息。</li>
    <li>- 常用于3D扫描、自动驾驶等应用。</li>
<br>2. 网格表示 (Mesh Representation):
    
    <li>- 由一组顶点、边和面组成的多边形网格,描述物体的表面。</li>
    <li>- 可以表达物体的拓扑结构和细节几何信息。</li>
    <li>- 是最常见的三维模型表示方式,适用于大多数3D图形应用。</li>
<br>3. 体素表示 (Voxel Representation):
    <li>- 将三维空间划分为规则的立方体单元(体素),每个体素记录是否被物体占据。</li>
    <li>- 可以表示复杂的内部结构,但需要大量的存储空间。</li>
    <li>- 常用于医疗成像、3D打印等领域。</li>
<br>4. 隐式表示 (Implicit Representation):
    
    <li>- 使用一个隐式函数来描述物体的表面,如符号距离函数(Signed Distance Function)。</li>
    <li>- 可以表达光滑的曲面,并支持高效的渲染和编辑操作。</li>
    <li>- 适用于需要高质量几何表示的应用,如动画、游戏等。</li>
<br>5. 参数化表示 (Parametric Representation):
    
    <li>- 使用参数方程来描述物体的表面,如NURBS曲面。</li>
    <li>- 可以精确地表达复杂的曲面形状,并支持参数编辑。</li>
    <li>- 常用于计算机辅助设计(CAD)和计算机辅助制造(CAM)等领域。</li>
    
二 .实践题
一. 蝴蝶翩翩起舞的角色动画,根据正向动力学和路径动画来写蝴蝶翩翩起舞的伪代码
#include <iostream>
#include <cmath>
 
// 定义蝴蝶类
class Butterfly {
public:
    float positionX, positionY;
    float wingAngle;
    float time;
 
    Butterfly() : positionX(0), positionY(0), wingAngle(0), time(0) {}
 
    void update(float deltaTime) {
        time += deltaTime;
 
        // 更新蝴蝶位置(路径动画)
        positionX = 100 * sin(time);
        positionY = 50 * cos(time) + 50 * sin(2 * time);
 
        // 更新翅膀角度(正向动力学)
        wingAngle = 30 * sin(5 * time);
    }
 
    void draw() {
        // 绘制蝴蝶主体
        std::cout << "Drawing butterfly at (" << positionX << ", " << positionY << ")\n";
        // 绘制翅膀
        std::cout << "Left wing angle: " << wingAngle << "\n";
        std::cout << "Right wing angle: " << -wingAngle << "\n";
    }
};
 
int main() {
    Butterfly butterfly;
    float deltaTime = 0.016; // 假设每帧约60 FPS
 
    for (int i = 0; i < 600; ++i) { // 模拟10秒
        butterfly.update(deltaTime);
        butterfly.draw();
    }
 
    return 0;
}二. 一个人脸的变形的直接变形伪代码
#include <iostream>
#include <vector>
#include <cmath>
 
// 定义关键点结构
struct Point {
    float x, y;
};
 
// 计算距离
float distance(const Point& a, const Point& b) {
    return std::sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
 
// 控制函数,使用幂函数
float influence(float distance, float maxDistance, float exponent) {
    return std::pow(1.0f - std::min(distance / maxDistance, 1.0f), exponent);
}
 
// 直接变形函数
void directManipulation(std::vector<Point>& vertices, const Point& controlPoint, const Point& deltaP, float maxDistance, float exponent) {
    for (auto& vertex : vertices) {
        float dist = distance(vertex, controlPoint);
        float S = influence(dist, maxDistance, exponent);
        vertex.x += S * deltaP.x;
        vertex.y += S * deltaP.y;
    }
}
 
// 示例使用
int main() {
    // 初始顶点
    std::vector<Point> vertices = {
        {0, 0}, {1, 0}, {0.5, 1}
    };
 
    // 控制点和位移
    Point controlPoint = {0.5, 0.5};
    Point deltaP = {0.1, 0.1};
 
    float maxDistance = 2.0; // 最大影响距离
    float exponent = 2.0;    // 控制函数的幂
 
    directManipulation(vertices, controlPoint, deltaP, maxDistance, exponent);
 
    // 输出变形后的顶点
    for (const auto& vertex : vertices) {
        std::cout << "(" << vertex.x << ", " << vertex.y << ")\n";
    }
 
    return 0;
}总而言之就是按照函数计算衰减然后影响位移
三. 介绍一个常用的渲染引擎和它使用的渲染方法 这个就不说了,lmy的范围里面没有渲染
2022年
1.简答和叙述
概述帧的含义
A.帧是指构成视频或动画的基本单元。每一帧都是一个静止的图像,利用人眼的视觉残留效应,当以足够高的帧率播放时,就会产生连续的视觉效果。各种坐标系的作用(相机,世界,局部,屏幕)
1. 相机坐标系(Camera Coordinate System): - 以相机位置和朝向为原点和轴向定义的坐标系。 - 用于描述物体在相机视野中的位置和方向。 - 渲染引擎将世界坐标系的物体变换到相机坐标系进行投影和光照计算。 2. 世界坐标系(World Coordinate System): - 整个三维场景的全局坐标系。 - 用于定义场景中物体的绝对位置和方向。 - 模型、灯光、相机等都位于世界坐标系中。 3. 局部坐标系(Local Coordinate System): - 每个三维物体自身的坐标系。 - 用于定义物体内部元素(顶点、面等)的相对位置。 - 物体的变换(位移、旋转、缩放)都在局部坐标系中进行。 4. 屏幕坐标系(Screen Coordinate System): - 二维显示屏幕上的坐标系。 - 用于描述像素在屏幕上的位置,通常以左上角为原点。 - 渲染引擎将三维场景投影到屏幕坐标系上进行显示。 这些坐标系在三维建模、动画和渲染流程中发挥着不同的作用: - 模型构建时使用局部坐标系定义几何形状。 - 场景组装时使用世界坐标系定位和摆放物体。 - 相机设置时使用相机坐标系确定视角。 - 最终渲染时将世界坐标系投影到屏幕坐标系上显示。常用的插值方法,并说明其特点和适用范围
线性插值 ,双线性插值,三次多项式插值,样条插值 1. 线性插值 (Linear Interpolation): - 特点: 简单、计算效率高,仅考虑两个相邻点。 - 适用范围**: 数据变化平稳、线性关系明显的场合。 2. 多项式插值 (Polynomial Interpolation): - 特点: 通过所有数据点的多项式,适合拟合全局数据。 - *适用范围: 数据点较少且要求通过所有点的情况。 - 缺点: 高次多项式可能导致龙格现象(振荡)。 3. 样条插值 (Spline Interpolation): - 特点: 使用低阶多项式(通常是三次样条),平滑且避免振荡。 - 适用范围: 大量数据点,需要平滑曲线的场合,常用于图形绘制和动画。 - 种类: 常用的有自然样条、B样条等。请注意
贝塞尔和Hermite是两种特殊的多项式插值;贝塞尔是多项式表示(伯恩斯坦多项式),但不是传统的插值概念,因为不强制通过所有控制点; 而Hermite是一种插值,由端点和切线控制.
Q.曲面细分建模的方法 A. (22级应该不考吧)曲面细分建模是一种通过递归细分多边形网格来生成平滑曲面的技术。常用的方法包括: 1. Catmull-Clark细分: - 主要用于四边形网格。 - 通过细分生成新的顶点,将网格变得更平滑。 - 常用于动画和工业设计。 2. Doo-Sabin细分: - 适用于任意多边形。 - 生成新顶点并计算新的面。 - 逐步逼近平滑曲面。 3. Loop细分: - 专为三角形网格设计。 - 生成新的边中点,细分三角形。 - 保持曲面的光滑性。 4. Butterfly细分: - 适用于三角形网格。 - 使用插值方法生成新顶点。 - 保持网格的细节。
Q.什么是渲染 A. (22级应该不考这种)简单来说,渲染就是将虚拟的三维世界转换为我们在屏幕上看到的最终图像的过程
粒子系统的基本原理与实现步骤
原理:利用许多简单形状的微小粒子作为基本元素聚集起来,来表示不容易使用建模等方法表示的模糊物体如烟雾和火焰,每个粒子经历出生,成长,衰老和死亡的过程.每个粒子的属性独立的由一些随机参数控制 实现步骤:对每一个粒子 1. 粒子生成,属性数值初始化 2. 删除生命周期结束的粒子 3. 根据粒子的动态属性进行变换 4. 绘制由生命周期未结束的粒子组成的图形空间中旋转的表达方式及各自的特点
1. 矩阵表示:使用仿射矩阵表示旋转.特点有: 1. 可以传递,一系列矩阵表示的旋转相连可以表示一个旋转;自然,也可以快速找到逆变换 2. 被各种图形API广泛支持 3. 能对向量单次运算求出结果 4. 对存储空间要求比较大 5. 不够直观 2. 欧拉角:使用三个角度描述一个坐标系相对方位和旋转,分别称为**滚转角**(Roll)、**俯仰角**(Pitch)和**偏航角**(Yaw),按顺序对这三个角度的轴进行旋转组合成一个复合的旋转结果.特点有 1. 更为直观,比矩阵和四元数都更易于使用;当需要键盘输入时欧拉角是唯一选择 2. 存储空间更小,只需要三个数值; 3. 任意三个数值都能表示一个欧拉角形式的旋转,但矩阵和四元数存在非法情况 4. 不可传递,因为涉及到三个角度的顺序定义 5. 别名问题,插值问题,万向锁问题 3. 四元数:表示四维空间,由一个实数单位1和三个虚数单位i,j,k组成.特点有下 1. 可平滑的球面线性插值,比欧拉角方法的直接插值产生更平滑连续的旋转 2. 可传递(连接多次旋转),可以快速求逆 3. 可以和矩阵形式快速转换 4. 相对存储较少,四个数值,介于欧拉角和矩阵中间 5. 相对于欧拉角,不存在万向锁问题 6. 不直观四元数计算旋转的方式:
定义旋转轴为单位向量,旋转角度为,可以用四元数表示为: 定义目标向量为,将向量表示为纯四元数,则旋转后的向量为: 其中是的共轭(四元数的共轭就是虚部加变减)
举例说明如何建立角色动画中的角色模型
(我个人认为这里想问的是层次结构建模的方法) 大概是根据层次结构建立骨架->在三维模型中计算骨架,或将建立的骨架嵌入->根据正向运动学或逆向运动学计算当先顶点整体位置->线性混合蒙皮计算模型的顶点位置2.综合
给了一个小车和路径控制点的图例,实现在GC0连续情况下,ease-in/ease-out地实现小的路径动画
// 控制点列表和切线列表
controlPoints = [(x0, y0), (x1, y1), ..., (xn, yn)]
tangents = [(m0x, m0y), (m1x, m1y), ..., (mnx, mny)]
// Hermite 样条矩阵
H = [
    [ 2, -2,  1,  1],
    [-3,  3, -2, -1],
    [ 0,  0,  1,  0],
    [ 1,  0,  0,  0]
]
// Hermite 样条函数(矩阵形式)
function hermiteMatrix(t, p0, p1, m0, m1):
    T = [t^3, t^2, t, 1]
    G = [p0, p1, m0, m1]
    
    // 计算 T * H * G
    result = multiply(T, multiply(H, G))
    return result
// Ease-in/ease-out 函数
function ease(t):
    return t * t * (3 - 2 * t)
// 动画函数
function animateCar():
    duration = 5.0 // 动画持续时间(秒)
    startTime = currentTime()
    numSegments = len(controlPoints) - 1
    
    while currentTime() - startTime < duration:
        totalTime = currentTime() - startTime
        segmentDuration = duration / numSegments
        currentSegment = int(totalTime / segmentDuration)
        segmentT = (totalTime % segmentDuration) / segmentDuration
        
        easedT = ease(segmentT)
        
        // 确保在数组范围内
        if currentSegment < numSegments:
            p0 = controlPoints[currentSegment]
            p1 = controlPoints[currentSegment + 1]
            m0 = tangents[currentSegment]
            m1 = tangents[currentSegment + 1]
            
            position = hermiteMatrix(easedT, p0, p1, m0, m1)
            
            // 更新小车位置
            car.setPosition(position)
        
        // 渲染帧
        renderFrame()
// 主程序
animateCar()
上述伪代码使用Hermite曲线实现,且使用矩阵形式表示.
网传视频台北101大厦摇晃,你认为用什么动画技术可以实现这种视频造假,简述步骤
