虚幻4渲染编程(动画篇)【第二卷:动画系统源码分析】

我的专栏目录:

小IVan:专题概述及目录​zhuanlan.zhihu.com图标

这一节没有具体的效果实现,只是把动画系统捋一下。如果想掌握一个系统,首先还是要从原理入手吧,知道它底下都干了什么。

我是一个技术美术,代码能力有限,如有错误还请各路大神指正。

我们先捋一下这几个类的关系

我这里就直接上截图了:

v2-ce2f28810d76dfd9a6e6eeb083c7299e_b.jpg

可以看到

如上图所示可以看到是这么一个关系(XXX可以不用去管它暂时,这些不是我们关心的重点)

从UObject到UMeshComponent是图元汇编的基础,骨骼模型其实也是属于图源汇编阶段范畴的,这部分的分析在我的图元汇编篇有详细描述了(图元汇编篇第一节传送门)

小IVan:虚幻4渲染编程(图元汇编篇)【第一卷:CableComponent的原理及Unity实现】​zhuanlan.zhihu.com图标

下面来主要研究是后半部分。

我们来到USkinnedMeshComponent,找到CreateSceneProxy,可以看到这里在抽取我们导入的骨骼模型资源的渲染资源数据:

v2-a747a67b544b00944bc28dd26cbd8dff_b.jpg
v2-00dab2e5e2be9705177a8a188413f395_b.jpg

这里的思路和我们之前抽取staticmesh资源数据的思路是一样的(详见图元汇编篇第四卷),只不过这里是骨骼模型资源数据罢了。

抽取了模型资源之后就是进行渲染操作啦,渲染逻辑在这里:

v2-b04495396bb37783850d6eb514d05209_b.jpg

在骨骼更新之前我们下断点,可以看到如下画面

v2-554d460d319076d52663be4e525cd42e_b.jpg

如果不进行骨骼Transform的更新,我们得到的只是一个TPose,要让它动起来,我们需要更新骨骼数据,骨骼数据再驱动模型,从而动起来。

这里进行骨骼的transform计算

v2-6de97d42b1ec3e9328a04f5e5fc11902_b.jpg

在RefreshBoneTransform会调用动画数据的收集

v2-9aa0378b82774e2636faa460143d050c_b.jpg
v2-94ce4e69eb1386a50a571d039bdc5fa4_b.jpg

完成FillComponentSpaceTransforms之后,就能看到我们的骨骼数据了

v2-39c339de2f5439f2cb2494889c4517aa_b.jpg

然后人物动了起来

v2-46588bfe63d666d9ecbc7cdc2afe0352_b.jpg

那么问题来了,这些函数的数据是哪里来的呢,这些函数是如何填充骨架transform的呢,于是我们找到了如下代码

v2-6d41e676afac5e0b3ac4629e483029a0_b.jpg

看到EvalueateAnimationNode之后一切就清晰了,这些数据是抽取的AnimationNode的。这些AnimationNode在哪里呢?答案就在下图。

v2-52d2ccb4d3ad34a5c68855859450cea8_b.jpg

这些AnimNode会去采集UAnimationAsset种的曲线数据,这些Node控制动画的混合,输出。

就拿TransformBone节点为例,我们它的evaluate函数打个断点

v2-ec2894aeaa6ce8b5ac63a759e78fc9d0_b.jpg

一切已经非常清晰了。

再来是Update的顺序,使用过动画蓝图的话,就会对NativeUpdateAnimation这个函数非常熟悉了。那么动画蓝图的update和骨骼的update是谁先谁后呢

v2-cbef2d33bda25d729268a1e601933732_b.jpg

(一部分)勾的函数就会调用NativeUpdateAnimation,可以看到,动画蓝图的update在骨骼transform的update之前。


最后来总结一下虚幻的动画系统

(1)动画系统所用到的资源

当我们把动画模型资源导入引擎,会生成以下几个原始源文件

【1】动画模型网格资源

v2-756c60acdc6caa7e333ab061a7fdadcb_b.jpg

它储存了模型资源的信息,如顶点,索引缓冲,蒙皮权重,顶点格式工厂类型,顶点uv和法线,morph等等信息。

【2】物理资产

v2-9f15e12b732637f29899a6d191d2321f_b.jpg

与物理相关的资产,由骨架信息生成

【3】骨架资产

v2-0eb1837c03ba7a96aa1a52d9b16981b3_b.jpg

储存了骨架树等信息

【4】动画资产

v2-78a7f1071c25c767b647a2a4095ac690_b.jpg

就是存的动画曲线信息,至于什么AnimMontage,BlendSpace这些,是把这些动画资产进行组合,然后采样动画资产信息的时候会按照这些组合方式进行采样。以blendspace1D为例,在采样动画数据的时候,会把动画A和动画B按照Alpha进行混合。

(2)动画蓝图

动画蓝图主要分为两部分,一部分是AnimInstance,一部分是AnimGraph。

v2-4bea4e1c47ba1471999f95a49a1d5ef2_b.jpg

AnimInstance会在AnimGraph之前调用更新,AnimInstance更像是个数据处理器,处理好了数据再给后面阶段的AnimGraph用。AnimGraph负责组织AnimNode,每个AnimNode里面封装了一部分对骨骼的操作逻辑,比如IK或者lookAt等等。RefreshBoneTransforms会去调用AnimGraph所组织的AnimNode的Evalueate方法来刷新骨骼的transform。这些transform再被提交给渲染线程。渲染线程的GetDynamicElement再把信息传给DrawingPolicy然后绘制。

简而言之就是,我们用AnimInstance控制数据。然后我们再用AnimInstance计算出的数据来操作AnimGraph进而来控制骨架的运动。场景代理再把我们算出的骨架数据传给渲染线程,渲染线程再把变形后的模型画出来。

(3)动画状态机

动画状态机到底是个什么。

v2-ef8479eb79512251c29ee245ebe6b21e_b.jpg

其实它就是一个比较复杂的AnimNode(动画节点)而已!不要把它想得那么高端。

下面通过一系列图来形象再描述一下动画状态机的作用:

假设现在我组合好了一个人物再站立时候的AnimGraph01

v2-3186fb7ad0a8304036eed45dc6faa428_b.jpg

然后我又组合出了一个跑步的AnimGraph02

v2-e41747c97f60cf193ca51eec8d51af20_b.jpg

我现在需要根据不同的条件来切换这两个graph,于是状态机横空出世。可以把状态机理解为一个超级复杂的if节点。如果什么什么条件,输出AnimGraph01的数据,如果什么什么条件输出AnimGraph02的数据。

用材质编辑器的思路来对比学习一下:

v2-04e10b3383d7d533b310057686d962d5_b.jpg

这里只是举个方便理解的例子哈,原理肯定是完全不一样的。原理的具体分析在文章前半部分了。

搞清楚这些原理之后,动画系统状态机的构建等操作就再也不在迷茫了。我看有很多人想尽各种办法,硬背参数和节点用法都来了。感觉没什么必要哈。


虚幻4动画系统大的骨架就是这样了,当然还有很多小的细节,不过这些细节都是建立在这个大的流程上的。比如AnimNotify,如何采样动画数据混合等等。

我只是个美术,代码功力有限。如有错误,还请各路大神留言斧正。

Enjoy it !

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cpongo11

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值