¿Por qué es necesario modificar la transform3D's m34 de CALayer antes de aplicar la transformada rotate?

El siguiente código puede transformar una rotation de perspectiva para una capa:

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

Sin embargo, si las dos líneas se invierten:

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

entonces la perspectiva se ha ido. Ahora es ortográfico (sin perspectiva). ¿Alguien familiarizado con la perspectiva sabe por qué motivo?


Actualizar:

 // 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 

(la label de "OpenGL" se agrega porque probablemente sea el mismo principio en OpenGL)

Configurar primero m34 es equivalente a girar primero y luego a proyectar. Configurar el último m34 es más o less equivalente a proyectar primero y luego rotar. Como las coorderadas de input tienen z = 0, la proyección primero no hará nada.

Para ver por qué esto es así, debe comprender un poco acerca de cómo funcionan las matrices de transformación.

Creo que en las posiciones de CA se transforman mediante una matriz de transformación M haciendo:

 [xyzw] = [xyzw] * M 

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

Multiplicar dos matrices de transformación juntas equivale a concatenar las transformadas. La transformación / matriz a la izquierda ocurre primero. Es bastante fácil ver por qué esto es:

 [xyzw] * (LEFT * RIGHT) = ([xyzw] * LEFT) * RIGHT 

La mayoría (¿todas?) De las funciones de transformación de CA (por ejemplo, CATransform3DRotate ) simplemente premultiplican su matriz de transformación mediante otra matriz adecuadamente construida, por ejemplo:

 M = ROTATE * M 

La configuration de m34 es más o less equivalente a la premultiplicación por una matriz de proyección, es decir:

 M = PROJ * M 

(donde PROJ es la matriz de proyección – una matriz de identidad, pero con el set m34 )

Esto no es del todo cierto (por eso sigo diciendo aproximadamente), solo funciona si M tiene algunos 0s y 1s en los lugares correctos. Básicamente, en el caso general, simplemente establecer m34 tiene sentido, lo correcto es multiplicar por una matriz de proyección.

De todos modos, si pones todo eso en order, verás por qué lo que dije en el primer párrafo es cierto (suponiendo que no haya cometido ningún error 🙂