1
votes

I have a case where I need a method to rotate a model matrix in OpenGL to absolute value. Most of the rotate() methods out there add rotation to a current one multiplying the current matrix with the new rotation. I need to rotate the model matrix to some value without keeping the old rotation. What I currently do is to destroy the current matrix to identity. Then calculate its scale from scratch based on scale variables I set before. Then multiply it with rotation matrix acquired from quaternion and eventually again translating it.

It looks to me as too many calculations for such a task. Is there a shorter way to reset matrix rotation while keeping its scale and translation parts intact? Here is my current method (Java):

 public void rotateTo3( float xr,float yr,float zr) {



 Quaternion  xrotQ=   Glm.angleAxis( (xr),Vec3.X_AXIS);
 Quaternion  yrotQ=   Glm.angleAxis( (yr),Vec3.Y_AXIS);
 Quaternion  zrotQ=   Glm.angleAxis( (zr),Vec3.Z_AXIS);
  xrotQ= Glm.normalize(xrotQ);
  yrotQ= Glm.normalize(yrotQ);
  zrotQ= Glm.normalize(zrotQ);

  Quaternion acumQuat=new Quaternion();
  acumQuat= Quaternion.mul(xrotQ,yrotQ);
  acumQuat= Quaternion.mul(acumQuat,zrotQ);


  Mat4 rotMat=new Mat4(1);
  rotMat=Glm.matCast(acumQuat);

    _model = new Mat4(1);




   scaleTo(_scaleX, _scaleY, _scaleZ);//reconstruct scale
   _model = Glm.translate(_model, new Vec3(_pivot.x, _pivot.y, 0));


  _model=rotMat.mul(_model); ///add new rotation


   _model = Glm.translate(_model, new Vec3(-_pivot.x, -_pivot.y, 0));



   translateTo(_x, _y, _z);//reconstruct translation

}

2
What's wrong with rotating back, in the opposite direction? Or just keeping the original scale (non-rotated) matrix around, if it doesn't change much? - BlueRaja - Danny Pflughoeft

2 Answers

6
votes

This is actually done rather easy. The key insight is, that a homogenous transformation matrix consists 3 parts: The upper left 3×3 matrix is a rotation-scaling, the rightmost top 1×3 column is the translation, the bottom left 3×1 allows for affine scaling and the bottom right is 1.

So we can write it as

RS T
 A 1

Now what you want to do is decomposing a given RS into R and S. Now rotations are always orthogonal, which means R^T = R^-1. But scalings are not, as for a scaling S^T = S != S^-1, hence we can write

(RS)^T * RS = S^T * R^T * R * S = S^T * R^-1 * R * S = S^T * S = S^2

scaling happens only on the diagonal, so you can extract the x, y and z scaling factors by taking the square root of the elements on the diagonal.

0
votes

I don't think there's any matrix magic to do this, but could you just store your rotation and scale in separate matrices?

void init() {
     _modelScale = some_scale_matrix;
}

void update() {
    _modelRot = LoadIdentity();
    do_some_rotation(_modelRot)

    _model = _modelRot * _modelScale;
}

You could also extend this to a third matrix for translation if you wanted to.