added an 'auto-normalize' option for weight paint mode, that automatically ensures...
authorJoseph Eagar <joeedh@gmail.com>
Fri, 30 Oct 2009 02:09:52 +0000 (02:09 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Fri, 30 Oct 2009 02:09:52 +0000 (02:09 +0000)
release/scripts/ui/space_view3d_toolbar.py
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_scene.c

index 6ba45ac..1b80a35 100644 (file)
@@ -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:
index 1dac987..4241db0 100644 (file)
@@ -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; i<dvert->totweight; 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; i<dvert->totweight; 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);
        
index f14f7b5..952f629 100644 (file)
@@ -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 {
index 899d600..d6dbb7c 100644 (file)
@@ -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", "");