Fix #119703: Incorrect conversion of identity quaternion to axis angle

Fix of conversion identity quaternion to axis angle. Basically,
if the length of the imaginary part-vector is zero, it is
incorrect to normalize it. Simple identity should be returned.

Pull Request: https://projects.blender.org/blender/blender/pulls/119762
This commit is contained in:
Iliya Katushenock
2024-06-06 19:26:40 +02:00
committed by Brecht Van Lommel
parent 9f1f869e16
commit cdcefa43e3
2 changed files with 23 additions and 2 deletions

View File

@@ -630,8 +630,11 @@ AxisAngleBase<T, AngleT> to_axis_angle(const QuaternionBase<T> &quat)
T sin_half_angle = math::length(axis);
/* Prevent division by zero for axis conversion. */
if (sin_half_angle < T(0.0005)) {
sin_half_angle = T(1);
axis[1] = T(1);
using AngleAxisT = typename AxisAngleBase<T, AngleT>::vec3_type;
const AngleAxisT identity_axis = AxisAngleBase<T, AngleT>::identity().axis();
BLI_assert(abs(cos_half_angle) > 0.0005);
AxisAngleBase<T, AngleT> identity(identity_axis * sign(cos_half_angle), AngleT(0));
return identity;
}
/* Normalize the axis. */
axis /= sin_half_angle;

View File

@@ -879,4 +879,22 @@ TEST(math_rotation, DualQuaternionTransform)
}
}
TEST(math_axis_angle, AxisAngleFromQuaternion)
{
{
const math::AxisAngle axis_angle({0.0f, 1.0f, 0.0f}, math::AngleRadian(0));
const math::Quaternion quaternion(1.0f, {0.0f, 0.0f, 0.0f});
const math::AxisAngle from_quaternion = math::to_axis_angle(quaternion);
EXPECT_V3_NEAR(axis_angle.axis(), from_quaternion.axis(), 1e-6);
EXPECT_NEAR(axis_angle.angle().radian(), from_quaternion.angle().radian(), 1e-6);
}
{
const math::AxisAngle axis_angle({0.0f, -1.0f, 0.0f}, math::AngleRadian(0));
const math::Quaternion quaternion(-1.0f, {0.0f, 0.0f, 0.0f});
const math::AxisAngle from_quaternion = math::to_axis_angle(quaternion);
EXPECT_V3_NEAR(axis_angle.axis(), from_quaternion.axis(), 1e-6);
EXPECT_NEAR(axis_angle.angle().radian(), from_quaternion.angle().radian(), 1e-6);
}
}
} // namespace blender::math::tests