diff options
author | Pablo Dobarro <pablodp606@gmail.com> | 2019-09-30 16:56:12 +0300 |
---|---|---|
committer | Pablo Dobarro <pablodp606@gmail.com> | 2019-09-30 16:58:03 +0300 |
commit | e8f6f70846e57be81d5d4e28556f7a12d291f5db (patch) | |
tree | d86a3780a58439f185e580b16372faa5a3b427c4 /source/blender | |
parent | 3dc027add3976557e120a1afdb58e80628ae32b0 (diff) |
PBVH: PBVH_FullyMasked and PBVH_FullyUnmasked flags
This commit introduces flags to tag the PBVH nodes as fully masked or unmasked. This is used in do_brush_actions to filter fully masked nodes during a stroke. Other tools can also be updated to use this flags.
Sculpt updates now require a flag to update the mask or the vertex coordinates.
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D5935
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_pbvh.h | 27 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pbvh.c | 109 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_mask.c | 10 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 111 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_intern.h | 9 |
5 files changed, 230 insertions, 36 deletions
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 426f81d889a..0d3b00cf927 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -50,18 +50,21 @@ typedef struct { } PBVHProxyNode; typedef enum { - PBVH_Leaf = 1, + PBVH_Leaf = 1 << 0, - PBVH_UpdateNormals = 2, - PBVH_UpdateBB = 4, - PBVH_UpdateOriginalBB = 8, - PBVH_UpdateDrawBuffers = 16, - PBVH_UpdateRedraw = 32, + PBVH_UpdateNormals = 1 << 1, + PBVH_UpdateBB = 1 << 2, + PBVH_UpdateOriginalBB = 1 << 3, + PBVH_UpdateDrawBuffers = 1 << 4, + PBVH_UpdateRedraw = 1 << 5, + PBVH_UpdateMask = 1 << 6, - PBVH_RebuildDrawBuffers = 64, - PBVH_FullyHidden = 128, + PBVH_RebuildDrawBuffers = 1 << 7, + PBVH_FullyHidden = 1 << 8, + PBVH_FullyMasked = 1 << 9, + PBVH_FullyUnmasked = 1 << 10, - PBVH_UpdateTopology = 256, + PBVH_UpdateTopology = 1 << 11, } PBVHNodeFlags; typedef struct PBVHFrustumPlanes { @@ -229,11 +232,16 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, /* Node Access */ void BKE_pbvh_node_mark_update(PBVHNode *node); +void BKE_pbvh_node_mark_update_mask(PBVHNode *node); void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node); void BKE_pbvh_node_mark_redraw(PBVHNode *node); void BKE_pbvh_node_mark_normals_update(PBVHNode *node); void BKE_pbvh_node_mark_topology_update(PBVHNode *node); void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden); +void BKE_pbvh_node_fully_masked_set(PBVHNode *node, int fully_masked); +bool BKE_pbvh_node_fully_masked_get(PBVHNode *node); +void BKE_pbvh_node_fully_unmasked_set(PBVHNode *node, int fully_masked); +bool BKE_pbvh_node_fully_unmasked_get(PBVHNode *node); void BKE_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, @@ -267,6 +275,7 @@ void BKE_pbvh_bmesh_after_stroke(PBVH *bvh); /* Update Bounding Box/Redraw and clear flags */ void BKE_pbvh_update_bounds(PBVH *bvh, int flags); +void BKE_pbvh_update_vertex_data(PBVH *bvh, int flags); void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg); void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]); void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *r_totface); diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 7bbf1068aa7..b3e511aad8e 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1103,6 +1103,56 @@ static void pbvh_faces_update_normals(PBVH *bvh, PBVHNode **nodes, int totnode) MEM_freeN(vnors); } +static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + + PBVHUpdateData *data = userdata; + PBVH *bvh = data->bvh; + PBVHNode *node = data->nodes[n]; + if (node->flag & PBVH_UpdateMask) { + + bool has_unmasked = false; + bool has_masked = true; + if (node->flag & PBVH_Leaf) { + PBVHVertexIter vd; + + BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_UNIQUE) + { + if (vd.mask && *vd.mask < 1.0f) { + has_unmasked = true; + } + if (vd.mask && *vd.mask > 0.0f) { + has_masked = false; + } + } + BKE_pbvh_vertex_iter_end; + } + else { + has_unmasked = true; + has_masked = true; + } + BKE_pbvh_node_fully_masked_set(node, !has_unmasked); + BKE_pbvh_node_fully_unmasked_set(node, has_masked); + + node->flag &= ~PBVH_UpdateMask; + } +} + +static void pbvh_update_mask_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag) +{ + PBVHUpdateData data = { + .bvh = bvh, + .nodes = nodes, + .flag = flag, + }; + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_mask_redraw_task_cb, &settings); +} + static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls)) @@ -1305,6 +1355,26 @@ void BKE_pbvh_update_bounds(PBVH *bvh, int flag) MEM_SAFE_FREE(nodes); } +void BKE_pbvh_update_vertex_data(PBVH *bvh, int flag) +{ + if (!bvh->nodes) { + return; + } + + PBVHNode **nodes; + int totnode; + + BKE_pbvh_search_gather(bvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode); + + if (flag & (PBVH_UpdateMask)) { + pbvh_update_mask_redraw(bvh, nodes, totnode, flag); + } + + if (nodes) { + MEM_freeN(nodes); + } +} + void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]) { PBVHIter iter; @@ -1435,6 +1505,11 @@ void BKE_pbvh_node_mark_update(PBVHNode *node) PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw; } +void BKE_pbvh_node_mark_update_mask(PBVHNode *node) +{ + node->flag |= PBVH_UpdateMask | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw; +} + void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node) { node->flag |= PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw; @@ -1462,6 +1537,40 @@ void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden) } } +void BKE_pbvh_node_fully_masked_set(PBVHNode *node, int fully_masked) +{ + BLI_assert(node->flag & PBVH_Leaf); + + if (fully_masked) { + node->flag |= PBVH_FullyMasked; + } + else { + node->flag &= ~PBVH_FullyMasked; + } +} + +bool BKE_pbvh_node_fully_masked_get(PBVHNode *node) +{ + return (node->flag & PBVH_Leaf) && (node->flag & PBVH_FullyMasked); +} + +void BKE_pbvh_node_fully_unmasked_set(PBVHNode *node, int fully_masked) +{ + BLI_assert(node->flag & PBVH_Leaf); + + if (fully_masked) { + node->flag |= PBVH_FullyUnmasked; + } + else { + node->flag &= ~PBVH_FullyUnmasked; + } +} + +bool BKE_pbvh_node_fully_unmasked_get(PBVHNode *node) +{ + return (node->flag & PBVH_Leaf) && (node->flag & PBVH_FullyUnmasked); +} + void BKE_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node, const int **r_vert_indices, diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index 7133936ff79..a93e55685d2 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -126,7 +126,7 @@ static void mask_flood_fill_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_end; if (redraw) { - BKE_pbvh_node_mark_redraw(node); + BKE_pbvh_node_mark_update_mask(node); if (data->multires) { BKE_pbvh_node_mark_normals_update(node); } @@ -174,6 +174,8 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED); } + BKE_pbvh_update_vertex_data(pbvh, PBVH_UpdateMask); + sculpt_undo_push_end(); if (nodes) { @@ -283,7 +285,7 @@ static void mask_box_select_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_end; if (redraw) { - BKE_pbvh_node_mark_redraw(node); + BKE_pbvh_node_mark_update_mask(node); } } @@ -355,6 +357,8 @@ bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti * multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED); } + BKE_pbvh_update_vertex_data(pbvh, PBVH_UpdateMask); + sculpt_undo_push_end(); ED_region_tag_redraw(ar); @@ -542,6 +546,8 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED); } + BKE_pbvh_update_vertex_data(pbvh, PBVH_UpdateMask); + sculpt_undo_push_end(); ED_region_tag_redraw(vc.ar); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 90c5c3e32f0..a871fb66686 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1857,6 +1857,12 @@ bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v) float t[3], bb_min[3], bb_max[3]; int i; + if (data->ignore_fully_masked) { + if (BKE_pbvh_node_fully_masked_get(node)) { + return false; + } + } + if (data->original) { BKE_pbvh_node_get_original_BB(node, bb_min, bb_max); } @@ -1887,6 +1893,12 @@ bool sculpt_search_circle_cb(PBVHNode *node, void *data_v) SculptSearchCircleData *data = data_v; float bb_min[3], bb_max[3]; + if (data->ignore_fully_masked) { + if (BKE_pbvh_node_fully_masked_get(node)) { + return false; + } + } + if (data->original) { BKE_pbvh_node_get_original_BB(node, bb_min, bb_max); } @@ -1920,6 +1932,27 @@ static void sculpt_clip(Sculpt *sd, SculptSession *ss, float co[3], const float } } +static PBVHNode **sculpt_pbvh_gather_cursor_update(Object *ob, + Sculpt *sd, + const Brush *brush, + bool use_original, + float radius_scale, + int *r_totnode) +{ + SculptSession *ss = ob->sculpt; + PBVHNode **nodes = NULL; + SculptSearchSphereData data = { + .ss = ss, + .sd = sd, + .radius_squared = ss->cursor_radius, + .original = use_original, + .ignore_fully_masked = false, + .center = NULL, + }; + BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, r_totnode); + return nodes; +} + static PBVHNode **sculpt_pbvh_gather_generic(Object *ob, Sculpt *sd, const Brush *brush, @@ -1936,8 +1969,9 @@ static PBVHNode **sculpt_pbvh_gather_generic(Object *ob, SculptSearchSphereData data = { .ss = ss, .sd = sd, - .radius_squared = ss->cache ? SQUARE(ss->cache->radius * radius_scale) : ss->cursor_radius, + .radius_squared = SQUARE(ss->cache->radius * radius_scale), .original = use_original, + .ignore_fully_masked = brush->sculpt_tool != SCULPT_TOOL_MASK, .center = NULL, }; BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, r_totnode); @@ -1952,6 +1986,7 @@ static PBVHNode **sculpt_pbvh_gather_generic(Object *ob, .radius_squared = ss->cache ? SQUARE(ss->cache->radius * radius_scale) : ss->cursor_radius, .original = use_original, .dist_ray_to_aabb_precalc = &dist_ray_to_aabb_precalc, + .ignore_fully_masked = brush->sculpt_tool != SCULPT_TOOL_MASK, }; BKE_pbvh_search_gather(ss->pbvh, sculpt_search_circle_cb, &data, &nodes, r_totnode); } @@ -5173,7 +5208,12 @@ static void do_brush_action_task_cb(void *__restrict userdata, data->nodes[n], data->brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS); - BKE_pbvh_node_mark_update(data->nodes[n]); + if (data->brush->sculpt_tool == SCULPT_TOOL_MASK) { + BKE_pbvh_node_mark_update_mask(data->nodes[n]); + } + else { + BKE_pbvh_node_mark_update(data->nodes[n]); + } } static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSettings *ups) @@ -6531,7 +6571,8 @@ bool sculpt_cursor_geometry_info_update(bContext *C, } ss->cursor_radius = radius; - PBVHNode **nodes = sculpt_pbvh_gather_generic(ob, sd, brush, original, radius_scale, &totnode); + PBVHNode **nodes = sculpt_pbvh_gather_cursor_update( + ob, sd, brush, original, radius_scale, &totnode); /* In case there are no nodes under the cursor, return the face normal */ if (!totnode) { @@ -6697,7 +6738,7 @@ void sculpt_update_object_bounding_box(Object *ob) } } -static void sculpt_flush_update_step(bContext *C) +static void sculpt_flush_update_step(bContext *C, SculptUpdateType update_flags) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Object *ob = CTX_data_active_object(C); @@ -6731,11 +6772,13 @@ static void sculpt_flush_update_step(bContext *C) * only the part of the 3D viewport where changes happened. */ rcti r; - BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateBB); - /* Update the object's bounding box too so that the object - * doesn't get incorrectly clipped during drawing in - * draw_mesh_object(). [#33790] */ - sculpt_update_object_bounding_box(ob); + if (update_flags & SCULPT_UPDATE_COORDS) { + BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateBB); + /* Update the object's bounding box too so that the object + * doesn't get incorrectly clipped during drawing in + * draw_mesh_object(). [#33790] */ + sculpt_update_object_bounding_box(ob); + } if (sculpt_get_redraw_rect(ar, CTX_wm_region_view3d(C), ob, &r)) { if (ss->cache) { @@ -6755,7 +6798,7 @@ static void sculpt_flush_update_step(bContext *C) } } -static void sculpt_flush_update_done(const bContext *C, Object *ob) +static void sculpt_flush_update_done(const bContext *C, Object *ob, SculptUpdateType update_flags) { /* After we are done drawing the stroke, check if we need to do a more * expensive depsgraph tag to update geometry. */ @@ -6792,7 +6835,13 @@ static void sculpt_flush_update_done(const bContext *C, Object *ob) } } - BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateOriginalBB); + if (update_flags & SCULPT_UPDATE_COORDS) { + BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateOriginalBB); + } + + if (update_flags & SCULPT_UPDATE_MASK) { + BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateMask); + } if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { BKE_pbvh_bmesh_after_stroke(ss->pbvh); @@ -6904,7 +6953,12 @@ static void sculpt_stroke_update_step(bContext *C, ss->cache->first_time = false; /* Cleanup */ - sculpt_flush_update_step(C); + if (brush->sculpt_tool == SCULPT_TOOL_MASK) { + sculpt_flush_update_step(C, SCULPT_UPDATE_MASK); + } + else { + sculpt_flush_update_step(C, SCULPT_UPDATE_COORDS); + } } static void sculpt_brush_exit_tex(Sculpt *sd) @@ -6957,7 +7011,12 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str sculpt_undo_push_end(); - sculpt_flush_update_done(C, ob); + if (brush->sculpt_tool == SCULPT_TOOL_MASK) { + sculpt_flush_update_done(C, ob, SCULPT_UPDATE_MASK); + } + else { + sculpt_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); + } WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); } @@ -8297,7 +8356,7 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent * if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { sculpt_filter_cache_free(ss); sculpt_undo_push_end(); - sculpt_flush_update_done(C, ob); + sculpt_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); return OPERATOR_FINISHED; } @@ -8330,7 +8389,7 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent * sculpt_flush_stroke_deform(sd, ob, true); } - sculpt_flush_update_step(C); + sculpt_flush_update_step(C, SCULPT_UPDATE_COORDS); return OPERATOR_RUNNING_MODAL; } @@ -8535,7 +8594,7 @@ static void mask_filter_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_end; if (update) { - BKE_pbvh_node_mark_redraw(node); + BKE_pbvh_node_mark_update_mask(node); } } @@ -8700,7 +8759,7 @@ static void dirty_mask_task_cb(void *__restrict userdata, } } BKE_pbvh_vertex_iter_end; - BKE_pbvh_node_mark_redraw(node); + BKE_pbvh_node_mark_update_mask(node); } static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op) @@ -8786,6 +8845,8 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op) MEM_SAFE_FREE(nodes); + BKE_pbvh_update_vertex_data(pbvh, SCULPT_UPDATE_MASK); + sculpt_undo_push_end(); ED_region_tag_redraw(ar); @@ -8829,10 +8890,10 @@ static void sculpt_mask_expand_cancel(bContext *C, wmOperator *op) BKE_pbvh_node_mark_redraw(ss->filter_cache->nodes[i]); } - sculpt_flush_update_step(C); + sculpt_flush_update_step(C, SCULPT_UPDATE_MASK); sculpt_filter_cache_free(ss); sculpt_undo_push_end(); - sculpt_flush_update_done(C, ob); + sculpt_flush_update_done(C, ob, SCULPT_UPDATE_MASK); ED_workspace_status_text(C, NULL); } @@ -8882,7 +8943,7 @@ static void sculpt_expand_task_cb(void *__restrict userdata, vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } *vd.mask = final_mask; - BKE_pbvh_node_mark_redraw(node); + BKE_pbvh_node_mark_update_mask(node); } } BKE_pbvh_vertex_iter_end; @@ -8975,7 +9036,7 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent * sculpt_filter_cache_free(ss); sculpt_undo_push_end(); - sculpt_flush_update_done(C, ob); + sculpt_flush_update_done(C, ob, SCULPT_UPDATE_MASK); ED_workspace_status_text(C, NULL); return OPERATOR_FINISHED; } @@ -9005,7 +9066,7 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent * ss->filter_cache->mask_update_current_it = mask_expand_update_it; } - sculpt_flush_update_step(C); + sculpt_flush_update_step(C, SCULPT_UPDATE_MASK); return OPERATOR_RUNNING_MODAL; } @@ -9177,7 +9238,7 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent "cancel"); ED_workspace_status_text(C, status_str); - sculpt_flush_update_step(C); + sculpt_flush_update_step(C, SCULPT_UPDATE_MASK); WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } @@ -9498,7 +9559,7 @@ void ED_sculpt_update_modal_transform(struct bContext *C) sculpt_flush_stroke_deform(sd, ob, true); } - sculpt_flush_update_step(C); + sculpt_flush_update_step(C, SCULPT_UPDATE_COORDS); } void ED_sculpt_end_transform(struct bContext *C) @@ -9509,7 +9570,7 @@ void ED_sculpt_end_transform(struct bContext *C) sculpt_filter_cache_free(ss); } sculpt_undo_push_end(); - sculpt_flush_update_done(C, ob); + sculpt_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); } typedef enum eSculptPivotPositionModes { diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 9da9af6c078..37458eaa833 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -44,6 +44,13 @@ bool sculpt_mode_poll_view3d(struct bContext *C); bool sculpt_poll(struct bContext *C); bool sculpt_poll_view3d(struct bContext *C); +/* Updates */ + +typedef enum SculptUpdateType { + SCULPT_UPDATE_COORDS = 1 << 0, + SCULPT_UPDATE_MASK = 1 << 1, +} SculptUpdateType; + /* Stroke */ typedef struct SculptCursorGeometryInfo { @@ -245,6 +252,7 @@ typedef struct { float radius_squared; float *center; bool original; + bool ignore_fully_masked; } SculptSearchSphereData; typedef struct { @@ -252,6 +260,7 @@ typedef struct { struct SculptSession *ss; float radius_squared; bool original; + bool ignore_fully_masked; struct DistRayAABB_Precalc *dist_ray_to_aabb_precalc; } SculptSearchCircleData; |