Decomposing a rotation matrix
- by DeadMG
I have a rotation matrix. How can I get the rotation around a specified axis contained within this matrix?
Edit:
It's a 3D matrix (4x4), and I want to know how far around a predetermined (not contained) axis the matrix rotates. I can already decompose the matrix but D3DX will only give the entire matrix as one rotation around one axis, whereas I need to split the matrix up into angle of rotation around an already-known axis, and the rest.
Sample code and brief problem description:
D3DXMATRIX CameraRotationMatrix;
D3DXVECTOR3 CameraPosition;
//D3DXVECTOR3 CameraRotation;
inline D3DXMATRIX GetRotationMatrix() {
return CameraRotationMatrix;
}
inline void TranslateCamera(float x, float y, float z) {
D3DXVECTOR3 rvec, vec(x, y, z);
#pragma warning(disable : 4238)
D3DXVec3TransformNormal(&rvec, &vec, &GetRotationMatrix());
#pragma warning(default : 4238)
CameraPosition += rvec;
RecomputeVPMatrix();
}
inline void RotateCamera(float x, float y, float z) {
D3DXVECTOR3 RotationRequested(x, y, z);
D3DXVECTOR3 XAxis, YAxis, ZAxis;
D3DXMATRIX rotationx, rotationy, rotationz;
XAxis = D3DXVECTOR3(1, 0, 0);
YAxis = D3DXVECTOR3(0, 1, 0);
ZAxis = D3DXVECTOR3(0, 0, 1);
#pragma warning(disable : 4238)
D3DXVec3TransformNormal(&XAxis, &XAxis, &GetRotationMatrix());
D3DXVec3TransformNormal(&YAxis, &YAxis, &GetRotationMatrix());
D3DXVec3TransformNormal(&ZAxis, &ZAxis, &GetRotationMatrix());
#pragma warning(default : 4238)
D3DXMatrixIdentity(&rotationx);
D3DXMatrixIdentity(&rotationy);
D3DXMatrixIdentity(&rotationz);
D3DXMatrixRotationAxis(&rotationx, &XAxis, RotationRequested.x);
D3DXMatrixRotationAxis(&rotationy, &YAxis, RotationRequested.y);
D3DXMatrixRotationAxis(&rotationz, &ZAxis, RotationRequested.z);
CameraRotationMatrix *= rotationz;
CameraRotationMatrix *= rotationy;
CameraRotationMatrix *= rotationx;
RecomputeVPMatrix();
}
inline void RecomputeVPMatrix() {
D3DXMATRIX ProjectionMatrix;
D3DXMatrixPerspectiveFovLH(
&ProjectionMatrix,
FoV,
(float)D3DDeviceParameters.BackBufferWidth / (float)D3DDeviceParameters.BackBufferHeight,
FarPlane,
NearPlane
);
D3DXVECTOR3 CamLookAt;
D3DXVECTOR3 CamUpVec;
#pragma warning(disable : 4238)
D3DXVec3TransformNormal(&CamLookAt, &D3DXVECTOR3(1, 0, 0), &GetRotationMatrix());
D3DXVec3TransformNormal(&CamUpVec, &D3DXVECTOR3(0, 1, 0), &GetRotationMatrix());
#pragma warning(default : 4238)
D3DXMATRIX ViewMatrix;
#pragma warning(disable : 4238)
D3DXMatrixLookAtLH(&ViewMatrix, &CameraPosition, &(CamLookAt + CameraPosition), &CamUpVec);
#pragma warning(default : 4238)
ViewProjectionMatrix = ViewMatrix * ProjectionMatrix;
D3DVIEWPORT9 vp = {
0,
0,
D3DDeviceParameters.BackBufferWidth,
D3DDeviceParameters.BackBufferHeight,
0,
1
};
D3DDev->SetViewport(&vp);
}
Effectively, after a certain time, when RotateCamera is called, it begins to rotate in the relative X axis- even though constant zero is passed in for that request when responding to mouse input, so I know that when moving the mouse, the camera should not roll at all. I tried spamming 0,0,0 requests and saw no change (one per frame at 1500 frames per second), so I'm fairly sure that I'm not seeing FP error or matrix accumulation error. I tried writing a RotateCameraYZ function and stripping all X-axis from the function. I've spent several days trying to discover why this is the case, and eventually decided on just hacking around it.
Just for reference, I've seen some diagrams on Wikipedia, and I actually have a relatively strange axis layout, which is Y axis up, but X axis forwards and Z axis right, so Y axis yaw, Z axis pitch, X axis roll.