fix [#29431] "Normalize All" from Weight Tools don't work correctly
authorCampbell Barton <ideasman42@gmail.com>
Wed, 5 Sep 2012 04:16:09 +0000 (04:16 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 5 Sep 2012 04:16:09 +0000 (04:16 +0000)
source/blender/blenkernel/BKE_deform.h
source/blender/blenkernel/intern/deform.c
source/blender/editors/object/object_vgroup.c

index 25677165fc2c6bdf6901ef6be8be13ebcb2b3286..52a143ddf55a96b65577f92010b18359dd684f15 100644 (file)
@@ -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 */
index aef9543a8e2376cb70498f6c0e59ea293bd6ac3e..4110d4565b2319936c994efdfd2c98ee167e468f 100644 (file)
@@ -33,6 +33,7 @@
 #include <string.h>
 #include <math.h>
 #include <ctype.h>
+#include <stdlib.h>
 
 #include "MEM_guardedalloc.h"
 
 
 #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;
index b13a299c4c79a2dfbcbb4fd13d2587cf4155d3b5..c8ba9240db37c9a044108ce8be25b69bce7b517e 100644 (file)
@@ -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,29 +1152,35 @@ 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;
-                               }
-
-                               defvert_normalize_lock(dv, def_nr);
-                       }
+               if ((lock_active == TRUE) &&
+                   (lock_flags != NULL) &&
+                   (def_nr < defbase_tot))
+               {
+                       lock_flags[def_nr] = TRUE;
                }
-               else {
-                       for (i = 0; i < dvert_tot; i++) {
 
-                               /* in case its not selected */
-                               if (!(dv = dvert_array[i])) {
-                                       continue;
+               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(dv);
                        }
                }
 
+               if (lock_flags) {
+                       MEM_freeN(lock_flags);
+               }
+
                MEM_freeN(dvert_array);
        }
 }