BLI: Add 2D transformation matrix decomposition
This patch adds support for 2D transformation matrix decomposition into translation, rotation, and scale. Pull Request: https://projects.blender.org/blender/blender/pulls/111178
This commit is contained in:
parent
1594f7fb95
commit
85a3f61150
|
@ -257,6 +257,7 @@ template<typename MatT, typename VectorT>
|
|||
* Extract euler rotation from transform matrix.
|
||||
* \return the rotation with the smallest values from the potential candidates.
|
||||
*/
|
||||
template<typename T> [[nodiscard]] inline AngleRadianBase<T> to_angle(const MatBase<T, 2, 2> &mat);
|
||||
template<typename T> [[nodiscard]] inline EulerXYZBase<T> to_euler(const MatBase<T, 3, 3> &mat);
|
||||
template<typename T> [[nodiscard]] inline EulerXYZBase<T> to_euler(const MatBase<T, 4, 4> &mat);
|
||||
template<typename T>
|
||||
|
@ -316,6 +317,15 @@ template<bool AllowNegativeScale = false, typename T>
|
|||
* Rotation and scale values will be flipped if it is negative.
|
||||
* This is a costly operation so it is disabled by default.
|
||||
*/
|
||||
template<bool AllowNegativeScale = false, typename T>
|
||||
inline void to_rot_scale(const MatBase<T, 2, 2> &mat,
|
||||
AngleRadianBase<T> &r_rotation,
|
||||
VecBase<T, 2> &r_scale);
|
||||
template<bool AllowNegativeScale = false, typename T>
|
||||
inline void to_loc_rot_scale(const MatBase<T, 3, 3> &mat,
|
||||
VecBase<T, 2> &r_location,
|
||||
AngleRadianBase<T> &r_rotation,
|
||||
VecBase<T, 2> &r_scale);
|
||||
template<bool AllowNegativeScale = false, typename T, typename RotationT>
|
||||
inline void to_rot_scale(const MatBase<T, 3, 3> &mat,
|
||||
RotationT &r_rotation,
|
||||
|
@ -705,6 +715,12 @@ template<typename T, int NumCol, int NumRow, typename VectorT>
|
|||
|
||||
namespace detail {
|
||||
|
||||
template<typename T> AngleRadianBase<T> normalized_to_angle(const MatBase<T, 2, 2> &mat)
|
||||
{
|
||||
BLI_assert(math::is_unit_scale(mat));
|
||||
return AngleRadianBase(mat[0][0], mat[0][1]);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void normalized_to_eul2(const MatBase<T, 3, 3> &mat, EulerXYZBase<T> &eul1, EulerXYZBase<T> &eul2)
|
||||
{
|
||||
|
@ -1070,6 +1086,11 @@ extern template MatBase<float, 4, 4> from_rotation(const AxisAngleCartesian &rot
|
|||
|
||||
} // namespace detail
|
||||
|
||||
template<typename T> [[nodiscard]] inline AngleRadianBase<T> to_angle(const MatBase<T, 2, 2> &mat)
|
||||
{
|
||||
return detail::normalized_to_angle(mat);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] inline Euler3Base<T> to_euler(const MatBase<T, 3, 3> &mat, EulerOrder order)
|
||||
{
|
||||
|
@ -1188,6 +1209,12 @@ template<bool AllowNegativeScale, typename T>
|
|||
/* Implementation details. Use `to_euler` and `to_quaternion` instead. */
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
inline void to_rotation(const MatBase<T, 2, 2> &mat, AngleRadianBase<T> &r_rotation)
|
||||
{
|
||||
r_rotation = to_angle<T>(mat);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void to_rotation(const MatBase<T, 3, 3> &mat, QuaternionBase<T> &r_rotation)
|
||||
{
|
||||
|
@ -1208,6 +1235,31 @@ inline void to_rotation(const MatBase<T, 3, 3> &mat, Euler3Base<T> &r_rotation)
|
|||
|
||||
} // namespace detail
|
||||
|
||||
template<bool AllowNegativeScale, typename T>
|
||||
inline void to_rot_scale(const MatBase<T, 2, 2> &mat,
|
||||
AngleRadianBase<T> &r_rotation,
|
||||
VecBase<T, 2> &r_scale)
|
||||
{
|
||||
MatBase<T, 2, 2> normalized_mat = normalize_and_get_size(mat, r_scale);
|
||||
if constexpr (AllowNegativeScale) {
|
||||
if (UNLIKELY(is_negative(normalized_mat))) {
|
||||
normalized_mat = -normalized_mat;
|
||||
r_scale = -r_scale;
|
||||
}
|
||||
}
|
||||
detail::to_rotation<T>(normalized_mat, r_rotation);
|
||||
}
|
||||
|
||||
template<bool AllowNegativeScale, typename T>
|
||||
inline void to_loc_rot_scale(const MatBase<T, 3, 3> &mat,
|
||||
VecBase<T, 2> &r_location,
|
||||
AngleRadianBase<T> &r_rotation,
|
||||
VecBase<T, 2> &r_scale)
|
||||
{
|
||||
r_location = mat.location();
|
||||
to_rot_scale<AllowNegativeScale>(MatBase<T, 2, 2>(mat), r_rotation, r_scale);
|
||||
}
|
||||
|
||||
template<bool AllowNegativeScale, typename T, typename RotationT>
|
||||
inline void to_rot_scale(const MatBase<T, 3, 3> &mat,
|
||||
RotationT &r_rotation,
|
||||
|
|
|
@ -411,6 +411,23 @@ TEST(math_matrix, MatrixMethods)
|
|||
EXPECT_V3_NEAR(float3(eul), float3(expect_eul), 0.0002f);
|
||||
}
|
||||
|
||||
TEST(math_matrix, Transformation2DMatrixDecomposition)
|
||||
{
|
||||
const float2 translation = float2(1.0f, 2.0f);
|
||||
const AngleRadian rotation = AngleRadian(0.5f);
|
||||
const float2 scale = float2(5.0f, 3.0f);
|
||||
|
||||
const float3x3 transformation = from_loc_rot_scale<float3x3>(translation, rotation, scale);
|
||||
|
||||
AngleRadian decomposed_rotation;
|
||||
float2 decomposed_translation, decomposed_scale;
|
||||
to_loc_rot_scale(transformation, decomposed_translation, decomposed_rotation, decomposed_scale);
|
||||
|
||||
EXPECT_V2_NEAR(decomposed_translation, translation, 0.00001f);
|
||||
EXPECT_V2_NEAR(decomposed_scale, scale, 0.00001f);
|
||||
EXPECT_NEAR(decomposed_rotation.radian(), rotation.radian(), 0.00001f);
|
||||
}
|
||||
|
||||
TEST(math_matrix, MatrixToQuaternionLegacy)
|
||||
{
|
||||
float3x3 mat = {{0.808309, -0.578051, -0.111775},
|
||||
|
|
Loading…
Reference in New Issue