[Bf-blender-cvs] [ec703819c1b] temp-T97352-3d-texturing-seam-bleeding-b2: Add missing segments from a fan.

Jeroen Bakker noreply at git.blender.org
Tue Jun 14 14:57:00 CEST 2022


Commit: ec703819c1bb00f3003d6e76df749ed4977ced14
Author: Jeroen Bakker
Date:   Tue Jun 14 13:11:48 2022 +0200
Branches: temp-T97352-3d-texturing-seam-bleeding-b2
https://developer.blender.org/rBec703819c1bb00f3003d6e76df749ed4977ced14

Add missing segments from a fan.

TODO: Borders should be updated.

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

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 792acd41f00..31f0144539a 100644
--- a/source/blender/blenkernel/BKE_uv_islands.hh
+++ b/source/blender/blenkernel/BKE_uv_islands.hh
@@ -8,6 +8,7 @@
 
 #include "BLI_array.hh"
 #include "BLI_edgehash.h"
+#include "BLI_float3x3.hh"
 #include "BLI_math.h"
 #include "BLI_math_vec_types.hh"
 #include "BLI_vector.hh"
@@ -73,6 +74,16 @@ struct MeshPrimitive {
     return vertices[0];
   }
 
+  bool has_vertex(const MeshVertex &v) const
+  {
+    for (int i = 0; i < 3; i++) {
+      if (vertices[i].vertex == &v) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   MeshUVVert *get_other_uv_vertex(const MeshVertex *v1, const MeshVertex *v2)
   {
     BLI_assert(vertices[0].vertex == v1 || vertices[1].vertex == v1 || vertices[2].vertex == v1);
@@ -248,6 +259,14 @@ struct UVEdge {
       vertex->uv_edges.append_non_duplicates(this);
     }
   }
+
+  UVVertex *get_other_uv_vertex(const MeshVertex *vertex)
+  {
+    if (vertices[0]->vertex == vertex) {
+      return vertices[1];
+    }
+    return vertices[0];
+  }
 };
 
 struct UVPrimitive {
@@ -394,22 +413,25 @@ struct UVBorderEdge {
 struct UVBorderCorner {
   UVBorderEdge *first;
   UVBorderEdge *second;
+  float angle;
 
-  UVBorderCorner(UVBorderEdge *first, UVBorderEdge *second) : first(first), second(second)
+  UVBorderCorner(UVBorderEdge *first, UVBorderEdge *second, float angle)
+      : first(first), second(second), angle(angle)
   {
   }
 
   float2 uv(float factor)
   {
-    float2 linear;
-    interp_v2_v2v2(linear, first->get_uv_vertex(0)->uv, second->get_uv_vertex(1)->uv, factor);
-    float2 origin = second->get_uv_vertex(0)->uv;
+    float2 origin = first->get_uv_vertex(1)->uv;
+    float angle_between = angle * factor;
     float desired_len = second->length() * factor + first->length() * (1.0 - factor);
+    float2 v = first->get_uv_vertex(0)->uv - origin;
+    normalize_v2(v);
 
-    float2 dir = linear - origin;
-    normalize_v2(dir);
-
-    return origin + dir * desired_len;
+    float3x3 rot_mat = float3x3::from_rotation(angle_between);
+    float2 rotated = rot_mat * v;
+    float2 result = rotated * desired_len + first->get_uv_vertex(1)->uv;
+    return result;
   }
 };
 
diff --git a/source/blender/blenkernel/intern/uv_islands.cc b/source/blender/blenkernel/intern/uv_islands.cc
index 91bdde22c0e..4728a3e85f1 100644
--- a/source/blender/blenkernel/intern/uv_islands.cc
+++ b/source/blender/blenkernel/intern/uv_islands.cc
@@ -41,10 +41,10 @@ static std::optional<UVBorderCorner> sharpest_border_corner(UVBorder &border, fl
     if (edge.flags.extendable == false) {
       continue;
     }
-    float new_radius = border.outside_angle(edge);
-    if (new_radius < *r_angle) {
-      *r_angle = new_radius;
-      result = UVBorderCorner(&border.edges[edge.prev_index], &edge);
+    float new_angle = border.outside_angle(edge);
+    if (new_angle < *r_angle) {
+      *r_angle = new_angle;
+      result = UVBorderCorner(&border.edges[edge.prev_index], &edge, new_angle);
     }
   }
   return result;
@@ -55,10 +55,10 @@ static std::optional<UVBorderCorner> sharpest_border_corner(UVIsland &island)
   std::optional<UVBorderCorner> result;
   float sharpest_angle = std::numeric_limits<float>::max();
   for (UVBorder &border : island.borders) {
-    float new_radius;
-    std::optional<UVBorderCorner> new_result = sharpest_border_corner(border, &new_radius);
-    if (new_radius < sharpest_angle) {
-      sharpest_angle = new_radius;
+    float new_angle;
+    std::optional<UVBorderCorner> new_result = sharpest_border_corner(border, &new_angle);
+    if (new_angle < sharpest_angle) {
+      sharpest_angle = new_angle;
       result = new_result;
     }
   }
@@ -101,6 +101,7 @@ struct FanSegment {
   }
 };
 
+// TODO: should have InnerEdges and Primitives to reduce complexity in algorithm
 struct Fan {
   /* Blades of the fan. */
   Vector<FanSegment> segments;
@@ -250,6 +251,19 @@ static void add_uv_primitive_shared_uv_edge(UVIsland &island,
   island.validate_primitive(island.uv_primitives.last());
 }
 
+static MeshPrimitive *find_fill_border(const MeshVertex &v1,
+                                       const MeshVertex &v2,
+                                       const MeshVertex &v3)
+{
+  for (MeshEdge *edge : v1.edges) {
+    for (MeshPrimitive *primitive : edge->primitives) {
+      if (primitive->has_vertex(v1) && primitive->has_vertex(v2) && primitive->has_vertex(v3)) {
+        return primitive;
+      }
+    }
+  }
+  return nullptr;
+}
 /**
  * Find a primitive that can be used to fill give corner.
  * Will return nullptr when no primitive can be found.
@@ -296,7 +310,7 @@ static void add_uv_primitive_fill(UVIsland &island,
   uv_primitive.append_to_uv_edges();
   uv_primitive.append_to_uv_vertices();
   island.uv_primitives.append(uv_primitive);
-  island.validate_primitive(island.uv_primitives.last());
+  // island.validate_primitive(island.uv_primitives.last());
 }
 
 static void extend_at_vert(UVIsland &island, UVBorderCorner &corner, const MeshData &mesh_data)
@@ -370,20 +384,78 @@ static void extend_at_vert(UVIsland &island, UVBorderCorner &corner, const MeshD
   }
   else {
     UVEdge *current_edge = corner.first->edge;
-    FanSegment *last_added = nullptr;
-    for (int i = 0; i < num_to_add + 1; i++) {
+    for (int i = 0; i < num_to_add; i++) {
+      float2 old_uv = current_edge->get_other_uv_vertex(uv_vertex->vertex)->uv;
+      MeshVertex *shared_edge_vertex =
+          current_edge->get_other_uv_vertex(uv_vertex->vertex)->vertex;
+
       float factor = (i + 1.0f) / (num_to_add + 1.0f);
       float2 new_uv = corner.uv(factor);
 
       // Find an segment that contains the 'current edge'.
       for (FanSegment &segment : fan.segments) {
-        if (!segment.flags.should_be_added) {
+        if (segment.flags.found) {
           continue;
         }
 
-        last_added = &segment;
+        // Find primitive that shares the current edge and the segment edge.
+        MeshPrimitive *fill_primitive = find_fill_border(
+            *uv_vertex->vertex,
+            *shared_edge_vertex,
+            *segment.primitive->vertices[segment.vert_order[1]].vertex);
+        if (fill_primitive == nullptr) {
+          continue;
+        }
+        MeshVertex *other_prim_vertex =
+            fill_primitive->get_other_uv_vertex(uv_vertex->vertex, shared_edge_vertex)->vertex;
+
+        UVVertex uv_vertex_template;
+        uv_vertex_template.vertex = uv_vertex->vertex;
+        uv_vertex_template.uv = uv_vertex->uv;
+        UVVertex *vertex_1_ptr = island.lookup_or_create(uv_vertex_template);
+        uv_vertex_template.vertex = shared_edge_vertex;
+        uv_vertex_template.uv = old_uv;
+        UVVertex *vertex_2_ptr = island.lookup_or_create(uv_vertex_template);
+        uv_vertex_template.vertex = other_prim_vertex;
+        uv_vertex_template.uv = new_uv;
+        UVVertex *vertex_3_ptr = island.lookup_or_create(uv_vertex_template);
+
+        add_uv_primitive_fill(
+            island, *vertex_1_ptr, *vertex_2_ptr, *vertex_3_ptr, *fill_primitive);
+
+        segment.flags.found = true;
+
+        /* TODO: should be done based on meshvertex */
+        UVPrimitive &new_prim = island.uv_primitives[island.uv_primitives.size() - 1];
+        current_edge = new_prim.get_uv_edge(uv_vertex->uv, new_uv);
+
+        break;
       }
     }
+
+    {
+      /* Add final segment. */
+      float2 old_uv = current_edge->get_other_uv_vertex(uv_vertex->vertex)->uv;
+      MeshVertex *shared_edge_vertex =
+          current_edge->get_other_uv_vertex(uv_vertex->vertex)->vertex;
+      MeshPrimitive *fill_primitive = find_fill_border(
+          *uv_vertex->vertex, *shared_edge_vertex, *corner.second->get_uv_vertex(1)->vertex);
+      BLI_assert(fill_primitive);
+      MeshVertex *other_prim_vertex =
+          fill_primitive->get_other_uv_vertex(uv_vertex->vertex, shared_edge_vertex)->vertex;
+
+      UVVertex uv_vertex_template;
+      uv_vertex_template.vertex = uv_vertex->vertex;
+      uv_vertex_template.uv = uv_vertex->uv;
+      UVVertex *vertex_1_ptr = island.lookup_or_create(uv_vertex_template);
+      uv_vertex_template.vertex = shared_edge_vertex;
+      uv_vertex_template.uv = old_uv;
+      UVVertex *vertex_2_ptr = island.lookup_or_create(uv_vertex_template);
+      uv_vertex_template.vertex = other_prim_vertex;
+      uv_vertex_template.uv = corner.second->get_uv_vertex(1)->uv;
+      UVVertex *vertex_3_ptr = island.lookup_or_create(uv_vertex_template);
+      add_uv_primitive_fill(island, *vertex_1_ptr, *vertex_2_ptr, *vertex_3_ptr, *fill_primitive);
+    }
   }
 }
 
@@ -408,7 +480,7 @@ void UVIsland::extend_border(const UVIslandsMask &mask,
 
   // Debug setting to reduce the extension to a number of iterations as long as not all corner
   // cases have been implemented.
-  int num_iterations = 6;
+  int num_iterations = 7;
   while (num_iterations) {
     if (num_iterations == 1) {
       printf("Last iteration");
@@ -426,7 +498,7 @@ void UVIsland::extend_border(const UVIslandsMask &mask,
 
     // TODO: extend
     extend_at_vert(*this, *extension_corner, mesh_data);
-    validate_border();
+    // validate_border();
 
     /* Mark that the vert is extended. Unable to extend twice. */
     extension_corner->second->flags.extendable = false;



More information about the Bf-blender-cvs mailing list