Fix Matrix4x4t Decompose to rotation vector.

The calculation of the rotation matrix was for left-handed
coordinates with row-vectors, but assimp uses right-handed
coordinates and column-vectors.
pull/1759/head
Tommy 2018-02-01 18:11:14 +01:00
parent e22f5161f5
commit 35f2d8c907
1 changed files with 18 additions and 12 deletions

View File

@ -424,12 +424,18 @@ inline void aiMatrix4x4t<TReal>::Decompose(aiVector3t<TReal>& pScaling, aiVector
{ {
ASSIMP_MATRIX4_4_DECOMPOSE_PART; ASSIMP_MATRIX4_4_DECOMPOSE_PART;
/* /*
| CE -CF D 0 | assuming a right-handed coordinate system
M = | BDE+AF -BDF+AE -BC 0 | and post-multiplication of column vectors,
| -ADE+BF -ADF+BE AC 0 | the rotation matrix for an euler XYZ rotation is M = Rz * Ry * Rx.
| 0 0 0 1 | combining gives:
| CE BDE-AF ADE+BF 0 |
M = | CF BDF+AE ADF-BE 0 |
| -D CB AC 0 |
| 0 0 0 1 |
where
A = cos(angle_x), B = sin(angle_x); A = cos(angle_x), B = sin(angle_x);
C = cos(angle_y), D = sin(angle_y); C = cos(angle_y), D = sin(angle_y);
E = cos(angle_z), F = sin(angle_z); E = cos(angle_z), F = sin(angle_z);
@ -438,20 +444,20 @@ inline void aiMatrix4x4t<TReal>::Decompose(aiVector3t<TReal>& pScaling, aiVector
// Use a small epsilon to solve floating-point inaccuracies // Use a small epsilon to solve floating-point inaccuracies
const TReal epsilon = 10e-3f; const TReal epsilon = 10e-3f;
pRotation.y = std::asin(vCols[2].x);// D. Angle around oY. pRotation.y = std::asin(-vCols[0].z);// D. Angle around oY.
TReal C = std::cos(pRotation.y); TReal C = std::cos(pRotation.y);
if(std::fabs(C) > epsilon) if(std::fabs(C) > epsilon)
{ {
// Finding angle around oX. // Finding angle around oX.
TReal tan_x = vCols[2].z / C;// A TReal tan_x = vCols[2].z / C;// A
TReal tan_y = -vCols[2].y / C;// B TReal tan_y = vCols[1].z / C;// B
pRotation.x = std::atan2(tan_y, tan_x); pRotation.x = std::atan2(tan_y, tan_x);
// Finding angle around oZ. // Finding angle around oZ.
tan_x = vCols[0].x / C;// E tan_x = vCols[0].x / C;// E
tan_y = -vCols[1].x / C;// F tan_y = vCols[0].y / C;// F
pRotation.z = std::atan2(tan_y, tan_x); pRotation.z = std::atan2(tan_y, tan_x);
} }
else else
@ -459,8 +465,8 @@ inline void aiMatrix4x4t<TReal>::Decompose(aiVector3t<TReal>& pScaling, aiVector
pRotation.x = 0;// Set angle around oX to 0. => A == 1, B == 0, C == 0, D == 1. pRotation.x = 0;// Set angle around oX to 0. => A == 1, B == 0, C == 0, D == 1.
// And finding angle around oZ. // And finding angle around oZ.
TReal tan_x = vCols[1].y;// -BDF+AE => E TReal tan_x = vCols[1].y;// BDF+AE => E
TReal tan_y = vCols[0].y;// BDE+AF => F TReal tan_y = -vCols[1].x;// BDE-AF => F
pRotation.z = std::atan2(tan_y, tan_x); pRotation.z = std::atan2(tan_y, tan_x);
} }