3DsMax动画插件
* 简易骨骼动画:
Mesh当前帧顶点 = Mesh绑定时顶点 * 绑定时骨骼的变换到本帧骨骼的变换的改变量。
= Mesh绑定时顶点 * 绑定时骨骼的变换的逆矩阵 * 本帧的骨骼变换。
= Mesh绑定时顶点 * 绑定时骨骼的变换的逆矩阵 * 本帧的骨骼相对父节点的变换 * 本帧父骨骼的变换。
其中,
Mesh绑定时顶点:由Max导出。
绑定时骨骼的变换的逆矩阵:从Max的Skin Modifier的GetBoneInitTM中取得(或者Physique Modifier的GetInitNodeTM中取得)矩阵。
本帧的骨骼相对父节点的变换:从Max的骨骼的NodeTM和父骨骼的NodeTM得到,注意对于行矩阵,矩阵顺序是 ParentToChild = ChildToWorld * Inverse(ParentToWorld)。列矩阵则相反,根节点则直接保存NodeTM即可。帧之间的插值也主要是对这些数据做插值,在两帧之间没有很大变化的时候,四元数加向量和矩阵视觉上并没有很大差别。
本帧父骨骼的变换:由前面从根节点累加。
(摘自:http://www.cnblogs.com/linyizsh/archive/2011/03/22/1991343.html)
相信大家如果在使用或者看别人使用3Ds Max做骨骼动画的时候,多多少少应该见过美术做模型的时候,在没有绑定骨骼之前,角色蒙皮的手通常都是平举着的。加上Skin或者Physique修改器后,蒙皮的姿势通常就是第0帧了。那么在Max导出骨骼动画的时候,这个手平举着的姿势是算是第几帧呢?又是对应具体哪些数据呢?这个问题,在我开始做骨骼动画前,问过老宋,不过不知道当时是我稀里糊涂还是老宋稀里糊涂,反正没弄明白,折腾了好久,终于在2005年下半年弄明白了。不过过了这么多年,感觉自己很健忘,今天收拾那个古老而庞大的3Ds Max Exporter,终于又逼我整理了一遍思路,笔记如下。
我们知道,3Ds Max 的骨骼动画修改器常用的有两个: Skin和Physique。
在Physique里的IPhyBlendedRigidVertex通过IPhyBlendedRigidVertex::GetOffsetVector能拿到该顶点相对于某块骨骼的偏移位置,通常,我们把这个偏移乘上GetInitNodeTM获得的骨骼矩阵再乘上骨骼权重,并累加,就能得到初始位置。
在Skin修改器里,我们并没有这样的GetOffsetVector,而是只能通过Mesh获得第0帧的数据。
那么他们的区别在哪里呢?
实际上,Physique GetOffsetVector获得的就是角色手平举的时候的蒙皮位置,称为Init Pose。Skin只能直接获得第0帧数据(跟获取Static Mesh一样的方法).
但是,在Physique里我们完全也可以采用跟Skin里同样的方法来提取数据而不需要使用GetOffsetVector。在Skin里也可以计算出Init Pose.那么这个计算过程是怎么样的呢?
其实,这个过程跟我们计算骨骼动画的任意一帧的过程是完全一样的,我们假设Init Pose是第i帧。
假设,第0帧的时候:位置是v0, 骨骼变换矩阵是TM(0,k)
手平举着的时候, 位置是vi, 骨骼变换矩阵式TM(i,k).
TM(i,k) 就是Bone InitTM ,通过Physique::GetBoneInitTM()来获取
四个权重对应位置为 W(k);
在第0帧的时候,顶点相对四个骨骼的的位移应该为 v0 * invTM(0,k).
(这个值在Physique里取出来的就是vtxBlend->GetOffsetVector(j), Skin则只能计算了)
所以。其实我们并不需要这个Offset,从第0帧,加上i帧的Bone InitTM就可以算出这个offset)
那么从第0帧,算到第i帧(初始帧), 根据骨骼动画公式。
vi = SIGMA【 v0 * invTM(0,k) * TM(i,k) 】 (k = 0, 4).
那么同理,在Physique里,也可以用同样的方法,得到Init Pose的第i帧的position数据。用这个方法跟通过vtxBlend->GetOffsetVector(j)获取的Init Pose结果基本是一样的(不一样是因为浮点误差)
对于顶点Position如上处理,那么对于法向量呢?我们知道不管是Physique也好,Skin也好,直接都是无法取到Init Pose的Normal的,如果是Skin,Position取第0帧,Normal也取第0帧,那么刚好。但是如果你用的是Physique,而又是通过vtxBlend->GetOffsetVector(j)来获取Init Pose的Position的,那么对不起,Init Pose的Normal肯定要你自己算了。 这个过程我就不重复了。将 vi的计算公式中的矩阵改成 Inv后再转置就好了,因为法向量的变换矩阵跟顶点变换矩阵的关系就是逆+转置。
补充说明一点,在导出数据后,顶点Position有两种保存方法:
1. 一个顶点保存一个值,比如保存第0帧数据。那么计算第t帧的时候的公式应该是
vt = SIGMA【 v0 * invTM(0,k) * TM(t,k) 】 (k = 0, 4)
跟前面的一样的哈。 就是说你还需要把骨骼的InvTM(0,k)给保存下来,并且每次把 TM(t,k)插值好了后乘上去。这个无疑增加了骨骼矩阵混合的计算量。但是它允许你只保存一份顶点数据。
2. 一个顶点相对于四个骨骼各保存一份,也就是保存vtxBlend->GetOffsetVector(j)获取回来的值,或者是v0 * invTM(0,k) k=(0,4)。 假设保存下去的这个值是v(0,k), 0就是第0帧啦,k当然是第k根骨头啦。 那么这个时候,你做混合的时候只要
vt = SIGMA【 v(0,k) * TM(t,k) 】 (k = 0, 4) 。
计算减少了。但是你要保存的数据多了。嘿嘿,四个顶点位置,还有四个法向量哦,还有四个Tangent呢?哇哈哈。疯了。
鉴于保存四个顶点位置开销实在太大,我宁愿在骨架混合的时候多计算,只保存一份顶点位置就好了。
说明:
v0 : 第0帧,顶点位置
vi : 第i帧,顶点位置
vt : t时刻,顶点位置
TM(t,k) : t时刻,影响这个顶点的第k个骨骼的变换矩阵
TM(i,k) : 第i帧,影响这个顶点的第k个骨骼的变换矩阵
invTM(0,k) : 第0帧,影响这个顶点的第k个骨骼的变换矩阵的逆矩
(摘自:http://blog.csdn.net/yaokang522/article/details/7311745)
3DsMax动画插件的更多相关文章
- 让网站动起来!12款优秀的 jQuery 动画插件推荐
如今,大多数设计师和开发人员被要客户要求开发动态的网站.创造视觉震撼和醒目的动态网站是艰巨的任务,因为它需要大量的努力和创造力.在网络上有大量的工具和插件可用于创建网站动画.许多开发人员正在使用 HT ...
- Minimit Anima – 硬件加速的 CSS3 动画插件
Minimit Anima 是一个实现 CSS3 Transforms 和 Transitions 动画的 jQuery 插件.基于硬件加速的 CSS3 动画执行更快,而且它有一个类似于 jQuery ...
- Velocity – 另外一款加速的 jQuery 动画插件
Velocity 是一款 jQuery 插件,重新实现了 $.animate() 方法,提供更高的性能(比 CSS 动画还更快),同时包括一些新的功能,以改进动画工作流程.Velocity 除了包括所 ...
- 八款强大的jQuery图片滑块动画插件
jQuery是一款相当轻巧的JavaScript框架,目前几乎每一个WEB项目都在使用jQuery,因为jQuery插件实在太丰富,尤其是 一些图片滑块插件和jQuery焦点图插件,更是多如牛毛,很多 ...
- Unity CCTween UGUI 动画插件
在这简单的介绍一下 CCTween 动画插件的使用 因为GIF 制作软件不太好(网上随便下载的)所以导致效果不太好,有时间我重新制作一下 这是一下简单的效果 下面介绍怎么使用 首先 先下载 CCTwe ...
- jquery背景动画插件使用
在网页制作动画特效的时候,有时候想通过背景插入图片,然后通过控制背景显示的位置来实现一些动画效果,这样就不用使用绝对定位控制left和top来实现动画效果!但是jquery本身的动画函数是不支持背景动 ...
- 好用的jquery.animateNumber.js数字动画插件
在做公司的运营报告页面时,有一个数字累计增加的动画效果,一开始,毫无头绪,不知如何下手,于是上网查资料,发现大多都是用的插件来实现的,那么今天,我也来用插件jquery.animateNumber.j ...
- jquery轻量级数字动画插件jquery.countup.js
插件描述: jquery.countup.js 是一款轻量级jquery数字动画插件.该数字动画插件可以在页面滚动时,将指定的数字从0开始计数增加动画. 插件说明 jquery.countup.js ...
- #Plugin 数字滚动累加动画插件
数字滚动累加动画插件 NumScroll 1.使用前先引入jquery2.前端学习群:814798690 下载地址 https://github.com/chaorenzeng/jquery.num ...
随机推荐
- Python学习札记(九) Basic6 dict and set
参考:dict and set Note: A.dict Hint:注意最后三点. 1.Python内置字典dict,全称directory,在别的语言如C++中称为map,使用键值-value存储, ...
- Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException
这个版本默认是开启了保护模式,进入redis的文件夹下的src 输入(前提是得开启redis服务): ./redis-cli config set protected-mode "no&qu ...
- PHP运算符-算术运算符、三元运算符、逻辑运算符
运算符是用来对变量.常量或数据进行计算的符号,它对一个值或一组值执行一个指定的操作.PHP的运算符包括算术运算符.字符串运算符.赋值运算符.位运算符.逻辑运算符.比较运算符.递增或递减运算符.错误控制 ...
- 异步提交表单插件jquery.form.min.js的使用实例
因为项目中需要达到效果:前台点击按钮弹出文件选择框,选择文件确定之后,上传到后台对文件进行处理并给出响应信息. 尝试过使用$.post,$.ajsx,将表单序列化之后传到后台,但是后台并不能收到文件, ...
- JSP XML 数据处理
JSP XML 数据处理 当通过HTTP发送XML数据时,就有必要使用JSP来处理传入和流出的XML文档了,比如RSS文档.作为一个XML文档,它仅仅只是一堆文本而已,使用JSP创建XML文档并不比创 ...
- MFC sendmessage实现进程间通信
用sendmessage实现进程间通信. 1.WM_COPYDATA实现进程间通信 实现方式是发送WM_COPYDATA消息. 发送程序: LRESULT copyDataResult; //copy ...
- Spring3.0 核心jar包详解
org.springframework.aop 包含在应用中使用Spring的AOP特性时所需的类. org.springframework.asm Spring独立的ASM程序, Spring ...
- BZOJ 1045 [HAOI2008]糖果传递 ★(环形等分:中位数)
题意 有n个小朋友坐成一圈,每人有ai个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为1. 思路 假设平均数是x,且a1给an了k个(k<0说明是an给a1了-k个),那么总代价就 ...
- python高级内置函数和各种推导式的介绍:一行搞定的代码
一.知识要点 all 都为真 any 有真的 min 最小的 max 最大的 sum 求和 reversed 反转 sorted 排序 zip 对应合并 [] 列表推倒式 () 生成器 {} 字典推倒 ...
- commons-fileupload实现上传进度条的显示
本文将使用 apache fileupload ,spring MVC jquery 实现一个带进度条的多文件上传, 由于fileupload 的局限,暂不能实现每个上传文件都显示进度条, ...