[Bf-blender-cvs] [da95fa83444] blender-v2.90-release: Fix UV unwrap not working with only one pinned vertex

Brecht Van Lommel noreply at git.blender.org
Wed Aug 12 12:07:12 CEST 2020


Commit: da95fa8344445814ed46a4346d8cbd22186b20cb
Author: Brecht Van Lommel
Date:   Mon Aug 10 18:32:07 2020 +0200
Branches: blender-v2.90-release
https://developer.blender.org/rBda95fa8344445814ed46a4346d8cbd22186b20cb

Fix UV unwrap not working with only one pinned vertex

Now the one vertex defines the position of the UV chart, while rotation and
shape is still determined automatically.

Initial patch by Willis (wlssirius).

Differential Revision: https://developer.blender.org/D8484

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

M	source/blender/editors/uvedit/uvedit_parametrizer.c

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

diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c
index a4ee9a294fe..e83b54ae8bf 100644
--- a/source/blender/editors/uvedit/uvedit_parametrizer.c
+++ b/source/blender/editors/uvedit/uvedit_parametrizer.c
@@ -190,6 +190,9 @@ typedef struct PChart {
       LinearSolver *context;
       float *abf_alpha;
       PVert *pin1, *pin2;
+      PVert *single_pin;
+      float single_pin_area;
+      float single_pin_uv[2];
     } lscm;
     struct PChartPack {
       float rescale, area;
@@ -467,6 +470,17 @@ static void p_chart_uv_bbox(PChart *chart, float minv[2], float maxv[2])
   }
 }
 
+static float p_chart_uv_area(PChart *chart)
+{
+  float area = 0.0f;
+
+  for (PFace *f = chart->faces; f; f = f->nextlink) {
+    area += fabsf(p_face_uv_area_signed(f));
+  }
+
+  return area;
+}
+
 static void p_chart_uv_scale(PChart *chart, float scale)
 {
   PVert *v;
@@ -3176,7 +3190,7 @@ static void p_chart_lscm_begin(PChart *chart, PBool live, PBool abf)
     }
   }
 
-  if ((live && (!select || !deselect)) || (npins == 1)) {
+  if ((live && (!select || !deselect))) {
     chart->u.lscm.context = NULL;
   }
   else {
@@ -3185,6 +3199,16 @@ static void p_chart_lscm_begin(PChart *chart, PBool live, PBool abf)
     p_chart_topological_sanity_check(chart);
 #endif
 
+    if (npins == 1) {
+      chart->u.lscm.single_pin_area = p_chart_uv_area(chart);
+      for (v = chart->verts; v; v = v->nextlink) {
+        if (v->flag & PVERT_PIN) {
+          chart->u.lscm.single_pin = v;
+          break;
+        }
+      }
+    }
+
     if (abf) {
       if (!p_chart_abf_solve(chart)) {
         param_warning("ABF solving failed: falling back to LSCM.\n");
@@ -3192,12 +3216,12 @@ static void p_chart_lscm_begin(PChart *chart, PBool live, PBool abf)
     }
 
     if (npins <= 1) {
-      /* not enough pins, lets find some ourself */
+      /* No pins, let's find some ourself. */
       PEdge *outer;
 
       p_chart_boundaries(chart, NULL, &outer);
 
-      /* outer can be NULL with non-finite coords. */
+      /* Outer can be NULL with non-finite coords. */
       if (!(outer && p_chart_symmetry_pins(chart, outer, &pin1, &pin2))) {
         p_chart_extrema_verts(chart, &pin1, &pin2);
       }
@@ -3235,6 +3259,11 @@ static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
     }
   }
 
+  if (chart->u.lscm.single_pin) {
+    /* If only one pin, save area and pin for transform later. */
+    copy_v2_v2(chart->u.lscm.single_pin_uv, chart->u.lscm.single_pin->uv);
+  }
+
   if (chart->u.lscm.pin1) {
     EIG_linear_solver_variable_lock(context, 2 * pin1->u.id);
     EIG_linear_solver_variable_lock(context, 2 * pin1->u.id + 1);
@@ -3358,6 +3387,25 @@ static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
   return P_FALSE;
 }
 
+static void p_chart_lscm_transform_single_pin(PChart *chart)
+{
+  PVert *pin = chart->u.lscm.single_pin;
+
+  /* If only one pin, keep UV area the same. */
+  const float new_area = p_chart_uv_area(chart);
+  if (new_area > 0.0f) {
+    const float scale = chart->u.lscm.single_pin_area / new_area;
+    if (scale > 0.0f) {
+      p_chart_uv_scale(chart, sqrtf(scale));
+    }
+  }
+
+  /* Translate to keep the pinned vertex in place. */
+  float offset[2];
+  sub_v2_v2v2(offset, chart->u.lscm.single_pin_uv, pin->uv);
+  p_chart_uv_translate(chart, offset);
+}
+
 static void p_chart_lscm_end(PChart *chart)
 {
   if (chart->u.lscm.context) {
@@ -3372,6 +3420,8 @@ static void p_chart_lscm_end(PChart *chart)
   chart->u.lscm.context = NULL;
   chart->u.lscm.pin1 = NULL;
   chart->u.lscm.pin2 = NULL;
+  chart->u.lscm.single_pin = NULL;
+  chart->u.lscm.single_pin_area = 0.0f;
 }
 
 /* Stretch */
@@ -3781,6 +3831,23 @@ static void p_chart_rotate_minimum_area(PChart *chart)
   }
 }
 
+static void p_chart_rotate_fit_aabb(PChart *chart)
+{
+  float(*points)[2] = MEM_mallocN(sizeof(*points) * chart->nverts, __func__);
+
+  p_chart_uv_to_array(chart, points);
+
+  float angle = BLI_convexhull_aabb_fit_points_2d(points, chart->nverts);
+
+  MEM_freeN(points);
+
+  if (angle != 0.0f) {
+    float mat[2][2];
+    angle_to_mat2(mat, angle);
+    p_chart_uv_transform(chart, mat);
+  }
+}
+
 /* Area Smoothing */
 
 /* 2d bsp tree for inverse mapping - that's a bit silly */
@@ -4576,8 +4643,12 @@ void param_lscm_solve(ParamHandle *handle)
       if (result && !(chart->flag & PCHART_HAS_PINS)) {
         p_chart_rotate_minimum_area(chart);
       }
+      else if (result && chart->u.lscm.single_pin) {
+        p_chart_rotate_fit_aabb(chart);
+        p_chart_lscm_transform_single_pin(chart);
+      }
 
-      if (!result || (chart->u.lscm.pin1)) {
+      if (!result || !(chart->flag & PCHART_HAS_PINS)) {
         p_chart_lscm_end(chart);
       }
     }
@@ -4692,28 +4763,13 @@ static void param_pack_rotate(ParamHandle *handle, bool ignore_pinned)
   PHandle *phandle = (PHandle *)handle;
 
   for (i = 0; i < phandle->ncharts; i++) {
-    float(*points)[2];
-    float angle;
-
     chart = phandle->charts[i];
 
     if (ignore_pinned && (chart->flag & PCHART_HAS_PINS)) {
       continue;
     }
 
-    points = MEM_mallocN(sizeof(*points) * chart->nverts, __func__);
-
-    p_chart_uv_to_array(chart, points);
-
-    angle = BLI_convexhull_aabb_fit_points_2d(points, chart->nverts);
-
-    MEM_freeN(points);
-
-    if (angle != 0.0f) {
-      float mat[2][2];
-      angle_to_mat2(mat, angle);
-      p_chart_uv_transform(chart, mat);
-    }
+    p_chart_rotate_fit_aabb(chart);
   }
 }



More information about the Bf-blender-cvs mailing list