diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_data_modifier.py | 19 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_270.c | 14 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_decimate.h | 4 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_decimate_collapse.c | 67 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_modifier_types.h | 3 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_modifier.c | 7 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_decimate.c | 13 |
7 files changed, 91 insertions, 36 deletions
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index d6d4e03df39..381c9add34f 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -262,24 +262,37 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): row.prop(md, "decimate_type", expand=True) if decimate_type == 'COLLAPSE': + has_vgroup = bool(md.vertex_group) layout.prop(md, "ratio") split = layout.split() - row = split.row(align=True) + + col = split.column() + row = col.row(align=True) row.prop_search(md, "vertex_group", ob, "vertex_groups", text="") row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT') - split.prop(md, "use_collapse_triangulate") + layout_info = col + + col = split.column() + row = col.row() + row.active = has_vgroup + row.prop(md, "vertex_group_factor") + + col.prop(md, "use_collapse_triangulate") + elif decimate_type == 'UNSUBDIV': layout.prop(md, "iterations") + layout_info = layout 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_info = layout - layout.label(text=iface_("Face Count: %d") % md.face_count, translate=False) + layout_info.label(text=iface_("Faces: %d") % md.face_count, translate=False) def DISPLACE(self, layout, ob, md): has_texture = (md.texture is not None) diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index df985448ccd..37c255620d9 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -830,5 +830,19 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) scene->r.simplify_particles_render = scene->r.simplify_particles; } } + + if (!DNA_struct_elem_find(fd->filesdna, "DecimateModifierData", "float", "defgrp_factor")) { + Object *ob; + + for (ob = main->object.first; ob; ob = ob->id.next) { + ModifierData *md; + for (md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Decimate) { + DecimateModifierData *dmd = (DecimateModifierData *)md; + dmd->defgrp_factor = 1.0f; + } + } + } + } } } diff --git a/source/blender/bmesh/tools/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h index 17b55be52dc..b0a85b09d5a 100644 --- a/source/blender/bmesh/tools/bmesh_decimate.h +++ b/source/blender/bmesh/tools/bmesh_decimate.h @@ -42,8 +42,4 @@ 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 -#define BM_MESH_DECIM_WEIGHT_EPS (1.0f / BM_MESH_DECIM_WEIGHT_MAX) - #endif /* __BMESH_DECIMATE_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 3bcf9a3cd0b..6b6219ca321 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -212,10 +212,15 @@ static bool bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_ * * This avoids cases where a flat (or near flat) areas get very un-even geometry. */ -static float bm_decim_build_edge_cost_single__topology(BMEdge *e) +static float bm_decim_build_edge_cost_single_squared__topology(BMEdge *e) { return fabsf(dot_v3v3(e->v1->no, e->v2->no)) / min_ff(-len_squared_v3v3(e->v1->co, e->v2->co), -FLT_EPSILON); } +static float bm_decim_build_edge_cost_single__topology(BMEdge *e) +{ + return fabsf(dot_v3v3(e->v1->no, e->v2->no)) / min_ff(-len_v3v3(e->v1->co, e->v2->co), -FLT_EPSILON); +} + #endif /* USE_TOPOLOGY_FALLBACK */ static void bm_decim_build_edge_cost_single( @@ -253,15 +258,6 @@ static void bm_decim_build_edge_cost_single( else { goto clear; } - - if (vweights) { - if ((vweights[BM_elem_index_get(e->v1)] >= BM_MESH_DECIM_WEIGHT_MAX) && - (vweights[BM_elem_index_get(e->v2)] >= BM_MESH_DECIM_WEIGHT_MAX)) - { - /* skip collapsing this edge */ - goto clear; - } - } /* end sanity check */ @@ -270,21 +266,21 @@ static void bm_decim_build_edge_cost_single( q1 = &vquadrics[BM_elem_index_get(e->v1)]; q2 = &vquadrics[BM_elem_index_get(e->v2)]; - if (vweights == NULL) { - cost = (BLI_quadric_evaluate(q1, optimize_co) + - BLI_quadric_evaluate(q2, optimize_co)); - } - else { - /* add 1.0 so planar edges are still weighted against */ - cost = (((BLI_quadric_evaluate(q1, optimize_co) + 1.0f) * vweights[BM_elem_index_get(e->v1)]) + - ((BLI_quadric_evaluate(q2, optimize_co) + 1.0f) * vweights[BM_elem_index_get(e->v2)])); - } + cost = (BLI_quadric_evaluate(q1, optimize_co) + + BLI_quadric_evaluate(q2, optimize_co)); + + // print("COST %.12f\n"); /* note, 'cost' shouldn't be negative but happens sometimes with small values. * this can cause faces that make up a flat surface to over-collapse, see [#37121] */ cost = fabsf(cost); + /* edge weights can be 2 max, ((2 * 2) ^ 2) == 16x max, + * a high weight means being inserted into the heap ahead of 16x better edges. + * but thats fine since its the purpose of weighting. */ +#define VWEIGHT_SCALE 2 + #ifdef USE_TOPOLOGY_FALLBACK if (UNLIKELY(cost < TOPOLOGY_FALLBACK_EPS)) { /* subtract existing cost to further differentiate edges from one another @@ -292,10 +288,35 @@ static void bm_decim_build_edge_cost_single( * keep topology cost below 0.0 so their values don't interfere with quadric cost, * (and they get handled first). * */ - cost = bm_decim_build_edge_cost_single__topology(e) - cost; - BLI_assert(cost <= 0.0f); + if (vweights == NULL) { + cost = bm_decim_build_edge_cost_single_squared__topology(e) - cost; + } + else { + /* with weights we need to use the real length so we can scale them properly */ + float e_weight = (vweights[BM_elem_index_get(e->v1)] + + vweights[BM_elem_index_get(e->v2)]); + cost = bm_decim_build_edge_cost_single__topology(e) - cost; + /* note, this is rather arbitrary max weight is 2 here, + * allow for skipping edges 4x the length, based on weights */ + if (e_weight) { + e_weight *= VWEIGHT_SCALE; + cost *= 1.0f + SQUARE(e_weight); + } + + BLI_assert(cost <= 0.0f); + } } + else #endif + if (vweights) { + float e_weight = 2.0f - (vweights[BM_elem_index_get(e->v1)] + + vweights[BM_elem_index_get(e->v2)]); + if (e_weight) { + e_weight *= VWEIGHT_SCALE; + cost += (BM_edge_calc_length(e) * SQUARE(e_weight)); + } + } +#undef VWEIGHT_SCALE eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, cost, e); return; @@ -950,7 +971,9 @@ static void bm_decim_edge_collapse( int i; if (vweights) { - vweights[v_other_index] += vweights[v_clear_index]; + float v_other_weight = interpf(vweights[v_other_index], vweights[v_clear_index], customdata_fac); + CLAMP(v_other_weight, 0.0f, 1.0f); + vweights[v_other_index] = v_other_weight; } e = NULL; /* paranoid safety check */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index f3c61f0ab6c..1fc66b9b016 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -431,10 +431,11 @@ typedef struct DecimateModifierData { float angle; /* (mode == MOD_DECIM_MODE_DISSOLVE) */ char defgrp_name[64]; /* MAX_VGROUP_NAME */ + float defgrp_factor; short flag, mode; /* runtime only */ - int face_count, pad2; + int face_count; } DecimateModifierData; enum { diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 1c719b1376b..6f1f6f97a15 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1506,6 +1506,13 @@ static void rna_def_modifier_decimate(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_DECIM_FLAG_TRIANGULATE); RNA_def_property_ui_text(prop, "Triangulate", "Keep triangulated faces resulting from decimation (collapse only)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "vertex_group_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "defgrp_factor"); + RNA_def_property_range(prop, 0, 1.0f); + RNA_def_property_ui_range(prop, 0, 1, 1, 4); + RNA_def_property_ui_text(prop, "Factor", "Vertex group strength"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); /* end collapse-only option */ /* (mode == MOD_DECIM_MODE_DISSOLVE) */ diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index 7c13774ee99..878015c7a7b 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -61,6 +61,7 @@ static void initData(ModifierData *md) dmd->percent = 1.0; dmd->angle = DEG2RADF(5.0f); + dmd->defgrp_factor = 1.0; } static void copyData(ModifierData *md, ModifierData *target) @@ -78,7 +79,9 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) CustomDataMask dataMask = 0; /* ask for vertexgroups if we need them */ - if (dmd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT; + if (dmd->defgrp_name[0] && (dmd->defgrp_factor > 0.0f)) { + dataMask |= CD_MASK_MDEFORMVERT; + } return dataMask; } @@ -130,7 +133,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } if (dmd->mode == MOD_DECIM_MODE_COLLAPSE) { - if (dmd->defgrp_name[0]) { + if (dmd->defgrp_name[0] && (dmd->defgrp_factor > 0.0f)) { MDeformVert *dvert; int defgrp_index; @@ -144,14 +147,12 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (dmd->flag & MOD_DECIM_FLAG_INVERT_VGROUP) { for (i = 0; i < vert_tot; i++) { - const float f = 1.0f - defvert_find_weight(&dvert[i], defgrp_index); - vweights[i] = f > BM_MESH_DECIM_WEIGHT_EPS ? (1.0f / f) : BM_MESH_DECIM_WEIGHT_MAX; + vweights[i] = (1.0f - defvert_find_weight(&dvert[i], defgrp_index)) * dmd->defgrp_factor; } } else { for (i = 0; i < vert_tot; i++) { - const float f = defvert_find_weight(&dvert[i], defgrp_index); - vweights[i] = f > BM_MESH_DECIM_WEIGHT_EPS ? (1.0f / f) : BM_MESH_DECIM_WEIGHT_MAX; + vweights[i] = (defvert_find_weight(&dvert[i], defgrp_index)) * dmd->defgrp_factor; } } } |