fix [#29431] "Normalize All" from Weight Tools don't work correctly

This commit is contained in:
Campbell Barton 2012-09-05 04:16:09 +00:00
parent a512cac545
commit 99fcec3334
3 changed files with 75 additions and 20 deletions

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

@ -33,6 +33,7 @@
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>
#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;

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