Bevel: better attachment points for unbeveled edges, arc miter.

This commit is contained in:
2019-02-07 10:42:28 -05:00
parent 4c42e949e9
commit dec4f6d7ed
2 changed files with 98 additions and 43 deletions

View File

@@ -14,7 +14,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/** \file \ingroup bmesh
/** \file bmesh_bevel.c
*
* Main functions for beveling a BMesh (used by the tool and modifier)
*/
@@ -76,6 +76,7 @@ typedef struct EdgeHalf {
BMFace *fnext; /* face between this edge and next, if any */
struct BoundVert *leftv; /* left boundary vert (looking along edge to end) */
struct BoundVert *rightv; /* right boundary vert, if beveled */
int profile_index; /* offset into profile to attach non-beveled edge */
int seg; /* how many segments for the bevel */
float offset_l; /* offset for this edge, on left side */
float offset_r; /* offset for this edge, on right side */
@@ -2212,7 +2213,7 @@ static void adjust_miter_coords(BevelParams *bp, BevVert *bv, EdgeHalf *emiter)
adjust_bound_vert(v1, co1);
/* co3 is similar, but plane is through v3next and line is other side of miter edge */
emiter_other = v3->efirst;
emiter_other = v3->elast; /*v3->efirst;*/
vother = BM_edge_other_vert(emiter_other->e, bv->v);
sub_v3_v3v3(edge_dir, bv->v->co, vother->co);
normalize_v3(edge_dir);
@@ -2366,17 +2367,33 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
e3->leftv = e3->rightv = v;
}
ang_kind = edges_angle_kind(e, e2, bv->v);
/* Are we doing special mitering?
* ang_kind is -1, 0, 1 as angle is <, =, > 180 degrees.
* There can only be one outer reflex angle, so only one outer miter,
* and emiter will be set to the first edge of such an edge.
* A miter kind of BEVEL_MITER_SHARP means no special miter */
if ((miter_outer != BEVEL_MITER_SHARP && !emiter && ang_kind == 1) ||
(miter_inner != BEVEL_MITER_SHARP && ang_kind == -1))
{
if (ang_kind == 1)
emiter = e; /* a reflex angle, i.e., the (only) outer miter, if any */
emiter = e;
/* make one or two more boundverts; for now all will have same co */
v1 = v;
v1->ebev = NULL;
if (ang_kind == 1 && miter_outer == BEVEL_MITER_PATCH)
v2 = add_new_bound_vert(mem_arena, vm, co);
else
v2 = NULL;
v3 = add_new_bound_vert(mem_arena, vm, co);
v3->ebev = e2;
v3->efirst = e2;
v3->elast = e2;
v3->eon = NULL;
e2->leftv = v3;
if (ang_kind == 1 && miter_outer == BEVEL_MITER_PATCH) {
v1->is_patch_start = true;
v2 = add_new_bound_vert(mem_arena, vm, co);
v2->eon = v1->eon;
v2->sinratio = v1->sinratio;
v2->ebev = NULL;
@@ -2398,22 +2415,29 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
else {
v1->is_arc_start = true;
copy_v3_v3(v1->profile.midco, co);
v2 = NULL;
if (e->next == e2) {
v1->elast = v1->efirst;
}
else {
int between = nip + nnip;
int bet2 = between / 2;
bool betodd = (between % 2) == 1;
int i = 0;
/* Put first half of in-between edges at index 0,
* second half at index bp->seg.
* If between is odd, put middle one at midindex */
for (e3 = e->next; e3 != e2; e3 = e3->next) {
v1->elast = e3;
if (i < bet2)
e3->profile_index = 0;
else if (betodd && i == bet2)
e3->profile_index = bp->seg / 2;
else
e3->profile_index = bp->seg;
i++;
}
}
}
v3 = add_new_bound_vert(mem_arena, vm, co);
v3->ebev = e2;
v3->efirst = e2;
v3->elast = e2;
v3->eon = NULL;
e2->leftv = v3;
}
}
else {
@@ -4933,6 +4957,8 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
e->seg = 0;
}
e->is_rev = (bme->v2 == v);
e->leftv = e->rightv = NULL;
e->profile_index = 0;
}
/* now done with tag flag */
@@ -5059,9 +5085,9 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
BoundVert *v, *vstart, *vend;
EdgeHalf *e, *eprev;
VMesh *vm;
int i, k, n;
int i, k, n, kstart, kend;
bool do_rebuild = false;
bool go_ccw, corner3special, keep;
bool go_ccw, corner3special, keep, on_profile_start;
BMVert *bmv;
BMEdge *bme, *bme_new, *bme_prev;
BMFace *f_new, *f_other;
@@ -5108,56 +5134,85 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
go_ccw = false;
}
}
on_profile_start = false;
if (go_ccw) {
vstart = eprev->rightv;
vend = e->leftv;
if (e->profile_index > 0) {
vstart = vstart->prev;
on_profile_start = true;
}
}
else {
vstart = eprev->leftv;
vend = e->rightv;
if (eprev->profile_index > 0) {
vstart = vstart->next;
on_profile_start = true;
}
}
BLI_assert(vstart != NULL && vend != NULL);
v = vstart;
BLI_array_append(vv, v->nv.v);
BLI_array_append(ee, bme);
/* check for special case: multisegment 3rd face opposite a beveled edge with no vmesh */
corner3special = (vm->mesh_kind == M_NONE && v->ebev != e && v->ebev != eprev);
if (!on_profile_start) {
BLI_array_append(vv, v->nv.v);
BLI_array_append(ee, bme);
}
while (v != vend) {
/* check for special case: multisegment 3rd face opposite a beveled edge with no vmesh */
corner3special = (vm->mesh_kind == M_NONE && v->ebev != e && v->ebev != eprev);
if (go_ccw) {
if (vm->seg > 1) {
if (vm->mesh_kind == M_ADJ || bp->vertex_only || corner3special) {
i = v->index;
for (k = 1; k < vm->seg; k++) {
bmv = mesh_vert(vm, i, 0, k)->v;
BLI_array_append(vv, bmv);
BLI_array_append(ee, bme); /* TODO: maybe better edge here */
if (corner3special && v->ebev && !v->ebev->is_seam)
BLI_array_append(vv_fix, bmv);
}
i = v->index;
if (on_profile_start) {
kstart = e->profile_index;
on_profile_start = false;
}
else {
kstart = 1;
}
if (eprev->rightv == v && eprev->profile_index > 0) {
kend = eprev->profile_index;
}
else {
kend = vm->seg;
}
for (k = kstart; k <= kend; k++) {
bmv = mesh_vert(vm, i, 0, k)->v;
if (bmv) {
BLI_array_append(vv, bmv);
BLI_array_append(ee, bme); /* TODO: maybe better edge here */
if (corner3special && v->ebev && !v->ebev->is_seam && k != vm->seg)
BLI_array_append(vv_fix, bmv);
}
}
v = v->next;
}
else {
/* going cw */
if (vm->seg > 1) {
if (vm->mesh_kind == M_ADJ || bp->vertex_only ||
(vm->mesh_kind == M_NONE && v->ebev != e && v->ebev != eprev))
{
i = v->prev->index;
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);
if (corner3special && v->ebev && !v->ebev->is_seam)
BLI_array_append(vv_fix, bmv);
}
i = v->prev->index;
if (on_profile_start) {
kstart = eprev->profile_index;
on_profile_start = false;
}
else {
kstart = vm->seg - 1;
}
if (e->rightv == v->prev && e->profile_index > 0) {
kend = e->profile_index;
}
else {
kend = 0;
}
for (k = kstart; k >= kend; k--) {
bmv = mesh_vert(vm, i, 0, k)->v;
if (bmv) {
BLI_array_append(vv, bmv);
BLI_array_append(ee, bme);
if (corner3special && v->ebev && !v->ebev->is_seam && k != 0)
BLI_array_append(vv_fix, bmv);
}
}
v = v->prev;
}
BLI_array_append(vv, v->nv.v);
BLI_array_append(ee, bme);
}
do_rebuild = true;
}
@@ -6047,7 +6102,7 @@ void BM_mesh_bevel(
bp.use_weights = use_weights;
bp.loop_slide = loop_slide;
bp.limit_offset = limit_offset;
bp.offset_adjust = false; // DEBUG true;
bp.offset_adjust = false;
bp.dvert = dvert;
bp.vertex_group = vertex_group;
bp.mat_nr = mat;