# Scaling a rotated child with parent-child transforms

In unity, if you parent something to another object, then give the child some rotation, and scale the parent, the scale applies to some arbitrary axis to the child, here's some pictures to demonstrate:

Now I scale the Z axis of the parent object and this happens:

My from scratch game does not do this. Rather it applies the parent scale along the same local axis on the child, so you get this:

I don't know how to achieve Unity's scaling behaviour though. Right now transformations are combinations of standard transform matrices that are just applied child to parent. Like this:

Matrixf child = Matrixf::Translate(childTrans) * Matrixf::Rotate(childRotation) * Matrixf::Scale(childScale);
Matrixf parent = Matrixf::Translate(parentTrans) * Matrixf::Rotate(parentRotation) * Matrixf::Scale(parentScale);

Matrixf worldChildTransform = parent * child;


Transform matrices defined as such:

inline static Matrix Translate(Vec3<T> translate)
{
Matrix mat;
mat.m[0][0] = T(1.0); mat.m[0][1] = T(0.0); mat.m[0][2] = T(0.0); mat.m[0][3] = translate.x;
mat.m[1][0] = T(0.0); mat.m[1][1] = T(1.0); mat.m[1][2] = T(0.0); mat.m[1][3] = translate.y;
mat.m[2][0] = T(0.0); mat.m[2][1] = T(0.0); mat.m[2][2] = T(1.0); mat.m[2][3] = translate.z;
mat.m[3][0] = T(0.0); mat.m[3][1] = T(0.0); mat.m[3][2] = T(0.0); mat.m[3][3] = T(1.0);
return mat;
}

inline static Matrix Rotate(Vec3<T> rotation)
{
// This is a body 3-2-1 (z, then y, then x) rotation
const T cx = cos(rotation.x);
const T sx = sin(rotation.x);
const T cy = cos(rotation.y);
const T sy = sin(rotation.y);
const T cz = cos(rotation.z);
const T sz = sin(rotation.z);

Matrix res;
res.m[0][0] = cy*cz;    res.m[0][1] = -cx*sz + sx*sy*cz;    res.m[0][2] =  sx*sz + cx*sy*cz;    res.m[0][3] = T(0.0);
res.m[1][0] = cy*sz;    res.m[1][1] =  cx*cz + sx*sy*sz;    res.m[1][2] = -sx*cz + cx*sy*sz;    res.m[1][3] = T(0.0);
res.m[2][0] = -sy;      res.m[2][1] = sx*cy;                res.m[2][2] = cx*cy;                res.m[2][3] = T(0.0);
res.m[3][0] = T(0.0);   res.m[3][1] = T(0.0);               res.m[3][2] = T(0.0);               res.m[3][3] = T(1.0);
return res;
}

inline static Matrix Scale(Vec3<T> scale)
{
Matrix mat;
mat.m[0][0] = scale.x;  mat.m[0][1] = T(0.0);   mat.m[0][2] = T(0.0);   mat.m[0][3] = T(0.0);
mat.m[1][0] = T(0.0);   mat.m[1][1] = scale.y;  mat.m[1][2] = T(0.0);   mat.m[1][3] = T(0.0);
mat.m[2][0] = T(0.0);   mat.m[2][1] = T(0.0);   mat.m[2][2] = scale.z;  mat.m[2][3] = T(0.0);
mat.m[3][0] = T(0.0);   mat.m[3][1] = T(0.0);   mat.m[3][2] = T(0.0);   mat.m[3][3] = T(1.0);
return mat;
}


Given this configuration

Parent position = (0, 0, 3)
Parent scale = (0.5, 0.5, 0.2)
Parent rotation = (0, 0, 0) (euler angles, radians)

Child local position = (0, 0, 4.2)
Child local scale = (1, 1, 1)
Child local rotation = (0, 0.9, 0) (euler angles, radians)


Then we have the following matrices

Child (combined translation, rotation and scale)

{0.621609986, 0.000000000, 0.783326924, 0.000000000}
{0.000000000, 1.00000000, 0.000000000, 0.000000000}
{-0.783326924, 0.000000000, 0.621609986, 4.19999981}
{0.000000000, 0.000000000, 0.000000000, 1.00000000}


Parent (combined again)

{0.500000000, 0.000000000, 0.000000000, 0.000000000}
{0.000000000, 0.500000000, 0.000000000, 0.000000000}
{0.000000000, 0.000000000, 0.200000003, 3.00000000}
{0.000000000, 0.000000000, 0.000000000, 1.00000000}


Then parent * child gives this:

{0.310804993, 0.000000000, 0.391663462, 0.000000000}
{0.000000000, 0.500000000, 0.000000000, 0.000000000}
{-0.156665385, 0.000000000, 0.124321997, 3.83999991}
{0.000000000, 0.000000000, 0.000000000, 1.00000000}

• Can you clarify, do you want to get the colourful cubes in your game to have the same scaling behaviour as the grey scene in Unity? Or are you looking for a way to get the behaviour the coloured cubes are showing and apply it in a Unity scene? – DMGregory Apr 13 '20 at 23:52
• I want the same scaling behaviour as the grey scene in Unity to be present in my (non-unity) game – DavidColson Apr 14 '20 at 7:03
• Can you please post the content of all of your submatrices? The transformation order seems correct. Maybe you used wrong inputs or the calculated matrices are not correct. – wychmaster Apr 14 '20 at 10:51
• I've posted the contents of the child, parent and result matrices, is that enough? – DavidColson Apr 14 '20 at 18:13
• One last detail: can you show us how you multiply your vertices by this worldChildTransform matrix? I have a suspicion you're using the opposite multiplication order there, compared to the parent * child order you've shown. – DMGregory Apr 14 '20 at 23:04