linmath.h
linmath.h copied to clipboard
quat_from_mat4 not working
Unfortunately, the function doesn't give correct results.
Here's a proposal to change it (taken from https://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm):
float tr = M[0][0] + M[1][1] + M[2][2];
if (tr > 0) {
float S = sqrt(tr+1.0) * 2; // S=4*qw
q[3] = 0.25 * S;
q[0] = (M[1][2] - M[2][1]) / S;
q[1] = (M[2][0] - M[0][2]) / S;
q[2] = (M[0][1] - M[1][0]) / S;
} else if ((M[0][0] > M[1][1])&(M[0][0] > M[2][2])) {
float S = sqrt(1.0 + M[0][0] - M[1][1] - M[2][2]) * 2; // S=4*qx
q[3] = (M[1][2] - M[2][1]) / S;
q[0] = 0.25 * S;
q[1] = (M[1][0] + M[0][1]) / S;
q[2] = (M[2][0] + M[0][2]) / S;
} else if (M[1][1] > M[2][2]) {
float S = sqrt(1.0 + M[1][1] - M[0][0] - M[2][2]) * 2; // S=4*qy
q[3] = (M[2][0] - M[0][2]) / S;
q[0] = (M[1][0] + M[0][1]) / S;
q[1] = 0.25 * S;
q[2] = (M[2][1] + M[1][2]) / S;
} else {
float S = sqrt(1.0 + M[2][2] - M[0][0] - M[1][1]) * 2; // S=4*qz
q[3] = (M[0][1] - M[1][0]) / S;
q[0] = (M[2][0] + M[0][2]) / S;
q[1] = (M[2][1] + M[1][2]) / S;
q[2] = 0.25 * S;
}
Did you check that the order of the quaternion elements is correct? linmath.h uses a slightly different convention and uses the last element for the real part, i.e. the ordering of the quaternions is i,j,k,r
.
I've also tried shifting the elements, but it didn't work either. Does it work fine in your case?
I did a simple test:
- Initialize an identity matrix
- Extract quaternion with quat_from_mat
- Create a new matrix with mat_from_quat
- Realized that it's not the identity matrix
Can you do this test? If it works for you maybe it's something I messed up :)
I've also tried shifting the elements, but it didn't work either. Does it work fine in your case?
I did a simple test:
1. Initialize an identity matrix 2. Extract quaternion with quat_from_mat
There's your problem right there. An identity matrix has no distinct eigenvector, i.e. axis of rotation: Every vector is an eigenvector of an identity matrix.
Which in turn means, that there's no unique quaternion associated with it.
You must test with a rotation matrix.
Oh, thanks for pointing me that out!
By the way, I've tested it with some transforms coming from an animated data (which contains rotation matrices) and I couldn't get good results, while using the approach I posted it worked smoothly.
Have you had any issue with the function?
https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2015/01/matrix-to-quat.pdf note: row-major post-multiplied
Yeah, I'll have to look at this. A couple of weeks ago I got a bunch of pull requests, and I was so swamped with work, that I didn't check them properly. Mea culpa.
TTBT when I published linmath.h I never expected to take off like that. There are a few warts and pimples I'd like to clean up, but wonder how much that would break for existing codebases.