Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2013-09-07 12:13:39 +0400
committerCampbell Barton <ideasman42@gmail.com>2013-09-07 12:13:39 +0400
commit0423d2b25256101b697c3007bb9b39a358ff50ce (patch)
tree441b6d6afdd26bd35442ab3302bc68f42d704083 /source
parent65fcc29d0c49ab8ef02bcae2aedab55da0bbde58 (diff)
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.
Diffstat (limited to 'source')
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c1
-rw-r--r--source/blender/bmesh/operators/bmo_fill_grid.c116
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c7
3 files changed, 83 insertions, 41 deletions
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index e6291cac241..0bd4907eab9 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -542,6 +542,7 @@ static BMOpDefine bmo_grid_fill_def = {
/* 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 */
diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c
index 35916c76e85..b0af0c0218b 100644
--- a/source/blender/bmesh/operators/bmo_fill_grid.c
+++ b/source/blender/bmesh/operators/bmo_fill_grid.c
@@ -154,25 +154,15 @@ static void bm_loop_pair_test_copy(BMLoop *l_pair_a[2], BMLoop *l_pair_b[2])
* 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 @@ static void bm_loop_interp_from_grid_boundary_2(BMesh *bm, BMLoop *l, BMLoop *l_
/**
+ * 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 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const
/* 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,6 +254,14 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const
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) {
@@ -279,7 +308,7 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const
/* place the vertex */
#ifdef BARYCENTRIC_INTERP
- {
+ if (use_interp_simple == false) {
float co_a[3], co_b[3];
barycentric_transform(
@@ -295,14 +324,17 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const
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;
@@ -310,13 +342,16 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const
/* 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 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const
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 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const
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 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const
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 @@ static void bm_grid_fill(BMesh *bm,
#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 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
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 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
/* 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:
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 75ff5256e10..757f1a83751 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -2983,6 +2983,7 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
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 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op)
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 @@ void MESH_OT_fill_grid(wmOperatorType *ot)
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)