Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2011-09-19 08:53:11 +0400
committerCampbell Barton <ideasman42@gmail.com>2011-09-19 08:53:11 +0400
commit8835a18e2e8521f88a809b78101efc109bd92848 (patch)
tree4951d062938d9ee27b7224f4617d543133af4802 /source/blender/editors/sculpt_paint/paint_vertex.c
parenta89b253aa62021b9fb8cf5881629b136f1c236da (diff)
refactor wpaint_stroke_update_step not to call expensive functions per-vertex and move args passed to do_weight_paint_vertex into WeightPaintInfo structure since there were far too many args to this function.
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_vertex.c')
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c271
1 files changed, 147 insertions, 124 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 46aa1b2e4da..854febc0246 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1161,15 +1161,15 @@ static char has_locked_group(MDeformVert *dvert, char *lock_flags)
* gen_lck_flags gets the status of "flag" for each bDeformGroup
*in ob->defbase and returns an array containing them
*/
-static char *gen_lck_flags(Object* ob, int defbase_len)
+static char *gen_lock_flags(Object* ob, int defbase_tot)
{
char is_locked = FALSE;
int i;
- //int defbase_len = BLI_countlist(&ob->defbase);
- char *lock_flags = MEM_mallocN(defbase_len*sizeof(char), "defflags");
+ //int defbase_tot = BLI_countlist(&ob->defbase);
+ char *lock_flags = MEM_mallocN(defbase_tot*sizeof(char), "defflags");
bDeformGroup *defgroup;
- for(i = 0, defgroup = ob->defbase.first; i < defbase_len && defgroup; defgroup = defgroup->next, i++) {
+ for(i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) {
lock_flags[i] = ((defgroup->flag & DG_LOCK_WEIGHT) != 0);
is_locked |= lock_flags[i];
}
@@ -1181,9 +1181,9 @@ static char *gen_lck_flags(Object* ob, int defbase_len)
return NULL;
}
-static int has_locked_group_selected(int defbase_len, char *defbase_sel, char *lock_flags) {
+static int has_locked_group_selected(int defbase_tot, char *defbase_sel, char *lock_flags) {
int i;
- for(i = 0; i < defbase_len; i++) {
+ for(i = 0; i < defbase_tot; i++) {
if(defbase_sel[i] && lock_flags[i]) {
return TRUE;
}
@@ -1193,12 +1193,12 @@ static int has_locked_group_selected(int defbase_len, char *defbase_sel, char *l
#if 0 /* UNUSED */
-static int has_unselected_unlocked_bone_group(int defbase_len, char *defbase_sel, int selected, char *lock_flags, char *bone_groups) {
+static int has_unselected_unlocked_bone_group(int defbase_tot, char *defbase_sel, int selected, char *lock_flags, char *bone_groups) {
int i;
- if(defbase_len == selected) {
+ if(defbase_tot == selected) {
return FALSE;
}
- for(i = 0; i < defbase_len; i++) {
+ for(i = 0; i < defbase_tot; i++) {
if(bone_groups[i] && !defbase_sel[i] && !lock_flags[i]) {
return TRUE;
}
@@ -1208,12 +1208,12 @@ static int has_unselected_unlocked_bone_group(int defbase_len, char *defbase_sel
#endif
-static void multipaint_selection(MDeformVert *dvert, float change, char *defbase_sel, int defbase_len) {
+static void multipaint_selection(MDeformVert *dvert, float change, char *defbase_sel, int defbase_tot) {
int i;
MDeformWeight *dw;
float val;
// make sure they are all at most 1 after the change
- for(i = 0; i < defbase_len; i++) {
+ for(i = 0; i < defbase_tot; i++) {
if(defbase_sel[i]) {
dw = defvert_find_index(dvert, i);
if(dw && dw->weight) {
@@ -1230,7 +1230,7 @@ static void multipaint_selection(MDeformVert *dvert, float change, char *defbase
}
}
// apply the valid change
- for(i = 0; i < defbase_len; i++) {
+ for(i = 0; i < defbase_tot; i++) {
if(defbase_sel[i]) {
dw = defvert_find_index(dvert, i);
if(dw && dw->weight) {
@@ -1289,7 +1289,7 @@ static float redistribute_change(MDeformVert *ndv, char *change_status, int chan
// observe the changes made to the weights of groups.
// make sure all locked groups on the vertex have the same deformation
// by moving the changes made to groups onto other unlocked groups
-static void enforce_locks(MDeformVert *odv, MDeformVert *ndv, int defbase_len, char *lock_flags, char *bone_groups, char *validmap) {
+static void enforce_locks(MDeformVert *odv, MDeformVert *ndv, int defbase_tot, char *lock_flags, char *bone_groups, char *validmap) {
float totchange = 0.0f;
float totchange_allowed = 0.0f;
float left_over;
@@ -1311,9 +1311,9 @@ static void enforce_locks(MDeformVert *odv, MDeformVert *ndv, int defbase_len, c
return;
}
// record if a group was changed, unlocked and not changed, or locked
- change_status = MEM_callocN(sizeof(char)*defbase_len, "unlocked_unchanged");
+ change_status = MEM_callocN(sizeof(char)*defbase_tot, "unlocked_unchanged");
- for(i = 0; i < defbase_len; i++) {
+ for(i = 0; i < defbase_tot; i++) {
ndw = defvert_find_index(ndv, i);
odw = defvert_find_index(odv, i);
// the weights are zero, so we can assume a lot
@@ -1452,51 +1452,87 @@ static void clamp_weights(MDeformVert *dvert) {
}
}
+/* struct to avoid passing many args each call to do_weight_paint_vertex() */
+typedef struct WeightPaintInfo {
+
+ int defbase_tot;
+
+ /* both must add up to 'defbase_tot' */
+ int defbase_tot_sel;
+ int defbase_tot_unsel;
+
+ int vgroup_mirror; /* mirror group or -1 */
+
+ char *lock_flags; /* boolean array for locked bones,
+ * length of defbase_tot */
+ char *defbase_sel; /* boolean array for selected bones,
+ * length of defbase_tot */
+
+
+ /* TODO, both are the result of wpaint_make_validmap() buy I'm not
+ * convinced they must be separated like this, nevertheless there are
+ * possible side-effects with merging them which need to be looked into
+ * carefully, for now keep both since theres not too much harm in it
+ * but review at some point if bone_group's var can use validmap instead.
+ * - campbell */
+ char *vgroup_validmap;
+ char *bone_groups;
+
+
+ char do_flip;
+ char do_multipaint;
+} WeightPaintInfo;
+
/* fresh start to make multi-paint and locking modular */
-/* returns TRUE if it thinks you need to reset the weights due to normalizing while multi-painting */
-static int apply_mp_lcks_normalize(Mesh *me, int index, MDeformWeight *dw, MDeformWeight *tdw, int defbase_len, float change, float oldChange, float oldw, float neww, char *defbase_sel, int selected, char *bone_groups, char *validmap, char *lock_flags, int multipaint)
+/* returns TRUE if it thinks you need to reset the weights due to
+ * normalizing while multi-painting */
+static int apply_mp_locks_normalize(Mesh *me, WeightPaintInfo *wpi,
+ const int index,
+ MDeformWeight *dw, MDeformWeight *tdw,
+ float change, float oldChange,
+ float oldw, float neww)
{
- MDeformVert *dvert = me->dvert+index;
- MDeformVert dv= {NULL};
+ MDeformVert *dv= me->dvert+index;
+ MDeformVert dv_test= {NULL};
- dv.dw= MEM_dupallocN(dvert->dw);
- dv.flag = dvert->flag;
- dv.totweight = dvert->totweight;
+ dv_test.dw= MEM_dupallocN(dv->dw);
+ dv_test.flag = dv->flag;
+ dv_test.totweight = dv->totweight;
/* do not multi-paint if a locked group is selected or the active group is locked
* !lock_flags[dw->def_nr] helps if nothing is selected, but active group is locked */
- if((lock_flags == NULL) || (lock_flags[dw->def_nr] == FALSE && has_locked_group_selected(defbase_len, defbase_sel, lock_flags) == FALSE)) {
- if(multipaint && selected > 1) {
+ if((wpi->lock_flags == NULL) || (wpi->lock_flags[dw->def_nr] == FALSE && has_locked_group_selected(wpi->defbase_tot, wpi->defbase_sel, wpi->lock_flags) == FALSE)) {
+ if(wpi->do_multipaint && wpi->defbase_tot_sel > 1) {
if(change && change!=1) {
- multipaint_selection(dvert, change, defbase_sel, defbase_len);
+ multipaint_selection(dv, change, wpi->defbase_sel, wpi->defbase_tot);
}
}
else { /* this lets users paint normally, but don't let them paint locked groups */
dw->weight = neww;
}
}
- clamp_weights(dvert);
+ clamp_weights(dv);
- enforce_locks(&dv, dvert, defbase_len, lock_flags, bone_groups, validmap);
+ enforce_locks(&dv_test, dv, wpi->defbase_tot, wpi->lock_flags, wpi->vgroup_validmap, wpi->vgroup_validmap);
- do_weight_paint_auto_normalize_all_groups(dvert, validmap);
+ do_weight_paint_auto_normalize_all_groups(dv, wpi->vgroup_validmap);
- if(oldChange && multipaint && selected > 1) {
+ if(oldChange && wpi->do_multipaint && wpi->defbase_tot_sel > 1) {
if(tdw->weight != oldw) {
if(neww > oldw) {
if(tdw->weight <= oldw) {
- MEM_freeN(dv.dw);
+ MEM_freeN(dv_test.dw);
return TRUE;
}
}
else {
if(tdw->weight >= oldw) {
- MEM_freeN(dv.dw);
+ MEM_freeN(dv_test.dw);
return TRUE;
}
}
}
}
- MEM_freeN(dv.dw);
+ MEM_freeN(dv_test.dw);
return FALSE;
}
@@ -1514,23 +1550,21 @@ static int get_first_selected_nonzero_weight(MDeformVert *dvert, char *defbase_s
return -1;
}
+
static char *wpaint_make_validmap(Object *ob);
-static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index,
- float alpha, float paintweight, int flip,
- int vgroup_mirror, char *validmap, int multipaint)
+
+// int flip, int vgroup_mirror, char *validmap, int multipaint
+static void do_weight_paint_vertex( /* vars which remain the same for every vert */
+ VPaint *wp, Object *ob, WeightPaintInfo *wpi,
+ /* vars which change on each stroke */
+ int index, float alpha, float paintweight
+ )
{
Mesh *me= ob->data;
MDeformWeight *dw, *uw;
int vgroup= ob->actdef-1;
-
- char *lock_flags;
-
- char *defbase_sel;
- int selected;
- int defbase_len;
-
if(wp->flag & VP_ONLYVGROUP) {
dw= defvert_find_index(me->dvert+index, vgroup);
@@ -1543,38 +1577,29 @@ static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index,
if(dw==NULL || uw==NULL)
return;
- lock_flags = gen_lck_flags(ob, defbase_len = BLI_countlist(&ob->defbase));
- defbase_sel = MEM_mallocN(defbase_len * sizeof(char), "dg_selected_flags");
- selected = get_selected_defgroups(ob, defbase_sel, defbase_len);
- if(!selected && ob->actdef) {
- selected = 1;
- }
-
- /* TODO: De-duplicate the simple weight paint */
+ /* TODO: De-duplicate the simple weight paint - jason */
+ /* ... or not, since its <10 SLOC - campbell */
/* If there are no locks or multipaint,
* then there is no need to run the more complicated checks */
- if((multipaint == FALSE || selected <= 1) && (lock_flags == NULL || has_locked_group(&me->dvert[index], lock_flags) == FALSE)) {
- wpaint_blend(wp, dw, uw, alpha, paintweight, flip, FALSE);
- do_weight_paint_auto_normalize_all_groups(me->dvert+index, validmap);
+ if((wpi->do_multipaint == FALSE || wpi->defbase_tot_sel <= 1) && (wpi->lock_flags == NULL || has_locked_group(&me->dvert[index], wpi->lock_flags) == FALSE)) {
+ wpaint_blend(wp, dw, uw, alpha, paintweight, wpi->do_flip, FALSE);
+ do_weight_paint_auto_normalize_all_groups(me->dvert+index, wpi->vgroup_validmap);
if(me->editflag & ME_EDIT_MIRROR_X) { /* x mirror painting */
int j= mesh_get_x_mirror_vert(ob, index);
if(j>=0) {
/* copy, not paint again */
- uw= defvert_verify_index(me->dvert+j, (vgroup_mirror != -1) ? vgroup_mirror : vgroup);
+ uw= defvert_verify_index(me->dvert+j, (wpi->vgroup_mirror != -1) ? wpi->vgroup_mirror : vgroup);
uw->weight= dw->weight;
- do_weight_paint_auto_normalize_all_groups(me->dvert+j, validmap);
+ do_weight_paint_auto_normalize_all_groups(me->dvert+j, wpi->vgroup_validmap);
}
}
}
- else { /* use locks and/or multipaint */
-
- /* Need to know which groups are bone groups */
- char *bone_groups = validmap ? validmap : wpaint_make_validmap(ob);
-
+ else {
+ /* use locks and/or multipaint */
float oldw;
float neww;
float testw=0;
@@ -1584,22 +1609,27 @@ static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index,
MDeformWeight *tdw = NULL, *tuw;
MDeformVert dv= {NULL};
+ /* Need to know which groups are bone groups */
+ if(wpi->bone_groups == NULL) {
+ wpi->bone_groups= wpi->vgroup_validmap ? wpi->vgroup_validmap : wpaint_make_validmap(ob);
+ }
+
oldw = dw->weight;
- wpaint_blend(wp, dw, uw, alpha, paintweight, flip, multipaint && selected >1);
+ wpaint_blend(wp, dw, uw, alpha, paintweight, wpi->do_flip, wpi->do_multipaint && wpi->defbase_tot_sel >1);
neww = dw->weight;
dw->weight = oldw;
// setup multi-paint
- if(selected > 1 && multipaint) {
+ if(wpi->defbase_tot_sel > 1 && wpi->do_multipaint) {
dv.dw= MEM_dupallocN((me->dvert+index)->dw);
dv.flag = me->dvert[index].flag;
dv.totweight = (me->dvert+index)->totweight;
tdw = dw;
tuw = uw;
- change = get_mp_change(wp->wpaint_prev+index, defbase_sel, neww-oldw);
+ change = get_mp_change(wp->wpaint_prev+index, wpi->defbase_sel, neww - oldw);
if(change) {
if(!tdw->weight) {
- i = get_first_selected_nonzero_weight(me->dvert+index, defbase_sel);
+ i = get_first_selected_nonzero_weight(me->dvert+index, wpi->defbase_sel);
if(i>=0) {
tdw = &(me->dvert[index].dw[i]);
tuw = defvert_verify_index(wp->wpaint_prev+index, tdw->def_nr);
@@ -1639,7 +1669,7 @@ static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index,
}
}
- if(apply_mp_lcks_normalize(me, index, dw, tdw, defbase_len, change, oldChange, oldw, neww, defbase_sel, selected, bone_groups, validmap, lock_flags, multipaint)) {
+ if(apply_mp_locks_normalize(me, wpi, index, dw, tdw, change, oldChange, oldw, neww)) {
reset_to_prev(&dv, me->dvert+index);
change = 0;
oldChange = 0;
@@ -1647,28 +1677,21 @@ static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index,
if(dv.dw) {
MEM_freeN(dv.dw);
}
- // dvert may have been altered greatly
+ /* dvert may have been altered greatly */
dw = defvert_find_index(me->dvert+index, vgroup);
if(me->editflag & ME_EDIT_MIRROR_X) { /* x mirror painting */
int j= mesh_get_x_mirror_vert(ob, index);
if(j>=0) {
/* copy, not paint again */
- uw= defvert_verify_index(me->dvert+j, (vgroup_mirror != -1) ? vgroup_mirror : vgroup);
+ uw= defvert_verify_index(me->dvert+j, (wpi->vgroup_mirror != -1) ? wpi->vgroup_mirror : vgroup);
//uw->weight= dw->weight;
- apply_mp_lcks_normalize(me, j, uw, tdw, defbase_len, change, oldChange, oldw, neww, defbase_sel, selected, bone_groups, validmap, lock_flags, multipaint);
+ apply_mp_locks_normalize(me, wpi, j, uw, tdw, change, oldChange, oldw, neww);
}
}
- if(!validmap) {
- MEM_freeN(bone_groups);
- }
}
- if(lock_flags) {
- MEM_freeN(lock_flags);
- }
- MEM_freeN(defbase_sel);
}
@@ -1770,9 +1793,6 @@ static char *wpaint_make_validmap(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, "wpaint_make_validmap gh");
int i = 0, step1=1;
@@ -1793,10 +1813,11 @@ static char *wpaint_make_validmap(Object *ob)
if (md->type == eModifierType_Armature)
{
- amd = (ArmatureModifierData*) md;
+ ArmatureModifierData *amd= (ArmatureModifierData*) md;
if(amd->object && amd->object->pose) {
- pose = amd->object->pose;
+ bPose *pose= amd->object->pose;
+ bPoseChannel *chan;
for (chan=pose->chanbase.first; chan; chan=chan->next) {
if (chan->bone->flag & BONE_NO_DEFORM)
@@ -1921,11 +1942,14 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
float mat[4][4];
float paintweight;
int *indexar;
- int totindex, index, totw, flip;
+ int totindex, index, totw;
float alpha;
float mval[2], pressure;
int use_vert_sel;
+ /* intentionally dont initialize as NULL, make sure we initialize all members below */
+ WeightPaintInfo wpi;
+
/* cannot paint if there is no stroke data */
if (wpd == NULL) {
// XXX: force a redraw here, since even though we can't paint,
@@ -1944,12 +1968,29 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
/* load projection matrix */
mul_m4_m4m4(mat, ob->obmat, vc->rv3d->persmat);
- flip = RNA_boolean_get(itemptr, "pen_flip");
pressure = RNA_float_get(itemptr, "pressure");
RNA_float_get_array(itemptr, "mouse", mval);
mval[0]-= vc->ar->winrct.xmin;
mval[1]-= vc->ar->winrct.ymin;
-
+
+
+
+ /* *** setup WeightPaintInfo - pass onto do_weight_paint_vertex *** */
+ wpi.defbase_tot= BLI_countlist(&ob->defbase);
+ wpi.defbase_sel= MEM_mallocN(wpi.defbase_tot*sizeof(char), "wpi.defbase_sel");
+ wpi.defbase_tot_sel= get_selected_defgroups(ob, wpi.defbase_sel, wpi.defbase_tot);
+ if(wpi.defbase_tot_sel == 0 && ob->actdef) wpi.defbase_tot_sel = 1;
+ wpi.defbase_tot_unsel= wpi.defbase_tot - wpi.defbase_tot_sel;
+ wpi.vgroup_mirror= wpd->vgroup_mirror;
+ wpi.lock_flags= gen_lock_flags(ob, wpi.defbase_tot);
+ wpi.vgroup_validmap= wpd->vgroup_validmap;
+ wpi.bone_groups= NULL; /* initialized on the fly */
+ wpi.do_flip= RNA_boolean_get(itemptr, "pen_flip");
+ wpi.do_multipaint= (ts->multipaint != 0);
+ /* *** done setting up WeightPaintInfo *** */
+
+
+
swap_m4m4(wpd->vc.rv3d->persmat, mat);
use_vert_sel= (me->editflag & ME_EDIT_VERT_SEL) != 0;
@@ -2044,52 +2085,34 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
for(index=0; index<totindex; index++) {
if(indexar[index] && indexar[index]<=me->totface) {
- MFace *mface= me->mface + (indexar[index]-1);
-
- if((me->dvert+mface->v1)->flag) {
- alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v1, mval, pressure);
- if(alpha) {
- do_weight_paint_vertex(wp, ob, mface->v1,
- alpha, paintweight, flip, wpd->vgroup_mirror,
- wpd->vgroup_validmap, ts->multipaint);
- }
- (me->dvert+mface->v1)->flag= 0;
- }
-
- if((me->dvert+mface->v2)->flag) {
- alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v2, mval, pressure);
- if(alpha) {
- do_weight_paint_vertex(wp, ob, mface->v2,
- alpha, paintweight, flip, wpd->vgroup_mirror,
- wpd->vgroup_validmap, ts->multipaint);
- }
- (me->dvert+mface->v2)->flag= 0;
- }
-
- if((me->dvert+mface->v3)->flag) {
- alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v3, mval, pressure);
- if(alpha) {
- do_weight_paint_vertex(wp, ob, mface->v3,
- alpha, paintweight, flip, wpd->vgroup_mirror,
- wpd->vgroup_validmap, ts->multipaint);
- }
- (me->dvert+mface->v3)->flag= 0;
- }
-
- if((me->dvert+mface->v4)->flag) {
- if(mface->v4) {
- alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v4, mval, pressure);
+ MFace *mf= me->mface + (indexar[index]-1);
+ unsigned int fidx= mf->v4 ? 3:2;;
+ do {
+ int vidx= *(&mf->v1 + fidx);
+
+ if(me->dvert[vidx].flag) {
+ alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*vidx, mval, pressure);
if(alpha) {
- do_weight_paint_vertex(wp, ob, mface->v4,
- alpha, paintweight, flip, wpd->vgroup_mirror,
- wpd->vgroup_validmap, ts->multipaint);
+ do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight);
}
- (me->dvert+mface->v4)->flag= 0;
+ me->dvert[vidx].flag= 0;
}
- }
+ } while (fidx--);
}
}
-
+
+
+ /* *** free wpi members */
+ if(wpi.lock_flags) {
+ MEM_freeN(wpi.lock_flags);
+ }
+ if(wpi.bone_groups && (wpi.bone_groups != wpi.vgroup_validmap)) {
+ MEM_freeN(wpi.bone_groups);
+ }
+ MEM_freeN(wpi.defbase_sel);
+ /* *** dont freeing wpi members */
+
+
swap_m4m4(vc->rv3d->persmat, mat);
DAG_id_tag_update(ob->data, 0);