diff options
author | Howard Trickey <howard.trickey@gmail.com> | 2014-05-29 15:32:16 +0400 |
---|---|---|
committer | Howard Trickey <howard.trickey@gmail.com> | 2014-05-29 15:32:16 +0400 |
commit | 6bde9a52f9270841331c7762a5df9505894d962a (patch) | |
tree | ce2166554d1f9dd8db7a204ffa1bbd87477e319b /source/blender/bmesh/tools/bmesh_bevel.c | |
parent | 6c721a86ffae49b7ce34b8a83fbe9346faefd043 (diff) |
Fix T39174 Bevel didn't maintain edge attributes.
When rebuilding the polygons that touch bevel-involved vertices,
need to copy the edge attributes from corresponding original edges.
Special treatment of corner segments, to maintain continuity of
smooth and seam attributes.
Another fix: if have four meeting edges, two opposite ones beveled
and the other two not, propgate the non-beveled-edges attributes
across the line that joins them (perpendicular to the bevel).
Diffstat (limited to 'source/blender/bmesh/tools/bmesh_bevel.c')
-rw-r--r-- | source/blender/bmesh/tools/bmesh_bevel.c | 125 |
1 files changed, 119 insertions, 6 deletions
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 1f3002e05f9..f436c1fc919 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -3082,19 +3082,24 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) BoundVert *v, *vstart, *vend; EdgeHalf *e, *eprev; VMesh *vm; - int i, k; + int i, k, n; bool do_rebuild = false; BMVert *bmv; + BMEdge *bme, *bme_new, *bme_prev; + BMFace *f_new; BMVert **vv = NULL; BMVert **vv_fix = NULL; + BMEdge **ee = NULL; BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE); BLI_array_staticdeclare(vv_fix, BM_DEFAULT_NGON_STACK_SIZE); + BLI_array_staticdeclare(ee, BM_DEFAULT_NGON_STACK_SIZE); BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { lprev = l->prev; bv = find_bevvert(bp, l->v); e = find_edge_half(bv, l->e); + bme = e->e; eprev = find_edge_half(bv, lprev->e); BLI_assert(e != NULL && eprev != NULL); vstart = eprev->leftv; @@ -3105,6 +3110,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) v = vstart; vm = bv->vmesh; BLI_array_append(vv, v->nv.v); + BLI_array_append(ee, bme); while (v != vend) { if (vm->mesh_kind == M_NONE && v->ebev && v->ebev->seg > 1 && v->ebev != e && v->ebev != eprev) { /* case of 3rd face opposite a beveled edge, with no vmesh */ @@ -3113,6 +3119,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) for (k = 1; k < e->seg; k++) { bmv = mesh_vert(vm, i, 0, k)->v; BLI_array_append(vv, bmv); + BLI_array_append(ee, bme); /* may want to merge UVs of these later */ if (!e->is_seam) BLI_array_append(vv_fix, bmv); @@ -3124,25 +3131,57 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) for (k = vm->seg - 1; k > 0; k--) { bmv = mesh_vert(vm, i, 0, k)->v; BLI_array_append(vv, bmv); + BLI_array_append(ee, bme); } } v = v->prev; BLI_array_append(vv, v->nv.v); + BLI_array_append(ee, bme); } do_rebuild = true; } else { BLI_array_append(vv, l->v); + BLI_array_append(ee, l->e); } } if (do_rebuild) { - BMFace *f_new = bev_create_ngon(bm, vv, BLI_array_count(vv), NULL, f, true); + n = BLI_array_count(vv); + f_new = bev_create_ngon(bm, vv, n, NULL, f, true); for (k = 0; k < BLI_array_count(vv_fix); k++) { bev_merge_uvs(bm, vv_fix[k]); } + /* copy attributes from old edges */ + BLI_assert(n == BLI_array_count(ee)); + bme_prev = ee[n - 1]; + for (k = 0; k < n; k++) { + bme_new = BM_edge_exists(vv[k], vv[(k + 1) % n]); + BLI_assert(ee[k] && bme_new); + if (ee[k] != bme_new) { + BM_elem_attrs_copy(bm, bm, ee[k], bme_new); + /* want to undo seam and smooth for corner segments + * if those attrs aren't contiguous around face */ + if (k < n - 1 && ee[k] == ee[k + 1]) { + if (BM_elem_flag_test(ee[k], BM_ELEM_SEAM) && + !BM_elem_flag_test(bme_prev, BM_ELEM_SEAM)) + { + BM_elem_flag_disable(bme_new, BM_ELEM_SEAM); + } + /* actually want "sharp" to be contiguous, so reverse the test */ + if (!BM_elem_flag_test(ee[k], BM_ELEM_SMOOTH) && + BM_elem_flag_test(bme_prev, BM_ELEM_SMOOTH)) + { + BM_elem_flag_enable(bme_new, BM_ELEM_SMOOTH); + } + } + else + bme_prev = ee[k]; + } + } + /* don't select newly created boundary faces... */ if (f_new) { BM_elem_flag_disable(f_new, BM_ELEM_TAG); @@ -3150,6 +3189,8 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) } BLI_array_free(vv); + BLI_array_free(vv_fix); + BLI_array_free(ee); return do_rebuild; } @@ -3243,6 +3284,70 @@ static void bev_merge_end_uvs(BMesh *bm, BevVert *bv, EdgeHalf *e) } /* + * Is this BevVert the special case of a weld (no vmesh) where there are + * four edges total, two are beveled, and the other two are on opposite sides? + */ +static bool bevvert_is_weld_cross(BevVert *bv) +{ + return (bv->edgecount == 4 && bv->selcount == 2 && + ((bv->edges[0].is_bev && bv->edges[2].is_bev) || + (bv->edges[1].is_bev && bv->edges[3].is_bev))); +} + +/* + * Copy edge attribute data across the non-beveled crossing edges of a cross weld. + * + * Situation looks like this: + * + * e->next + * | + * -------3------- + * -------2------- + * -------1------- e + * -------0------ + * | + * e->prev + * + * where e is the EdgeHalf of one of the beveled edges, + * e->next and e->prev are EdgeHalfs for the unbeveled edges of the cross + * and their attributes are to be copied to the edges 01, 12, 23. + * The vert i is mesh_vert(vm, vmindex, 0, i)->v + */ +static void weld_cross_attrs_copy(BMesh *bm, BevVert *bv, VMesh *vm, int vmindex, EdgeHalf *e) +{ + BMEdge *bme_prev, *bme_next, *bme; + int i, nseg; + bool disable_seam, enable_smooth; + + bme_prev = bme_next = NULL; + for (i = 0; i < 4; i++) { + if (&bv->edges[i] == e) { + bme_prev = bv->edges[(i + 3) % 4].e; + bme_next = bv->edges[(i + 1) % 4].e; + break; + } + } + BLI_assert(bme_prev && bme_next); + + /* want seams and sharp edges to cross only if that way on both sides */ + disable_seam = BM_elem_flag_test(bme_prev, BM_ELEM_SEAM) != BM_elem_flag_test(bme_next, BM_ELEM_SEAM); + enable_smooth = BM_elem_flag_test(bme_prev, BM_ELEM_SMOOTH) != BM_elem_flag_test(bme_next, BM_ELEM_SMOOTH); + + nseg = e->seg; + for (i = 0; i < nseg; i++) { + bme = BM_edge_exists(mesh_vert(vm, vmindex, 0, i)->v, + mesh_vert(vm, vmindex, 0, i + 1)->v); + BLI_assert(bme); + BM_elem_attrs_copy(bm, bm, bme_prev, bme); + if (disable_seam) + BM_elem_flag_disable(bme, BM_ELEM_SEAM); + if (enable_smooth) + BM_elem_flag_enable(bme, BM_ELEM_SMOOTH); + } +} + + +/* * Build the polygons along the selected Edge */ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) @@ -3286,15 +3391,15 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) f1 = e1->fprev; f2 = e1->fnext; + i1 = e1->leftv->index; + i2 = e2->leftv->index; + vm1 = bv1->vmesh; + vm2 = bv2->vmesh; if (nseg == 1) { bev_create_quad_straddle(bm, bmv1, bmv2, bmv3, bmv4, f1, f2, e1->is_seam); } else { - i1 = e1->leftv->index; - i2 = e2->leftv->index; - vm1 = bv1->vmesh; - vm2 = bv2->vmesh; bmv1i = bmv1; bmv2i = bmv2; odd = nseg % 2; @@ -3330,6 +3435,14 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) BLI_assert(bme1 && bme2); BM_elem_attrs_copy(bm, bm, bme, bme1); BM_elem_attrs_copy(bm, bm, bme, bme2); + + /* If either end is a "weld cross", want continuity of edge attributes across end edge(s) */ + if (bevvert_is_weld_cross(bv1)) { + weld_cross_attrs_copy(bm, bv1, vm1, i1, e1); + } + if (bevvert_is_weld_cross(bv2)) { + weld_cross_attrs_copy(bm, bv2, vm2, i2, e2); + } } /* Returns the square of the length of the chord from parameter u0 to parameter u1 |