diff options
author | Howard Trickey <howard.trickey@gmail.com> | 2013-11-10 16:31:57 +0400 |
---|---|---|
committer | Howard Trickey <howard.trickey@gmail.com> | 2013-11-10 16:31:57 +0400 |
commit | bfb9cefccbf8ff9733e9739e9c4dbc93a762bebe (patch) | |
tree | b5cfac9f94eb2ac52586084a633f7658e17d5058 /source/blender | |
parent | 73c2253ac629665715ec700b049e97fe1b17bc56 (diff) |
Added options for how bevel amount is measured.
Now there is an 'Offset Type' dropdown on tool
shelf with types:
Offset - current method, offset of new edge
from old along sliding face
Width - width of new bevel face (if segments=1)
Depth - amount a chamfering plane moves down
from original edge
Percent - percent of way sliding edges move
along their adjacent edges
The different options mainly are useful when
beveling more than one edge at once.
Leaving as a TODO to put these in the modifier,
as doing that has more permanent effects so
want to let users shake out problems with this
first.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_opdefines.c | 1 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_operators.h | 8 | ||||
-rw-r--r-- | source/blender/bmesh/operators/bmo_bevel.c | 9 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_bevel.c | 97 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_bevel.h | 2 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_bevel.c | 28 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_bevel.c | 3 |
7 files changed, 113 insertions, 35 deletions
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index ea533837b04..ef43d73d485 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1557,6 +1557,7 @@ static BMOpDefine bmo_bevel_def = { /* slots_in */ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input edges and vertices */ {"offset", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */ + {"offset_type", BMO_OP_SLOT_INT}, /* how to measure offset (enum) */ {"segments", BMO_OP_SLOT_INT}, /* number of segments in bevel */ {"vertex_only", BMO_OP_SLOT_BOOL}, /* only bevel vertices, not edges */ {{'\0'}}, diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index 56d63694d88..b3d97947cab 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -117,6 +117,14 @@ enum { BMOP_POKE_BOUNDS }; +/* Bevel offset_type slot values */ +enum { + BEVEL_AMT_OFFSET, + BEVEL_AMT_WIDTH, + BEVEL_AMT_DEPTH, + BEVEL_AMT_PERCENT +}; + extern const BMOpDefine *bmo_opdefines[]; extern const int bmo_opdefines_total; diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index eef470e0d85..4eec15d4d7e 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -35,9 +35,10 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) { - const float offset = BMO_slot_float_get(op->slots_in, "offset"); - const int seg = BMO_slot_int_get(op->slots_in, "segments"); - const bool vonly = BMO_slot_bool_get(op->slots_in, "vertex_only"); + const float offset = BMO_slot_float_get(op->slots_in, "offset"); + const int offset_type = BMO_slot_int_get(op->slots_in, "offset_type"); + const int seg = BMO_slot_int_get(op->slots_in, "segments"); + const bool vonly = BMO_slot_bool_get(op->slots_in, "vertex_only"); if (offset > 0) { BMOIter siter; @@ -58,7 +59,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) } } - BM_mesh_bevel(bm, offset, seg, vonly, false, false, NULL, -1); + BM_mesh_bevel(bm, offset, offset_type, seg, vonly, false, false, NULL, -1); BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); } diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index bb3fe129e0b..7293e400951 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -73,7 +73,8 @@ typedef struct EdgeHalf { struct BoundVert *leftv; /* left boundary vert (looking along edge to end) */ struct BoundVert *rightv; /* right boundary vert, if beveled */ int seg; /* how many segments for the bevel */ - float offset; /* offset for this edge */ + float offset_l; /* offset for this edge, on left side */ + float offset_r; /* offset for this edge, on right side */ bool is_bev; /* is this edge beveled? */ bool is_rev; /* is e->v2 the vertex at this end? */ bool is_seam; /* is e a seam for custom loopdata (e.g., UVs)? */ @@ -128,6 +129,7 @@ typedef struct BevelParams { MemArena *mem_arena; /* use for all allocs while bevel runs, if we need to free we can switch to mempool */ float offset; /* blender units to offset each side of a beveled edge */ + int offset_type; /* how offset is measured; enum defined in bmesh_operators.h */ int seg; /* number of segments in beveled edge profile */ bool vertex_only; /* bevel vertices only */ bool use_weights; /* bevel amount affected by weights on edges or verts */ @@ -469,7 +471,7 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, if (ang < 100.0f * BEVEL_EPSILON) { /* special case: e1 and e2 are parallel; put offset point perp to both, from v. * need to find a suitable plane. - * if offsets are different, we're out of luck: just use e1->offset */ + * if offsets are different, we're out of luck: just use e1->offset_r */ if (f) copy_v3_v3(norm_v, f->no); else @@ -477,14 +479,14 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, cross_v3_v3v3(norm_perp1, dir1, norm_v); normalize_v3(norm_perp1); copy_v3_v3(off1a, v->co); - madd_v3_v3fl(off1a, norm_perp1, e1->offset); + madd_v3_v3fl(off1a, norm_perp1, e1->offset_r); copy_v3_v3(meetco, off1a); } else if (fabsf(ang - (float)M_PI) < 100.0f * BEVEL_EPSILON) { /* special case e1 and e2 are antiparallel, so bevel is into * a zero-area face. Just make the offset point on the * common line, at offset distance from v. */ - slide_dist(e2, v, e2->offset, meetco); + slide_dist(e2, v, e2->offset_l, meetco); } else { /* get normal to plane where meet point should be */ @@ -504,10 +506,10 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, /* get points that are offset distances from each line, then another point on each line */ copy_v3_v3(off1a, v->co); - madd_v3_v3fl(off1a, norm_perp1, e1->offset); + madd_v3_v3fl(off1a, norm_perp1, e1->offset_r); add_v3_v3v3(off1b, off1a, dir1); copy_v3_v3(off2a, v->co); - madd_v3_v3fl(off2a, norm_perp2, e2->offset); + madd_v3_v3fl(off2a, norm_perp2, e2->offset_l); add_v3_v3v3(off2b, off2a, dir2); /* intersect the lines; by construction they should be on the same plane and not parallel */ @@ -552,10 +554,10 @@ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, /* get points that are offset distances from each line, then another point on each line */ copy_v3_v3(off1a, v->co); - madd_v3_v3fl(off1a, norm_perp1, e1->offset); + madd_v3_v3fl(off1a, norm_perp1, e1->offset_r); sub_v3_v3v3(off1b, off1a, dir1); copy_v3_v3(off2a, v->co); - madd_v3_v3fl(off2a, norm_perp2, e2->offset); + madd_v3_v3fl(off2a, norm_perp2, e2->offset_l); add_v3_v3v3(off2b, off2a, dir2); ang = angle_v3v3(dir1, dir2); @@ -564,7 +566,7 @@ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, copy_v3_v3(meetco, off1a); } else if (fabsf(ang - (float)M_PI) < 100.0f * BEVEL_EPSILON) { - slide_dist(e2, v, e2->offset, meetco); + slide_dist(e2, v, e2->offset_l, meetco); } else { iret = isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2); @@ -612,7 +614,7 @@ static void offset_in_plane(EdgeHalf *e, const float plane_no[3], int left, floa cross_v3_v3v3(fdir, no, dir); normalize_v3(fdir); copy_v3_v3(r, v->co); - madd_v3_v3fl(r, fdir, e->offset); + madd_v3_v3fl(r, fdir, left? e->offset_l : e->offset_r); } /* Calculate the point on e where line (co_a, co_b) comes closest to and return it in projco */ @@ -818,7 +820,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv) v->efirst = v->elast = e; e->rightv = v; /* make artifical extra point along unbeveled edge, and form triangle */ - slide_dist(e->next, bv->v, e->offset, co); + slide_dist(e->next, bv->v, e->offset_l, co); v = add_new_bound_vert(mem_arena, vm, co); v->efirst = v->elast = e->next; e->next->leftv = e->next->rightv = v; @@ -828,7 +830,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv) return; } - lastd = bp->vertex_only ? bv->offset : e->offset; + lastd = bp->vertex_only ? bv->offset : e->offset_l; vm->boundstart = NULL; do { if (e->is_bev) { @@ -1921,6 +1923,18 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv) } } +/* Return the angle between the two faces adjacent to e. + * If there are not two, return 0. */ +static float edge_face_angle(EdgeHalf *e) { + if (e->fprev && e->fnext) { + /* angle between faces is supplement of angle between face normals */ + return (float)M_PI - angle_normalized_v3v3(e->fprev->no, e->fnext->no); + } + else { + return 0.0f; + } +} + /* take care, this flag isn't cleared before use, it just so happens that its not set */ #define BM_BEVEL_EDGE_TAG_ENABLE(bme) BM_ELEM_API_FLAG_ENABLE( (bme), _FLAG_OVERLAP) #define BM_BEVEL_EDGE_TAG_DISABLE(bme) BM_ELEM_API_FLAG_DISABLE( (bme), _FLAG_OVERLAP) @@ -1937,7 +1951,7 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) BMFace *f; BMIter iter, iter2; EdgeHalf *e; - float weight; + float weight, z; int i, found_shared_face, ccw_test_sum; int nsel = 0; int ntot = 0; @@ -2053,16 +2067,6 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) e->seg = 0; } e->is_rev = (bme->v2 == v); - if (e->is_bev) { - e->offset = bp->offset; - if (bp->use_weights) { - weight = BM_elem_float_data_get(&bm->edata, bme, CD_BWEIGHT); - e->offset *= weight; - } - } - else { - e->offset = 0.0f; - } } /* find wrap-around shared face */ BM_ITER_ELEM (f, &iter2, bme, BM_FACES_OF_EDGE) { @@ -2098,6 +2102,50 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) for (i = 0, e = bv->edges; i < ntot; i++, e++) { e->next = &bv->edges[(i + 1) % ntot]; e->prev = &bv->edges[(i + ntot - 1) % ntot]; + + /* set offsets */ + if (e->is_bev) { + /* Convert distance as specified by user into offsets along + * faces on left side and right side of this edgehalf. + * Except for percent method, offset will be same on each side. */ + switch (bp->offset_type) { + case BEVEL_AMT_OFFSET: + e->offset_l = bp->offset; + break; + case BEVEL_AMT_WIDTH: + z = fabs(2.0f * sinf(edge_face_angle(e) / 2.0f)); + if (z < BEVEL_EPSILON) + e->offset_l = 0.01f * bp->offset; /* undefined behavior, so tiny bevel */ + else + e->offset_l = bp->offset / z; + break; + case BEVEL_AMT_DEPTH: + z = fabs(cosf(edge_face_angle(e) / 2.0f)); + if (z < BEVEL_EPSILON) + e->offset_l = 0.01f * bp->offset; /* undefined behavior, so tiny bevel */ + else + e->offset_l = bp->offset / z; + break; + case BEVEL_AMT_PERCENT: + e->offset_l = BM_edge_calc_length(e->prev->e) * bp->offset / 100.0f; + e->offset_r = BM_edge_calc_length(e->next->e) * bp->offset / 100.0f; + break; + default: + BLI_assert(!"bad bevel offset kind"); + e->offset_l = bp->offset; + } + if (bp->offset_type != BEVEL_AMT_PERCENT) + e->offset_r = e->offset_l; + if (bp->use_weights) { + weight = BM_elem_float_data_get(&bm->edata, bme, CD_BWEIGHT); + e->offset_l *= weight; + e->offset_r *= weight; + } + } + else { + e->offset_l = e->offset_r = 0.0f; + } + BM_BEVEL_EDGE_TAG_DISABLE(e->e); if (e->fprev && e->fnext) e->is_seam = !contig_ldata_across_edge(bm, e->e, e->fprev, e->fnext); @@ -2370,7 +2418,7 @@ static float bevel_limit_offset(BMesh *bm, BevelParams *bp) * * \warning all tagged edges _must_ be manifold. */ -void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, +void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, const float segments, const bool vertex_only, const bool use_weights, const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group) { @@ -2380,6 +2428,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, BevelParams bp = {NULL}; bp.offset = offset; + bp.offset_type = offset_type; bp.seg = segments; bp.vertex_only = vertex_only; bp.use_weights = use_weights; diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h index bee26357aca..9897b6b070c 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.h +++ b/source/blender/bmesh/tools/bmesh_bevel.h @@ -29,7 +29,7 @@ struct MDeformVert; -void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, +void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, const float segments, const bool vertex_only, const bool use_weights, const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group); diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index dd3aacb2d67..7e1293ee043 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -131,6 +131,7 @@ static bool edbm_bevel_calc(wmOperator *op) BMEditMesh *em = opdata->em; BMOperator bmop; const float offset = RNA_float_get(op->ptr, "offset"); + const int offset_type = RNA_enum_get(op->ptr, "offset_type"); const int segments = RNA_int_get(op->ptr, "segments"); const bool vertex_only = RNA_boolean_get(op->ptr, "vertex_only"); @@ -140,8 +141,8 @@ static bool edbm_bevel_calc(wmOperator *op) } EDBM_op_init(em, &bmop, op, - "bevel geom=%hev offset=%f segments=%i vertex_only=%b", - BM_ELEM_SELECT, offset, segments, vertex_only); + "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i", + BM_ELEM_SELECT, offset, segments, vertex_only, offset_type); BMO_op_exec(em->bm, &bmop); @@ -256,12 +257,14 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event) static float edbm_bevel_mval_factor(wmOperator *op, const wmEvent *event) { BevelData *opdata = op->customdata; - int use_dist = true; + bool use_dist = true; + bool is_percent = false; float mdiff[2]; float factor; mdiff[0] = opdata->mcenter[0] - event->mval[0]; mdiff[1] = opdata->mcenter[1] - event->mval[1]; + is_percent = (RNA_int_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT); if (use_dist) { factor = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length) * opdata->pixel_size; @@ -286,7 +289,13 @@ static float edbm_bevel_mval_factor(wmOperator *op, const wmEvent *event) if (factor < 0.0f) factor = 0.0f; } else { - CLAMP(factor, 0.0f, 1.0f); + if (is_percent) { + factor *= 100.0f; + CLAMP(factor, 0.0f, 100.0f); + } + else { + CLAMP(factor, 0.0f, 1.0f); + } } return factor; @@ -361,6 +370,14 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event) void MESH_OT_bevel(wmOperatorType *ot) { + static EnumPropertyItem offset_type_items[] = { + {BEVEL_AMT_OFFSET, "OFFSET", 0, "Offset", "Amount is offset of new edges from original"}, + {BEVEL_AMT_WIDTH, "WIDTH", 0, "Width", "Amount is width of new face"}, + {BEVEL_AMT_DEPTH, "DEPTH", 0, "Depth", "Amount is perpendicular distance from original edge to bevel face"}, + {BEVEL_AMT_PERCENT, "PERCENT", 0, "Percent", "Amount is percent of adjacent edge length"}, + {0, NULL, 0, NULL, NULL}, + }; + /* identifiers */ ot->name = "Bevel"; ot->description = "Edge Bevel"; @@ -376,7 +393,8 @@ void MESH_OT_bevel(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; - RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Offset", "", 0.0f, 1.0f); + RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Amount Type", "What distance Amount measures"); + RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Amount", "", 0.0f, 1.0f); RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8); RNA_def_boolean(ot->srna, "vertex_only", false, "Vertex only", "Bevel only vertices"); } diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index 326ffba3e2e..6a1de92f9b2 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -158,7 +158,8 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *ob, } } - BM_mesh_bevel(bm, bmd->value, bmd->res, + /* TODO: add offset_kind to modifier properties to, and pass in as 3rd arg here */ + BM_mesh_bevel(bm, bmd->value, 0, bmd->res, vertex_only, bmd->lim_flags & MOD_BEVEL_WEIGHT, do_clamp, dvert, vgroup); |