首页 GAMES104-Lecture 08 游戏引擎的动画技术基础
文章
取消

GAMES104-Lecture 08 游戏引擎的动画技术基础

Challenges

可交互性和动态变化的动画:

  • 在游戏中不能预设玩家的行为

  • 游戏中的动画要和很多gameplay互动

  • 受制于周围的环境

实时:

  • 每一帧都要计算

  • 动画数据很大

真实度:

  • 更生动

  • 表情

Basics of Animation Technology

2D Animation

  • Sprite animation

  • Sprite-like animation technique in pseudo-3D game:在各个视角采了一系列的位置,根据相机的位置播放不同的sprit动画

  • 粒子系统:是一个序列帧

  • Live2D:

    • 把角色的所有元素分解成一个一个的小图元,通过旋转、放缩、变形

    • 给所有的图元设置深度

    • 给每一个图元生成一个控制网格

    • 设置key frame

3D Animation

  • DoF(Degrees of Freedom)

pFi7hIx.jpg

  • 6DoFs:平移的三个自由度(xyz),旋转的三个自由度(xyz)

  • Rigid Hierarchical Animation:层次结构刚体动画

    • 问题是骨骼转的时候mesh彼此会穿插
  • Per-vertex Animation:顶点动画

    • 把每个顶点的offset按时间序列存在一个texture里面

    • 横轴是每个顶点的offset(有时也会把法线存下来)

    • 纵轴是时间

pFi75i6.jpg

  • Morph Target Animation(也是一种顶点动画)

    • 在顶点之间的Key Frame去插值
  • 3D Skinned Animation

    • 蒙皮动画,每个顶点受到多根骨骼的影响,来保证在运动的时候是水密性的,不会互相穿插
  • 2D Skinned Animation

  • Physics-based Animation

    • 布娃娃系统Ragdoll

    • 衣料模拟

    • Inverse Kinematics(IK)反向动力学

      • 给定一个指定点,角色该怎么运动才最自然
  • Animation Content Creation

    • 在编辑器里手key动画

    • 动作捕捉

Skinned Animation Implementation

  • How to Animate a Mesh

    • Mesh:先做一个网格

    • Skeleton:为网格适配一套骨骼

    • Skinning/Rig:刷上一层蒙皮,给每一个顶点设置骨骼的权重(也就是顶点收到哪个骨骼影响大,影响小)

    • Pose:让骨骼按照指定的动作动画

    • Animation

  • Different Spaces

    • World Space

    • Model Space:以模型为中心的space

    • Local Space:局部坐标系,每一根骨骼会平移旋转,每个骨骼的坐标系是不同的,坐标系会传递

    • 把Local坐标系从根节点,一路积分上来,才能算出model space,然后考虑模型的位置和旋转,才能再转换成世界坐标系,然后才能被渲染

pFi7fd1.jpg

  • Skeleton for Creature

    • 人的骨骼,root一般在胯部,Pelvis,脊椎末端

pFi72L9.jpg

  • Joint vs. Bone

    • Joint关节:会直接存储关节的数据,因为关节会带动bone动,不会直接存储bone的数据

    • joint是有很多自由度的

    • joint是一个刚体,不会被twist(扭曲),但Bone会

pFi7yzF.jpg

  • Humaniod Skeleton in Real Game

    • 人脸上可能要加很多骨骼来做细节、翅膀、斗篷的骨骼

    • 所以要提前设定好标准骨骼数是多少

  • Joints for Game Play

    • 武器要mount(镶嵌)到手上的武器joint上

pFi7cM4.jpg

  • Root Joint

    • 脚的中心,用来判断离地高度

    • Pelvis joint是root joint的第一个child joint

pFi7WZR.jpg

  • Horse Skeleton

    • 四足动物的尾椎骨是Pelvis joint

    • root在肚子下面

pFi7gsJ.jpg

  • Bind Animation for Objects

    • 一些object是有父子关系的,有些动画是绑定的

    • 在人的身上有一个Mount的joint,马鞍位置也有一个Mount的joint,这两个joint重合在一起,不仅是位置重合,旋转也是重合的;人和车也有

pFFBYOe.jpg

  • Bind Pose - T-pose vs. A-pose

    • T-pose角色的肩膀部分其实是挤压的,所以目前一般就会给A-pose,这样肩胛处精度会高一点
  • Skeleton Pose

    • 骨骼一个动作静止的状态叫做pose

    • 把pose连在一起就是一个动画

    • 在真正表达一个动画的pose的时候是有9个自由度的9DoFs,也就是放缩

Math of 3D Rotation

  • 2D Orientation Math

pFFBGQO.jpg

  • 3D Orientation Math

pFFBJyD.jpg

  • Euler Angle:Yaw航向角、Pitch攻角、Roll横滚角

pFFBKoR.jpg

  • 转的顺序不同,效果也不同

  • Gimbal Lock万向结

    • 陀螺仪:可以用来测导弹的轨迹

    • 稳定器

  • Degeneration of Euler Angle

    • 当一个轴转了90度时死锁
  • Problems of Euler Angle

    • 难以插值

    • 欧拉角的叠加很难

    • 容易沿着xyz轴转,但难以沿着其他轴转

  • Quaternion 四元数

    • Complex Number(复数)and 2D Rotation

pFFBQF1.jpg

  • Quaternion,模、共轭(虚部全部取负数)、逆(normalized的四元数的共轭就是它的逆)

pFFBlJx.jpg

  • 在做旋转的时候,需要先乘以q转换为四元数,旋转完后再乘以q^-1

  • Rotation Math by Quaternion

pFFB1W6.jpg

pFFB8SK.jpg

pFurI8U.jpg

pFurTv4.jpg

  • Given Axis Rotation by Quaternion

pFuro2F.jpg

Joint Pose

  • Orientation(朝向,其实rotation就是改变Orientation)

    • 大部分骨骼动画是旋转
  • Position:Pelvis、facial joints和一些特殊的joints才会发生位置的变化

  • Scale:面部变化可能会使用scale

  • Affine Matrix:joint表达的核心仿射矩阵,与透视矩阵不同的是不需要除以w,因为这是在一个永远正交的空间中进行变换(应该是最后光栅化的时候才会做投影)

pFurh5V.jpg

  • 关节在变换的时候,其所有父关节local space变换矩阵的乘积等于当前关节model space的变换矩阵

pFur2bn.jpg

  • 为什么要把所有的坐标信息存到局部坐标系呢?

    • 如果在model space进行插值,进行的是平移变换,那么骨头的长度会发生变换

    • 而在local space进行插值,进行的是旋转,所以此时骨头长度是正常的没有发生长度的变化

pFurWEq.jpg

  • Single Jpint Skinning

    • 每一个顶点都可以用一个权重参数被绑定在一个或多个joint上面(但最好不要超过4个,一般会用一个byte来存这个限制数量)

    • 当关节在动的时候,绑定在这个joint的顶点也要跟着移动才对

    • Skinning Matrix:动画矩阵,当一个顶点绑定了某个joint后,顶点的原位置乘上这些joint的Skinning Matrix就可以获得变换后的位置

pFurfU0.jpg

pFur5CT.jpg

  • Skinning Matrix Pallette:动画矩阵的表,有三部分,首先是模型坐标系到世界坐标系的变换矩阵,依赖的joint在模型坐标系下的最终pose,绑定的joint模型坐标系下变换矩阵的逆

pFuyonJ.jpg

  • Weighted Skinning with Multi-joints

    • 如果绑定了多个关节,那么权重和要为1

pFuy5X4.jpg

  • Weighted Skinning Blend:分别算出顶点关于每个joint变换后的位置(根据上面的方法),然后根据权重插值(必须要在模型空间,不能在local space,因为每个joint的local space是不同的)

  • Interpolation between Poses

    • 对于位移和scale,使用线性插值就可以

    • 但是对于旋转不行,需要在q1和q2的插值基础上做一个Normalization,这样就能得到正确的插值,这个方法叫做NLERP;问题是这个旋转的速度是不均匀的,所以有了SLERP

    • Shortest Path Fixing of NLERP:最短路径的插值,因为一个位置转到另外一个位置,有两种转法,一个是直接最短路径转到,另一个是转一圈后才转到

pFuyfpT.jpg

  • SLERP:Uniform Rotation Interpolation

    • 找到两个q(四元数)之间的夹角,根据当前位置的θ角进行一个插值,但缺点就是反三角函数的运算比较费(因为要查表去算)

    • 用sinθ做分母是不稳定的

    • 所以最终的措施是结合NLERP和SLERP

    • 夹角小用NLERP,夹角大用SLERP

pFuygkq.jpg

Simple Animation Runtime Pipeline

pFuy2t0.jpg

  • 首先有大量动画的clips

  • 根据上一帧和下一帧来插值出当前的pose

  • 转换到model space里

  • 计算出每个骨骼的Skinning Matrix Palatte

  • 然后进入gpu,计算顶点位置

Animation Compression

  • 动画数据存储数据量很大

  • 每个人的模型有70个关节,每个关节要在每秒钟存30个pose,每个pose包含平移旋转和放缩

  • 但是很多数据其实是不变的,比如scale,很多情况下都是1,很多位移的local position也是不变的,变的最多的是rotation,rotation中也有经常变和不经常变的

pFuyh1U.jpg

Simplest Compression - DoF Reduction

  • 丢弃掉不变的track,比如scale track,在人形骨骼中,除了面部基本都不会变

  • 丢弃掉translate track,在人形骨骼中,除了pelvis、facial joint和特殊的joints外也基本不变

Keyframe

  • keyframe extraction-Linear Keys Reduction:剔除原来pose里的非关键帧,根据插值出来的pose和实际pose来算error,只要error在阈值之下就选取作为关键帧,优点是线性插值计算简单,缺点就是为了减小error往往要打很多的关键帧

  • Ctamull-Rom Spline:一个三阶多项式曲线,这个曲线很平滑

pFuyRhV.jpg

  • Float Quantization:浮点数32bit,存储量很大,所以可以把float的值先映射到(0,1),然后再映射到(0,65535),也就是一个16bit的无符号整型

pFuy4cF.jpg

  • Quaternion Quantization:如何对一个四元数进行定点压缩呢?

    • 当对四元数归一化压缩后,虽然每一个数都有可能在[-1,1],但如果把最大值丢掉,那么另外三个数一定在 $ [-\frac{1}{\sqrt {2}},\frac{1}{\sqrt {2}}] $ ,那么就需要只用2个bit记录下哪一位是最大值,然后记录剩下的三个值,最后根据归一化反向算法(其实就是根据记录的三个值算剩下一个值),算出所有值,也就是说,每一个虚部只需要使用15bit,所以最后存一个四元数就用3个无符号整型就可以,也就是48bit;反之,如果用4个float存,那就是128bit

    • Error Propagation:error会传递下去,前几个error还行,当传到最后几个骨骼的时候,error就会很大了,所以压缩算法可能出现这样的问题;

    • Joint Sensitivity to Error:不同的joints对error的敏感度不同,比如在手的地方,压缩算法做不好就会动画抖动

  • Measuring Accuracy

    • data error

    • visual error:难以去计算每个顶点的visual error,在每一个joint设置两个垂直于它的点,通过设置offset的大小来控制error,因为不同骨骼对于error敏感度不同,设置的offset就可以不同

pFKAVuq.jpg

  • Error Compensation-In Place Correction

    • 因为计算是传递的,所以下一个joint对上一个joint产生的error进行补偿

    • 产生的问题就是,在末端骨骼的动画数据一般是平滑的低频数据,但是为了给上面的joint补偿而变得高频,比如产生抖动

Animation DCC Process

  • Mesh:先构建mesh,美术构建的是高精度mesh,但是做动画会使用low poly;在动画关节的地方会额外加几圈mesh

  • Skeleton binding:在现代的软件中,搭好T-pose或者A-pose后,使用工具中的骨架然后一个个对上;加上武器、pelvis、root的骨骼

  • Skinning:现代软件都是自动计算,根据深度学习之类前沿的算法计算出来,动画师也可以自己调整,每一根骨骼对顶点的权重是多少

  • Animation creation:设置关键帧和关键帧之间的时间间隔

  • Exporting:root不会跟动画一起存下,而是会单独导出来一个位移曲线来给引擎用

pFKAAvn.jpg

本文由作者按照 CC BY 4.0 进行授权