Commit: a9f6ab735721e9242d3fc95f35c8e7ee69e42160 Author: Pablo Dobarro Date: Thu Jan 14 01:05:11 2021 +0100 Branches: sculpt-dev https://developer.blender.org/rBa9f6ab735721e9242d3fc95f35c8e7ee69e42160
Basic mask expand operation working =================================================================== M source/blender/editors/sculpt_paint/sculpt.c M source/blender/editors/sculpt_paint/sculpt_expand.c M source/blender/editors/sculpt_paint/sculpt_intern.h =================================================================== diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index fb1efd10e1f..174b06ce1a2 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -10561,6 +10561,8 @@ void ED_operatortypes_sculpt(void) WM_operatortype_append(SCULPT_OT_project_lasso_gesture); WM_operatortype_append(SCULPT_OT_project_box_gesture); + WM_operatortype_append(SCULPT_OT_expand); + WM_operatortype_append(SCULPT_OT_sample_color); WM_operatortype_append(SCULPT_OT_loop_to_vertex_colors); WM_operatortype_append(SCULPT_OT_vertex_to_loop_colors); diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.c b/source/blender/editors/sculpt_paint/sculpt_expand.c index 2c53e320522..465ed91bf1f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.c +++ b/source/blender/editors/sculpt_paint/sculpt_expand.c @@ -74,25 +74,149 @@ static EnumPropertyItem prop_sculpt_expand_faloff_type_items[] = { {SCULPT_EXPAND_FALLOFF_TOPOLOGY, "TOPOLOGY", 0, "Topology", ""}, {SCULPT_EXPAND_FALLOFF_NORMALS, "NORMALS", 0, "Normals", ""}, {SCULPT_EXPAND_FALLOFF_SPHERICAL, "SPHERICAL", 0, "Spherical", ""}, + {SCULPT_EXPAND_FALLOFF_BOUNDARY_TOPOLOGY, "BOUNDARY_TOPOLOGY`", 0, "Boundary Topology", ""}, {0, NULL, 0, NULL, NULL}, }; - - static float *sculpt_expand_geodesic_falloff_create(Sculpt *sd, Object *ob, const int vertex) { return SCULPT_geodesic_from_vertex_and_symm(sd, ob, vertex, FLT_MAX); } -static float *sculpt_expand_topology_falloff_create() { - return NULL; +typedef struct ExpandFloodFillData { + float original_normal[3]; + float edge_sensitivity; + float *dists; + float *edge_factor; +} ExpandFloodFillData; + +static bool mask_expand_topology_floodfill_cb( + SculptSession *UNUSED(ss), int from_v, int to_v, bool is_duplicate, void *userdata) +{ + ExpandFloodFillData *data = userdata; + if (!is_duplicate) { + const int to_it = data->dists[from_v] + 1; + data->dists[to_v] = to_it; + } + else { + data->dists[to_v] = data->dists[from_v]; + } + return true; } -static float *sculpt_expand_spherical_falloff_create() { - return NULL; +static float *sculpt_expand_topology_falloff_create(Sculpt *sd, Object *ob, const int vertex) { + SculptSession *ss = ob->sculpt; + const int totvert = SCULPT_vertex_count_get(ss); + float *dists = MEM_malloc_arrayN(sizeof (float), totvert, "spherical dist"); + + SculptFloodFill flood; + SCULPT_floodfill_init(ss, &flood); + SCULPT_floodfill_add_initial_with_symmetry(sd, ob, ss, &flood, vertex, FLT_MAX); + + ExpandFloodFillData fdata; + fdata.dists = dists; + + SCULPT_floodfill_execute(ss, &flood, mask_expand_topology_floodfill_cb, &fdata); + SCULPT_floodfill_free(&flood); + + return dists; } -static float *sculpt_expand_normal_falloff_create() { - return NULL; +static bool mask_expand_normals_floodfill_cb( + SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata) +{ + ExpandFloodFillData *data = userdata; + if (!is_duplicate) { + float current_normal[3], prev_normal[3]; + SCULPT_vertex_normal_get(ss, to_v, current_normal); + SCULPT_vertex_normal_get(ss, from_v, prev_normal); + const float from_edge_factor = data->edge_factor[from_v]; + data->edge_factor[to_v] = dot_v3v3(current_normal, prev_normal) * + from_edge_factor; + data->dists[to_v] = dot_v3v3(data->original_normal, current_normal) * + powf(from_edge_factor, data->edge_sensitivity); + CLAMP(data->dists[to_v], 0.0f, 1.0f); + } + else { + /* PBVH_GRIDS duplicate handling. */ + data->edge_factor[to_v] = data->edge_factor[from_v]; + data->dists[to_v] = data->dists[from_v]; + } + + return true; +} + +static float *sculpt_expand_normal_falloff_create(Sculpt *sd, Object *ob, const int vertex, const float edge_sensitivity) { + SculptSession *ss = ob->sculpt; + const int totvert = SCULPT_vertex_count_get(ss); + float *dists = MEM_malloc_arrayN(sizeof (float), totvert, "normal dist"); + float *edge_factor = MEM_callocN(sizeof(float) * totvert, + "mask edge factor"); + for (int i = 0; i < totvert; i++) { + edge_factor[i] = 1.0f; + } + + SculptFloodFill flood; + SCULPT_floodfill_init(ss, &flood); + SCULPT_floodfill_add_initial_with_symmetry(sd, ob, ss, &flood, vertex, FLT_MAX); + + ExpandFloodFillData fdata; + fdata.dists = dists; + fdata.edge_factor = edge_factor; + fdata.edge_sensitivity = edge_sensitivity; + SCULPT_vertex_normal_get(ss, vertex, fdata.original_normal); + + SCULPT_floodfill_execute(ss, &flood, mask_expand_topology_floodfill_cb, &fdata); + SCULPT_floodfill_free(&flood); + + for (int repeat = 0; repeat < 2; repeat++) { + for (int i = 0; i < totvert; i++) { + float avg = 0.0f; + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) { + avg += dists[ni.index]; + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + dists[i] = avg / ni.size; + } + } + + MEM_SAFE_FREE(edge_factor); + + return dists; +} + + +static float *sculpt_expand_spherical_falloff_create(Sculpt *sd, Object *ob, const int vertex) { + SculptSession *ss = ob->sculpt; + const int totvert = SCULPT_vertex_count_get(ss); + + float *dists = MEM_malloc_arrayN(sizeof (float), totvert, "spherical dist"); + for (int i = 0; i < totvert; i++) { + dists[i] = FLT_MAX; + } + const char symm = SCULPT_mesh_symmetry_xyz_get(ob); + + for (char symm_it = 0; symm_it <= symm; symm_it++) { + if (SCULPT_is_symmetry_iteration_valid(symm_it, symm)) { + int v = -1; + if (symm_it == 0) { + v = vertex; + } + else { + float location[3]; + flip_v3_v3(location, SCULPT_vertex_co_get(ss, vertex), symm_it); + v = SCULPT_nearest_vertex_get(sd, ob, location, FLT_MAX, false); + } + if (v != -1) { + const float *co = SCULPT_vertex_co_get(ss, v); + for (int i = 0; i < totvert; i++) { + dists[i] = min_ff(dists[i], len_v3v3(co, SCULPT_vertex_co_get(ss, i))); + } + } + } + } + + return dists; } static void sculpt_expand_update_max_falloff_factor(SculptSession *ss, ExpandCache *expand_cache) { @@ -110,19 +234,22 @@ static void sculpt_expand_falloff_factors_from_vertex_and_symm_create(ExpandCach return; } + if (expand_cache->falloff_factor) { + MEM_freeN(expand_cache->falloff_factor); + } switch (falloff_type) { case SCULPT_EXPAND_FALLOFF_GEODESICS: expand_cache->falloff_factor = sculpt_expand_geodesic_falloff_create(sd, ob, vertex); break; case SCULPT_EXPAND_FALLOFF_TOPOLOGY: - + expand_cache->falloff_factor = sculpt_expand_topology_falloff_create(sd, ob, vertex); break; case SCULPT_EXPAND_FALLOFF_NORMALS: - + expand_cache->falloff_factor = sculpt_expand_normal_falloff_create(sd, ob, vertex, 300.0f); break; case SCULPT_EXPAND_FALLOFF_SPHERICAL: - + expand_cache->falloff_factor = sculpt_expand_spherical_falloff_create(sd, ob, vertex); break; case SCULPT_EXPAND_FALLOFF_BOUNDARY_TOPOLOGY: @@ -135,15 +262,11 @@ static void sculpt_expand_falloff_factors_from_vertex_and_symm_create(ExpandCach sculpt_expand_update_max_falloff_factor(ss, expand_cache); } - -float *sculpt_expand_falloff_factors_update() { - return NULL; -} - - void sculpt_expand_cache_free(ExpandCache *expand_cache) { - - + MEM_SAFE_FREE(expand_cache->nodes); + MEM_SAFE_FREE(expand_cache->falloff_factor); + MEM_SAFE_FREE(expand_cache->initial_mask); + MEM_SAFE_FREE(expand_cache->initial_face_sets); MEM_SAFE_FREE(expand_cache); } @@ -187,263 +310,96 @@ static void sculpt_mask_expand_cancel(bContext *C, wmOperator *op) static void sculpt_expand_cancel(bContext *C, wmOperator *op) { + Object *ob = CTX_data_active_object(C); + SculptSession *ss = ob->sculpt; + sculpt_expand_cache_free(ss->expand_cache); ED_workspace_status_text(C, NULL); } -static void sculpt_expand_task_cb(void *__restrict userdata, +static bool sculpt_expand_state_get(ExpandCache *expand_cache, int i) { + bool enabled = expand_cache->falloff_factor[i] <= expand_cache->active_factor; + if (expand_cache->invert) { + enabled = !enabled; + } + return enabled; +} + + +static void sculpt_expand_mask_update_task_cb(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = userdata; SculptSession *ss = data->ob->sculpt; PBVHNode *node = data->nodes[i]; - PBVHVertexIter vd; - int update_it = data->mask_expand_update_it; + ExpandCache *expand_cache = ss->expand_cache; + bool any_changed = false; + + PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL) { - int vi = vd.index; - float final_mask = *vd.mask; - if (data->mask_expand_use_normals) { - if (ss->filter_cache->normal_factor[SCULPT_active_vertex_get(ss)] < - ss->filter_cache->normal_factor[vd.index]) { - final_mask = 1.0f; + const float initial_mask = *vd.mask; + const bool enabled = sculpt_expand_state_get(expand_cache, vd.index); + + if (enabled){ + if (expand_cache->mask_preserve_previous) { + *vd.mask = max_ff(initial_mask, expand_cache->initial_mask[vd.index]); } else { - final_mask = 0.0f; + *vd.mask = 1.0f; } - } - else { - if (ss->filter_cache->mask_update_it[vi] <= update_it && - ss->filter_cache->mask_update_it[vi] != 0) { - final_mask = 1.0f; } else { - final_mask = 0.0f; - } - } - - if (data->mask_expand_create_face_set) { - if (final_mask == 1.0f) { - SCULPT_vertex_face_set_set(ss, vd.index, ss->filter_cache->new_face_set); - } - BKE_pbvh_node_mark_redraw(node); - } - else { - - if (data->mask_expa @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs