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:
authorAlexander Gavrilov <angavrilov@gmail.com>2017-10-07 12:45:21 +0300
committerAlexander Gavrilov <angavrilov@gmail.com>2017-10-07 12:45:21 +0300
commit6b8abefcc6f3ac01632f278b9147ff9b09f5c721 (patch)
treec287e3b0ecc4517bc3ec534ae6c92980e5780b26 /source/blender/editors/sculpt_paint
parent83ce02879f7c6733adc098d00a01963fc4212abd (diff)
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.
Diffstat (limited to 'source/blender/editors/sculpt_paint')
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c77
1 files changed, 40 insertions, 37 deletions
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);
}