cocos2dx blender 骨骼动画实现

前言 cocos2d-x 中相关部分代码介绍  背景知识介绍

参考

http://www.3dkingdoms.com/weekly/weekly.php?a=4

一 简单3d 模型支持

第一步实现对3d 模型的简单支持,完成一个CCSprite3D 类

参考CCSprite 类 以及 CCGLProgram 代码 主要修改 draw 方法。

添加了定点数组pos  绘制索引数组index. 以及若干 3d 变换相关的成员方法 平移 旋转 缩放。

对draw方法的改造,首先增加对opengl 矩阵进行计算的stdTransform, 将3d空间中的变换 矩阵乘到 MV 矩阵上面。

注意cocos2d 使用了两种投影方式,一种是 平行投影,一种是3d 透视投影,默认使用的3d 投影, 这种方式下MV矩阵也被修改,将坐标原点移动到了屏幕的右下角。

3d绘制需要 开启depth_test 深度测试。

之后只需要将顶点数组传入vertexAttribPointer 中 将索引数组传给glDrawElements 中即可.

测试时可以手动写一个 正方体的 顶点数组数据。

注意要对模型进行一定的缩放,否则屏幕上面会看不到。

使用 画 line 以及 画顶点 方式 绘制 可以用来调试。


二 3d 模型 基本变换支持

http://en.wikipedia.org/wiki/Transformation_matrix

cocos2dx 中使用kazmath 这个数学库,这个库中的矩阵kmMat4使用列优先的方式存储,即0 1 2 3 存储的是 矩阵第一列数据。

对应平移变换只需要修改 最后一列的 前3行数据即可,分别对应x y z 平移。

http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation

对于旋转,一般使用四元式进行计算,因此对于旋转可以先按照四元式进行计算,最后转化成一个矩阵即可。

四元式 通过对旋转轴和相对于轴的旋转角度来表示(通过一些sin cos计算),两个四元式之间的插值使用圆插值(slerp).

基本的 x y z 轴的旋转矩阵 可以参考2维度旋转矩阵的构造方法。

http://onlinemca.com/mca_course/kurukshetra_university/semester5/computergraphics/three_d_transformation.php

对于缩放直接修改矩阵主对角线上面的值即可。


下面这些矩阵对顶点的计算 都是按照 行优先矩阵 左乘以 顶点列向量, 相当于列优先矩阵 右乘以 顶点行向量 来计算结果的。在给opengl 传入矩阵的时候 是以 列优先的方式传入数据的。  http://www.opengl.org/archives/resources/faq/technical/transformations.htm

在kazmath 这个库里面 矩阵是以列优先方式存储,矩阵相乘的时候第一个矩阵的第一行 乘以 第二个矩阵的第一列 得到第一个元素,即是第一个矩阵左乘第二个矩阵。 

http://www.mindcontrol.org/~hplus/graphics/matrix-layout.html

貌似在direct3d中传入的矩阵数据是按照行优先的顺序的,因此在direct中如果要做两个矩阵的乘法,第一个矩阵左乘第二个矩阵,则选取的矩阵元素和opengl是不同的。

当然这里使用的左乘 是数学上面的左乘的概念,即用一个矩阵的 第一行 乘以 第二个矩阵的第一列 得到第一个元素。


注意矩阵乘法是不可以交换了,因此对于这三种变换,不同的乘顺序会产生不同的结果。举例如下:

旋转矩阵 左乘 平移矩阵,则旋转矩阵中的值将会影响到平移的值,而平移的数值不会影响结果中的旋转部分的值,结果就是在世界空间中 对象是旋转一定角度之后,沿着这个角度进行平移的。

如果平移矩阵 左乘 旋转矩阵, 平移的值不会影响结果中的旋转部分, 旋转也不会影响平移。结果就是物体现在本地旋转,但是之后 还是沿着世界坐标中原来的轴进行平移。

先考虑 缩放矩阵 左乘 旋转矩阵 结果就是 相当于在原来的旋转矩阵上面 同一行 乘以一个相同的系数, 这个矩阵在作用到顶点的时候  这个 系数可以提取出来,则相当于 对顶点先进行了旋转 接着 还是按照原来的 世界坐标的方向 进行缩放, 这样得到的是一个 切拉伸的效果,这样物体会变形。

那么 旋转矩阵 左乘 缩放 矩阵 得到的结果就和上面不同,因此应该是物体旋转之后,相应的缩放轴也跟着旋转了,因此缩放 不是沿着世界轴进行的,而是沿着物体本身的本地坐标轴进行的,这样物体不会边形。

接着考虑缩放左乘 平移矩阵 , 结果中的缩放部分没有变化,但是平移部分会被改变,结果就是 物体还是按照原来的比例缩放,但是 新的平移位移的时候相对于 原来的平移位移会产生一定比例的缩放。

如果是 平移 左乘 缩放矩阵  结果中平移部分 和 缩放部分都不会发生改变, 结果就是 物体在世界坐标空间中 按照原来的比例 缩放 , 接着平移正常的位移。


可以总结出来 平移 左乘 另外的矩阵 不过影响原来矩阵的结果, 而别的两种矩阵左乘平移矩阵 会影响平移的结果。缩放 左乘 旋转 会产生物体的边形, 而旋转左乘缩放 会保持物体的形状和单纯的进行缩放的物体形状是一致的。


因此如果你的目标是保证世界空间中平移不变则用平移矩阵左乘其它矩阵,如果是要保证物体的缩放形状不变则 用 旋转矩阵左乘 缩放矩阵。

如果要保持这两个不变性的话 矩阵乘法的顺序就是 平移 * 旋转 * 缩放

http://gamedev.stackexchange.com/questions/16719/what-is-the-correct-order-to-multiply-scale-rotation-and-translation-matrices-f

当然要根据自身想要的结果来调整矩阵的乘法顺序,并且可以通过增加父子变换的关系来控制矩阵乘法顺序。

一般情况是 父亲矩阵 左乘于 孩子矩阵 则结果就是 父亲在世界空间的平移 得到保持, 父亲缩放会导致旋转的孩子发生变形,父亲的旋转 会影响孩子自身的平移方向。

按照专业的说法叫做 孩子的变换矩阵作用在孩子节点自身的局部空间 而 父亲矩阵 会对孩子局部空间进行变换。


三 骨骼动画

本质上骨骼只是一个矩阵变换,如果要查看一个骨骼则观察其对应的矩阵即可。但是这种方式非常不直观,如何通过图像直观表现这种矩阵变换呢?

这里首先要明确表现和本质之间的区别,矩阵变换及其对应的3d骨骼对象不能等价。骨骼的作用只是施展一种变换到一个对象身上,至于这个对象当前的状态是什么并不关心,因此需要手动的对对象设定一个初始化的状态,而后续的状态通过这种骨骼矩阵变换来生成。

因此问题分成两个部分,如何描述这种初始化状态,如何描述这个矩阵变换。


骨骼分成两个端点 头和 尾部,之间有一定长度连接,并且这两个点之间有一定的旋转方向。

矩阵变换比较简单,可以通过一个四元式和一个3维向量, 以及一个骨骼长度来描述。

将骨骼的一端做为原点,这里我设定骨骼沿着x 轴方向,而骨骼长度就是lenght,offset表示孩子骨骼相对于父亲骨骼的 结束端点的 位置偏移,通常这个偏移量为0.

这样矩阵变换的计算方法就是 

外部矩阵 * 父亲骨骼平移矩阵 * 父亲骨骼旋转矩阵 * x轴方向 length长度 平移矩阵 * 孩子骨骼的平移矩阵 * 孩子骨骼旋转矩阵 

上面就能计算到 一个孩子骨骼的变换矩阵了。抽取其中的元素,可以得到每根骨骼的变换矩阵的计算方法是

外部矩阵 * 平移矩阵 * 旋转矩阵 

而传入给孩子骨骼的 矩阵就是  外部矩阵 * 平移矩阵 * 旋转矩阵 * x轴方向长度length 平移矩阵

这里的length存在的主要目的是为了方便的描述旋转,因为对于长度0的骨骼来讲 就没办法指定其旋转方向了。


解决了矩阵变换的描述方法 接着需要描述骨骼初始状态以及和mesh绑定时的初始状态

首先建模的时候会把骨骼的父子关系确定每个骨骼初始的旋转 长度 平移这些参数确定, 这里我们假设骨骼动画只有旋转, 这样的话 长度可以存储到上面提到的length里面。

这时候如何存储初始的旋转矩阵呢? 我们为每一个骨骼分配了一个额外的矩阵,这个矩阵里面存放 骨骼初始 骨骼的初始平移矩阵 左乘 旋转矩阵  的逆 矩阵。

这样在对一个骨骼上面的定点进行变换的时候,如果骨骼在初始状态,那么对定点的变换就是 单位矩阵,通过上面计算的逆矩阵 * 骨骼当前的变换矩阵 就会得到一个单位矩阵 而这个单位矩阵 再作用到 定点上 定点就不会运动了。这样就保证了 在骨骼的初始状态下 骨骼上绑定的 顶点 也是在初始状态, 不会运动。


上面计算的骨骼逆矩阵是骨骼局部空间的逆矩阵 因此是不够用的,对于子骨骼来讲 其变换矩阵是经过父亲层层传递的, 因此一个子骨骼的逆矩阵实际的逆向矩阵是 子局部逆向矩阵 * 父亲逆向矩阵

这时候 对于 计算孩子骨骼的实际变换矩阵就是   子局部逆向矩阵 * 父亲逆向矩阵 * 父亲传到的变换矩阵 * 子局部变化矩阵

这样如果 父亲 孩子骨骼都在bind位置时候,孩子上面的mesh 定点也是在bind位置的。

因此对于一个骨骼描述的数据就包括

rotate 四元式骨骼局部旋转

offset 3维度向量 骨骼局部偏移

length 长度 骨骼长度

reverse  kmMat4 局部逆矩阵

mat 计算的实际变换矩阵 用于给mesh定点使用 

child 骨骼的孩子骨骼

parent 骨骼的父亲

id 骨骼的编号

name 骨骼的名字


四:blender中的骨骼动画导出 并在cocos2dx 中导入 

blender 支持python脚本有比较好的扩展性 因此尝试导出blender中的模型和动画数据 在游戏引擎中使用

需要导出的数据包括

定点数据 包括 定点位置 定点绑定的骨骼编号 以及权重

面数据 每个三角面 由哪几个编号的定点构成

骨骼数据 骨骼在bind姿势下面 每个骨骼的旋转值, 偏移值, 长度信息, 骨骼的父亲信息

动画信息 不同frame下 每个骨骼的 旋转 长度 偏移 信息

 



转载于:https://www.cnblogs.com/liyonghelpme/p/4273736.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/377221.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于web.config中customErrors节点说明

关于web.config中<customErrors>节点说明 <customErrors>节点用于定义一些自定义错误信息的信息。此节点有Mode和defaultRedirect两个属性&#xff0c;其中defaultRedirect属性是一个可选属性&#xff0c;表示应用程序发生错误时重定向到的默认URL&#xff0c;如果…

肯德基收银系统模式_肯德基的完整形式是什么?

肯德基收银系统模式肯德基&#xff1a;肯塔基炸鸡 (KFC: Kentucky Fried Chicken) KFC is an abbreviation of "Kentucky Fried Chicken". It is a fast-food restaurant chain whose specialty is known for fried chicken because of its specialization in it. It…

泛型(CSDN转载)

函数的参数不同叫多态&#xff0c;函数的参数类型可以不确定吗&#xff1f; 函数的返回值只能是一个吗&#xff1f;函数的返回值可以不确定吗&#xff1f; 泛型是一种特殊的类型&#xff0c;它把指定类型的工作推迟到客户端代码声明并实例化类或方法的时候进行。 下面是两个经典…

《MySQL tips:隐式类型转换与隐式字符编码转换对查询效率的影响》

维护一个交易系统&#xff0c;交易记录表tradelog包含交易流水号(tradeid)、交易员id(operator)、交易时间(t_modified)等字段。 create table tradelog (id int(11) not null,tradeid varchar(32) default null,operator int(11) default null,t_modified datetime default n…

HDU4291 A Short problem

求通项和斐波那契数列的方法一样&#xff0c;矩阵快速幂。 这道题麻烦在套了三层。 但其实取模这种操作肯定会出现循环的&#xff0c;可以先本地暴出循环节&#xff0c;1000000007对应的循环节是222222224&#xff0c;222222224对应的循环节是183120。 最外层的结果是对1000000…

pvr波形是什么意思_PVR的完整形式是什么?

pvr波形是什么意思PVR&#xff1a;Priya村路演 (PVR: Priya Village Roadshow) PVR is an abbreviation of Priya Village Roadshow. It is one of the biggest and leading multiplex cinema chains in India. PVR是Priya Village Roadshow的缩写 。 它是印度最大和领先的多元…

《MySQL——查询长时间不返回的三种原因与查询慢的原因》

目录查询长时间不返回等MDL锁等flush等行锁查询慢构造一张表&#xff0c;表有两个字段id和c&#xff0c;再里面插入了10万行记录 create table t (id int(11) not null,c int(11) default null,primary key (id) ) engine InnoDB;delimiter ;; create procedure idata() begi…

Linux 命令积累 fuser lsof mtr

fuser 用途:使用文件或文件结构识别进程,即:查询都有哪些进程占用了制定的文件、目录、设备或套接字;lsof MTR fuser命令 用途:使用文件或文件结构识别进程,即:查询都有哪些进程占用了制定的文件、目录、设备或套接字;语法:fuser [-c|-d|-f] [-k] [-u] [-x] [-V] 文件/目录…

线程终止问题

http://topic.csdn.net/u/20080429/09/9cfe5204-20b5-40fb-ac12-afdc1e4939e9.html?590511460 线程终止问题 http://blog.csdn.net/wuyazhe/article/details/1771470 带有消息机制的线程 - CustomMessageQueue(c#) using System; using System.Collections.Generic; using Sy…

HTH的完整形式是什么?

HTH&#xff1a;希望这个(那个)有帮助 (HTH: Hope This (That) Helps) HTH is an abbreviation of "Hope This (That) Helps". HTH是“希望有帮助”的缩写 。 It is an expression, which is commonly used in messaging or chatting on social media networking si…

排序算法复习—希尔排序

希尔排序&#xff0c;也称递减增量排序算法&#xff0c;是插入排序的一种更高效的改进版本。 希尔排序将整个待排元素序列分割成若干个子序列&#xff08;由相隔某个“增量”的元素组成的&#xff09;分别进行直接插入排序&#xff0c;过程中较小的元素&#xff0c;跳跃式的往前…

《MySQL——幻读与next-key lock与间隙锁带来的死锁》

create table t (id int(11) not null,c int(11) default null,d int(11) default null,primary key (id),key c (c) ) engine InnoDB;insert into t values(0,0,0),(5,5,5),(10,10,10),(15,15,15),(20,20,20),(25,25,25);该表除了主键id&#xff0c;还有索引c。 问下面的语句…

css 阴影 效果_CSS阴影效果

css 阴影 效果CSS中的阴影效果 (Shadow Effects in CSS) It is always good to make our web pages stylish and beautiful, web pages that would catch users eyes instantly but one gets confused as to how to style his or her web page. The confusion is quite legit t…

java常见的ClassNotFoundException-----菜鸟学习java

java常见的ClassNotFoundException 1 - java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory 添加包common-logging.jar2 - java.lang.ClassNotFoundException: javax.transaction.Synchronization 添加包jta.jar(hiberante)3 - java.lang.ClassNo…

关于easyui的一些小知识点(1)

让layout布局自动适应浏览器宽度只需要加上fit"true"属性。转载于:https://www.cnblogs.com/haifg/p/3613789.html

《MySQL——加锁规则(待补全,有些没看懂)》

catalog加锁规则等值查询间隙锁非唯一索引等值锁主键索引范围锁非唯一索引范围锁唯一索引范围锁 bug非唯一索引上存在"等值"的例子limit语句加锁关于死锁总结 1、查询过程中访问到的对象才会加锁&#xff0c;而加锁的基本单位是next-key lock&#xff08;前开后闭&am…

c# 命名空间命名规范_C#中的命名空间

c# 命名空间命名规范C&#xff03;命名空间 (C# Namespace ) In C# namespaces are used to group similar type of classes. Two classes with same name in different namespaces never conflict to each other. 在C&#xff03;中&#xff0c;名称空间用于对相似类型的类进…

PHP环境搭建:Windows 7下安装配置PHP+Apache+Mysql环境教程

这两天刚装好Windows 7&#xff0c;碰巧前段时间有朋友问我Windows下如何安装搭建PHP环境&#xff0c;所以打算勤劳下&#xff0c;手动一步步搭建PHP环境&#xff0c;暂且不使用PHP环境搭建软件了&#xff0c;在此详细图解在Windows 7下安装配置PHPApacheMysql环境的教程&#…

《MySQL—— 业务高峰期的性能问题的紧急处理的手段 》

catalog短连接风暴先处理占着连接但是不工作地线程减少连接过程的消耗慢查询性能问题索引没有设计好语句没写好选错索引QPS突增问题短连接风暴 正常的短连接&#xff1a; 执行很少sql语句就断开&#xff0c;下次需要的时候再重连。MySQL建立连接的过程成本很高&#xff0c;包含…

sql 算出下级销售总和_找出总和字符串

sql 算出下级销售总和Description: 描述&#xff1a; This is a standard interview problem to check that the given string is a sum string or not using backtracking. 这是一个标准的面试问题&#xff0c;用于检查给定的字符串是否为总和字符串或不使用回溯。 Problem…