Weight Paint: support accumulate for blur brush

This re-applies smoothing based on the previous update.

Can smooth more but harder to get such even distribution.
This commit is contained in:
Campbell Barton 2016-03-23 01:22:26 +11:00
parent e2181c2ef2
commit 84d8b35d6c
Notes: blender-bot 2023-02-14 12:33:44 +01:00
Referenced by issue #34596, Weight Paint: Blur brush performs paint with average rather than true blur.
2 changed files with 58 additions and 9 deletions

View File

@ -1055,6 +1055,10 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
col.prop(brush, "vertex_tool", text="Blend")
if brush.vertex_tool == 'BLUR':
col.prop(brush, "use_accumulate")
col.separator()
col = layout.column()
col.prop(toolsettings, "use_auto_normalize", text="Auto Normalize")
col.prop(toolsettings, "use_multipaint", text="Multi-Paint")

View File

@ -35,6 +35,7 @@
#include "BLI_math.h"
#include "BLI_array_utils.h"
#include "BLI_bitmap.h"
#include "BLI_stack.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@ -76,6 +77,12 @@
#include "paint_intern.h" /* own include */
/* small structure to defer applying weight-paint results */
struct WPaintDefer {
int index;
float alpha, weight;
};
/* check if we can do partial updates and have them draw realtime
* (without rebuilding the 'derivedFinal') */
static bool vertex_paint_use_fast_update_check(Object *ob)
@ -1850,6 +1857,8 @@ struct WPaintData {
int *vmap_mem;
} blur_data;
BLI_Stack *accumulate_stack; /* for reuse (WPaintDefer) */
int defbase_tot;
};
@ -2052,6 +2061,12 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UN
me->medge, me->totvert, me->totedge);
}
if ((brush->vertexpaint_tool == PAINT_BLEND_BLUR) &&
(brush->flag & BRUSH_ACCUMULATE))
{
wpd->accumulate_stack = BLI_stack_new(sizeof(struct WPaintDefer), __func__);
}
/* imat for normals */
mul_m4_m4m4(mat, wpd->vc.rv3d->viewmat, ob->obmat);
invert_m4_m4(imat, mat);
@ -2060,12 +2075,12 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UN
return true;
}
static float wpaint_blur_weight_single(MDeformVert *dv, WeightPaintInfo *wpi)
static float wpaint_blur_weight_single(const MDeformVert *dv, const WeightPaintInfo *wpi)
{
return defvert_find_weight(dv, wpi->active.index);
}
static float wpaint_blur_weight_multi(MDeformVert *dv, WeightPaintInfo *wpi)
static float wpaint_blur_weight_multi(const MDeformVert *dv, const WeightPaintInfo *wpi)
{
float weight = BKE_defvert_multipaint_collective_weight(
dv, wpi->defbase_tot, wpi->defbase_sel, wpi->defbase_tot_sel, wpi->do_auto_normalize);
@ -2074,20 +2089,20 @@ static float wpaint_blur_weight_multi(MDeformVert *dv, WeightPaintInfo *wpi)
}
static float wpaint_blur_weight_calc_from_connected(
VPaint *wp, WeightPaintInfo *wpi, struct WPaintData *wpd, const unsigned int vidx,
float (*blur_weight_func)(MDeformVert *, WeightPaintInfo *))
const MDeformVert *dvert, WeightPaintInfo *wpi, struct WPaintData *wpd, const unsigned int vidx,
float (*blur_weight_func)(const MDeformVert *, const WeightPaintInfo *))
{
const MeshElemMap *map = &wpd->blur_data.vmap[vidx];
float paintweight;
if (map->count != 0) {
paintweight = 0.0f;
for (int j = 0; j < map->count; j++) {
paintweight += blur_weight_func(&wp->wpaint_prev[map->indices[j]], wpi);
paintweight += blur_weight_func(&dvert[map->indices[j]], wpi);
}
paintweight /= map->count;
}
else {
paintweight = blur_weight_func(&wp->wpaint_prev[vidx], wpi);
paintweight = blur_weight_func(&dvert[vidx], wpi);
}
return paintweight;
@ -2131,7 +2146,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
return;
}
float (*blur_weight_func)(MDeformVert *, WeightPaintInfo *) =
float (*blur_weight_func)(const MDeformVert *, const WeightPaintInfo *) =
wpd->do_multipaint ? wpaint_blur_weight_multi : wpaint_blur_weight_single;
vc = &wpd->vc;
@ -2245,6 +2260,14 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
}
}
/* accumulate means we refer to the previous,
* which is either the last update, or when we started painting */
BLI_Stack *accumulate_stack = wpd->accumulate_stack;
const bool use_accumulate = (accumulate_stack != NULL);
BLI_assert(accumulate_stack == NULL || BLI_stack_is_empty(accumulate_stack));
const MDeformVert *dvert_prev = use_accumulate ? me->dvert : wp->wpaint_prev;
#define WP_PAINT(v_idx_var) \
{ \
unsigned int vidx = v_idx_var; \
@ -2254,9 +2277,18 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
mval, brush_size_pressure, brush_alpha_pressure, NULL); \
if (alpha) { \
if (use_blur) { \
paintweight = wpaint_blur_weight_calc_from_connected(wp, &wpi, wpd, vidx, blur_weight_func); \
paintweight = wpaint_blur_weight_calc_from_connected( \
dvert_prev, &wpi, wpd, vidx, blur_weight_func); \
} \
if (use_accumulate) { \
struct WPaintDefer *dweight = BLI_stack_push_r(accumulate_stack); \
dweight->index = vidx; \
dweight->alpha = alpha; \
dweight->weight = paintweight; \
} \
else { \
do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight); \
} \
do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight); \
} \
me->dvert[vidx].flag = 0; \
} \
@ -2286,6 +2318,15 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
}
#undef WP_PAINT
if (use_accumulate) {
unsigned int defer_count = BLI_stack_count(accumulate_stack);
while (defer_count--) {
struct WPaintDefer *dweight = BLI_stack_peek(accumulate_stack);
do_weight_paint_vertex(wp, ob, &wpi, dweight->index, dweight->alpha, dweight->weight);
BLI_stack_discard(accumulate_stack);
}
}
/* *** free wpi members */
/* *** done freeing wpi members */
@ -2330,6 +2371,10 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
MEM_freeN(wpd->blur_data.vmap_mem);
}
if (wpd->accumulate_stack) {
BLI_stack_free(wpd->accumulate_stack);
}
MEM_freeN(wpd);
}