From a102d3397f69e84b11d57ac15a5206a60cf41614 Mon Sep 17 00:00:00 2001 From: Antony Riakiotakis Date: Thu, 19 Dec 2013 14:39:54 +0200 Subject: Sculpting: * Support for symmetry in lasso masking * Optimize away symmetry multiplication of gravity vector if no gravity active * Move flip_v3_v3 to paint_utils (used in masking as well) * Use OpenMP for mask flood fill too. --- source/blender/editors/sculpt_paint/paint_intern.h | 1 + source/blender/editors/sculpt_paint/paint_mask.c | 77 ++++++++++++++-------- source/blender/editors/sculpt_paint/paint_utils.c | 17 +++++ source/blender/editors/sculpt_paint/sculpt.c | 20 +----- 4 files changed, 70 insertions(+), 45 deletions(-) (limited to 'source/blender/editors/sculpt_paint') diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 01f5d53594e..57eaa454621 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -219,6 +219,7 @@ int vert_paint_poll(struct bContext *C); int mask_paint_poll(struct bContext *C); int facemask_paint_poll(struct bContext *C); +void flip_v3_v3(float out[3], const float in[3], const char symm); /* stroke operator */ typedef enum BrushStrokeMode { diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index 320bf4f0f5e..acc138afcb8 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -94,6 +94,9 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) PBVH *pbvh; PBVHNode **nodes; int totnode, i; +#ifdef _OPENMP + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; +#endif mode = RNA_enum_get(op->ptr, "mode"); value = RNA_float_get(op->ptr, "value"); @@ -108,6 +111,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) sculpt_undo_push_begin("Mask flood fill"); + #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) for (i = 0; i < totnode; i++) { PBVHVertexIter vi; @@ -231,7 +235,7 @@ int do_sculpt_mask_box_select(ViewContext *vc, rcti *rect, bool select, bool UNU BKE_pbvh_search_gather(pbvh, BKE_pbvh_node_planes_contain_AABB, clip_planes_final, &nodes, &totnode); -#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) + #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) for (i = 0; i < totnode; i++) { PBVHVertexIter vi; bool any_masked = false; @@ -270,6 +274,7 @@ typedef struct LassoMaskData { bool *px; int width; rcti rect; /* bounding box for scanfilling */ + int symmpass; } LassoMaskData; @@ -280,9 +285,11 @@ static bool is_effected_lasso(LassoMaskData *data, float co[3]) { float scr_co_f[2]; short scr_co_s[2]; + float co_final[3]; + flip_v3_v3(co_final, co, data->symmpass); /* first project point to 2d space */ - ED_view3d_project_float_v2_m4(data->vc->ar, co, scr_co_f, data->projviewobjmat); + ED_view3d_project_float_v2_m4(data->vc->ar, co_final, scr_co_f, data->projviewobjmat); scr_co_s[0] = scr_co_f[0]; scr_co_s[1] = scr_co_f[1]; @@ -309,20 +316,19 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) int (*mcords)[2] = (int (*)[2])WM_gesture_lasso_path_to_array(C, op, &mcords_tot); if (mcords) { - float clip_planes[4][4]; + float clip_planes[4][4], clip_planes_final[4][4]; BoundBox bb; bglMats mats = {{0}}; Object *ob; ViewContext vc; LassoMaskData data; -#ifdef _OPENMP Sculpt *sd = CTX_data_tool_settings(C)->sculpt; -#endif + int symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL; struct MultiresModifierData *mmd; DerivedMesh *dm; PBVH *pbvh; PBVHNode **nodes; - int totnode, i; + int totnode, i, symmpass; PaintMaskFloodMode mode = PAINT_MASK_FLOOD_VALUE; bool select = true; /* TODO: see how to implement deselection */ float value = select ? 1.0 : 0.0; @@ -356,38 +362,55 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) pbvh = dm->getPBVH(ob, dm); ob->sculpt->pbvh = pbvh; - /* gather nodes inside lasso's enclosing rectangle (should greatly help with bigger meshes) */ - BKE_pbvh_search_gather(pbvh, BKE_pbvh_node_planes_contain_AABB, clip_planes, &nodes, &totnode); - sculpt_undo_push_begin("Mask lasso fill"); -#pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) - for (i = 0; i < totnode; i++) { - PBVHVertexIter vi; - bool any_masked = false; + for (symmpass = 0; symmpass <= symm; ++symmpass) { + if (symmpass == 0 || + (symm & symmpass && + (symm != 5 || symmpass != 3) && + (symm != 6 || (symmpass != 3 && symmpass != 5)))) + { + int j = 0; + + /* flip the planes symmetrically as needed */ + for (; j < 4; j++) { + flip_plane(clip_planes_final[j], clip_planes[j], symmpass); + } - BKE_pbvh_vertex_iter_begin(pbvh, nodes[i], vi, PBVH_ITER_UNIQUE) { - if (is_effected_lasso(&data, vi.co)) { - if (!any_masked) { - any_masked = true; + data.symmpass = symmpass; - sculpt_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK); + /* gather nodes inside lasso's enclosing rectangle (should greatly help with bigger meshes) */ + BKE_pbvh_search_gather(pbvh, BKE_pbvh_node_planes_contain_AABB, clip_planes_final, &nodes, &totnode); - BKE_pbvh_node_mark_redraw(nodes[i]); - if (BKE_pbvh_type(pbvh) == PBVH_GRIDS) - multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED); - } + #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) + for (i = 0; i < totnode; i++) { + PBVHVertexIter vi; + bool any_masked = false; - mask_flood_fill_set_elem(vi.mask, mode, value); + BKE_pbvh_vertex_iter_begin(pbvh, nodes[i], vi, PBVH_ITER_UNIQUE) { + if (is_effected_lasso(&data, vi.co)) { + if (!any_masked) { + any_masked = true; + + sculpt_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK); + + BKE_pbvh_node_mark_redraw(nodes[i]); + if (BKE_pbvh_type(pbvh) == PBVH_GRIDS) + multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED); + } + + mask_flood_fill_set_elem(vi.mask, mode, value); + } + } BKE_pbvh_vertex_iter_end; } - } BKE_pbvh_vertex_iter_end; + + if (nodes) + MEM_freeN(nodes); + } } sculpt_undo_push_end(); - if (nodes) - MEM_freeN(nodes); - ED_region_tag_redraw(vc.ar); MEM_freeN((void *)mcords); MEM_freeN(data.px); diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index bfc431baea5..dd414a7b2b2 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -342,6 +342,23 @@ int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int *index, return 1; } +/* Uses symm to selectively flip any axis of a coordinate. */ +void flip_v3_v3(float out[3], const float in[3], const char symm) +{ + if (symm & PAINT_SYMM_X) + out[0] = -in[0]; + else + out[0] = in[0]; + if (symm & PAINT_SYMM_Y) + out[1] = -in[1]; + else + out[1] = in[1]; + if (symm & PAINT_SYMM_Z) + out[2] = -in[2]; + else + out[2] = in[2]; +} + /* used for both 3d view and image window */ void paint_sample_color(const bContext *C, ARegion *ar, int x, int y) /* frontbuf */ { diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 4a1859c15f8..975aa28166e 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -759,23 +759,6 @@ static float integrate_overlap(Brush *br) return max; } -/* Uses symm to selectively flip any axis of a coordinate. */ -static void flip_v3_v3(float out[3], const float in[3], const char symm) -{ - if (symm & PAINT_SYMM_X) - out[0] = -in[0]; - else - out[0] = in[0]; - if (symm & PAINT_SYMM_Y) - out[1] = -in[1]; - else - out[1] = in[1]; - if (symm & PAINT_SYMM_Z) - out[2] = -in[2]; - else - out[2] = in[2]; -} - static void flip_v3(float v[3], const char symm) { flip_v3_v3(v, v, symm); @@ -3478,9 +3461,10 @@ static void calc_brushdata_symm(Sculpt *sd, StrokeCache *cache, const char symm, mul_m4_v3(cache->symm_rot_mat, cache->location); mul_m4_v3(cache->symm_rot_mat, cache->grab_delta_symmetry); - if (cache->supports_gravity) + if (cache->supports_gravity) { flip_v3_v3(cache->gravity_direction, cache->true_gravity_direction, symm); mul_m4_v3(cache->symm_rot_mat, cache->gravity_direction); + } } typedef void (*BrushActionFunc)(Sculpt *sd, Object *ob, Brush *brush); -- cgit v1.2.3