【UE4】面部捕捉+动作捕捉
参考资料:
演奇:【UE4】对自定义角色进行 动作捕捉面部捕捉
最近在帮学校老师做虚拟偶像,因为厦门疫情被迫暂停。研究了一部分内容,还未完全验证可行性,有待后续跟进。
一、前置知识:
3D模型动画的基本原理是让模型中各顶点的位置随时间进行变化。主要种类分为:
Rigid 关节动画、Rig骨骼蒙皮动画、Morph 渐变动画
1.Rigid 关节动画
关节动画的模型不是一个整体的网格体(Mesh),而是分成很多部分,通过一个父子层次结构将这些分散的Mesh组织在一起,父级Mesh带动其下子Mesh的运动,这样各个Mesh的顶点是作为一个整体参与运动的。每个动画帧中,设定好各子Mesh相对于父Mesh的变换(旋转、移动、缩放),通过子到父,一级一级地累加变换,得到该Mesh在整个动画模型中的变换,从而确定每个子Mesh在世界空间中的位置和方向。由于关节动画驱动的是物体的子Mesh,而子Mesh中的每个顶点又是固定在其本身的坐标系中,这样就有可能在两个Mesh的结合处产生裂缝。UE5演示工程《古代山谷》中的“The Ancient”就是用这种办法将五千多万个三角形的高模结合成了一个拥有动画的Boss。
从数学上来说,关节动画中的每个Mesh上的顶点都定义在自己的坐标系中,子Mesh通过父子层级关系,逐级进行矩阵累乘,得到该Mesh在整个模型所在坐标系中的变换,从而确定每个Mesh在世界坐标系中的位置和方向,然后以Mesh为单位进行渲染。
2.Rig骨骼蒙皮动画
骨骼蒙皮动画即Skinned Mesh,拥有骨骼(Bone)和蒙皮(Skinned)两个部分。骨骼拥有和关节动画类似的父子层次结构。骨骼蒙皮动画的关键帧中会存储每个骨骼关节的移动旋转缩放信息。而Mesh上的顶点会依据每个骨骼对它施加的权重(Weight)(即每个骨骼的“影响力”),跟随骨骼进行相应的变换。所谓的蒙皮(Skin)即是对顶点赋予权重(Weight)的过程。相较于关节动画,骨骼蒙皮动画的Mesh为一个整体,而关节动画的Mesh则是分散的。骨骼蒙皮动画不会因骨骼的变换而导致顶点结合处的撕裂。一个骨骼动画通常包括骨骼层次结构数据、网格(Mesh)数据、网格蒙皮信息(Skin info)和骨骼的动画(关键帧)数据。
从数学上来说,骨骼蒙皮动画的Mesh会根据每个骨骼对它施加的权重(Weight)进行线性混合蒙皮(Linear Blending Skinning,LBS),从而让Mesh产生形变,得到的形变结果为数学计算的结果。Mesh的顶点是定义在模型自身坐标系的,即相对于Mesh原点的,而骨骼动画中决定模型顶点最终世界坐标的是骨骼,所以要让骨骼决定顶点的世界坐标,这就要将顶点和骨骼联系起来,蒙皮信息(Skin info)正是起了这个作用。
关于骨骼蒙皮动画的具体相关知识解读请参阅:https://blog.csdn.net/u010270148/article/details/78029589
3.Morph 渐变动画
Morph动画是直接指定动画每一帧的顶点位置,其动画关键帧中存储的是Mesh所有顶点在关键帧对应时刻的位置,再将顶点进行插值运算。Blendshapes(BS)是Morph动画的一种应用。在实际操作过程中,我们会制作好变换后的Mesh,再将变换后的Mesh指定给原Mesh,再通过一个0到1之间的值对Mesh的变化程度进行控制。需要注意的是:BS只能在拓扑结构相同的Mesh之间进行变换,即需要在面数和布线结构都相同的情况下才能产生正确的变换动画。相较于骨骼动画,BS可以直接指定变化后的结果,对于变化的可控性更高,所以常用于表情制作以及对蒙皮后的Mesh进行修形。
总结
关节动画控制的是多个Mesh的位置,关键帧内记录的是每个Mesh的位置信息。
骨骼蒙皮动画控制的是骨骼,关键帧内记录的是每个骨骼的位置信息。顶点根据蒙皮的权重数据完成位置的变换。
Morph动画控制的是顶点,关键帧内记录的是每个顶点的位置信息。
通过对比可知,关节动画由于其Mesh都是独立变换的,无法在Mesh之间形成连续的过度,Mesh的面不会被拉伸和挤压。但也正是因为这点,UE5的Nanite可以将高模适用于关节动画。(待验证)
骨骼蒙皮动画因为不会在骨骼变化后导致Mesh破碎,所以被广泛应用于人物、动物等需要产生Mesh形变的动画。但又因为骨骼是通过权重去影响Mesh的顶点,是数学计算的结果,设计时难以直接对最终效果进行调整。这就会导致需要非常高精确度的权重信息才会得出正确的形变结果。
Morph动画可以直接定义形变后Mesh的形态,所以只需要让其符合形变前模型的拓扑结构便能产生较高精度的结果。但缺点也很明显:需要两份Mesh才能完成一段动画,面数翻倍,数据量巨大。
二、BS制作流程
面部AR示例官方文档:
Epic提供了一套面部AR示例工程,其中的技术结合了Apple的ARKit面部追踪系统。ARKit面部追踪系统使用一个内部的面部网格体,将其包裹到用户的面部,并作为模仿表情的基础。这套系统定义了51套BS姿势,对应了面部的51个部位方向的表情。
eyeLookUpLeft
eyeLookDownLeft
eyeLookInLeft
eyeLookOutLeft
eyeBlinkLeft
eyeWideLeft
eyeSquintLeft
cheekSquintLeft
eyeLookUpRight
eyeLookDownRight
eyeLookInRight
eyeLookOutRight
eyeBlinkRight
eyeWideRight
eyeSquintRight
cheekSquintRight
browInnerUp
browDownLeft
browDownRight
browOuterUpLeft
browOuterUpRight
cheekPuff
noseSneerLeft
noseSneerRight
jawOpen
jawForwardHalf
jawLeft
jawRight
mouthFunnel
mouthPucker
mouthLeft
mouthRight
mouthRollUpper
mouthRollLower
mouthShrugUpper
mouthShrugLower
mouthClose
mouthSmileLeft
mouthSmileRight
mouthFrownLeft
mouthFrownRight
mouthDimpleLeft
mouthDimpleRight
mouthUpperUpLeft
mouthUpperUpRight
mouthLowerDownLeft
mouthLowerDownRight
mouthPressLeft
mouthPressRight
mouthStretchLeft
mouthStretchRight
关于表情的制作有多种思路:
思路一、找到一个已经做好51套BS的素材,使用晶格体包裹的方法直接将素材BS重定向到自己的模型(效果较差),再重新手动修形。
BS晶格体包裹重定向:
BS手动修形:
思路二、使用ADV插件生成BS(推荐)
新版ADV插件对Apple ARkit做出了适配,我们可以使用ADV生成51套BS。
首先需要在绑定类型里面选择Blendshapes并勾选apple arkit,
然后对面部进行绑定,相关教程:
https://www.bilibili.com/video/BV1X4411n7yb?p=7&spm_id_from=pageDriver
生成控制器后可以在面部控制器看到一个Apple的logo,点击之后右侧便会出现51套BS。可以逐一测试,如果有问题再手动修形。
思路三、骨骼动画+BS修形(此思路可能会和诺亦腾动补骨骼冲突,待验证)
官方并没有全部使用BS来制作表情,而是将20个部位使用骨骼蒙皮动画进行制作,原本51套BS中对应的20个曲线是对骨骼动画的校正和修形。
早期版本的ADV没有对ARkit的支持,需要手动修改51个BS,所以采用了这种办法。这种方法相对比较麻烦,但精确性更高,有相关需求可以采用。
这种方法需要先制作头部骨骼蒙皮绑定,然后使用动画+Blendshape混合制作。
动画的第一帧(0帧)一定要是空的,后面的每一帧表情都会和第0帧对比,在引擎中生成Pose。
后面的每一帧用蒙皮动画去K出对应51个BS中的一处即可。
jawopen涉及到的口腔牙齿舌头动画可以做成blendshape,单独的牙齿舌头模型(一个jawopen blendshape),然后Shift加选主体脑袋(选中jaw open blendshape),然后Ctrl+J合并一下就好啦。
官方做了1帧参考帧+20帧对应BS的表情帧,可以依据需求,在限定的51个表情内制作更多的表情帧。
四、导出设置
在Maya的窗口——动画编辑器——形变编辑器里面可以看到所有的Blendshapes。
使用思路二ADV会生成很多自带的BS用于表情控制,可以只保留51套BS,其余的删除。
在导出请前检查BS名称是否和之前列出的能对上,否则会导致动画蓝图无法读取到BS信息的情况。
导出:
1. 选中骨骼+模型
2. 文件——发送到Unreal——选择,出现选择Unreal项目以发送FBX资产,建议选择工程文件下的Content文件夹
3. 设置名称,建议以SK_作为前缀
4. 检查设置,需要勾选平滑组、动画、烘焙动画、蒙皮、混合变形
Maya会自动在Unreal项目中创建一个Import文件夹,同时坐标轴也会自动调整成Unreal的坐标。
三、引擎流程
1.导入设置
导入骨骼网格体,需要勾选“导入变形目标(Import Morph Targets)”
如果是使用思路三制作骨骼动画和BS,则需要勾选”导入动画(Import Animation)”
2.动画蓝图
在导入引擎之后,我们需要为面部的网格体制作动画蓝图
a. 打开骨骼网格体
b. 为网格体创建动画蓝图
c. 创建函数,命名为InEditorOffsets
d. 在函数处创建变量CalibrationOffsets,然后直接将示例文件内的相应节点复制到创建的函数内。(所有导入进来的Morph Target (BS)都会自动转换为Anim Curve以供动画蓝图使用。此处是在调用这些曲线并封装成函数)
e. 回到AnimGraph,创建Live Link Pose节点。(这里会把捕捉到的面部数据输入,用于调整后面的曲线。)
f. 创建Modify Curve,调节曲线混合模式为Weighted Moving Average。创建变量WMA Alpha,类型为float,默认值为0.8。(此处作用是利用WMA Alpha通过加权移动平均法整体调整输入的面部数据,消除微弱的抖动)
g. 调用CalibrationOffsets,把封装好的曲线Break出来,供面部数据调用。
h. 在调用完曲线后,可以对曲线进行任意的混合调整。此处为对眨眼的修正。
i.官方示例中存在一个Pose资产,注释为驱动骨骼旋转
如果使用了上面说到的思路三去制作BS(面部带骨骼),那么就需要在引擎中制作PoseAsset。
将思路三制作的动画导入,选中动画,按如下方式制作成PoseAsset
使用思路二制作则不需要制作这一步。
j. 打开角色的骨骼,在动画曲线处(AnimCurves)自行右键添加三条曲线,并命名为headYaw、headRoll、headPitch。
调用添加的曲线,用于控制头部骨骼的旋转。
请注意输入的顺序,headYaw被输入Roll,headRoll被输入Pitch,headPitch被输入Yaw。由于Apple的Metal和UE的DirectX使用了不同的坐标系,此处需要转化。(待验证)
控制头部旋转的骨骼有两个,head、neck都需要接收曲线控制。这里需要注意父子级顺序。(待验证)
k. 输出动画蓝图
到这里,面部绑定完成,已经可以对角色表情进行测试了