From de257b6366455ba6a3604c0830a92245df11f7bc Mon Sep 17 00:00:00 2001 From: Cody Winchester Date: Tue, 26 May 2020 20:53:38 +0200 Subject: Modifiers: Add normalize weights option to vertex weight modifiers Original patch by Cody Winchester (@CodyWinch), several fixes and cleanup by Bastien Montagne (@mont29). Differential revision: https://developer.blender.org/D7656 --- .../startup/bl_ui/properties_data_modifier.py | 9 +++++++ source/blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenloader/intern/versioning_290.c | 14 ++++++++++ source/blender/makesdna/DNA_modifier_types.h | 4 ++- source/blender/makesrna/intern/rna_modifier.c | 25 +++++++++++++++++ .../blender/modifiers/intern/MOD_weightvg_util.c | 31 +++++++++++++++++++++- .../blender/modifiers/intern/MOD_weightvg_util.h | 3 ++- source/blender/modifiers/intern/MOD_weightvgedit.c | 4 ++- source/blender/modifiers/intern/MOD_weightvgmix.c | 3 ++- .../modifiers/intern/MOD_weightvgproximity.c | 4 ++- 10 files changed, 92 insertions(+), 7 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 75e9a320130..71c6817abe9 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -1437,6 +1437,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): if md.falloff_type == 'CURVE': layout.template_curve_mapping(md, "map_curve") + row = layout.row(align=True) + row.prop(md, "normalize") + # Common mask options layout.separator() self.vertex_weight_mask(layout, ob, md) @@ -1462,6 +1465,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col.label(text="Mix Set:") col.prop(md, "mix_set", text="") + row = layout.row(align=True) + row.prop(md, "normalize") + # Common mask options layout.separator() self.vertex_weight_mask(layout, ob, md) @@ -1495,6 +1501,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): row.prop(md, "falloff_type") row.prop(md, "invert_falloff", text="", icon='ARROW_LEFTRIGHT') + row = layout.row(align=True) + row.prop(md, "normalize") + # Common mask options layout.separator() self.vertex_weight_mask(layout, ob, md) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index ddebf50691f..981799ec1dd 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -31,7 +31,7 @@ extern "C" { * \note Use #STRINGIFY() rather than defining with quotes. */ #define BLENDER_VERSION 290 -#define BLENDER_SUBVERSION 3 +#define BLENDER_SUBVERSION 4 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 0a3a1a2f881..6574c983b09 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -26,6 +26,8 @@ #include "DNA_brush_types.h" #include "DNA_genfile.h" #include "DNA_gpencil_modifier_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" #include "DNA_screen_types.h" #include "BKE_collection.h" @@ -241,6 +243,18 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 290, 4)) { + /* Clear old deprecated bitflag from edit weights modifiers, we now use it for something else. + */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { + if (md->type == eModifierType_WeightVGEdit) { + md->flag &= ~MOD_WVG_EDIT_WEIGHTS_NORMALIZE; + } + } + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 972ef197954..e74f42f5c10 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -1416,7 +1416,7 @@ typedef struct WeightVGEditModifierData { /* WeightVGEdit flags. */ enum { - /* (1 << 0) is free for future use! */ + MOD_WVG_EDIT_WEIGHTS_NORMALIZE = (1 << 0), MOD_WVG_INVERT_FALLOFF = (1 << 1), MOD_WVG_EDIT_INVERT_VGROUP_MASK = (1 << 2), /** Add vertices with higher weight than threshold to vgroup. */ @@ -1504,6 +1504,7 @@ enum { /* WeightVGMix->flag */ enum { MOD_WVG_MIX_INVERT_VGROUP_MASK = (1 << 0), + MOD_WVG_MIX_WEIGHTS_NORMALIZE = (1 << 1), }; typedef struct WeightVGProximityModifierData { @@ -1566,6 +1567,7 @@ enum { MOD_WVG_PROXIMITY_GEOM_FACES = (1 << 2), MOD_WVG_PROXIMITY_INVERT_VGROUP_MASK = (1 << 3), MOD_WVG_PROXIMITY_INVERT_FALLOFF = (1 << 4), + MOD_WVG_PROXIMITY_WEIGHTS_NORMALIZE = (1 << 3), }; /* Defines common to all WeightVG modifiers. */ diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 48e3c47208f..885d65e50ad 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -4888,6 +4888,14 @@ static void rna_def_modifier_weightvgedit(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Invert Falloff", "Invert the resulting falloff weight"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "normalize", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "edit_flags", MOD_WVG_EDIT_WEIGHTS_NORMALIZE); + RNA_def_property_ui_text( + prop, + "Normalize Weights", + "Normalize the resulting weights (otherwise they are only clamped within [0.0, 1.0] range)"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "map_curve", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "cmap_curve"); RNA_def_property_ui_text(prop, "Mapping Curve", "Custom mapping curve"); @@ -5045,6 +5053,14 @@ static void rna_def_modifier_weightvgmix(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WVG_MIX_INVERT_VGROUP_MASK); RNA_def_property_ui_text(prop, "Invert", "Invert vertex group mask influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "normalize", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WVG_MIX_WEIGHTS_NORMALIZE); + RNA_def_property_ui_text( + prop, + "Normalize Weights", + "Normalize the resulting weights (otherwise they are only clamped within [0.0, 1.0] range)"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); } static void rna_def_modifier_weightvgproximity(BlenderRNA *brna) @@ -5151,6 +5167,15 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Invert Falloff", "Invert the resulting falloff weight"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "normalize", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna( + prop, NULL, "proximity_flags", MOD_WVG_PROXIMITY_WEIGHTS_NORMALIZE); + RNA_def_property_ui_text( + prop, + "Normalize Weights", + "Normalize the resulting weights (otherwise they are only clamped within [0.0, 1.0] range)"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + /* Common masking properties. */ rna_def_modifier_weightvg_mask(brna, srna, diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c index 5dae6bb8505..1a38787777f 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.c +++ b/source/blender/modifiers/intern/MOD_weightvg_util.c @@ -272,16 +272,45 @@ void weightvg_update_vg(MDeformVert *dvert, const bool do_add, const float add_thresh, const bool do_rem, - const float rem_thresh) + const float rem_thresh, + const bool do_normalize) { int i; + float min_w = weights[0]; + float norm_fac = 1.0f; + if (do_normalize) { + float max_w = weights[0]; + for (i = 1; i < num; i++) { + const float w = weights[i]; + + /* No need to clamp here, normalization will ensure we stay within [0.0, 1.0] range. */ + if (w < min_w) { + min_w = w; + } + else if (w > max_w) { + max_w = w; + } + } + + const float range = max_w - min_w; + if (fabsf(range) > FLT_EPSILON) { + norm_fac = 1.0f / range; + } + else { + min_w = 0.0f; + } + } + for (i = 0; i < num; i++) { float w = weights[i]; MDeformVert *dv = &dvert[indices ? indices[i] : i]; MDeformWeight *dw = dws ? dws[i] : ((defgrp_idx >= 0) ? BKE_defvert_find_index(dv, defgrp_idx) : NULL); + if (do_normalize) { + w = (w - min_w) * norm_fac; + } /* Never allow weights out of [0.0, 1.0] range. */ CLAMP(w, 0.0f, 1.0f); diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.h b/source/blender/modifiers/intern/MOD_weightvg_util.h index 09a6a1afb3e..50597d43112 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.h +++ b/source/blender/modifiers/intern/MOD_weightvg_util.h @@ -86,6 +86,7 @@ void weightvg_update_vg(struct MDeformVert *dvert, const bool do_add, const float add_thresh, const bool do_rem, - const float rem_thresh); + const float rem_thresh, + const bool do_normalize); #endif /* __MOD_WEIGHTVG_UTIL_H__ */ diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index 1ff8dfbdcca..8ce1aaee942 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -239,6 +239,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* Do mapping. */ const bool do_invert_mapping = (wmd->edit_flags & MOD_WVG_INVERT_FALLOFF) != 0; + const bool do_normalize = (wmd->edit_flags & MOD_WVG_EDIT_WEIGHTS_NORMALIZE) != 0; if (do_invert_mapping || wmd->falloff_type != MOD_WVG_MAPPING_NONE) { RNG *rng = NULL; @@ -283,7 +284,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * do_add, wmd->add_threshold, do_rem, - wmd->rem_threshold); + wmd->rem_threshold, + do_normalize); /* If weight preview enabled... */ #if 0 /* XXX Currently done in mod stack :/ */ diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index f1db8502d74..57156aec5ec 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -224,6 +224,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * int numIdx = 0; int i; const bool invert_vgroup_mask = (wmd->flag & MOD_WVG_MIX_INVERT_VGROUP_MASK) != 0; + const bool do_normalize = (wmd->flag & MOD_WVG_MIX_WEIGHTS_NORMALIZE) != 0; /* Flags. */ #if 0 const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0; @@ -408,7 +409,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * * XXX Depending on the MOD_WVG_SET_xxx option chosen, we might have to add vertices to vgroup. */ weightvg_update_vg( - dvert, defgrp_index, dw1, numIdx, indices, org_w, true, -FLT_MAX, false, 0.0f); + dvert, defgrp_index, dw1, numIdx, indices, org_w, true, -FLT_MAX, false, 0.0f, do_normalize); /* If weight preview enabled... */ #if 0 /* XXX Currently done in mod stack :/ */ diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 3e746403050..e3f833ff81e 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -429,6 +429,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * int i; const bool invert_vgroup_mask = (wmd->proximity_flags & MOD_WVG_PROXIMITY_INVERT_VGROUP_MASK) != 0; + const bool do_normalize = (wmd->proximity_flags & MOD_WVG_PROXIMITY_WEIGHTS_NORMALIZE) != 0; /* Flags. */ #if 0 const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0; @@ -604,7 +605,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * invert_vgroup_mask); /* Update vgroup. Note we never add nor remove vertices from vgroup here. */ - weightvg_update_vg(dvert, defgrp_index, dw, numIdx, indices, org_w, false, 0.0f, false, 0.0f); + weightvg_update_vg( + dvert, defgrp_index, dw, numIdx, indices, org_w, false, 0.0f, false, 0.0f, do_normalize); /* If weight preview enabled... */ #if 0 /* XXX Currently done in mod stack :/ */ -- cgit v1.2.3