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

nop*_*ole 4 3d opengl-es calayer ios

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

CATransform3D transform3DFoo = CATransform3DIdentity;

transform3DFoo.m34 = -1.0 / 1000;

transform3DFoo = CATransform3DRotate(transform3DFoo, M_PI / 4, 1, 0, 0);
Run Code Online (Sandbox Code Playgroud)

但是,如果两条线相反:

CATransform3D transform3DFoo = CATransform3DIdentity;

transform3DFoo = CATransform3DRotate(transform3DFoo, M_PI / 4, 1, 0, 0);

transform3DFoo.m34 = -1.0 / 1000;
Run Code Online (Sandbox Code Playgroud)

然后,视角消失了.现在它是正字法(没有透视).有熟悉透视的人知道原因吗?


更新:

// 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 
Run Code Online (Sandbox Code Playgroud)

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

dav*_*ave 5

m34首先设置相当于先旋转然后投影.设置m34最后大致相当于首先投射然后旋转.由于输入坐标的z = 0,首先投影将不会做任何事情.

要了解其原因,您需要了解一下转换矩阵的工作原理.

我相信在CA位置通过变换矩阵M进行变换:

[x y z w] = [x y z w] * M
Run Code Online (Sandbox Code Playgroud)

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

将两个变换矩阵相乘将等效于连接变换.左边的变换/矩阵首先出现.很容易理解这是为什么:

[x y z w] * (LEFT * RIGHT) = ([x y z w] * LEFT) * RIGHT
Run Code Online (Sandbox Code Playgroud)

大多数(全部?)的CA变换函数(例如CATransform3DRotate)只是通过另一个适当构造的矩阵预乘你的变换矩阵,例如:

M = ROTATE * M
Run Code Online (Sandbox Code Playgroud)

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

M = PROJ * M
Run Code Online (Sandbox Code Playgroud)

(PROJ投影矩阵在哪里- 单位矩阵但带有m34集合)

这并不完全正确(这就是为什么我一直粗略地说) - 只有M在正确的位置有一些0和1 才有效.基本上,在一般情况下,设置m34只是一个无意义的事情 - 正确的做法是乘以投影矩阵.

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