Commit: bad96e5c7c7ed721941e7bf0d96f4b2481052349 Author: Pablo Dobarro Date: Mon Apr 22 01:09:47 2019 +0200 Branches: sculpt-mode-features https://developer.blender.org/rBbad96e5c7c7ed721941e7bf0d96f4b2481052349
Sculpt mask: Mask by normal operator This is an experimental operator that can be used to generate mask for faces in hard surface sculpts. It does not have UI and without undo support the behaviour is unpredictable, but this code can be used to add another automasking mode to the automasking system. =================================================================== M source/blender/editors/sculpt_paint/sculpt.c =================================================================== diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index d7ded4e6995..129d191a924 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -7606,6 +7606,134 @@ void SCULPT_OT_color_fill(struct wmOperatorType *ot) ot->flag = OPTYPE_REGISTER; } +static int sculpt_mask_by_normal_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e)) +{ + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + Object *ob = CTX_data_active_object(C); + SculptSession *ss = ob->sculpt; + ARegion *ar = CTX_wm_region(C); + PBVH *pbvh = ob->sculpt->pbvh; + struct Scene *scene = CTX_data_scene(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); + PBVHNode **nodes; + int totnode; + + /* Disable for multires and dyntopo for now */ + if (BKE_pbvh_type(pbvh) != PBVH_FACES) { + ss->use_orco = false; + return OPERATOR_CANCELLED; + } + + /* Initial setup */ + BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, true, true); + + BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); + sculpt_undo_push_begin("Mask Coplanar"); + for (int i = 0; i < totnode; i++) { + sculpt_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK); + BKE_pbvh_node_mark_redraw(nodes[i]); + } + + /* Mask generation */ + int init_vert = ss->active_vertex_mesh_index; + + BLI_Stack *stack; + MVert *mvert = ss->mvert; + float threshold; + int *mvert_visited = MEM_callocN(ss->totvert * sizeof (int), "visited vertices"); + + threshold = RNA_float_get(op->ptr, "threshold"); + + stack = BLI_stack_new(sizeof(int), "verts stack"); + BLI_stack_push(stack, &init_vert); + + while(!BLI_stack_is_empty(stack)){ + int vert; + BLI_stack_pop(stack, &vert); + MeshElemMap *vert_map = &ss->pmap[vert]; + if(mvert_visited[vert] == 0) { + ss->vmask[vert] = 1.0f; + mvert[vert].flag |= ME_VERT_PBVH_UPDATE; + mvert_visited[vert] = 1; + } + int i = 0; + for (i = 0; i < ss->pmap[vert].count; i++) { + const MPoly *p = &ss->mpoly[vert_map->indices[i]]; + unsigned f_adj_v[2]; + if (poly_get_adj_loops_from_vert(p, ss->mloop, vert, f_adj_v) != -1) { + int j; + for (j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) { + if (vert_map->count != 2 || ss->pmap[f_adj_v[j]].count <= 2) { + if(mvert_visited[f_adj_v[j]] == 0){ + mvert_visited[f_adj_v[j]] = 1; + float original_normal[3]; + float new_normal[3]; + normal_short_to_float_v3(original_normal, mvert[vert].no); + normal_short_to_float_v3(new_normal, mvert[f_adj_v[j]].no); + if (dot_v3v3(original_normal, new_normal) > threshold) { + ss->vmask[f_adj_v[j]] = dot_v3v3(original_normal, new_normal); + mvert[f_adj_v[j]].flag |= ME_VERT_PBVH_UPDATE; + BLI_stack_push(stack, &f_adj_v[j]); + } + } + } + } + } + } + } + + MEM_freeN(mvert_visited); + + /* Smooth iterations */ + SculptThreadedTaskData data = { + .sd = sd, .ob = ob, .nodes = nodes, .smooth_value = 0.5f, .filter_type = MASK_FILTER_BLUR, + }; + + int smooth_iterations = RNA_int_get(op->ptr, "smooth_iterations"); + for (int i = 0; i < smooth_iterations; i++) { + ParallelRangeSettings settings; + BLI_parallel_range_settings_defaults(&settings); + settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT); + BLI_task_parallel_range( + 0, totnode, + &data, + mask_filter_task_cb, + &settings); + } + + /* Invert mask */ + if (RNA_boolean_get(op->ptr, "invert")) { + for (int i = 0; i < ss->totvert; i++) { + ss->vmask[i] = 1.0f - ss->vmask[i]; + } + } + + sculpt_undo_push_end(); + ED_region_tag_redraw(ar); + + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + return OPERATOR_FINISHED; +} + +static void SCULPT_OT_mask_by_normal(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Mask by normal"; + ot->idname = "SCULPT_OT_mask_by_normal"; + ot->description = "Creates a mask limited by the normal difference of the vertices"; + + /* api callbacks */ + ot->invoke = sculpt_mask_by_normal_invoke; + ot->poll = sculpt_mode_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + ot->prop = RNA_def_float(ot->srna, "threshold", 0.9993f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f); + ot->prop = RNA_def_int(ot->srna, "smooth_iterations", 2, 0, 10, "Smooth iterations", "", 0, 10); + ot->prop = RNA_def_boolean(ot->srna, "invert", false, "Invert", ""); +} + + void ED_operatortypes_sculpt(void) @@ -7623,4 +7751,5 @@ void ED_operatortypes_sculpt(void) WM_operatortype_append(SCULPT_OT_mesh_filter); WM_operatortype_append(SCULPT_OT_mask_filter); WM_operatortype_append(SCULPT_OT_color_fill); + WM_operatortype_append(SCULPT_OT_mask_by_normal); } _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs