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
This commit is contained in:
Cody Winchester 2020-05-26 20:53:38 +02:00 committed by Bastien Montagne
parent 00674c12cc
commit de257b6366
10 changed files with 92 additions and 7 deletions

View File

@ -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)

View File

@ -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

View File

@ -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.
*

View File

@ -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. */

View File

@ -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,

View File

@ -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);

View File

@ -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__ */

View File

@ -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 :/ */

View File

@ -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 :/ */

View File

@ -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 :/ */