diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint/sculpt_automasking.c')
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_automasking.c | 93 |
1 files changed, 76 insertions, 17 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c index bfa657147fd..c475259623a 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.c +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c @@ -89,21 +89,65 @@ bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, co return false; } -float SCULPT_automasking_factor_get(SculptSession *ss, int vert) +static int sculpt_automasking_mode_effective_bits(const Sculpt *sculpt, const Brush *brush) { - if (ss->cache && ss->cache->automask) { - return ss->cache->automask[vert]; + return sculpt->automasking_flags | brush->automasking_flags; +} + +static bool SCULPT_automasking_needs_cache(const Sculpt *sd, const Brush *brush) +{ + + const int automasking_flags = sculpt_automasking_mode_effective_bits(sd, brush); + if (automasking_flags & BRUSH_AUTOMASKING_TOPOLOGY) { + return true; + } + if (automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) { + return brush->automasking_boundary_edges_propagation_steps != 1; } - else { + if (automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS) { + return brush->automasking_boundary_edges_propagation_steps != 1; + } + return false; +} + +float SCULPT_automasking_factor_get(SculptSession *ss, int vert) +{ + if (!ss->cache) { return 1.0f; } + /* If the cache is initialized with valid info, use the cache. This is used when the + * automasking information can't be computed in real time per vertex and needs to be + * initialized for the whole mesh when the stroke starts. */ + if (ss->cache->automask_factor) { + return ss->cache->automask_factor[vert]; + } + + if (ss->cache->automask_settings.flags & BRUSH_AUTOMASKING_FACE_SETS) { + if (!SCULPT_vertex_has_face_set(ss, vert, ss->cache->automask_settings.initial_face_set)) { + return 0.0f; + } + } + + if (ss->cache->automask_settings.flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) { + if (SCULPT_vertex_is_boundary(ss, vert)) { + return 0.0f; + } + } + + if (ss->cache->automask_settings.flags & BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS) { + if (!SCULPT_vertex_has_unique_face_set(ss, vert)) { + return 0.0f; + } + } + + return 1.0f; } void SCULPT_automasking_end(Object *ob) { SculptSession *ss = ob->sculpt; - if (ss->cache && ss->cache->automask) { - MEM_freeN(ss->cache->automask); + if (ss->cache && ss->cache->automask_factor) { + MEM_freeN(ss->cache->automask_factor); } } @@ -129,11 +173,12 @@ typedef struct AutomaskFloodFillData { } AutomaskFloodFillData; static bool automask_floodfill_cb( - SculptSession *ss, int UNUSED(from_v), int to_v, bool UNUSED(is_duplicate), void *userdata) + SculptSession *ss, int from_v, int to_v, bool UNUSED(is_duplicate), void *userdata) { AutomaskFloodFillData *data = userdata; data->automask_factor[to_v] = 1.0f; + data->automask_factor[from_v] = 1.0f; return (!data->use_radius || SCULPT_is_vertex_inside_brush_radius_symm( SCULPT_vertex_co_get(ss, to_v), data->location, data->radius, data->symm)); @@ -155,7 +200,7 @@ static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *au const int totvert = SCULPT_vertex_count_get(ss); for (int i = 0; i < totvert; i++) { - ss->cache->automask[i] = 0.0f; + ss->cache->automask_factor[i] = 0.0f; } /* Flood fill automask to connected vertices. Limited to vertices inside @@ -211,7 +256,7 @@ float *SCULPT_boundary_automasking_init(Object *ob, { SculptSession *ss = ob->sculpt; - if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) { + if (!ss->pmap) { BLI_assert(!"Boundary Edges masking: pmap missing"); return NULL; } @@ -223,7 +268,7 @@ float *SCULPT_boundary_automasking_init(Object *ob, edge_distance[i] = EDGE_DISTANCE_INF; switch (mode) { case AUTOMASK_INIT_BOUNDARY_EDGES: - if (!SCULPT_vertex_is_boundary(ss, i)) { + if (SCULPT_vertex_is_boundary(ss, i)) { edge_distance[i] = 0; } break; @@ -261,6 +306,14 @@ float *SCULPT_boundary_automasking_init(Object *ob, return automask_factor; } +static void SCULPT_stroke_automasking_settings_update(SculptSession *ss, Sculpt *sd, Brush *brush) +{ + BLI_assert(ss->cache); + + ss->cache->automask_settings.flags = sculpt_automasking_mode_effective_bits(sd, brush); + ss->cache->automask_settings.initial_face_set = SCULPT_active_face_set_get(ss); +} + void SCULPT_automasking_init(Sculpt *sd, Object *ob) { SculptSession *ss = ob->sculpt; @@ -271,20 +324,26 @@ void SCULPT_automasking_init(Sculpt *sd, Object *ob) return; } - ss->cache->automask = MEM_callocN(sizeof(float) * SCULPT_vertex_count_get(ss), - "automask_factor"); + SCULPT_stroke_automasking_settings_update(ss, sd, brush); + SCULPT_boundary_info_ensure(ob); + + if (!SCULPT_automasking_needs_cache(sd, brush)) { + return; + } + + ss->cache->automask_factor = MEM_malloc_arrayN(totvert, sizeof(float), "automask_factor"); for (int i = 0; i < totvert; i++) { - ss->cache->automask[i] = 1.0f; + ss->cache->automask_factor[i] = 1.0f; } if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_TOPOLOGY)) { SCULPT_vertex_random_access_init(ss); - SCULPT_topology_automasking_init(sd, ob, ss->cache->automask); + SCULPT_topology_automasking_init(sd, ob, ss->cache->automask_factor); } if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_FACE_SETS)) { SCULPT_vertex_random_access_init(ss); - sculpt_face_sets_automasking_init(sd, ob, ss->cache->automask); + sculpt_face_sets_automasking_init(sd, ob, ss->cache->automask_factor); } if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) { @@ -292,13 +351,13 @@ void SCULPT_automasking_init(Sculpt *sd, Object *ob) SCULPT_boundary_automasking_init(ob, AUTOMASK_INIT_BOUNDARY_EDGES, brush->automasking_boundary_edges_propagation_steps, - ss->cache->automask); + ss->cache->automask_factor); } if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) { SCULPT_vertex_random_access_init(ss); SCULPT_boundary_automasking_init(ob, AUTOMASK_INIT_BOUNDARY_FACE_SETS, brush->automasking_boundary_edges_propagation_steps, - ss->cache->automask); + ss->cache->automask_factor); } } |