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:
-rw-r--r--source/blender/blenkernel/BKE_paint.h18
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h2
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.cc2
-rw-r--r--source/blender/blenkernel/intern/paint.cc206
-rw-r--r--source/blender/blenkernel/intern/pbvh.c19
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h1
-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
-rw-r--r--source/blender/gpu/GPU_buffers.h1
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c27
-rw-r--r--source/blender/gpu/intern/gpu_shader_builder_stubs.cc4
-rw-r--r--source/blender/makesrna/intern/rna_object.c2
22 files changed, 275 insertions, 203 deletions
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 9a067e761d7..b2ecd28e884 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -213,9 +213,7 @@ bool BKE_paint_always_hide_test(struct Object *ob);
/**
* Returns non-zero if any of the face's vertices are hidden, zero otherwise.
*/
-bool paint_is_face_hidden(const struct MLoopTri *lt,
- const bool *hide_vert,
- const struct MLoop *mloop);
+bool paint_is_face_hidden(const struct MLoopTri *lt, const bool *hide_poly);
/**
* Returns non-zero if any of the corners of the grid
* face whose inner corner is at (x, y) are hidden, zero otherwise.
@@ -689,7 +687,7 @@ void BKE_sculpt_update_object_for_edit(struct Depsgraph *depsgraph,
bool need_pmap,
bool need_mask,
bool is_paint_tool);
-void BKE_sculpt_update_object_before_eval(const struct Scene *scene, struct Object *ob_eval);
+void BKE_sculpt_update_object_before_eval(struct Object *ob_eval);
void BKE_sculpt_update_object_after_eval(struct Depsgraph *depsgraph, struct Object *ob_eval);
/**
@@ -698,6 +696,7 @@ void BKE_sculpt_update_object_after_eval(struct Depsgraph *depsgraph, struct Obj
*/
struct MultiresModifierData *BKE_sculpt_multires_active(const struct Scene *scene,
struct Object *ob);
+int *BKE_sculpt_face_sets_ensure(struct Mesh *mesh);
int BKE_sculpt_mask_layers_ensure(struct Object *ob, struct MultiresModifierData *mmd);
void BKE_sculpt_toolsettings_data_ensure(struct Scene *scene);
@@ -719,18 +718,17 @@ void BKE_sculpt_sync_face_sets_visibility_to_grids(struct Mesh *mesh,
struct SubdivCCG *subdiv_ccg);
/**
- * Ensures that a Face Set data-layers exists. If it does not, it creates one respecting the
- * visibility stored in the vertices of the mesh. If it does, it copies the visibility from the
- * mesh to the Face Sets. */
-void BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(struct Mesh *mesh);
+ * If a face set layer exists, initialize its visiblity (sign) from the mesh's hidden values.
+ */
+void BKE_sculpt_face_sets_update_from_base_mesh_visibility(struct Mesh *mesh);
/**
- * Ensures we do have expected mesh data in original mesh for the sculpt mode.
+ * Makes sculpt data consistent with other data on the mesh.
*
* \note IDs are expected to be original ones here, and calling code should ensure it updates its
* depsgraph properly after calling this function if it needs up-to-date evaluated data.
*/
-void BKE_sculpt_ensure_orig_mesh_data(struct Scene *scene, struct Object *object);
+void BKE_sculpt_ensure_orig_mesh_data(struct Object *object);
/**
* Test if PBVH can be used directly for drawing, which is faster than
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 716ee7d2a21..403f3a31ba0 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -674,6 +674,8 @@ const float (*BKE_pbvh_get_vert_normals(const PBVH *pbvh))[3];
const bool *BKE_pbvh_get_vert_hide(const PBVH *pbvh);
bool *BKE_pbvh_get_vert_hide_for_write(PBVH *pbvh);
+const bool *BKE_pbvh_get_poly_hide(const PBVH *pbvh);
+
PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node);
void BKE_pbvh_node_color_buffer_free(PBVH *pbvh);
bool BKE_pbvh_get_color_layer(const struct Mesh *me,
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index 986e10b3a16..d7db0ad765c 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -1720,7 +1720,7 @@ void makeDerivedMesh(struct Depsgraph *depsgraph,
BKE_object_free_derived_caches(ob);
if (DEG_is_active(depsgraph)) {
- BKE_sculpt_update_object_before_eval(scene, ob);
+ BKE_sculpt_update_object_before_eval(ob);
}
/* NOTE: Access the `edit_mesh` after freeing the derived caches, so that `ob->data` is restored
diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc
index f5f460c6ed4..fd4696f97fb 100644
--- a/source/blender/blenkernel/intern/paint.cc
+++ b/source/blender/blenkernel/intern/paint.cc
@@ -1247,13 +1247,12 @@ void BKE_paint_blend_read_lib(BlendLibReader *reader, Scene *sce, Paint *p)
}
}
-bool paint_is_face_hidden(const MLoopTri *lt, const bool *hide_vert, const MLoop *mloop)
+bool paint_is_face_hidden(const MLoopTri *lt, const bool *hide_poly)
{
- if (!hide_vert) {
+ if (!hide_poly) {
return false;
}
- return ((hide_vert[mloop[lt->tri[0]].v]) || (hide_vert[mloop[lt->tri[1]].v]) ||
- (hide_vert[mloop[lt->tri[2]].v]));
+ return hide_poly[lt->poly];
}
bool paint_is_grid_face_hidden(const uint *grid_hidden, int gridsize, int x, int y)
@@ -1632,15 +1631,8 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
return false;
}
-/**
- * \param need_mask: So that the evaluated mesh that is returned has mask data.
- */
-static void sculpt_update_object(Depsgraph *depsgraph,
- Object *ob,
- Object *ob_eval,
- bool need_pmap,
- bool need_mask,
- bool is_paint_tool)
+static void sculpt_update_object(
+ Depsgraph *depsgraph, Object *ob, Object *ob_eval, bool need_pmap, bool is_paint_tool)
{
Scene *scene = DEG_get_input_scene(depsgraph);
Sculpt *sd = scene->toolsettings->sculpt;
@@ -1662,15 +1654,6 @@ static void sculpt_update_object(Depsgraph *depsgraph,
ss->scene = scene;
- if (need_mask) {
- if (mmd == nullptr) {
- BLI_assert(CustomData_has_layer(&me->vdata, CD_PAINT_MASK));
- }
- else {
- BLI_assert(CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK));
- }
- }
-
ss->shapekey_active = (mmd == nullptr) ? BKE_keyblock_from_object(ob) : nullptr;
/* NOTE: Weight pPaint require mesh info for loop lookup, but it never uses multires code path,
@@ -1726,7 +1709,6 @@ static void sculpt_update_object(Depsgraph *depsgraph,
/* Sculpt Face Sets. */
if (use_face_sets) {
- BLI_assert(CustomData_has_layer(&me->pdata, CD_SCULPT_FACE_SETS));
ss->face_sets = static_cast<int *>(CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS));
}
else {
@@ -1859,24 +1841,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
}
}
-static void sculpt_face_sets_ensure(Mesh *mesh)
-{
- if (CustomData_has_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)) {
- return;
- }
-
- int *new_face_sets = static_cast<int *>(CustomData_add_layer(
- &mesh->pdata, CD_SCULPT_FACE_SETS, CD_CONSTRUCT, nullptr, mesh->totpoly));
-
- /* Initialize the new Face Set data-layer with a default valid visible ID and set the default
- * color to render it white. */
- for (int i = 0; i < mesh->totpoly; i++) {
- new_face_sets[i] = 1;
- }
- mesh->face_sets_color_default = 1;
-}
-
-void BKE_sculpt_update_object_before_eval(const Scene *scene, Object *ob_eval)
+void BKE_sculpt_update_object_before_eval(Object *ob_eval)
{
/* Update before mesh evaluation in the dependency graph. */
SculptSession *ss = ob_eval->sculpt;
@@ -1906,16 +1871,6 @@ void BKE_sculpt_update_object_before_eval(const Scene *scene, Object *ob_eval)
MEM_freeN(nodes);
}
}
-
- if (ss) {
- Object *ob_orig = DEG_get_original_object(ob_eval);
- Mesh *mesh = BKE_object_get_original_mesh(ob_orig);
- MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob_orig);
-
- /* Ensure attribute layout is still correct. */
- sculpt_face_sets_ensure(mesh);
- BKE_sculpt_mask_layers_ensure(ob_orig, mmd);
- }
}
void BKE_sculpt_update_object_after_eval(Depsgraph *depsgraph, Object *ob_eval)
@@ -1924,7 +1879,7 @@ void BKE_sculpt_update_object_after_eval(Depsgraph *depsgraph, Object *ob_eval)
* other data when modifiers change the mesh. */
Object *ob_orig = DEG_get_original_object(ob_eval);
- sculpt_update_object(depsgraph, ob_orig, ob_eval, false, false, false);
+ sculpt_update_object(depsgraph, ob_orig, ob_eval, false, false);
}
void BKE_sculpt_color_layer_create_if_needed(Object *object)
@@ -1962,13 +1917,53 @@ void BKE_sculpt_color_layer_create_if_needed(Object *object)
}
void BKE_sculpt_update_object_for_edit(
- Depsgraph *depsgraph, Object *ob_orig, bool need_pmap, bool need_mask, bool is_paint_tool)
+ Depsgraph *depsgraph, Object *ob_orig, bool need_pmap, bool /*need_mask*/, bool is_paint_tool)
{
BLI_assert(ob_orig == DEG_get_original_object(ob_orig));
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob_orig);
- sculpt_update_object(depsgraph, ob_orig, ob_eval, need_pmap, need_mask, is_paint_tool);
+ sculpt_update_object(depsgraph, ob_orig, ob_eval, need_pmap, is_paint_tool);
+}
+
+int *BKE_sculpt_face_sets_ensure(Mesh *mesh)
+{
+ using namespace blender;
+ using namespace blender::bke;
+ if (CustomData_has_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)) {
+ return static_cast<int *>(CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS));
+ }
+
+ const AttributeAccessor attributes = mesh->attributes_for_write();
+ const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
+ ".hide_poly", ATTR_DOMAIN_FACE, false);
+
+ MutableSpan<int> face_sets = {
+ static_cast<int *>(CustomData_add_layer(
+ &mesh->pdata, CD_SCULPT_FACE_SETS, CD_CONSTRUCT, nullptr, mesh->totpoly)),
+ mesh->totpoly};
+
+ /* Initialize the new face sets with a default valid visible ID and set the default
+ * color to render it white. */
+ if (hide_poly.is_single() && !hide_poly.get_internal_single()) {
+ face_sets.fill(1);
+ }
+ else {
+ const int face_sets_default_visible_id = 1;
+ const int face_sets_default_hidden_id = -(face_sets_default_visible_id + 1);
+
+ const VArraySpan<bool> hide_poly_span{hide_poly};
+ for (const int i : face_sets.index_range()) {
+ /* Assign a new hidden ID to hidden faces. This way we get at initial split in two Face Sets
+ * between hidden and visible faces based on the previous mesh visibly from other mode that
+ * can be useful in some cases. */
+ face_sets[i] = hide_poly_span[i] ? face_sets_default_hidden_id :
+ face_sets_default_visible_id;
+ }
+ }
+
+ mesh->face_sets_color_default = 1;
+ return face_sets.data();
}
int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
@@ -2092,67 +2087,48 @@ static bool check_sculpt_object_deformed(Object *object, const bool for_construc
return deformed;
}
-void BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(Mesh *mesh)
+void BKE_sculpt_face_sets_update_from_base_mesh_visibility(Mesh *mesh)
{
- const int face_sets_default_visible_id = 1;
- const int face_sets_default_hidden_id = -(face_sets_default_visible_id + 1);
-
- bool initialize_new_face_sets = false;
-
- if (CustomData_has_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)) {
- /* Make everything visible. */
- int *current_face_sets = static_cast<int *>(
- CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS));
- for (int i = 0; i < mesh->totpoly; i++) {
- current_face_sets[i] = abs(current_face_sets[i]);
- }
- }
- else {
- initialize_new_face_sets = true;
- int *new_face_sets = static_cast<int *>(CustomData_add_layer(
- &mesh->pdata, CD_SCULPT_FACE_SETS, CD_CONSTRUCT, nullptr, mesh->totpoly));
-
- /* Initialize the new Face Set data-layer with a default valid visible ID and set the default
- * color to render it white. */
- for (int i = 0; i < mesh->totpoly; i++) {
- new_face_sets[i] = face_sets_default_visible_id;
- }
- mesh->face_sets_color_default = face_sets_default_visible_id;
+ using namespace blender;
+ using namespace blender::bke;
+ if (!CustomData_has_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)) {
+ return;
}
- int *face_sets = static_cast<int *>(CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS));
- const bool *hide_poly = (const bool *)CustomData_get_layer_named(
- &mesh->pdata, CD_PROP_BOOL, ".hide_poly");
+ const AttributeAccessor attributes = mesh->attributes();
+ const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
+ ".hide_poly", ATTR_DOMAIN_FACE, false);
+ if (hide_poly.is_single() && !hide_poly.get_internal_single()) {
+ return;
+ }
- for (int i = 0; i < mesh->totpoly; i++) {
- if (!(hide_poly && hide_poly[i])) {
- continue;
- }
+ MutableSpan<int> face_sets{
+ static_cast<int *>(CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS)), mesh->totpoly};
- if (initialize_new_face_sets) {
- /* When initializing a new Face Set data-layer, assign a new hidden Face Set ID to hidden
- * vertices. This way, we get at initial split in two Face Sets between hidden and
- * visible vertices based on the previous mesh visibly from other mode that can be
- * useful in some cases. */
- face_sets[i] = face_sets_default_hidden_id;
- }
- else {
- /* Otherwise, set the already existing Face Set ID to hidden. */
- face_sets[i] = -abs(face_sets[i]);
- }
+ for (const int i : hide_poly.index_range()) {
+ face_sets[i] = hide_poly[i] ? -std::abs(face_sets[i]) : std::abs(face_sets[i]);
}
}
-void BKE_sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh)
+static void set_hide_poly_from_face_sets(Mesh &mesh)
{
+ using namespace blender;
using namespace blender::bke;
- const int *face_sets = static_cast<const int *>(
- CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS));
- if (!face_sets) {
+ if (!CustomData_has_layer(&mesh.pdata, CD_SCULPT_FACE_SETS)) {
+ return;
+ }
+
+ const Span<int> face_sets{
+ static_cast<const int *>(CustomData_get_layer(&mesh.pdata, CD_SCULPT_FACE_SETS)),
+ mesh.totpoly};
+
+ MutableAttributeAccessor attributes = mesh.attributes_for_write();
+ if (std::all_of(
+ face_sets.begin(), face_sets.end(), [&](const int value) { return value > 0; })) {
+ attributes.remove(".hide_poly");
return;
}
- MutableAttributeAccessor attributes = mesh->attributes_for_write();
SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_only_span<bool>(
".hide_poly", ATTR_DOMAIN_FACE);
if (!hide_poly) {
@@ -2162,7 +2138,11 @@ void BKE_sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh)
hide_poly.span[i] = face_sets[i] < 0;
}
hide_poly.finish();
+}
+void BKE_sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh)
+{
+ set_hide_poly_from_face_sets(*mesh);
BKE_mesh_flush_hidden_from_polys(mesh);
}
@@ -2200,41 +2180,29 @@ void BKE_sculpt_sync_face_sets_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv
void BKE_sculpt_sync_face_set_visibility(Mesh *mesh, SubdivCCG *subdiv_ccg)
{
- BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(mesh);
+ BKE_sculpt_face_sets_update_from_base_mesh_visibility(mesh);
BKE_sculpt_sync_face_sets_visibility_to_base_mesh(mesh);
BKE_sculpt_sync_face_sets_visibility_to_grids(mesh, subdiv_ccg);
}
-void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object)
+void BKE_sculpt_ensure_orig_mesh_data(Object *object)
{
Mesh *mesh = BKE_mesh_from_object(object);
- MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, object);
-
BLI_assert(object->mode == OB_MODE_SCULPT);
/* Copy the current mesh visibility to the Face Sets. */
- BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(mesh);
- if (object->sculpt != nullptr) {
- /* If a sculpt session is active, ensure we have its face-set data properly up-to-date. */
- object->sculpt->face_sets = static_cast<int *>(
- CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS));
-
- /* NOTE: In theory we could add that on the fly when required by sculpt code.
- * But this then requires proper update of depsgraph etc. For now we play safe, optimization is
- * always possible later if it's worth it. */
- BKE_sculpt_mask_layers_ensure(object, mmd);
- }
+ BKE_sculpt_face_sets_update_from_base_mesh_visibility(mesh);
/* Tessfaces aren't used and will become invalid. */
BKE_mesh_tessface_clear(mesh);
/* We always need to flush updates from depsgraph here, since at the very least
- * `BKE_sculpt_face_sets_ensure_from_base_mesh_visibility()` will have updated some data layer of
+ * `BKE_sculpt_face_sets_update_from_base_mesh_visibility()` will have updated some data layer of
* the mesh.
*
* All known potential sources of updates:
* - Addition of, or changes to, the `CD_SCULPT_FACE_SETS` data layer
- * (`BKE_sculpt_face_sets_ensure_from_base_mesh_visibility`).
+ * (`BKE_sculpt_face_sets_update_from_base_mesh_visibility`).
* - Addition of a `CD_PAINT_MASK` data layer (`BKE_sculpt_mask_layers_ensure`).
* - Object has any active modifier (modifier stack can be different in Sculpt mode).
* - Multires:
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 6d761f56f13..2de5c718918 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -285,7 +285,7 @@ static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node)
}
if (has_visible == false) {
- if (!paint_is_face_hidden(lt, pbvh->hide_vert, pbvh->mloop)) {
+ if (!paint_is_face_hidden(lt, pbvh->hide_poly)) {
has_visible = true;
}
}
@@ -552,6 +552,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
pbvh->mesh = mesh;
pbvh->header.type = PBVH_FACES;
pbvh->mpoly = mpoly;
+ pbvh->hide_poly = (bool *)CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, ".hide_poly");
pbvh->material_indices = (const int *)CustomData_get_layer_named(
&mesh->pdata, CD_PROP_INT32, "material_index");
pbvh->mloop = mloop;
@@ -1313,11 +1314,7 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
}
case PBVH_FACES:
node->draw_buffers = GPU_pbvh_mesh_buffers_build(
- pbvh->mesh,
- pbvh->looptri,
- CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS),
- node->prim_indices,
- node->totprim);
+ pbvh->mesh, pbvh->looptri, node->prim_indices, node->totprim);
break;
case PBVH_BMESH:
node->draw_buffers = GPU_pbvh_bmesh_buffers_build(pbvh->flags &
@@ -2293,7 +2290,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
const MLoopTri *lt = &pbvh->looptri[faces[i]];
const int *face_verts = node->face_vert_indices[i];
- if (pbvh->respect_hide && paint_is_face_hidden(lt, pbvh->hide_vert, mloop)) {
+ if (pbvh->respect_hide && paint_is_face_hidden(lt, pbvh->hide_poly)) {
continue;
}
@@ -2602,7 +2599,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,
const MLoopTri *lt = &pbvh->looptri[faces[i]];
const int *face_verts = node->face_vert_indices[i];
- if (pbvh->respect_hide && paint_is_face_hidden(lt, pbvh->hide_vert, mloop)) {
+ if (pbvh->respect_hide && paint_is_face_hidden(lt, pbvh->hide_poly)) {
continue;
}
@@ -3219,6 +3216,12 @@ const bool *BKE_pbvh_get_vert_hide(const PBVH *pbvh)
return pbvh->hide_vert;
}
+const bool *BKE_pbvh_get_poly_hide(const PBVH *pbvh)
+{
+ BLI_assert(pbvh->header.type == PBVH_FACES);
+ return pbvh->hide_poly;
+}
+
bool *BKE_pbvh_get_vert_hide_for_write(PBVH *pbvh)
{
BLI_assert(pbvh->header.type == PBVH_FACES);
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index b848327b7a9..8ab56839f9c 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -156,6 +156,7 @@ struct PBVH {
bool *hide_vert;
struct MVert *verts;
const struct MPoly *mpoly;
+ bool *hide_poly;
/** Material indices. Only valid for polygon meshes. */
const int *material_indices;
const struct MLoop *mloop;
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);
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index d1d91cb7508..5cdc5f19540 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -49,7 +49,6 @@ typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers;
*/
GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const struct Mesh *mesh,
const struct MLoopTri *looptri,
- const int *sculpt_face_sets,
const int *face_indices,
int face_indices_len);
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 8e3058b884d..78f595cbff2 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -210,13 +210,9 @@ static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers, GPUPrimType prim)
/** \name Mesh PBVH
* \{ */
-static bool gpu_pbvh_is_looptri_visible(const MLoopTri *lt,
- const bool *hide_vert,
- const MLoop *mloop,
- const int *sculpt_face_sets)
+static bool gpu_pbvh_is_looptri_visible(const MLoopTri *lt, const bool *hide_poly)
{
- return (!paint_is_face_hidden(lt, hide_vert, mloop) && sculpt_face_sets &&
- sculpt_face_sets[lt->poly] > SCULPT_FACE_SET_NONE);
+ return !paint_is_face_hidden(lt, hide_poly);
}
void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id,
@@ -233,8 +229,8 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id,
GPUAttrRef vcol_refs[MAX_GPU_ATTR];
GPUAttrRef cd_uvs[MAX_GPU_ATTR];
- const bool *hide_vert = (const bool *)CustomData_get_layer_named(
- &mesh->vdata, CD_PROP_BOOL, ".hide_vert");
+ const bool *hide_poly = (const bool *)CustomData_get_layer_named(
+ &mesh->pdata, CD_PROP_BOOL, ".hide_poly");
const int *material_indices = (const int *)CustomData_get_layer_named(
&mesh->pdata, CD_PROP_INT32, "material_index");
@@ -315,7 +311,7 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id,
for (uint i = 0; i < buffers->face_indices_len; i++) {
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
- if (!gpu_pbvh_is_looptri_visible(lt, hide_vert, buffers->mloop, sculpt_face_sets)) {
+ if (!gpu_pbvh_is_looptri_visible(lt, hide_poly)) {
continue;
}
@@ -355,7 +351,7 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id,
buffers->mloop[lt->tri[2]].v,
};
- if (!gpu_pbvh_is_looptri_visible(lt, hide_vert, buffers->mloop, sculpt_face_sets)) {
+ if (!gpu_pbvh_is_looptri_visible(lt, hide_poly)) {
continue;
}
@@ -395,7 +391,7 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id,
buffers->mloop[lt->tri[2]].v,
};
- if (!gpu_pbvh_is_looptri_visible(lt, hide_vert, buffers->mloop, sculpt_face_sets)) {
+ if (!gpu_pbvh_is_looptri_visible(lt, hide_poly)) {
continue;
}
@@ -459,7 +455,6 @@ void GPU_pbvh_mesh_buffers_update(PBVHGPUFormat *vbo_id,
GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const Mesh *mesh,
const MLoopTri *looptri,
- const int *sculpt_face_sets,
const int *face_indices,
const int face_indices_len)
{
@@ -472,8 +467,8 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const Mesh *mesh,
buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
- const bool *hide_vert = (bool *)CustomData_get_layer_named(
- &mesh->vdata, CD_PROP_BOOL, ".hide_vert");
+ const bool *hide_poly = (bool *)CustomData_get_layer_named(
+ &mesh->pdata, CD_PROP_BOOL, ".hide_poly");
/* smooth or flat for all */
buffers->smooth = polys[looptri[face_indices[0]].poly].flag & ME_SMOOTH;
@@ -483,7 +478,7 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const Mesh *mesh,
/* Count the number of visible triangles */
for (i = 0, tottri = 0; i < face_indices_len; i++) {
const MLoopTri *lt = &looptri[face_indices[i]];
- if (gpu_pbvh_is_looptri_visible(lt, hide_vert, loops, sculpt_face_sets)) {
+ if (gpu_pbvh_is_looptri_visible(lt, hide_poly)) {
int r_edges[3];
BKE_mesh_looptri_get_real_edges(mesh, lt, r_edges);
for (int j = 0; j < 3; j++) {
@@ -516,7 +511,7 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const Mesh *mesh,
const MLoopTri *lt = &looptri[face_indices[i]];
/* Skip hidden faces */
- if (!gpu_pbvh_is_looptri_visible(lt, hide_vert, loops, sculpt_face_sets)) {
+ if (!gpu_pbvh_is_looptri_visible(lt, hide_poly)) {
continue;
}
diff --git a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc
index e15054bd045..db14d7fbeb9 100644
--- a/source/blender/gpu/intern/gpu_shader_builder_stubs.cc
+++ b/source/blender/gpu/intern/gpu_shader_builder_stubs.cc
@@ -136,9 +136,7 @@ eAttrDomain BKE_id_attribute_domain(const struct ID *UNUSED(id),
/* -------------------------------------------------------------------- */
/** \name Stubs of BKE_paint.h
* \{ */
-bool paint_is_face_hidden(const struct MLoopTri *UNUSED(lt),
- const bool *UNUSED(hide_vert),
- const struct MLoop *UNUSED(mloop))
+bool paint_is_face_hidden(const struct MLoopTri *UNUSED(lt), const bool *UNUSED(hide_poly))
{
BLI_assert_unreachable();
return false;
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 6cbc24db2d8..cfc3a832166 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -500,7 +500,7 @@ void rna_Object_data_update(Main *bmain, Scene *scene, PointerRNA *ptr)
Object *object = (Object *)ptr->data;
if (object->mode == OB_MODE_SCULPT) {
- BKE_sculpt_ensure_orig_mesh_data(scene, object);
+ BKE_sculpt_ensure_orig_mesh_data(object);
}
rna_Object_internal_update_data_dependency(bmain, scene, ptr);