diff options
Diffstat (limited to 'source/blender/bmesh/operators/bmo_subdivide.c')
-rw-r--r-- | source/blender/bmesh/operators/bmo_subdivide.c | 209 |
1 files changed, 109 insertions, 100 deletions
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index fc507cdbd21..45e3c8d193d 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -32,6 +32,7 @@ #include "BLI_rand.h" #include "BLI_array.h" #include "BLI_noise.h" +#include "BLI_stack.h" #include "BKE_customdata.h" @@ -79,8 +80,9 @@ static void bmo_subd_init_shape_info(BMesh *bm, SubDParams *params) } -typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts, - const SubDParams *params); +typedef void (*subd_pattern_fill_fp)( + BMesh *bm, BMFace *face, BMVert **verts, + const SubDParams *params); /* * note: this is a pattern-based edge subdivider. @@ -162,10 +164,11 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v_a, BMVert *v_b, BMFace return NULL; } /* calculates offset for co, based on fractal, sphere or smooth settings */ -static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params, float perc, - BMVert *vsta, BMVert *vend) +static void alter_co( + BMVert *v, BMEdge *UNUSED(e_orig), + const SubDParams *params, const float perc, + const BMVert *v_a, const BMVert *v_b) { - float tvec[3], fac; float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp); int i; @@ -177,28 +180,26 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params } else if (params->use_smooth) { /* we calculate an offset vector vec1[], to be added to *co */ - float len, nor[3], nor1[3], nor2[3], val; + float dir[3], tvec[3]; + float fac, len, val; - sub_v3_v3v3(nor, vsta->co, vend->co); - len = 0.5f * normalize_v3(nor); - - copy_v3_v3(nor1, vsta->no); - copy_v3_v3(nor2, vend->no); + sub_v3_v3v3(dir, v_a->co, v_b->co); + len = (float)M_SQRT1_2 * normalize_v3(dir); /* cosine angle */ - fac = dot_v3v3(nor, nor1); - mul_v3_v3fl(tvec, nor1, fac); + fac = dot_v3v3(dir, v_a->no); + mul_v3_v3fl(tvec, v_a->no, fac); /* cosine angle */ - fac = -dot_v3v3(nor, nor2); - madd_v3_v3fl(tvec, nor2, fac); + fac = -dot_v3v3(dir, v_b->no); + madd_v3_v3fl(tvec, v_b->no, fac); /* falloff for multi subdivide */ val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc)); val = bmesh_subd_falloff_calc(params->smooth_falloff, val); if (params->use_smooth_even) { - val *= BM_vert_calc_shell_factor(v); + val *= shell_v3v3_mid_normalized_to_dist(v_a->no, v_b->no); } mul_v3_fl(tvec, params->smooth * val * len); @@ -207,12 +208,13 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params } if (params->use_fractal) { - const float len = len_v3v3(vsta->co, vend->co); - float normal[3], co2[3], base1[3], base2[3]; + float normal[3], co2[3], base1[3], base2[3], tvec[3]; + const float len = len_v3v3(v_a->co, v_b->co); + float fac; fac = params->fractal * len; - mid_v3_v3v3(normal, vsta->no, vend->no); + mid_v3_v3v3(normal, v_a->no, v_b->no); ortho_basis_v3v3_v3(base1, base2, normal); add_v3_v3v3(co2, v->co, params->fractal_ofs); @@ -233,9 +235,12 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params * this by getting the normals and coords for each shape key and * re-calculate the smooth value for each but this is quite involved. * for now its ok to simply apply the difference IMHO - campbell */ - sub_v3_v3v3(tvec, v->co, co); if (params->shape_info.totlayer > 1) { + float tvec[3]; + + sub_v3_v3v3(tvec, v->co, co); + /* skip the last layer since its the temp */ i = params->shape_info.totlayer - 1; co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset); @@ -249,19 +254,21 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params /* assumes in the edge is the correct interpolated vertices already */ /* percent defines the interpolation, rad and flag are for special options */ /* results in new vertex with correct coordinate, vertex normal and weight group info */ -static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *oedge, - const SubDParams *params, float percent, - float percent2, - BMEdge **out, BMVert *vsta, BMVert *vend) +static BMVert *bm_subdivide_edge_addvert( + BMesh *bm, BMEdge *edge, BMEdge *e_orig, + const SubDParams *params, + const float factor_edge_split, const float factor_subd, + BMVert *v_a, BMVert *v_b, + BMEdge **r_edge) { - BMVert *ev; + BMVert *v_new; - ev = BM_edge_split(bm, edge, edge->v1, out, percent); + v_new = BM_edge_split(bm, edge, edge->v1, r_edge, factor_edge_split); - BMO_elem_flag_enable(bm, ev, ELE_INNER); + BMO_elem_flag_enable(bm, v_new, ELE_INNER); /* offset for smooth or sphere or fractal */ - alter_co(ev, oedge, params, percent2, vsta, vend); + alter_co(v_new, e_orig, params, factor_subd, v_a, v_b); #if 0 //BMESH_TODO /* clip if needed by mirror modifier */ @@ -278,35 +285,40 @@ static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *oedge, } #endif - interp_v3_v3v3(ev->no, vsta->no, vend->no, percent2); - normalize_v3(ev->no); + interp_v3_v3v3(v_new->no, v_a->no, v_b->no, factor_subd); + normalize_v3(v_new->no); - return ev; + return v_new; } -static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge, - int curpoint, int totpoint, const SubDParams *params, - BMEdge **newe, BMVert *vsta, BMVert *vend) +static BMVert *subdivide_edge_num( + BMesh *bm, BMEdge *edge, BMEdge *e_orig, + int curpoint, int totpoint, const SubDParams *params, + BMVert *v_a, BMVert *v_b, + BMEdge **r_edge) { - BMVert *ev; - float percent, percent2 = 0.0f; + BMVert *v_new; + float factor_edge_split, factor_subd; if (BMO_elem_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) { - percent = BMO_slot_map_float_get(params->slot_edge_percents, edge); + factor_edge_split = BMO_slot_map_float_get(params->slot_edge_percents, edge); + factor_subd = 0.0f; } else { - percent = 1.0f / (float)(totpoint + 1 - curpoint); - percent2 = (float)(curpoint + 1) / (float)(totpoint + 1); - + factor_edge_split = 1.0f / (float)(totpoint + 1 - curpoint); + factor_subd = (float)(curpoint + 1) / (float)(totpoint + 1); } - ev = bm_subdivide_edge_addvert(bm, edge, oedge, params, percent, - percent2, newe, vsta, vend); - return ev; + v_new = bm_subdivide_edge_addvert( + bm, edge, e_orig, params, + factor_edge_split, factor_subd, + v_a, v_b, r_edge); + return v_new; } -static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *params, - BMVert *vsta, BMVert *vend) +static void bm_subdivide_multicut( + BMesh *bm, BMEdge *edge, const SubDParams *params, + BMVert *v_a, BMVert *v_b) { BMEdge *eed = edge, *e_new, e_tmp = *edge; BMVert *v, v1_tmp = *edge->v1, v2_tmp = *edge->v2, *v1 = edge->v1, *v2 = edge->v2; @@ -316,15 +328,11 @@ static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *par e_tmp.v2 = &v2_tmp; for (i = 0; i < numcuts; i++) { - v = subdivideedgenum(bm, eed, &e_tmp, i, params->numcuts, params, &e_new, vsta, vend); - - BMO_elem_flag_enable(bm, v, SUBD_SPLIT); - BMO_elem_flag_enable(bm, eed, SUBD_SPLIT); - BMO_elem_flag_enable(bm, e_new, SUBD_SPLIT); + v = subdivide_edge_num(bm, eed, &e_tmp, i, params->numcuts, params, v_a, v_b, &e_new); - BMO_elem_flag_enable(bm, v, ELE_SPLIT); - BMO_elem_flag_enable(bm, eed, ELE_SPLIT); - BMO_elem_flag_enable(bm, e_new, SUBD_SPLIT); + BMO_elem_flag_enable(bm, v, SUBD_SPLIT | ELE_SPLIT); + BMO_elem_flag_enable(bm, eed, SUBD_SPLIT | ELE_SPLIT); + BMO_elem_flag_enable(bm, e_new, SUBD_SPLIT | ELE_SPLIT); BM_CHECK_ELEMENT(v); if (v->e) BM_CHECK_ELEMENT(v->e); @@ -437,7 +445,7 @@ static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert * e = connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new); e_tmp = *e; - v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, &e_new, e->v1, e->v2); + v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, e->v1, e->v2, &e_new); if (i != numcuts - 1) { connect_smallest_face(bm, v_last, v, &f_new); @@ -580,8 +588,7 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts e_tmp = *e; for (a = 0; a < numcuts; a++) { - v = subdivideedgenum(bm, e, &e_tmp, a, numcuts, params, &e_new, - v1, v2); + v = subdivide_edge_num(bm, e, &e_tmp, a, numcuts, params, v1, v2, &e_new); BMESH_ASSERT(v != NULL); @@ -688,8 +695,7 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, e_tmp.v1 = &v1_tmp; e_tmp.v2 = &v2_tmp; for (j = 0; j < i; j++) { - v = subdivideedgenum(bm, e, &e_tmp, j, i, params, &e_new, - verts[a], verts[b]); + v = subdivide_edge_num(bm, e, &e_tmp, j, i, params, verts[a], verts[b], &e_new); lines[i + 1][j + 1] = v; BMO_elem_flag_enable(bm, e_new, ELE_INNER); @@ -766,8 +772,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BMOpSlot *einput; const SubDPattern *pat; SubDParams params; - SubDFaceData *facedata = NULL; - BLI_array_declare(facedata); + BLI_Stack *facedata; BMIter viter, fiter, liter; BMVert *v, **verts = NULL; BMEdge *edge; @@ -782,7 +787,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BLI_array_declare(verts); float smooth, fractal, along_normal; bool use_sphere, use_single_edge, use_grid_fill, use_only_quads; - int cornertype, seed, i, j, matched, a, b, numcuts, totesel, smooth_falloff; + int cornertype, seed, i, j, a, b, numcuts, totesel, smooth_falloff; BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT); @@ -802,13 +807,13 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) patterns[1] = NULL; /* straight cut is patterns[1] == NULL */ switch (cornertype) { - case SUBD_PATH: + case SUBD_CORNER_PATH: patterns[1] = &quad_2edge_path; break; - case SUBD_INNERVERT: + case SUBD_CORNER_INNERVERT: patterns[1] = &quad_2edge_innervert; break; - case SUBD_FAN: + case SUBD_CORNER_FAN: patterns[1] = &quad_2edge_fan; break; } @@ -875,9 +880,12 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BM_EDGE, EDGE_PERCENT); + facedata = BLI_stack_new(sizeof(SubDFaceData), __func__); + BM_ITER_MESH (face, &fiter, bm, BM_FACES_OF_MESH) { BMEdge *e1 = NULL, *e2 = NULL; float vec1[3], vec2[3]; + bool matched = false; /* skip non-quads if requested */ if (use_only_quads && face->len != 4) @@ -891,8 +899,6 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BLI_array_grow_items(edges, face->len); BLI_array_grow_items(verts, face->len); - matched = 0; - totesel = 0; BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, i) { edges[i] = l_new->e; @@ -930,12 +936,13 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } } if (matched) { - BLI_array_grow_one(facedata); - b = BLI_array_count(facedata) - 1; - facedata[b].pat = pat; - facedata[b].start = verts[i]; - facedata[b].face = face; - facedata[b].totedgesel = totesel; + SubDFaceData *fd; + + fd = BLI_stack_push_r(facedata); + fd->pat = pat; + fd->start = verts[i]; + fd->face = face; + fd->totedgesel = totesel; BMO_elem_flag_enable(bm, face, SUBD_SPLIT); break; } @@ -966,15 +973,15 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } } if (matched) { - BLI_array_grow_one(facedata); - j = BLI_array_count(facedata) - 1; + SubDFaceData *fd; BMO_elem_flag_enable(bm, face, SUBD_SPLIT); - facedata[j].pat = pat; - facedata[j].start = verts[a]; - facedata[j].face = face; - facedata[j].totedgesel = totesel; + fd = BLI_stack_push_r(facedata); + fd->pat = pat; + fd->start = verts[a]; + fd->face = face; + fd->totedgesel = totesel; break; } } @@ -982,16 +989,16 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } if (!matched && totesel) { - BLI_array_grow_one(facedata); - j = BLI_array_count(facedata) - 1; + SubDFaceData *fd; BMO_elem_flag_enable(bm, face, SUBD_SPLIT); /* must initialize all members here */ - facedata[j].start = NULL; - facedata[j].pat = NULL; - facedata[j].totedgesel = totesel; - facedata[j].face = face; + fd = BLI_stack_push_r(facedata); + fd->start = NULL; + fd->pat = NULL; + fd->totedgesel = totesel; + fd->face = face; } } @@ -1009,16 +1016,17 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) copy_v3_v3(v->co, co); } - i = 0; - for (i = 0; i < BLI_array_count(facedata); i++) { - face = facedata[i].face; + for (; !BLI_stack_is_empty(facedata); BLI_stack_discard(facedata)) { + SubDFaceData *fd = BLI_stack_peek(facedata); + + face = fd->face; /* figure out which pattern to use */ BLI_array_empty(verts); - pat = facedata[i].pat; + pat = fd->pat; - if (!pat && facedata[i].totedgesel == 2) { + if (!pat && fd->totedgesel == 2) { int vlen; /* ok, no pattern. we still may be able to do something */ @@ -1079,7 +1087,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BMIter other_fiter; BM_ITER_ELEM (other_loop, &other_fiter, loops[a]->v, BM_LOOPS_OF_VERT) { if (other_loop->f != face) { - if (BM_vert_in_face(other_loop->f, loops[b]->v)) { + if (BM_vert_in_face(loops[b]->v, other_loop->f)) { /* we assume that these verts are not making an edge in the face */ BLI_assert(other_loop->prev->v != loops[a]->v); BLI_assert(other_loop->next->v != loops[a]->v); @@ -1131,7 +1139,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) a = 0; BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, j) { - if (l_new->v == facedata[i].start) { + if (l_new->v == fd->start) { a = j + 1; break; } @@ -1156,7 +1164,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, params.shape_info.tmpkey); - if (facedata) BLI_array_free(facedata); + BLI_stack_free(facedata); if (edges) BLI_array_free(edges); if (verts) BLI_array_free(verts); BLI_array_free(loops_split); @@ -1169,14 +1177,15 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } /* editmesh-emulating function */ -void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, - const float smooth, const short smooth_falloff, const bool use_smooth_even, - const float fractal, const float along_normal, - const int numcuts, - const int seltype, const int cornertype, - const short use_single_edge, const short use_grid_fill, - const short use_only_quads, - const int seed) +void BM_mesh_esubdivide( + BMesh *bm, const char edge_hflag, + const float smooth, const short smooth_falloff, const bool use_smooth_even, + const float fractal, const float along_normal, + const int numcuts, + const int seltype, const int cornertype, + const short use_single_edge, const short use_grid_fill, + const short use_only_quads, + const int seed) { BMOperator op; |