[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [53641] trunk/blender/source/blender: * Fix for #31581.

Antony Riakiotakis kalast at gmail.com
Mon Jan 7 22:42:40 CET 2013


Revision: 53641
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=53641
Author:   psy-fi
Date:     2013-01-07 21:42:40 +0000 (Mon, 07 Jan 2013)
Log Message:
-----------
* 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.

Modified Paths:
--------------
    trunk/blender/source/blender/blenlib/intern/math_geom.c
    trunk/blender/source/blender/bmesh/intern/bmesh_interp.c
    trunk/blender/source/blender/editors/transform/transform.c

Modified: trunk/blender/source/blender/blenlib/intern/math_geom.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/math_geom.c	2013-01-07 21:39:36 UTC (rev 53640)
+++ trunk/blender/source/blender/blenlib/intern/math_geom.c	2013-01-07 21:42:40 UTC (rev 53641)
@@ -2335,15 +2335,26 @@
 {
 	/* 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,26 +2363,50 @@
 		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 @@
 		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;
+			}
 		}
 	}
 }

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_interp.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_interp.c	2013-01-07 21:39:36 UTC (rev 53640)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_interp.c	2013-01-07 21:42:40 UTC (rev 53641)
@@ -606,9 +606,9 @@
 	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 @@
 	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 @@
 
 	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 **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);

Modified: trunk/blender/source/blender/editors/transform/transform.c
===================================================================
--- trunk/blender/source/blender/editors/transform/transform.c	2013-01-07 21:39:36 UTC (rev 53640)
+++ trunk/blender/source/blender/editors/transform/transform.c	2013-01-07 21:42:40 UTC (rev 53641)
@@ -462,7 +462,10 @@
 			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 @@
 					}
 
 				}
-				
+
 				if (!affected)
 					continue;
 




More information about the Bf-blender-cvs mailing list