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

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to