变换主要学习两种:仿射变换和3D变换
仿射变换采用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变换可以理解为在仿射变换的基础上加了一个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; } |