6
\$\begingroup\$

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?

\$\endgroup\$

1 Answer 1

7
\$\begingroup\$

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) *
              glm::translate(..);
\$\endgroup\$
2
  • \$\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\$ Aug 30, 2013 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\$ Aug 30, 2013 at 22:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .