From 790e9d9fa084c30609a13d175c56a4f3c14f132e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 3 Jun 2013 05:07:16 +0000 Subject: [PATCH] fix [#35311] Planar Decimate / Limited Dissolve fails to merge some adjacent faces optionally limit by face flipping, also added support to delimit by material and edge crease. --- .../startup/bl_ui/properties_data_modifier.py | 3 ++ source/blender/bmesh/intern/bmesh_opdefines.c | 1 + .../blender/bmesh/intern/bmesh_operator_api.h | 6 +++ source/blender/bmesh/operators/bmo_dissolve.c | 3 +- source/blender/bmesh/tools/bmesh_decimate.h | 4 +- .../bmesh/tools/bmesh_decimate_dissolve.c | 50 ++++++++++++++++--- .../editors/interface/interface_templates.c | 2 +- source/blender/editors/mesh/editmesh_tools.c | 7 ++- source/blender/makesdna/DNA_modifier_types.h | 3 +- source/blender/makesrna/RNA_enum_types.h | 1 + source/blender/makesrna/intern/rna_mesh.c | 10 +++- source/blender/makesrna/intern/rna_modifier.c | 7 +++ .../blender/modifiers/intern/MOD_decimate.c | 2 +- 13 files changed, 84 insertions(+), 15 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 6e657f4f5f7..43c5eba1bb1 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -262,6 +262,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): else: # decimate_type == 'DISSOLVE': layout.prop(md, "angle_limit") layout.prop(md, "use_dissolve_boundaries") + layout.label("Delimit:") + row = layout.row() + row.prop(md, "delimit") layout.label(text=iface_("Face Count: %d") % md.face_count, translate=False) diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 59de3622adb..b42e6c537a9 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -941,6 +941,7 @@ static BMOpDefine bmo_dissolve_limit_def = { {"use_dissolve_boundaries", BMO_OP_SLOT_BOOL}, {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, + {"delimit", BMO_OP_SLOT_INT}, {{'\0'}}, }, {{{'\0'}}}, /* no output */ diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index ccc90172d7a..24bfcd70d75 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -297,6 +297,12 @@ typedef enum { BMO_SYMMETRIZE_POSITIVE_Z, } BMO_SymmDirection; +typedef enum { + BMO_DELIM_NORMAL = 1 << 0, + BMO_DELIM_MATERIAL = 1 << 1, + BMO_DELIM_SEAM = 1 << 2, +} BMO_Delimit; + void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag); void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag); diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index ee483edbef5..0f72a016e2f 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -452,8 +452,9 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op) const float angle_max = (float)M_PI / 2.0f; const float angle_limit = min_ff(angle_max, BMO_slot_float_get(op->slots_in, "angle_limit")); const bool do_dissolve_boundaries = BMO_slot_bool_get(op->slots_in, "use_dissolve_boundaries"); + const BMO_Delimit delimit = BMO_slot_int_get(op->slots_in, "delimit"); - BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries, + BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries, delimit, (BMVert **)BMO_SLOT_AS_BUFFER(vinput), vinput->len, (BMEdge **)BMO_SLOT_AS_BUFFER(einput), einput->len); } diff --git a/source/blender/bmesh/tools/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h index d3eaf1c6670..c77cb18c518 100644 --- a/source/blender/bmesh/tools/bmesh_decimate.h +++ b/source/blender/bmesh/tools/bmesh_decimate.h @@ -33,9 +33,11 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations); void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, + const BMO_Delimit delimit, BMVert **vinput_arr, const int vinput_len, BMEdge **einput_arr, const int einput_len); -void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries); +void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, + const BMO_Delimit delimit); /* these weights are accumulated so too high values may reach 'inf' too quickly */ #define BM_MESH_DECIM_WEIGHT_MAX 100000.0f diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index a5122b242be..9d4e01d19cd 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -70,6 +70,7 @@ static int dissolve_elem_cmp(const void *a1, const void *a2) } void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, + const BMO_Delimit delimit, BMVert **vinput_arr, const int vinput_len, BMEdge **einput_arr, const int einput_len) { @@ -77,7 +78,6 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool DissolveElemWeight *weight_elems = MEM_mallocN(max_ii(einput_len, vinput_len) * sizeof(DissolveElemWeight), __func__); int i, tot_found; - BMIter iter; BMEdge *e_iter; BMEdge **earray; @@ -94,7 +94,13 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool /* go through and split edge */ for (i = 0, tot_found = 0; i < einput_len; i++) { BMEdge *e = einput_arr[i]; - const float angle = BM_edge_calc_face_angle(e); + const bool is_contig = BM_edge_is_contiguous(e); + float angle; + + angle = BM_edge_calc_face_angle(e); + if (is_contig == false) { + angle = (float)M_PI - angle; + } if (angle < angle_limit) { tot_found++; @@ -108,12 +114,39 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool for (i = 0; i < tot_found; i++) { BMEdge *e = (BMEdge *)weight_elems[i].ele; + const bool is_contig = BM_edge_is_contiguous(e); + float angle; - if (/* may have become non-manifold */ - BM_edge_is_manifold(e) && - /* check twice because cumulative effect could dissolve over angle limit */ - (BM_edge_calc_face_angle(e) < angle_limit)) + /* may have become non-manifold */ + if (!BM_edge_is_manifold(e)) { + continue; + } + + if ((delimit & BMO_DELIM_SEAM) && + (BM_elem_flag_test(e, BM_ELEM_SEAM))) { + continue; + } + + if ((delimit & BMO_DELIM_MATERIAL) && + (e->l->f->mat_nr != e->l->radial_next->f->mat_nr)) + { + continue; + } + + if ((delimit & BMO_DELIM_NORMAL) && + (is_contig == false)) + { + continue; + } + + /* check twice because cumulative effect could dissolve over angle limit */ + angle = BM_edge_calc_face_angle(e); + if (is_contig == false) { + angle = (float)M_PI - angle; + } + + if (angle < angle_limit) { BMFace *f_new = BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, @@ -223,7 +256,8 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool MEM_freeN(weight_elems); } -void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries) +void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, + const BMO_Delimit delimit) { int vinput_len; int einput_len; @@ -231,7 +265,9 @@ void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do BMVert **vinput_arr = BM_iter_as_arrayN(bm, BM_VERTS_OF_MESH, NULL, &vinput_len, NULL, 0); BMEdge **einput_arr = BM_iter_as_arrayN(bm, BM_EDGES_OF_MESH, NULL, &einput_len, NULL, 0); + BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries, + delimit, vinput_arr, vinput_len, einput_arr, einput_len); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index f07b31eff17..464fcfb0496 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -150,7 +150,7 @@ static void id_search_cb(const bContext *C, void *arg_template, const char *str, if ((id->name[2] == '.') && (str[0] != '.')) continue; - if (BLI_strcasestr(id->name + 2, str)) { + if (*str == '\0' || BLI_strcasestr(id->name + 2, str)) { /* +1 is needed because name_uiprefix_id used 3 letter prefix * followed by ID_NAME-2 characters from id->name */ diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 8bbb0e8489e..ed809f15184 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3056,6 +3056,7 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op) BMesh *bm = em->bm; const float angle_limit = RNA_float_get(op->ptr, "angle_limit"); const bool use_dissolve_boundaries = RNA_boolean_get(op->ptr, "use_dissolve_boundaries"); + const int delimit = RNA_enum_get(op->ptr, "delimit"); char dissolve_flag; @@ -3091,8 +3092,8 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op) } if (!EDBM_op_callf(em, op, - "dissolve_limit edges=%he verts=%hv angle_limit=%f use_dissolve_boundaries=%b", - dissolve_flag, dissolve_flag, angle_limit, use_dissolve_boundaries)) + "dissolve_limit edges=%he verts=%hv angle_limit=%f use_dissolve_boundaries=%b delimit=%i", + dissolve_flag, dissolve_flag, angle_limit, use_dissolve_boundaries, delimit)) { return OPERATOR_CANCELLED; } @@ -3123,6 +3124,8 @@ void MESH_OT_dissolve_limited(wmOperatorType *ot) RNA_def_property_float_default(prop, DEG2RADF(5.0f)); RNA_def_boolean(ot->srna, "use_dissolve_boundaries", 0, "All Boundaries", "Dissolve all vertices inbetween face boundaries"); + RNA_def_enum_flag(ot->srna, "delimit", mesh_delimit_mode_items, 0, "Delimit", + "Delimit dissolve operation"); } static int edbm_split_exec(bContext *C, wmOperator *op) diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 66685c131d4..4fa8ed2b34a 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -367,7 +367,8 @@ typedef struct DecimateModifierData { float percent; /* (mode == MOD_DECIM_MODE_COLLAPSE) */ short iter; /* (mode == MOD_DECIM_MODE_UNSUBDIV) */ - short pad; + char delimit; /* (mode == MOD_DECIM_MODE_DISSOLVE) */ + char pad; float angle; /* (mode == MOD_DECIM_MODE_DISSOLVE) */ char defgrp_name[64]; /* MAX_VGROUP_NAME */ diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index 513e249a64a..86d043b839a 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -52,6 +52,7 @@ extern EnumPropertyItem snap_target_items[]; extern EnumPropertyItem snap_element_items[]; extern EnumPropertyItem snap_node_element_items[]; extern EnumPropertyItem mesh_select_mode_items[]; +extern EnumPropertyItem mesh_delimit_mode_items[]; extern EnumPropertyItem space_type_items[]; extern EnumPropertyItem region_type_items[]; extern EnumPropertyItem modifier_type_items[]; diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 9c1b9a9630b..7e54f665214 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -42,6 +42,8 @@ #include "BLI_math_rotation.h" #include "BLI_utildefines.h" +#include "BKE_editmesh.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_types.h" @@ -50,6 +52,13 @@ #include "WM_types.h" +EnumPropertyItem mesh_delimit_mode_items[] = { + {BMO_DELIM_NORMAL, "NORMAL", 0, "Normal", "Delimit by face directions"}, + {BMO_DELIM_MATERIAL, "MATERIAL", 0, "Material", "Delimit by face material"}, + {BMO_DELIM_SEAM, "SEAM", 0, "Seam", "Delimit by edge seams"}, + {0, NULL, 0, NULL, NULL}, +}; + #ifdef RNA_RUNTIME #include "DNA_scene_types.h" @@ -60,7 +69,6 @@ #include "BKE_depsgraph.h" #include "BKE_main.h" #include "BKE_mesh.h" -#include "BKE_editmesh.h" #include "BKE_report.h" #include "ED_mesh.h" /* XXX Bad level call */ diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 3cf1e0c3b20..0b7d6823b8f 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1216,6 +1216,13 @@ static void rna_def_modifier_decimate(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS); RNA_def_property_ui_text(prop, "All Boundaries", "Dissolve all vertices inbetween face boundaries (planar only)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "delimit", PROP_ENUM, PROP_NONE); + RNA_def_property_flag(prop, PROP_ENUM_FLAG); /* important to run before default set */ + RNA_def_property_enum_items(prop, mesh_delimit_mode_items); + RNA_def_property_ui_text(prop, "Delimit", "Limit merging geometry"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + /* end dissolve-only option */ diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index aacf622c185..6c75f1d4be9 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -180,7 +180,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, case MOD_DECIM_MODE_DISSOLVE: { const int do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0; - BM_mesh_decimate_dissolve(bm, dmd->angle, do_dissolve_boundaries); + BM_mesh_decimate_dissolve(bm, dmd->angle, do_dissolve_boundaries, (BMO_Delimit)dmd->delimit); break; } }