* Fix for #31581. The issue was that we scaled the face prior to
authorAntony Riakiotakis <kalast@gmail.com>
Mon, 7 Jan 2013 21:42:40 +0000 (21:42 +0000)
committerAntony Riakiotakis <kalast@gmail.com>
Mon, 7 Jan 2013 21:42:40 +0000 (21:42 +0000)
projecting it. The original paper suggests to simply interpolate between
the two points of an edge if the distance of the point to that edge is
smaller than a threshold.

* Fixed both 3D and 2D code to utilize this. Possibly other places in
blender where this scaling is done will have to be adjusted.

* Changed vertex interpolation to use 2D interpolation, since it already
did projection on plane and 2d calculations are faster.

* Also added notifier on hard recalc when uvcalc_transfor_correction is
used. Results in instant feedback on UV editor when edge sliding.

source/blender/blenlib/intern/math_geom.c
source/blender/bmesh/intern/bmesh_interp.c
source/blender/editors/transform/transform.c

index a643c89..91939b4 100644 (file)
@@ -2335,14 +2335,25 @@ void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[
 {
        /* TODO: t1 and t2 overlap each iter, we could call this only once per iter and reuse previous value */
        float totweight, t1, t2, len, *vmid, *vprev, *vnext;
-       int i;
+       int i, inext, icur;
+       bool edge_interp = false;
 
        totweight = 0.0f;
 
        for (i = 0; i < n; i++) {
+               icur = i;
+               inext = (i == n - 1) ? 0 : i + 1;
+
                vmid = v[i];
                vprev = (i == 0) ? v[n - 1] : v[i - 1];
-               vnext = (i == n - 1) ? v[0] : v[i + 1];
+               vnext = v[inext];
+
+               /* Mark Mayer et al algorithm that is used here does not operate well if vertex is close
+                * to borders of face. In that case, do simple linear interpolation between the two edges */
+               if (dist_to_line_segment_v3(co, vmid, vnext) < 10*FLT_EPSILON) {
+                       edge_interp = true;
+                       break;
+               }
 
                t1 = mean_value_half_tan_v3(co, vprev, vmid);
                t2 = mean_value_half_tan_v3(co, vmid, vnext);
@@ -2352,25 +2363,49 @@ void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[
                totweight += w[i];
        }
 
-       if (totweight != 0.0f) {
-               for (i = 0; i < n; i++) {
-                       w[i] /= totweight;
+       if (edge_interp) {
+               float len_cur = len_v3v3(co, vmid);
+               float len_next = len_v3v3(co, vnext);
+               float edge_len = len_cur + len_next;
+               for (i = 0; i < n; i++)
+                       w[i] = 0.0;
+
+               w[icur] = len_next/edge_len;
+               w[inext] = len_cur/edge_len;
+       }
+       else {
+               if (totweight != 0.0f) {
+                       for (i = 0; i < n; i++) {
+                               w[i] /= totweight;
+                       }
                }
        }
 }
 
+
 void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[2])
 {
        /* TODO: t1 and t2 overlap each iter, we could call this only once per iter and reuse previous value */
        float totweight, t1, t2, len, *vmid, *vprev, *vnext;
-       int i;
+       int i, inext, icur;
+       bool edge_interp = false;
 
        totweight = 0.0f;
 
        for (i = 0; i < n; i++) {
+               icur = i;
+               inext = (i == n - 1) ? 0 : i + 1;
+
                vmid = v[i];
                vprev = (i == 0) ? v[n - 1] : v[i - 1];
-               vnext = (i == n - 1) ? v[0] : v[i + 1];
+               vnext = v[inext];
+
+               /* Mark Mayer et al algorithm that is used here does not operate well if vertex is close
+                * to borders of face. In that case, do simple linear interpolation between the two edges */
+               if (dist_to_line_segment_v2(co, vmid, vnext) < 10*FLT_EPSILON) {
+                       edge_interp = true;
+                       break;
+               }
 
                t1 = mean_value_half_tan_v2(co, vprev, vmid);
                t2 = mean_value_half_tan_v2(co, vmid, vnext);
@@ -2380,9 +2415,21 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[
                totweight += w[i];
        }
 
-       if (totweight != 0.0f) {
-               for (i = 0; i < n; i++) {
-                       w[i] /= totweight;
+       if (edge_interp) {
+               float len_cur = len_v2v2(co, vmid);
+               float len_next = len_v2v2(co, vnext);
+               float edge_len = len_cur + len_next;
+               for (i = 0; i < n; i++)
+                       w[i] = 0.0;
+
+               w[icur] = len_next/edge_len;
+               w[inext] = len_cur/edge_len;
+       }
+       else {
+               if (totweight != 0.0f) {
+                       for (i = 0; i < n; i++) {
+                               w[i] /= totweight;
+                       }
                }
        }
 }
index 4ec91b8..1afaf85 100644 (file)
@@ -606,9 +606,9 @@ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
        void **vblocks  = do_vertex ? BLI_array_alloca(vblocks, source->len) : NULL;
        void **blocks   = BLI_array_alloca(blocks,  source->len);
        float (*cos)[3] = BLI_array_alloca(cos,     source->len);
+       float (*cos_2d)[2] = BLI_array_alloca(cos_2d,     source->len);
        float *w        = BLI_array_alloca(w,       source->len);
-       float co[3];
-       float cent[3] = {0.0f, 0.0f, 0.0f};
+       float co[2];
        int i, ax, ay;
 
        BM_elem_attrs_copy(bm, bm, source, target->f);
@@ -617,7 +617,6 @@ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
        l_iter = l_first = BM_FACE_FIRST_LOOP(source);
        do {
                copy_v3_v3(cos[i], l_iter->v->co);
-               add_v3_v3(cent, cos[i]);
 
                w[i] = 0.0f;
                blocks[i] = l_iter->head.data;
@@ -634,28 +633,17 @@ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source,
 
        axis_dominant_v3(&ax, &ay, source->no);
 
-       /* scale source face coordinates a bit, so points sitting directly on an
-        * edge will work. */
-       mul_v3_fl(cent, 1.0f / (float)source->len);
        for (i = 0; i < source->len; i++) {
-               float vec[3], tmp[3];
-               sub_v3_v3v3(vec, cent, cos[i]);
-               mul_v3_fl(vec, 0.001f);
-               add_v3_v3(cos[i], vec);
-
-               copy_v3_v3(tmp, cos[i]);
-               cos[i][0] = tmp[ax];
-               cos[i][1] = tmp[ay];
-               cos[i][2] = 0.0f;
+               cos_2d[i][0] = cos[i][ax];
+               cos_2d[i][1] = cos[i][ay];
        }
 
 
        /* interpolate */
        co[0] = target->v->co[ax];
        co[1] = target->v->co[ay];
-       co[2] = 0.0f;
 
-       interp_weights_poly_v3(w, cos, source->len, co);
+       interp_weights_poly_v2(w, cos_2d, source->len, co);
        CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, source->len, target->head.data);
        if (do_vertex) {
                CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, source->len, target->v->head.data);
@@ -676,30 +664,18 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source)
        void **blocks   = BLI_array_alloca(blocks, source->len);
        float (*cos)[3] = BLI_array_alloca(cos,    source->len);
        float *w        = BLI_array_alloca(w,      source->len);
-       float cent[3] = {0.0f, 0.0f, 0.0f};
        int i;
 
        i = 0;
        l_iter = l_first = BM_FACE_FIRST_LOOP(source);
        do {
                copy_v3_v3(cos[i], l_iter->v->co);
-               add_v3_v3(cent, cos[i]);
 
                w[i] = 0.0f;
                blocks[i] = l_iter->v->head.data;
                i++;
        } while ((l_iter = l_iter->next) != l_first);
 
-       /* scale source face coordinates a bit, so points sitting directly on an
-        * edge will work. */
-       mul_v3_fl(cent, 1.0f / (float)source->len);
-       for (i = 0; i < source->len; i++) {
-               float vec[3];
-               sub_v3_v3v3(vec, cent, cos[i]);
-               mul_v3_fl(vec, 0.01f);
-               add_v3_v3(cos[i], vec);
-       }
-
        /* interpolate */
        interp_weights_poly_v3(w, cos, source->len, v->co);
        CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, source->len, v->head.data);
index 3b443e8..78a8bd4 100644 (file)
@@ -462,7 +462,10 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
                        WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
                else
                        WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
-               
+
+               if (t->mode == TFM_EDGE_SLIDE && (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT))
+                       WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
+
                /* for realtime animation record - send notifiers recognised by animation editors */
                // XXX: is this notifier a lame duck?
                if ((t->animtimer) && IS_AUTOKEY_ON(t->scene))
@@ -5424,7 +5427,7 @@ void projectSVData(TransInfo *t, int final)
                                        }
 
                                }
-                               
+
                                if (!affected)
                                        continue;