diff options
author | Howard Trickey <howard.trickey@gmail.com> | 2019-01-07 02:12:00 +0300 |
---|---|---|
committer | Howard Trickey <howard.trickey@gmail.com> | 2019-01-07 02:12:00 +0300 |
commit | 496f6adce29cd0da2f91cb574ca396679aa35645 (patch) | |
tree | b854406a89fc31d7dfcaf754a42a020ad53b33f6 /source/blender | |
parent | b4a77a351e31256c91e573b85b7252e3ca6d61e7 (diff) |
Better bevel normal hardening when some faces were smooth.
Harden normals causes normal splitting, which will not give the
appearance expected due to autosmooth unless some edges are sharpened,
so this change fixes that. Also bevel tool will turn on autosmooth
if not already on if hardening normals.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_opdefines.c | 1 | ||||
-rw-r--r-- | source/blender/bmesh/operators/bmo_bevel.c | 3 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_bevel.c | 47 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_bevel.h | 2 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_bevel.c | 16 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_bevel.c | 9 |
6 files changed, 70 insertions, 8 deletions
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 2cae6fb3823..db4985c62f6 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1765,6 +1765,7 @@ static BMOpDefine bmo_bevel_def = { {"harden_normals", BMO_OP_SLOT_BOOL}, /* harden normals */ {"face_strength_mode", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_bevel_face_strength_type}, /* whether to set face strength, and which faces to set if so */ + {"smoothresh", BMO_OP_SLOT_FLT}, /* for passing mesh's smoothresh, used in hardening */ {{'\0'}}, }, /* slots_out */ diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index 1ef8531397f..3277824b890 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -47,6 +47,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) const bool mark_sharp = BMO_slot_bool_get(op->slots_in, "mark_sharp"); const bool harden_normals = BMO_slot_bool_get(op->slots_in, "harden_normals"); const int face_strength_mode = BMO_slot_int_get(op->slots_in, "face_strength_mode"); + const float smoothresh = BMO_slot_float_get(op->slots_in, "smoothresh"); if (offset > 0) { BMOIter siter; @@ -72,7 +73,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) BM_mesh_bevel( bm, offset, offset_type, seg, profile, vonly, false, clamp_overlap, NULL, -1, material, - loop_slide, mark_seam, mark_sharp, harden_normals, face_strength_mode); + loop_slide, mark_seam, mark_sharp, harden_normals, face_strength_mode, smoothresh); BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_TAG); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 7149df7dc4e..452dfa22993 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -222,6 +222,7 @@ typedef struct BevelParams { int vertex_group; /* vertex group index, maybe set if vertex_only */ int mat_nr; /* if >= 0, material number for bevel; else material comes from adjacent faces */ int face_strength_mode; /* setting face strength if > 0 */ + float smoothresh; /* mesh's smoothresh, used if hardening */ } BevelParams; // #pragma GCC diagnostic ignored "-Wpadded" @@ -1703,6 +1704,33 @@ static void bevel_extend_edge_data(BevVert *bv) } while (bcur != start); } +/* Mark edges as sharp if they are between a smooth recon face and a new face. */ +static void bevel_edges_sharp_boundary(BMesh *bm, BevelParams *bp) +{ + BMIter fiter, liter; + BMFace *f, *fother; + BMLoop *l, *lother; + FKind fkind; + + BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) { + if (!BM_elem_flag_test(f, BM_ELEM_SMOOTH)) + continue; + if (get_face_kind(bp, f) != F_RECON) + continue; + BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) { + /* cases we care about will have exactly one adjacent face */ + lother = l->radial_next; + fother = lother->f; + if (lother != l && fother) { + fkind = get_face_kind(bp, lother->f); + if (ELEM(fkind, F_EDGE, F_VERT)) { + BM_elem_flag_disable(l->e, BM_ELEM_SMOOTH); + } + } + } + } +} + /* * Harden normals for bevel. * The desired effect is that the newly created F_EDGE and F_VERT faces appear smoothly shaded @@ -1725,11 +1753,25 @@ static void bevel_harden_normals(BMesh *bm, BevelParams *bp) return; /* recalculate all face and vertex normals; side effect: ensures vertex, edge, face indices */ + /* I suspect this is not necessary: TODO: test that guess */ BM_mesh_normals_update(bm); + cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); + + /* If there is not already a custom split normal layer then making one (with BM_lnorspace_update) + * will not respect the autosmooth angle between smooth faces. To get that to happen, we have + * to mark the sharpen the edges that are only sharp because of the angle test -- otherwise would be smooth. + */ + if (cd_clnors_offset == -1) { + BM_edges_sharp_from_angle_set(bm, bp->smoothresh); + bevel_edges_sharp_boundary(bm, bp); + } + /* ensure that bm->lnor_spacearr has properly stored loop normals; side effect: ensures loop indices */ BM_lnorspace_update(bm); - cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); + + if (cd_clnors_offset == -1) + cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL); BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) { fkind = get_face_kind(bp, f); @@ -5677,7 +5719,7 @@ void BM_mesh_bevel( const bool vertex_only, const bool use_weights, const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group, const int mat, const bool loop_slide, const bool mark_seam, const bool mark_sharp, - const bool harden_normals, const int face_strength_mode) + const bool harden_normals, const int face_strength_mode, const float smoothresh) { BMIter iter, liter; BMVert *v, *v_next; @@ -5704,6 +5746,7 @@ void BM_mesh_bevel( bp.mark_sharp = mark_sharp; bp.harden_normals = harden_normals; bp.face_strength_mode = face_strength_mode; + bp.smoothresh = smoothresh; bp.face_hash = NULL; if (profile >= 0.950f) { /* r ~ 692, so PRO_SQUARE_R is 1e4 */ diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h index 2bfa2be8f1c..36a80ee5e25 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.h +++ b/source/blender/bmesh/tools/bmesh_bevel.h @@ -34,6 +34,6 @@ void BM_mesh_bevel( const float profile, const bool vertex_only, const bool use_weights, const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group, const int mat, const bool loop_slide, const bool mark_seam, const bool mark_sharp, - const bool harden_normals, const int face_strength_mode); + const bool harden_normals, const int face_strength_mode, const float smoothresh); #endif /* __BMESH_BEVEL_H__ */ diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index ff259f01f64..0d99c433c11 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -41,6 +41,8 @@ #include "BKE_layer.h" #include "BKE_mesh.h" +#include "DNA_mesh_types.h" + #include "RNA_define.h" #include "RNA_access.h" @@ -231,6 +233,7 @@ static bool edbm_bevel_calc(wmOperator *op) const bool harden_normals = RNA_boolean_get(op->ptr, "harden_normals"); const int face_strength_mode = RNA_enum_get(op->ptr, "face_strength_mode"); + for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { em = opdata->ob_store[ob_index].em; @@ -243,12 +246,21 @@ static bool edbm_bevel_calc(wmOperator *op) material = CLAMPIS(material, -1, em->ob->totcol - 1); } + Mesh *me = em->ob->data; + + if (harden_normals && !(me->flag & ME_AUTOSMOOTH)) { + /* harden_normals only has a visible effect if autosmooth is on, so turn it on */ + me->flag |= ME_AUTOSMOOTH; + } + EDBM_op_init( em, &bmop, op, "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f clamp_overlap=%b " - "material=%i loop_slide=%b mark_seam=%b mark_sharp=%b harden_normals=%b face_strength_mode=%i", + "material=%i loop_slide=%b mark_seam=%b mark_sharp=%b harden_normals=%b face_strength_mode=%i " + "smoothresh=%f", BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile, - clamp_overlap, material, loop_slide, mark_seam, mark_sharp, harden_normals, face_strength_mode); + clamp_overlap, material, loop_slide, mark_seam, mark_sharp, harden_normals, face_strength_mode, + me->smoothresh); BMO_op_exec(em->bm, &bmop); diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index e63b5407a74..363cdb083d4 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -116,7 +116,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes const bool loop_slide = (bmd->flags & MOD_BEVEL_EVEN_WIDTHS) == 0; const bool mark_seam = (bmd->edge_flags & MOD_BEVEL_MARK_SEAM); const bool mark_sharp = (bmd->edge_flags & MOD_BEVEL_MARK_SHARP); - const bool harden_normals = (bmd->flags & MOD_BEVEL_HARDEN_NORMALS); + bool harden_normals = (bmd->flags & MOD_BEVEL_HARDEN_NORMALS); const int face_strength_mode = bmd->face_str_mode; bm = BKE_mesh_to_bmesh_ex( @@ -187,10 +187,15 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes } } + if (harden_normals && !(((Mesh *)ctx->object->data)->flag & ME_AUTOSMOOTH)) { + modifier_setError(md, "Enable 'Auto Smooth' option in mesh settings for hardening"); + harden_normals = false; + } + BM_mesh_bevel(bm, bmd->value, offset_type, bmd->res, bmd->profile, vertex_only, bmd->lim_flags & MOD_BEVEL_WEIGHT, do_clamp, dvert, vgroup, mat, loop_slide, mark_seam, mark_sharp, - harden_normals, face_strength_mode); + harden_normals, face_strength_mode, mesh->smoothresh); result = BKE_mesh_from_bmesh_for_eval_nomain(bm, 0); |