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:
authorHans Goudey <h.goudey@me.com>2022-09-12 20:48:35 +0300
committerHans Goudey <h.goudey@me.com>2022-09-12 20:48:42 +0300
commitb5f7af31d6d474c3b455bacda079969fde7c0962 (patch)
treef75a543982b38f5222052b80647fbf35f23b5805 /source/blender/editors
parent3d3c34f345c766daabb56a453f8c8ef7bead801b (diff)
When these features aren't used, there is no sense in storing the
corresponding data layers and using their values for computations. Avoiding that should increase performance in many operations that would otherwise have to read, write, or propagate these values. It also means decreased memory usage-- not just for sculpt mode but for any mesh that was in sculpt mode. Previously the mask, face set, and hide status layers were *always* allocated by sculpt mode. Here are a few basic tests when masking and face sets are not used: | Test | Before | After | | Subsurf Modifier | 148 ms | 126 ms | | Sculpt Overlay Extraction | 24 ms every redraw | 0 ms | | Memory usage | 252 MB | 236 MB | I wouldn't expect any difference when they are used though. The code changes are mostly just making sculpt features safe for when the layers aren't stored, and some changes to the conversion to and from the hide layers. Use of the ".hide_poly" attribute replaces testing whether face sets are negative in many places. Differential Revision: https://developer.blender.org/D15937
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/object/object_remesh.cc4
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c12
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c63
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_dyntopo.c8
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_expand.c23
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_face_set.c17
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mask.c5
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_geodesic.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h10
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_mask_expand.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_ops.c32
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c16
12 files changed, 152 insertions, 44 deletions
diff --git a/source/blender/editors/object/object_remesh.cc b/source/blender/editors/object/object_remesh.cc
index a6b51048209..aa8dc4debd9 100644
--- a/source/blender/editors/object/object_remesh.cc
+++ b/source/blender/editors/object/object_remesh.cc
@@ -186,7 +186,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
}
if (ob->mode == OB_MODE_SCULPT) {
- BKE_sculpt_ensure_orig_mesh_data(CTX_data_scene(C), ob);
+ BKE_sculpt_ensure_orig_mesh_data(ob);
ED_sculpt_undo_geometry_end(ob);
}
@@ -912,7 +912,7 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update
}
if (ob->mode == OB_MODE_SCULPT) {
- BKE_sculpt_ensure_orig_mesh_data(qj->scene, ob);
+ BKE_sculpt_ensure_orig_mesh_data(ob);
ED_sculpt_undo_geometry_end(ob);
}
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index 0ea45f83336..437ff7506ba 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -134,6 +134,7 @@ static void mask_flood_fill_task_cb(void *__restrict userdata,
static int mask_flood_fill_exec(bContext *C, wmOperator *op)
{
+ const Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
PaintMaskFloodMode mode;
@@ -146,6 +147,9 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
mode = RNA_enum_get(op->ptr, "mode");
value = RNA_float_get(op->ptr, "value");
+ MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
+ BKE_sculpt_mask_layers_ensure(ob, mmd);
+
BKE_sculpt_update_object_for_edit(depsgraph, ob, false, true, false);
pbvh = ob->sculpt->pbvh;
multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
@@ -774,6 +778,8 @@ static void sculpt_gesture_init_face_set_properties(SculptGestureContext *sgcont
struct Mesh *mesh = BKE_mesh_from_object(sgcontext->vc.obact);
sgcontext->operation = MEM_callocN(sizeof(SculptGestureFaceSetOperation), "Face Set Operation");
+ sgcontext->ss->face_sets = BKE_sculpt_face_sets_ensure(mesh);
+
SculptGestureFaceSetOperation *face_set_operation = (SculptGestureFaceSetOperation *)
sgcontext->operation;
@@ -817,7 +823,7 @@ static void mask_gesture_apply_task_cb(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin (sgcontext->ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
if (sculpt_gesture_is_vertex_effected(sgcontext, &vd)) {
- float prevmask = *vd.mask;
+ float prevmask = vd.mask ? *vd.mask : 0.0f;
if (!any_masked) {
any_masked = true;
@@ -863,6 +869,10 @@ static void sculpt_gesture_init_mask_properties(SculptGestureContext *sgcontext,
SculptGestureMaskOperation *mask_operation = (SculptGestureMaskOperation *)sgcontext->operation;
+ Object *object = sgcontext->vc.obact;
+ MultiresModifierData *mmd = BKE_sculpt_multires_active(sgcontext->vc.scene, object);
+ BKE_sculpt_mask_layers_ensure(sgcontext->vc.obact, mmd);
+
mask_operation->op.sculpt_gesture_begin = sculpt_gesture_mask_begin;
mask_operation->op.sculpt_gesture_apply_for_symmetry_pass =
sculpt_gesture_mask_apply_for_symmetry_pass;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 51ff064c58d..119bd254abf 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -253,11 +253,11 @@ float SCULPT_vertex_mask_get(SculptSession *ss, PBVHVertRef vertex)
float *mask;
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
- return ss->vmask[vertex.i];
+ return ss->vmask ? ss->vmask[vertex.i] : 0.0f;
case PBVH_BMESH:
v = (BMVert *)vertex.i;
mask = BM_ELEM_CD_GET_VOID_P(v, CustomData_get_offset(&ss->bm->vdata, CD_PAINT_MASK));
- return *mask;
+ return mask ? *mask : 0.0f;
case PBVH_GRIDS: {
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
const int grid_index = vertex.i / key->grid_area;
@@ -329,7 +329,7 @@ int SCULPT_active_face_set_get(SculptSession *ss)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
- return ss->face_sets[ss->active_face_index];
+ return ss->face_sets ? ss->face_sets[ss->active_face_index] : SCULPT_FACE_SET_NONE;
case PBVH_GRIDS: {
const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg,
ss->active_grid_index);
@@ -383,6 +383,7 @@ bool SCULPT_vertex_visible_get(SculptSession *ss, PBVHVertRef vertex)
void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visible)
{
+ BLI_assert(ss->face_sets != NULL);
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
case PBVH_GRIDS:
@@ -405,6 +406,7 @@ void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visibl
void SCULPT_face_sets_visibility_invert(SculptSession *ss)
{
+ BLI_assert(ss->face_sets != NULL);
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
case PBVH_GRIDS:
@@ -422,6 +424,9 @@ void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible)
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
case PBVH_GRIDS:
+ if (!ss->face_sets) {
+ return;
+ }
for (int i = 0; i < ss->totfaces; i++) {
/* This can run on geometry without a face set assigned, so its ID sign can't be changed to
@@ -446,11 +451,15 @@ void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible)
bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, PBVHVertRef vertex)
{
+ const bool *hide_poly = BKE_pbvh_get_poly_hide(ss->pbvh);
+ if (!hide_poly) {
+ return true;
+ }
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
MeshElemMap *vert_map = &ss->pmap[vertex.i];
for (int j = 0; j < ss->pmap[vertex.i].count; j++) {
- if (ss->face_sets[vert_map->indices[j]] > 0) {
+ if (!hide_poly[vert_map->indices[j]]) {
return true;
}
}
@@ -466,11 +475,15 @@ bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, PBVHVertRef verte
bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, PBVHVertRef vertex)
{
+ const bool *hide_poly = BKE_pbvh_get_poly_hide(ss->pbvh);
+ if (!hide_poly) {
+ return true;
+ }
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
MeshElemMap *vert_map = &ss->pmap[vertex.i];
for (int j = 0; j < ss->pmap[vertex.i].count; j++) {
- if (ss->face_sets[vert_map->indices[j]] < 0) {
+ if (hide_poly[vert_map->indices[j]]) {
return false;
}
}
@@ -482,7 +495,7 @@ bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, PBVHVertRe
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
const int grid_index = vertex.i / key->grid_area;
const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index);
- return ss->face_sets[face_index] > 0;
+ return !hide_poly[face_index];
}
}
return true;
@@ -492,6 +505,7 @@ void SCULPT_vertex_face_set_set(SculptSession *ss, PBVHVertRef vertex, int face_
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
+ BLI_assert(ss->face_sets != NULL);
MeshElemMap *vert_map = &ss->pmap[vertex.i];
for (int j = 0; j < ss->pmap[vertex.i].count; j++) {
if (ss->face_sets[vert_map->indices[j]] > 0) {
@@ -502,6 +516,7 @@ void SCULPT_vertex_face_set_set(SculptSession *ss, PBVHVertRef vertex, int face_
case PBVH_BMESH:
break;
case PBVH_GRIDS: {
+ BLI_assert(ss->face_sets != NULL);
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
const int grid_index = vertex.i / key->grid_area;
const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index);
@@ -517,6 +532,9 @@ int SCULPT_vertex_face_set_get(SculptSession *ss, PBVHVertRef vertex)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
+ if (!ss->face_sets) {
+ return SCULPT_FACE_SET_NONE;
+ }
MeshElemMap *vert_map = &ss->pmap[vertex.i];
int face_set = 0;
for (int i = 0; i < ss->pmap[vertex.i].count; i++) {
@@ -529,6 +547,9 @@ int SCULPT_vertex_face_set_get(SculptSession *ss, PBVHVertRef vertex)
case PBVH_BMESH:
return 0;
case PBVH_GRIDS: {
+ if (!ss->face_sets) {
+ return SCULPT_FACE_SET_NONE;
+ }
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
const int grid_index = vertex.i / key->grid_area;
const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index);
@@ -542,6 +563,9 @@ bool SCULPT_vertex_has_face_set(SculptSession *ss, PBVHVertRef vertex, int face_
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
+ if (!ss->face_sets) {
+ return face_set == SCULPT_FACE_SET_NONE;
+ }
MeshElemMap *vert_map = &ss->pmap[vertex.i];
for (int i = 0; i < ss->pmap[vertex.i].count; i++) {
if (ss->face_sets[vert_map->indices[i]] == face_set) {
@@ -553,6 +577,9 @@ bool SCULPT_vertex_has_face_set(SculptSession *ss, PBVHVertRef vertex, int face_
case PBVH_BMESH:
return true;
case PBVH_GRIDS: {
+ if (!ss->face_sets) {
+ return face_set == SCULPT_FACE_SET_NONE;
+ }
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
const int grid_index = vertex.i / key->grid_area;
const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index);
@@ -599,6 +626,9 @@ static void UNUSED_FUNCTION(sculpt_visibility_sync_vertex_to_face_sets)(SculptSe
void SCULPT_visibility_sync_all_vertex_to_face_sets(SculptSession *ss)
{
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
+ if (ss->face_sets == NULL) {
+ return;
+ }
for (int i = 0; i < ss->totfaces; i++) {
const MPoly *poly = &ss->mpoly[i];
bool poly_visible = true;
@@ -620,6 +650,9 @@ void SCULPT_visibility_sync_all_vertex_to_face_sets(SculptSession *ss)
static bool sculpt_check_unique_face_set_in_base_mesh(SculptSession *ss, int index)
{
+ if (!ss->face_sets) {
+ return true;
+ }
MeshElemMap *vert_map = &ss->pmap[index];
int face_set = -1;
for (int i = 0; i < ss->pmap[index].count; i++) {
@@ -676,6 +709,9 @@ bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, PBVHVertRef vertex)
case PBVH_BMESH:
return true;
case PBVH_GRIDS: {
+ if (!ss->face_sets) {
+ return true;
+ }
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
const int grid_index = vertex.i / key->grid_area;
const int vertex_index = vertex.i - grid_index * key->grid_area;
@@ -703,6 +739,9 @@ int SCULPT_face_set_next_available_get(SculptSession *ss)
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
case PBVH_GRIDS: {
+ if (!ss->face_sets) {
+ return 0;
+ }
int next_face_set = 0;
for (int i = 0; i < ss->totfaces; i++) {
if (abs(ss->face_sets[i]) > next_face_set) {
@@ -792,9 +831,10 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss,
iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
iter->neighbors = iter->neighbors_fixed;
iter->neighbor_indices = iter->neighbor_indices_fixed;
+ const bool *hide_poly = BKE_pbvh_get_vert_hide(ss->pbvh);
for (int i = 0; i < ss->pmap[vertex.i].count; i++) {
- if (ss->face_sets[vert_map->indices[i]] < 0) {
+ if (hide_poly && hide_poly[vert_map->indices[i]]) {
/* Skip connectivity from hidden faces. */
continue;
}
@@ -3302,6 +3342,15 @@ static void do_brush_action(Sculpt *sd,
BKE_pbvh_ensure_node_loops(ss->pbvh);
}
+ if (SCULPT_tool_is_mask(brush->sculpt_tool)) {
+ MultiresModifierData *mmd = BKE_sculpt_multires_active(ss->scene, ob);
+ BKE_sculpt_mask_layers_ensure(ob, mmd);
+ }
+ if (SCULPT_tool_is_face_sets(brush->sculpt_tool)) {
+ Mesh *mesh = BKE_object_get_original_mesh(ob);
+ ss->face_sets = BKE_sculpt_face_sets_ensure(mesh);
+ }
+
/* Build a list of all nodes that are potentially within the brush's area of influence */
if (SCULPT_tool_needs_all_pbvh_nodes(brush)) {
diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
index ad8a1cde9dc..46674c5d239 100644
--- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c
@@ -215,13 +215,7 @@ static void SCULPT_dynamic_topology_disable_ex(
BKE_sculptsession_bm_to_me(ob, true);
/* Reset Face Sets as they are no longer valid. */
- if (!CustomData_has_layer(&me->pdata, CD_SCULPT_FACE_SETS)) {
- CustomData_add_layer(&me->pdata, CD_SCULPT_FACE_SETS, CD_SET_DEFAULT, NULL, me->totpoly);
- }
- ss->face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS);
- for (int i = 0; i < me->totpoly; i++) {
- ss->face_sets[i] = 1;
- }
+ CustomData_free_layers(&me->pdata, CD_SCULPT_FACE_SETS, me->totpoly);
me->face_sets_color_default = 1;
/* Sync the visibility to vertices manually as the pmap is still not initialized. */
diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.c b/source/blender/editors/sculpt_paint/sculpt_expand.c
index 4aafeacfbff..414a855ab2f 100644
--- a/source/blender/editors/sculpt_paint/sculpt_expand.c
+++ b/source/blender/editors/sculpt_paint/sculpt_expand.c
@@ -17,6 +17,7 @@
#include "DNA_brush_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "BKE_brush.h"
@@ -1390,9 +1391,15 @@ static void sculpt_expand_original_state_store(Object *ob, ExpandCache *expand_c
/* Face Sets are always stored as they are needed for snapping. */
expand_cache->initial_face_sets = MEM_malloc_arrayN(totface, sizeof(int), "initial face set");
expand_cache->original_face_sets = MEM_malloc_arrayN(totface, sizeof(int), "original face set");
- for (int i = 0; i < totface; i++) {
- expand_cache->initial_face_sets[i] = ss->face_sets[i];
- expand_cache->original_face_sets[i] = ss->face_sets[i];
+ if (ss->face_sets) {
+ for (int i = 0; i < totface; i++) {
+ expand_cache->initial_face_sets[i] = ss->face_sets[i];
+ expand_cache->original_face_sets[i] = ss->face_sets[i];
+ }
+ }
+ else {
+ memset(expand_cache->initial_face_sets, SCULPT_FACE_SET_NONE, sizeof(int) * totface);
+ memset(expand_cache->original_face_sets, SCULPT_FACE_SET_NONE, sizeof(int) * totface);
}
if (expand_cache->target == SCULPT_EXPAND_TARGET_MASK) {
@@ -2118,6 +2125,16 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
return OPERATOR_CANCELLED;
}
+ if (ss->expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS) {
+ Mesh *mesh = ob->data;
+ ss->face_sets = BKE_sculpt_face_sets_ensure(mesh);
+ }
+
+ if (ss->expand_cache->target == SCULPT_EXPAND_TARGET_MASK) {
+ MultiresModifierData *mmd = BKE_sculpt_multires_active(ss->scene, ob);
+ BKE_sculpt_mask_layers_ensure(ob, mmd);
+ }
+
/* Face Set operations are not supported in dyntopo. */
if (ss->expand_cache->target == SCULPT_EXPAND_TARGET_FACE_SETS &&
BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c
index 64bc6188bbc..e66a7f8b9de 100644
--- a/source/blender/editors/sculpt_paint/sculpt_face_set.c
+++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c
@@ -303,6 +303,9 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ Mesh *mesh = ob->data;
+ ss->face_sets = BKE_sculpt_face_sets_ensure(mesh);
+
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, mode == SCULPT_FACE_SET_MASKED, false);
const int tot_vert = SCULPT_vertex_count_get(ss);
@@ -349,7 +352,6 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
}
if (all_visible) {
- Mesh *mesh = ob->data;
mesh->face_sets_color_default = next_face_set;
BKE_pbvh_face_sets_color_set(
ss->pbvh, mesh->face_sets_color_seed, mesh->face_sets_color_default);
@@ -373,7 +375,6 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
}
if (mode == SCULPT_FACE_SET_SELECTION) {
- Mesh *mesh = ob->data;
BMesh *bm;
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
bm = BM_mesh_create(&allocsize,
@@ -850,6 +851,10 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ if (!pbvh_has_face_sets(ss->pbvh)) {
+ return OPERATOR_CANCELLED;
+ }
+
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
const int tot_vert = SCULPT_vertex_count_get(ss);
@@ -1000,6 +1005,10 @@ static int sculpt_face_sets_randomize_colors_exec(bContext *C, wmOperator *UNUSE
return OPERATOR_CANCELLED;
}
+ if (!pbvh_has_face_sets(ss->pbvh)) {
+ return OPERATOR_CANCELLED;
+ }
+
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
int totnode;
@@ -1154,7 +1163,9 @@ static void sculpt_face_set_shrink(Object *ob,
static bool check_single_face_set(SculptSession *ss, int *face_sets, const bool check_visible_only)
{
-
+ if (face_sets == NULL) {
+ return true;
+ }
int first_face_set = SCULPT_FACE_SET_NONE;
if (check_visible_only) {
for (int f = 0; f < ss->totfaces; f++) {
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
index cba1d3dcdc1..bb27e4f1e9e 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
@@ -14,6 +14,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
#include "BKE_brush.h"
#include "BKE_context.h"
@@ -174,11 +175,15 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ const Scene *scene = CTX_data_scene(C);
PBVHNode **nodes;
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
int totnode;
int filter_type = RNA_enum_get(op->ptr, "filter_type");
+ MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
+ BKE_sculpt_mask_layers_ensure(ob, mmd);
+
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
SculptSession *ss = ob->sculpt;
diff --git a/source/blender/editors/sculpt_paint/sculpt_geodesic.c b/source/blender/editors/sculpt_paint/sculpt_geodesic.c
index a5885092ee3..c0856ab21d2 100644
--- a/source/blender/editors/sculpt_paint/sculpt_geodesic.c
+++ b/source/blender/editors/sculpt_paint/sculpt_geodesic.c
@@ -170,6 +170,8 @@ static float *SCULPT_geodesic_mesh_create(Object *ob,
}
}
+ const bool *hide_poly = BKE_pbvh_get_poly_hide(ss->pbvh);
+
/* Add edges adjacent to an initial vertex to the queue. */
for (int i = 0; i < totedge; i++) {
const int v1 = edges[i].v1;
@@ -199,7 +201,7 @@ static float *SCULPT_geodesic_mesh_create(Object *ob,
if (ss->epmap[e].count != 0) {
for (int poly_map_index = 0; poly_map_index < ss->epmap[e].count; poly_map_index++) {
const int poly = ss->epmap[e].indices[poly_map_index];
- if (ss->face_sets[poly] <= 0) {
+ if (hide_poly && hide_poly[poly]) {
continue;
}
const MPoly *mpoly = &polys[poly];
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 4bc06d68a02..7a72e5cc84b 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -1837,6 +1837,16 @@ BLI_INLINE bool SCULPT_tool_is_paint(int tool)
return ELEM(tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR);
}
+BLI_INLINE bool SCULPT_tool_is_mask(int tool)
+{
+ return ELEM(tool, SCULPT_TOOL_MASK);
+}
+
+BLI_INLINE bool SCULPT_tool_is_face_sets(int tool)
+{
+ return ELEM(tool, SCULPT_TOOL_DRAW_FACE_SETS);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c
index 9556d24f12c..ec246cd3788 100644
--- a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c
+++ b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c
@@ -391,7 +391,7 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
if (create_face_set) {
ss->filter_cache->prev_face_set = MEM_callocN(sizeof(float) * ss->totfaces, "prev face mask");
for (int i = 0; i < ss->totfaces; i++) {
- ss->filter_cache->prev_face_set[i] = ss->face_sets[i];
+ ss->filter_cache->prev_face_set[i] = ss->face_sets ? ss->face_sets[i] : 0;
}
ss->filter_cache->new_face_set = SCULPT_face_set_next_available_get(ss);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.c b/source/blender/editors/sculpt_paint/sculpt_ops.c
index 10a2ece73de..055e02a5703 100644
--- a/source/blender/editors/sculpt_paint/sculpt_ops.c
+++ b/source/blender/editors/sculpt_paint/sculpt_ops.c
@@ -300,28 +300,30 @@ static void sculpt_init_session(Main *bmain, Depsgraph *depsgraph, Scene *scene,
ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
ob->sculpt->mode_type = OB_MODE_SCULPT;
- BKE_sculpt_ensure_orig_mesh_data(scene, ob);
+ BKE_sculpt_ensure_orig_mesh_data(ob);
BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
/* This function expects a fully evaluated depsgraph. */
BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false);
- /* Here we can detect geometry that was just added to Sculpt Mode as it has the
- * SCULPT_FACE_SET_NONE assigned, so we can create a new Face Set for it. */
- /* In sculpt mode all geometry that is assigned to SCULPT_FACE_SET_NONE is considered as not
- * initialized, which is used is some operators that modify the mesh topology to perform certain
- * actions in the new polys. After these operations are finished, all polys should have a valid
- * face set ID assigned (different from SCULPT_FACE_SET_NONE) to manage their visibility
- * correctly. */
- /* TODO(pablodp606): Based on this we can improve the UX in future tools for creating new
- * objects, like moving the transform pivot position to the new area or masking existing
- * geometry. */
SculptSession *ss = ob->sculpt;
- const int new_face_set = SCULPT_face_set_next_available_get(ss);
- for (int i = 0; i < ss->totfaces; i++) {
- if (ss->face_sets[i] == SCULPT_FACE_SET_NONE) {
- ss->face_sets[i] = new_face_set;
+ if (ss->face_sets) {
+ /* Here we can detect geometry that was just added to Sculpt Mode as it has the
+ * SCULPT_FACE_SET_NONE assigned, so we can create a new Face Set for it. */
+ /* In sculpt mode all geometry that is assigned to SCULPT_FACE_SET_NONE is considered as not
+ * initialized, which is used is some operators that modify the mesh topology to perform
+ * certain actions in the new polys. After these operations are finished, all polys should have
+ * a valid face set ID assigned (different from SCULPT_FACE_SET_NONE) to manage their
+ * visibility correctly. */
+ /* TODO(pablodp606): Based on this we can improve the UX in future tools for creating new
+ * objects, like moving the transform pivot position to the new area or masking existing
+ * geometry. */
+ const int new_face_set = SCULPT_face_set_next_available_get(ss);
+ for (int i = 0; i < ss->totfaces; i++) {
+ if (ss->face_sets[i] == SCULPT_FACE_SET_NONE) {
+ ss->face_sets[i] = new_face_set;
+ }
}
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index a31be07d8af..22928a8c934 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -476,7 +476,8 @@ static bool sculpt_undo_restore_face_sets(bContext *C, SculptUndoNode *unode)
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = BKE_view_layer_active_object_get(view_layer);
Mesh *me = BKE_object_get_original_mesh(ob);
- int *face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS);
+ int *face_sets = CustomData_add_layer(
+ &me->pdata, CD_SCULPT_FACE_SETS, CD_CONSTRUCT, NULL, me->totpoly);
for (int i = 0; i < me->totpoly; i++) {
face_sets[i] = unode->face_sets[i];
}
@@ -1354,8 +1355,13 @@ static SculptUndoNode *sculpt_undo_face_sets_push(Object *ob, SculptUndoType typ
unode->face_sets = MEM_callocN(me->totpoly * sizeof(int), "sculpt face sets");
const int *face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS);
- for (int i = 0; i < me->totpoly; i++) {
- unode->face_sets[i] = face_sets[i];
+ if (face_sets) {
+ for (int i = 0; i < me->totpoly; i++) {
+ unode->face_sets[i] = face_sets[i];
+ }
+ }
+ else {
+ memset(unode->face_sets, SCULPT_FACE_SET_NONE, sizeof(int) * me->totpoly);
}
BLI_addtail(&usculpt->nodes, unode);
@@ -1513,7 +1519,9 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
sculpt_undo_store_hidden(ob, unode);
break;
case SCULPT_UNDO_MASK:
- sculpt_undo_store_mask(ob, unode);
+ if (pbvh_has_mask(ss->pbvh)) {
+ sculpt_undo_store_mask(ob, unode);
+ }
break;
case SCULPT_UNDO_COLOR:
sculpt_undo_store_color(ob, unode);