Why does a CALayer's transform3D's m34 need to be modified before applying the rotate transform?
3d, calayer, ios, opengl-es
Solution
Setting `m34` first is equivalent to rotating first and then projecting. Setting `m34` last is roughly equivalent to projecting first and then rotating. As the input coordinates have z=0, projecting first won't do anything.
To see why this is, you need to understand a little about how transform matrices work.
I believe that in CA positions are transformed by a transform matrix `M` by doing:
[x y z w] = [x y z w] * M
(see http://en.wikipedia.org/wiki/Matrix_multiplication)
Multiplying two transform matrices together is equivalent to concatenating the transforms. The transform/matrix on the left happens first. It's pretty easy to see why this is:
[x y z w] * (LEFT * RIGHT) = ([x y z w] * LEFT) * RIGHT
Most (all?) of the CA transform functions (eg `CATransform3DRotate`) just premultiply your transform matrix by another aptly constructed matrix, eg:
M = ROTATE * M
Setting `m34` is roughly equivalent to premultiplying by a projection matrix, that is:
M = PROJ * M
(where `PROJ` is the projection matrix -- an identity matrix but with `m34` set)
This isn't entirely true (which is why I keep saying roughly) -- it only works if `M` has some 0s and 1s in the right places. Basically, in the general case, just setting `m34` is a nonsense thing to do -- the right thing to do is to multiply by a projection matrix.
Anyway, if you put all that together you should be able to see why what I said in the first paragraph is true (assuming I haven't made any mistakes :)
Problem
The following code can make a perspective rotation transform for a layer: ``` CATransform3D transform3DFoo = CATransform3DIdentity; transform3DFoo.m34 = -1.0 / 1000; transform3DFoo = CATransform3DRotate(transform3DFoo, M_PI / 4, 1, 0, 0); ``` However, if the two lines are reversed: ``` CATransform3D transform3DFoo = CATransform3DIdentity; transform3DFoo = CATransform3DRotate(transform3DFoo, M_PI / 4, 1, 0, 0); transform3DFoo.m34 = -1.0 / 1000; ``` then the perspective is gone. Now it is orthographic (no perspective). Does someone who is familiar with perspective know why the reason? Update: ``` // 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 ``` (the tag of "OpenGL" is added because it probably is the same principle in OpenGL)