在CCNode的类中,有一个得到 一个节点坐标系转换父亲坐标系的一个矩阵,节点内坐标乘以这个矩阵,就可以转换为在节点父节点中的坐标,方法名为:

Mat4& Node::getNodeToParentTransform()

现在简单分析一下转换原理:

/*得到节点坐标系转换到父亲的坐标系的 矩阵某个点(在本地也就是节点坐标) 乘以这个矩阵,就得到自己在父亲节点下的坐标,嵌套坐标举例子:LayerA 添加 LayerB,B的原点坐标也就是左下角坐标为10,10,也就是这一点在自身坐标下为0,0,在LayerA下就为10,10,这个矩阵的作用是Mat*(0,0)=(10,10),再比如在B下有一点是10,10,那么在没有旋转和缩放的前提下,在LayerA中的位置应该为20,20 ,Mat*(10,10)=(20,20)所以这个矩阵叫做 转换 子节点坐标到父节点坐标的 转换矩阵*/
const Mat4& Node::getNodeToParentTransform() const
{/*先 缩放,在旋转,最后平移,详细可以看3d数学基础 8.3,解释了缩放矩阵,旋转矩阵,平移矩阵,然后相乘但是这里注意的是(3d数学是行向量,也就是 X * S * R *T,顺序执行),而cocos 是列向量 是 T * R * S * X,所以计算矩阵的时候要倒着乘,*/if (_transformDirty){// Translate valuesfloat x = _position.x;float y = _position.y;float z = _positionZ;/*旋转和缩放都是以锚点为中心,所以这里要计算出锚点1 如果忽略锚点,说明x,y 指的是 左下角坐标,因为计算的时候要以锚点为准,所以需要加上anchorPointInPoints2 如果没有忽略锚点,说明x,y指的就是锚点,直接往下计算就可以了*/if (_ignoreAnchorPointForPosition)//,加上锚点的坐标,计算缩放和旋转,以锚点为中心计算,
        {x += _anchorPointInPoints.x;//_anchorPointInPoints为物体左下角和锚点之间的距离y += _anchorPointInPoints.y;}//计算出cos和sin,这里是4个弦组成的 旋转矩阵,radians为度数,绕着旋转的点是锚点float cx = 1, sx = 0, cy = 1, sy = 0;if (_rotationZ_X || _rotationZ_Y)// 2D这两个值始终是相等的,暂时不考虑3D
        {//右手坐标系,所以如果旋转45,那么弧度是负,顺时针为负float radiansX = -CC_DEGREES_TO_RADIANS(_rotationZ_X);float radiansY = -CC_DEGREES_TO_RADIANS(_rotationZ_Y);cx = cosf(radiansX);sx = sinf(radiansX);cy = cosf(radiansY);sy = sinf(radiansY);}bool needsSkewMatrix = ( _skewX || _skewY );//是否切面/*这里这么做的原因,因为 旋转和缩放是以锚点为中心,但是平移量是以原点距离父节点原点为准,也就是需要知道原点的坐标,也就是左下角的坐标,因为涉及到缩放,所以锚点坐标要程序scale,得到新的左下角坐标距离锚点的位置,比如锚点坐标为30,30(本地坐标),也就是左下角距离锚点30,30,scale=0.5的时候,变为 左下角距离锚点15,15*/Vec2 anchorPoint;anchorPoint.x = _anchorPointInPoints.x * _scaleX;anchorPoint.y = _anchorPointInPoints.y * _scaleY;  /*如果锚点不是左下角,那么需要通过下面的计算得出旋转之后的左下角的坐标。锚点为旋转点,那么左下角距离原点的坐标成为了负数,也就是-30,-30,的出来的结果是相对于锚点的偏移量,所以下面anchorPoint要加一个负号,通过-anchorPoint和旋转矩阵想乘,得到了新的左下角的相对于锚点的偏移量而x,y为锚点的世界坐标(这里是指父节点中的坐标),(也就是到 ‘原点’的距离),加上相对于锚点为中心的旋转后的左下角坐标的偏移量,得到新的(想象一个如果锚点在左下角,就好理解了,一个意思)左下角的世界坐标(在父节点中的坐标)*///如果不是切变 并且锚点不在左下角,计算出左下角的父节点坐标//如果是切变,往后会有处理//其实这里是在mat矩阵形成前,先求出了左下角的x,y,其实如果不在这求出//先求出 mat矩阵,这个矩阵是集缩放和旋转一体的,然后anchorPointInPoints(初始左下角坐标,相对于锚点)与这个矩阵想乘//仍然可以求出变换之后的左下角坐标,后面的切变求偏移就是这么计算的,//因为求切变的时候,最终的矩阵集 切变,缩放,旋转矩阵为一体了,就差一个平移了,然后anchorPointInPoints//与这个矩阵想乘,然后再被锚点坐标相加,得出来父节点坐标下的左下角最终坐标,并把这个值作为平移值if (! needsSkewMatrix && !_anchorPointInPoints.equals(Vec2::ZERO)){float xx=  cy * -anchorPoint.x + -sx * -anchorPoint.y;x +=xx;float yy=sy * -anchorPoint.x +  cx * -anchorPoint.y;y += yy;}//先缩放,在旋转,在平移的组合矩阵// T * R * S *坐标,顺序别错了// 这个矩阵* 本地坐标,得到就是相对于父节点的坐标(相当于本地坐标转世界坐标,父节点相当于世界了)float mat[] = {cy * _scaleX,   sy * _scaleX,   0,          0,-sx * _scaleY,  cx * _scaleY,   0,          0,0,              0,              _scaleZ,    0,x,              y,              z,          1 };_transform.set(mat);//应该是更新之后的矩阵//*************关于3d的东西,忽略*************//
        if(!_ignoreAnchorPointForPosition){_transform.translate(anchorPoint.x, anchorPoint.y, 0);//
        }//下面是绕 Y轴或X轴旋转,一般是3d的时候,2d的时候就是围绕点旋转,不考虑// XXX// FIX ME: Expensive operation.// FIX ME: It should be done together with the rotationZif(_rotationY) {Mat4 rotY;Mat4::createRotationY(CC_DEGREES_TO_RADIANS(_rotationY), &rotY);_transform = _transform * rotY;}if(_rotationX) {Mat4 rotX;Mat4::createRotationX(CC_DEGREES_TO_RADIANS(_rotationX), &rotX);_transform = _transform * rotX;}if(!_ignoreAnchorPointForPosition){_transform.translate(-anchorPoint.x, -anchorPoint.y, 0);}//*************关于3d的东西,先不看 结束*************////如果是切变,那么此时的x,y还是锚点坐标if (needsSkewMatrix){//这个矩阵的意思是 坐标X根据坐标Y被切变,坐标Y根据坐标X被切变,Z轴忽略,只考虑2d//
            Mat4 skewMatrix(1, (float)tanf(CC_DEGREES_TO_RADIANS(_skewY)), 0, 0,(float)tanf(CC_DEGREES_TO_RADIANS(_skewX)), 1, 0, 0,0,  0,  1, 0,0,  0,  0, 1);//这里的顺序是_transform * skewMatrix,而不是相反,本地坐标先被切变得到新的本地坐标,然后在// 乘以缩放旋转平移矩阵_transform = _transform * skewMatrix;// adjust anchor point//和旋转的原理是一样的,12,13指的是 x,y原点距离世界坐标原点的值,因为之前的计算都是围绕锚点展开的//所以此时的x,y是指锚点世界坐标,需要转换成左下角原点,算法上面说过,和旋转一样            //0 1 4 5代表的是 第一列的前两个和第二列的前两个值,缩放和旋转也是影响的这几个值(只考虑2d情况)if (!_anchorPointInPoints.equals(Vec2::ZERO)){// XXX: Argh, Mat4 needs a "translate" method.// XXX: Although this is faster than multiplying a vec4 * mat4_transform.m[12] += _transform.m[0] * -_anchorPointInPoints.x + _transform.m[4] * -_anchorPointInPoints.y;_transform.m[13] += _transform.m[1] * -_anchorPointInPoints.x + _transform.m[5] * -_anchorPointInPoints.y;}}if (_useAdditionalTransform){_transform = _transform * _additionalTransform;}_transformDirty = false;}return _transform;
}

转载于:https://www.cnblogs.com/xiaonanxia/p/9104248.html

cocos子节点转父节点坐标 原理浅析(局部坐标转世界坐标同理)相关推荐

  1. JS获取子节点、父节点和兄弟节点的方法实例总结

    本文实例讲述了JS获取子节点.父节点和兄弟节点的方法.分享给大家供大家参考,具体如下: 一.js获取子节点的方式 1. 通过获取dom方式直接获取子节点 其中test的父标签id的值,div为标签的名 ...

  2. XML解析 (JAVA解析xml文件)java+Dom4j+Xpath xml文件解析根据子节点得到父节点 查找校验xml文件中相同的节点属性值 java遍历文件夹解析XML

    XML解析 (JAVA解析xml文件)java+Dom4j+Xpath xml文件解析根据子节点得到父节点 以及查找xml文件中相同的节点属性值 项目背景:这是本人实习中所碰到的项目,当时感觉很棘手, ...

  3. js父元素获取子元素img_JS获取子节点、父节点和兄弟节点的方法实例总结

    本文实例讲述了JS获取子节点.父节点和兄弟节点的方法.分享给大家供大家参考,具体如下: 一.js获取子节点的方式 1. 通过获取dom方式直接获取子节点 其中test的父标签id的值,div为标签的名 ...

  4. js与jquery获取子节点、父节点、兄弟节点的方法

    js与jquery获取子节点.父节点.兄弟节点的方法 在写代码时,时不时会遇到获取子节点.父节点等需要,但有的时候总是弄混淆不是很清晰,所以针对这些问题,总结了jquery与js获取节点的方法 js方 ...

  5. java 树状数据,递归 从子节点找父节点

    前言:递归算法在项目中也会使用到,简单介绍一下在项目中使用到的场景 递归方法实现三个要素: 1.明确递归终止条件: 2.给出递归终止时的处理办法: 3.提取重复的逻辑,缩小问题的规模. 场景一:根据树 ...

  6. Java根据子节点查找父节点

    /*** 根据节点查找父节点* @param label* @return*/public static Label getParentLabelObject(Label label,List< ...

  7. Oracle树查询(查询所有子节点,父节点等等)_转载

    Oracle树查询(查询所有子节点,父节点等等) 转载 2016年01月14日 10:11:55 Oracle树查询的最重要的就是select...start with... connect by . ...

  8. dom4j添加节点的父节点_HTML DOM节点介绍

    HTML DOM节点介绍,在HTML DOM中,所有事物都是节点.DOM是被视为节点树的HTML. DOM节点 根据W3C的HTML DOM标准,HTML文档中的所有内容都是节点: 整个文档是一个文档 ...

  9. layui如何获取父节点的父节点_layui树形组件(右键、父节点选中子节点全被选中)...

    一:右键菜单: layui里面没有给到右键菜单,所以,我自己把源码改了一下: 找到layui文件夹里modules下的tree.js 用以上代码,替换以下代码 当i.which等于3,是右键事件,等于 ...

  10. html dom节点取父节点,JavaScript DOM父子兄节点操作必看详解

    首先我们知道网页中的所有内容都是节点(标签.属性.文本.注释等) ,之前我们已经说过了一些元素的获取方法 比如element.getElementById(),element.querySelecto ...

最新文章

  1. 我还不懂什么是分布式事务
  2. websocket python爬虫_python实现基于websocket协议的网络爬虫
  3. 数组作为函数参数进行传递
  4. go mod依赖离线安装_Go语言go mod包依赖管理工具使用详解
  5. Jenkins --SVN
  6. php 安装pdo odbc,PHP PDO ODBC连接
  7. 删除 字符串中‘*’号 两端的除外。指针h、p分别指向第一个和最后一个字符
  8. 矢量归一化_7. 从矢量观测到姿态观测
  9. python怎么读数据库_Python如何读写SQLite数据库
  10. 计算机关闭节能模式,bios怎么关闭cpu节能模式_bios节能模式怎么设置
  11. 计算机网络原理 谢希仁(第8版)第一章习题答案
  12. SSM+MySQL实现在线考试系统(含源码、MySQL、文档,包运行)
  13. html 长度太长截断,HTML CSS 表格换行禁止 超出指定长度自动截断
  14. c语言简单的图案设计,分形艺术图案设计
  15. 华为手机禁用省电精灵
  16. AVProVideo☀️九、“今朝若能同淋雪,此生也算共白头”。一曲《南山雪》,学习给视频做字幕。
  17. 区块链目前的几大共识算法
  18. 大数据的Hadoop架构有哪些优势?
  19. 生命的法则——植渝轩语录
  20. 深圳行-八:惠州泡温泉

热门文章

  1. C++中explicit的用法
  2. implements
  3. 【Try to Hack】Windows用户管理
  4. 【NodeJS】nodejs | 缓存设置
  5. dqn系列梳理_我梳理了乡村爱情和刘老根中的重要人物,发现赵本山真是宇宙中心...
  6. 朱老师核心课程之串口实验烧录
  7. 计算机语言发展和分类
  8. kmsbasertpendpoint阅读笔记
  9. php宝塔搭建新版手机软件库游戏库系统php源码
  10. 图片怎么变成html语音,怎么将文字变成语音