forked from bartvdbraak/blender
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.
This commit is contained in:
parent
8a1ef33e88
commit
790e9d9fa0
@ -262,6 +262,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
|||||||
else: # decimate_type == 'DISSOLVE':
|
else: # decimate_type == 'DISSOLVE':
|
||||||
layout.prop(md, "angle_limit")
|
layout.prop(md, "angle_limit")
|
||||||
layout.prop(md, "use_dissolve_boundaries")
|
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)
|
layout.label(text=iface_("Face Count: %d") % md.face_count, translate=False)
|
||||||
|
|
||||||
|
@ -941,6 +941,7 @@ static BMOpDefine bmo_dissolve_limit_def = {
|
|||||||
{"use_dissolve_boundaries", BMO_OP_SLOT_BOOL},
|
{"use_dissolve_boundaries", BMO_OP_SLOT_BOOL},
|
||||||
{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
|
{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
|
||||||
{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
|
{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
|
||||||
|
{"delimit", BMO_OP_SLOT_INT},
|
||||||
{{'\0'}},
|
{{'\0'}},
|
||||||
},
|
},
|
||||||
{{{'\0'}}}, /* no output */
|
{{{'\0'}}}, /* no output */
|
||||||
|
@ -297,6 +297,12 @@ typedef enum {
|
|||||||
BMO_SYMMETRIZE_POSITIVE_Z,
|
BMO_SYMMETRIZE_POSITIVE_Z,
|
||||||
} BMO_SymmDirection;
|
} 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_enable(BMesh *bm, BMOperator *op, const int op_flag);
|
||||||
void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag);
|
void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag);
|
||||||
|
|
||||||
|
@ -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_max = (float)M_PI / 2.0f;
|
||||||
const float angle_limit = min_ff(angle_max, BMO_slot_float_get(op->slots_in, "angle_limit"));
|
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 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,
|
(BMVert **)BMO_SLOT_AS_BUFFER(vinput), vinput->len,
|
||||||
(BMEdge **)BMO_SLOT_AS_BUFFER(einput), einput->len);
|
(BMEdge **)BMO_SLOT_AS_BUFFER(einput), einput->len);
|
||||||
}
|
}
|
||||||
|
@ -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_unsubdivide(BMesh *bm, const int iterations);
|
||||||
|
|
||||||
void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
|
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,
|
BMVert **vinput_arr, const int vinput_len,
|
||||||
BMEdge **einput_arr, const int einput_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 */
|
/* these weights are accumulated so too high values may reach 'inf' too quickly */
|
||||||
#define BM_MESH_DECIM_WEIGHT_MAX 100000.0f
|
#define BM_MESH_DECIM_WEIGHT_MAX 100000.0f
|
||||||
|
@ -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,
|
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,
|
BMVert **vinput_arr, const int vinput_len,
|
||||||
BMEdge **einput_arr, const int einput_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) *
|
DissolveElemWeight *weight_elems = MEM_mallocN(max_ii(einput_len, vinput_len) *
|
||||||
sizeof(DissolveElemWeight), __func__);
|
sizeof(DissolveElemWeight), __func__);
|
||||||
int i, tot_found;
|
int i, tot_found;
|
||||||
|
|
||||||
BMIter iter;
|
BMIter iter;
|
||||||
BMEdge *e_iter;
|
BMEdge *e_iter;
|
||||||
BMEdge **earray;
|
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 */
|
/* go through and split edge */
|
||||||
for (i = 0, tot_found = 0; i < einput_len; i++) {
|
for (i = 0, tot_found = 0; i < einput_len; i++) {
|
||||||
BMEdge *e = einput_arr[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) {
|
if (angle < angle_limit) {
|
||||||
tot_found++;
|
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++) {
|
for (i = 0; i < tot_found; i++) {
|
||||||
BMEdge *e = (BMEdge *)weight_elems[i].ele;
|
BMEdge *e = (BMEdge *)weight_elems[i].ele;
|
||||||
|
const bool is_contig = BM_edge_is_contiguous(e);
|
||||||
|
float angle;
|
||||||
|
|
||||||
if (/* may have become non-manifold */
|
/* may have become non-manifold */
|
||||||
BM_edge_is_manifold(e) &&
|
if (!BM_edge_is_manifold(e)) {
|
||||||
/* check twice because cumulative effect could dissolve over angle limit */
|
continue;
|
||||||
(BM_edge_calc_face_angle(e) < angle_limit))
|
}
|
||||||
|
|
||||||
|
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,
|
BMFace *f_new = BM_faces_join_pair(bm, e->l->f,
|
||||||
e->l->radial_next->f,
|
e->l->radial_next->f,
|
||||||
e,
|
e,
|
||||||
@ -223,7 +256,8 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool
|
|||||||
MEM_freeN(weight_elems);
|
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 vinput_len;
|
||||||
int einput_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);
|
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);
|
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,
|
BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries,
|
||||||
|
delimit,
|
||||||
vinput_arr, vinput_len,
|
vinput_arr, vinput_len,
|
||||||
einput_arr, einput_len);
|
einput_arr, einput_len);
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ static void id_search_cb(const bContext *C, void *arg_template, const char *str,
|
|||||||
if ((id->name[2] == '.') && (str[0] != '.'))
|
if ((id->name[2] == '.') && (str[0] != '.'))
|
||||||
continue;
|
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
|
/* +1 is needed because name_uiprefix_id used 3 letter prefix
|
||||||
* followed by ID_NAME-2 characters from id->name
|
* followed by ID_NAME-2 characters from id->name
|
||||||
*/
|
*/
|
||||||
|
@ -3056,6 +3056,7 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op)
|
|||||||
BMesh *bm = em->bm;
|
BMesh *bm = em->bm;
|
||||||
const float angle_limit = RNA_float_get(op->ptr, "angle_limit");
|
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 bool use_dissolve_boundaries = RNA_boolean_get(op->ptr, "use_dissolve_boundaries");
|
||||||
|
const int delimit = RNA_enum_get(op->ptr, "delimit");
|
||||||
|
|
||||||
char dissolve_flag;
|
char dissolve_flag;
|
||||||
|
|
||||||
@ -3091,8 +3092,8 @@ static int edbm_dissolve_limited_exec(bContext *C, wmOperator *op)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!EDBM_op_callf(em, op,
|
if (!EDBM_op_callf(em, op,
|
||||||
"dissolve_limit edges=%he verts=%hv angle_limit=%f use_dissolve_boundaries=%b",
|
"dissolve_limit edges=%he verts=%hv angle_limit=%f use_dissolve_boundaries=%b delimit=%i",
|
||||||
dissolve_flag, dissolve_flag, angle_limit, use_dissolve_boundaries))
|
dissolve_flag, dissolve_flag, angle_limit, use_dissolve_boundaries, delimit))
|
||||||
{
|
{
|
||||||
return OPERATOR_CANCELLED;
|
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_property_float_default(prop, DEG2RADF(5.0f));
|
||||||
RNA_def_boolean(ot->srna, "use_dissolve_boundaries", 0, "All Boundaries",
|
RNA_def_boolean(ot->srna, "use_dissolve_boundaries", 0, "All Boundaries",
|
||||||
"Dissolve all vertices inbetween face 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)
|
static int edbm_split_exec(bContext *C, wmOperator *op)
|
||||||
|
@ -367,7 +367,8 @@ typedef struct DecimateModifierData {
|
|||||||
|
|
||||||
float percent; /* (mode == MOD_DECIM_MODE_COLLAPSE) */
|
float percent; /* (mode == MOD_DECIM_MODE_COLLAPSE) */
|
||||||
short iter; /* (mode == MOD_DECIM_MODE_UNSUBDIV) */
|
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) */
|
float angle; /* (mode == MOD_DECIM_MODE_DISSOLVE) */
|
||||||
|
|
||||||
char defgrp_name[64]; /* MAX_VGROUP_NAME */
|
char defgrp_name[64]; /* MAX_VGROUP_NAME */
|
||||||
|
@ -52,6 +52,7 @@ extern EnumPropertyItem snap_target_items[];
|
|||||||
extern EnumPropertyItem snap_element_items[];
|
extern EnumPropertyItem snap_element_items[];
|
||||||
extern EnumPropertyItem snap_node_element_items[];
|
extern EnumPropertyItem snap_node_element_items[];
|
||||||
extern EnumPropertyItem mesh_select_mode_items[];
|
extern EnumPropertyItem mesh_select_mode_items[];
|
||||||
|
extern EnumPropertyItem mesh_delimit_mode_items[];
|
||||||
extern EnumPropertyItem space_type_items[];
|
extern EnumPropertyItem space_type_items[];
|
||||||
extern EnumPropertyItem region_type_items[];
|
extern EnumPropertyItem region_type_items[];
|
||||||
extern EnumPropertyItem modifier_type_items[];
|
extern EnumPropertyItem modifier_type_items[];
|
||||||
|
@ -42,6 +42,8 @@
|
|||||||
#include "BLI_math_rotation.h"
|
#include "BLI_math_rotation.h"
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
|
#include "BKE_editmesh.h"
|
||||||
|
|
||||||
#include "RNA_access.h"
|
#include "RNA_access.h"
|
||||||
#include "RNA_define.h"
|
#include "RNA_define.h"
|
||||||
#include "RNA_types.h"
|
#include "RNA_types.h"
|
||||||
@ -50,6 +52,13 @@
|
|||||||
|
|
||||||
#include "WM_types.h"
|
#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
|
#ifdef RNA_RUNTIME
|
||||||
|
|
||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
@ -60,7 +69,6 @@
|
|||||||
#include "BKE_depsgraph.h"
|
#include "BKE_depsgraph.h"
|
||||||
#include "BKE_main.h"
|
#include "BKE_main.h"
|
||||||
#include "BKE_mesh.h"
|
#include "BKE_mesh.h"
|
||||||
#include "BKE_editmesh.h"
|
|
||||||
#include "BKE_report.h"
|
#include "BKE_report.h"
|
||||||
|
|
||||||
#include "ED_mesh.h" /* XXX Bad level call */
|
#include "ED_mesh.h" /* XXX Bad level call */
|
||||||
|
@ -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_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_ui_text(prop, "All Boundaries", "Dissolve all vertices inbetween face boundaries (planar only)");
|
||||||
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
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 */
|
/* end dissolve-only option */
|
||||||
|
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
|
|||||||
case MOD_DECIM_MODE_DISSOLVE:
|
case MOD_DECIM_MODE_DISSOLVE:
|
||||||
{
|
{
|
||||||
const int do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user