Search code examples
iosobjective-c3dcore-animationtransformation

What's the proper order to rotate and translate an CALayer with CATransform3D


I have a CALayer which I want to translate and rotate at the same time. I have the following codes which can work actually:

    // layer 1:
    // translate: (△x, △y, △z) = (length/2, 0, length/2)
    // rotate around y: 90 degree
    CATransform3D transformLayer1 = CATransform3DIdentity;
    transformLayer1 = CATransform3DTranslate(transformLayer1, length/2, 0, length/2   );
    transformLayer1 = CATransform3DRotate(transformLayer1, M_PI_2, 0, 1, 0);
    self.layer1.transform = transformLayer1;

During my test, I find the transforming result will be different if I change the order of translation and rotation, for example, the codes are changed like this:

    CATransform3D transformLayer1 = CATransform3DIdentity;

    // do rotation firstly, and then translation
    transformLayer1 = CATransform3DRotate(transformLayer1, M_PI_2, 0, 1, 0);
    transformLayer1 = CATransform3DTranslate(transformLayer1, length/2, 0, length/2   );
    
    self.layer1.transform = transformLayer1;

enter image description here

In the debugging, I print the value of the transform matrix at each step. The results show the value of m43 are different. Is there anyone who can explain why this happened? Or how to understand the Core Animation functions of CATransform3DTranslate() and CATransform3DRotate() ?


Solution

  • The proper order depends on what you want... but matrix multiplication is not commutative which means A*B != B*A where A and B are matrices.

    but if i remember correctly in terms of code, i think the matrix you want to be applied first should be on the very right, so if you have ROT and TRANS matrices, and you want to do a rotation then a transform, make it TRANS*ROT (last time i did anything with matrices was a long time ago, so i may have this backwards)

    use the concat function to do the multipilcation instead of creating the next matrix based off the last one so its easier to see whats going on in terms of left and right multiplying (maybe swift is clever enough to overload the * operator to do this but im not sure)