[Bf-blender-cvs] [6a7dc3348ad] master: Vertex Paint: fix feedback loop w/ smear tool

Campbell Barton noreply at git.blender.org
Tue Oct 3 13:59:18 CEST 2017


Commit: 6a7dc3348ad9ad00d2827372bd4860dc36dc4163
Author: Campbell Barton
Date:   Tue Oct 3 23:04:22 2017 +1100
Branches: master
https://developer.blender.org/rB6a7dc3348ad9ad00d2827372bd4860dc36dc4163

Vertex Paint: fix feedback loop w/ smear tool

Was reading and writing from same array,
this also makes smear thread-safe.

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

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 98732e0bb9e..ce232030819 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1198,6 +1198,12 @@ struct WPaintData {
 	bool do_multipaint;           /* true if multipaint enabled and multiple groups selected */
 
 	int defbase_tot;
+
+	/* Special storage for smear brush, avoid feedback loop - update each step and swap. */
+	struct {
+		float *weight_prev;
+		float *weight_curr;
+	} smear;
 };
 
 /* Initialize the stroke cache invariants from operator properties */
@@ -1422,6 +1428,26 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
 		wpd->mirror.lock = tmpflags;
 	}
 
+	if (vp->paint.brush->vertexpaint_tool == PAINT_BLEND_SMEAR) {
+		wpd->smear.weight_prev = MEM_mallocN(sizeof(float) * me->totvert, __func__);
+		const MDeformVert *dv = me->dvert;
+		if (wpd->do_multipaint) {
+			const bool do_auto_normalize = ((ts->auto_normalize != 0) && (wpd->vgroup_validmap != NULL));
+			for (int i = 0; i < me->totvert; i++, dv++) {
+				float weight = BKE_defvert_multipaint_collective_weight(
+				        dv, wpd->defbase_tot, wpd->defbase_sel, wpd->defbase_tot_sel, do_auto_normalize);
+				CLAMP(weight, 0.0f, 1.0f);
+				wpd->smear.weight_prev[i] = weight;
+			}
+		}
+		else {
+			for (int i = 0; i < me->totvert; i++, dv++) {
+				wpd->smear.weight_prev[i] = defvert_find_weight(dv, wpd->active.index);
+			}
+		}
+		wpd->smear.weight_curr = MEM_dupallocN(wpd->smear.weight_prev);
+	}
+
 	/* painting on subsurfs should give correct points too, this returns me->totvert amount */
 	ob->sculpt->building_vp_handle = true;
 	wpd->vp_handle = ED_vpaint_proj_handle_create(scene, ob, &wpd->vertexcosnos);
@@ -1663,8 +1689,7 @@ static void do_wpaint_brush_smear_task_cb_ex(
 
 									if (stroke_dot > stroke_dot_max) {
 										stroke_dot_max = stroke_dot;
-										MDeformVert *dv = &data->me->dvert[v_other_index];
-										weight_final = wpaint_get_active_weight(dv, data->wpi);
+										weight_final = data->wpd->smear.weight_prev[v_other_index];
 										do_color = true;
 									}
 								}
@@ -1679,6 +1704,9 @@ static void do_wpaint_brush_smear_task_cb_ex(
 							do_weight_paint_vertex(
 							        data->vp, data->ob, data->wpi,
 							        v_index, final_alpha, (float)weight_final);
+							/* Access the weight again because it might not have been applied completely. */
+							data->wpd->smear.weight_curr[v_index] =
+							        wpaint_get_active_weight(&data->me->dvert[v_index], data->wpi);
 						}
 					}
 				}
@@ -2044,6 +2072,10 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 
 	swap_m4m4(vc->rv3d->persmat, mat);
 
+	if (wp->paint.brush->vertexpaint_tool == PAINT_BLEND_SMEAR) {
+		SWAP(float *, wpd->smear.weight_curr, wpd->smear.weight_prev);
+	}
+
 	/* calculate pivot for rotation around seletion if needed */
 	/* also needed for "View Selected" on last stroke */
 	paint_last_stroke_update(scene, vc->ar, mval);
@@ -2093,6 +2125,10 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
 			MEM_freeN((void *)wpd->active.lock);
 		if (wpd->mirror.lock)
 			MEM_freeN((void *)wpd->mirror.lock);
+		if (wpd->smear.weight_prev)
+			MEM_freeN(wpd->smear.weight_prev);
+		if (wpd->smear.weight_curr)
+			MEM_freeN(wpd->smear.weight_curr);
 
 		MEM_freeN(wpd);
 	}
@@ -2323,6 +2359,12 @@ struct VPaintData {
 	bool *mlooptag;
 
 	bool is_texbrush;
+
+	/* Special storage for smear brush, avoid feedback loop - update each step and swap. */
+	struct {
+		uint *color_prev;
+		uint *color_curr;
+	} smear;
 };
 
 static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float mouse[2])
@@ -2374,6 +2416,12 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
 		vpd->mlooptag = MEM_mallocN(sizeof(bool) * me->totloop, "VPaintData mlooptag");
 	}
 
+	if (brush->vertexpaint_tool == PAINT_BLEND_SMEAR) {
+		vpd->smear.color_prev = MEM_mallocN(sizeof(uint) * me->totloop, __func__);
+		memcpy(vpd->smear.color_prev, me->mloopcol, sizeof(uint) * me->totloop);
+		vpd->smear.color_curr = MEM_dupallocN(vpd->smear.color_prev);
+	}
+
 	/* Create projection handle */
 	if (vpd->is_texbrush) {
 		ob->sculpt->building_vp_handle = true;
@@ -2747,7 +2795,7 @@ static void do_vpaint_brush_smear_task_cb_ex(
 
 										if (stroke_dot > stroke_dot_max) {
 											stroke_dot_max = stroke_dot;
-											color_final = lcol[mp->loopstart + k];
+											color_final = data->vpd->smear.color_prev[mp->loopstart + k];
 											do_color = true;
 										}
 									}
@@ -2780,6 +2828,8 @@ static void do_vpaint_brush_smear_task_cb_ex(
 									lcol[l_index] = vpaint_blend(
 									        data->vp, lcol[l_index], color_orig, color_final,
 									        final_alpha, 255 * brush_strength);
+
+									data->vpd->smear.color_curr[l_index] = lcol[l_index];
 								}
 							}
 						}
@@ -2955,6 +3005,10 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 
 	swap_m4m4(vc->rv3d->persmat, mat);
 
+	if (vp->paint.brush->vertexpaint_tool == PAINT_BLEND_SMEAR) {
+		SWAP(uint *, vpd->smear.color_curr, vpd->smear.color_prev);
+	}
+
 	/* calculate pivot for rotation around seletion if needed */
 	/* also needed for "View Selected" on last stroke */
 	paint_last_stroke_update(scene, vc->ar, mval);
@@ -2980,6 +3034,10 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
 
 	if (vpd->mlooptag)
 		MEM_freeN(vpd->mlooptag);
+	if (vpd->smear.color_prev)
+		MEM_freeN(vpd->smear.color_prev);
+	if (vpd->smear.color_curr)
+		MEM_freeN(vpd->smear.color_curr);
 
 	WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);



More information about the Bf-blender-cvs mailing list