[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [59913] trunk/blender/source/blender: changes to grid fill

Campbell Barton ideasman42 at gmail.com
Sat Sep 7 10:13:40 CEST 2013


Revision: 59913
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=59913
Author:   campbellbarton
Date:     2013-09-07 08:13:39 +0000 (Sat, 07 Sep 2013)
Log Message:
-----------
changes to grid fill
- use 4 weights for vertex customdata blending (was previously only using 2)
- option for simple blending, which blends locations using weights too and doesn't attempt to maintain the shape,
  useful for flat surfaces or times when keeping the shape gives odd results.

Modified Paths:
--------------
    trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c
    trunk/blender/source/blender/bmesh/operators/bmo_fill_grid.c
    trunk/blender/source/blender/editors/mesh/editmesh_tools.c

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c	2013-09-07 06:56:27 UTC (rev 59912)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c	2013-09-07 08:13:39 UTC (rev 59913)
@@ -542,6 +542,7 @@
 	/* restricts edges to groups.  maps edges to integer */
 	 {"mat_nr",         BMO_OP_SLOT_INT},      /* material to use */
 	 {"use_smooth",     BMO_OP_SLOT_BOOL},     /* smooth state to use */
+	 {"use_interp_simple", BMO_OP_SLOT_BOOL},  /* use simple interpolation */
 	 {{'\0'}},
 	},
 	/* slots_out */

Modified: trunk/blender/source/blender/bmesh/operators/bmo_fill_grid.c
===================================================================
--- trunk/blender/source/blender/bmesh/operators/bmo_fill_grid.c	2013-09-07 06:56:27 UTC (rev 59912)
+++ trunk/blender/source/blender/bmesh/operators/bmo_fill_grid.c	2013-09-07 08:13:39 UTC (rev 59913)
@@ -154,25 +154,15 @@
  * Interpolate from boundary loops.
  *
  * \note These weights will be calculated multiple times per vertex.
- * Since this runs on each loop, could reduce calls to #barycentric_weights_v2_quad.
  */
-static void bm_loop_interp_from_grid_boundary_4(BMesh *bm, BMLoop *l, BMLoop *l_bound[4], const float uv[2])
+static void bm_loop_interp_from_grid_boundary_4(BMesh *bm, BMLoop *l, BMLoop *l_bound[4], const float w[4])
 {
-	float cos[4][2] = {
-	    {uv[0],     0},
-	    {0,     uv[1]},
-	    {uv[0],     1},
-	    {1,     uv[1]}};
-
 	void *l_cdata[4] = {
 	    l_bound[0]->head.data,
 	    l_bound[1]->head.data,
 	    l_bound[2]->head.data,
 	    l_bound[3]->head.data};
 
-	float w[4];
-
-	barycentric_weights_v2_quad(UNPACK4(cos), uv, w);
 	CustomData_bmesh_interp(&bm->ldata, l_cdata, w, NULL, 4, l->head.data);
 }
 
@@ -192,13 +182,42 @@
 
 
 /**
+ * Avoids calling #barycentric_weights_v2_quad often by caching weights into an array.
+ */
+static void barycentric_weights_v2_grid_cache(const unsigned int xtot, const unsigned int ytot,
+                                              float (*weight_table)[4])
+{
+	float x_step = 1.0f / (float)(xtot - 1);
+	float y_step = 1.0f / (float)(ytot - 1);
+	unsigned int i = 0;
+	float xy_fl[2];
+
+	unsigned int x, y;
+	for (y = 0; y < ytot; y++) {
+		xy_fl[1] = y_step * (float)y;
+		for (x = 0; x < xtot; x++) {
+			xy_fl[0] = x_step * (float)x;
+			{
+				const float cos[4][2] = {
+				    {xy_fl[0], 0.0f},
+				    {0.0f, xy_fl[1]},
+				    {xy_fl[0], 1.0f},
+				    {1.0f, xy_fl[1]}};
+				barycentric_weights_v2_quad(UNPACK4(cos), xy_fl, weight_table[i++]);
+			}
+		}
+	}
+}
+
+
+/**
  * This may be useful outside the bmesh operator.
  *
  * \param v_grid  2d array of verts, all boundary verts must be set, we fill in the middle.
  */
 static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const int ytot,
                                const short mat_nr, const bool use_smooth,
-                               const bool use_flip)
+                               const bool use_flip, const bool use_interp_simple)
 {
 	const bool use_vert_interp = CustomData_has_interp(&bm->vdata);
 	const bool use_loop_interp = CustomData_has_interp(&bm->ldata);
@@ -207,6 +226,8 @@
 	/* for use_loop_interp */
 	BMLoop *((*larr_x_a)[2]), *((*larr_x_b)[2]), *((*larr_y_a)[2]), *((*larr_y_b)[2]);
 
+	float (*weight_table)[4];
+
 #define XY(_x, _y)  ((_x) + ((_y) * (xtot)))
 
 #ifdef BARYCENTRIC_INTERP
@@ -233,7 +254,15 @@
 	        true);
 #endif
 
+	if (use_interp_simple || use_vert_interp || use_loop_interp) {
+		weight_table = MEM_mallocN(sizeof(*weight_table) * xtot * ytot, __func__);
+		barycentric_weights_v2_grid_cache(xtot, ytot, weight_table);
+	}
+	else {
+		weight_table = NULL;
+	}
 
+
 	/* Store loops */
 	if (use_loop_interp) {
 		/* x2 because each edge connects 2 loops */
@@ -279,7 +308,7 @@
 
 			/* place the vertex */
 #ifdef BARYCENTRIC_INTERP
-			{
+			if (use_interp_simple == false) {
 				float co_a[3], co_b[3];
 
 				barycentric_transform(
@@ -295,28 +324,34 @@
 
 				interp_v3_v3v3(co, co_a, co_b, (float)y / ((float)ytot - 1));
 			}
-
-#else
-			interp_v3_v3v3(
-			        co,
-			        v_grid[x]->co,
-			        v_grid[(xtot * ytot) + (x - xtot)]->co,
-			        (float)y / ((float)ytot - 1));
+			else
 #endif
+			{
+				const float *w = weight_table[XY(x, y)];
 
+				zero_v3(co);
+				madd_v3_v3fl(co, v_grid[XY(x,        0)]->co, w[0]);
+				madd_v3_v3fl(co, v_grid[XY(0,        y)]->co, w[1]);
+				madd_v3_v3fl(co, v_grid[XY(x, ytot - 1)]->co, w[2]);
+				madd_v3_v3fl(co, v_grid[XY(xtot - 1, y)]->co, w[3]);
+			}
+
 			v = BM_vert_create(bm, co, NULL, BM_CREATE_NOP);
 			v_grid[(y * xtot) + x] = v;
 
 			/* interpolate only along one axis, this could be changed
 			 * but from user pov gives predictable results since these are selected loop */
 			if (use_vert_interp) {
-				void *v_cdata[2] = {
-				    v_grid[XY(x,          0)]->head.data,
-				    v_grid[XY(x, (ytot - 1))]->head.data,
+				const float *w = weight_table[XY(x, y)];
+
+				void *v_cdata[4] = {
+				    v_grid[XY(x,        0)]->head.data,
+				    v_grid[XY(0,        y)]->head.data,
+				    v_grid[XY(x, ytot - 1)]->head.data,
+				    v_grid[XY(xtot - 1, y)]->head.data,
 				};
-				const float t = (float)y / ((float)ytot - 1);
-				const float w[2] = {1.0f - t, t};
-				CustomData_bmesh_interp(&bm->vdata, v_cdata, w, NULL, 2, v->head.data);
+
+				CustomData_bmesh_interp(&bm->vdata, v_cdata, w, NULL, 4, v->head.data);
 			}
 
 		}
@@ -354,7 +389,6 @@
 				BMLoop *l_quad[4];
 				BMLoop *l_bound[4];
 				BMLoop *l_tmp;
-				float uv[2]; /* xy in the grid */
 				int x_side, y_side, i;
 				char interp_from;
 
@@ -396,29 +430,28 @@
 
 				for (x_side = 0; x_side < 2; x_side++) {
 					for (y_side = 0; y_side < 2; y_side++) {
-
-						uv[0] = (float)(x + x_side) / (xtot - 1);
-						uv[1] = (float)(y + y_side) / (ytot - 1);
-
 						if (interp_from == 'B') {
+							const float *w = weight_table[XY(x + x_side, y + y_side)];
 							l_bound[0] = larr_x_a[x][x_side];  /* B */
 							l_bound[1] = larr_y_a[y][y_side];  /* L */
 							l_bound[2] = larr_x_b[x][x_side];  /* T */
 							l_bound[3] = larr_y_b[y][y_side];  /* R */
 
-							bm_loop_interp_from_grid_boundary_4(bm, l_quad[i++], l_bound, uv);
+							bm_loop_interp_from_grid_boundary_4(bm, l_quad[i++], l_bound, w);
 						}
 						else if (interp_from == 'X') {
+							const float t = (float)(y + y_side) / (ytot - 1);
 							l_bound[0] = larr_x_a[x][x_side];  /* B */
 							l_bound[1] = larr_x_b[x][x_side];  /* T */
 
-							bm_loop_interp_from_grid_boundary_2(bm, l_quad[i++], l_bound, uv[1]);
+							bm_loop_interp_from_grid_boundary_2(bm, l_quad[i++], l_bound, t);
 						}
 						else if (interp_from == 'Y') {
+							const float t = (float)(x + x_side) / (xtot - 1);
 							l_bound[0] = larr_y_a[y][y_side];  /* L */
 							l_bound[1] = larr_y_b[y][y_side];  /* R */
 
-							bm_loop_interp_from_grid_boundary_2(bm, l_quad[i++], l_bound, uv[0]);
+							bm_loop_interp_from_grid_boundary_2(bm, l_quad[i++], l_bound, t);
 						}
 						else {
 							BLI_assert(0);
@@ -444,13 +477,17 @@
 		MEM_freeN(larr_y_b);
 	}
 
+	if (weight_table) {
+		MEM_freeN(weight_table);
+	}
+
 #undef XY
 }
 
 static void bm_grid_fill(BMesh *bm,
                          struct BMEdgeLoopStore *estore_a,      struct BMEdgeLoopStore *estore_b,
                          struct BMEdgeLoopStore *estore_rail_a, struct BMEdgeLoopStore *estore_rail_b,
-                         const short mat_nr, const bool use_smooth)
+                         const short mat_nr, const bool use_smooth, const bool use_interp_simple)
 {
 #define USE_FLIP_DETECT
 
@@ -521,7 +558,7 @@
 #endif
 
 
-	bm_grid_fill_array(bm, v_grid, xtot, ytot, mat_nr, use_smooth, use_flip);
+	bm_grid_fill_array(bm, v_grid, xtot, ytot, mat_nr, use_smooth, use_flip, use_interp_simple);
 	MEM_freeN(v_grid);
 
 #undef USE_FLIP_DETECT
@@ -550,8 +587,9 @@
 	struct BMEdgeLoopStore *estore_rail_a, *estore_rail_b;
 	BMVert *v_a_first, *v_a_last;
 	BMVert *v_b_first, *v_b_last;
-	const short mat_nr     = BMO_slot_int_get(op->slots_in,  "mat_nr");
-	const bool use_smooth  = BMO_slot_bool_get(op->slots_in, "use_smooth");
+	const short mat_nr = BMO_slot_int_get(op->slots_in,  "mat_nr");
+	const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
+	const bool use_interp_simple = BMO_slot_bool_get(op->slots_in, "use_interp_simple");
 
 	int count;
 	bool change = false;
@@ -643,7 +681,7 @@
 
 	/* finally we have all edge loops needed */
 	bm_grid_fill(bm, estore_a, estore_b, estore_rail_a, estore_rail_b,
-	             mat_nr, use_smooth);
+	             mat_nr, use_smooth, use_interp_simple);
 
 	change = true;
 cleanup:

Modified: trunk/blender/source/blender/editors/mesh/editmesh_tools.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/editmesh_tools.c	2013-09-07 06:56:27 UTC (rev 59912)
+++ trunk/blender/source/blender/editors/mesh/editmesh_tools.c	2013-09-07 08:13:39 UTC (rev 59913)
@@ -2983,6 +2983,7 @@
 	const short use_smooth = edbm_add_edge_face__smooth_get(em->bm);
 	const int totedge_orig = em->bm->totedge;
 	const int totface_orig = em->bm->totface;
+	const bool use_interp_simple = RNA_boolean_get(op->ptr, "use_interp_simple");
 	const bool use_prepare = true;
 
 
@@ -3018,8 +3019,9 @@
 
 
 	if (!EDBM_op_init(em, &bmop, op,
-	                  "grid_fill edges=%he mat_nr=%i use_smooth=%b",
-	                  use_prepare ? BM_ELEM_TAG : BM_ELEM_SELECT, em->mat_nr, use_smooth))
+	                  "grid_fill edges=%he mat_nr=%i use_smooth=%b use_interp_simple=%b",
+	                  use_prepare ? BM_ELEM_TAG : BM_ELEM_SELECT,
+	                  em->mat_nr, use_smooth, use_interp_simple))
 	{
 		return OPERATOR_CANCELLED;
 	}
@@ -3066,6 +3068,7 @@
 	RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 	prop = RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "Number of sides (zero disables)", -100, 100);
 	RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+	RNA_def_boolean(ot->srna, "use_interp_simple", 0, "Simple Blending", "");
 }
 
 static int edbm_fill_holes_exec(bContext *C, wmOperator *op)




More information about the Bf-blender-cvs mailing list