From fe68d2672dcba346a5bbf904a3d46141e5b4c651 Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Fri, 30 Oct 2009 02:09:52 +0000 Subject: [PATCH] added an 'auto-normalize' option for weight paint mode, that automatically ensures vertex groups that affect bones all add up to 1.0. please test and give feedback. --- release/scripts/ui/space_view3d_toolbar.py | 3 +- .../editors/sculpt_paint/paint_vertex.c | 131 +++++++++++++++++- source/blender/makesdna/DNA_scene_types.h | 2 + source/blender/makesrna/intern/rna_scene.c | 6 + 4 files changed, 134 insertions(+), 8 deletions(-) diff --git a/release/scripts/ui/space_view3d_toolbar.py b/release/scripts/ui/space_view3d_toolbar.py index 6ba45ac1cac..1b80a35b504 100644 --- a/release/scripts/ui/space_view3d_toolbar.py +++ b/release/scripts/ui/space_view3d_toolbar.py @@ -519,6 +519,7 @@ class VIEW3D_PT_tools_brush(PaintPanel): elif context.weight_paint_object and brush: layout.itemR(context.tool_settings, "vertex_group_weight", text="Weight", slider=True) + layout.itemR(context.tool_settings, "auto_normalize", text="Auto Normalize") col = layout.column() row = col.row(align=True) @@ -532,7 +533,7 @@ class VIEW3D_PT_tools_brush(PaintPanel): row = col.row(align=True) row.itemR(brush, "jitter", slider=True) row.itemR(brush, "use_jitter_pressure", toggle=True, text="") - + # Vertex Paint Mode # elif context.vertex_paint_object and brush: diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 1dac98780da..4241db0e371 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -43,8 +43,9 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" +#include "BLI_ghash.h" - +#include "DNA_anim_types.h" #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_brush_types.h" @@ -986,7 +987,44 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode) } -static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index, int alpha, float paintweight, int vgroup_mirror) +static void do_weight_paint_auto_normalize(MDeformVert *dvert, + int paint_nr, char *map) +{ + MDeformWeight *dw = dvert->dw; + float sum=0.0f, fac=0.0f, paintw=0.0f; + int i, tot=0; + + if (!map) + return; + + for (i=0; itotweight; i++) { + if (dvert->dw[i].def_nr == paint_nr) + paintw = dvert->dw[i].weight; + + if (map[dvert->dw[i].def_nr]) { + tot += 1; + if (dvert->dw[i].def_nr != paint_nr) + sum += dvert->dw[i].weight; + } + } + + if (!tot || sum <= (1.0f - paintw)) + return; + + fac = sum / (1.0f - paintw); + fac = fac==0.0f ? 1.0f : 1.0f / fac; + + for (i=0; itotweight; i++) { + if (map[dvert->dw[i].def_nr]) { + if (dvert->dw[i].def_nr != paint_nr) + dvert->dw[i].weight *= fac; + } + } +} + +static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index, + int alpha, float paintweight, + int vgroup_mirror, char *validmap) { Mesh *me= ob->data; MDeformWeight *dw, *uw; @@ -1004,7 +1042,8 @@ static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index, int alpha, return; wpaint_blend(wp, dw, uw, (float)alpha/255.0, paintweight); - + do_weight_paint_auto_normalize(me->dvert+index, vgroup, validmap); + if(me->editflag & ME_EDIT_MIRROR_X) { /* x mirror painting */ int j= mesh_get_x_mirror_vert(ob, index); if(j>=0) { @@ -1015,6 +1054,8 @@ static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index, int alpha, uw= ED_vgroup_weight_verify(me->dvert+j, vgroup); uw->weight= dw->weight; + + do_weight_paint_auto_normalize(me->dvert+j, vgroup, validmap); } } } @@ -1208,8 +1249,67 @@ struct WPaintData { int vgroup_mirror; float *vertexcosnos; float wpimat[3][3]; + + /*variables for auto normalize*/ + int auto_normalize; + char *vgroup_validmap; /*stores if vgroups tie to deforming bones or not*/ }; +static char *wpaint_make_validmap(Mesh *me, Object *ob) +{ + bDeformGroup *dg; + ModifierData *md; + char *validmap; + bPose *pose; + bPoseChannel *chan; + ArmatureModifierData *amd; + GHash *gh = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp); + int i = 0; + + /*add all names to a hash table*/ + for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) { + BLI_ghash_insert(gh, dg->name, NULL); + } + + if (!i) + return; + + validmap = MEM_callocN(i, "wpaint valid map"); + + /*now loop through the armature modifiers and identify deform bones*/ + for (md = ob->modifiers.first; md; md=md->next) { + if (!(md->mode & eModifierMode_Realtime)) + continue; + + if (md->type == eModifierType_Armature) + { + amd = (ArmatureModifierData*) md; + pose = amd->object->pose; + + for (chan=pose->chanbase.first; chan; chan=chan->next) { + if (chan->bone->flag & BONE_NO_DEFORM) + continue; + + if (BLI_ghash_haskey(gh, chan->name)) { + BLI_ghash_remove(gh, chan->name, NULL, NULL); + BLI_ghash_insert(gh, chan->name, SET_INT_IN_POINTER(1)); + } + } + } + } + + /*add all names to a hash table*/ + for (dg=ob->defbase.first, i=0; dg; dg=dg->next, i++) { + if (BLI_ghash_lookup(gh, dg->name) != NULL) { + validmap[i] = 1; + } + } + + BLI_ghash_free(gh, NULL, NULL); + + return validmap; +} + static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *event) { Scene *scene= CTX_data_scene(C); @@ -1236,6 +1336,12 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *event) view3d_set_viewcontext(C, &wpd->vc); wpd->vgroup_mirror= -1; + /*set up auto-normalize, and generate map for detecting which + vgroups affect deform bones*/ + wpd->auto_normalize = ts->auto_normalize; + if (wpd->auto_normalize) + wpd->vgroup_validmap = wpaint_make_validmap(me, ob); + // if(qual & LR_CTRLKEY) { // sample_wpaint(scene, ar, v3d, 0); // return; @@ -1417,7 +1523,9 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P if((me->dvert+mface->v1)->flag) { alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v1, mval); if(alpha) { - do_weight_paint_vertex(wp, ob, mface->v1, alpha, paintweight, wpd->vgroup_mirror); + do_weight_paint_vertex(wp, ob, mface->v1, + alpha, paintweight, wpd->vgroup_mirror, + wpd->vgroup_validmap); } (me->dvert+mface->v1)->flag= 0; } @@ -1425,7 +1533,9 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P if((me->dvert+mface->v2)->flag) { alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v2, mval); if(alpha) { - do_weight_paint_vertex(wp, ob, mface->v2, alpha, paintweight, wpd->vgroup_mirror); + do_weight_paint_vertex(wp, ob, mface->v2, + alpha, paintweight, wpd->vgroup_mirror, + wpd->vgroup_validmap); } (me->dvert+mface->v2)->flag= 0; } @@ -1433,7 +1543,9 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P if((me->dvert+mface->v3)->flag) { alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v3, mval); if(alpha) { - do_weight_paint_vertex(wp, ob, mface->v3, alpha, paintweight, wpd->vgroup_mirror); + do_weight_paint_vertex(wp, ob, mface->v3, + alpha, paintweight, wpd->vgroup_mirror, + wpd->vgroup_validmap); } (me->dvert+mface->v3)->flag= 0; } @@ -1442,7 +1554,9 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P if(mface->v4) { alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v4, mval); if(alpha) { - do_weight_paint_vertex(wp, ob, mface->v4, alpha, paintweight, wpd->vgroup_mirror); + do_weight_paint_vertex(wp, ob, mface->v4, + alpha, paintweight, wpd->vgroup_mirror, + wpd->vgroup_validmap); } (me->dvert+mface->v4)->flag= 0; } @@ -1466,6 +1580,9 @@ static void wpaint_stroke_done(bContext *C, struct PaintStroke *stroke) MEM_freeN(wpd->vertexcosnos); MEM_freeN(wpd->indexar); + if (wpd->vgroup_validmap) + MEM_freeN(wpd->vgroup_validmap); + /* frees prev buffer */ copy_wpaint_prev(ts->wpaint, NULL, 0); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index f14f7b58bef..952f62942ef 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -669,6 +669,8 @@ typedef struct ToolSettings { /* Transform */ short snap_mode, snap_flag, snap_target; short proportional, prop_mode; + + int auto_normalize, intpad; /*auto normalizing mode in wpaint*/ } ToolSettings; typedef struct bStats { diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 899d600abcd..d6dbb7cac5f 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -562,6 +562,12 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Sculpt"); RNA_def_property_ui_text(prop, "Sculpt", ""); + prop = RNA_def_property(srna, "auto_normalize", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "auto_normalize", 1); + RNA_def_property_ui_text(prop, "WPaint Auto-Normalize", + "Ensure all bone-deforming vertex groups add up to 1.0 while " + "weight painting"); + prop= RNA_def_property(srna, "vertex_paint", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "vpaint"); RNA_def_property_ui_text(prop, "Vertex Paint", "");