Concatenating Transformations

Experimental Setup

This experiment explores the results of either (1) finding the cross product of two transformation matrices before multiplying the result to a vector ((M1×M2)×v), or (2) applying a transformation to the vector, then applying another transformation to the changed vector (M1×(M2×v)). The goal is to develop techniques to either manipulate a vector in its local coordinates or manipulate a vector in global coordinates.

The vector is [1,0,0] in each case. Rotations are always π/2 around the z-axis, scales are always by 2× in x, and translations are always +3 in y.

Transforms in local coordinates

Name First Operation Second Operation Concatenated Matrices Applied to Vector
TT Translation Translation (T×T)×v= T×(T×v)=
TR Translation Rotation (T×R)×v= T×(R×v)=
TS Translation Scale (T×S)×v= T×(S×v)=
ST Scale Translation (S×T)×v= S×(T×v)=
SR Scale Rotation (S×R)×v= S×(R×v)=
SS Scale Scale (S×S)×v= S×(S×v)=
RT Rotation Translation (R×T)×v= R×(T×v)=
RR Rotation Rotation (R×R)×v= R×(R×v)=
RS Rotation Scale (R×S)×v= R×(S×v)=

Let's look at RT. You rotate [1,0,0] by π/2 around z to get [0,1,0]. Translate +3 in y and you end up with [-3,1,0]. Why -3? Because the transform occured in the object's local coordinates, where the object's y has rotated to the global x axis.

Not the result I had expected. (M1×M2)×v appears to work in object coordinates as expected, but the results are always the same. Knowing that matrix multiplication is not commutative, let's try reversing the order of some operations and see what happens.

Transforms in global coordinates

This time we reverse the order of transformation matrices.

Name First Operation Second Operation Concatenated Matrices Applied to Vector
TR Translation Rotation (R×T)×v= R×(T×v)=
TS Translation Scale (S×T)×v= S×(T×v)=
ST Scale Translation (T×S)×v= T×(S×v)=
SR Scale Rotation (R×S)×v= R×(S×v)=
RT Rotation Translation (T×R)×v= T×(R×v)=
RS Rotation Scale (S×R)×v= S×(R×v)=

Let's take a look at RT again. We rotated [1,0,0] by π/2 around z to get [0,1,0]. We translate by +3 in y as before, but this time we end up with [0,4,0]. The translation occurred in global coordinates.

A closer look shows that TR in this table is identical to RT in the above table. The real difference is how one thinks about the effect these operations have. By multiplying a transform to the left or right of another transform we can influence its behavior in global or local coordinates.

Result

java.awt.geom.AffineTransform has an interesting discussion on this subject. The class provides methods to concatenate and preConcatenate a transformation matrix. The JavaDoc explains that these methods are to be used to manipulate a transformation in local (or "user space") or global coordinates ("absolute pixel space"). The results of this experiment support this approach. Multiplying a transform on the right updates the transform in its local coordinates, and multiplying a transform on the left ("pre") updates the transform in global coordinates.

House explains that matrix multiplication is associative and x'=R(H(Sx))=(RHS)x. Thus, (M1×M2)×v=M1×(M2×v) and (M2×M1)×v=M2×(M1×v).