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:
parent
9781600d68
commit
301731692e
|
@ -2003,23 +2003,22 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
|
|||
Object *ob,
|
||||
MultiresModifierData *mmd)
|
||||
{
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
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();
|
||||
MutableAttributeAccessor attributes = me->attributes_for_write();
|
||||
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
|
||||
* isn't one already */
|
||||
if (mmd && !CustomData_has_layer(&me->loop_data, CD_GRID_PAINT_MASK)) {
|
||||
GridPaintMask *gmask;
|
||||
int level = max_ii(1, mmd->sculptlvl);
|
||||
int gridsize = BKE_ccg_gridsize(level);
|
||||
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));
|
||||
|
||||
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 (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()) {
|
||||
const blender::IndexRange face = faces[i];
|
||||
const IndexRange face = faces[i];
|
||||
|
||||
/* Mask center. */
|
||||
float avg = 0.0f;
|
||||
for (const int vert : corner_verts.slice(face)) {
|
||||
avg += paint_mask[vert];
|
||||
avg += mask_span[vert];
|
||||
}
|
||||
avg /= float(face.size());
|
||||
|
||||
|
@ -2046,13 +2046,13 @@ int BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph,
|
|||
for (const int corner : face) {
|
||||
GridPaintMask *gpm = &gmask[corner];
|
||||
const int vert = corner_verts[corner];
|
||||
const int prev = corner_verts[blender::bke::mesh::face_corner_prev(face, vert)];
|
||||
const int next = corner_verts[blender::bke::mesh::face_corner_next(face, vert)];
|
||||
const int prev = corner_verts[mesh::face_corner_prev(face, vert)];
|
||||
const int next = corner_verts[mesh::face_corner_next(face, vert)];
|
||||
|
||||
gpm->data[0] = avg;
|
||||
gpm->data[1] = (paint_mask[vert] + paint_mask[next]) * 0.5f;
|
||||
gpm->data[2] = (paint_mask[vert] + paint_mask[prev]) * 0.5f;
|
||||
gpm->data[3] = paint_mask[vert];
|
||||
gpm->data[1] = (mask_span[vert] + mask_span[next]) * 0.5f;
|
||||
gpm->data[2] = (mask_span[vert] + mask_span[prev]) * 0.5f;
|
||||
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. */
|
||||
if (!paint_mask) {
|
||||
CustomData_add_layer_named(
|
||||
&me->vert_data, CD_PROP_FLOAT, CD_SET_DEFAULT, me->totvert, ".sculpt_mask");
|
||||
if (attributes.add<float>(".sculpt_mask", ATTR_DOMAIN_POINT, AttributeInitDefaultValue())) {
|
||||
/* The evaluated mesh must be updated to contain the new data. */
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
ret |= SCULPT_MASK_LAYER_CALC_VERT;
|
||||
|
|
|
@ -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(
|
||||
pbvh->face_data, CD_PROP_BOOL, ".hide_poly")) :
|
||||
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;
|
||||
|
@ -3167,12 +3165,10 @@ bool pbvh_has_mask(const PBVH *pbvh)
|
|||
case PBVH_GRIDS:
|
||||
return (pbvh->gridkey.has_mask != 0);
|
||||
case PBVH_FACES:
|
||||
return (pbvh->vert_data &&
|
||||
CustomData_has_layer_named(pbvh->vert_data, CD_PROP_FLOAT, ".sculpt_mask"));
|
||||
return pbvh->mesh->attributes().contains(".sculpt_mask");
|
||||
case PBVH_BMESH:
|
||||
return (pbvh->header.bm &&
|
||||
(CustomData_get_offset_named(
|
||||
&pbvh->header.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask") != -1));
|
||||
return pbvh->header.bm &&
|
||||
(CustomData_has_layer_named(&pbvh->header.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask"));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -3183,8 +3179,7 @@ bool pbvh_has_face_sets(PBVH *pbvh)
|
|||
switch (pbvh->header.type) {
|
||||
case PBVH_GRIDS:
|
||||
case PBVH_FACES:
|
||||
return pbvh->face_data && CustomData_get_layer_named(
|
||||
pbvh->face_data, CD_PROP_INT32, ".sculpt_face_set") != nullptr;
|
||||
return pbvh->mesh->attributes().contains(".sculpt_face_set");
|
||||
case PBVH_BMESH:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@ struct PBVH_GPU_Args {
|
|||
const char *render_color;
|
||||
|
||||
int face_sets_color_seed, face_sets_color_default;
|
||||
const int *face_sets; /* for PBVH_FACES and PBVH_GRIDS */
|
||||
|
||||
SubdivCCG *subdiv_ccg;
|
||||
const DMFlagMat *grid_flag_mats;
|
||||
|
|
|
@ -575,34 +575,32 @@ struct PBVHBatches {
|
|||
}
|
||||
}
|
||||
else if (vbo.type == CD_PBVH_FSET_TYPE) {
|
||||
const int *face_sets = args.face_sets;
|
||||
|
||||
if (!face_sets) {
|
||||
uchar white[3] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
|
||||
|
||||
foreach_grids(
|
||||
[&](int /*x*/, int /*y*/, int /*grid_index*/, CCGElem * /*elems*/[4], int /*i*/) {
|
||||
*static_cast<uchar3 *>(GPU_vertbuf_raw_step(&access)) = white;
|
||||
});
|
||||
}
|
||||
else {
|
||||
const bke::AttributeAccessor attributes = args.me->attributes();
|
||||
if (const VArray<int> face_sets = *attributes.lookup<int>(".sculpt_face_set",
|
||||
ATTR_DOMAIN_FACE)) {
|
||||
const VArraySpan<int> face_sets_span(face_sets);
|
||||
foreach_grids(
|
||||
[&](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};
|
||||
|
||||
if (face_sets) {
|
||||
const int face_index = BKE_subdiv_ccg_grid_to_face_index(args.subdiv_ccg,
|
||||
grid_index);
|
||||
const int fset = face_sets[face_index];
|
||||
const int fset = face_sets_span[face_index];
|
||||
|
||||
/* Skip for the default color Face Set to render it white. */
|
||||
if (fset != args.face_sets_color_default) {
|
||||
BKE_paint_face_set_overlay_color_get(
|
||||
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;
|
||||
|
||||
const bke::AttributeAccessor attributes = args.me->attributes();
|
||||
|
||||
if (vbo.type == CD_PBVH_CO_TYPE) {
|
||||
extract_data_vert_faces<float3>(args, args.vert_positions, vert_buf);
|
||||
}
|
||||
|
@ -704,35 +704,35 @@ struct PBVHBatches {
|
|||
fill_vbo_normal_faces(args, vert_buf);
|
||||
}
|
||||
else if (vbo.type == CD_PBVH_MASK_TYPE) {
|
||||
if (const float *mask = static_cast<const float *>(
|
||||
CustomData_get_layer_named(args.vert_data, CD_PROP_FLOAT, ".sculpt_mask")))
|
||||
float *data = static_cast<float *>(GPU_vertbuf_get_data(&vert_buf));
|
||||
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<MLoopTri> looptris = args.mlooptri;
|
||||
const Span<int> looptri_faces = args.looptri_faces;
|
||||
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) {
|
||||
if (hide_poly && hide_poly[looptri_faces[looptri_i]]) {
|
||||
continue;
|
||||
}
|
||||
for (int i : IndexRange(3)) {
|
||||
const int vert = corner_verts[looptris[looptri_i].tri[i]];
|
||||
*data = mask[vert];
|
||||
*data = mask_span[vert];
|
||||
data++;
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
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));
|
||||
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;
|
||||
uchar4 fset_color(UCHAR_MAX);
|
||||
|
||||
|
@ -744,7 +744,7 @@ struct PBVHBatches {
|
|||
if (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) {
|
||||
BKE_paint_face_set_overlay_color_get(fset, args.face_sets_color_seed, fset_color);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_paint.hh"
|
||||
|
||||
|
@ -40,14 +41,6 @@ static void extract_sculpt_data_init(const MeshRenderData &mr,
|
|||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
|
||||
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_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);
|
||||
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
int cd_mask_ofs = CustomData_get_offset_named(cd_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_mask_ofs = CustomData_get_offset_named(&mr.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
|
||||
int cd_face_set_ofs = CustomData_get_offset_named(
|
||||
&mr.bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
|
||||
BMIter f_iter;
|
||||
BMFace *efa;
|
||||
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);
|
||||
do {
|
||||
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);
|
||||
}
|
||||
vbo_data->mask = v_mask;
|
||||
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);
|
||||
if (face_set_id != mr.me->face_sets_color_default) {
|
||||
BKE_paint_face_set_overlay_color_get(
|
||||
|
@ -86,17 +80,21 @@ static void extract_sculpt_data_init(const MeshRenderData &mr,
|
|||
}
|
||||
}
|
||||
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 (const int corner : mr.faces[face_index]) {
|
||||
float v_mask = 0.0f;
|
||||
if (cd_mask) {
|
||||
v_mask = cd_mask[mr.corner_verts[corner]];
|
||||
if (mask) {
|
||||
v_mask = mask[mr.corner_verts[corner]];
|
||||
}
|
||||
vbo_data->mask = v_mask;
|
||||
|
||||
uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
|
||||
if (cd_face_set) {
|
||||
const int face_set_id = cd_face_set[face_index];
|
||||
if (face_set) {
|
||||
const int face_set_id = face_set[face_index];
|
||||
/* Skip for the default color Face Set to render it white. */
|
||||
if (face_set_id != mr.me->face_sets_color_default) {
|
||||
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);
|
||||
|
||||
Mesh *coarse_mesh = mr.me;
|
||||
CustomData *cd_vdata = &coarse_mesh->vert_data;
|
||||
CustomData *cd_pdata = &coarse_mesh->face_data;
|
||||
|
||||
/* First, interpolate mask if available. */
|
||||
GPUVertBuf *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 Span<int> coarse_corner_verts = coarse_mesh->corner_verts();
|
||||
|
||||
if (cd_mask) {
|
||||
if (mask) {
|
||||
const VArraySpan<float> mask_span(mask);
|
||||
GPUVertFormat mask_format = {0};
|
||||
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 (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);
|
||||
const int *cd_face_set = (const int *)CustomData_get_layer_named(
|
||||
cd_pdata, CD_PROP_INT32, ".sculpt_face_set");
|
||||
const VArray<float> cd_face_sets = *attributes.lookup<float>(".sculpt_mask", ATTR_DOMAIN_POINT);
|
||||
|
||||
GPUVertFormat *format = get_sculpt_data_format();
|
||||
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];
|
||||
|
||||
uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
|
||||
if (cd_face_set) {
|
||||
const int face_set_id = cd_face_set[face_index];
|
||||
if (cd_face_sets) {
|
||||
const int face_set_id = cd_face_sets[face_index];
|
||||
/* Skip for the default color Face Set to render it white. */
|
||||
if (face_set_id != coarse_mesh->face_sets_color_default) {
|
||||
BKE_paint_face_set_overlay_color_get(
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_editmesh.hh"
|
||||
#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);
|
||||
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.
|
||||
* 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);
|
||||
CustomData_free_layer_named(&new_ob_mesh->face_data, ".sculpt_face_set", new_ob_mesh->faces_num);
|
||||
new_ob_mesh->attributes_for_write().remove(".sculpt_face_set");
|
||||
|
||||
/* 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);
|
||||
|
||||
|
@ -509,7 +511,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
|
|||
BM_mesh_free(bm);
|
||||
|
||||
/* 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);
|
||||
BKE_mesh_nomain_to_mesh(new_ob_mesh, new_mesh, new_ob);
|
||||
|
|
|
@ -294,24 +294,22 @@ static void join_mesh_single(Depsgraph *depsgraph,
|
|||
* of them will have different IDs for their Face Sets. */
|
||||
static void mesh_join_offset_face_sets_ID(Mesh *mesh, int *face_set_offset)
|
||||
{
|
||||
if (!mesh->faces_num) {
|
||||
return;
|
||||
}
|
||||
|
||||
int *face_sets = (int *)CustomData_get_layer_named_for_write(
|
||||
&mesh->face_data, CD_PROP_INT32, ".sculpt_face_set", mesh->faces_num);
|
||||
using namespace blender;
|
||||
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
|
||||
bke::SpanAttributeWriter<int> face_sets = attributes.lookup_for_write_span<int>(
|
||||
".sculpt_face_set");
|
||||
if (!face_sets) {
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
* subtracted depending on the initial sign of the integer to get the new ID. */
|
||||
if (face_sets[f] <= *face_set_offset) {
|
||||
face_sets[f] += *face_set_offset;
|
||||
if (face_sets.span[i] <= *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;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_ccg.h"
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_mesh.hh"
|
||||
|
@ -73,38 +74,36 @@ static void partialvis_update_mesh(Object *ob,
|
|||
PartialVisArea area,
|
||||
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 float *paint_mask;
|
||||
bool any_changed = false, any_visible = false;
|
||||
|
||||
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(
|
||||
&me->vert_data, CD_PROP_BOOL, ".hide_vert", me->totvert));
|
||||
if (hide_vert == nullptr) {
|
||||
hide_vert = static_cast<bool *>(CustomData_add_layer_named(
|
||||
&me->vert_data, CD_PROP_BOOL, CD_SET_DEFAULT, me->totvert, ".hide_vert"));
|
||||
}
|
||||
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
|
||||
const VArray<float> mask = *attributes.lookup_or_default<float>(
|
||||
".sculpt_mask", ATTR_DOMAIN_POINT, 0.0f);
|
||||
|
||||
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);
|
||||
|
||||
for (const int vert : verts) {
|
||||
float vmask = paint_mask ? paint_mask[vert] : 0;
|
||||
|
||||
/* Hide vertex if in the hide volume. */
|
||||
if (is_effected(area, planes, positions[vert], vmask)) {
|
||||
hide_vert[vert] = (action == PARTIALVIS_HIDE);
|
||||
if (is_effected(area, planes, positions[vert], mask[vert])) {
|
||||
hide_vert.span[vert] = (action == PARTIALVIS_HIDE);
|
||||
any_changed = true;
|
||||
}
|
||||
|
||||
if (!hide_vert[vert]) {
|
||||
if (!hide_vert.span[vert]) {
|
||||
any_visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
hide_vert.finish();
|
||||
|
||||
if (any_changed) {
|
||||
BKE_pbvh_node_mark_rebuild_draw(node);
|
||||
BKE_pbvh_node_fully_hidden_set(node, !any_visible);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_brush.hh"
|
||||
#include "BKE_ccg.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)
|
||||
{
|
||||
using namespace blender;
|
||||
Vector<PBVHNode *> nodes = blender::bke::pbvh::search_gather(ss->pbvh, {});
|
||||
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_FACES: {
|
||||
Mesh *mesh = BKE_pbvh_get_mesh(ss->pbvh);
|
||||
float *layer = static_cast<float *>(CustomData_get_layer_named_for_write(
|
||||
&mesh->vert_data, CD_PROP_FLOAT, ".sculpt_mask", mesh->totvert));
|
||||
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
|
||||
bke::SpanAttributeWriter<float> attribute = attributes.lookup_or_add_for_write_span<float>(
|
||||
".sculpt_mask", ATTR_DOMAIN_POINT);
|
||||
for (PBVHNode *node : nodes) {
|
||||
PBVHVertexIter vd;
|
||||
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_node_mark_redraw(node);
|
||||
|
|
|
@ -66,14 +66,16 @@ using blender::Vector;
|
|||
|
||||
int ED_sculpt_face_sets_find_next_available_id(Mesh *mesh)
|
||||
{
|
||||
const int *face_sets = static_cast<const int *>(
|
||||
CustomData_get_layer_named(&mesh->face_data, CD_PROP_INT32, ".sculpt_face_set"));
|
||||
if (!face_sets) {
|
||||
using namespace blender;
|
||||
const VArray<int> attribute = *mesh->attributes().lookup<int>(".sculpt_face_set",
|
||||
ATTR_DOMAIN_FACE);
|
||||
if (!attribute) {
|
||||
return SCULPT_FACE_SET_NONE;
|
||||
}
|
||||
const VArraySpan<int> face_sets(attribute);
|
||||
|
||||
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++;
|
||||
|
@ -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)
|
||||
{
|
||||
int *face_sets = static_cast<int *>(CustomData_get_layer_named_for_write(
|
||||
&mesh->face_data, CD_PROP_INT32, ".sculpt_face_set", mesh->faces_num));
|
||||
using namespace blender;
|
||||
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
|
||||
bke::SpanAttributeWriter<int> face_sets = attributes.lookup_for_write_span<int>(
|
||||
".sculpt_face_set");
|
||||
if (!face_sets) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mesh->faces_num; i++) {
|
||||
if (face_sets[i] == SCULPT_FACE_SET_NONE) {
|
||||
face_sets[i] = new_id;
|
||||
for (const int i : face_sets.span.index_range()) {
|
||||
if (face_sets.span[i] == SCULPT_FACE_SET_NONE) {
|
||||
face_sets.span[i] = new_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -567,22 +567,20 @@ static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode, bool *m
|
|||
SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
|
||||
|
||||
if (unode->maxvert) {
|
||||
/* Regular mesh restore. */
|
||||
float *vmask = static_cast<float *>(CustomData_get_layer_named_for_write(
|
||||
&mesh->vert_data, CD_PROP_FLOAT, ".sculpt_mask", mesh->totvert));
|
||||
if (!vmask) {
|
||||
vmask = static_cast<float *>(CustomData_add_layer_named(
|
||||
&mesh->vert_data, CD_PROP_FLOAT, CD_SET_DEFAULT, mesh->totvert, ".sculpt_mask"));
|
||||
}
|
||||
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
|
||||
bke::SpanAttributeWriter<float> mask = attributes.lookup_or_add_for_write_span<float>(
|
||||
".sculpt_mask", ATTR_DOMAIN_POINT);
|
||||
|
||||
const Span<int> index = unode->index;
|
||||
|
||||
for (int i = 0; i < unode->totvert; i++) {
|
||||
if (vmask[index[i]] != unode->mask[i]) {
|
||||
SWAP(float, vmask[index[i]], unode->mask[i]);
|
||||
if (mask.span[index[i]] != unode->mask[i]) {
|
||||
std::swap(mask.span[index[i]], unode->mask[i]);
|
||||
modified_vertices[index[i]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
mask.finish();
|
||||
}
|
||||
else if (unode->maxgrid && subdiv_ccg != nullptr) {
|
||||
/* Multires restore. */
|
||||
|
@ -600,7 +598,7 @@ static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode, bool *m
|
|||
grid = grids[unode->grids[j]];
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue