[Bf-blender-cvs] [4b281ecd742] temp-T97352-3d-texturing-seam-bleeding: Fix unconnected seams.

Jeroen Bakker noreply at git.blender.org
Wed Apr 20 09:22:29 CEST 2022


Commit: 4b281ecd7428d2a955966a1702c8ec6f5aa64f61
Author: Jeroen Bakker
Date:   Wed Apr 20 09:20:47 2022 +0200
Branches: temp-T97352-3d-texturing-seam-bleeding
https://developer.blender.org/rB4b281ecd7428d2a955966a1702c8ec6f5aa64f61

Fix unconnected seams.

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

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

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

diff --git a/source/blender/blenkernel/intern/pbvh_pixels_seams.cc b/source/blender/blenkernel/intern/pbvh_pixels_seams.cc
index 8d44cb33358..b1a8857cf74 100644
--- a/source/blender/blenkernel/intern/pbvh_pixels_seams.cc
+++ b/source/blender/blenkernel/intern/pbvh_pixels_seams.cc
@@ -180,12 +180,39 @@ Bitmaps create_tile_bitmap(const PBVH &pbvh, Image &image, ImageUser &image_user
   return result;
 }
 
-int2 find_source_pixel()
+int2 find_source_pixel(Bitmap &bitmap, float2 near_image_coord)
 {
-  return int2(50, 50);
+  // TODO: Should we take lambda into account?
+  const int SEARCH_RADIUS = 2;
+  float min_distance = FLT_MAX;
+  int2 result(0, 0);
+  int2 image_coord(int(near_image_coord.x), int(near_image_coord.y));
+  for (int v = image_coord.y - SEARCH_RADIUS; v <= image_coord.y + SEARCH_RADIUS; v++) {
+    for (int u = image_coord.x - SEARCH_RADIUS; u <= image_coord.x + SEARCH_RADIUS; u++) {
+      if (u < 0 || u > bitmap.resolution.x || v < 0 || v > bitmap.resolution.y) {
+        /** Pixel not part of this tile. */
+        continue;
+      }
+
+      int2 uv(u, v);
+      const PixelInfo &pixel_info = bitmap.get_pixel_info(uv);
+      if (!pixel_info.is_extracted()) {
+        continue;
+      }
+
+      float distance = len_v2v2_int(uv, image_coord);
+      if (distance < min_distance) {
+        result = uv;
+        min_distance = distance;
+      }
+    }
+  }
+
+  return result;
 }
 
-static void BKE_pbvh_pixels_clear_seams(PBVH *pbvh)
+/** Clears all existing seam fixes in the given PBVH. */
+static void pbvh_pixels_clear_seams(PBVH *pbvh)
 {
   for (int n = 0; n < pbvh->totnode; n++) {
     PBVHNode &node = pbvh->nodes[n];
@@ -208,6 +235,57 @@ static void add_seam_fix(PBVHNode &node,
   seam_fixes.pixels.append(SeamFix{src_pixel, dst_pixel});
 }
 
+static void fix_unconnected_seam(
+    PBVH &pbvh, Bitmap &bitmap, const rcti &uvbounds, const MLoopUV &luv_1, const MLoopUV &luv_2)
+{
+  for (int v = uvbounds.ymin; v <= uvbounds.ymax; v++) {
+    for (int u = uvbounds.xmin; u <= uvbounds.xmax; u++) {
+      if (u < 0 || u > bitmap.resolution[0] || v < 0 || v > bitmap.resolution[1]) {
+        /** Pixel not part of this tile. */
+        continue;
+      }
+      int pixel_offset = v * bitmap.resolution[0] + u;
+      PixelInfo &pixel_info = bitmap.bitmap[pixel_offset];
+      if (pixel_info.is_extracted() || pixel_info.is_seam_fix()) {
+        /* Skip this pixel as it already has a solution. */
+        continue;
+      }
+
+      // What is the distance to the edge.
+      float2 uv(float(u) / bitmap.resolution[0], float(v) / bitmap.resolution[1]);
+      float2 closest_point;
+      // TODO: Should we use lambda to reduce artifacts?
+      closest_to_line_v2(closest_point, uv, luv_1.uv, luv_2.uv);
+
+      /* Calculate the distance in pixel space. */
+      float2 uv_coord(u, v);
+      float2 closest_coord(closest_point.x * bitmap.resolution.x,
+                           closest_point.y * bitmap.resolution.y);
+      float distance_to_edge = len_v2v2(uv_coord, closest_coord);
+      if (distance_to_edge > 2.5f) {
+        continue;
+      }
+
+      int2 source_pixel = find_source_pixel(bitmap, closest_coord);
+      int2 destination_pixel(u, v);
+
+      PixelInfo src_pixel_info = bitmap.get_pixel_info(source_pixel);
+      if (!src_pixel_info.is_extracted()) {
+        continue;
+      }
+      int src_node = src_pixel_info.get_node_index();
+
+      PBVHNode &node = pbvh.nodes[src_node];
+      add_seam_fix(node,
+                   bitmap.image_tile.get_tile_number(),
+                   source_pixel,
+                   bitmap.image_tile.get_tile_number(),
+                   destination_pixel);
+      bitmap.mark_seam_fix(destination_pixel);
+    }
+  }
+}
+
 void BKE_pbvh_pixels_rebuild_seams(
     PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image_user, int cd_loop_uv_offset)
 {
@@ -222,12 +300,11 @@ void BKE_pbvh_pixels_rebuild_seams(
   from_mesh_params.calc_vert_normal = false;
   BM_mesh_bm_from_me(bm, mesh, &from_mesh_params);
 
-  BKE_pbvh_pixels_clear_seams(pbvh);
+  pbvh_pixels_clear_seams(pbvh);
 
   // find seams.
   // for each edge
   Vector<BMLoopPair> pairs = find_connected_loops(bm, cd_loop_uv_offset);
-  printf("found %lld pairs\n", pairs.size());
 
   // Make a bitmap per tile indicating pixels that have already been assigned to a PBVHNode.
   Bitmaps bitmaps = create_tile_bitmap(*pbvh, *image, *image_user);
@@ -263,50 +340,7 @@ void BKE_pbvh_pixels_rebuild_seams(
         continue;
       }
       else {
-
-        for (int v = uvbounds_i.ymin; v <= uvbounds_i.ymax; v++) {
-          for (int u = uvbounds_i.xmin; u <= uvbounds_i.xmax; u++) {
-            if (u < 0 || u > bitmap.resolution[0] || v < 0 || v > bitmap.resolution[1]) {
-              /** Pixel not part of this tile. */
-              continue;
-            }
-            int pixel_offset = v * bitmap.resolution[0] + u;
-            PixelInfo &pixel_info = bitmap.bitmap[pixel_offset];
-            if (pixel_info.is_extracted() || pixel_info.is_seam_fix()) {
-              /* Skip this pixel as it already has a solution. */
-              continue;
-            }
-
-            // What is the distance to the edge.
-            float2 uv(float(u) / bitmap.resolution[0], float(v) / bitmap.resolution[1]);
-            float2 closest_point;
-            float lambda = closest_to_line_v2(closest_point, uv, luv_1->uv, luv_2->uv);
-
-            /* Calcualte the distance in pixel space. */
-            float2 uv_coord(u, v);
-            float2 closest_coord(closest_point.x * bitmap.resolution.x,
-                                 closest_point.y * bitmap.resolution.y);
-            float distance_to_edge = len_v2v2(uv_coord, closest_coord);
-            if (distance_to_edge > 2.5f) {
-              continue;
-            }
-
-            int2 source_pixel = find_source_pixel();
-            int2 destination_pixel(u, v);
-
-            PixelInfo src_pixel_info = bitmap.get_pixel_info(source_pixel);
-            BLI_assert(src_pixel_info.is_extracted());
-            int src_node = src_pixel_info.get_node_index();
-
-            PBVHNode &node = pbvh->nodes[src_node];
-            add_seam_fix(node,
-                         bitmap.image_tile.get_tile_number(),
-                         source_pixel,
-                         bitmap.image_tile.get_tile_number(),
-                         destination_pixel);
-            bitmap.mark_seam_fix(destination_pixel);
-          }
-        }
+        fix_unconnected_seam(*pbvh, bitmap, uvbounds_i, *luv_1, *luv_2);
       }
     }
   }
@@ -321,22 +355,34 @@ void BKE_pbvh_pixels_fix_seams(PBVHNode *node, Image *image, ImageUser *image_us
 
   for (UDIMSeamFixes &fixes : node_data.seams) {
     iuser.tile = fixes.dst_tile_number;
-    ImBuf *image_buffer = BKE_image_acquire_ibuf(image, &iuser, nullptr);
-    if (image_buffer == nullptr) {
+    ImBuf *dst_image_buffer = BKE_image_acquire_ibuf(image, &iuser, nullptr);
+    if (dst_image_buffer == nullptr) {
+      continue;
+    }
+
+    iuser.tile = fixes.src_tile_number;
+    ImBuf *src_image_buffer = BKE_image_acquire_ibuf(image, &iuser, nullptr);
+    if (src_image_buffer == nullptr) {
       continue;
     }
 
     for (SeamFix &fix : fixes.pixels) {
-      int src_offset = fix.src_pixel.y * image_buffer->x + fix.src_pixel.x;
-      int dst_offset = fix.dst_pixel.y * image_buffer->x + fix.dst_pixel.x;
-      if (image_buffer->rect_float != nullptr) {
-        copy_v4_fl4(&image_buffer->rect_float[dst_offset * 4], 1.0, 0.0, 0.0, 1.0);
+      int src_offset = fix.src_pixel.y * src_image_buffer->x + fix.src_pixel.x;
+      int dst_offset = fix.dst_pixel.y * dst_image_buffer->x + fix.dst_pixel.x;
+      if (src_image_buffer->rect_float != nullptr && dst_image_buffer->rect_float != nullptr) {
+        copy_v4_v4(&dst_image_buffer->rect_float[dst_offset * 4],
+                   &src_image_buffer->rect_float[src_offset * 4]);
+      }
+      else if (src_image_buffer->rect != nullptr && dst_image_buffer->rect != nullptr) {
+        dst_image_buffer->rect_float[dst_offset] = src_image_buffer->rect_float[src_offset];
       }
     }
+
     /* TODO: should be narrowed to the part of the image that needs to be updated. Requires
-     * access to the image tile.*/
+     * access to the image tile. */
     BKE_image_partial_update_mark_full_update(image);
-    BKE_image_release_ibuf(image, image_buffer, nullptr);
+    BKE_image_release_ibuf(image, src_image_buffer, nullptr);
+    BKE_image_release_ibuf(image, dst_image_buffer, nullptr);
   }
 }



More information about the Bf-blender-cvs mailing list