From 0342fb5d20cd13b495a7511ccfdfc3044d83cb04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Tue, 3 Aug 2021 13:43:24 +0200 Subject: Fix T90387: division by zero when trying to invert scale Fix division by zero when `BKE_bone_parent_transform_invert()` inverts a scale vector with zero components. Zero values in the to-be-inverted vector are now simply skipped, i.e. remain zero after inversion. This at least ensures that `invert_v3_safe(invert_v3_safe(vector))` results in the same vector. This commit does NOT fix the conceptual problem that an inversion of a potentially non-invertible vector is relied upon. It just avoids the division by zero. --- source/blender/blenkernel/intern/armature.c | 2 +- source/blender/blenlib/BLI_math_vector.h | 1 + source/blender/blenlib/intern/math_vector_inline.c | 13 +++++++++++++ source/blender/blenlib/tests/BLI_math_vector_test.cc | 18 ++++++++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) (limited to 'source') diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 434d696f9bd..1f02b084534 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1882,7 +1882,7 @@ void BKE_bone_parent_transform_invert(struct BoneParentTransform *bpt) { invert_m4(bpt->rotscale_mat); invert_m4(bpt->loc_mat); - invert_v3(bpt->post_scale); + invert_v3_safe(bpt->post_scale); } void BKE_bone_parent_transform_combine(const struct BoneParentTransform *in1, diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 2f4cf1721af..860ba14a3ed 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -185,6 +185,7 @@ MINLINE void negate_v3_db(double r[3]); MINLINE void invert_v2(float r[2]); MINLINE void invert_v3(float r[3]); +MINLINE void invert_v3_safe(float r[3]); /* Invert the vector, but leaves zero values as zero. */ MINLINE void abs_v2(float r[2]); MINLINE void abs_v2_v2(float r[2], const float a[2]); diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index 55f7a152b83..dddefd60b1b 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -847,6 +847,19 @@ MINLINE void invert_v3(float r[3]) r[2] = 1.0f / r[2]; } +MINLINE void invert_v3_safe(float r[3]) +{ + if (r[0] != 0.0f) { + r[0] = 1.0f / r[0]; + } + if (r[1] != 0.0f) { + r[1] = 1.0f / r[1]; + } + if (r[2] != 0.0f) { + r[2] = 1.0f / r[2]; + } +} + MINLINE void abs_v2(float r[2]) { r[0] = fabsf(r[0]); diff --git a/source/blender/blenlib/tests/BLI_math_vector_test.cc b/source/blender/blenlib/tests/BLI_math_vector_test.cc index 7e75a521d4c..955f02b8065 100644 --- a/source/blender/blenlib/tests/BLI_math_vector_test.cc +++ b/source/blender/blenlib/tests/BLI_math_vector_test.cc @@ -45,3 +45,21 @@ TEST(math_vector, ClampVecWithVecs) EXPECT_FLOAT_EQ(1.0f, c[0]); EXPECT_FLOAT_EQ(3.0f, c[1]); } + +TEST(math_vector, test_invert_v3_safe) +{ + float v3_with_zeroes[3] = {0.0f, 2.0f, 3.0f}; + invert_v3_safe(v3_with_zeroes); + EXPECT_FLOAT_EQ(0.0f, v3_with_zeroes[0]); + EXPECT_FLOAT_EQ(0.5f, v3_with_zeroes[1]); + EXPECT_FLOAT_EQ(0.33333333333f, v3_with_zeroes[2]); + + float v3_without_zeroes[3] = {1.0f, 2.0f, 3.0f}; + float inverted_unsafe[3] = {1.0f, 2.0f, 3.0f}; + invert_v3_safe(v3_without_zeroes); + invert_v3(inverted_unsafe); + + EXPECT_FLOAT_EQ(inverted_unsafe[0], v3_without_zeroes[0]); + EXPECT_FLOAT_EQ(inverted_unsafe[1], v3_without_zeroes[1]); + EXPECT_FLOAT_EQ(inverted_unsafe[2], v3_without_zeroes[2]); +} -- cgit v1.2.3