[Bf-blender-cvs] [6177d9f0c89] blender-v3.3-release: Fix: reverse uv lookup fails due to floating point accuracy issues

Jacques Lucke noreply at git.blender.org
Wed Aug 31 10:28:44 CEST 2022


Commit: 6177d9f0c8981837491f5153e3aab4ec0d04db44
Author: Jacques Lucke
Date:   Wed Aug 31 10:28:35 2022 +0200
Branches: blender-v3.3-release
https://developer.blender.org/rB6177d9f0c8981837491f5153e3aab4ec0d04db44

Fix: reverse uv lookup fails due to floating point accuracy issues

The case when the query uv is almost on an edge but outside of any
triangle was handled before. Now the case where the query uv is
almost on an edge but inside more than one triangle is handled as well.

===================================================================

M	source/blender/geometry/intern/reverse_uv_sampler.cc

===================================================================

diff --git a/source/blender/geometry/intern/reverse_uv_sampler.cc b/source/blender/geometry/intern/reverse_uv_sampler.cc
index 39fec40333c..f66e4a3ac2e 100644
--- a/source/blender/geometry/intern/reverse_uv_sampler.cc
+++ b/source/blender/geometry/intern/reverse_uv_sampler.cc
@@ -50,6 +50,11 @@ ReverseUVSampler::Result ReverseUVSampler::sample(const float2 &query_uv) const
   float3 best_bary_weights;
   const MLoopTri *best_looptri;
 
+  /* The distance to an edge that is allowed to be inside or outside the triangle. Without this,
+   * the lookup can fail for floating point accuracy reasons when the uv is almost exact on an
+   * edge. */
+  const float edge_epsilon = 0.00001f;
+
   for (const int looptri_index : looptri_indices) {
     const MLoopTri &looptri = looptris_[looptri_index];
     const float2 &uv_0 = uv_map_[looptri.tri[0]];
@@ -68,8 +73,12 @@ ReverseUVSampler::Result ReverseUVSampler::sample(const float2 &query_uv) const
     const float dist = MAX3(x_dist, y_dist, z_dist);
 
     if (dist <= 0.0f && best_dist <= 0.0f) {
-      /* The uv sample is in multiple triangles. */
-      return Result{ResultType::Multiple};
+      const float worse_dist = std::max(dist, best_dist);
+      /* Allow ignoring multiple triangle intersections if the uv is almost exactly on an edge. */
+      if (worse_dist < -edge_epsilon) {
+        /* The uv sample is in multiple triangles. */
+        return Result{ResultType::Multiple};
+      }
     }
 
     if (dist < best_dist) {
@@ -79,8 +88,9 @@ ReverseUVSampler::Result ReverseUVSampler::sample(const float2 &query_uv) const
     }
   }
 
-  /* Allow for a small epsilon in case the uv is on th edge. */
-  if (best_dist < 0.00001f) {
+  /* Allow using the closest (but not intersecting) triangle if the uv is almost exactly on an
+   * edge. */
+  if (best_dist < edge_epsilon) {
     return Result{ResultType::Ok, best_looptri, math::clamp(best_bary_weights, 0.0f, 1.0f)};
   }



More information about the Bf-blender-cvs mailing list