[Bf-blender-cvs] [059ee7280f1] temp-T97352-3d-texturing-seam-bleeding-b: Calculating angle of uv verts.

Jeroen Bakker noreply at git.blender.org
Wed May 25 09:01:31 CEST 2022


Commit: 059ee7280f12cf6adef365c8f849590c0f09af3b
Author: Jeroen Bakker
Date:   Tue May 24 16:10:07 2022 +0200
Branches: temp-T97352-3d-texturing-seam-bleeding-b
https://developer.blender.org/rB059ee7280f12cf6adef365c8f849590c0f09af3b

Calculating angle of uv verts.

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

M	source/blender/blenkernel/BKE_uv_islands.hh
M	source/blender/blenkernel/CMakeLists.txt
M	source/blender/blenkernel/intern/pbvh_pixels.cc
A	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 475ba2953a1..260735bcd7d 100644
--- a/source/blender/blenkernel/BKE_uv_islands.hh
+++ b/source/blender/blenkernel/BKE_uv_islands.hh
@@ -5,6 +5,8 @@
 
 #include <fstream>
 
+#include "BLI_array.hh"
+#include "BLI_math.h"
 #include "BLI_math_vec_types.hh"
 #include "BLI_vector.hh"
 
@@ -15,7 +17,15 @@ namespace blender::bke::uv_islands {
 // TODO: Joining uv island should check where the borders could be merged.
 // TODO: this isn't optimized for performance.
 
-//#define DEBUG_SVG
+/*
+ * When enabled various parts of the code would generate an SVG file to visual see how the
+ * algorithm makes decisions.
+ */
+#define DEBUG_SVG
+
+struct UVIslands;
+struct UVIslandsMask;
+struct UVBorder;
 
 struct UVVertex {
   /* Loop index of the vertex in the original mesh. */
@@ -86,8 +96,15 @@ struct UVPrimitive {
 
 struct UVBorderVert {
   float2 uv;
+
+  struct {
+    /** Should this vertex still be checked when performing extension. */
+    bool extendable : 1;
+  } flags;
+
   explicit UVBorderVert(float2 &uv) : uv(uv)
   {
+    flags.extendable = true;
   }
 };
 
@@ -100,55 +117,39 @@ struct UVBorderEdge {
   }
 };
 
+struct UVBorder {
+  /** Ordered list of UV Verts of the border of this island. */
+  // TODO: support multiple rings + order (CW, CCW)
+  Vector<UVBorderVert> verts;
+
+  /**
+   * Flip the order of the verts, changing the order between CW and CCW.
+   */
+  void flip_order();
+
+  /**
+   * Calculate the outside angle of the given vert.
+   */
+  float outside_angle(const UVBorderVert &vert) const;
+};
+
 struct UVIsland {
   Vector<UVPrimitive> primitives;
-  Vector<UVBorderVert> border;
+  /**
+   * List of borders of this island. There can be multiple borders per island as a border could be
+   * completely encapsulated by another one.
+   */
+  Vector<UVBorder> borders;
 
   UVIsland(const UVPrimitive &primitive)
   {
     append(primitive);
   }
 
-  void extract_border()
-  {
-    Vector<UVBorderEdge> edges;
-
-    for (UVPrimitive &primitive : primitives) {
-      for (UVEdge &edge : primitive.edges) {
-        if (edge.is_border_edge()) {
-          edges.append(UVBorderEdge(&edge));
-        }
-      }
-    }
-
-    edges.first().tag = true;
-    UVEdge *starting_edge = edges.first().edge;
-
-    border.append(UVBorderVert(starting_edge->vertices[0].uv));
-    border.append(UVBorderVert(starting_edge->vertices[1].uv));
-    UVBorderVert &first = border.first();
-    UVBorderVert &current = border.last();
-
-    while (current.uv != first.uv) {
-      for (UVBorderEdge &border_edge : edges) {
-        if (border_edge.tag == true) {
-          continue;
-        }
-        int i;
-        for (i = 0; i < 2; i++) {
-          if (border_edge.edge->vertices[i].uv == current.uv) {
-            border.append(UVBorderVert(border_edge.edge->vertices[1 - i].uv));
-            border_edge.tag = true;
-            current = border.last();
-            break;
-          }
-        }
-        if (i != 2) {
-          break;
-        }
-      }
-    }
-  }
+  /** Initialize the border attribute. */
+  void extract_border();
+  /** Iterative extend border to fit the mask. */
+  void extend_border(const UVIslandsMask &mask, const short island_index);
 
  private:
   void append(const UVPrimitive &primitive)
@@ -220,12 +221,12 @@ struct UVIsland {
   }
 };
 
-struct UVIslands;
-struct UVIslandsMask;
+/* Debug functions to export to a SVG file. */
 void svg_header(std::ostream &ss);
 void svg(std::ostream &ss, const UVIslands &islands, int step);
 void svg(std::ostream &ss, const UVPrimitive &primitive, int step);
 void svg(std::ostream &ss, const UVIslandsMask &mask, int step);
+void svg(std::ostream &ss, const UVBorder &border);
 void svg_footer(std::ostream &ss);
 
 struct UVIslands {
@@ -255,6 +256,27 @@ struct UVIslands {
     }
   }
 
+  void extend_borders(const UVIslandsMask &islands_mask)
+  {
+    ushort index = 0;
+    for (UVIsland &island : islands) {
+      island.extend_border(islands_mask, index++);
+    }
+
+#ifdef DEBUG_SVG
+    std::ofstream of;
+    of.open("/tmp/borders.svg");
+    svg_header(of);
+    for (const UVIsland &island : islands) {
+      for (const UVBorder &border : island.borders) {
+        svg(of, border);
+      }
+    }
+    svg_footer(of);
+    of.close();
+#endif
+  }
+
  private:
   void add(const UVPrimitive &primitive)
   {
@@ -322,6 +344,13 @@ struct UVIslandsMask {
   {
     mask.fill(0xffff);
   }
+  /**
+   * Is the given uv coordinate part of the given island_index mask.
+   *
+   * true - part of the island mask.
+   * false - not part of the island mask.
+   */
+  bool is_masked(const short island_index, const float2 uv) const;
 
   void add(const UVIslands &islands)
   {
@@ -365,76 +394,7 @@ struct UVIslandsMask {
     mask[offset] = island_index;
   }
 
-  void dilate()
-  {
-#ifdef DEBUG_SVG
-    std::ofstream of;
-    of.open("/tmp/dilate.svg");
-    svg_header(of);
-    int index = 0;
-#endif
-    while (true) {
-      bool changed = dilate_x();
-      changed |= dilate_y();
-      if (!changed) {
-        break;
-      }
-#ifdef DEBUG_SVG
-      svg(of, *this, index++);
-#endif
-    }
-#ifdef DEBUG_SVG
-    svg(of, *this, index);
-    svg_footer(of);
-    of.close();
-#endif
-  }
-
-  bool dilate_x()
-  {
-    bool changed = false;
-    const Array<uint16_t> prev_mask = mask;
-    for (int y = 0; y < resolution.y; y++) {
-      for (int x = 0; x < resolution.x; x++) {
-        uint64_t offset = y * resolution.x + x;
-        if (prev_mask[offset] != 0xffff) {
-          continue;
-        }
-        if (x != 0 && prev_mask[offset - 1] != 0xffff) {
-          mask[offset] = prev_mask[offset - 1];
-          changed = true;
-        }
-        else if (x < resolution.x - 1 && prev_mask[offset + 1] != 0xffff) {
-          mask[offset] = prev_mask[offset + 1];
-          changed = true;
-        }
-      }
-    }
-    return changed;
-  }
-
-  bool dilate_y()
-  {
-    bool changed = false;
-    const Array<uint16_t> prev_mask = mask;
-    for (int y = 0; y < resolution.y; y++) {
-      for (int x = 0; x < resolution.x; x++) {
-        uint64_t offset = y * resolution.x + x;
-        if (prev_mask[offset] != 0xffff) {
-          continue;
-        }
-        if (y != 0 && prev_mask[offset - resolution.x] != 0xffff) {
-          mask[offset] = prev_mask[offset - resolution.x];
-          changed = true;
-        }
-        else if (y < resolution.y - 1 && prev_mask[offset + resolution.x] != 0xffff) {
-          mask[offset] = prev_mask[offset + resolution.x];
-          changed = true;
-        }
-      }
-    }
-    return changed;
-  }
+  void dilate();
 
   void print() const
   {
@@ -472,127 +432,4 @@ struct UVIslandsMask {
   }
 };
 
-void svg_header(std::ostream &ss)
-{
-  ss << "<svg viewBox=\"0 0 1024 1024\" width=\"1024\" height=\"1024\" "
-        "xmlns=\"http://www.w3.org/2000/svg\">\n";
-}
-void svg_footer(std::ostream &ss)
-{
-  ss << "</svg>\n";
-}
-void svg(std::ostream &ss, const UVEdge &edge)
-{
-  ss << "       <line x1=\"" << edge.vertices[0].uv.x * 1024 << "\" y1=\""
-     << edge.vertices[0].uv.y * 1024 << "\" x2=\"" << edge.vertices[1].uv.x * 1024 << "\" y2=\""
-     << edge.vertices[1].uv.y * 1024 << "\"/>\n";
-}
-
-void svg(std::ostream &ss, const UVIslands &islands, int step)
-{
-  ss << "<g transform=\"translate(" << step * 1024 << " 0)\">\n";
-  int island_index = 0;
-  for (const UVIsland &island : islands.islands) {
-    ss << "  <g fill=\"yellow\">\n";
-
-    /* Inner edges */
-    ss << "    <g stroke=\"grey\" stroke-dasharray=\"5 5\">\n";
-    for (const UVPrimitive &primitive : island.primitives) {
-      for (int i = 0; i < 3; i++) {
-        const UVEdge &edge = primitive.edges[i];
-        if (edge.adjacent_uv_primitive == -1) {
-          continue;
-        }
-        svg(ss, edge);
-      }
-    }
-    ss << "     </g>\n";
-
-    /* Border */
-    ss << "    <g stroke=\"black\" stroke-width=\"2\">\n";
-    for (const UVPrimitive &primitive : island.primitives) {
-      for (int i = 0; i < 3; i++) {
-        const UVEdge &edge = primitive.edges[i];
-        if (edge.adjacent_uv_primitive != -1) {
-          continue;
-        }
-        svg(ss, edge);
-      }
-    }
-    ss << "     </g>\n";
-
-    ss << "   </g>\n";
-    island_index++;
-  }
-
-  ss << "</g>\n";
-}
-
-void svg(std::ostream &ss, const UVIslandsMask &mask, int step)
-{
-  ss << "<g transform=\"translate(" << step * 1024 << " 0)\">\n";
-  ss << " <g fill=\"none\" stroke=\"black\">\n";
-
-  float2 resolution = float2(mask.resolution.x, mask.resolution.y);
-  for (int x = 0; x < mask.resolution.x; x++) {
-    for (int y = 0; y < mask.resolution.y; y++) {
-      int offset = y * mask.resolution.x + x;
-      int offset2 = offset - 1;
-      if (y == 0 && mask.mask[offset] == 0xffff) {
-        continue;
-      }
-      if (x > 0 && mask.mask[offset] == mask.mask[offset2]) {
-        continue;
-      }
-      float2 start = float2(float(x), float(y)) / resolution * float2(1024, 1024);
-      float2 end = float2(float(x), float(y + 1)) / resolution * float2(1024, 1024);
-      ss << "       <line x1=\"" << start.x << "\" y1=\"" << start.y << "\" x2=\"" << end.x
-         << "\" y2=\"" << end.y << "\"/>\n";
-    }
-  }
-
-  for (int x = 0; x < mask.resolution.x; x++) {
-    for (int y = 0; y < mask.resolution.y; y++) {
-      int offset = y * mask.resolution.x + x;
-      int offset2 = offset - mask.resolution.x;
-      if (x == 0 && mask.mask[offset] == 0xffff) {
-        continue;
-      }
-      if (y > 0 && mask.mask[offset] == mask.mask[offset2]) {
-        continue;
-      }
-      float2 start = float2(float(x), float(y)) / resolution * float2(1024, 1024);
-      float2 end = float2(float(x + 1), float(y)) / resolution * float2(1024, 1024);
-      ss << "       <line x1=\"" << start.x << "\" y1=\"" << start.y << "\" x2=\"" << end.x
-         << "\" y2=\"" << end.y << "\"/>\n";
-    }
-  }
-  ss << " </g>\n";
-  ss << "</g>\n";
-}
-
-void svg_coords(std::ostream &ss, const float2 &coords)
-{
-  ss << coords.x * 1024 << "," << coords.y * 1024;
-}
-
-void svg(std::ostream &ss, const 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list