[Bf-blender-cvs] [8ef03b070d6] temp-T97352-3d-texturing-seam-bleeding-b2: Use edges for borders.

Jeroen Bakker noreply at git.blender.org
Tue Jun 7 14:45:24 CEST 2022


Commit: 8ef03b070d6f757d0ed799fb8526db8edb02f9be
Author: Jeroen Bakker
Date:   Tue Jun 7 14:39:08 2022 +0200
Branches: temp-T97352-3d-texturing-seam-bleeding-b2
https://developer.blender.org/rB8ef03b070d6f757d0ed799fb8526db8edb02f9be

Use edges for borders.

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

M	source/blender/blenkernel/BKE_uv_islands.hh
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 33aecaceca9..77c430dea7c 100644
--- a/source/blender/blenkernel/BKE_uv_islands.hh
+++ b/source/blender/blenkernel/BKE_uv_islands.hh
@@ -4,6 +4,7 @@
 #pragma once
 
 #include <fstream>
+#include <optional>
 
 #include "BLI_array.hh"
 #include "BLI_edgehash.h"
@@ -71,6 +72,16 @@ struct MeshPrimitive {
     BLI_assert_unreachable();
     return vertices[0];
   }
+
+  MeshUVVert *get_other_uv_vertex(const MeshVertex *v1, const MeshVertex *v2)
+  {
+    for (MeshUVVert &uv_vertex : vertices) {
+      if (uv_vertex.vertex != v1 && uv_vertex.vertex != v2) {
+        return &uv_vertex;
+      }
+    }
+    return nullptr;
+  }
 };
 
 /** Wrapper to contain all required mesh data. */
@@ -284,43 +295,51 @@ struct UVPrimitive {
     }
     return false;
   }
+
+  UVBorder extract_border() const;
 };
 
-struct UVBorderVert {
-  UVVertex *uv_vertex;
+struct UVBorderEdge {
+  UVEdge *edge;
+  bool tag = false;
+  UVPrimitive *uv_primitive;
+  /* Should the vertices of the edge be evaluated in reverse order. */
+  bool reverse_order = false;
 
-  /* Indexes of connected border verts. */
-  int64_t index;
-  int64_t prev_index;
-  int64_t next_index;
-  int64_t border_index;
+  int64_t index = -1;
+  int64_t prev_index = -1;
+  int64_t next_index = -1;
+  int64_t border_index = -1;
 
   struct {
-    /** Should this vertex still be checked when performing extension. */
+    /* Is possible to extend on the `get_uv_vertex(0)` */
     bool extendable : 1;
   } flags;
 
-  explicit UVBorderVert(UVVertex *uv_vertex) : uv_vertex(uv_vertex)
+  explicit UVBorderEdge(UVEdge *edge, UVPrimitive *uv_primitive)
+      : edge(edge), uv_primitive(uv_primitive)
   {
     flags.extendable = true;
   }
-};
-
-struct UVBorderEdge {
-  UVEdge *edge;
-  bool tag = false;
-  UVPrimitive *uv_primitive;
 
-  explicit UVBorderEdge(UVEdge *edge, UVPrimitive *uv_primitive)
-      : edge(edge), uv_primitive(uv_primitive)
+  UVVertex *get_uv_vertex(int index)
+  {
+    int actual_index = reverse_order ? 1 - index : index;
+    return edge->vertices[actual_index];
+  }
+  const UVVertex *get_uv_vertex(int index) const
   {
+    int actual_index = reverse_order ? 1 - index : index;
+    return edge->vertices[actual_index];
   }
 };
 
+using UVBorderCorner = std::pair<UVBorderEdge &, UVBorderEdge &>;
+
 struct UVBorder {
   /** Ordered list of UV Verts of the border of this island. */
   // TODO: support multiple rings + order (CW, CCW)
-  Vector<UVBorderVert> verts;
+  Vector<UVBorderEdge> edges;
 
   /**
    * Flip the order of the verts, changing the order between CW and CCW.
@@ -330,9 +349,11 @@ struct UVBorder {
   /**
    * Calculate the outside angle of the given vert.
    */
-  float outside_angle(const UVBorderVert &vert) const;
+  float outside_angle(const UVBorderEdge &vert) const;
 
   void update_indexes(uint64_t border_index);
+
+  static std::optional<UVBorder> extract_from_edges(Vector<UVBorderEdge> &edges);
 };
 
 struct UVIsland {
@@ -340,8 +361,8 @@ struct UVIsland {
   Vector<UVEdge> uv_edges;
   Vector<UVPrimitive> uv_primitives;
   /**
-   * List of borders of this island. There can be multiple borders per island as a border could be
-   * completely encapsulated by another one.
+   * 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;
 
@@ -400,7 +421,7 @@ struct UVIsland {
   }
 
   /** Initialize the border attribute. */
-  void extract_border();
+  void extract_borders();
   /** Iterative extend border to fit the mask. */
   void extend_border(const UVIslandsMask &mask,
                      const short island_index,
@@ -504,8 +525,24 @@ struct UVIslands {
   void extract_borders()
   {
     for (UVIsland &island : islands) {
-      island.extract_border();
+      island.extract_borders();
     }
+
+#ifdef DEBUG_SVG
+    std::ofstream of;
+    of.open("/tmp/borders.svg");
+    svg_header(of);
+    for (UVIsland &island : islands) {
+      int index = 0;
+      for (UVBorder &border : island.borders) {
+        border.update_indexes(index);
+        index++;
+        svg(of, border);
+      }
+    }
+    svg_footer(of);
+    of.close();
+#endif
   }
 
   void extend_borders(const UVIslandsMask &islands_mask, const MeshData &mesh_data)
diff --git a/source/blender/blenkernel/intern/uv_islands.cc b/source/blender/blenkernel/intern/uv_islands.cc
index 58e758a56d7..e69f19b7ee8 100644
--- a/source/blender/blenkernel/intern/uv_islands.cc
+++ b/source/blender/blenkernel/intern/uv_islands.cc
@@ -3,13 +3,17 @@
 
 #include "BKE_uv_islands.hh"
 
+#include <optional>
+
 namespace blender::bke::uv_islands {
+
 /* -------------------------------------------------------------------- */
 /** \name UVIsland
  * \{ */
 
-void UVIsland::extract_border()
+void UVIsland::extract_borders()
 {
+  /* Lookup all borders of the island. */
   Vector<UVBorderEdge> edges;
   for (int64_t prim_index = 0; prim_index < uv_primitives.size(); prim_index++) {
     UVPrimitive &prim = uv_primitives[prim_index];
@@ -21,72 +25,38 @@ void UVIsland::extract_border()
   }
 
   while (true) {
-    UVBorder border;
-    /* Find a part of the border that haven't been extracted yet. */
-    UVBorderEdge *starting_border_edge = nullptr;
-    for (UVBorderEdge &edge : edges) {
-      if (edge.tag == false) {
-        starting_border_edge = &edge;
-        break;
-      }
-    }
-    if (starting_border_edge == nullptr) {
+    std::optional<UVBorder> border = UVBorder::extract_from_edges(edges);
+    if (!border.has_value()) {
       break;
     }
-
-    starting_border_edge->tag = true;
-    float2 first_uv = starting_border_edge->edge->vertices[0]->uv;
-    float2 current_uv = starting_border_edge->edge->vertices[1]->uv;
-    UVVertex *current_vert = starting_border_edge->edge->vertices[1];
-    border.verts.append(UVBorderVert(starting_border_edge->edge->vertices[0]));
-    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.verts.append(UVBorderVert(current_vert));
-            current_uv = border_edge.edge->vertices[1 - i]->uv;
-            current_vert = border_edge.edge->vertices[1 - i];
-            border_edge.tag = true;
-            break;
-          }
-        }
-        if (i != 2) {
-          break;
-        }
-      }
-    }
-    borders.append(border);
+    borders.append(*border);
   }
 }
 
-static UVBorderVert *sharpest_border_vert(UVBorder &border, float *r_angle)
+static std::optional<UVBorderCorner> sharpest_border_corner(UVBorder &border, float *r_angle)
 {
   *r_angle = std::numeric_limits<float>::max();
-  UVBorderVert *result = nullptr;
-  for (UVBorderVert &vert : border.verts) {
-    if (vert.flags.extendable == false) {
+  std::optional<UVBorderCorner> result;
+  for (UVBorderEdge &edge : border.edges) {
+    if (edge.flags.extendable == false) {
       continue;
     }
-    float new_radius = border.outside_angle(vert);
+    float new_radius = border.outside_angle(edge);
     if (new_radius < *r_angle) {
       *r_angle = new_radius;
-      result = |
+      result = UVBorderCorner(border.edges[edge.prev_index], edge);
     }
   }
   return result;
 }
 
-static UVBorderVert *sharpest_border_vert(UVIsland &island)
+static std::optional<UVBorderCorner> sharpest_border_corner(UVIsland &island)
 {
-  UVBorderVert *result = nullptr;
+  std::optional<UVBorderCorner> result;
   float sharpest_angle = std::numeric_limits<float>::max();
   for (UVBorder &border : island.borders) {
     float new_radius;
-    UVBorderVert *new_result = sharpest_border_vert(border, &new_radius);
+    std::optional<UVBorderCorner> new_result = sharpest_border_corner(border, &new_radius);
     if (new_radius < sharpest_angle) {
       sharpest_angle = new_radius;
       result = new_result;
@@ -168,7 +138,7 @@ struct Fan {
     }
   }
 
-  void init_uv_coordinates(UVBorderVert &vert, const UVIsland &island)
+  void init_uv_coordinates(UVVertex &uv_vertex, const UVIsland &island)
   {
     for (FanSegment &segment : segments) {
       int2 test_edge = int2(segment.primitive->vertices[segment.vert_order[0]].vertex->v,
@@ -178,9 +148,9 @@ struct Fan {
           int2 o(edge->vertices[0]->vertex->v, edge->vertices[1]->vertex->v);
           if ((test_edge.x == o.x && test_edge.y == o.y) ||
               (test_edge.x == o.y && test_edge.y == o.x)) {
-            segment.uvs[0] = vert.uv_vertex->uv;
+            segment.uvs[0] = uv_vertex.uv;
             for (int i = 0; i < 2; i++) {
-              if (edge->vertices[i]->uv == vert.uv_vertex->uv) {
+              if (edge->vertices[i]->uv == uv_vertex.uv) {
                 segment.uvs[1] = edge->vertices[1 - i]->uv;
                 break;
               }
@@ -211,18 +181,20 @@ static void print(const Fan &fan)
   }
 }
 
-static void extend_at_vert(UVIsland &island, UVBorderVert &vert, const MeshData &mesh_data)
+static void extend_at_vert(UVIsland &island, UVBorderCorner &corner, const MeshData &mesh_data)
 {
-  Fan fan(*vert.uv_vertex->vertex);
+  BLI_assert(corner.first.get_uv_vertex(1) == corner.second.get_uv_vertex(0));
+  UVVertex *uv_vertex = corner.second.get_uv_vertex(0);
+  Fan fan(*(uv_vertex->vertex));
   print(fan);
-  fan.init_uv_coordinates(vert, island);
+  fan.init_uv_coordinates(*uv_vertex, island);
   print(fan);
 
   for (FanSegment &segment : fan.segments) {
     segment.flags.found = false;
     MeshVertex *v0 = segment.primitive->vertices[segment.vert_order[0]].vertex;
     MeshVertex *v1 = segment.primitive->vertices[segment.vert_order[1]].vertex;
-    for (UVEdge *edge : vert.uv_vertex->uv_edges) {
+    for (UVEdge *edge : uv_vertex->uv_edges) {
       if ((edge->vertices[0]->vertex == v0 && edge->vertices[1]->vertex == v1) ||
           (edge->vertices[0]->vertex == v1 && edge->vertices[1]->vertex == v0)) {
         segment.flags.found = true;
@@ -244,34 +216,59 @@ static vo

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list