diff options
author | Campbell Barton <ideasman42@gmail.com> | 2013-09-06 09:44:18 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2013-09-06 09:44:18 +0400 |
commit | 6439ae9d51dfe3a77ff778e35cf83909bbc93acc (patch) | |
tree | b62a6cebe2dc88b4db4b1fe50924b5039c23dacf /source/blender/blenlib | |
parent | e045e324a47fcaf5c5fd13bbb165cabe9c1051bf (diff) |
fix for barycentric_weights_v2_quad() divide by zero when the location we're checking the weight of touches one of the weighting coords exactly.
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r-- | source/blender/blenlib/intern/math_geom.c | 50 |
1 files changed, 29 insertions, 21 deletions
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 68f246e3982..cf1377f6627 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -2200,8 +2200,6 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo ((_area = cross_v2v2(dirs[i1], dirs[i2])) != 0.0f ? \ fabsf(((lens[i1] * lens[i2]) - dot_v2v2(dirs[i1], dirs[i2])) / _area) : 0.0f) - float wtot, area; - const float dirs[4][2] = { {v1[0] - co[0], v1[1] - co[1]}, {v2[0] - co[0], v2[1] - co[1]}, @@ -2216,20 +2214,29 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo len_v2(dirs[3]), }; - /* variable 'area' is just for storage, - * the order its initialized doesn't matter */ + /* avoid divide by zero */ + if (UNLIKELY(lens[0] < FLT_EPSILON)) { w[0] = 1.0f; w[1] = w[2] = w[3] = 0.0f; } + else if (UNLIKELY(lens[1] < FLT_EPSILON)) { w[1] = 1.0f; w[0] = w[2] = w[3] = 0.0f; } + else if (UNLIKELY(lens[2] < FLT_EPSILON)) { w[2] = 1.0f; w[0] = w[1] = w[3] = 0.0f; } + else if (UNLIKELY(lens[3] < FLT_EPSILON)) { w[3] = 1.0f; w[0] = w[1] = w[2] = 0.0f; + } + else { + float wtot, area; + + /* variable 'area' is just for storage, + * the order its initialized doesn't matter */ #ifdef __clang__ # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wunsequenced" #endif - /* inline mean_value_half_tan four times here */ - float t[4] = { - MEAN_VALUE_HALF_TAN_V2(area, 0, 1), - MEAN_VALUE_HALF_TAN_V2(area, 1, 2), - MEAN_VALUE_HALF_TAN_V2(area, 2, 3), - MEAN_VALUE_HALF_TAN_V2(area, 3, 0), - }; + /* inline mean_value_half_tan four times here */ + float t[4] = { + MEAN_VALUE_HALF_TAN_V2(area, 0, 1), + MEAN_VALUE_HALF_TAN_V2(area, 1, 2), + MEAN_VALUE_HALF_TAN_V2(area, 2, 3), + MEAN_VALUE_HALF_TAN_V2(area, 3, 0), + }; #ifdef __clang__ # pragma clang diagnostic pop @@ -2237,18 +2244,19 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo #undef MEAN_VALUE_HALF_TAN_V2 - w[0] = (t[3] + t[0]) / lens[0]; - w[1] = (t[0] + t[1]) / lens[1]; - w[2] = (t[1] + t[2]) / lens[2]; - w[3] = (t[2] + t[3]) / lens[3]; + w[0] = (t[3] + t[0]) / lens[0]; + w[1] = (t[0] + t[1]) / lens[1]; + w[2] = (t[1] + t[2]) / lens[2]; + w[3] = (t[2] + t[3]) / lens[3]; - wtot = w[0] + w[1] + w[2] + w[3]; + wtot = w[0] + w[1] + w[2] + w[3]; - if (wtot != 0.0f) { - mul_v4_fl(w, 1.0f / wtot); - } - else { /* dummy values for zero area face */ - copy_v4_fl(w, 1.0f / 4.0f); + if (wtot != 0.0f) { + mul_v4_fl(w, 1.0f / wtot); + } + else { /* dummy values for zero area face */ + copy_v4_fl(w, 1.0f / 4.0f); + } } } |