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
}
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
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
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.