一,动画混合
当我们知道了动画算法原理、有了各种动画切片素材(clips)后,怎么让这些动画自然地连接在一起,达到无极切换的效果呢?
1.1 数学混合:线性插值
不同于上节课的lerp(同一个clip内不同pose之间),动画blending需要在不同clip之间线性插值
- 计算权重:就跑步的案例来说,根据速度来变化两个clip之间的权重即可。
- 对齐混合时间线:,要lerp两个clip动画,就需要2个动画的循环时间线是一致的,比如跑步是左右脚各一次循环,走路也得是,并且脚的落地时间一致,做到时间线对应,这样才方便归一化后用权重lerp。下图就是跑是走的速度的两倍时如何根据当前速度进行插值时时间线上的变化(其中length是指时间长短),delta time是指要去对应clip1和clip2的哪一个时间帧去取对应的pose。
1.2 混合空间Blend Space
1.2.1 1D Blend Space
比如在直走、向左以及向右等多个clip中的插值,由于变量只有一个移动方向,所以是一维的混合,但采样点可能有多个,并且插值也不一定是线性或均匀的
1.2.2 2D Blend Space
如果除了角度外,行走速度也可以变化,就变为了二维的Blend Space。
这里还涉及一些人体习惯,比如人侧向走时速度超过一个很低的阈值就无法保持平衡,会直接进入侧向跑的clip,因此clip的分布也是不均匀的,这时插值成本就比较高。我们可以采用 Delaunay Triangulation三角网格化的方法将这些clip化成不同三角形,然后根据当前的速度和方位确定当前的点在哪个三角形内。最后用重心插值对三角形的三个点(三个clip)进行插值。
1.2.3 Skeleton Masked Blending骨骼遮罩混合
很多动画是只影响局部的,比如鼓掌,这时如果想要不同姿势下的鼓掌怎么办?可以使用一个blend mask去遮住无关的部分,只对需要的部分进行blend,这样还可以减少blending的计算量
1.2.4 Addictive Blending
如果在这个基础上我还想要小人们都冲着我点头怎么办?
使用一个差值形成的difference clip,即加在其他clip上从而产生进一步效果的一种clip。使用时可以加上旋转或缩放来应用其效果。
addictive blending一般使用和制作的比较谨慎,因为随意增加差值容易带来人体超自然扭曲问题。因此在规划人体运动时,应该避免过渡叠加这种动画,避免关节异常。
二,动画状态机Animation State Machine(ASM)
当我们在进行动画设计和融合的时候,会发现有些动画clip是存在逻辑关系的而不是可以任意插值的,比如“跳”这个动作我们一般分为“起跳”、“滞空loop”以及"落地"三个部分,而且其存在明确的顺序关系。因而动画状态机就被引入了进来。
2.1 动画状态机定义
ASM包含“节点node”和“变换transitions”。
2.1.1 节点:分为clip和blend space。
节点可以指动画clip,也可以指把一整个blend space打包成的一个节点,甚至可以把一个动画蓝图放进去当一个节点,总之就是一个可以循环的state。
拿跳跃举例:当角色触发跳跃时,进入了jump start节点;当检测到运动到高点时,就进入jump loop节点循环;直到检测到快要落地时,进入landing节点,landing播放完后,重新进入idle(静息)节点。
2.1.2 Transitions
从一个节点到另一个节点涉及的blending的问题,这里经常会用到magic number 0.2秒去过渡。
但transitions的核心问题在于触发条件,什么时候转换节点,这个触发条件可能是很多个,见下文。
2.2 Cross Fades
Transition的时候,主要有两种方式:
- 常规的smooth transition:即像上述所讲的一样在符合可以同步前提下进行两个动画clip下的blending,动画1越来越少动画2越来越多。
- Frozen transition:动画1先停住,动画2逐渐进来。
以“跑步”切换到“起跳”为例,使用smooth transition会感觉跳起来后仍有部分跑步的样子,使用Frozen transition则会有专门停下来跳起来的感觉。哪种效果好由艺术家决定。
cross fades的方式如下图所示有超多方法,动画技术主要使用linear和“easy in easy out(一般用cubic-bazier曲线表示)”(左边两种)
- 虚幻引擎中的动画节点和transition----老师认为比较下来UE的设计的非常好,很灵活可以自由组合,图标交互等很符合设计师直觉,可以参考该动画蓝图系统
三,动画混合树
3.1 Layered ASM
layered ASM是把角色的不同部位分成不同的状态机去使用,利用不同的状态机去管理身体的不同部分,从而让整个动画看起来更流畅和灵活,如图是鬼泣5的实现,其上半身一层进行复杂攻击,下半身一层进行跑跳,还有一层反应受击。
但随着技术的发展,现在普遍使用的是动画混合树。
3.2 动画混合树
动画混合树就是把Layered ASM的结构用树表示,如图,其中每个非叶节点的产出都是一个pose。
-
动画树的叶子节点与ASM的节点内容一样,是clip、blend space或者蓝图,所以叶子节点本身也可以是一个小动画树。
-
非叶节点是blend node,比较常用的有lerp(二通道lerp直接输入权重,多通道的权重另外输入)、相加(插值动画的addictive blend node)等。
-
动画树的核心作用是控制变量,动画树会定义大量变量暴露给外面的game play系统来进行控制(环境参数速度健康值、以及事件等),而这些变量的值决定了动画的混合行为。通过树的设计,我们只需设置这些变量的值就可以决定最终动画的展现。
-
变量有两种,一种是环境变量,速度健康值血量等;还有一类变量类似于类的private data,通过event事件触发去进行调整。当某件事发生的时候,会改变动画树中的某些变量,从而影响动画混合效果。
-
实际在引擎中计算每个节点的blending时,还会有专门的计算结构去计算其百分比
四,IK技术(Inverse Kinematics)
基本概念:前边介绍的根据动画移动到某个位置属于前向动力学(FK, Forward Kinematics),而根据要到的位置设计动画属于反向动力学IK,从子节点位置反向去计算父节点位置,通常用于处理环境或是其他因素对角色的约束。
IK问题的经典例子是用手抓把手或者走在不平的地上,这时的约束点手腕被称为末端效果器(end-effector)。
4.1 Two Bones IK
例如走路,大腿、小腿长度a\b固定,如果确定了最后要踩在哪个位置,胯部到阶梯处的距离c也可以计算,那么三条边都知道就可以唯一确定一个三角形,就可以确定大腿抬起的角度θ。
但由于这样求解本质是求两个球的交点,会存多个解的问题(因为三角形是平面的,但实际大腿还可以z方向转动,可以变成正弯或者内八外八,因此解是一个圆环)。这时就需要让艺术家提供一个参考方向向量reference vector,在这个方向上找到解。
4.2 Multi-Joint IK
-
在实际情况中 IK 远比这个复杂。实际中参与这个 IK 的关节点不止两个,主要有两个难点:
- 自由度太高,计算花费高:需要实时计算多维的非线性(包括旋转、平移、放缩)函数的解。
- 解有无穷多个:确定了首尾两个目标点,中间的关节点可以随意移动。
-
此时首先要做的第一步是判断可达性(Reachability),而不能达到分两种情况:
- 所有关节的长度加起来也达不到目标点(太远)
- 全身最长的骨骼比其他骨骼的长度加起来都大—近处盲区。(太近)
-
其次很重要的一点是人体骨骼的旋转是有限的,就比如手指的指节处的关节只能沿握手方向转动,而且该旋转的角度也有限制。错误的处理会导致很离谱的扭曲。
那么具体怎么处理呢?由于直接求解高维非线性方程存在的问题,所以在工程中开发出了一些实际好用的方法如下:
4.2.1 CCD(Cyclic Coordinate Decent)
该方法的主要思路是从最末端节点开始向父节点依次遍历,每一次都将末端节点旋转到离目标点最近的位置(该节点与目标点连线上),经过多次迭代可以得到一个近似解。—计算简单,最经典方法
可达性上,一般认为超过设定迭代次数还没有收敛时,就认为不可达。
优化点:
- 限制每次旋转的角度(within tolerance regions公差范围),从而让整个旋转尽量均摊到每个joint上。
- 让越靠近根节点的joint旋转角度越小等
4.2.2 FARBRIK(Forward And Backward Reaching Inverse Kinematics)
意译就是:向前迭代一遍再向后迭代一遍,来解决IK这个问题
具体步骤:
- forward:先把从最后一个节点强行拉到目标位置,这时骨骼会变长;然后再把上一个节点移动到两节点原骨骼长度的位置,这时与下一个骨骼的长度又会变长;再移动下一个节点到原骨骼长度为止……如此反复,直到根骨骼也被移动
- backword:反向进行forward的步骤,先把根节点移回原位置,最后移动末端节点
- 多次重复1、2步骤,末尾节点就会很接近目标位置了。
- CCD和FARBRIK都不能保证完全指向目标点,需要设置公差范围
- 和CCD一样可以限制旋转角度,只需每次移动时移动到限制范围的垂直投影上:
4.2.3 IK with Multiple End-Effectors
前边都只是单一约束点的例子,但实际中经常有多个约束点,比如爬墙攀岩时,双手双脚都被约束了。这时当我们试图把一个点移到它的目标点时可能会让其他已经到位的节点又偏移开。在 CCD 和 FABRIK里也有解决方法,但是不是最优解。
推荐使用雅可比矩阵Jacobian Matrix方法解决,在后续物理系统会详细介绍。
4.2.4 Other IK Solutions其他解决方法(了解)
Physics-based Method:更自然,但是如果没有优化,需要耗费大量的计算。
PBD(Position Base Dynamics):和传统的基于物理的方法不同,有更好的视觉表现,以及更低的计算花费。
-
目前IK 的挑战:
- IK是假设骨骼本身没体积的,但实际上是有的,尤其在蒙皮之后,所以会出现IK后骨骼自我穿插等、重叠等问题。
- 游戏中人物碰到障碍物如洞穴,自然作出下蹲动作,这是设计师提前设计好的。而如果想用IK做到像人那样看到一个物体就就知道提前作出对应动作还是很难的。
- 需要更自然的人物的行为:中心平衡、支撑等。
-
IK技术近10年还在快速发展,感兴趣又数学好的同学可以关注这个方向
-
由于IK技术会改变动画的pipeline,因此十分重要
五,面部动画
人的表情是由43块肌肉横向纵向共同作用组成的,许多微表情非常难以表现。
Facial Action Coding System是电影行业提出的,它把人类常用的表情归纳成了46种标准表情单元(AU, Action Unit),这些 AU 可以融合的。后来 Apple 又把这46个 AU 归纳成28个最核心的AU,其中23个是对称的,这时只要使用28个表情的AU的差值顶点动画(BS)进行融合(一般additive就行)就可以组合成各种表情了----Morph Target Animation。
- 但这种方式存储量大,并且随着表面细节增多计算量也会变很大。
- 因此实际引擎中还是会用骨骼做大量的角色动画,比如眼球旋转、大幅度动作和捏脸系统,都需要用到骨骼
- 针对二维动画,UV Texture Facial Animation也经常使用,它是将不同的纹理贴图来代表不同的表情
- 另外Muscle Model Animation也在发展中(主要在影视行业),它是直接基于物理去驱动面部的43块肌肉来实现各种表情。
六,动画重定向
现在大多数动画都采用动作捕捉来获取,那我如何将采集到的一套动画能够应用到不同角色上?
- 一些术语(terminology):
- Source Character 原角色
- Target Character 目标角色
- Source Animation 原角色动画
- Target Animation 目标动画
6.1 同标准骨骼结构
- 基本操作是将他们的骨骼一一对应,无视具体长短等强行对应
- 对于骨骼的旋转来说,它基于原角色的 Bounding Pose来发生改变,也就是应用的是相对角度;对于平移和放缩,我们考虑两个骨骼的相对长度,然后按照长度进行等比例进行的改变。
- 对于角色的移动来说,我们还需要注意角色的离地高度的不同,对其作出适当的调整。比如说,我们以角色腰线高度为准,将角色的高低进行适当调整,并且一般位移的速度也会根据腰线高度适当放缩。
- 还有一些特殊情况我们会用 IK 来解决。如下图,总腿长一致但大小腿长度不同的角色,他进行一个蹲的的时候会有问题,此时会用IK解决这个问题 , 把脚锁在地面上。-----一般游戏角色固定,会离线做好重定向
6.2 不同标准骨骼重定向
上述所有都是基于大家骨骼架构整体相同的前提,但实际游戏中经常会有不同的,这时候怎么处理呢?
NVIDIA方法:找到对应的两组骨骼,它们之间的骨骼数可能不同(如上图source是四块,target是三块),先把骨骼都长度归一化;针对target骨骼,去找每个骨骼对应source的位置,并适当调整;比如图上黄色第一根骨骼对应0-0.3部分,就把他调整到source的0.0-0.3的位置。
6.3 动画重定向的挑战
- 角色的自穿插(瘦角色和胖角色,瘦角色走路手放在两侧可能刚好,但是胖角色就会穿模)
- 自接触的约束(由于肩宽问题,源角色动作没问题,但是由于肩宽不同,目标角色可能会发生两个手掌碰不到的问题)
- 角色的平衡
- 表情领域也面临动画重定向问题,比如小眼睛的闭眼动画到大眼睛的模型上就闭不上眼,这时可以利用拉普拉斯算子模拟橡皮表面把顶点拉到闭合。