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/blenkernel/intern/paint.cc')
-rw-r--r--source/blender/blenkernel/intern/paint.cc262
1 files changed, 123 insertions, 139 deletions
diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc
index d277bbcca63..1a1bf285847 100644
--- a/source/blender/blenkernel/intern/paint.cc
+++ b/source/blender/blenkernel/intern/paint.cc
@@ -1088,10 +1088,10 @@ bool BKE_paint_ensure(ToolSettings *ts, Paint **r_paint)
Sculpt *data = MEM_cnew<Sculpt>(__func__);
paint = &data->paint;
- /* Turn on X plane mirror symmetry by default */
+ /* Turn on X plane mirror symmetry by default. */
paint->symmetry_flags |= PAINT_SYMM_X;
- /* Make sure at least dyntopo subdivision is enabled */
+ /* Make sure at least dyntopo subdivision is enabled. */
data->flags |= SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE;
}
else if ((GpPaint **)r_paint == &ts->gp_paint) {
@@ -1146,7 +1146,7 @@ void BKE_paint_init(Main *bmain, Scene *sce, ePaintMode mode, const uchar col[3]
brush = BKE_brush_first_search(bmain, ob_mode);
if (!brush) {
brush = BKE_brush_add(bmain, "Brush", ob_mode);
- id_us_min(&brush->id); /* fake user only */
+ id_us_min(&brush->id); /* Fake user only. */
}
BKE_paint_brush_set(paint, brush);
}
@@ -1247,18 +1247,17 @@ 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)
{
- /* skip face if any of its corners are hidden */
+ /* Skip face if any of its corners are hidden. */
return (BLI_BITMAP_TEST(grid_hidden, y * gridsize + x) ||
BLI_BITMAP_TEST(grid_hidden, y * gridsize + x + 1) ||
BLI_BITMAP_TEST(grid_hidden, (y + 1) * gridsize + x + 1) ||
@@ -1288,7 +1287,7 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, uint level, uint x, uint y
return gpm->data[(y * factor) * gridsize + (x * factor)];
}
-/* threshold to move before updating the brush rotation */
+/* Threshold to move before updating the brush rotation. */
#define RAKE_THRESHHOLD 20
void paint_update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, float rotation)
@@ -1331,8 +1330,8 @@ bool paint_calculate_rake_rotation(UnifiedPaintSettings *ups,
paint_update_brush_rake_rotation(ups, brush, rotation);
ok = true;
}
- /* make sure we reset here to the last rotation to avoid accumulating
- * values in case a random rotation is also added */
+ /* Make sure we reset here to the last rotation to avoid accumulating
+ * values in case a random rotation is also added. */
else {
paint_update_brush_rake_rotation(ups, brush, ups->last_rake_angle);
ok = false;
@@ -1528,20 +1527,29 @@ void BKE_sculptsession_free(Object *ob)
}
}
-MultiresModifierData *BKE_sculpt_multires_active(const Scene *scene, Object *ob)
+static MultiresModifierData *sculpt_multires_modifier_get(const Scene *scene,
+ Object *ob,
+ const bool auto_create_mdisps)
{
Mesh *me = (Mesh *)ob->data;
ModifierData *md;
VirtualModifierData virtualModifierData;
if (ob->sculpt && ob->sculpt->bm) {
- /* can't combine multires and dynamic topology */
+ /* Can't combine multires and dynamic topology. */
return nullptr;
}
+ bool need_mdisps = false;
+
if (!CustomData_get_layer(&me->ldata, CD_MDISPS)) {
- /* multires can't work without displacement layer */
- return nullptr;
+ if (!auto_create_mdisps) {
+ /* Multires can't work without displacement layer. */
+ return nullptr;
+ }
+ else {
+ need_mdisps = true;
+ }
}
/* Weight paint operates on original vertices, and needs to treat multires as regular modifier
@@ -1559,6 +1567,10 @@ MultiresModifierData *BKE_sculpt_multires_active(const Scene *scene, Object *ob)
}
if (mmd->sculptlvl > 0 && !(mmd->flags & eMultiresModifierFlag_UseSculptBaseMesh)) {
+ if (need_mdisps) {
+ CustomData_add_layer(&me->ldata, CD_MDISPS, CD_SET_DEFAULT, nullptr, me->totloop);
+ }
+
return mmd;
}
@@ -1569,6 +1581,11 @@ MultiresModifierData *BKE_sculpt_multires_active(const Scene *scene, Object *ob)
return nullptr;
}
+MultiresModifierData *BKE_sculpt_multires_active(const Scene *scene, Object *ob)
+{
+ return sculpt_multires_modifier_get(scene, ob, false);
+}
+
/* Checks if there are any supported deformation modifiers active */
static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
{
@@ -1580,14 +1597,14 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
return false;
}
- /* non-locked shape keys could be handled in the same way as deformed mesh */
+ /* Non-locked shape keys could be handled in the same way as deformed mesh. */
if ((ob->shapeflag & OB_SHAPE_LOCK) == 0 && me->key && ob->shapenr) {
return true;
}
md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData);
- /* exception for shape keys because we can edit those */
+ /* Exception for shape keys because we can edit those. */
for (; md; md = md->next) {
const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast<ModifierType>(md->type));
if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) {
@@ -1614,22 +1631,15 @@ 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;
SculptSession *ss = ob->sculpt;
Mesh *me = BKE_object_get_original_mesh(ob);
Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
- MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
+ MultiresModifierData *mmd = sculpt_multires_modifier_get(scene, ob, true);
const bool use_face_sets = (ob->mode & OB_MODE_SCULPT) != 0;
BLI_assert(me_eval != nullptr);
@@ -1644,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,
@@ -1708,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 {
@@ -1841,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;
@@ -1888,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)
@@ -1906,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)
@@ -1944,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 = -2;
+
+ 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)
@@ -2014,7 +2027,7 @@ int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
ret |= SCULPT_MASK_LAYER_CALC_LOOP;
}
- /* create vertex paint mask layer if there isn't one already */
+ /* Create vertex paint mask layer if there isn't one already. */
if (!paint_mask) {
CustomData_add_layer(&me->vdata, CD_PAINT_MASK, CD_SET_DEFAULT, nullptr, me->totvert);
ret |= SCULPT_MASK_LAYER_CALC_VERT;
@@ -2038,7 +2051,7 @@ void BKE_sculpt_toolsettings_data_ensure(Scene *scene)
sd->constant_detail = 3.0f;
}
- /* Set sane default tiling offsets */
+ /* Set sane default tiling offsets. */
if (!sd->paint.tile_offset[0]) {
sd->paint.tile_offset[0] = 1.0f;
}
@@ -2056,8 +2069,7 @@ static bool check_sculpt_object_deformed(Object *object, const bool for_construc
/* Active modifiers means extra deformation, which can't be handled correct
* on birth of PBVH and sculpt "layer" levels, so use PBVH only for internal brush
- * stuff and show final evaluated mesh so user would see actual object shape.
- */
+ * stuff and show final evaluated mesh so user would see actual object shape. */
deformed |= object->sculpt->deform_modifiers_active;
if (for_construction) {
@@ -2066,75 +2078,55 @@ static bool check_sculpt_object_deformed(Object *object, const bool for_construc
else {
/* As in case with modifiers, we can't synchronize deformation made against
* PBVH and non-locked keyblock, so also use PBVH only for brushes and
- * final DM to give final result to user.
- */
+ * final DM to give final result to user. */
deformed |= object->sculpt->shapekey_active && (object->shapeflag & OB_SHAPE_LOCK) == 0;
}
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) {
@@ -2144,7 +2136,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);
}
@@ -2182,41 +2178,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: