From 99fcec33347c94228ca0c225dcbdd7cb6117e99b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 5 Sep 2012 04:16:09 +0000 Subject: [PATCH] fix [#29431] "Normalize All" from Weight Tools don't work correctly --- source/blender/blenkernel/BKE_deform.h | 3 +- source/blender/blenkernel/intern/deform.c | 52 ++++++++++++++++++- source/blender/editors/object/object_vgroup.c | 40 ++++++++------ 3 files changed, 75 insertions(+), 20 deletions(-) diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 25677165fc2..52a143ddf55 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -67,7 +67,8 @@ void defvert_remap(struct MDeformVert *dvert, int *map, const int map_len); void defvert_flip(struct MDeformVert *dvert, const int *flip_map, const int flip_map_len); void defvert_flip_merged(struct MDeformVert *dvert, const int *flip_map, const int flip_map_len); void defvert_normalize(struct MDeformVert *dvert); -void defvert_normalize_lock(struct MDeformVert *dvert, const int def_nr_lock); +void defvert_normalize_lock_single(struct MDeformVert *dvert, const int def_nr_lock); +void defvert_normalize_lock_map(struct MDeformVert *dvert, const char *lock_flags, const int defbase_tot); /* utility function, note that MAX_VGROUP_NAME chars is the maximum string length since its only * used with defgroups currently */ diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index aef9543a8e2..4110d4565b2 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "MEM_guardedalloc.h" @@ -41,7 +42,10 @@ #include "BKE_deform.h" -#include "BLI_blenlib.h" +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_path_util.h" +#include "BLI_string.h" #include "BLI_utildefines.h" @@ -204,7 +208,7 @@ void defvert_normalize(MDeformVert *dvert) } } -void defvert_normalize_lock(MDeformVert *dvert, const int def_nr_lock) +void defvert_normalize_lock_single(MDeformVert *dvert, const int def_nr_lock) { if (dvert->totweight <= 0) { /* nothing */ @@ -248,6 +252,50 @@ void defvert_normalize_lock(MDeformVert *dvert, const int def_nr_lock) } } +void defvert_normalize_lock_map(MDeformVert *dvert, const char *lock_flags, const int defbase_tot) +{ + if (dvert->totweight <= 0) { + /* nothing */ + } + else if (dvert->totweight == 1) { + if (LIKELY(defbase_tot >= 1) && lock_flags[0]) { + dvert->dw[0].weight = 1.0f; + } + } + else { + MDeformWeight *dw; + unsigned int i; + float tot_weight = 0.0f; + 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; + } + } + + lock_iweight = maxf(0.0f, 1.0f - lock_iweight); + + if (tot_weight > 0.0f) { + /* paranoid, should be 1.0 but in case of float error clamp anyway */ + + 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; + + /* in case of division errors with very low weights */ + CLAMP(dw->weight, 0.0f, 1.0f); + } + } + } + } +} + void defvert_flip(MDeformVert *dvert, const int *flip_map, const int flip_map_len) { MDeformWeight *dw; diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index b13a299c4c7..c8ba9240db3 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -62,6 +62,7 @@ #include "BKE_tessmesh.h" #include "BKE_report.h" #include "BKE_DerivedMesh.h" +#include "BKE_object_deform.h" #include "RNA_access.h" #include "RNA_define.h" @@ -1136,7 +1137,6 @@ static void vgroup_levels(Object *ob, float offset, float gain) } } -/* TODO - select between groups */ static void vgroup_normalize_all(Object *ob, int lock_active) { MDeformVert *dv, **dvert_array = NULL; @@ -1152,27 +1152,33 @@ static void vgroup_normalize_all(Object *ob, int lock_active) ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot, use_vert_sel); if (dvert_array) { - if (lock_active) { + const int defbase_tot = BLI_countlist(&ob->defbase); + char *lock_flags = BKE_objdef_lock_flags_get(ob, defbase_tot); - for (i = 0; i < dvert_tot; i++) { - /* in case its not selected */ - if (!(dv = dvert_array[i])) { - continue; + if ((lock_active == TRUE) && + (lock_flags != NULL) && + (def_nr < defbase_tot)) + { + lock_flags[def_nr] = TRUE; + } + + for (i = 0; i < dvert_tot; i++) { + /* in case its not selected */ + if ((dv = dvert_array[i])) { + if (lock_flags) { + defvert_normalize_lock_map(dv, lock_flags, defbase_tot); + } + else if (lock_active) { + defvert_normalize_lock_single(dv, def_nr); + } + else { + defvert_normalize(dv); } - - defvert_normalize_lock(dv, def_nr); } } - else { - for (i = 0; i < dvert_tot; i++) { - /* in case its not selected */ - if (!(dv = dvert_array[i])) { - continue; - } - - defvert_normalize(dv); - } + if (lock_flags) { + MEM_freeN(lock_flags); } MEM_freeN(dvert_array);