1. AffineTransform __CCAffineTransformMake(float a, float b, float c, float d, float tx, float ty)
  2. {
  3. AffineTransform t;
  4. t.a = a; t.b = b; t.c = c; t.d = d; t.tx = tx; t.ty = ty;
  5. return t;
  6. }
  7. Vec2 __CCPointApplyAffineTransform(const Vec2& point, const AffineTransform& t)
  8. {
  9. Vec2 p;
  10. p.x = (float)((double)t.a * point.x + (double)t.c * point.y + t.tx);
  11. p.y = (float)((double)t.b * point.x + (double)t.d * point.y + t.ty);
  12. return p;
  13. }
  14. Vec2 PointApplyTransform(const Vec2& point, const Mat4& transform)
  15. {
  16. Vec3 vec(point.x, point.y, 0);
  17. transform.transformPoint(&vec);
  18. return Vec2(vec.x, vec.y);
  19. }
  20. Size __CCSizeApplyAffineTransform(const Size& size, const AffineTransform& t)
  21. {
  22. Size s;
  23. s.width = (float)((double)t.a * size.width + (double)t.c * size.height);
  24. s.height = (float)((double)t.b * size.width + (double)t.d * size.height);
  25. return s;
  26. }
  27. AffineTransform AffineTransformMakeIdentity()
  28. {
  29. return __CCAffineTransformMake(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
  30. }
  31. extern const AffineTransform AffineTransformIdentity = AffineTransformMakeIdentity();
  32. const AffineTransform AffineTransform::IDENTITY = AffineTransformMakeIdentity();
  33. //获取仿射变换转换之后的坐标
  34. Rect RectApplyAffineTransform(const Rect& rect, const AffineTransform& anAffineTransform)
  35. {
  36. //四个最值
  37. float top = rect.getMinY(); //左上角Y
  38. float left = rect.getMinX(); //左上角X
  39. float right = rect.getMaxX(); //右下角X
  40. float bottom = rect.getMaxY(); //右下角Y
  41. //四个顶点坐标
  42. Vec2 topLeft = PointApplyAffineTransform(Vec2(left, top), anAffineTransform); //左上角
  43. Vec2 topRight = PointApplyAffineTransform(Vec2(right, top), anAffineTransform); //右上角
  44. Vec2 bottomLeft = PointApplyAffineTransform(Vec2(left, bottom), anAffineTransform); //左下角
  45. Vec2 bottomRight = PointApplyAffineTransform(Vec2(right, bottom), anAffineTransform); //右下角
  46. //找到可以承载这个矩形的最大正矩形坐标
  47. float minX = min(min(topLeft.x, topRight.x), min(bottomLeft.x, bottomRight.x));
  48. float maxX = max(max(topLeft.x, topRight.x), max(bottomLeft.x, bottomRight.x));
  49. float minY = min(min(topLeft.y, topRight.y), min(bottomLeft.y, bottomRight.y));
  50. float maxY = max(max(topLeft.y, topRight.y), max(bottomLeft.y, bottomRight.y));
  51. //返回可容纳最大矩形的Rect
  52. return Rect(minX, minY, (maxX - minX), (maxY - minY));
  53. }
  54. //直接获取坐标
  55. Rect RectApplyTransform(const Rect& rect, const Mat4& transform)
  56. {
  57. //四个最值
  58. float top = rect.getMinY();
  59. float left = rect.getMinX();
  60. float right = rect.getMaxX();
  61. float bottom = rect.getMaxY();
  62. //四个顶点坐标
  63. Vec3 topLeft(left, top, 0);
  64. Vec3 topRight(right, top, 0);
  65. Vec3 bottomLeft(left, bottom, 0);
  66. Vec3 bottomRight(right, bottom, 0);
  67. transform.transformPoint(&topLeft);
  68. transform.transformPoint(&topRight);
  69. transform.transformPoint(&bottomLeft);
  70. transform.transformPoint(&bottomRight);
  71. //获取四个最值点
  72. float minX = min(min(topLeft.x, topRight.x), min(bottomLeft.x, bottomRight.x));
  73. float maxX = max(max(topLeft.x, topRight.x), max(bottomLeft.x, bottomRight.x));
  74. float minY = min(min(topLeft.y, topRight.y), min(bottomLeft.y, bottomRight.y));
  75. float maxY = max(max(topLeft.y, topRight.y), max(bottomLeft.y, bottomRight.y));
  76. //返会可容纳的最大矩形
  77. return Rect(minX, minY, (maxX - minX), (maxY - minY));
  78. }
  79. // [ 1 0 0 ]
  80. //[x y 1]* [ 0 1 0 ]
  81. // [ tx ty 1 ]
  82. //平移到(x+tx, y+ty, 1)
  83. AffineTransform AffineTransformTranslate(const AffineTransform& t, float tx, float ty)
  84. {
  85. return __CCAffineTransformMake(t.a, t.b, t.c, t.d, t.tx + t.a * tx + t.c * ty, t.ty + t.b * tx + t.d * ty);
  86. }
  87. // [ a*sx 0 0 ]
  88. //[x y 1]* [ 0 d*sy 0 ]
  89. // [ 0 0 1 ]
  90. //x坐标缩放sx倍,y坐标缩放sy倍
  91. AffineTransform AffineTransformScale(const AffineTransform& t, float sx, float sy)
  92. {
  93. return __CCAffineTransformMake(t.a * sx, t.b * sx, t.c * sy, t.d * sy, t.tx, t.ty);
  94. }
  95. // [ cosa sina 0 ]
  96. //[x y 1]* [ -sina cosa 0 ]
  97. // [ 0 0 1 ]
  98. //旋转
  99. AffineTransform AffineTransformRotate(const AffineTransform& t, float anAngle)
  100. {
  101. float sine = sinf(anAngle);
  102. float cosine = cosf(anAngle);
  103. return __CCAffineTransformMake( t.a * cosine + t.c * sine,
  104. t.b * cosine + t.d * sine,
  105. t.c * cosine - t.a * sine,
  106. t.d * cosine - t.b * sine,
  107. t.tx,
  108. t.ty);
  109. }
  110. //将两个矩阵相乘 得到第二个矩阵的xy轴在第一个矩阵xy轴上的投影
  111. //下面的参数化简完就变成了
  112. //[ a1*a2 0 0 ]
  113. //[ 0 d1*d2 0 ]
  114. //[ 0 0 0 ]
  115. /* Concatenate `t2' to `t1' and return the result:
  116. t' = t1 * t2 */
  117. AffineTransform AffineTransformConcat(const AffineTransform& t1, const AffineTransform& t2)
  118. {
  119. return __CCAffineTransformMake( t1.a * t2.a + t1.b * t2.c, t1.a * t2.b + t1.b * t2.d, //a,b
  120. t1.c * t2.a + t1.d * t2.c, t1.c * t2.b + t1.d * t2.d, //c,d
  121. t1.tx * t2.a + t1.ty * t2.c + t2.tx, //tx
  122. t1.tx * t2.b + t1.ty * t2.d + t2.ty); //ty
  123. }
  124. Mat4 TransformConcat(const Mat4& t1, const Mat4& t2)
  125. {
  126. return t1 * t2;
  127. }
  128. //
  129. /* Return true if `t1' and `t2' are equal, false otherwise. */
  130. bool AffineTransformEqualToTransform(const AffineTransform& t1, const AffineTransform& t2)
  131. {
  132. return (t1.a == t2.a && t1.b == t2.b && t1.c == t2.c && t1.d == t2.d && t1.tx == t2.tx && t1.ty == t2.ty);
  133. }
  134. //交换xy轴的值
  135. //转换为
  136. //[ d 0 0 ]
  137. //[ 0 a 0 ]
  138. //[ 0 0 0 ]
  139. AffineTransform AffineTransformInvert(const AffineTransform& t)
  140. {
  141. float determinant = 1 / (t.a * t.d - t.b * t.c);
  142. return __CCAffineTransformMake(determinant * t.d, -determinant * t.b, -determinant * t.c, determinant * t.a,
  143. determinant * (t.c * t.ty - t.d * t.tx), determinant * (t.b * t.tx - t.a * t.ty) );
  144. }
  145. NS_CC_END

如果不明白为什么一些原理,比如tx=ty=0,可以看一下下面这篇文章,有很细致的讲解,我这个是只是对代码的解读。

仿射变换几何讲解

cocos2dx 仿射变换的更多相关文章

  1. cocos2dx骨骼动画Armature源码分析(三)

    代码目录结构 cocos2dx里骨骼动画代码在cocos -> editor-support -> cocostudio文件夹中,win下通过筛选器,文件结构如下.(mac下没有分,是整个 ...

  2. [原创]cocos2d-x研习录-第二阶 概念类之精灵类(CCSprite)

    上一节说布景层CCLayer是小容器,那么精灵类CCSprite就是容器添加的内容,它是构成游戏的主要元素.精灵这个名称应该是游戏专用,它表示游戏中玩家操作的主角.敌人.NPC(Non Player ...

  3. [置顶] COcos2d-X 中文API

    本文来自http://blog.csdn.net/runaying ,引用必须注明出处! COcos2d-X 中文API 温馨提醒:使用二维码扫描软件,就可以在手机上访问我的博客啦!另外大家可以访问另 ...

  4. Cocos2D-x权威指南: CCNode类方法:

    5.1.4 画图节点CCNode和图层CCLayer CCNode中提供的方法,在public块中的方法主要有下面几个部分: 1.针对节点显示的属性信息读写 2.针对节点变换的属性信息读写 3.针对子 ...

  5. Cocos2D-X扫盲之坐标系、锚点

    一.引言 在Cocos2D-X的开发过程中,经常会碰到设置精灵位置的问题.而设置位置的过程,涉及到两个问题:第一是坐标系,包括原点的位置.X/Y坐标轴的方向灯:第二是基准点(Cocos2D-X中叫锚点 ...

  6. cocos2dx调用浏览器打开网址

    安卓端cocos2dx/platform/android路径下CCApplication.h: virtual void openURL(const char* pszUrl); CCApplicat ...

  7. 使用“Cocos引擎”创建的cpp工程如何在VS中调试Cocos2d-x源码

    前段时间Cocos2d-x更新了一个Cocos引擎,这是一个集合源码,IDE,Studio这一家老小的整合包,我们可以使用这个Cocos引擎来创建我们的项目. 在Cocos2d-x被整合到Cocos引 ...

  8. Cocos2d-x不要随便在onEnter里面addChild

    使用任何版本的Cocos2d-x(1.x,2.x,3.0),在onEnter中调用addChild,都要小心谨慎,因为它有可能导致两种莫名其妙的BUG,莫名其妙的BUG当然难以定位了!更何况这个BUG ...

  9. 通过Matrix进行二维图形仿射变换

    Affine Transformation是一种二维坐标到二维坐标之间的线性变换,保持二维图形的"平直性"和"平行性".仿射变换可以通过一系列的原子变换的复合来 ...

随机推荐

  1. JSX语法及特点介绍

    1.1 基本语法 1)自定义组件名首字母大写:元素名即组件名,首字母需要大写.首字母小写时React会以为这是HTML的标准标签,因此自定义的组件名需要首字母大写,否则会报错. 2)嵌套:在rende ...

  2. Python 函数参数有冒号 声明后有-> 箭头 返回值注释 参数类型注释

    在python3.7 环境下 函数声明时能在参数后加冒号,如图: 1 def f(ham: str, eggs: str = 'eggs') -> str : 2 print("Ann ...

  3. 版本号/缓存刷新 laravel mix函数

    很多开发者会给编译的前端资源添加时间戳或者唯一令牌后缀以强制浏览器加载最新版本而不是代码的缓存副本.Mix 可以使用 version 方法为你处理这种场景. version 方法会自动附加唯一哈希到已 ...

  4. Python--day48--ORM框架SQLAlchemy

    SQLAlchemy: SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执 ...

  5. Native memory allocation (mmap) failed to map xxx bytes for committing reserved memory

    遇到问题 在服务器上运行 nexus 出现Native memory allocation (mmap) failed to map 838860800 bytes for committing re ...

  6. [转]vue - 前置工作 - 目录功能介绍

    一个DEMOS的完整目录(由于GWF问题,我就不一一打开网站一个个去搜索并且解释了)可以去关注:https://www.cnblogs.com/ye-hcj build build.js(本文来自ht ...

  7. java 合并流(SequenceInputStream)

    需要两个源文件,还有输出的目标文件 SequenceInputStream: 将两个文件的内容合并成一个文件 该类提供的方法: SequenceInputStream(InputStream s1, ...

  8. linux初始化和关停

    如已提到的, 模块初始化函数注册模块提供的任何功能. 这些功能, 我们指的是新功能, 可以由应用程序存取的或者一整个驱动或者一个新软件抽象. 实际的初始化函数定义常常 如: static int   ...

  9. 给培训学校讲解ORM框架的课件

    导读:这是我给某培训学校培训.net程序员所设计的课件,他们普遍反映太难了,是这样吗?

  10. jQuery验证码发送时间秒递减(刷新存储cookie)

    <input id="sendEmail" type="button" name="sendEmail" onclick=" ...