Search code examples
openglmatrixglm-math

why is the transformation matrices behaving differently


I get different results when scaling objects.

The objects have four different glm::vec3 values

 1) Position , Rotation , Scaling , Center Point

This is the Transformation Matrix of the object

   TransformationMatrix = PositionMatrix() * RotationMatrix() * ScalingMatrix();

The rotation and scaling Matrix looks like this.

glm::vec3 pivotVector(pivotx, pivoty, pivotz);
glm::mat4 TransPivot = glm::translate(glm::mat4x4(1.0f), pivotVector);
glm::mat4 TransPivotInverse = glm::translate(glm::mat4x4(1.0f), -pivotVector);
glm::mat4 TransformationScale = glm::scale(glm::mat4(1.0), glm::vec3(scax, scay, scaz));
return   TransPivot * TransformationScale * TransPivotInverse;

In the first case.

enter image description here

I move the rectangle object to 200 units in x.

Than i scale the group which is at position x = 0.0

so the final matrix for the rectangle object is

 finalMatrix = rectangleTransformationMatrix * groupTransformationMatrix

The result i what i expected.The rectangle scales and moves towards the center of the screen.

enter image description here

Now if i do the same thing with three containers.

Here i move the group container to 200 and scale the Top container which is at position 0.0

   finalMatrix = rectangleTransformationMatrix * groupTransformationMatrix * TopTransformationMatrix

the rectangle scales at its own position as if the center point of the screen has also moved 200 units.

enter image description here

If i add -200 units to the pivot point x of the top container than i get the result what i expected.

where rectangle moves towards the center of the screen and scales.

If someone can please explain me why i need to add -200 units to the center point of the Top container.Whereas in the first case i did not need to add any value to the pivot point of the scaling container.

when both the operations are identical in nature.

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

First case

Rectangle - > position( x = 200 , y = 0, z = 0) , scaling( 1.0 , 1.0 , 1.0 ) , Rotation( 0.0 , 0.0 , 0.0 )
glm::mat4 PositionMatrix = glm::position( // fill the values);
glm::mat4 ScalingMatrix = glm::scaling( // fill the values);
glm::mat4 RotationMatrix = glm::rotate( // fill the values);
RectangleMatrix = PositionMatrix() * RotationMtrix() * ScalingMatrix();

the matrix for group

 froup - > position( x = 0.0 , y = 0, z = 0) , scaling( 0.5 , 1.0 , 1.0 ) , Rotation( 0.0 , 0.0 , 0.0 )
groupMatrix = PositionMatrix() * RotationMtrix() * ScalingMatrix();

final result finalMatrix = RectangleMatrix * groupMatrix

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Second case

Rectangle - > position( x = 0 , y = 0, z = 0) , scaling( 1.0 , 1.0 , 1.0 ) , Rotation( 0.0 , 0.0 , 0.0 )
glm::mat4 PositionMatrix = glm::position( // fill the values);
glm::mat4 ScalingMatrix = glm::scaling( // fill the values);
glm::mat4 RotationMatrix = glm::rotate( // fill the values);
RectangleMatrix = PositionMatrix() * RotationMtrix() * ScalingMatrix();

the matrix for group

 group - > position( x = 200.0 , y = 0, z = 0) , scaling( 1.0 , 1.0 , 1.0 ) , Rotation( 0.0 , 0.0 , 0.0 )
groupMatrix = PositionMatrix() * RotationMtrix() * ScalingMatrix();

the matrix for Top

 Top - > position( x = 0.0 , y = 0, z = 0) , scaling( 0.5 , 1.0 , 1.0 ) , Rotation( 0.0 , 0.0 , 0.0 )
TopMatrix = PositionMatrix() * RotationMtrix() * ScalingMatrix();

final result finalMatrix = RectangleMatrix * groupMatrix * TopMatrix


Solution

  • Matrix operations are not Commutative. scale * translate is not the same as translate * scale

    If you have a translation of 200 and and a scale of 0.2, then

    translate(200) * scale(0.2)
    

    gives object scaled by 0.2 and translated by 200. But

    scale(0.2) * translate(200)
    

    gives object scaled by 0.2 and translated by 40 (0.2*200).

    If you have 2 matrices:

    groupMatrix = PositionMatrix() * RotationMtrix() * ScalingMatrix();
    TopMatrix = PositionMatrix() * RotationMtrix() * ScalingMatrix();
    

    Then groupMatrix * TopMatrix is the same as

    groupPositionMatrix * groupRotationMtrix * groupScalingMatrix * topPositionMatrix * topRotationMtrix * topScalingMatrix
    

    The result is different if the scale is encoded in groupScalingMatrix or topScalingMatrix respectively the translation is encoded in groupPositionMatrix or topPositionMatrix.