From 4be74273462bbee7ba14dc660a53d769dee235e4 Mon Sep 17 00:00:00 2001 From: Irie Shinsuke Date: Thu, 10 Oct 2013 06:33:23 +0000 Subject: Weight Paint Tools: Add "Subset" option to "Normalize All" This option is needed when vertex groups are used for both armature deformation and the other purpose such as influence of mesh modifier. Thanks to Campbell for code review! --- source/blender/blenkernel/intern/deform.c | 115 +++++++++++++++++++----------- 1 file changed, 73 insertions(+), 42 deletions(-) (limited to 'source/blender/blenkernel/intern/deform.c') diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 882085aa5db..a183872552d 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -217,24 +217,35 @@ void defvert_remap(MDeformVert *dvert, int *map, const int map_len) void defvert_normalize_subset(MDeformVert *dvert, const bool *vgroup_subset, const int vgroup_tot) { - MDeformWeight *dw; - unsigned int i; - float tot_weight = 0.0f; - - for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { + if (dvert->totweight == 0) { + /* nothing */ + } + else if (dvert->totweight == 1) { + MDeformWeight *dw = dvert->dw; if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { - tot_weight += dw->weight; + dw->weight = 1.0f; } } + else { + MDeformWeight *dw; + unsigned int i; + float tot_weight = 0.0f; - if (tot_weight > 0.0f) { - float scalar = 1.0f / tot_weight; for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { - dw->weight *= scalar; - - /* in case of division errors with very low weights */ - CLAMP(dw->weight, 0.0f, 1.0f); + tot_weight += dw->weight; + } + } + + if (tot_weight > 0.0f) { + float scalar = 1.0f / tot_weight; + for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { + if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + dw->weight *= scalar; + + /* in case of division errors with very low weights */ + CLAMP(dw->weight, 0.0f, 1.0f); + } } } } @@ -242,7 +253,7 @@ void defvert_normalize_subset(MDeformVert *dvert, void defvert_normalize(MDeformVert *dvert) { - if (dvert->totweight <= 0) { + if (dvert->totweight == 0) { /* nothing */ } else if (dvert->totweight == 1) { @@ -269,14 +280,20 @@ void defvert_normalize(MDeformVert *dvert) } } -void defvert_normalize_lock_single(MDeformVert *dvert, const int def_nr_lock) +/* Same as defvert_normalize() if the locked vgroup is not a member of the subset */ +void defvert_normalize_lock_single(MDeformVert *dvert, + const bool *vgroup_subset, const int vgroup_tot, + const int def_nr_lock) { - if (dvert->totweight <= 0) { + if (dvert->totweight == 0) { /* nothing */ } else if (dvert->totweight == 1) { - if (def_nr_lock != 0) { - dvert->dw[0].weight = 1.0f; + MDeformWeight *dw = dvert->dw; + if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if (def_nr_lock != 0) { + dw->weight = 1.0f; + } } } else { @@ -287,13 +304,15 @@ void defvert_normalize_lock_single(MDeformVert *dvert, const int def_nr_lock) float lock_iweight = 1.0f; for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { - if (dw->def_nr != def_nr_lock) { - tot_weight += dw->weight; - } - else { - dw_lock = dw; - lock_iweight = (1.0f - dw_lock->weight); - CLAMP(lock_iweight, 0.0f, 1.0f); + if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if (dw->def_nr != def_nr_lock) { + tot_weight += dw->weight; + } + else { + dw_lock = dw; + lock_iweight = (1.0f - dw_lock->weight); + CLAMP(lock_iweight, 0.0f, 1.0f); + } } } @@ -302,25 +321,33 @@ void defvert_normalize_lock_single(MDeformVert *dvert, const int def_nr_lock) float scalar = (1.0f / tot_weight) * lock_iweight; for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { - if (dw != dw_lock) { - dw->weight *= scalar; + if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if (dw != dw_lock) { + dw->weight *= scalar; - /* in case of division errors with very low weights */ - CLAMP(dw->weight, 0.0f, 1.0f); + /* in case of division errors with very low weights */ + CLAMP(dw->weight, 0.0f, 1.0f); + } } } } } } -void defvert_normalize_lock_map(MDeformVert *dvert, const bool *lock_flags, const int defbase_tot) +/* Same as defvert_normalize() if no locked vgroup is a member of the subset */ +void defvert_normalize_lock_map(MDeformVert *dvert, + const bool *vgroup_subset, const int vgroup_tot, + const bool *lock_flags, const int defbase_tot) { - if (dvert->totweight <= 0) { + if (dvert->totweight == 0) { /* nothing */ } else if (dvert->totweight == 1) { - if (LIKELY(defbase_tot >= 1) && lock_flags[0]) { - dvert->dw[0].weight = 1.0f; + MDeformWeight *dw = dvert->dw; + if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if (LIKELY(defbase_tot >= 1) && lock_flags[0]) { + dw->weight = 1.0f; + } } } else { @@ -330,12 +357,14 @@ void defvert_normalize_lock_map(MDeformVert *dvert, const bool *lock_flags, cons float lock_iweight = 0.0f; for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { - if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) { - tot_weight += dw->weight; - } - else { - /* invert after */ - lock_iweight += dw->weight; + if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) { + tot_weight += dw->weight; + } + else { + /* invert after */ + lock_iweight += dw->weight; + } } } @@ -346,11 +375,13 @@ void defvert_normalize_lock_map(MDeformVert *dvert, const bool *lock_flags, cons float scalar = (1.0f / tot_weight) * lock_iweight; for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { - if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) { - dw->weight *= scalar; + if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) { + dw->weight *= scalar; - /* in case of division errors with very low weights */ - CLAMP(dw->weight, 0.0f, 1.0f); + /* in case of division errors with very low weights */ + CLAMP(dw->weight, 0.0f, 1.0f); + } } } } -- cgit v1.2.3