Categories: 技术原创

iOS学习笔记:变换

变换主要学习两种:仿射变换和3D变换

  • 仿射变换(CGAffineTransform):
  • 仿射变换采用3*3的二位矩阵乘法来进行变换,仿射的意义主要在于无论矩形怎么变换,平行的两条线在变换后依然平行,如图:

    计算过程如下:

    1
    2
    3
    = [x*a + y*c + 1*tx,
     x*b + y*d + 1*ty,
     x*0 + y*0 + 1*1] = [x', y', 1]

    主要用于在二维空间中进行平移,缩放,旋转,API提供了进行混合变换的方法,无需自己进行计算

    进行旋转是角度角度和弧度的转换公式:

    1
    #define DEGREES_TO_RADIANS(x) ((x)/180.0*M_PI)
  • 3D变换(CATransform3D):
  • 3D变换可以理解为在仿射变换的基础上加了一个Z轴的变换,如图:

    计算过程和仿射变换同理

    其中需要注意透视投影由

    1
    m34

    这个元素控制,m34 = -1.0/Z,当Z为正数的时候有近大远小的透视效果,当Z越靠近远点时效果越不明显,Z为无穷大时得到 -1.0/∞ ≈ 0, m34的值默认为0

    灭点通常位于图层的中心点,当图层发生变换时,灭点永远位于图层变换前的anchorPoint上,所以改变一个图层的position也改变了图层的灭点

    sublayerTransform 属性可以控制一个图层上的所有子图层进行相同的变换

    doubleSided 控制视图在被反转到背面,从相机视角消失的时候不会被绘制,默认为YES

    光亮和阴影的问题:

    这里需要引入GLKit框架做向量运算

    每个面的CATransform3D都被转换成GLKMatrix4,然后通过GLKMatrix4GetMatrix3函数得出一个3×3的旋转矩阵。这个旋转矩阵指定了图层的方向,然后可以用它来得到正太向量的值。

    原书中GLKMatrix4和CATransform3D转换的方法并不正确,因为这二者的内存结构并不一致,这里附上转换方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 此方法理论上来说并不安全
    - (GLKMatrix4)matrix4From3DTransformation:(CATransform3D)transform
    {
      GLKMatrix4 matrix = GLKMatrix4Make((float)transform.m11, (float)transform.m12, (float)transform.m13, (float)transform.m14,
                                         (float)transform.m21, (float)transform.m22, (float)transform.m23, (float)transform.m24,
                                         (float)transform.m31, (float)transform.m32, (float)transform.m33, (float)transform.m34,
                                         (float)transform.m41, (float)transform.m42, (float)transform.m43, (float)transform.m44);
     
      return matrix;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    - (CATransform3D)transform3DFromGLKMatrix4:(GLKMatrix4)matrix4
    {
      CATransform3D transform = CATransform3DIdentity;
      transform.m11 = matrix4.m00;
      transform.m12 = matrix4.m01;
      transform.m13 = matrix4.m02;
      transform.m14 = matrix4.m03;
      transform.m21 = matrix4.m10;
      transform.m22 = matrix4.m11;
      transform.m23 = matrix4.m12;
      transform.m24 = matrix4.m13;
      transform.m31 = matrix4.m20;
      transform.m32 = matrix4.m21;
      transform.m33 = matrix4.m22;
      transform.m34 = matrix4.m23;
      transform.m41 = matrix4.m30;
      transform.m42 = matrix4.m31;
      transform.m43 = matrix4.m32;
      transform.m44 = matrix4.m33;
      return transform;
    }
    龚杰洪

    Recent Posts

    GOLANG面试八股文-并发控制

    背景 协程A执行过程中需要创建…

    1 年 ago

    MYSQL面试八股文-常见面试问题和答案整理二

    索引B+树的理解和坑 MYSQ…

    1 年 ago

    MYSQL面试八股文-InnoDB的MVCC实现机制

    背景 什么是MVCC? MVC…

    1 年 ago

    MYSQL面试八股文-索引类型和使用相关总结

    什么是索引? 索引是一种用于加…

    1 年 ago

    MYSQL面试八股文-索引优化之全文索引(解决文本搜索问题)

    背景:为什么要有全文索引 在当…

    1 年 ago