[Bf-blender-cvs] [a9f6ab73572] sculpt-dev: Basic mask expand operation working
Pablo Dobarro
noreply at git.blender.org
Thu Jan 14 01:07:00 CET 2021
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. @@
More information about the Bf-blender-cvs
mailing list