Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/sculpt_paint/sculpt_automasking.c
| Show First 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) { | if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| int SCULPT_automasking_mode_effective_bits(const Sculpt *sculpt, const Brush *brush) | |||||
| { | |||||
| 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; | |||||
| } | |||||
| 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) | float SCULPT_automasking_factor_get(SculptSession *ss, int vert) | ||||
| { | { | ||||
| if (ss->cache && ss->cache->automask) { | if (!ss->cache) { | ||||
| return ss->cache->automask[vert]; | 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; | |||||
| } | } | ||||
sergey: Reverse the condition, unindent the body. | |||||
| } | |||||
| 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; | return 1.0f; | ||||
| } | } | ||||
| void SCULPT_automasking_end(Object *ob) | void SCULPT_automasking_end(Object *ob) | ||||
| { | { | ||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| if (ss->cache && ss->cache->automask) { | if (ss->cache && ss->cache->automask_factor) { | ||||
| MEM_freeN(ss->cache->automask); | MEM_freeN(ss->cache->automask_factor); | ||||
| } | } | ||||
| } | } | ||||
| static bool sculpt_automasking_is_constrained_by_radius(Brush *br) | static bool sculpt_automasking_is_constrained_by_radius(Brush *br) | ||||
| { | { | ||||
| /* 2D falloff is not constrained by radius. */ | /* 2D falloff is not constrained by radius. */ | ||||
| if (br->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { | if (br->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { | ||||
| return false; | return false; | ||||
| Show All 35 Lines | static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *automask_factor) | ||||
| if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) { | if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) { | ||||
| BLI_assert(!"Topology masking: pmap missing"); | BLI_assert(!"Topology masking: pmap missing"); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| const int totvert = SCULPT_vertex_count_get(ss); | const int totvert = SCULPT_vertex_count_get(ss); | ||||
| for (int i = 0; i < totvert; i++) { | 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 | /* Flood fill automask to connected vertices. Limited to vertices inside | ||||
| * the brush radius if the tool requires it. */ | * the brush radius if the tool requires it. */ | ||||
| SculptFloodFill flood; | SculptFloodFill flood; | ||||
| SCULPT_floodfill_init(ss, &flood); | SCULPT_floodfill_init(ss, &flood); | ||||
| SCULPT_floodfill_add_active(sd, ob, ss, &flood, ss->cache->radius); | SCULPT_floodfill_add_active(sd, ob, ss, &flood, ss->cache->radius); | ||||
| ▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | if (edge_distance[i] != EDGE_DISTANCE_INF) { | ||||
| automask_factor[i] *= (1.0f - edge_boundary_automask); | automask_factor[i] *= (1.0f - edge_boundary_automask); | ||||
| } | } | ||||
| } | } | ||||
| MEM_SAFE_FREE(edge_distance); | MEM_SAFE_FREE(edge_distance); | ||||
| return automask_factor; | 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) | void SCULPT_automasking_init(Sculpt *sd, Object *ob) | ||||
| { | { | ||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| Brush *brush = BKE_paint_brush(&sd->paint); | Brush *brush = BKE_paint_brush(&sd->paint); | ||||
| const int totvert = SCULPT_vertex_count_get(ss); | const int totvert = SCULPT_vertex_count_get(ss); | ||||
| if (!SCULPT_is_automasking_enabled(sd, ss, brush)) { | if (!SCULPT_is_automasking_enabled(sd, ss, brush)) { | ||||
| return; | return; | ||||
| } | } | ||||
Done Inline ActionsYou can simplify all this by doing something like this: int SCULPT_automasking_mode_effective_bits(const Sculpt *sculpt, const Brush *brush) {
return sculpt->automasking_flags | brush->automasking_flags;
}
....
ss->cache->automask_settings.flags = SCULPT_automasking_mode_effective_bits(sculpt, brush);After doing this, I'd also say that SCULPT_automasking_needs_cache can become more clean: const int automasking_flags = SCULPT_automasking_mode_effective_bits(...);
if (automasking_flags & FOO) {
...
}
if (automasking_flags & BAR) {
..
}sergey: You can simplify all this by doing something like this:
int… | |||||
| ss->cache->automask = MEM_callocN(sizeof(float) * SCULPT_vertex_count_get(ss), | SCULPT_stroke_automasking_settings_update(ss, sd, brush); | ||||
| "automask_factor"); | 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++) { | for (int i = 0; i < totvert; i++) { | ||||
| ss->cache->automask[i] = 1.0f; | ss->cache->automask_factor[i] = 1.0f; | ||||
| } | } | ||||
Done Inline Actions
sergey: - Use `MEM_calloc_arrayN` / `MEM_malloc_arrayN`
- Don't use calloc semantic if you're fully… | |||||
| if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_TOPOLOGY)) { | if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_TOPOLOGY)) { | ||||
| SCULPT_vertex_random_access_init(ss); | 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)) { | if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_FACE_SETS)) { | ||||
| SCULPT_vertex_random_access_init(ss); | 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)) { | if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) { | ||||
| SCULPT_vertex_random_access_init(ss); | SCULPT_vertex_random_access_init(ss); | ||||
| SCULPT_boundary_automasking_init(ob, | SCULPT_boundary_automasking_init(ob, | ||||
| AUTOMASK_INIT_BOUNDARY_EDGES, | AUTOMASK_INIT_BOUNDARY_EDGES, | ||||
| brush->automasking_boundary_edges_propagation_steps, | 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)) { | if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) { | ||||
| SCULPT_vertex_random_access_init(ss); | SCULPT_vertex_random_access_init(ss); | ||||
| SCULPT_boundary_automasking_init(ob, | SCULPT_boundary_automasking_init(ob, | ||||
| AUTOMASK_INIT_BOUNDARY_FACE_SETS, | AUTOMASK_INIT_BOUNDARY_FACE_SETS, | ||||
| brush->automasking_boundary_edges_propagation_steps, | brush->automasking_boundary_edges_propagation_steps, | ||||
| ss->cache->automask); | ss->cache->automask_factor); | ||||
| } | } | ||||
| } | } | ||||
Reverse the condition, unindent the body.