为什么在应用旋转变换之前需要修改 CALayer's transform3D 的 m34?



以下代码可以为图层进行透视旋转转换:

CATransform3D transform3DFoo = CATransform3DIdentity;
transform3DFoo.m34 = -1.0 / 1000;
transform3DFoo = CATransform3DRotate(transform3DFoo, M_PI / 4, 1, 0, 0);

但是,如果两行颠倒:

CATransform3D transform3DFoo = CATransform3DIdentity;
transform3DFoo = CATransform3DRotate(transform3DFoo, M_PI / 4, 1, 0, 0);
transform3DFoo.m34 = -1.0 / 1000;

然后视角就消失了。 现在是正交的(没有透视)。 熟悉透视的人知道为什么吗?


更新:

// First Identity and then transform3DFoo.m34 = -1.0 / 1000; is done
1.00000     0.00000     0.00000     0.00000 
0.00000     1.00000     0.00000     0.00000 
0.00000     0.00000     1.00000    -0.00100 
0.00000     0.00000     0.00000     1.00000 
// and then CATransform3DRotate(transform3DFoo, M_PI / 4, 1, 0, 0);
1.00000     0.00000     0.00000     0.00000 
0.00000     0.70711     0.70711    -0.00071 
0.00000    -0.70711     0.70711    -0.00071 
0.00000     0.00000     0.00000     1.00000 
// Now start with Identity and only the Rotate statement is done:
1.00000     0.00000     0.00000     0.00000 
0.00000     0.70711     0.70711     0.00000 
0.00000    -0.70711     0.70711     0.00000 
0.00000     0.00000     0.00000     1.00000 
// and then transform3DFoo.m34 = -1.0 / 1000; is done
1.00000     0.00000     0.00000     0.00000 
0.00000     0.70711     0.70711     0.00000 
0.00000    -0.70711     0.70711    -0.00100 
0.00000     0.00000     0.00000     1.00000 

(添加"OpenGL"的标签,因为它可能是OpenGL中的相同原理)

首先设置m34相当于先旋转后投影。最后设置m34大致相当于先投影后旋转。由于输入坐标的 z=0,因此首先投影不会执行任何操作。

要了解为什么会这样,您需要了解一些转换矩阵的工作原理。

我相信在 CA 中,位置是通过变换矩阵M通过以下方式变换的

[x y z w] = [x y z w] * M

(见 http://en.wikipedia.org/wiki/Matrix_multiplication)

两个变换矩阵相乘等效于将变换连接起来。左侧的变换/矩阵首先发生。很容易理解为什么会这样:

[x y z w] * (LEFT * RIGHT) = ([x y z w] * LEFT) * RIGHT

大多数(所有?)CA变换函数(例如CATransform3DRotate)只是将变换矩阵预先乘以另一个恰当构造的矩阵,例如:

M = ROTATE * M

设置m34大致相当于预乘投影矩阵,即:

M = PROJ * M

(其中PROJ是投影矩阵 - 一个单位矩阵,但有m34集)

这并不完全正确(这就是为什么我一直粗略地说)——它只有在M正确的位置有一些 0 和 1 时才有效。基本上,在一般情况下,仅仅设置m34是一件无稽之谈 - 正确的做法是乘以投影矩阵。

无论如何,如果你把所有这些放在一起,你应该能够理解为什么我在第一段中所说的是正确的(假设我没有犯任何错误:)

最新更新