Open dakom opened 3 years ago
No. There are infinitely many values of Rotation, Translation, Scale and Origin that combine to the same matrix. Origin is a convenience parameter, but it is impossible to recover. Decomposition only returns one of the many matrices it could be, using some heuristics to define its outputs.
If we know the origin and it is not [0, 0, 0], is it possible to get the rotation, translation and scale?
Rotation and scale are identical, the only difference is the translation. If you know the origin you used to create the matrix with, you can extract the original translation with something like (untested):
translation[0] = mtx[12] - origin[0] + (mtx[0] * origin[0] + mtx[4] * origin[1] + mtx[8] * origin[2]);
translation[1] = mtx[13] - origin[1] + (mtx[1] * origin[0] + mtx[5] * origin[1] + mtx[9] * origin[2]);
translation[2] = mtx[14] - origin[2] + (mtx[2] * origin[0] + mtx[6] * origin[1] + mtx[10] * origin[2]);
Here is a function in typescript:
function getTranslation(out: vec3, mat: mat4, origin?: vec3) {
out[0] = mat[12];
out[1] = mat[13];
out[2] = mat[14];
if (origin) {
const ox = origin[0];
const oy = origin[1];
const oz = origin[2];
/*
Algebraically solve for translation vector, based on code in
fromRotationTranslationScaleOrigin
*/
out[0] += mat[0] * ox + mat[4] * oy + mat[8] * oz - ox;
out[1] += mat[1] * ox + mat[5] * oy + mat[9] * oz - oy;
out[2] += mat[2] * ox + mat[6] * oy + mat[10] * oz - oz;
}
return out;
}
And here are some tests (in addition to the existing getTranslation
tests):
it('should get translation with zero origin', () => {
const out = [0, 0, 0] as vec3;
const matrix = mat4.create();
fromTranslation(matrix, [1, 2, 3]);
getTranslation(out, matrix, [0, 0, 0]);
expect(out).toBeEqualish([1, 2, 3]);
});
it('should get translation with non-zero origin', () => {
const out = [0, 0, 0] as vec3;
const matrix = mat4.create();
const quaternion = [-0.1767767, 0.3061862, 0.1767767, 0.9185587] as quat;
const origin = [-4, -5, -6] as vec3;
fromRotationTranslationScaleOrigin(matrix, quaternion, [1, 2, 3], [1.5, 2.5, 3.5], origin);
getTranslation(out, matrix, origin);
expect(out).toBeEqualish([1, 2, 3]);
});
it('should not modify origin', () => {
const out = [0, 0, 0] as vec3;
const matrix = mat4.create();
const quaternion = [-0.1767767, 0.3061862, 0.1767767, 0.9185587] as quat;
const origin = [-4, -5, -6] as vec3;
fromRotationTranslationScaleOrigin(matrix, quaternion, [1, 2, 3], [1.5, 2.5, 3.5], origin);
getTranslation(out, matrix, origin);
expect(origin).toEqual([-4, -5, -6]);
});
Feel free to use and adjust for your styling needs.
If a Matrix is created via
fromRotationTranslationScaleOrigin()
, is it possible to recover the origin, or more specifically, each of:?