Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/sculpt_paint/sculpt_automasking.c')
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_automasking.c93
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);
}
}