骨骼动画的原理及在Unity中的使用
制作骨骼动画

我们看看这几步操作后,我们得到了那些数据:
1.每个皮肤顶点的初始世界坐标。
2.每个骨骼关节顶点的初始世界坐标。
3.每个顶点被骨骼顶点的影响信息。
4.骨骼如何移动。
骨骼动画原理
核心: 通过骨骼带动皮肤运动,也就是通过骨骼的移动动态计算mesh上的点的位置
过程:
1.将mesh上的点转换为骨骼空间上的点。
骨骼空间就是以关节为原点确定的空间,并不是一个实体。
2.通过缩放、旋转、平移将骨骼移动到新的位置。
3.根据骨骼的新位置计算mesh顶点新世界坐标(骨骼移动,但mesh顶点与骨骼的相对位置不变,所以产生了顶点随骨骼移动的感觉),若一个顶点被多个骨骼影响,则要进行顶点混合计算新世界坐标。
举例
初始位置(绑定姿势):

骨骼移动后的位置:

1.计算小臂上一点S在小臂空间中的位置。
这个就要根据初始的骨骼位置和mesh上顶点的位置来计算了,也就是常说的绑定姿势状态。
先说一下该例中每个坐标的意义:
(x1,y1,z1):左肩关节SL的世界坐标。
(x2,y2,z2):左肘关节在以左肩关节为原点的坐标系本地坐标。
(x3,y3,z3):附着于左小臂上的皮肤上的一点S的世界坐标。
这里为了简单,假设所有的关节都没有经过旋转和缩放。
先将S转换到通过SL确定的空间中,也就是大臂UAL空间,直接减去SL的坐标即可(x3-x1,y3-y1,z3-z1)。
再将S点在大臂UAL空间中的坐标转换到小臂LA空间中,直接减去EL的坐标即可(x3-x1-x2,y3-y1-y2,z3-z1-z2)。
以上只是一个简单的说明,而实际的使用中,初始的骨骼位置可能是通过缩放、旋转、平移后得到的,一般会通过矩阵的方式来表示这一系列变换。
关于OpenGL中的坐标转换可以参考这个链接的说明LearnOpenGL CN。
看完这个我们就应该知道如何将一个子坐标空间的点转化为世界坐标了。下面再使用该例子进行举例。
先计算模型矩阵再求模型矩阵的逆矩阵:

或者直接将求模型矩阵的运算反过来也可以:

得到World→EL矩阵后就可应直接通过矩阵运算直接将世界坐标上的一点转化为EL空间上的一点了。

注意:
1.注意矩阵的运算顺序,因为矩阵运算是不满足交换率的,如果顺序错了,结果很可能也就错了。
2.矩阵EL→World一般叫做EL空间的模型(model)矩阵,矩阵World→EL一般叫做EL空间的绑定姿势矩阵(bindpose)
3.有时存储的Mesh顶点信息不是直接的世界坐标,而是一个有层次结构的mesh,但这并不影响流程,只要在运算时增加一步将这些顶点转化为世界坐标的操作即可。
2.计算EL顺时针旋转90°后S点的位置。
直接通过左肩SL,左肘关节EL的缩放、旋转、平移信息计算小臂LA空间的模型矩阵,使用上一步算出的小臂LA空间坐标乘以该模型矩阵即算出了该点收到骨骼移动的影响后的位置。

3.顶点混合
有一些顶点不一定只受一个骨骼的影响,可能受多个骨骼的影响,此时就要通过顶点混合计算该点的新坐标。
现在假设点S同时受SL,EL的影响且影响权重分别为0.4,0.6。
①分别计算点S在SL、EL空间中的本地坐标。

②分别计算点S在SL、EL移动后的世界坐标。

③根据SL、EL对点S的影响权重混合坐标,获得新的世界坐标。

这里举例的是受两个骨骼影响的情况,受3个、4个时原理也是相同的,只不过运算量会更大一些。
小结
1.空间的平移、旋转、缩放都可以用矩阵来表示,而且这些矩阵也可以结合在一起成为一个矩阵,多层空间结构的变换也一样可以组合为一个矩阵。
2.现在看来骨骼动画的核心其实就是几个矩阵乘法的问题,大概就是这样:

其中model矩阵随着动画的播放不停的变化,也就实现了骨骼带动皮肤的功能。
假设一个顶点受多个骨骼影响,那么就再根据权重混合一下。
3.mesh的初始位置、bindpose、影响因素都是通过制作该骨骼动画模型时确定的,可以参考第一小节制作骨骼动画的过程。
Unity中的骨骼动画
我们这里以一个Mixamo上的免费资源Samba Dancing为例。
资源下载


资源导入
直接将资源拖入Unity中即可,可以看到在Unity中生成了一个文件夹和一个预制件。

加入动画
1.把模型prefab拖入场景中。
2.然后将mixamo.com动画拖到场景中的Samba Dancing中,Unity会自动生成对应的Animator Controller。

运行场景,查看动画效果
直接点击运行即可。
数据说明
动画数据说明:

左边是每一帧变化的骨骼,右边是每个骨骼关键帧的平移,旋转,缩放信息。
模型信息说明

Skinned Mesh Renderer属性详解
Cast Shadows:是否投射阴影。
Receive Shadows:是否接收阴影。
Materials:材质。
Use Light Probes:是否使用光探针。
Reflection Probes:反射探针设置。
Anchor Override:网格锚点。
Lightmap Parameters:光照烘培参数。
Quality:每个顶点最多收到的骨骼影响数量。
Update When Offscreen:当mesh在屏幕外时是否更新,依据RootBone和Bounds判断。
Mesh:Mesh信息。
mesh信息包含了每个顶点的位置信息,受骨骼影响的权重信息、切线、法线、UV映射信息。
RootBone:根骨骼,有两个作用。
1.作为mesh在屏幕外时是否更新的依据。
2.进行坐标计算时的Root空间。
在Unity中计算mesh上一点位置的流程大概是这样的:

先通过上述一系列计算得到点在RootBone空间中的位置,上述过程对开发者时不可见的。然后将接下来的步骤交给Material中的Shader解决。查看Shader文件可以看到,在顶点着色其中第一步会给输入的点乘以一个MVP矩阵获取该点在屏幕上的位置,其中的M就是RootBone的模型矩阵。
以Unity 5.37的Standard Shader为例,截取其使用的顶点着色器的一部分
VertexOutputForwardBase vertForwardBase (VertexInput v)
{
UNITY_SETUP_INSTANCE_ID(v);
VertexOutputForwardBase o;
UNITY_INITIALIZE_OUTPUT(VertexOutputForwardBase, o);
UNITY_TRANSFER_INSTANCE_ID(v, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
float4 posWorld = mul(unity_ObjectToWorld, v.vertex);
#if UNITY_REQUIRE_FRAG_WORLDPOS
#if UNITY_PACK_WORLDPOS_WITH_TANGENT
o.tangentToWorldAndPackedData[0].w = posWorld.x;
o.tangentToWorldAndPackedData[1].w = posWorld.y;
o.tangentToWorldAndPackedData[2].w = posWorld.z;
#else
o.posWorld = posWorld.xyz;
#endif
#endif
可以看到,通过posWorld = mul(unity_ObjectToWorld, v.vertex);对顶点以RootBone空间为基础做了转换。
Bounds:根骨骼的边界。
如果有什么错误,希望各位在博客下留言指正,我会尽快改正。
骨骼动画的原理及在Unity中的使用的更多相关文章
- 动画重定向技术分析和Unity中的应用
http://www.jianshu.com/p/6e9ba1b9c99e 因为一些手游项目需要使用Unity引擎,但在动画部分需要使用重定向技术来实现动画复用,考虑到有些项目开发人员没有过这方面的经 ...
- Unity3D 骨骼动画原理学习笔记
最近研究了一下游戏中模型的骨骼动画的原理,做一个学习笔记,便于大家共同学习探讨. ps:最近改bug改的要死要活,博客写的吭哧吭哧的~ 首先列出学习参考的前人的文章,本文较多的参考了其中的表述: 1. ...
- 浅谈Unity3D 骨骼动画
转载请标明出处http://www.cnblogs.com/zblade/ 最近研究了一下游戏中模型的骨骼动画的原理,做一个学习笔记,便于大家共同学习探讨. ps:最近改bug改的要死要活,博客写的吭 ...
- CSharpGL(50)使用Assimp加载骨骼动画
CSharpGL(50)使用Assimp加载骨骼动画 在(http://ogldev.atspace.co.uk/www/tutorial38/tutorial38.html)介绍了C++用Asism ...
- three.js之初探骨骼动画
今后的几篇郭先生主要说说three.js骨骼动画.three.js骨骼动画十分有意思,但是对于初学者来说,学起来要稍微困难一些,官方文档比较少,网上除了用圆柱体的例子就是引用外部模型的,想要熟练使用骨 ...
- three.js 自制骨骼动画(一)
上一篇郭先生解析了一下官方的骨骼动画案例,这篇郭先生就要做一个稍微复杂一点的骨骼动画了,就拿一个小人下手吧.在线案例请点击博客原文.话不多说先上大图 骨骼动画在GUI上面都有体现.制作骨骼动画的步骤在 ...
- Unity 2D骨骼动画2:创建真实动画
http://bbs.9ria.com/thread-401781-1-1.html 在这个系列,我们将关注Unity引擎提供的基于骨骼动画工具.它的主要思想是为了把它应用到你自己的游戏来介绍和教基本 ...
- 动画重定向技术分析及其在Unity中的应用
前言 笔者新的手游项目使用Unity引擎,动画部分要使用重定向技术来实现动画复用.笔者之前在大公司工作的时候对这块了解比较深入,读过Havok引擎在这部分的实现源码,并基于自己的理解,在公司自研的手游 ...
- Unity3d动画脚本 Animation Scripting(深入了解游戏引擎中的动画处理原理)
也许这一篇文章的内容有点枯燥,但我要说的是如果你想深入的了解游戏引擎是如何处理动画片断或者素材并 让玩家操控的角色动起来栩栩如生,那么这真是一篇好文章(当然我仅仅是翻译了一下) 动画脚本 Anim ...
随机推荐
- SQLPLUS SQLCMD连接管理oracle sqlserver的简单用法
1. SQLPLUS 与plsql一样,其实不需要安装oracle客户端,只要是有sqlplus的即时客户端 以及将目录放置到path或者是相应的oralce_home变量中即可. 打开运行cmd s ...
- centos7安装浏览器
firefox(火狐) sudo yum install firefox chrome(谷歌) 添加源:sudo wget http://repo.fdzh.org/chrome/google-chr ...
- python学习笔记十——模块与函数
第五章 模块与函数 5.1 python程序的结构 函数+类->模块 模块+模块->包 函数+类+模块+包=Python pyth ...
- rabbitmq安装与使用总结
一.随着公司业务量的增加,原本部署在Windows服务器的RabbitMQ集群(3.6.1)总是出现莫名其妙的问题,经查询官方Issue,确认是RabbitMQ 3.6.1 版本的bug.查看从3.6 ...
- Guava的RateLimiter在单机限流中的正确用法
错误使用 在实现限流时,网上的各种文章基本都会提到Guava的RateLimiter,用于实现单机的限流,并给出类似的代码: public void method() { RateLimiter ra ...
- appium框架感悟
个人觉得 所谓框架 最终结果就是对存放的元素进行处理 从底层获取数据 往上层传输数据过程中 对其一步一步的封装 由繁到简 再由繁至简
- BZOJ4399魔法少女LJJ——线段树合并+并查集
题目描述 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了LJJ感叹道“这里真是个迷人的绿色世界,空气清新.淡雅,到处散发着醉人的奶浆味: ...
- BZOJ1036[ZJOI2008]树的统计——树链剖分+线段树
题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ...
- BZOJ4650 NOI2016优秀的拆分(后缀数组)
显然只要求出以每个位置开始的AA串数量就可以了,将其和反串同位置的结果乘一下,加起来就是答案.考虑对每种长度的字符串计数.若当前考虑的A串长度为x,我们每隔x个字符设一个关键点,求出相邻两关键点的后缀 ...
- hdu 3727 Jewel (可持久化线段树+bit)
链接: http://acm.hdu.edu.cn/showproblem.php?pid=3727 题意: 对一段序列进行四种操作: Insert x :在序列尾部插入一个x: Query_1 s ...