| 207 | } |
| 208 | |
| 209 | void Matrix3x3::Decompose(Float3& scale, Matrix3x3& rotation) const |
| 210 | { |
| 211 | // Scaling is the length of the rows |
| 212 | scale = Float3( |
| 213 | Math::Sqrt(M11 * M11 + M12 * M12 + M13 * M13), |
| 214 | Math::Sqrt(M21 * M21 + M22 * M22 + M23 * M23), |
| 215 | Math::Sqrt(M31 * M31 + M32 * M32 + M33 * M33)); |
| 216 | |
| 217 | // If any of the scaling factors are zero, than the rotation matrix can not exist |
| 218 | rotation = Identity; |
| 219 | if (scale.IsAnyZero()) |
| 220 | return; |
| 221 | |
| 222 | // Calculate an perfect orthonormal matrix (no reflections) |
| 223 | const auto at = Float3(M31 / scale.Z, M32 / scale.Z, M33 / scale.Z); |
| 224 | const auto up = Float3::Cross(at, Float3(M11 / scale.X, M12 / scale.X, M13 / scale.X)); |
| 225 | const auto right = Float3::Cross(up, at); |
| 226 | rotation.SetRight(right); |
| 227 | rotation.SetUp(up); |
| 228 | rotation.SetForward(at); |
| 229 | |
| 230 | // In case of reflexions |
| 231 | scale.X = Float3::Dot(right, GetRight()) > 0.0f ? scale.X : -scale.X; |
| 232 | scale.Y = Float3::Dot(up, GetUp()) > 0.0f ? scale.Y : -scale.Y; |
| 233 | scale.Z = Float3::Dot(at, GetBackward()) > 0.0f ? scale.Z : -scale.Z; |
| 234 | } |
| 235 | |
| 236 | void Matrix3x3::Decompose(Float3& scale, Quaternion& rotation) const |
| 237 | { |
nothing calls this directly
no test coverage detected