# combine two translation/rotation/scale triplets without matrices

Let t1/2, r1/2 and s1/2 be two sets of transformations. Translations are vec3, rotations are quaternions and scales are vec3. Lets assume that all common operations are defined (overloaded operators in c++).

How do I combine (in what order) the two sets of transformations into a third set t3, r3 and s3, such that mat4(t1, r1, s1) * mat4(t2, r2, s2) == mat4(t3, r3, s3), without actually converting to matrices?

Mat4 is composed as M = T * R * S. (OpenGL conventions, if it makes any difference)

Thanks

My original code:

transform transform::operator * (const transform &other) const
{
transform r;
r.orientation = orientation * other.orientation;
r.scale = scale * other.scale;
r.position = position + (other.position * orientation) * scale;
return r;
}


this used to work when scale was just one number (uniform scale). But it does not work with non-uniform scale. I guess that one of the scales have to be rotated, but I am failing to find the correct way.

This is how I test it:

for (uint32 round = 0; round < 10; round++)
{
vec3 pa = randomDirection3() * randomRange(-5, 20);
vec3 pb = randomDirection3() * randomRange(-5, 20);
quat oa = randomDirectionQuat();
quat ob = randomDirectionQuat();
vec3 sa = randomRange3(real(0.1), 10);
vec3 sb = randomRange3(real(0.1), 10);
transform ta(pa, oa, sa), tb(pb, ob, sb);
test(mat4(ta * tb), mat4(ta) * mat4(tb));
}

• This is not possible in the general case when you have both non-90-degree rotations on the "first" transformation and non-uniform scale on the second transformation. This can result in a squash or stretch being applied diagonal to the coordinate axes, which a vec3 of axis-aligned scale values is insufficient to describe. See discussion in this Q&A for more details. Would you be open to adding a second quaternion to your transformation representation to store the basis for scaling? – DMGregory Jan 20 at 14:07
• Oh, I had not thought about that. Thank you very much. I will stay with just uniform scales. – Tomas Jan 20 at 14:37