Bevel: better attachment points for unbeveled edges, arc miter.
authorHoward Trickey <howard.trickey@gmail.com>
Thu, 7 Feb 2019 15:42:28 +0000 (10:42 -0500)
committerHoward Trickey <howard.trickey@gmail.com>
Thu, 7 Feb 2019 15:42:28 +0000 (10:42 -0500)
source/blender/bmesh/tools/bmesh_bevel.c
source/blender/bmesh/tools/bmesh_bevel.h

index 5dea6da7b1d3ffc921fa7826f8aaed64083fd270..5833e3427a4f88a1b74a3e1ee2eefcb9fedc0dd8 100644 (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;
index 9d8e4de2772bfb229a49a52944eb612d8aee9d64..bb4c3191c4b9c9107a205c4ef6d850d1fc38f3f3 100644 (file)
@@ -17,7 +17,7 @@
 #ifndef __BMESH_BEVEL_H__
 #define __BMESH_BEVEL_H__
 
-/** \file \ingroup bmesh
+/** \file bmesh_bevel.h
  */
 
 struct MDeformVert;