在cocos2dx中,rmature的骨骼上能够绑定另外的armature,在我的项目中使用了该功能来完毕骑乘功能,可是在使用过程发现了例如以下的bug,特写在这里做一下记录。

</span>

首先说说cocos2dx的代码。在cocos2dx的骨骼的update函数中有例如以下代码用于骨骼的矩阵更新。

    if (_boneTransformDirty)
{
if (_dataVersion >= VERSION_COMBINED)
{
TransformHelp::nodeConcat(*_tweenData, *_boneData);
_tweenData->scaleX -= 1;
_tweenData->scaleY -= 1;
}
<span style="white-space:pre"> </span>//(1)
_worldInfo->copy(_tweenData); _worldInfo->x = _tweenData->x + _position.x;
_worldInfo->y = _tweenData->y + _position.y;
_worldInfo->scaleX = _tweenData->scaleX * _scaleX;
_worldInfo->scaleY = _tweenData->scaleY * _scaleY;
_worldInfo->skewX = _tweenData->skewX + _skewX + CC_DEGREES_TO_RADIANS(_rotationZ_X);
_worldInfo->skewY = _tweenData->skewY + _skewY - CC_DEGREES_TO_RADIANS(_rotationZ_Y);
<span style="white-space:pre"> </span>//(2)
if(_parentBone)
{
applyParentTransform(_parentBone);
}
else
{
if (_armatureParentBone) //(3)
{
applyParentTransform(_armatureParentBone);
}
}
<span style="white-space:pre"> </span>//(4)
TransformHelp::nodeToMatrix(*_worldInfo, _worldTransform);
<span style="white-space:pre"> </span>//(5)
if (_armatureParentBone)
{
_worldTransform = TransformConcat(_worldTransform, _armature->getNodeToParentTransform());
}
}

在上面的代码中,

1、程序首先计算了bone本身的变换信息,

2、然后在第二步。假设骨骼有父骨骼,则乘以父骨骼的变换信息。假设没有父骨骼可是该骨骼所在的armature有父骨骼(即armayure被作为了其它armature的bone的display。这时就先乘以armature的父骨骼的变换信息。

3、第四步将worldinfo转换为矩阵。

4、第五步计算再将bone所在的armature的变换信息应用于变换矩阵上,得到终于的骨骼的矩阵信息。

问题就出在上面代码标号为3的地方,我们都知道矩阵变换是不满足交换定律的(当然少数情况除外)。

可是骨骼矩阵之间的关系应该例如以下:

parentArmature-------armatureParentBone------------armature------------bone

或者是armature-----------。。。。------parentBone-----bone  中间省略一些parentBone。

因此在上面的代码中。假设不包括armatureParentBone,那么矩阵变换关系是bone * parentBone *...*parentBone,结果正确。即没有armature作为bone的render。

可是假设有armature作为bone的render,那么关系是bone*armatureParentBone*armature,那么在矩阵变换的顺序上就出现了问题。

因此我将代码做了一些改动例如以下:

  //if it is a armature display render node, apply transform to armature.
BaseData worldInfo;
if (!_parentBone && _armatureParentBone)
{ //bone * armature
TransformHelp::nodeToMatrix(*_worldInfo, _worldTransform);
_worldTransform = TransformConcat( _armature->getNodeToParentTransform(), _worldTransform);
TransformHelp::matrixToNode(_worldTransform, worldInfo);
} else {
worldInfo = *_worldInfo;
} BaseData cache = *_worldInfo;
*_worldInfo = worldInfo;
//apply to parent bone.
if(_parentBone) //bone * parentbone
{
applyParentTransform(_parentBone);
} else { // * armatureParentBone
if (_armatureParentBone)
{
applyParentTransform(_armatureParentBone);
}
}
TransformHelp::nodeToMatrix(*_worldInfo, _worldTransform);

上面的代码中,假设bone没有parentBone而且有armatureParentBone。则先乘以armature的矩阵。

假设没有 则直接乘以parentBone的变换。

最后假设有armatureparentBone。还的乘以parenBone的变换。

cocos2d的armature绑定到其它armature骨骼上的bug的更多相关文章

  1. 把多个JavaScript函数绑定到onload事件处理函数上

    为了让函数只在页面加载完毕后才得到执行,我们会把函数绑定到onload事件上: window.onload = userFunction 但如果有两个函数:firstFunction() 和 seco ...

  2. 使用MethodType函数将方法绑定到类或实例上

    在开始正文之前,需要了解下Python的绑定方法(bound method)和非绑定方法. 简单做个测试: 定义一个类,类中由实例方法.静态方法和类方法. class ClassA: def inst ...

  3. linux 将进程或者线程绑定到指定的cpu上

    基本概念 cpu亲和性(affinity) CPU的亲和性, 就是进程要在指定的 CPU 上尽量长时间地运行而不被迁移到其他处理器,也称为CPU关联性:再简单的点的描述就将指定的进程或线程绑定到相应的 ...

  4. jQ给下拉框绑定事件,为什么要绑定在框(select标签)上,而不是绑定在选项(option标签)上

    这是我在学习锋利的 jquery 书中 5.1.4 的代码时遇到的一个小问题,源代码如下: <head> <style type="text/css"> * ...

  5. 外部配置属性值是如何被绑定到XxxProperties类属性上的?--SpringBoot源码(五)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 前言 本篇接 SpringBoot是如何实现自动配置的?--SpringBoot源码(四) 温故而知新,我们来简单回顾一下上 ...

  6. 利刃 MVVMLight 5:绑定在表单验证上的应用

    表单验证是MVVM体系中的重要一块.而绑定除了推动 Model-View-ViewModel (MVVM) 模式松散耦合 逻辑.数据 和 UI定义 的关系之外,还为业务数据验证方案提供强大而灵活的支持 ...

  7. asp.net core mvc中如何把二级域名绑定到特定的控制器上

    由于公司的工作安排,一直在研究其他技术,所以一直没时间更新博客,今天终于可以停下手头的事情,写一些新内容了. 应用场景:企业门户网站会根据内容不同,设置不同的板块,如新浪有体育,娱乐频道,等等.有的情 ...

  8. 获得touch事件,jquery绑定事件监听器,ios设备上打开touch状态以响应focus,active等伪类

    2. 默认的监听方式 document.addEventListener('touchstart', function(){ alert('hello'); }, false); 使用jquery时 ...

  9. 如何在双向绑定的Image控件上绘制自定义标记(wpf)

    我们的需求是什么? 答:需要在图片上增加一些自定义标记,例如:2个图片对比时,对相同区域进行高亮. 先上效果图: 设计思路 1.概述 1.通过TargeUpdated事件,重新绘制图片进行替换. 2. ...

随机推荐

  1. 场景分割:MIT Scene Parsing 与DilatedNet 扩展卷积网络

    MIT Scene Parsing Benchmark简介 Scene parsing is to segment and parse an image into different image re ...

  2. Handling unhandled exceptions and signals

    there are two ways to catch otherwise uncaught conditions that will lead to a crash: Use the functio ...

  3. Eigen库笔记整理(二)

    Eigen/Geometry 模块提供了各种旋转和平移的表示 旋转矩阵直接使用 Matrix3d 或 Matrix3f Eigen::Matrix3d rotation_matrix = Eigen: ...

  4. oracle 安装准备

    1.选择数据库 (官网查询支持的操作系统) 2.选择系统 (官网查询支持的硬件)(更新补丁) 3.选择硬件 (io性能测试--oracle 大量小文件读写) 4.oracle 升级(和打补丁) 5.o ...

  5. top命令的用法

    top命令的用法 2018年07月15日 09:50:04 zhuoya_ 阅读数:1858    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/z ...

  6. Linux内核-内存回收逻辑和算法(LRU)

    Linux内核内存回收逻辑和算法(LRU) LRU 链表 在 Linux 中,操作系统对 LRU 的实现主要是基于一对双向链表:active 链表和 inactive 链表,这两个链表是 Linux ...

  7. enote笔记法的思考

    章节:enote笔记法的思考   why enote笔记法: key1)大脑喜欢颜色. 我们的大脑天生就喜欢颜色.对颜色很敏感,这是由我们人类过去的演化历程决定的. 你可以理解为,文字有了颜色,让这个 ...

  8. Mybatis中collection和association的使用区别

    1. 关联-association2. 集合-collection 比如同时有User.java和Card.java两个类 User.java如下: public class User{ privat ...

  9. Python学习第二阶段day1 内置函数,序列化,软件目录开发规范

    内置函数 1.abs()  求绝对值 2.all()    所有元素为真才返回真 all( [1,1,2,3,-1] ) 值为True 3.any()   所有元素为假才返回假  any([0,0,0 ...

  10. 1007 Maximum Subsequence Sum (PAT(Advance))

    1007 Maximum Subsequence Sum (25 分)   Given a sequence of K integers { N​1​​, N​2​​, ..., N​K​​ }. A ...