[Bf-blender-cvs] [7395c0c] master: Weight Paint: multi-paint uses collective weights

Alexander Gavrilov noreply at git.blender.org
Wed Jan 20 22:35:38 CET 2016


Commit: 7395c0c88a4dfbcfb5fe3c763a7d938d4f1fd5b5
Author: Alexander Gavrilov
Date:   Tue Jan 19 14:54:47 2016 +0300
Branches: master
https://developer.blender.org/rB7395c0c88a4dfbcfb5fe3c763a7d938d4f1fd5b5

Weight Paint: multi-paint uses collective weights

Similarly, the displayed weight distribution should be used as the
target of brush application instead of the invisible active group.

Multi-paint is split into a new function because all the calls to
defvert_verify_index at the top of the old code should never be
done in multi-paint mode.

===================================================================

M	source/blender/editors/sculpt_paint/paint_vertex.c

===================================================================

diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 572d19d..978bc27 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1338,22 +1338,6 @@ static void do_weight_paint_normalize_all_locked_try_active(
 	}
 }
 
-/*
- * See if the current deform vertex has a locked group
- */
-
-static bool has_locked_group_selected(int defbase_tot, const bool *defbase_sel, const bool *lock_flags)
-{
-	int i;
-	for (i = 0; i < defbase_tot; i++) {
-		if (defbase_sel[i] && lock_flags[i]) {
-			return true;
-		}
-	}
-	return false;
-}
-
-
 #if 0 /* UNUSED */
 static bool has_unselected_unlocked_bone_group(int defbase_tot, bool *defbase_sel, int selected,
                                                const bool *lock_flags, const bool *vgroup_validmap)
@@ -1371,43 +1355,72 @@ static bool has_unselected_unlocked_bone_group(int defbase_tot, bool *defbase_se
 }
 #endif
 
-
-static void multipaint_selection(MDeformVert *dvert, const int defbase_tot, float change, const bool *defbase_sel)
+static void multipaint_clamp_change(
+        MDeformVert *dvert, const int defbase_tot, const bool *defbase_sel,
+        float *change_p)
 {
 	int i;
 	MDeformWeight *dw;
 	float val;
-	/* make sure they are all at most 1 after the change */
-	for (i = 0; i < defbase_tot; i++) {
-		if (defbase_sel[i]) {
-			dw = defvert_find_index(dvert, i);
-			if (dw && dw->weight) {
+	float change = *change_p;
+
+	/* verify that the change does not cause values exceeding 1 and clamp it */
+	for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+		if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
+			if (dw->weight) {
 				val = dw->weight * change;
 				if (val > 1) {
-					/* TODO: when the change is reduced, you need to recheck
-					 * the earlier values to make sure they are not 0
-					 * (precision error) */
 					change = 1.0f / dw->weight;
 				}
+			}
+		}
+	}
+
+	*change_p = change;
+}
+
+static bool multipaint_verify_change(MDeformVert *dvert, const int defbase_tot, float change, const bool *defbase_sel)
+{
+	int i;
+	MDeformWeight *dw;
+	float val;
+
+	/* in case the change is reduced, you need to recheck
+	 * the earlier values to make sure they are not 0
+	 * (precision error) */
+	for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+		if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
+			if (dw->weight) {
+				val = dw->weight * change;
 				/* the value should never reach zero while multi-painting if it
 				 * was nonzero beforehand */
 				if (val <= 0) {
-					return;
+					return false;
 				}
 			}
 		}
 	}
+
+	return true;
+}
+
+static void multipaint_apply_change(MDeformVert *dvert, const int defbase_tot, float change, const bool *defbase_sel)
+{
+	int i;
+	MDeformWeight *dw;
+
 	/* apply the valid change */
-	for (i = 0; i < defbase_tot; i++) {
-		if (defbase_sel[i]) {
-			dw = defvert_find_index(dvert, i);
-			if (dw && dw->weight) {
+	for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) {
+		if (dw->def_nr < defbase_tot && defbase_sel[dw->def_nr]) {
+			if (dw->weight) {
 				dw->weight = dw->weight * change;
+				CLAMP(dw->weight, 0.0f, 1.0f);
 			}
 		}
 	}
 }
 
+#if 0
 /* multi-paint's initial, potential change is computed here based on the user's stroke */
 static float get_mp_change(MDeformVert *odv, const int defbase_tot, const bool *defbase_sel, float brush_change)
 {
@@ -1450,6 +1463,7 @@ static void clamp_weights(MDeformVert *dvert)
 		CLAMP(dw->weight, 0.0f, 1.0f);
 	}
 }
+#endif
 
 /**
  * Variables stored both for 'active' and 'mirror' sides.
@@ -1499,83 +1513,7 @@ typedef struct WeightPaintInfo {
 	float brush_alpha_value;  /* result of BKE_brush_alpha_get() */
 } 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
- *
- * note: this assumes dw->def_nr range has been checked by the caller
- */
-static int apply_mp_locks_normalize(Mesh *me, const WeightPaintInfo *wpi,
-                                    const unsigned int index,
-                                    MDeformWeight *dw, MDeformWeight *tdw,
-                                    float change, float oldChange,
-                                    float oldw, float neww)
-{
-	MDeformVert *dv = &me->dvert[index];
-	MDeformVert dv_test = {NULL};
-
-	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 ((wpi->lock_flags == NULL) ||
-	    ((wpi->lock_flags[dw->def_nr] == false) && /* def_nr range has to be checked for by caller */
-	     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(dv, wpi->defbase_tot, change, wpi->defbase_sel);
-			}
-		}
-		else { /* this lets users paint normally, but don't let them paint locked groups */
-			dw->weight = neww;
-		}
-	}
-	clamp_weights(dv);
-
-	if (wpi->do_auto_normalize) {
-		do_weight_paint_normalize_all_locked_try_active(
-		        dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->active.lock);
-	}
-
-	if (oldChange && wpi->do_multipaint && wpi->defbase_tot_sel > 1) {
-		if (tdw->weight != oldw) {
-			if (neww > oldw) {
-				if (tdw->weight <= oldw) {
-					MEM_freeN(dv_test.dw);
-					return true;
-				}
-			}
-			else {
-				if (tdw->weight >= oldw) {
-					MEM_freeN(dv_test.dw);
-					return true;
-				}
-			}
-		}
-	}
-	MEM_freeN(dv_test.dw);
-	return false;
-}
-
-/* within the current dvert index, get the dw that is selected and has a weight
- * above 0, this helps multi-paint */
-static int get_first_selected_nonzero_weight(MDeformVert *dvert, const int defbase_tot, const bool *defbase_sel)
-{
-	int i;
-	MDeformWeight *dw = dvert->dw;
-	for (i = 0; i < dvert->totweight; i++, dw++) {
-		if (dw->def_nr < defbase_tot) {
-			if (defbase_sel[dw->def_nr] && dw->weight > 0.0f) {
-				return i;
-			}
-		}
-	}
-	return -1;
-}
-
-static void do_weight_paint_vertex(
+static void do_weight_paint_vertex_single(
         /* vars which remain the same for every vert */
         VPaint *wp, Object *ob, const WeightPaintInfo *wpi,
         /* vars which change on each stroke */
@@ -1661,7 +1599,7 @@ static void do_weight_paint_vertex(
 	/* If there are no normalize-locks or multipaint,
 	 * then there is no need to run the more complicated checks */
 
-	if (wpi->do_multipaint == false) {
+	{
 		dw->weight = wpaint_blend(wp, dw->weight, dw_prev->weight, alpha, paintweight,
 		                          wpi->brush_alpha_value, wpi->do_flip, false);
 
@@ -1718,6 +1656,7 @@ static void do_weight_paint_vertex(
 			}
 		}
 	}
+#if 0
 	else {
 		/* use locks and/or multipaint */
 		float oldw;
@@ -1810,8 +1749,112 @@ static void do_weight_paint_vertex(
 			apply_mp_locks_normalize(me, wpi, index_mirr, dw_mirr, tdw, change, oldChange, oldw, neww);
 		}
 	}
+#endif
+}
+
+static void do_weight_paint_vertex_multi(
+        /* vars which remain the same for every vert */
+        VPaint *wp, Object *ob, const WeightPaintInfo *wpi,
+        /* vars which change on each stroke */
+        const unsigned int index, float alpha, float paintweight)
+{
+	Mesh *me = ob->data;
+	MDeformVert *dv = &me->dvert[index];
+	MDeformVert *dv_prev = &wp->wpaint_prev[index];
+	bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+
+	/* mirror vars */
+	int index_mirr = -1;
+	MDeformVert *dv_mirr = NULL;
+
+	/* weights */
+	float oldw, curw, neww, change, curw_mirr, change_mirr;
+
+	/* from now on we can check if mirrors enabled if this var is -1 and not bother with the flag */
+	if (me->editflag & ME_EDIT_MIRROR_X) {
+		index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, topology);
+
+		if (index_mirr != -1 && index_mirr != index) {
+			dv_mirr = &me->dvert[index_mirr];
+		}
+	}
+
+	/* compute weight change by applying the brush to average or sum of group weights */
+	oldw = BKE_defvert_multipaint_collective_weight(
+	        dv_prev, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->do_auto_normalize);
+	curw = BKE_defvert_multipaint_collective_weight(
+	        dv, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->do_auto_normalize);
+
+	if (curw == 0.0f) {
+		/* note: no weight to assign to this vertex, could add all groups? */
+		return;
+	}
+
+	neww = wpaint_blend(wp, curw, oldw, alpha, paintweight, wpi->brush_alpha_value, wpi->do_flip, false);
+
+	change = neww / curw;
+
+	/* verify for all groups that 0 < result <= 1 */
+	multipaint_clamp_change(dv, wpi->defbase_tot, wpi->defbase_sel, &change);
+
+	if (dv_mirr != NULL) {
+		curw_mirr = BKE_defvert_multipaint_collective_weight(
+		        dv_mirr, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->do_auto_normalize);
+
+		if (curw_mirr == 0.0f) {
+			/* can't mirror into a zero weight vertex */
+			dv_mirr = NULL;
+		}
+		else {
+			/* mirror is changed to achieve the same collective weight value */
+			float orig = change_mirr = curw * change / curw_mirr;
+
+			multipaint_clamp_change(dv_mirr, wpi->defbase_tot, wpi->defbase_sel, &change_mirr);
+
+			if (!multipaint_verify_change(dv_mirr, wpi->defbase_tot, change_mirr, wpi->defbase_sel)) {
+				return;
+			}
+
+			change *= change_mirr / orig;
+		}
+	}
+
+	if (!multipaint_verify_change(dv, wpi->defbase_tot, change, wpi->defbase_sel)) {
+		return;
+	}
+
+	/* apply validated change to vertex and mirror */
+	multipaint_apply_change(dv, wpi->defbase_tot, change, wpi->defbase_sel);
+
+	if (dv_mirr != NULL) {
+		multipaint_apply_change(dv_mirr, wpi->defbase_tot, change_mirr, wpi->defbase_sel);
+	}
+
+	/* normalize */
+	if (wpi->do_auto_normalize) {
+		do_weight_paint_normalize_all_locked_try_active(
+		        dv, wpi->defbase_tot, wpi->vgroup_validmap, wpi->lock_flags, wpi->active.lock);
+
+		if (dv_mirr != NULL) {
+			do_weight_paint_normalize

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list