* 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:
@@ -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 (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,11 +2415,23 @@ void interp_weights_poly_v2(float *w, float v[][2], const int n, const float co[
|
||||
totweight += w[i];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* (x1, v1)(t1=0)------(x2, v2)(t2=1), 0<t<1 --> (x, v)(t) */
|
||||
|
@@ -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);
|
||||
|
@@ -463,6 +463,9 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
|
||||
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))
|
||||
|
Reference in New Issue
Block a user