[Bf-blender-cvs] [7820729053e] temp-T97352-3d-texturing-seam-bleeding-b2: Support for seam fixing with UDIM tiles.

Jeroen Bakker noreply at git.blender.org
Fri Jul 8 15:24:49 CEST 2022


Commit: 7820729053e974ddf78fb22a67e69a6490cbcde5
Author: Jeroen Bakker
Date:   Fri Jul 8 15:21:29 2022 +0200
Branches: temp-T97352-3d-texturing-seam-bleeding-b2
https://developer.blender.org/rB7820729053e974ddf78fb22a67e69a6490cbcde5

Support for seam fixing with UDIM tiles.

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

M	source/blender/blenkernel/BKE_uv_islands.hh
M	source/blender/blenkernel/intern/pbvh_pixels.cc
M	source/blender/blenkernel/intern/uv_islands.cc

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

diff --git a/source/blender/blenkernel/BKE_uv_islands.hh b/source/blender/blenkernel/BKE_uv_islands.hh
index 3b266a7870a..38e2f0523fa 100644
--- a/source/blender/blenkernel/BKE_uv_islands.hh
+++ b/source/blender/blenkernel/BKE_uv_islands.hh
@@ -943,20 +943,67 @@ struct UVIslands {
 /* Bitmask containing the num of the nearest Island. */
 // TODO: this is a really quick implementation.
 struct UVIslandsMask {
-  float2 udim_offset;
-  ushort2 resolution;
-  Array<uint16_t> mask;
 
-  UVIslandsMask(float2 udim_offset, ushort2 resolution)
-      : udim_offset(udim_offset), resolution(resolution), mask(resolution.x * resolution.y)
-  {
-    clear();
-  }
+  struct Tile {
+    float2 udim_offset;
+    ushort2 resolution;
+    Array<uint16_t> mask;
+
+    Tile(float2 udim_offset, ushort2 resolution)
+        : udim_offset(udim_offset), resolution(resolution), mask(resolution.x * resolution.y)
+    {
+      clear();
+    }
+
+    void clear()
+    {
+      mask.fill(0xffff);
+    }
+
+    void add(short island_index, const UVIsland &island)
+    {
+      for (const VectorList<UVPrimitive>::UsedVector &uv_primitives : island.uv_primitives)
+        for (const UVPrimitive &uv_primitive : 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 + udim_offset,
+                                     weights);
+              if (!barycentric_inside_triangle_v2(weights)) {
+                continue;
+              }
+
+              uint64_t offset = resolution.x * y + x;
+              mask[offset] = island_index;
+            }
+          }
+        }
+    }
+    bool is_masked(const uint16_t island_index, const float2 uv) const;
+  };
+
+  Vector<Tile> tiles;
 
-  void clear()
+  void add_tile(float2 udim_offset, ushort2 resolution)
   {
-    mask.fill(0xffff);
+    tiles.append_as(Tile(udim_offset, resolution));
   }
+
   /**
    * Is the given uv coordinate part of the given island_index mask.
    *
@@ -967,44 +1014,11 @@ struct UVIslandsMask {
 
   void add(const UVIslands &islands)
   {
-    for (int index = 0; index < islands.islands.size(); index++) {
-      add(index, islands.islands[index]);
-    }
-  }
-
-  void add(short island_index, const UVIsland &island)
-  {
-    for (const VectorList<UVPrimitive>::UsedVector &uv_primitives : island.uv_primitives)
-      for (const UVPrimitive &uv_primitive : 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;
-            }
-
-            uint64_t offset = resolution.x * y + x;
-            mask[offset] = island_index;
-          }
-        }
+    for (Tile &tile : tiles) {
+      for (int index = 0; index < islands.islands.size(); index++) {
+        tile.add(index, islands.islands[index]);
       }
+    }
   }
 
   void dilate(int max_iterations);
diff --git a/source/blender/blenkernel/intern/pbvh_pixels.cc b/source/blender/blenkernel/intern/pbvh_pixels.cc
index cf51b595746..6caba4f8c79 100644
--- a/source/blender/blenkernel/intern/pbvh_pixels.cc
+++ b/source/blender/blenkernel/intern/pbvh_pixels.cc
@@ -61,6 +61,7 @@ static void extract_barycentric_pixels(UDIMTilePixels &tile_data,
                                        const int64_t uv_island_index,
                                        const int64_t uv_primitive_index,
                                        const float2 uvs[3],
+                                       const float2 tile_offset,
                                        const int minx,
                                        const int miny,
                                        const int maxx,
@@ -79,7 +80,7 @@ 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);
-      const bool is_masked = uv_mask.is_masked(uv_island_index, uv);
+      const bool is_masked = uv_mask.is_masked(uv_island_index, uv + tile_offset);
       if (!start_detected && is_inside && is_masked) {
         start_detected = true;
         pixel_row.start_image_coordinate = ushort2(x, y);
@@ -210,6 +211,7 @@ static void do_encode_pixels(void *__restrict userdata,
                                    entry.uv_island_index,
                                    uv_prim_index,
                                    uvs,
+                                   tile_offset,
                                    minx,
                                    miny,
                                    maxx,
@@ -365,7 +367,12 @@ static void update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image
   // TODO: Currently uv_masks only supports a single udim tile. We should create one for each tile.
   // TODO: mask resolution should be based on the actual resolution of the image buffer (or a
   // factor of it).
-  uv_islands::UVIslandsMask uv_masks(float2(0.0, 0.0), ushort2(256, 256));
+  uv_islands::UVIslandsMask uv_masks;
+  LISTBASE_FOREACH (ImageTile *, tile_data, &image->tiles) {
+    image::ImageTileWrapper image_tile(tile_data);
+    uv_masks.add_tile(float2(image_tile.get_tile_x_offset(), image_tile.get_tile_y_offset()),
+                      ushort2(256, 256));
+  }
   uv_masks.add(islands);
   uv_masks.dilate(image->seamfix_iter);
 
diff --git a/source/blender/blenkernel/intern/uv_islands.cc b/source/blender/blenkernel/intern/uv_islands.cc
index ec8bd3e0db8..a5b6ab947d5 100644
--- a/source/blender/blenkernel/intern/uv_islands.cc
+++ b/source/blender/blenkernel/intern/uv_islands.cc
@@ -719,7 +719,7 @@ UVBorder UVPrimitive::extract_border() const
 /** \name UVIslandsMask
  * \{ */
 
-static bool dilate_x(UVIslandsMask &islands_mask)
+static bool dilate_x(UVIslandsMask::Tile &islands_mask)
 {
   bool changed = false;
   const Array<uint16_t> prev_mask = islands_mask.mask;
@@ -742,7 +742,7 @@ static bool dilate_x(UVIslandsMask &islands_mask)
   return changed;
 }
 
-static bool dilate_y(UVIslandsMask &islands_mask)
+static bool dilate_y(UVIslandsMask::Tile &islands_mask)
 {
   bool changed = false;
   const Array<uint16_t> prev_mask = islands_mask.mask;
@@ -766,33 +766,27 @@ static bool dilate_y(UVIslandsMask &islands_mask)
   return changed;
 }
 
-void UVIslandsMask::dilate(int max_iterations)
+static void dilate_tile(UVIslandsMask::Tile &tile, int max_iterations)
 {
-#ifdef DEBUG_SVG
-  std::ofstream of;
-  of.open("/tmp/dilate.svg");
-  svg_header(of);
-#endif
-
   int index = 0;
   while (index < max_iterations) {
-    bool changed = dilate_x(*this);
-    changed |= dilate_y(*this);
+    bool changed = dilate_x(tile);
+    changed |= dilate_y(tile);
     if (!changed) {
       break;
     }
-#ifdef DEBUG_SVG
-    svg(of, *this, index);
-#endif
     index++;
   }
-#ifdef DEBUG_SVG
-  svg_footer(of);
-  of.close();
-#endif
 }
 
-bool UVIslandsMask::is_masked(const short island_index, const float2 uv) const
+void UVIslandsMask::dilate(int max_iterations)
+{
+  for (Tile &tile : tiles) {
+    dilate_tile(tile, max_iterations);
+  }
+}
+
+bool UVIslandsMask::Tile::is_masked(const uint16_t island_index, const float2 uv) const
 {
   float2 local_uv = uv - udim_offset;
   if (local_uv.x < 0.0f || local_uv.y < 0.0f || local_uv.x >= 1.0f || local_uv.y >= 1.0f) {
@@ -804,6 +798,17 @@ bool UVIslandsMask::is_masked(const short island_index, const float2 uv) const
   return mask[offset] == island_index;
 }
 
+bool UVIslandsMask::is_masked(const short island_index, const float2 uv) const
+{
+  // TODO: should find tile containing the uv coords not going over all of them.
+  for (const Tile &tile : tiles) {
+    if (tile.is_masked(island_index, uv)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 /** \} */
 
 #ifdef DEBUG_SVG



More information about the Bf-blender-cvs mailing list