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.

This commit is contained in:
Campbell Barton
2013-09-06 05:44:18 +00:00
parent e045e324a4
commit 6439ae9d51

View File

@@ -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);
}
}
}