* Fix for #31581. The issue was that we scaled the face prior to

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.
This commit is contained in:
Antony Riakiotakis
2013-01-07 21:42:40 +00:00
parent 41c588256b
commit c3b5c726c7
3 changed files with 67 additions and 41 deletions

View 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;
}
}
}
}

View 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);

View 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;