[Bf-blender-cvs] [6b8abefcc6f] master: Make weight paint blur thread safe, and fix smear ignoring mirror.

Alexander Gavrilov noreply at git.blender.org
Sat Oct 7 11:57:20 CEST 2017


Commit: 6b8abefcc6f3ac01632f278b9147ff9b09f5c721
Author: Alexander Gavrilov
Date:   Sat Oct 7 12:45:21 2017 +0300
Branches: master
https://developer.blender.org/rB6b8abefcc6f3ac01632f278b9147ff9b09f5c721

Make weight paint blur thread safe, and fix smear ignoring mirror.

Instead of trying to be clever with swaps and lazy updating the weight
data, simply recalculate one single array. To improve performance, use
threading for that.

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

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 65306f1dd86..aa41e3f3530 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1197,11 +1197,9 @@ struct WPaintData {
 
 	int defbase_tot;
 
-	/* Special storage for smear brush, avoid feedback loop - update each step and swap. */
-	struct {
-		float *weight_prev;
-		float *weight_curr;
-	} smear;
+	/* original weight values for use in blur/smear */
+	float *precomputed_weight;
+	bool precomputed_weight_ready;
 };
 
 /* Initialize the stroke cache invariants from operator properties */
@@ -1427,24 +1425,8 @@ 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);
+	if (ELEM(vp->paint.brush->vertexpaint_tool, PAINT_BLEND_SMEAR, PAINT_BLEND_BLUR)) {
+		wpd->precomputed_weight = MEM_mallocN(sizeof(float) * me->totvert, __func__);
 	}
 
 	/* imat for normals */
@@ -1502,6 +1484,33 @@ static float wpaint_get_active_weight(const MDeformVert *dv, const WeightPaintIn
 	}
 }
 
+static void do_wpaint_precompute_weight_cb_ex(
+        void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
+{
+	SculptThreadedTaskData *data = userdata;
+	const MDeformVert *dv = &data->me->dvert[n];
+
+	data->wpd->precomputed_weight[n] = wpaint_get_active_weight(dv, data->wpi);
+}
+
+static void precompute_weight_values(
+        bContext *C, Object *ob, Brush *brush, struct WPaintData *wpd, WeightPaintInfo *wpi, Mesh *me)
+{
+	if (wpd->precomputed_weight_ready && (brush->flag & BRUSH_ACCUMULATE) == 0)
+		return;
+
+	/* threaded loop over vertices */
+	SculptThreadedTaskData data = {
+		.C = C, .ob = ob, .wpd = wpd, .wpi = wpi, .me = me,
+	};
+
+	BLI_task_parallel_range_ex(
+	        0, me->totvert, &data, NULL, 0, do_wpaint_precompute_weight_cb_ex,
+	        true, false);
+
+	wpd->precomputed_weight_ready = true;
+}
+
 static void do_wpaint_brush_blur_task_cb_ex(
         void *userdata, void *UNUSED(userdata_chunk), const int n, const int UNUSED(thread_id))
 {
@@ -1550,8 +1559,7 @@ static void do_wpaint_brush_blur_task_cb_ex(
 					for (int k = 0; k < mp->totloop; k++) {
 						const int l_index = mp->loopstart + k;
 						const MLoop *ml = &data->me->mloop[l_index];
-						const MDeformVert *dv = &data->me->dvert[ml->v];
-						weight_final += wpaint_get_active_weight(dv, data->wpi);
+						weight_final += data->wpd->precomputed_weight[ml->v];
 					}
 				}
 
@@ -1671,7 +1679,7 @@ static void do_wpaint_brush_smear_task_cb_ex(
 
 									if (stroke_dot > stroke_dot_max) {
 										stroke_dot_max = stroke_dot;
-										weight_final = data->wpd->smear.weight_prev[v_other_index];
+										weight_final = data->wpd->precomputed_weight[v_other_index];
 										do_color = true;
 									}
 								}
@@ -1686,9 +1694,6 @@ 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);
 						}
 					}
 				}
@@ -2054,14 +2059,14 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 	wpi.brush_alpha_value =  brush_alpha_value;
 	/* *** done setting up WeightPaintInfo *** */
 
+	if (wpd->precomputed_weight) {
+		precompute_weight_values(C, ob, brush, wpd, &wpi, ob->data);
+	}
+
 	wpaint_do_symmetrical_brush_actions(C, ob, wp, sd, wpd, &wpi);
 
 	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);
@@ -2109,10 +2114,8 @@ 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);
+		if (wpd->precomputed_weight)
+			MEM_freeN(wpd->precomputed_weight);
 
 		MEM_freeN(wpd);
 	}



More information about the Bf-blender-cvs mailing list