Reputation: 63
I use glm::decompose (https://glm.g-truc.net/0.9.6/api/a00204.html) in a way similar to the following:
glm::mat4 matrix;
// ...
glm::vec3 scale;
glm::quat rotation;
glm::vec3 translation;
glm::vec3 skew;
glm::vec4 perspective;
glm::decompose(matrix, scale, rotation, translation, skew, perspective);
Now I would like to compose the matrix back again using all above properties. The thing is simple if all I have in my matrix are scale, rotation and translation (glm::scale
, glm::rotate
, glm::translate
) but what interests me the most is the "skew" property. How can I apply all transformation to a new matrix so that after computation I would get the "matrix" back again?
Upvotes: 4
Views: 1779
Reputation: 2348
Based on Bob's answer, a glm::recompose()
would look something like this (with variable names from the question):
glm::mat4 m = glm::mat4(1.f);
m[0][3] = perspective.x;
m[1][3] = perspective.y;
m[2][3] = perspective.z;
m[3][3] = perspective.w;
m *= glm::translate(translation);
m *= glm::mat4_cast(rotation);
if (skew.x) {
glm::mat4 tmp { 1.f };
tmp[2][1] = skew.x;
m *= tmp;
}
if (skew.y) {
glm::mat4 tmp { 1.f };
tmp[2][0] = skew.y;
m *= tmp;
}
if (skew.z) {
glm::mat4 tmp { 1.f };
tmp[1][0] = skew.z;
m *= tmp;
}
m *= glm::scale(scale);
Upvotes: 1
Reputation: 14654
As mentioned in the comments, the answer is in the source code, the last function in the file b, cited in a
Bring the function recompose
void TransformationMatrix::recompose(const DecomposedType& decomp)
{
makeIdentity();
// first apply perspective
m_matrix[0][3] = (float) decomp.perspectiveX;
m_matrix[1][3] = (float) decomp.perspectiveY;
m_matrix[2][3] = (float) decomp.perspectiveZ;
m_matrix[3][3] = (float) decomp.perspectiveW;
// now translate
translate3d((float) decomp.translateX,
(float) decomp.translateY,
(float) decomp.translateZ);
// apply rotation
double xx = decomp.quaternionX * decomp.quaternionX;
double xy = decomp.quaternionX * decomp.quaternionY;
double xz = decomp.quaternionX * decomp.quaternionZ;
double xw = decomp.quaternionX * decomp.quaternionW;
double yy = decomp.quaternionY * decomp.quaternionY;
double yz = decomp.quaternionY * decomp.quaternionZ;
double yw = decomp.quaternionY * decomp.quaternionW;
double zz = decomp.quaternionZ * decomp.quaternionZ;
double zw = decomp.quaternionZ * decomp.quaternionW;
// Construct a composite rotation matrix from the quaternion values
TransformationMatrix rotationMatrix(
1 - 2 * (yy + zz), 2 * (xy - zw) , 2 * (xz + yw) , 0,
2 * (xy + zw) , 1 - 2 * (xx + zz), 2 * (yz - xw) , 0,
2 * (xz - yw) , 2 * (yz + xw) , 1 - 2 * (xx + yy), 0,
0 , 0 , 0 , 1);
multLeft(rotationMatrix);
//////////////////////////////////////////
// THIS IS WHAT YOU ARE INTERESTED //
//////////////////////////////////////////
// now apply skew
if (decomp.skewYZ) {
TransformationMatrix tmp;
tmp.setM32((float) decomp.skewYZ);
multLeft(tmp);
}
if (decomp.skewXZ) {
TransformationMatrix tmp;
tmp.setM31((float) decomp.skewXZ);
multLeft(tmp);
}
if (decomp.skewXY) {
TransformationMatrix tmp;
tmp.setM21((float) decomp.skewXY);
multLeft(tmp);
}
// finally, apply scale
scale3d((float) decomp.scaleX,
(float) decomp.scaleY,
(float) decomp.scaleZ);
}
Upvotes: 1