[Bf-blender-cvs] [94463e66fd3] temp-T101739-fix-seam-bleeding-non-manifold: Improve mix factor calculation.

Jeroen Bakker noreply at git.blender.org
Fri Jan 13 11:36:44 CET 2023


Commit: 94463e66fd3aa3f3011540a30117c5a299ba663b
Author: Jeroen Bakker
Date:   Fri Jan 13 10:52:06 2023 +0100
Branches: temp-T101739-fix-seam-bleeding-non-manifold
https://developer.blender.org/rB94463e66fd3aa3f3011540a30117c5a299ba663b

Improve mix factor calculation.

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

M	source/blender/blenkernel/intern/pbvh_pixels_copy.cc

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

diff --git a/source/blender/blenkernel/intern/pbvh_pixels_copy.cc b/source/blender/blenkernel/intern/pbvh_pixels_copy.cc
index 297d6f0123e..1fc553097f2 100644
--- a/source/blender/blenkernel/intern/pbvh_pixels_copy.cc
+++ b/source/blender/blenkernel/intern/pbvh_pixels_copy.cc
@@ -233,6 +233,13 @@ struct Rows {
       PixelType type = PixelType::Undecided;
       float distance = std::numeric_limits<float>::max();
       CopyPixelCommand copy_command;
+      /**
+       * Index of the edge in the list of non-manifold edges.
+       *
+       * The edge is kept to calculate athe mix factor between the two pixels that have chosen to
+       * be mixed.
+       */
+      int64_t edge_index = -1;
 
       Pixel() = default;
 
@@ -260,7 +267,10 @@ struct Rows {
       }
     }
 
-    void mask_brush_pixels(const PixelNodesTileData &nodes_tile_pixels)
+    /**
+     * Mark pixels that are painted on by the brush. Those pixels don't need to be updated.
+     */
+    void mark_pixels_effected_by_brush(const PixelNodesTileData &nodes_tile_pixels)
     {
       for (const UDIMTilePixels &tile_pixels : nodes_tile_pixels) {
         for (const PackedPixelRow &encoded_pixels : tile_pixels.pixel_rows) {
@@ -277,9 +287,14 @@ struct Rows {
       }
     }
 
+    /**
+     * Mark pixels that needs to be evaluated. Pixels that are marked will have its `edge_index`
+     * filled.
+     */
     void mark_for_evaluation(const Rows &rows, const NonManifoldTileEdges &tile_edges)
     {
-      for (const Edge<CoordSpace::Tile> &tile_edge : tile_edges) {
+      for (int tile_edge_index : tile_edges.index_range()) {
+        const Edge<CoordSpace::Tile> &tile_edge = tile_edges[tile_edge_index];
         rcti edge_bounds = get_bounds(tile_edge);
         add_margin(edge_bounds, rows.margin);
         clamp(edge_bounds, rows.resolution);
@@ -293,9 +308,12 @@ struct Rows {
 
         for (const int x : IndexRange(edge_bounds.xmin, BLI_rcti_size_x(&edge_bounds))) {
           Pixel &pixel = pixels[x];
-          if (pixel.type != PixelType::Undecided) {
+          if (pixel.type == PixelType::Brush) {
             continue;
           }
+          BLI_assert_msg(pixel.type != PixelType::CopyFromClosestEdge,
+                         "PixelType::CopyFromClosestEdge isn't allowed to be set as it is set "
+                         "when finding the pixels to copy.");
 
           const float2 point(pixel.copy_command.destination);
           float2 closest_edge_point;
@@ -304,13 +322,25 @@ struct Rows {
                                      tile_edge.vertex_1.coordinate,
                                      tile_edge.vertex_2.coordinate);
           float distance_to_edge = blender::math::distance(closest_edge_point, point);
-          if (distance_to_edge < rows.margin) {
+          if (distance_to_edge < rows.margin && distance_to_edge < pixel.distance) {
             pixel.type = PixelType::Selected;
+            pixel.distance = distance_to_edge;
+            pixel.edge_index = tile_edge_index;
           }
         }
       }
     }
 
+    /**
+     * Look for a second source pixel that will be blended with the first source pixel to improve
+     * the quality of the fix.
+     *
+     * - The second source pixel must be a neighbour pixel of the first source, or the same as the
+     *   first source when no second pixel could be found.
+     * - The second source pixel must be a pixel that is painted on by the brush.
+     * - The second source pixel must be the second closest pixel , or the first source
+     *   when no second pixel could be found.
+     */
     int2 find_second_source(Rows &rows, int2 destination, int2 first_source)
     {
       rcti search_bounds;
@@ -344,15 +374,32 @@ struct Rows {
       return found_source;
     }
 
-    float determine_mix_factor(int2 destination, int2 source_1, int2 source_2)
+    float determine_mix_factor(const int2 destination,
+                               const int2 source_1,
+                               const int2 source_2,
+                               const Edge<CoordSpace::Tile> &edge)
     {
+      /* Use stable result when both sources are the same. */
       if (source_1 == source_2) {
         return 0.0f;
       }
-      return dist_to_line_segment_v2(float2(destination), float2(source_1), float2(source_2));
+
+      float2 clamped_to_edge;
+      float destination_lambda = closest_to_line_v2(clamped_to_edge,
+                                                    float2(destination),
+                                                    edge.vertex_1.coordinate,
+                                                    edge.vertex_2.coordinate);
+      float source_1_lambda = closest_to_line_v2(
+          clamped_to_edge, float2(source_1), edge.vertex_1.coordinate, edge.vertex_2.coordinate);
+      float source_2_lambda = closest_to_line_v2(
+          clamped_to_edge, float2(source_2), edge.vertex_1.coordinate, edge.vertex_2.coordinate);
+
+      return clamp_f((destination_lambda - source_1_lambda) / (source_2_lambda - source_1_lambda),
+                     0.0f,
+                     1.0f);
     }
 
-    void find_copy_source(Rows &rows)
+    void find_copy_source(Rows &rows, const NonManifoldTileEdges &tile_edges)
     {
       for (int x : pixels.index_range()) {
         Pixel &elem = pixels[x];
@@ -365,6 +412,8 @@ struct Rows {
         BLI_rcti_init(&bounds, x, x, row_number, row_number);
         add_margin(bounds, rows.margin);
         clamp(bounds, rows.resolution);
+        // TODO: improvement is to clamp it with the bounds of the edge that is assigned to the
+        // pixel.
 
         float found_distance = std::numeric_limits<float>().max();
         int2 found_source(0);
@@ -392,8 +441,10 @@ struct Rows {
         elem.copy_command.source_1 = found_source;
         elem.copy_command.source_2 = find_second_source(
             rows, elem.copy_command.destination, found_source);
-        elem.copy_command.mix_factor = determine_mix_factor(
-            elem.copy_command.destination, elem.copy_command.source_1, elem.copy_command.source_2);
+        elem.copy_command.mix_factor = determine_mix_factor(elem.copy_command.destination,
+                                                            elem.copy_command.source_1,
+                                                            elem.copy_command.source_2,
+                                                            tile_edges[elem.edge_index]);
       }
     }
 
@@ -475,14 +526,14 @@ struct Rows {
     rows.resize(resolution.y, row_template);
     for (int row_number : rows.index_range()) {
       rows[row_number].reinit(row_number);
-      rows[row_number].mask_brush_pixels(node_tile_pixels);
+      rows[row_number].mark_pixels_effected_by_brush(node_tile_pixels);
     }
   }
 
-  void find_copy_source()
+  void find_copy_source(const NonManifoldTileEdges &tile_edges)
   {
     for (Row &row : rows) {
-      row.find_copy_source(*this);
+      row.find_copy_source(*this, tile_edges);
     }
   }
 
@@ -500,8 +551,8 @@ struct Rows {
     }
     /* Shrink vectors to fit the actual data it contains. From now on these vectors should be
      * immutable. */
-    //copy_tile.groups.resize(copy_tile.groups.size());
-    //copy_tile.command_deltas.resize(copy_tile.command_deltas.size());
+    // copy_tile.groups.resize(copy_tile.groups.size());
+    // copy_tile.command_deltas.resize(copy_tile.command_deltas.size());
   }
 
   void print_debug() const
@@ -553,7 +604,7 @@ void BKE_pbvh_pixels_copy_update(PBVH &pbvh,
 
     Rows rows(tile_resolution, image.seam_margin, nodes_tile_pixels);
     rows.mark_for_evaluation(tile_edges);
-    rows.find_copy_source();
+    rows.find_copy_source(tile_edges);
     rows.pack_into(copy_tile);
     copy_tile.print_compression_rate();
     pbvh_data.tiles_copy_pixels.tiles.append(copy_tile);



More information about the Bf-blender-cvs mailing list