In short: I need to combine rotation (in the form of a quaternion), scaling around a pivot point along with translation into a transformation matrix.

The long: I am trying to implement a proprietary model format. This format includes animations. Part of that animation involves generating a matrix which combines rotation (in the form of a quaternion) and scaling around a pivot point, with translation into a transformation matrix. I am using OpenGL and the OpenGL math library (GLM)

Someone else has already implemented parts of the proprietary model format using DirectX. The part in question was implemented in directX like this:

D3DXMatrixTransformation(&BaseMatrix, &ModelBaseData->PivotPoint, NULL, &ScalingVector, &ModelBaseData->PivotPoint, reinterpret_cast<D3DXQUATERNION*>(&RotationVector), &TranslationVector);

I found the WINE implementation of this function and attempted to duplicate it like this:

mat4 m1, m2, m3, m4, m5, m6, m7, p1, p2, p3, p4, p5;

m5 = glm::translate(0,0,0);
m7 = glm::translate(pivot+translationVector);
m1 = glm::translate(-pivot);
m3 = glm::scale(scalingVector);
m6 = glm::mat4_cast(rotationQuaternion); //Convert quaternion to a matrix

//m2 & m4 are identity
p1 = m1;// * m2
p2 = p1 * m3; //Apply scaling first
p3 = p2;// * m4;
p4 = p3 * m5; 
p5 = p4;
p5 = p4 * m6;
mat4 result = p5 * m7;

(I realize glm::translate(0,0,0) is the identity matrix) Unfortunately neither the scaling nor the rotation seems to work correctly like this. So I took another approach based off of this ordering of translation, rotation and scaling.

mat4 result = glm::scale(scalingVector) * glm::translate(pivot) * glm::mat4_cast(rotationQuaternion) * glm::translate(translationVector);

However the scaling does not appear to be around the pivot point and I'm not entirely sure about the rotation. Does anyone have any tips on how to accomplish this?


Rotation/scaling is around the origin. To both scale/rotate around a pivot, you apply a negative translation to move the pivot point to the origin, apply your scale and rotate, and then move your pivot point back.

mat4 result = glm::translate(-pivot) *
              glm::scale(..) *
              glm::rotate(..) *
              glm::translate(pivot) *
  • \$\begingroup\$ Thank you so much for the explanation and everything. To get it to work in my use case I had to reverse the negatives, I have no idea why. \$\endgroup\$ – wd40bomber7 Aug 30 '13 at 6:16
  • 2
    \$\begingroup\$ @wd40bomber7: That is just a convention as to what frame the translations are moving from and to. You chose the opposite from what Jimmy did, so have to reverse the two signs. \$\endgroup\$ – Pieter Geerkens Aug 30 '13 at 22:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.