[Bf-blender-cvs] [998d5415683] temp-T97352-3d-texturing-seam-bleeding: connected edges.

Jeroen Bakker noreply at git.blender.org
Wed Apr 20 13:23:57 CEST 2022


Commit: 998d541568354c7de2ab38d76ce7f5e9d8f145a7
Author: Jeroen Bakker
Date:   Wed Apr 20 13:23:47 2022 +0200
Branches: temp-T97352-3d-texturing-seam-bleeding
https://developer.blender.org/rB998d541568354c7de2ab38d76ce7f5e9d8f145a7

connected edges.

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

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 d70bdd0767b..b35663dd283 100644
--- a/source/blender/blenkernel/intern/pbvh_pixels_seams.cc
+++ b/source/blender/blenkernel/intern/pbvh_pixels_seams.cc
@@ -184,14 +184,14 @@ Bitmaps create_tile_bitmap(const PBVH &pbvh, Image &image, ImageUser &image_user
 
 int2 find_source_pixel(Bitmap &bitmap, float2 near_image_coord)
 {
-  // TODO: Should we take lambda into account?
+  // TODO: We should 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) {
+      if (u < 0 || u >= bitmap.resolution.x || v < 0 || v >= bitmap.resolution.y) {
         /** Pixel not part of this tile. */
         continue;
       }
@@ -237,12 +237,23 @@ 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)
+/* -------------------------------------------------------------------- */
+
+/** \name Build fixes for connected edges.
+ * \{ */
+
+static void build_fixes(PBVH &pbvh,
+                        Bitmap &bitmap,
+                        const rcti &uvbounds,
+                        const MLoopUV &luv_a_1,
+                        const MLoopUV &luv_a_2,
+                        const MLoopUV &luv_b_1,
+                        const MLoopUV &luv_b_2,
+                        const float scale_factor)
 {
   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]) {
+      if (u < 0 || u >= bitmap.resolution[0] || v < 0 || v >= bitmap.resolution[1]) {
         /** Pixel not part of this tile. */
         continue;
       }
@@ -252,23 +263,39 @@ static void fix_unconnected_seam(
         /* Skip this pixel as it already has a solution. */
         continue;
       }
-
+      float2 uv_coord(u, v);
       // What is the distance to the edge.
-      float2 uv(float(u) / bitmap.resolution[0], float(v) / bitmap.resolution[1]);
+      float2 uv(uv_coord.x / bitmap.resolution.x, uv_coord.y / bitmap.resolution.y);
       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);
+      const float lambda = closest_to_line_v2(closest_point, uv, luv_a_1.uv, luv_a_2.uv);
       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);
+
+      /* Distance to the edge in pixel space. */
+      float distance_to_edge = len_v2v2(closest_coord, uv_coord);
       if (distance_to_edge > 2.5f) {
         continue;
       }
 
-      int2 source_pixel = find_source_pixel(bitmap, closest_coord);
+      /*
+       * Project the point over onto the connected UV space. Taking into account the scale
+       * difference.
+       */
+      float2 other_closest_point;
+      interp_v2_v2v2(other_closest_point, luv_b_2.uv, luv_b_1.uv, lambda);
+      float2 direction_b;
+      sub_v2_v2v2(direction_b, luv_b_2.uv, luv_b_1.uv);
+      float2 perpedicular_b(direction_b.y, -direction_b.x);
+      normalize_v2(perpedicular_b);
+      perpedicular_b.x /= bitmap.resolution.x;
+      perpedicular_b.y /= bitmap.resolution.y;
+      float2 projected_coord = other_closest_point +
+                               perpedicular_b * distance_to_edge * scale_factor;
+      projected_coord.x *= bitmap.resolution.x;
+      projected_coord.y *= bitmap.resolution.y;
+
+      int2 source_pixel = find_source_pixel(bitmap, projected_coord);
       int2 destination_pixel(u, v);
 
       PixelInfo src_pixel_info = bitmap.get_pixel_info(source_pixel);
@@ -288,40 +315,29 @@ static void fix_unconnected_seam(
   }
 }
 
-void BKE_pbvh_pixels_rebuild_seams(
-    PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image_user, int cd_loop_uv_offset)
+static void build_fixes(PBVH &pbvh,
+                        const Vector<BMLoopConnection> &connected,
+                        Bitmaps &bitmaps,
+                        const int cd_loop_uv_offset)
 {
-  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
-
-  BMeshCreateParams bmesh_create_params{};
-  bmesh_create_params.use_toolflags = true;
-  BMesh *bm = BM_mesh_create(&allocsize, &bmesh_create_params);
-
-  BMeshFromMeshParams from_mesh_params{};
-  from_mesh_params.calc_face_normal = false;
-  from_mesh_params.calc_vert_normal = false;
-  BM_mesh_bm_from_me(bm, mesh, &from_mesh_params);
-
-  pbvh_pixels_clear_seams(pbvh);
-
-  // find seams.
-  // for each edge
-  Vector<BMLoopConnection> connected;
-  Vector<BMLoop *> unconnected;
-  find_connected_loops(bm, cd_loop_uv_offset, connected, unconnected);
-
-  // Make a bitmap per tile indicating pixels that have already been assigned to a PBVHNode.
-  Bitmaps bitmaps = create_tile_bitmap(*pbvh, *image, *image_user);
-
-  for (BMLoopConnection &pair : connected) {
+  for (const BMLoopConnection &pair : connected) {
     // determine bounding rect in uv space + margin of 1;
     rctf uvbounds;
     BLI_rctf_init_minmax(&uvbounds);
-    MLoopUV *luv_1 = static_cast<MLoopUV *>(BM_ELEM_CD_GET_VOID_P(pair.first, cd_loop_uv_offset));
-    MLoopUV *luv_2 = static_cast<MLoopUV *>(
+    MLoopUV *luv_a_1 = static_cast<MLoopUV *>(
+        BM_ELEM_CD_GET_VOID_P(pair.first, cd_loop_uv_offset));
+    MLoopUV *luv_a_2 = static_cast<MLoopUV *>(
         BM_ELEM_CD_GET_VOID_P(pair.first->next, cd_loop_uv_offset));
-    BLI_rctf_do_minmax_v(&uvbounds, luv_1->uv);
-    BLI_rctf_do_minmax_v(&uvbounds, luv_2->uv);
+    BLI_rctf_do_minmax_v(&uvbounds, luv_a_1->uv);
+    BLI_rctf_do_minmax_v(&uvbounds, luv_a_2->uv);
+
+    MLoopUV *luv_b_1 = static_cast<MLoopUV *>(
+        BM_ELEM_CD_GET_VOID_P(pair.second, cd_loop_uv_offset));
+    MLoopUV *luv_b_2 = static_cast<MLoopUV *>(
+        BM_ELEM_CD_GET_VOID_P(pair.second->next, cd_loop_uv_offset));
+
+    const float scale_factor = len_v2v2(luv_b_1->uv, luv_b_2->uv) /
+                               len_v2v2(luv_a_1->uv, luv_a_2->uv);
 
     for (Bitmap &bitmap : bitmaps.bitmaps) {
       rcti uvbounds_i;
@@ -339,10 +355,74 @@ void BKE_pbvh_pixels_rebuild_seams(
                             bitmap.resolution[1] +
                         MARGIN;
 
-      fix_unconnected_seam(*pbvh, bitmap, uvbounds_i, *luv_1, *luv_2);
+      build_fixes(pbvh, bitmap, uvbounds_i, *luv_a_1, *luv_a_2, *luv_b_1, *luv_b_2, scale_factor);
     }
   }
+}
 
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Build fixes for unconnected edges.
+ * \{ */
+
+static void build_fixes(
+    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);
+    }
+  }
+}
+
+static void build_fixes(PBVH &pbvh,
+                        const Vector<BMLoop *> &unconnected,
+                        Bitmaps &bitmaps,
+                        const int cd_loop_uv_offset)
+{
   for (const BMLoop *unconnected_loop : unconnected) {
     // determine bounding rect in uv space + margin of 1;
     rctf uvbounds;
@@ -370,9 +450,40 @@ void BKE_pbvh_pixels_rebuild_seams(
                             bitmap.resolution[1] +
                         MARGIN;
 
-      fix_unconnected_seam(*pbvh, bitmap, uvbounds_i, *luv_1, *luv_2);
+      build_fixes(pbvh, bitmap, uvbounds_i, *luv_1, *luv_2);
     }
   }
+}
+
+/** \} */
+
+void BKE_pbvh_pixels_rebuild_seams(
+    PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image_user, int cd_loop_uv_offset)
+{
+  const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
+
+  BMeshCreateParams bmesh_create_params{};
+  bmesh_create_params.use_toolflags = true;
+  BMesh *bm = BM_mesh_create(&allocsize, &bmesh_create_par

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list