Cleanup: Access sculpt attributes with C++ attribute API

Access masks and face sets through the `BKE_attribute.hh` API. This
us more flexibility long term, and makes code a bit simpler in the
meantime.
This commit is contained in:
Hans Goudey 2023-11-20 13:14:16 -05:00
parent 9781600d68
commit 301731692e
11 changed files with 127 additions and 134 deletions

View File

@ -2003,23 +2003,22 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
Object *ob, Object *ob,
MultiresModifierData *mmd) MultiresModifierData *mmd)
{ {
using namespace blender;
using namespace blender::bke;
Mesh *me = static_cast<Mesh *>(ob->data); Mesh *me = static_cast<Mesh *>(ob->data);
const blender::OffsetIndices faces = me->faces(); const OffsetIndices faces = me->faces();
const Span<int> corner_verts = me->corner_verts(); const Span<int> corner_verts = me->corner_verts();
MutableAttributeAccessor attributes = me->attributes_for_write();
int ret = 0; int ret = 0;
const float *paint_mask = static_cast<const float *>(
CustomData_get_layer_named(&me->vert_data, CD_PROP_FLOAT, ".sculpt_mask"));
/* if multires is active, create a grid paint mask layer if there /* if multires is active, create a grid paint mask layer if there
* isn't one already */ * isn't one already */
if (mmd && !CustomData_has_layer(&me->loop_data, CD_GRID_PAINT_MASK)) { if (mmd && !CustomData_has_layer(&me->loop_data, CD_GRID_PAINT_MASK)) {
GridPaintMask *gmask;
int level = max_ii(1, mmd->sculptlvl); int level = max_ii(1, mmd->sculptlvl);
int gridsize = BKE_ccg_gridsize(level); int gridsize = BKE_ccg_gridsize(level);
int gridarea = gridsize * gridsize; int gridarea = gridsize * gridsize;
gmask = static_cast<GridPaintMask *>( GridPaintMask *gmask = static_cast<GridPaintMask *>(
CustomData_add_layer(&me->loop_data, CD_GRID_PAINT_MASK, CD_SET_DEFAULT, me->totloop)); CustomData_add_layer(&me->loop_data, CD_GRID_PAINT_MASK, CD_SET_DEFAULT, me->totloop));
for (int i = 0; i < me->totloop; i++) { for (int i = 0; i < me->totloop; i++) {
@ -2031,14 +2030,15 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
} }
/* If vertices already have mask, copy into multires data. */ /* If vertices already have mask, copy into multires data. */
if (paint_mask) { if (const VArray<float> mask = *attributes.lookup<float>(".sculpt_mask", ATTR_DOMAIN_POINT)) {
const VArraySpan<float> mask_span(mask);
for (const int i : faces.index_range()) { for (const int i : faces.index_range()) {
const blender::IndexRange face = faces[i]; const IndexRange face = faces[i];
/* Mask center. */ /* Mask center. */
float avg = 0.0f; float avg = 0.0f;
for (const int vert : corner_verts.slice(face)) { for (const int vert : corner_verts.slice(face)) {
avg += paint_mask[vert]; avg += mask_span[vert];
} }
avg /= float(face.size()); avg /= float(face.size());
@ -2046,13 +2046,13 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
for (const int corner : face) { for (const int corner : face) {
GridPaintMask *gpm = &gmask[corner]; GridPaintMask *gpm = &gmask[corner];
const int vert = corner_verts[corner]; const int vert = corner_verts[corner];
const int prev = corner_verts[blender::bke::mesh::face_corner_prev(face, vert)]; const int prev = corner_verts[mesh::face_corner_prev(face, vert)];
const int next = corner_verts[blender::bke::mesh::face_corner_next(face, vert)]; const int next = corner_verts[mesh::face_corner_next(face, vert)];
gpm->data[0] = avg; gpm->data[0] = avg;
gpm->data[1] = (paint_mask[vert] + paint_mask[next]) * 0.5f; gpm->data[1] = (mask_span[vert] + mask_span[next]) * 0.5f;
gpm->data[2] = (paint_mask[vert] + paint_mask[prev]) * 0.5f; gpm->data[2] = (mask_span[vert] + mask_span[prev]) * 0.5f;
gpm->data[3] = paint_mask[vert]; gpm->data[3] = mask_span[vert];
} }
} }
} }
@ -2066,9 +2066,7 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
} }
/* 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) { if (attributes.add<float>(".sculpt_mask", ATTR_DOMAIN_POINT, AttributeInitDefaultValue())) {
CustomData_add_layer_named(
&me->vert_data, CD_PROP_FLOAT, CD_SET_DEFAULT, me->totvert, ".sculpt_mask");
/* The evaluated mesh must be updated to contain the new data. */ /* The evaluated mesh must be updated to contain the new data. */
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
ret |= SCULPT_MASK_LAYER_CALC_VERT; ret |= SCULPT_MASK_LAYER_CALC_VERT;

View File

@ -679,8 +679,6 @@ static void pbvh_draw_args_init(const Mesh &mesh, PBVH *pbvh, PBVH_GPU_Args *arg
args->hide_poly = pbvh->face_data ? static_cast<const bool *>(CustomData_get_layer_named( args->hide_poly = pbvh->face_data ? static_cast<const bool *>(CustomData_get_layer_named(
pbvh->face_data, CD_PROP_BOOL, ".hide_poly")) : pbvh->face_data, CD_PROP_BOOL, ".hide_poly")) :
nullptr; nullptr;
args->face_sets = static_cast<const int *>(
CustomData_get_layer_named(&pbvh->mesh->face_data, CD_PROP_INT32, ".sculpt_face_set"));
} }
args->active_color = mesh.active_color_attribute; args->active_color = mesh.active_color_attribute;
@ -3167,12 +3165,10 @@ bool pbvh_has_mask(const PBVH *pbvh)
case PBVH_GRIDS: case PBVH_GRIDS:
return (pbvh->gridkey.has_mask != 0); return (pbvh->gridkey.has_mask != 0);
case PBVH_FACES: case PBVH_FACES:
return (pbvh->vert_data && return pbvh->mesh->attributes().contains(".sculpt_mask");
CustomData_has_layer_named(pbvh->vert_data, CD_PROP_FLOAT, ".sculpt_mask"));
case PBVH_BMESH: case PBVH_BMESH:
return (pbvh->header.bm && return pbvh->header.bm &&
(CustomData_get_offset_named( (CustomData_has_layer_named(&pbvh->header.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask"));
&pbvh->header.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask") != -1));
} }
return false; return false;
@ -3183,8 +3179,7 @@ bool pbvh_has_face_sets(PBVH *pbvh)
switch (pbvh->header.type) { switch (pbvh->header.type) {
case PBVH_GRIDS: case PBVH_GRIDS:
case PBVH_FACES: case PBVH_FACES:
return pbvh->face_data && CustomData_get_layer_named( return pbvh->mesh->attributes().contains(".sculpt_face_set");
pbvh->face_data, CD_PROP_INT32, ".sculpt_face_set") != nullptr;
case PBVH_BMESH: case PBVH_BMESH:
return false; return false;
} }

View File

@ -52,7 +52,6 @@ struct PBVH_GPU_Args {
const char *render_color; const char *render_color;
int face_sets_color_seed, face_sets_color_default; int face_sets_color_seed, face_sets_color_default;
const int *face_sets; /* for PBVH_FACES and PBVH_GRIDS */
SubdivCCG *subdiv_ccg; SubdivCCG *subdiv_ccg;
const DMFlagMat *grid_flag_mats; const DMFlagMat *grid_flag_mats;

View File

@ -575,34 +575,32 @@ struct PBVHBatches {
} }
} }
else if (vbo.type == CD_PBVH_FSET_TYPE) { else if (vbo.type == CD_PBVH_FSET_TYPE) {
const int *face_sets = args.face_sets; const bke::AttributeAccessor attributes = args.me->attributes();
if (const VArray<int> face_sets = *attributes.lookup<int>(".sculpt_face_set",
if (!face_sets) { ATTR_DOMAIN_FACE)) {
uchar white[3] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; const VArraySpan<int> face_sets_span(face_sets);
foreach_grids(
[&](int /*x*/, int /*y*/, int /*grid_index*/, CCGElem * /*elems*/[4], int /*i*/) {
*static_cast<uchar3 *>(GPU_vertbuf_raw_step(&access)) = white;
});
}
else {
foreach_grids( foreach_grids(
[&](int /*x*/, int /*y*/, int grid_index, CCGElem * /*elems*/[4], int /*i*/) { [&](int /*x*/, int /*y*/, int grid_index, CCGElem * /*elems*/[4], int /*i*/) {
uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
if (face_sets) { const int face_index = BKE_subdiv_ccg_grid_to_face_index(args.subdiv_ccg,
const int face_index = BKE_subdiv_ccg_grid_to_face_index(args.subdiv_ccg, grid_index);
grid_index); const int fset = face_sets_span[face_index];
const int fset = face_sets[face_index];
/* Skip for the default color Face Set to render it white. */ /* Skip for the default color Face Set to render it white. */
if (fset != args.face_sets_color_default) { if (fset != args.face_sets_color_default) {
BKE_paint_face_set_overlay_color_get( BKE_paint_face_set_overlay_color_get(
fset, args.face_sets_color_seed, face_set_color); fset, args.face_sets_color_seed, face_set_color);
}
} }
*static_cast<uchar3 *>(GPU_vertbuf_raw_step(&access)) = face_set_color; *static_cast<uchar4 *>(GPU_vertbuf_raw_step(&access)) = face_set_color;
});
}
else {
const uchar white[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
foreach_grids(
[&](int /*x*/, int /*y*/, int /*grid_index*/, CCGElem * /*elems*/[4], int /*i*/) {
*static_cast<uchar4 *>(GPU_vertbuf_raw_step(&access)) = white;
}); });
} }
} }
@ -697,6 +695,8 @@ struct PBVHBatches {
GPUVertBuf &vert_buf = *vbo.vert_buf; GPUVertBuf &vert_buf = *vbo.vert_buf;
const bke::AttributeAccessor attributes = args.me->attributes();
if (vbo.type == CD_PBVH_CO_TYPE) { if (vbo.type == CD_PBVH_CO_TYPE) {
extract_data_vert_faces<float3>(args, args.vert_positions, vert_buf); extract_data_vert_faces<float3>(args, args.vert_positions, vert_buf);
} }
@ -704,35 +704,35 @@ struct PBVHBatches {
fill_vbo_normal_faces(args, vert_buf); fill_vbo_normal_faces(args, vert_buf);
} }
else if (vbo.type == CD_PBVH_MASK_TYPE) { else if (vbo.type == CD_PBVH_MASK_TYPE) {
if (const float *mask = static_cast<const float *>( float *data = static_cast<float *>(GPU_vertbuf_get_data(&vert_buf));
CustomData_get_layer_named(args.vert_data, CD_PROP_FLOAT, ".sculpt_mask"))) if (const VArray<float> mask = *attributes.lookup<float>(".sculpt_mask", ATTR_DOMAIN_POINT))
{ {
const VArraySpan<float> mask_span(mask);
const Span<int> corner_verts = args.corner_verts; const Span<int> corner_verts = args.corner_verts;
const Span<MLoopTri> looptris = args.mlooptri; const Span<MLoopTri> looptris = args.mlooptri;
const Span<int> looptri_faces = args.looptri_faces; const Span<int> looptri_faces = args.looptri_faces;
const bool *hide_poly = args.hide_poly; const bool *hide_poly = args.hide_poly;
float *data = static_cast<float *>(GPU_vertbuf_get_data(&vert_buf));
for (const int looptri_i : args.prim_indices) { for (const int looptri_i : args.prim_indices) {
if (hide_poly && hide_poly[looptri_faces[looptri_i]]) { if (hide_poly && hide_poly[looptri_faces[looptri_i]]) {
continue; continue;
} }
for (int i : IndexRange(3)) { for (int i : IndexRange(3)) {
const int vert = corner_verts[looptris[looptri_i].tri[i]]; const int vert = corner_verts[looptris[looptri_i].tri[i]];
*data = mask[vert]; *data = mask_span[vert];
data++; data++;
} }
} }
} }
else { else {
MutableSpan(static_cast<float *>(GPU_vertbuf_get_data(vbo.vert_buf)), totvert).fill(0); MutableSpan(data, totvert).fill(0);
} }
} }
else if (vbo.type == CD_PBVH_FSET_TYPE) { else if (vbo.type == CD_PBVH_FSET_TYPE) {
const int *face_sets = static_cast<const int *>(
CustomData_get_layer_named(args.face_data, CD_PROP_INT32, ".sculpt_face_set"));
uchar4 *data = static_cast<uchar4 *>(GPU_vertbuf_get_data(vbo.vert_buf)); uchar4 *data = static_cast<uchar4 *>(GPU_vertbuf_get_data(vbo.vert_buf));
if (face_sets) { if (const VArray<int> face_sets = *attributes.lookup<int>(".sculpt_face_set",
ATTR_DOMAIN_FACE)) {
const VArraySpan<int> face_sets_span(face_sets);
int last_face = -1; int last_face = -1;
uchar4 fset_color(UCHAR_MAX); uchar4 fset_color(UCHAR_MAX);
@ -744,7 +744,7 @@ struct PBVHBatches {
if (last_face != face_i) { if (last_face != face_i) {
last_face = face_i; last_face = face_i;
const int fset = face_sets[face_i]; const int fset = face_sets_span[face_i];
if (fset != args.face_sets_color_default) { if (fset != args.face_sets_color_default) {
BKE_paint_face_set_overlay_color_get(fset, args.face_sets_color_seed, fset_color); BKE_paint_face_set_overlay_color_get(fset, args.face_sets_color_seed, fset_color);

View File

@ -10,6 +10,7 @@
#include "BLI_string.h" #include "BLI_string.h"
#include "BKE_attribute.hh"
#include "BKE_mesh.hh" #include "BKE_mesh.hh"
#include "BKE_paint.hh" #include "BKE_paint.hh"
@ -40,14 +41,6 @@ static void extract_sculpt_data_init(const MeshRenderData &mr,
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
GPUVertFormat *format = get_sculpt_data_format(); GPUVertFormat *format = get_sculpt_data_format();
CustomData *cd_vdata = (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->vdata : &mr.me->vert_data;
CustomData *cd_pdata = (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->pdata : &mr.me->face_data;
const float *cd_mask = (const float *)CustomData_get_layer_named(
cd_vdata, CD_PROP_FLOAT, ".sculpt_mask");
const int *cd_face_set = (const int *)CustomData_get_layer_named(
cd_pdata, CD_PROP_INT32, ".sculpt_face_set");
GPU_vertbuf_init_with_format(vbo, format); GPU_vertbuf_init_with_format(vbo, format);
GPU_vertbuf_data_alloc(vbo, mr.loop_len); GPU_vertbuf_data_alloc(vbo, mr.loop_len);
@ -59,8 +52,9 @@ static void extract_sculpt_data_init(const MeshRenderData &mr,
gpuSculptData *vbo_data = (gpuSculptData *)GPU_vertbuf_get_data(vbo); gpuSculptData *vbo_data = (gpuSculptData *)GPU_vertbuf_get_data(vbo);
if (mr.extract_type == MR_EXTRACT_BMESH) { if (mr.extract_type == MR_EXTRACT_BMESH) {
int cd_mask_ofs = CustomData_get_offset_named(cd_vdata, CD_PROP_FLOAT, ".sculpt_mask"); int cd_mask_ofs = CustomData_get_offset_named(&mr.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
int cd_face_set_ofs = CustomData_get_offset_named(cd_pdata, CD_PROP_INT32, ".sculpt_face_set"); int cd_face_set_ofs = CustomData_get_offset_named(
&mr.bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
BMIter f_iter; BMIter f_iter;
BMFace *efa; BMFace *efa;
BM_ITER_MESH (efa, &f_iter, mr.bm, BM_FACES_OF_MESH) { BM_ITER_MESH (efa, &f_iter, mr.bm, BM_FACES_OF_MESH) {
@ -68,12 +62,12 @@ static void extract_sculpt_data_init(const MeshRenderData &mr,
l_iter = l_first = BM_FACE_FIRST_LOOP(efa); l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
do { do {
float v_mask = 0.0f; float v_mask = 0.0f;
if (cd_mask) { if (cd_mask_ofs != -1) {
v_mask = BM_ELEM_CD_GET_FLOAT(l_iter->v, cd_mask_ofs); v_mask = BM_ELEM_CD_GET_FLOAT(l_iter->v, cd_mask_ofs);
} }
vbo_data->mask = v_mask; vbo_data->mask = v_mask;
uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
if (cd_face_set) { if (cd_face_set_ofs != -1) {
const int face_set_id = BM_ELEM_CD_GET_INT(l_iter->f, cd_face_set_ofs); const int face_set_id = BM_ELEM_CD_GET_INT(l_iter->f, cd_face_set_ofs);
if (face_set_id != mr.me->face_sets_color_default) { if (face_set_id != mr.me->face_sets_color_default) {
BKE_paint_face_set_overlay_color_get( BKE_paint_face_set_overlay_color_get(
@ -86,17 +80,21 @@ static void extract_sculpt_data_init(const MeshRenderData &mr,
} }
} }
else { else {
const bke::AttributeAccessor attributes = mr.me->attributes();
const VArray<float> mask = *attributes.lookup<float>(".sculpt_mask", ATTR_DOMAIN_POINT);
const VArray<int> face_set = *attributes.lookup<int>(".sculpt_face_set", ATTR_DOMAIN_FACE);
for (int face_index = 0; face_index < mr.face_len; face_index++) { for (int face_index = 0; face_index < mr.face_len; face_index++) {
for (const int corner : mr.faces[face_index]) { for (const int corner : mr.faces[face_index]) {
float v_mask = 0.0f; float v_mask = 0.0f;
if (cd_mask) { if (mask) {
v_mask = cd_mask[mr.corner_verts[corner]]; v_mask = mask[mr.corner_verts[corner]];
} }
vbo_data->mask = v_mask; vbo_data->mask = v_mask;
uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
if (cd_face_set) { if (face_set) {
const int face_set_id = cd_face_set[face_index]; const int face_set_id = face_set[face_index];
/* Skip for the default color Face Set to render it white. */ /* Skip for the default color Face Set to render it white. */
if (face_set_id != mr.me->face_sets_color_default) { if (face_set_id != mr.me->face_sets_color_default) {
BKE_paint_face_set_overlay_color_get( BKE_paint_face_set_overlay_color_get(
@ -119,19 +117,19 @@ static void extract_sculpt_data_init_subdiv(const DRWSubdivCache &subdiv_cache,
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer); GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
Mesh *coarse_mesh = mr.me; Mesh *coarse_mesh = mr.me;
CustomData *cd_vdata = &coarse_mesh->vert_data;
CustomData *cd_pdata = &coarse_mesh->face_data;
/* First, interpolate mask if available. */ /* First, interpolate mask if available. */
GPUVertBuf *mask_vbo = nullptr; GPUVertBuf *mask_vbo = nullptr;
GPUVertBuf *subdiv_mask_vbo = nullptr; GPUVertBuf *subdiv_mask_vbo = nullptr;
const float *cd_mask = (const float *)CustomData_get_layer_named(
cd_vdata, CD_PROP_FLOAT, ".sculpt_mask"); const bke::AttributeAccessor attributes = coarse_mesh->attributes();
const VArray<float> mask = *attributes.lookup<float>(".sculpt_mask", ATTR_DOMAIN_POINT);
const OffsetIndices coarse_faces = coarse_mesh->faces(); const OffsetIndices coarse_faces = coarse_mesh->faces();
const Span<int> coarse_corner_verts = coarse_mesh->corner_verts(); const Span<int> coarse_corner_verts = coarse_mesh->corner_verts();
if (cd_mask) { if (mask) {
const VArraySpan<float> mask_span(mask);
GPUVertFormat mask_format = {0}; GPUVertFormat mask_format = {0};
GPU_vertformat_attr_add(&mask_format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); GPU_vertformat_attr_add(&mask_format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
@ -142,7 +140,7 @@ static void extract_sculpt_data_init_subdiv(const DRWSubdivCache &subdiv_cache,
for (int i = 0; i < coarse_mesh->faces_num; i++) { for (int i = 0; i < coarse_mesh->faces_num; i++) {
for (const int vert : coarse_corner_verts.slice(coarse_faces[i])) { for (const int vert : coarse_corner_verts.slice(coarse_faces[i])) {
*v_mask++ = cd_mask[vert]; *v_mask++ = mask_span[vert];
} }
} }
@ -165,8 +163,7 @@ static void extract_sculpt_data_init_subdiv(const DRWSubdivCache &subdiv_cache,
}; };
gpuFaceSet *face_sets = (gpuFaceSet *)GPU_vertbuf_get_data(face_set_vbo); gpuFaceSet *face_sets = (gpuFaceSet *)GPU_vertbuf_get_data(face_set_vbo);
const int *cd_face_set = (const int *)CustomData_get_layer_named( const VArray<float> cd_face_sets = *attributes.lookup<float>(".sculpt_mask", ATTR_DOMAIN_POINT);
cd_pdata, CD_PROP_INT32, ".sculpt_face_set");
GPUVertFormat *format = get_sculpt_data_format(); GPUVertFormat *format = get_sculpt_data_format();
GPU_vertbuf_init_build_on_device(vbo, format, subdiv_cache.num_subdiv_loops); GPU_vertbuf_init_build_on_device(vbo, format, subdiv_cache.num_subdiv_loops);
@ -176,8 +173,8 @@ static void extract_sculpt_data_init_subdiv(const DRWSubdivCache &subdiv_cache,
const int face_index = subdiv_loop_face_index[i]; const int face_index = subdiv_loop_face_index[i];
uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}; uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
if (cd_face_set) { if (cd_face_sets) {
const int face_set_id = cd_face_set[face_index]; const int face_set_id = cd_face_sets[face_index];
/* Skip for the default color Face Set to render it white. */ /* Skip for the default color Face Set to render it white. */
if (face_set_id != coarse_mesh->face_sets_color_default) { if (face_set_id != coarse_mesh->face_sets_color_default) {
BKE_paint_face_set_overlay_color_get( BKE_paint_face_set_overlay_color_get(

View File

@ -12,6 +12,7 @@
#include "BLT_translation.h" #include "BLT_translation.h"
#include "BKE_attribute.hh"
#include "BKE_context.hh" #include "BKE_context.hh"
#include "BKE_editmesh.hh" #include "BKE_editmesh.hh"
#include "BKE_layer.h" #include "BKE_layer.h"
@ -205,13 +206,14 @@ static int geometry_extract_apply(bContext *C,
C, OB_MESH, nullptr, ob->loc, ob->rot, false, local_view_bits); C, OB_MESH, nullptr, ob->loc, ob->rot, false, local_view_bits);
BKE_mesh_nomain_to_mesh(new_mesh, static_cast<Mesh *>(new_ob->data), new_ob); BKE_mesh_nomain_to_mesh(new_mesh, static_cast<Mesh *>(new_ob->data), new_ob);
Mesh *new_ob_mesh = static_cast<Mesh *>(new_ob->data);
/* Remove the Face Sets as they need to be recreated when entering Sculpt Mode in the new object. /* Remove the Face Sets as they need to be recreated when entering Sculpt Mode in the new object.
* TODO(pablodobarro): In the future we can try to preserve them from the original mesh. */ * TODO(pablodobarro): In the future we can try to preserve them from the original mesh. */
Mesh *new_ob_mesh = static_cast<Mesh *>(new_ob->data); new_ob_mesh->attributes_for_write().remove(".sculpt_face_set");
CustomData_free_layer_named(&new_ob_mesh->face_data, ".sculpt_face_set", new_ob_mesh->faces_num);
/* Remove the mask from the new object so it can be sculpted directly after extracting. */ /* Remove the mask from the new object so it can be sculpted directly after extracting. */
CustomData_free_layer_named(&new_ob_mesh->vert_data, ".sculpt_mask", new_ob_mesh->totvert); new_ob_mesh->attributes_for_write().remove(".sculpt_mask");
BKE_mesh_copy_parameters_for_eval(new_ob_mesh, mesh); BKE_mesh_copy_parameters_for_eval(new_ob_mesh, mesh);
@ -509,7 +511,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
BM_mesh_free(bm); BM_mesh_free(bm);
/* Remove the mask from the new object so it can be sculpted directly after slicing. */ /* Remove the mask from the new object so it can be sculpted directly after slicing. */
CustomData_free_layer_named(&new_ob_mesh->vert_data, ".sculpt_mask", new_ob_mesh->totvert); new_ob_mesh->attributes_for_write().remove(".sculpt_mask");
Mesh *new_mesh = static_cast<Mesh *>(new_ob->data); Mesh *new_mesh = static_cast<Mesh *>(new_ob->data);
BKE_mesh_nomain_to_mesh(new_ob_mesh, new_mesh, new_ob); BKE_mesh_nomain_to_mesh(new_ob_mesh, new_mesh, new_ob);

View File

@ -294,24 +294,22 @@ static void join_mesh_single(Depsgraph *depsgraph,
* of them will have different IDs for their Face Sets. */ * of them will have different IDs for their Face Sets. */
static void mesh_join_offset_face_sets_ID(Mesh *mesh, int *face_set_offset) static void mesh_join_offset_face_sets_ID(Mesh *mesh, int *face_set_offset)
{ {
if (!mesh->faces_num) { using namespace blender;
return; bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
} bke::SpanAttributeWriter<int> face_sets = attributes.lookup_for_write_span<int>(
".sculpt_face_set");
int *face_sets = (int *)CustomData_get_layer_named_for_write(
&mesh->face_data, CD_PROP_INT32, ".sculpt_face_set", mesh->faces_num);
if (!face_sets) { if (!face_sets) {
return; return;
} }
int max_face_set = 0; int max_face_set = 0;
for (int f = 0; f < mesh->faces_num; f++) { for (const int i : face_sets.span.index_range()) {
/* As face sets encode the visibility in the integer sign, the offset needs to be added or /* As face sets encode the visibility in the integer sign, the offset needs to be added or
* subtracted depending on the initial sign of the integer to get the new ID. */ * subtracted depending on the initial sign of the integer to get the new ID. */
if (face_sets[f] <= *face_set_offset) { if (face_sets.span[i] <= *face_set_offset) {
face_sets[f] += *face_set_offset; face_sets.span[i] += *face_set_offset;
} }
max_face_set = max_ii(max_face_set, face_sets[f]); max_face_set = max_ii(max_face_set, face_sets.span[i]);
} }
*face_set_offset = max_face_set; *face_set_offset = max_face_set;
} }

View File

@ -21,6 +21,7 @@
#include "DNA_object_types.h" #include "DNA_object_types.h"
#include "DNA_scene_types.h" #include "DNA_scene_types.h"
#include "BKE_attribute.hh"
#include "BKE_ccg.h" #include "BKE_ccg.h"
#include "BKE_context.hh" #include "BKE_context.hh"
#include "BKE_mesh.hh" #include "BKE_mesh.hh"
@ -73,38 +74,36 @@ static void partialvis_update_mesh(Object *ob,
PartialVisArea area, PartialVisArea area,
float planes[4][4]) float planes[4][4])
{ {
Mesh *me = static_cast<Mesh *>(ob->data); using namespace blender;
Mesh *mesh = static_cast<Mesh *>(ob->data);
const blender::Span<blender::float3> positions = BKE_pbvh_get_vert_positions(pbvh); const blender::Span<blender::float3> positions = BKE_pbvh_get_vert_positions(pbvh);
const float *paint_mask;
bool any_changed = false, any_visible = false; bool any_changed = false, any_visible = false;
const blender::Span<int> verts = BKE_pbvh_node_get_vert_indices(node); const blender::Span<int> verts = BKE_pbvh_node_get_vert_indices(node);
paint_mask = static_cast<const float *>(
CustomData_get_layer_named(&me->vert_data, CD_PROP_FLOAT, ".sculpt_mask"));
bool *hide_vert = static_cast<bool *>(CustomData_get_layer_named_for_write( bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
&me->vert_data, CD_PROP_BOOL, ".hide_vert", me->totvert)); const VArray<float> mask = *attributes.lookup_or_default<float>(
if (hide_vert == nullptr) { ".sculpt_mask", ATTR_DOMAIN_POINT, 0.0f);
hide_vert = static_cast<bool *>(CustomData_add_layer_named(
&me->vert_data, CD_PROP_BOOL, CD_SET_DEFAULT, me->totvert, ".hide_vert")); bke::SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_span<bool>(
} ".hide_vert", ATTR_DOMAIN_POINT);
SCULPT_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN); SCULPT_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
for (const int vert : verts) { for (const int vert : verts) {
float vmask = paint_mask ? paint_mask[vert] : 0;
/* Hide vertex if in the hide volume. */ /* Hide vertex if in the hide volume. */
if (is_effected(area, planes, positions[vert], vmask)) { if (is_effected(area, planes, positions[vert], mask[vert])) {
hide_vert[vert] = (action == PARTIALVIS_HIDE); hide_vert.span[vert] = (action == PARTIALVIS_HIDE);
any_changed = true; any_changed = true;
} }
if (!hide_vert[vert]) { if (!hide_vert.span[vert]) {
any_visible = true; any_visible = true;
} }
} }
hide_vert.finish();
if (any_changed) { if (any_changed) {
BKE_pbvh_node_mark_rebuild_draw(node); BKE_pbvh_node_mark_rebuild_draw(node);
BKE_pbvh_node_fully_hidden_set(node, !any_visible); BKE_pbvh_node_fully_hidden_set(node, !any_visible);

View File

@ -21,6 +21,7 @@
#include "DNA_modifier_types.h" #include "DNA_modifier_types.h"
#include "DNA_object_types.h" #include "DNA_object_types.h"
#include "BKE_attribute.hh"
#include "BKE_brush.hh" #include "BKE_brush.hh"
#include "BKE_ccg.h" #include "BKE_ccg.h"
#include "BKE_colortools.h" #include "BKE_colortools.h"
@ -1196,17 +1197,19 @@ static void sculpt_expand_restore_color_data(SculptSession *ss, ExpandCache *exp
static void write_mask_data(SculptSession *ss, const Span<float> mask) static void write_mask_data(SculptSession *ss, const Span<float> mask)
{ {
using namespace blender;
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, {}); Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, {});
switch (BKE_pbvh_type(ss->pbvh)) { switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: { case PBVH_FACES: {
Mesh *mesh = BKE_pbvh_get_mesh(ss->pbvh); Mesh *mesh = BKE_pbvh_get_mesh(ss->pbvh);
float *layer = static_cast<float *>(CustomData_get_layer_named_for_write( bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
&mesh->vert_data, CD_PROP_FLOAT, ".sculpt_mask", mesh->totvert)); bke::SpanAttributeWriter<float> attribute = attributes.lookup_or_add_for_write_span<float>(
".sculpt_mask", ATTR_DOMAIN_POINT);
for (PBVHNode *node : nodes) { for (PBVHNode *node : nodes) {
PBVHVertexIter vd; PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
layer[vd.index] = mask[vd.index]; attribute.span[vd.index] = mask[vd.index];
} }
BKE_pbvh_vertex_iter_end; BKE_pbvh_vertex_iter_end;
BKE_pbvh_node_mark_redraw(node); BKE_pbvh_node_mark_redraw(node);

View File

@ -66,14 +66,16 @@ using blender::Vector;
int ED_sculpt_face_sets_find_next_available_id(Mesh *mesh) int ED_sculpt_face_sets_find_next_available_id(Mesh *mesh)
{ {
const int *face_sets = static_cast<const int *>( using namespace blender;
CustomData_get_layer_named(&mesh->face_data, CD_PROP_INT32, ".sculpt_face_set")); const VArray<int> attribute = *mesh->attributes().lookup<int>(".sculpt_face_set",
if (!face_sets) { ATTR_DOMAIN_FACE);
if (!attribute) {
return SCULPT_FACE_SET_NONE; return SCULPT_FACE_SET_NONE;
} }
const VArraySpan<int> face_sets(attribute);
int next_face_set_id = 0; int next_face_set_id = 0;
for (int i = 0; i < mesh->faces_num; i++) { for (const int i : face_sets.index_range()) {
next_face_set_id = max_ii(next_face_set_id, face_sets[i]); next_face_set_id = max_ii(next_face_set_id, face_sets[i]);
} }
next_face_set_id++; next_face_set_id++;
@ -83,15 +85,17 @@ int ED_sculpt_face_sets_find_next_available_id(Mesh *mesh)
void ED_sculpt_face_sets_initialize_none_to_id(Mesh *mesh, const int new_id) void ED_sculpt_face_sets_initialize_none_to_id(Mesh *mesh, const int new_id)
{ {
int *face_sets = static_cast<int *>(CustomData_get_layer_named_for_write( using namespace blender;
&mesh->face_data, CD_PROP_INT32, ".sculpt_face_set", mesh->faces_num)); bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
bke::SpanAttributeWriter<int> face_sets = attributes.lookup_for_write_span<int>(
".sculpt_face_set");
if (!face_sets) { if (!face_sets) {
return; return;
} }
for (int i = 0; i < mesh->faces_num; i++) { for (const int i : face_sets.span.index_range()) {
if (face_sets[i] == SCULPT_FACE_SET_NONE) { if (face_sets.span[i] == SCULPT_FACE_SET_NONE) {
face_sets[i] = new_id; face_sets.span[i] = new_id;
} }
} }
} }

View File

@ -567,22 +567,20 @@ static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode, bool *m
SubdivCCG *subdiv_ccg = ss->subdiv_ccg; SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
if (unode->maxvert) { if (unode->maxvert) {
/* Regular mesh restore. */ bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
float *vmask = static_cast<float *>(CustomData_get_layer_named_for_write( bke::SpanAttributeWriter<float> mask = attributes.lookup_or_add_for_write_span<float>(
&mesh->vert_data, CD_PROP_FLOAT, ".sculpt_mask", mesh->totvert)); ".sculpt_mask", ATTR_DOMAIN_POINT);
if (!vmask) {
vmask = static_cast<float *>(CustomData_add_layer_named(
&mesh->vert_data, CD_PROP_FLOAT, CD_SET_DEFAULT, mesh->totvert, ".sculpt_mask"));
}
const Span<int> index = unode->index; const Span<int> index = unode->index;
for (int i = 0; i < unode->totvert; i++) { for (int i = 0; i < unode->totvert; i++) {
if (vmask[index[i]] != unode->mask[i]) { if (mask.span[index[i]] != unode->mask[i]) {
SWAP(float, vmask[index[i]], unode->mask[i]); std::swap(mask.span[index[i]], unode->mask[i]);
modified_vertices[index[i]] = true; modified_vertices[index[i]] = true;
} }
} }
mask.finish();
} }
else if (unode->maxgrid && subdiv_ccg != nullptr) { else if (unode->maxgrid && subdiv_ccg != nullptr) {
/* Multires restore. */ /* Multires restore. */
@ -600,7 +598,7 @@ static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode, bool *m
grid = grids[unode->grids[j]]; grid = grids[unode->grids[j]];
for (int i = 0; i < gridsize * gridsize; i++) { for (int i = 0; i < gridsize * gridsize; i++) {
SWAP(float, *CCG_elem_offset_mask(&key, grid, i), mask[index]); std::swap(*CCG_elem_offset_mask(&key, grid, i), mask[index]);
index++; index++;
} }
} }