[Bf-blender-cvs] [bfb9faaded1] temp-T96710-pbvh-pixels: Extend seams in x direction.

Jeroen Bakker noreply at git.blender.org
Fri Apr 8 11:07:50 CEST 2022


Commit: bfb9faaded1747bc1ccfd37816cfa38634692412
Author: Jeroen Bakker
Date:   Fri Apr 8 11:07:32 2022 +0200
Branches: temp-T96710-pbvh-pixels
https://developer.blender.org/rBbfb9faaded1747bc1ccfd37816cfa38634692412

Extend seams in x direction.

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

M	source/blender/blenkernel/BKE_pbvh.hh
M	source/blender/blenkernel/intern/pbvh_pixels.cc
M	source/blender/blenkernel/intern/pbvh_pixels_seams.cc

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

diff --git a/source/blender/blenkernel/BKE_pbvh.hh b/source/blender/blenkernel/BKE_pbvh.hh
index f598d9da58a..05ff9a53199 100644
--- a/source/blender/blenkernel/BKE_pbvh.hh
+++ b/source/blender/blenkernel/BKE_pbvh.hh
@@ -49,6 +49,18 @@ class BarycentricWeights {
     return BarycentricWeights(weights + rhs);
   }
 
+  BarycentricWeights &operator-=(const float3 &rhs)
+  {
+    weights -= rhs;
+    return *this;
+  }
+
+  BarycentricWeights &operator+=(const float3 &rhs)
+  {
+    weights += rhs;
+    return *this;
+  }
+
   operator const float *() const
   {
     return weights;
@@ -116,6 +128,7 @@ struct Triangle {
 struct TrianglePaintInput {
   int3 vert_indices;
   float3 add_barycentric_coord_x;
+  float3 add_barycentric_coord_y;
 
   TrianglePaintInput(const Triangle &triangle)
       : vert_indices(triangle.vert_indices),
diff --git a/source/blender/blenkernel/intern/pbvh_pixels.cc b/source/blender/blenkernel/intern/pbvh_pixels.cc
index 30da876391a..b7badb5674d 100644
--- a/source/blender/blenkernel/intern/pbvh_pixels.cc
+++ b/source/blender/blenkernel/intern/pbvh_pixels.cc
@@ -22,6 +22,8 @@
 
 namespace blender::bke::pbvh::pixels::extractor {
 
+#define DO_WATERTIGHT_CHECK
+
 /**
  * Keep track of visited polygons.
  *
@@ -49,10 +51,10 @@ class VisitedPolygons : std::vector<bool> {
 /**
  * @brief Calculate the delta of two neighbour uv coordinates in the given image buffer.
  */
-static float3 calc_barycentric_delta(const ImBuf *image_buffer,
-                                     const float2 uvs[3],
-                                     const int x,
-                                     const int y)
+static float3 calc_barycentric_delta_x(const ImBuf *image_buffer,
+                                       const float2 uvs[3],
+                                       const int x,
+                                       const int y)
 {
   const float2 start_uv(float(x) / image_buffer->x, float(y) / image_buffer->y);
   const float2 end_uv(float(x + 1) / image_buffer->x, float(y) / image_buffer->y);
@@ -62,6 +64,19 @@ static float3 calc_barycentric_delta(const ImBuf *image_buffer,
   return delta_barycentric;
 }
 
+static float3 calc_barycentric_delta_y(const ImBuf *image_buffer,
+                                       const float2 uvs[3],
+                                       const int x,
+                                       const int y)
+{
+  const float2 start_uv(float(x) / image_buffer->x, float(y) / image_buffer->y);
+  const float2 end_uv(float(x) / image_buffer->x, float(y + 1) / image_buffer->y);
+  const BarycentricWeights start_barycentric(uvs[0], uvs[1], uvs[2], start_uv);
+  const BarycentricWeights end_barycentric(uvs[0], uvs[1], uvs[2], end_uv);
+  const float3 delta_barycentric = end_barycentric - start_barycentric;
+  return delta_barycentric;
+}
+
 static void extract_barycentric_pixels(TileData &tile_data,
                                        const ImBuf *image_buffer,
                                        const int triangle_index,
@@ -179,7 +194,8 @@ static void do_encode_pixels(void *__restrict userdata,
       const int maxx = min_ii(ceil(maxu * image_buffer->x), image_buffer->x);
 
       TrianglePaintInput &triangle = triangles.get_paint_input(triangle_index);
-      triangle.add_barycentric_coord_x = calc_barycentric_delta(image_buffer, uvs, minx, miny);
+      triangle.add_barycentric_coord_x = calc_barycentric_delta_x(image_buffer, uvs, minx, miny);
+      triangle.add_barycentric_coord_y = calc_barycentric_delta_y(image_buffer, uvs, minx, miny);
       extract_barycentric_pixels(
           tile_data, image_buffer, triangle_index, uvs, minx, miny, maxx, maxy);
     }
@@ -290,6 +306,56 @@ static bool find_nodes_to_update(PBVH *pbvh,
   return true;
 }
 
+/** Durind debugging this check could be enabled. It will write to each image pixel that is covered
+ * by the pbvh. */
+constexpr bool do_watertight_check()
+{
+  return false;
+}
+
+static void apply_watertight_check(PBVH *pbvh, Image *image, ImageUser *image_user)
+{
+  ImageUser watertight = *image_user;
+  LISTBASE_FOREACH (ImageTile *, tile_data, &image->tiles) {
+    image::ImageTileWrapper image_tile(tile_data);
+    watertight.tile = image_tile.get_tile_number();
+    ImBuf *image_buffer = BKE_image_acquire_ibuf(image, &watertight, NULL);
+    if (image_buffer == nullptr) {
+      continue;
+    }
+    for (int n = 0; n < pbvh->totnode; n++) {
+      PBVHNode *node = &pbvh->nodes[n];
+      if ((node->flag & PBVH_Leaf) == 0) {
+        continue;
+      }
+      NodeData *node_data = static_cast<NodeData *>(node->pixels.node_data);
+      TileData *tile_node_data = node_data->find_tile_data(image_tile);
+      if (tile_node_data == nullptr) {
+        continue;
+      }
+
+      for (PixelsPackage &encoded_pixels : tile_node_data->packages) {
+        int pixel_offset = encoded_pixels.start_image_coordinate.y * image_buffer->x +
+                           encoded_pixels.start_image_coordinate.x;
+        for (int x = 0; x < encoded_pixels.num_pixels; x++) {
+          if (image_buffer->rect_float) {
+            image_buffer->rect_float[pixel_offset * 4] += 0.5;
+            // copy_v4_fl(&image_buffer->rect_float[pixel_offset * 4], 1.0);
+          }
+          if (image_buffer->rect) {
+            uint8_t *dest = static_cast<uint8_t *>(
+                static_cast<void *>(&image_buffer->rect[pixel_offset]));
+            copy_v4_uchar(dest, 255);
+          }
+          pixel_offset += 1;
+        }
+      }
+    }
+    BKE_image_release_ibuf(image, image_buffer, NULL);
+  }
+  BKE_image_partial_update_mark_full_update(image);
+}
+
 static void update_pixels(PBVH *pbvh,
                           const MeshElemMap *pmap,
                           const struct MPoly *mpoly,
@@ -325,7 +391,13 @@ static void update_pixels(PBVH *pbvh,
   TaskParallelSettings settings;
   BKE_pbvh_parallel_range_settings(&settings, true, nodes_to_update.size());
   BLI_task_parallel_range(0, nodes_to_update.size(), &user_data, do_encode_pixels, &settings);
-  // BKE_pbvh_pixels_fix_seams(*pbvh, *image, *image_user);
+  if (do_watertight_check()) {
+    apply_watertight_check(pbvh, image, image_user);
+  }
+  BKE_pbvh_pixels_fix_seams(*pbvh, *image, *image_user);
+  if (do_watertight_check()) {
+    apply_watertight_check(pbvh, image, image_user);
+  }
 
   /* Clear the UpdatePixels flag. */
   for (PBVHNode *node : nodes_to_update) {
@@ -358,49 +430,6 @@ static void update_pixels(PBVH *pbvh,
            float(compressed_data_len) / num_pixels);
   }
 #endif
-
-#define DO_WATERTIGHT_CHECK
-#ifdef DO_WATERTIGHT_CHECK
-  ImageUser watertight = *image_user;
-  LISTBASE_FOREACH (ImageTile *, tile_data, &image->tiles) {
-    image::ImageTileWrapper image_tile(tile_data);
-    watertight.tile = image_tile.get_tile_number();
-    ImBuf *image_buffer = BKE_image_acquire_ibuf(image, &watertight, NULL);
-    if (image_buffer == nullptr) {
-      continue;
-    }
-    for (int n = 0; n < pbvh->totnode; n++) {
-      PBVHNode *node = &pbvh->nodes[n];
-      if ((node->flag & PBVH_Leaf) == 0) {
-        continue;
-      }
-      NodeData *node_data = static_cast<NodeData *>(node->pixels.node_data);
-      TileData *tile_node_data = node_data->find_tile_data(image_tile);
-      if (tile_node_data == nullptr) {
-        continue;
-      }
-
-      for (PixelsPackage &encoded_pixels : tile_node_data->packages) {
-        int pixel_offset = encoded_pixels.start_image_coordinate.y * image_buffer->x +
-                           encoded_pixels.start_image_coordinate.x;
-        for (int x = 0; x < encoded_pixels.num_pixels; x++) {
-          if (image_buffer->rect_float) {
-            copy_v4_fl(&image_buffer->rect_float[pixel_offset * 4], 1.0);
-          }
-          if (image_buffer->rect) {
-            uint8_t *dest = static_cast<uint8_t *>(
-                static_cast<void *>(&image_buffer->rect[pixel_offset]));
-            copy_v4_uchar(dest, 255);
-          }
-          pixel_offset += 1;
-        }
-      }
-    }
-    BKE_image_release_ibuf(image, image_buffer, NULL);
-  }
-  BKE_image_partial_update_mark_full_update(image);
-
-#endif
 }
 
 }  // namespace blender::bke::pbvh::pixels::extractor
diff --git a/source/blender/blenkernel/intern/pbvh_pixels_seams.cc b/source/blender/blenkernel/intern/pbvh_pixels_seams.cc
index 9fe945e476c..423fa90869a 100644
--- a/source/blender/blenkernel/intern/pbvh_pixels_seams.cc
+++ b/source/blender/blenkernel/intern/pbvh_pixels_seams.cc
@@ -22,12 +22,46 @@ struct UVSeamExtenderRowPackage {
   {
   }
 
+  /**
+   * Check if any of the corners of the extended pixels is inside the triangle. In this case we
+   * should extend.
+   *
+   * This could be improved by using the triangle uv coordinates and using triangle intersection in
+   * UV space. Currently it can fail near the triangle vertices based on how the triangulation
+   * happens.
+   */
+  bool should_extend_start() const
+  {
+    BarycentricWeights weights = package->start_barycentric_coord.decode();
+    return (weights.is_inside_triangle() ||
+            (weights + triangle_paint_data->add_barycentric_coord_y).is_inside_triangle());
+  }
+
   void extend_x_start()
   {
     package->num_pixels += 1;
     package->start_image_coordinate[0] -= 1;
     package->start_barycentric_coord -= float2(triangle_paint_data->add_barycentric_coord_x);
   }
+
+  bool should_extend_end() const
+  {
+    BarycentricWeights weights = package->start_barycentric_coord.decode();
+    weights += triangle_paint_data->add_barycentric_coord_x * package->num_pixels;
+    if (weights.is_inside_triangle()) {
+      return true;
+    }
+    weights += triangle_paint_data->add_barycentric_coord_y;
+    if (weights.is_inside_triangle()) {
+      return true;
+    }
+    return false;
+  }
+
+  void extend_x_end()
+  {
+    package->num_pixels += 1;
+  }
 };
 
 class UVSeamExtenderRow : public Vector<UVSeamExtenderRowPackage> {
@@ -41,18 +75,29 @@ class UVSeamExtenderRow : public Vector<UVSeamExtenderRowPackage> {
     Vector<UVSeamExtenderRowPackage>::append(package);
   }
 
-  void extend_x()
+  void extend_x(int image_buffer_width)
   {
     std::sort(
         begin(), end(), [](const UVSeamExtender

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list