Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGermano Cavalcante <germano.costa@ig.com.br>2020-07-28 15:29:38 +0300
committerGermano Cavalcante <germano.costa@ig.com.br>2020-07-28 15:53:07 +0300
commit47b82fc02fb41b3d51784e0b571ad584eb468ea0 (patch)
treeefba763a33f0f9ba1f64c3997183ac15114c3d7b
parentb99358315e5a16ec0b0ebbd5c37f9a38aaae04b9 (diff)
Fix precision issues in 'interp_weights_poly_v2'
These precision issues were evident in corrected uvs when the option `"Correct Face Attributes"` is enabled.
-rw-r--r--source/blender/blenlib/BLI_math_vector.h3
-rw-r--r--source/blender/blenlib/intern/math_geom.c45
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c16
3 files changed, 46 insertions, 18 deletions
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index d46c02a961c..362ab3769a0 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -133,6 +133,7 @@ MINLINE void sub_v3_v3v3_db(double r[3], const double a[3], const double b[3]);
MINLINE void sub_v4_v4(float r[4], const float a[4]);
MINLINE void sub_v4_v4v4(float r[4], const float a[4], const float b[4]);
+MINLINE void sub_v2db_v2fl_v2fl(double r[2], const float a[2], const float b[2]);
MINLINE void sub_v3db_v3fl_v3fl(double r[3], const float a[3], const float b[3]);
MINLINE void mul_v2_fl(float r[2], float f);
@@ -205,6 +206,7 @@ MINLINE double dot_v3db_v3fl(const double a[3], const float b[3]) ATTR_WARN_UNUS
MINLINE double dot_v3v3_db(const double a[3], const double b[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float cross_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE double cross_v2v2_db(const double a[2], const double b[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3]);
MINLINE void cross_v3_v3v3_hi_prec(float r[3], const float a[3], const float b[3]);
MINLINE void cross_v3_v3v3_db(double r[3], const double a[3], const double b[3]);
@@ -221,6 +223,7 @@ MINLINE float len_manhattan_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE int len_manhattan_v2_int(const int v[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE float len_manhattan_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float len_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE double len_v2_db(const double v[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE double len_v2v2_db(const double a[2], const double b[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE float len_v2v2_int(const int v1[2], const int v2[2]);
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index ecdf108d00e..937bf8b1ae6 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -4176,8 +4176,8 @@ int interp_sparse_array(float *array, const int list_size, const float skipval)
#define DIR_V2_SET(d_len, va, vb) \
{ \
- sub_v2_v2v2((d_len)->dir, va, vb); \
- (d_len)->len = len_v2((d_len)->dir); \
+ sub_v2db_v2fl_v2fl((d_len)->dir, va, vb); \
+ (d_len)->len = len_v2_db((d_len)->dir); \
} \
(void)0
@@ -4185,8 +4185,8 @@ struct Float3_Len {
float dir[3], len;
};
-struct Float2_Len {
- float dir[2], len;
+struct Double2_Len {
+ double dir[2], len;
};
/* Mean value weights - smooth interpolation weights for polygons with
@@ -4209,21 +4209,30 @@ static float mean_value_half_tan_v3(const struct Float3_Len *d_curr,
return 0.0f;
}
-static float mean_value_half_tan_v2(const struct Float2_Len *d_curr,
- const struct Float2_Len *d_next)
+/**
+ * Mean value weights - same as #mean_value_half_tan_v3 but for 2D vectors.
+ *
+ * \note When interpolating a 2D polygon, a point can be considered "outside"
+ * the polygon's bounds. Thus, when the point is very distant and the vectors
+ * have relatively close values, the precision problems are evident since they
+ * do not indicate a point "inside" the polygon.
+ * To resolve this, doubles are used.
+ */
+static double mean_value_half_tan_v2_db(const struct Double2_Len *d_curr,
+ const struct Double2_Len *d_next)
{
- /* different from the 3d version but still correct */
- const float area = cross_v2v2(d_curr->dir, d_next->dir);
+ /* Different from the 3d version but still correct. */
+ const double area = cross_v2v2_db(d_curr->dir, d_next->dir);
/* Compare against zero since 'FLT_EPSILON' can be too large, see: T73348. */
- if (LIKELY(area != 0.0f)) {
- const float dot = dot_v2v2(d_curr->dir, d_next->dir);
- const float len = d_curr->len * d_next->len;
- const float result = (len - dot) / area;
+ if (LIKELY(area != 0.0)) {
+ const double dot = dot_v2v2_db(d_curr->dir, d_next->dir);
+ const double len = d_curr->len * d_next->len;
+ const double result = (len - dot) / area;
if (isfinite(result)) {
return result;
}
}
- return 0.0f;
+ return 0.0;
}
void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[3])
@@ -4328,11 +4337,11 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[
const float eps_sq = eps * eps;
const float *v_curr, *v_next;
- float ht_prev, ht; /* half tangents */
+ double ht_prev, ht; /* half tangents */
float totweight = 0.0f;
int i_curr, i_next;
char ix_flag = 0;
- struct Float2_Len d_curr, d_next;
+ struct Double2_Len d_curr, d_next;
/* loop over 'i_next' */
i_curr = n - 1;
@@ -4343,7 +4352,7 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[
DIR_V2_SET(&d_curr, v_curr - 2 /* v[n - 2] */, co);
DIR_V2_SET(&d_next, v_curr /* v[n - 1] */, co);
- ht_prev = mean_value_half_tan_v2(&d_curr, &d_next);
+ ht_prev = mean_value_half_tan_v2_db(&d_curr, &d_next);
while (i_next < n) {
/* Mark Mayer et al algorithm that is used here does not operate well if vertex is close
@@ -4362,8 +4371,8 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[
d_curr = d_next;
DIR_V2_SET(&d_next, v_next, co);
- ht = mean_value_half_tan_v2(&d_curr, &d_next);
- w[i_curr] = (ht_prev + ht) / d_curr.len;
+ ht = mean_value_half_tan_v2_db(&d_curr, &d_next);
+ w[i_curr] = (float)((ht_prev + ht) / d_curr.len);
totweight += w[i_curr];
/* step */
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index ca405907bdd..1b47832589e 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -509,6 +509,12 @@ MINLINE void sub_v3_v3v3_db(double r[3], const double a[3], const double b[3])
r[2] = a[2] - b[2];
}
+MINLINE void sub_v2db_v2fl_v2fl(double r[2], const float a[2], const float b[2])
+{
+ r[0] = (double)a[0] - (double)b[0];
+ r[1] = (double)a[1] - (double)b[1];
+}
+
MINLINE void sub_v3db_v3fl_v3fl(double r[3], const float a[3], const float b[3])
{
r[0] = (double)a[0] - (double)b[0];
@@ -917,6 +923,11 @@ MINLINE float cross_v2v2(const float a[2], const float b[2])
return a[0] * b[1] - a[1] * b[0];
}
+MINLINE double cross_v2v2_db(const double a[2], const double b[2])
+{
+ return a[0] * b[1] - a[1] * b[0];
+}
+
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
{
BLI_assert(r != a && r != b);
@@ -997,6 +1008,11 @@ MINLINE float len_v2(const float v[2])
return sqrtf(v[0] * v[0] + v[1] * v[1]);
}
+MINLINE double len_v2_db(const double v[2])
+{
+ return sqrt(v[0] * v[0] + v[1] * v[1]);
+}
+
MINLINE float len_v2v2(const float v1[2], const float v2[2])
{
float x, y;