[Bf-blender-cvs] [d9c7e240ed7] temp-T97352-3d-texturing-seam-bleeding-b2: Reduce pixel extraction based on the uv island dilated mask.

Jeroen Bakker noreply at git.blender.org
Fri Jun 17 11:34:00 CEST 2022


Commit: d9c7e240ed74ee1d303ea17149d3419c3de29735
Author: Jeroen Bakker
Date:   Fri Jun 17 11:27:45 2022 +0200
Branches: temp-T97352-3d-texturing-seam-bleeding-b2
https://developer.blender.org/rBd9c7e240ed74ee1d303ea17149d3419c3de29735

Reduce pixel extraction based on the uv island dilated mask.

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

M	source/blender/blenkernel/BKE_uv_islands.hh
M	source/blender/blenkernel/intern/paint_canvas.cc
M	source/blender/blenkernel/intern/pbvh_pixels.cc
M	source/blender/blenkernel/intern/uv_islands.cc
M	source/blender/blenloader/intern/versioning_300.c
M	source/blender/editors/space_image/image_buttons.c
M	source/blender/makesdna/DNA_image_defaults.h
M	source/blender/makesdna/DNA_image_types.h
M	source/blender/makesrna/intern/rna_image.c

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

diff --git a/source/blender/blenkernel/BKE_uv_islands.hh b/source/blender/blenkernel/BKE_uv_islands.hh
index caf18a2b29b..1c6607da15d 100644
--- a/source/blender/blenkernel/BKE_uv_islands.hh
+++ b/source/blender/blenkernel/BKE_uv_islands.hh
@@ -11,6 +11,7 @@
 #include "BLI_float3x3.hh"
 #include "BLI_math.h"
 #include "BLI_math_vec_types.hh"
+#include "BLI_rect.h"
 #include "BLI_vector.hh"
 
 #include "DNA_meshdata_types.h"
@@ -95,6 +96,16 @@ struct MeshPrimitive {
     }
     return nullptr;
   }
+
+  rctf uv_bounds() const
+  {
+    rctf result;
+    BLI_rctf_init_minmax(&result);
+    for (const MeshUVVert &uv_vertex : vertices) {
+      BLI_rctf_do_minmax_v(&result, uv_vertex.uv);
+    }
+    return result;
+  }
 };
 
 /** Wrapper to contain all required mesh data. */
@@ -892,33 +903,39 @@ struct UVIslandsMask {
 
   void add(short island_index, const UVIsland &island)
   {
-    for (const UVEdge &edge : island.uv_edges) {
-      add(island_index, edge);
-    }
-  }
-
-  void add(short island_index, const UVEdge &edge)
-  {
-    float2 p;
-    for (int i = 0; i < 10; i++) {
-      float f = i / 10.0f;
-      interp_v2_v2v2(p, edge.vertices[0]->uv, edge.vertices[1]->uv, f);
-      add(island_index, p);
-    }
-  }
+    for (const UVPrimitive &uv_primitive : island.uv_primitives) {
+      const MeshPrimitive *mesh_primitive = uv_primitive.primitive;
+
+      rctf uv_bounds = mesh_primitive->uv_bounds();
+      rcti buffer_bounds;
+      buffer_bounds.xmin = max_ii(floor((uv_bounds.xmin - udim_offset.x) * resolution.x), 0);
+      buffer_bounds.xmax = min_ii(ceil((uv_bounds.xmax - udim_offset.x) * resolution.x),
+                                  resolution.x - 1);
+      buffer_bounds.ymin = max_ii(floor((uv_bounds.ymin - udim_offset.y) * resolution.y), 0);
+      buffer_bounds.ymax = min_ii(ceil((uv_bounds.ymax - udim_offset.y) * resolution.y),
+                                  resolution.y - 1);
+
+      for (int y = buffer_bounds.ymin; y < buffer_bounds.ymax + 1; y++) {
+        for (int x = buffer_bounds.xmin; x < buffer_bounds.xmax + 1; x++) {
+          float2 uv(float(x) / resolution.x, float(y) / resolution.y);
+          float3 weights;
+          barycentric_weights_v2(mesh_primitive->vertices[0].uv,
+                                 mesh_primitive->vertices[1].uv,
+                                 mesh_primitive->vertices[2].uv,
+                                 uv,
+                                 weights);
+          if (!barycentric_inside_triangle_v2(weights)) {
+            continue;
+          }
 
-  void add(short island_index, const float2 uv)
-  {
-    float2 udim_corrected_uv = uv - udim_offset;
-    ushort2 mask_uv(udim_corrected_uv.x * resolution.x, udim_corrected_uv.y * resolution.y);
-    if (mask_uv.x < 0 || mask_uv.y < 0 || mask_uv.x >= resolution.x || mask_uv.y >= resolution.y) {
-      return;
+          uint64_t offset = resolution.x * y + x;
+          mask[offset] = island_index;
+        }
+      }
     }
-    uint64_t offset = resolution.x * mask_uv.y + mask_uv.x;
-    mask[offset] = island_index;
   }
 
-  void dilate();
+  void dilate(int max_iterations);
 
   void print() const
   {
diff --git a/source/blender/blenkernel/intern/paint_canvas.cc b/source/blender/blenkernel/intern/paint_canvas.cc
index b72418d88c0..497d98dcab3 100644
--- a/source/blender/blenkernel/intern/paint_canvas.cc
+++ b/source/blender/blenkernel/intern/paint_canvas.cc
@@ -113,6 +113,7 @@ char *BKE_paint_canvas_key_get(struct PaintModeSettings *settings, struct Object
   Image *image;
   ImageUser *image_user;
   if (BKE_paint_canvas_image_get(settings, ob, &image, &image_user)) {
+    ss << ",SEAM_DIST:" << image->seamfix_iter;
     ImageUser tile_user = *image_user;
     LISTBASE_FOREACH (ImageTile *, image_tile, &image->tiles) {
       tile_user.tile = image_tile->tile_number;
diff --git a/source/blender/blenkernel/intern/pbvh_pixels.cc b/source/blender/blenkernel/intern/pbvh_pixels.cc
index 3acc49eada3..f613f962522 100644
--- a/source/blender/blenkernel/intern/pbvh_pixels.cc
+++ b/source/blender/blenkernel/intern/pbvh_pixels.cc
@@ -29,25 +29,6 @@ namespace blender::bke::pbvh::pixels {
  */
 constexpr bool USE_WATERTIGHT_CHECK = false;
 
-/* -------------------------------------------------------------------- */
-
-/** \name UV Islands
- * \{ */
-
-/** Build UV islands from PBVH primitives. */
-static uv_islands::UVIslands build_uv_islands(uv_islands::MeshData &mesh_data)
-{
-  uv_islands::UVIslands islands(mesh_data);
-  uv_islands::UVIslandsMask uv_masks(float2(0.0, 0.0), ushort2(256, 256));
-  uv_masks.add(islands);
-  uv_masks.dilate();
-  islands.extract_borders();
-  islands.extend_borders(uv_masks, mesh_data);
-  return islands;
-}
-
-/** \} */
-
 /**
  * Calculate the delta of two neighbor UV coordinates in the given image buffer.
  */
@@ -76,6 +57,8 @@ static float2 calc_barycentric_delta_x(const ImBuf *image_buffer,
 
 static void extract_barycentric_pixels(UDIMTilePixels &tile_data,
                                        const ImBuf *image_buffer,
+                                       const uv_islands::UVIslandsMask &uv_mask,
+                                       const int64_t uv_island_index,
                                        const int64_t uv_primitive_index,
                                        const float2 uvs[3],
                                        const int minx,
@@ -96,12 +79,13 @@ static void extract_barycentric_pixels(UDIMTilePixels &tile_data,
       barycentric_weights_v2(uvs[0], uvs[1], uvs[2], uv, barycentric_weights);
 
       const bool is_inside = barycentric_inside_triangle_v2(barycentric_weights);
-      if (!start_detected && is_inside) {
+      const bool is_masked = uv_mask.is_masked(uv_island_index, uv);
+      if (!start_detected && is_inside && is_masked) {
         start_detected = true;
         pixel_row.start_image_coordinate = ushort2(x, y);
         pixel_row.start_barycentric_coord = float2(barycentric_weights.x, barycentric_weights.y);
       }
-      else if (start_detected && !is_inside) {
+      else if (start_detected && (!is_inside || !is_masked)) {
         break;
       }
     }
@@ -133,6 +117,7 @@ struct EncodePixelsUserData {
   Vector<PBVHNode *> *nodes;
   const MLoopUV *ldata_uv;
   const uv_islands::UVIslands *uv_islands;
+  const uv_islands::UVIslandsMask *uv_masks;
 };
 
 static void do_encode_pixels(void *__restrict userdata,
@@ -144,6 +129,8 @@ static void do_encode_pixels(void *__restrict userdata,
   ImageUser image_user = *data->image_user;
   PBVHNode *node = (*data->nodes)[n];
   NodeData *node_data = static_cast<NodeData *>(node->pixels.node_data);
+  const uv_islands::UVIslandsMask &uv_masks = *data->uv_masks;
+
   LISTBASE_FOREACH (ImageTile *, tile, &data->image->tiles) {
     image::ImageTileWrapper image_tile(tile);
     image_user.tile = image_tile.get_tile_number();
@@ -159,6 +146,7 @@ static void do_encode_pixels(void *__restrict userdata,
     for (int pbvh_node_prim_index = 0; pbvh_node_prim_index < node->totprim;
          pbvh_node_prim_index++) {
       int64_t geom_prim_index = node->prim_indices[pbvh_node_prim_index];
+      int64_t uv_island_index = 0;
       for (const uv_islands::UVIsland &island : data->uv_islands->islands) {
         for (const uv_islands::UVPrimitive &uv_primitive : island.uv_primitives) {
           if (uv_primitive.primitive->index != geom_prim_index) {
@@ -189,9 +177,18 @@ static void do_encode_pixels(void *__restrict userdata,
               image_buffer, uvs, minx, miny);
 
           /* Extract the pixels. */
-          extract_barycentric_pixels(
-              tile_data, image_buffer, uv_prim_index, uvs, minx, miny, maxx, maxy);
+          extract_barycentric_pixels(tile_data,
+                                     image_buffer,
+                                     uv_masks,
+                                     uv_island_index,
+                                     uv_prim_index,
+                                     uvs,
+                                     minx,
+                                     miny,
+                                     maxx,
+                                     maxy);
         }
+        uv_island_index++;
       }
     }
     BKE_image_release_ibuf(image, image_buffer, nullptr);
@@ -335,9 +332,18 @@ static void update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image
   if (ldata_uv == nullptr) {
     return;
   }
+
   uv_islands::MeshData mesh_data(
       pbvh->looptri, pbvh->totprim, pbvh->totvert, pbvh->mloop, ldata_uv);
-  uv_islands::UVIslands islands = build_uv_islands(mesh_data);
+  uv_islands::UVIslands islands(mesh_data);
+
+  // TODO: Currenly uv_masks only supports a single udim tile. We should create one for each tile.
+  uv_islands::UVIslandsMask uv_masks(float2(0.0, 0.0), ushort2(256, 256));
+  uv_masks.add(islands);
+  uv_masks.dilate(image->seamfix_iter);
+
+  islands.extract_borders();
+  islands.extend_borders(uv_masks, mesh_data);
   update_geom_primitives(*pbvh, mesh_data);
 
   EncodePixelsUserData user_data;
@@ -347,6 +353,7 @@ static void update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image
   user_data.ldata_uv = ldata_uv;
   user_data.nodes = &nodes_to_update;
   user_data.uv_islands = &islands;
+  user_data.uv_masks = &uv_masks;
 
   TaskParallelSettings settings;
   BKE_pbvh_parallel_range_settings(&settings, true, nodes_to_update.size());
diff --git a/source/blender/blenkernel/intern/uv_islands.cc b/source/blender/blenkernel/intern/uv_islands.cc
index f03d123fb37..dbe0c546170 100644
--- a/source/blender/blenkernel/intern/uv_islands.cc
+++ b/source/blender/blenkernel/intern/uv_islands.cc
@@ -741,26 +741,27 @@ static bool dilate_y(UVIslandsMask &islands_mask)
   return changed;
 }
 
-void UVIslandsMask::dilate()
+void UVIslandsMask::dilate(int max_iterations)
 {
 #ifdef DEBUG_SVG
   std::ofstream of;
   of.open("/tmp/dilate.svg");
   svg_header(of);
-  int index = 0;
 #endif
-  while (true) {
+
+  int index = 0;
+  while (index < max_iterations) {
     bool changed = dilate_x(*this);
     changed |= dilate_y(*this);
     if (!changed) {
       break;
     }
 #ifdef DEBUG_SVG
-    svg(of, *this, index++);
+    svg(of, *thi

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list