Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brecht@blender.org>2020-08-10 19:32:07 +0300
committerBrecht Van Lommel <brecht@blender.org>2020-08-12 12:52:09 +0300
commitda95fa8344445814ed46a4346d8cbd22186b20cb (patch)
tree56c975cd5acf824a1c36391b8e68c67efc9a9170 /source/blender/editors/uvedit
parentcbb1bb90fde1f01a7718212f0300d7895e353c06 (diff)
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
Diffstat (limited to 'source/blender/editors/uvedit')
-rw-r--r--source/blender/editors/uvedit/uvedit_parametrizer.c96
1 files changed, 76 insertions, 20 deletions
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);
}
}