diff options
author | Pablo Dobarro <pablodp606@gmail.com> | 2020-08-18 17:13:43 +0300 |
---|---|---|
committer | Pablo Dobarro <pablodp606@gmail.com> | 2020-08-18 17:14:10 +0300 |
commit | 3e5431fdf43906cd900f960f65ef8897e8a108a3 (patch) | |
tree | e750ab789a8309eefcc566a7848791ff7ac12428 | |
parent | 872efd8d73a3820680379230d83a0aadf5fc29ca (diff) |
Sculpt: Invert Smooth to Enhance Details
This enables the invert mode in the smooth brush as Enhance Details.
The operation is similar to the Sharpen Filter intensify details parameter,
which consist in applying the laplacian smooth displacement in the opposite
direction calculated using the original coordinates.
Reviewed By: sergey
Differential Revision: https://developer.blender.org/D8509
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 3 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_intern.h | 3 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_smooth.c | 88 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_brush.c | 14 |
4 files changed, 105 insertions, 3 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 03d079ba0e1..5d09109c506 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2331,7 +2331,7 @@ static float brush_strength(const Sculpt *sd, } case SCULPT_TOOL_SMOOTH: - return alpha * pressure * feather; + return flip * alpha * pressure * feather; case SCULPT_TOOL_PINCH: if (flip > 0.0f) { @@ -6365,6 +6365,7 @@ void SCULPT_cache_free(StrokeCache *cache) MEM_SAFE_FREE(cache->surface_smooth_laplacian_disp); MEM_SAFE_FREE(cache->layer_displacement_factor); MEM_SAFE_FREE(cache->prev_colors); + MEM_SAFE_FREE(cache->detail_directions); if (cache->pose_ik_chain) { SCULPT_pose_ik_chain_free(cache->pose_ik_chain); diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 65006031bb3..caa36a909fe 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -889,6 +889,9 @@ typedef struct StrokeCache { /* Pose brush */ struct SculptPoseIKChain *pose_ik_chain; + /* Enhance Details. */ + float (*detail_directions)[3]; + /* Clay Thumb brush */ /* Angle of the front tilting plane of the brush to simulate clay accumulation. */ float clay_thumb_front_angle; diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index 2b93298ac4a..63fe8643628 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -195,6 +195,85 @@ void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], int index } } +static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict tls) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + Sculpt *sd = data->sd; + const Brush *brush = data->brush; + + PBVHVertexIter vd; + + float bstrength = ss->cache->bstrength; + CLAMP(bstrength, -1.0f, 1.0f); + + SculptBrushTest test; + SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( + ss, &test, data->brush->falloff_shape); + + const int thread_id = BLI_task_parallel_thread_id(tls); + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + if (sculpt_brush_test_sq_fn(&test, vd.co)) { + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float disp[3]; + madd_v3_v3v3fl(disp, vd.co, ss->cache->detail_directions[vd.index], fade); + SCULPT_clip(sd, ss, vd.co, disp); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } + } + } + BKE_pbvh_vertex_iter_end; +} + +static void SCULPT_enhance_details_brush(Sculpt *sd, + Object *ob, + PBVHNode **nodes, + const int totnode) +{ + SculptSession *ss = ob->sculpt; + Brush *brush = BKE_paint_brush(&sd->paint); + + SCULPT_vertex_random_access_ensure(ss); + SCULPT_boundary_info_ensure(ob); + + if (SCULPT_stroke_is_first_brush_step(ss->cache)) { + const int totvert = SCULPT_vertex_count_get(ss); + ss->cache->detail_directions = MEM_malloc_arrayN( + totvert, 3 * sizeof(float), "details directions"); + + for (int i = 0; i < totvert; i++) { + float avg[3]; + SCULPT_neighbor_coords_average(ss, avg, i); + sub_v3_v3v3(ss->cache->detail_directions[i], avg, SCULPT_vertex_co_get(ss, i)); + } + } + + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + }; + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range(0, totnode, &data, do_enhance_details_brush_task_cb_ex, &settings); +} + static void do_smooth_brush_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls) @@ -300,7 +379,14 @@ void SCULPT_smooth(Sculpt *sd, void SCULPT_do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) { SculptSession *ss = ob->sculpt; - SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false); + if (ss->cache->bstrength <= 0.0f) { + /* Invert mode, intensify details. */ + SCULPT_enhance_details_brush(sd, ob, nodes, totnode); + } + else { + /* Regular mode, smooth. */ + SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false); + } } /* HC Smooth Algorithm. */ diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index a3fa4fed575..cc39a5dbe8d 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -45,6 +45,16 @@ static const EnumPropertyItem prop_direction_items[] = { {0, NULL, 0, NULL, NULL}, }; +static const EnumPropertyItem prop_smooth_direction_items[] = { + {0, "SMOOTH", ICON_ADD, "Smooth", "Smooth the surfae"}, + {BRUSH_DIR_IN, + "ENHANCE_DETAILS", + ICON_REMOVE, + "Enhance Details", + "Enhance the surface detail"}, + {0, NULL, 0, NULL, NULL}, +}; + static const EnumPropertyItem sculpt_stroke_method_items[] = { {0, "DOTS", 0, "Dots", "Apply paint on each mouse move step"}, {BRUSH_DRAG_DOT, "DRAG_DOT", 0, "Drag Dot", "Allows a single dot to be carefully positioned"}, @@ -527,6 +537,7 @@ static bool rna_BrushCapabilitiesSculpt_has_direction_get(PointerRNA *ptr) SCULPT_TOOL_DRAW_SHARP, SCULPT_TOOL_CLAY, SCULPT_TOOL_CLAY_STRIPS, + SCULPT_TOOL_SMOOTH, SCULPT_TOOL_LAYER, SCULPT_TOOL_INFLATE, SCULPT_TOOL_BLOB, @@ -795,7 +806,8 @@ static const EnumPropertyItem *rna_Brush_direction_itemf(bContext *C, case SCULPT_TOOL_CLAY: case SCULPT_TOOL_CLAY_STRIPS: return prop_direction_items; - + case SCULPT_TOOL_SMOOTH: + return prop_smooth_direction_items; case SCULPT_TOOL_MASK: switch ((BrushMaskTool)me->mask_tool) { case BRUSH_MASK_DRAW: |