diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-04-19 23:03:15 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-04-19 23:03:15 +0400 |
commit | e387ccdb427030927bb2cf9552c3ce6eb6ffa6b7 (patch) | |
tree | dfacf75746f50a381fd41e67fa65bfe97d6ac687 | |
parent | c7f8af329bb6c8cf7eeaa480269d75f86de9b896 (diff) |
bmesh inset: add depth option (make use of relative and even offset options)
-rw-r--r-- | source/blender/bmesh/intern/bmesh_opdefines.c | 1 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_queries.c | 20 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_queries.h | 1 | ||||
-rw-r--r-- | source/blender/bmesh/operators/bmo_inset.c | 57 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_tools.c | 13 |
5 files changed, 87 insertions, 5 deletions
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 5896a18223a..98d2b31e57c 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1099,6 +1099,7 @@ static BMOpDefine bmo_inset_def = { {BMO_OP_SLOT_BOOL, "use_even_offset"}, {BMO_OP_SLOT_BOOL, "use_relative_offset"}, {BMO_OP_SLOT_FLT, "thickness"}, + {BMO_OP_SLOT_FLT, "depth"}, {BMO_OP_SLOT_BOOL, "use_outset"}, {0} /* null-terminating sentinel */}, bmo_inset_exec, diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index af614f78aff..09cd6a2f96b 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -867,6 +867,26 @@ float BM_vert_edge_angle(BMVert *v) } /** + * \note this isn't optimal to run on an array of verts, + * see 'solidify_add_thickness' for a function which runs on an array. + */ +float BM_vert_shell_factor(BMVert *v) +{ + BMIter iter; + BMLoop *l; + float accum_shell = 0.0f; + float accum_angle = 0.0f; + + BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { + const float face_angle = BM_loop_face_angle(l); + accum_shell += shell_angle_to_dist(angle_normalized_v3v3(v->no, l->f->no)) * face_angle; + accum_angle += face_angle; + } + + return accum_shell / accum_angle; +} + +/** * Returns the edge existing between v1 and v2, or NULL if there isn't one. * * \note multiple edges may exist between any two vertices, and therefore diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 73d724c7bdd..d69a57bdb40 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -65,6 +65,7 @@ float BM_edge_face_angle(BMEdge *e); void BM_edge_face_tangent(BMEdge *e, BMLoop *e_loop, float r_tangent[3]); float BM_vert_edge_angle(BMVert *v); +float BM_vert_shell_factor(BMVert *v); BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2); diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index 4e4ea655414..c6fc173148f 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -80,6 +80,22 @@ static BMLoop *bm_edge_is_mixed_face_tag(BMLoop *l) } } +float bm_vert_avg_tag_dist(BMVert *v) +{ + BMIter iter; + BMEdge *e; + int tot; + float length = 0.0f; + + BM_ITER_ELEM_INDEX (e, &iter, v, BM_EDGES_OF_VERT, tot) { + BMVert *v_other = BM_edge_other_vert(e, v); + if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) { + length += BM_edge_length_calc(e); + } + } + + return length / (float)tot; +} /** * implementation is as follows... @@ -98,7 +114,8 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) const int use_even_offset = BMO_slot_bool_get(op, "use_even_offset"); const int use_even_boundry = use_even_offset; /* could make own option */ const int use_relative_offset = BMO_slot_bool_get(op, "use_relative_offset"); - const float thickness = BMO_slot_float_get(op, "thickness"); + const float thickness = BMO_slot_float_get(op, "thickness"); + const float depth = BMO_slot_float_get(op, "depth"); int edge_info_len = 0; @@ -482,4 +499,42 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) /* we could flag new edges/verts too, is it useful? */ BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, ELE_NEW); + + /* cheap feature to add depth to the inset */ + if (depth != 0.0f) { + float (*varr_co)[3]; + BMOIter oiter; + + /* untag verts */ + BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, FALSE); + + /* tag face verts */ + BMO_ITER (f, &oiter, bm, op, "faces", BM_FACE) { + BM_ITER_ELEM (v, &iter, f, BM_VERTS_OF_FACE) { + BM_elem_flag_enable(v, BM_ELEM_TAG); + } + } + + /* do in 2 passes so moving the verts doesn't feed back into face angle checks + * which BM_vert_shell_factor uses. */ + + /* over allocate */ + varr_co = MEM_callocN(sizeof(*varr_co) * bm->totvert, __func__); + + BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + const float fac = (depth * + (use_relative_offset ? bm_vert_avg_tag_dist(v) : 1.0f) * + (use_even_boundry ? BM_vert_shell_factor(v) : 1.0f)); + madd_v3_v3v3fl(varr_co[i], v->co, v->no, fac); + } + } + + BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + copy_v3_v3(v->co, varr_co[i]); + } + } + MEM_freeN(varr_co); + } } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 2d27b64d3af..26c50fb4feb 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -4200,13 +4200,16 @@ static int edbm_inset_exec(bContext *C, wmOperator *op) const int use_boundary = RNA_boolean_get(op->ptr, "use_boundary"); const int use_even_offset = RNA_boolean_get(op->ptr, "use_even_offset"); const int use_relative_offset = RNA_boolean_get(op->ptr, "use_relative_offset"); - const float thickness = RNA_float_get(op->ptr, "thickness"); + const float thickness = RNA_float_get(op->ptr, "thickness"); + const float depth = RNA_float_get(op->ptr, "depth"); const int use_outset = RNA_boolean_get(op->ptr, "use_outset"); const int use_select_inset = RNA_boolean_get(op->ptr, "use_select_inset"); /* not passed onto the BMO */ EDBM_op_init(em, &bmop, op, - "inset faces=%hf use_boundary=%b use_even_offset=%b use_relative_offset=%b thickness=%f use_outset=%b", - BM_ELEM_SELECT, use_boundary, use_even_offset, use_relative_offset, thickness, use_outset); + "inset faces=%hf use_boundary=%b use_even_offset=%b use_relative_offset=%b " + "thickness=%f depth=%f use_outset=%b", + BM_ELEM_SELECT, use_boundary, use_even_offset, use_relative_offset, + thickness, depth, use_outset); BMO_op_exec(em->bm, &bmop); @@ -4252,9 +4255,11 @@ void MESH_OT_inset(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_even_offset", TRUE, "Offset Even", "Scale the offset to give more even thickness"); RNA_def_boolean(ot->srna, "use_relative_offset", FALSE, "Offset Relative", "Scale the offset by surrounding geometry"); - prop = RNA_def_float(ot->srna, "thickness", 0.01f, 0.0f, FLT_MAX, "thickness", "", 0.0f, 10.0f); + prop = RNA_def_float(ot->srna, "thickness", 0.01f, 0.0f, FLT_MAX, "Thickness", "", 0.0f, 10.0f); /* use 1 rather then 10 for max else dragging the button moves too far */ RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 4); + prop = RNA_def_float(ot->srna, "depth", 0.0f, -FLT_MAX, FLT_MAX, "Depth", "", -10.0f, 10.0f); + RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.01, 4); RNA_def_boolean(ot->srna, "use_outset", FALSE, "Outset", "Outset rather than inset"); RNA_def_boolean(ot->srna, "use_select_inset", TRUE, "Select Outer", "Select the new inset faces"); |