Cleanup: Use C++ arrays for SculptUndoNode

Significantly reduce the amount of manual memory management by
replacing owning pointers with `blender::Array`. This also simplifies
counting the size of the undo steps and iterating over the array values
in some cases.
This commit is contained in:
Hans Goudey 2023-10-13 09:44:35 +02:00
parent 91c5eca81f
commit 3e81f66998
5 changed files with 107 additions and 169 deletions

View File

@ -695,22 +695,19 @@ bool BKE_pbvh_get_color_layer(Mesh *me, CustomDataLayer **r_layer, eAttrDomain *
/* Swaps colors at each element in indices (of domain pbvh->vcol_domain)
* with values in colors. */
void BKE_pbvh_swap_colors(PBVH *pbvh,
const int *indices,
const int indices_num,
float (*colors)[4]);
blender::Span<int> indices,
blender::MutableSpan<blender::float4> r_colors);
/* Stores colors from the elements in indices (of domain pbvh->vcol_domain)
* into colors. */
void BKE_pbvh_store_colors(PBVH *pbvh,
const int *indices,
const int indices_num,
float (*colors)[4]);
blender::Span<int> indices,
blender::MutableSpan<blender::float4> r_colors);
/* Like BKE_pbvh_store_colors but handles loop->vert conversion */
void BKE_pbvh_store_colors_vertex(PBVH *pbvh,
const int *indices,
const int indices_num,
float (*colors)[4]);
blender::Span<int> indices,
blender::MutableSpan<blender::float4> r_colors);
bool BKE_pbvh_is_drawing(const PBVH *pbvh);

View File

@ -161,14 +161,13 @@ void BKE_pbvh_vertex_color_set(PBVH *pbvh, PBVHVertRef vertex, const float color
}
void BKE_pbvh_swap_colors(PBVH *pbvh,
const int *indices,
const int indices_num,
float (*r_colors)[4])
const blender::Span<int> indices,
blender::MutableSpan<blender::float4> r_colors)
{
blender::bke::to_static_color_type(eCustomDataType(pbvh->color_layer->type), [&](auto dummy) {
using T = decltype(dummy);
T *pbvh_colors = static_cast<T *>(pbvh->color_layer->data);
for (const int i : IndexRange(indices_num)) {
for (const int i : indices.index_range()) {
T temp = pbvh_colors[indices[i]];
blender::bke::from_float(r_colors[i], pbvh_colors[indices[i]]);
blender::bke::to_float(temp, r_colors[i]);
@ -177,31 +176,29 @@ void BKE_pbvh_swap_colors(PBVH *pbvh,
}
void BKE_pbvh_store_colors(PBVH *pbvh,
const int *indices,
const int indices_num,
float (*r_colors)[4])
const blender::Span<int> indices,
blender::MutableSpan<blender::float4> r_colors)
{
blender::bke::to_static_color_type(eCustomDataType(pbvh->color_layer->type), [&](auto dummy) {
using T = decltype(dummy);
T *pbvh_colors = static_cast<T *>(pbvh->color_layer->data);
for (const int i : IndexRange(indices_num)) {
for (const int i : indices.index_range()) {
blender::bke::to_float(pbvh_colors[indices[i]], r_colors[i]);
}
});
}
void BKE_pbvh_store_colors_vertex(PBVH *pbvh,
const int *indices,
const int indices_num,
float (*r_colors)[4])
const blender::Span<int> indices,
blender::MutableSpan<blender::float4> r_colors)
{
if (pbvh->color_domain == ATTR_DOMAIN_POINT) {
BKE_pbvh_store_colors(pbvh, indices, indices_num, r_colors);
BKE_pbvh_store_colors(pbvh, indices, r_colors);
}
else {
blender::bke::to_static_color_type(eCustomDataType(pbvh->color_layer->type), [&](auto dummy) {
using T = decltype(dummy);
for (const int i : IndexRange(indices_num)) {
for (const int i : indices.index_range()) {
blender::bke::pbvh_vertex_color_get<T>(*pbvh, BKE_pbvh_make_vref(indices[i]), r_colors[i]);
}
});

View File

@ -1375,10 +1375,10 @@ void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, Scul
data->bm_log = ss->bm_log;
}
else {
data->coords = data->unode->co;
data->normals = data->unode->no;
data->vmasks = data->unode->mask;
data->colors = data->unode->col;
data->coords = reinterpret_cast<float(*)[3]>(data->unode->co.data());
data->normals = reinterpret_cast<float(*)[3]>(data->unode->no.data());
data->vmasks = data->unode->mask.data();
data->colors = reinterpret_cast<float(*)[4]>(data->unode->col.data());
}
}
@ -1428,7 +1428,7 @@ void SCULPT_orig_face_data_unode_init(SculptOrigFaceData *data, Object *ob, Scul
data->bm_log = ss->bm_log;
}
else {
data->face_sets = unode->face_sets;
data->face_sets = unode->face_sets.data();
}
}
@ -2043,7 +2043,7 @@ static void calc_area_normal_and_center_task(Object *ob,
if (ss->cache && !ss->cache->accum) {
unode = SCULPT_undo_push_node(ob, node, SCULPT_UNDO_COORDS);
use_original = (unode->co || unode->bm_entry);
use_original = (!unode->co.is_empty() || unode->bm_entry);
}
SculptBrushTest normal_test;
@ -3819,7 +3819,8 @@ static void sculpt_combine_proxies_node(Object &object,
float(*orco)[3] = nullptr;
if (use_orco && !ss->bm) {
orco = SCULPT_undo_push_node(&object, &node, SCULPT_UNDO_COORDS)->co;
orco = reinterpret_cast<float(*)[3]>(
(SCULPT_undo_push_node(&object, &node, SCULPT_UNDO_COORDS)->co.data()));
}
int proxy_count;
@ -4977,7 +4978,7 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
else {
/* Intersect with coordinates from before we started stroke. */
SculptUndoNode *unode = SCULPT_undo_get_node(node, SCULPT_UNDO_COORDS);
origco = (unode) ? unode->co : nullptr;
origco = (unode) ? reinterpret_cast<float(*)[3]>(unode->co.data()) : nullptr;
use_origco = origco ? true : false;
}
}
@ -5015,7 +5016,7 @@ static void sculpt_find_nearest_to_ray_cb(PBVHNode *node, void *data_v, float *t
else {
/* Intersect with coordinates from before we started stroke. */
SculptUndoNode *unode = SCULPT_undo_get_node(node, SCULPT_UNDO_COORDS);
origco = (unode) ? unode->co : nullptr;
origco = (unode) ? reinterpret_cast<float(*)[3]>(unode->co.data()) : nullptr;
use_origco = origco ? true : false;
}
}

View File

@ -20,12 +20,15 @@
#include "BKE_paint.hh"
#include "BKE_pbvh_api.hh"
#include "BLI_array.hh"
#include "BLI_bit_vector.hh"
#include "BLI_bitmap.h"
#include "BLI_compiler_attrs.h"
#include "BLI_compiler_compat.h"
#include "BLI_generic_array.hh"
#include "BLI_gsqueue.h"
#include "BLI_implicit_sharing.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_set.hh"
#include "BLI_span.hh"
#include "BLI_threads.h"
@ -177,30 +180,30 @@ struct SculptUndoNode {
char idname[MAX_ID_NAME]; /* Name instead of pointer. */
void *node; /* only during push, not valid afterwards! */
float (*co)[3];
float (*orig_co)[3];
float (*no)[3];
float (*col)[4];
float *mask;
blender::Array<blender::float3> co;
blender::Array<blender::float3> orig_co;
blender::Array<blender::float3> no;
blender::Array<blender::float4> col;
blender::Array<float> mask;
int totvert;
float (*loop_col)[4];
float (*orig_loop_col)[4];
blender::Array<blender::float4> loop_col;
blender::Array<blender::float4> orig_loop_col;
int totloop;
/* non-multires */
int maxvert; /* to verify if totvert it still the same */
int *index; /* Unique vertex indices, to restore into right location */
int maxvert; /* to verify if totvert it still the same */
blender::Array<int> index; /* Unique vertex indices, to restore into right location */
int maxloop;
int *loop_index;
blender::Array<int> loop_index;
BLI_bitmap *vert_hidden;
blender::BitVector<> vert_hidden;
/* multires */
int maxgrid; /* same for grid */
int gridsize; /* same for grid */
int totgrid; /* to restore into right location */
int *grids; /* to restore into right location */
int maxgrid; /* same for grid */
int gridsize; /* same for grid */
int totgrid; /* to restore into right location */
blender::Array<int> grids; /* to restore into right location */
BLI_bitmap **grid_hidden;
/* bmesh */
@ -228,9 +231,9 @@ struct SculptUndoNode {
float pivot_rot[4];
/* Sculpt Face Sets */
int *face_sets;
blender::Array<int> face_sets;
PBVHFaceRef *faces;
blender::Array<PBVHFaceRef> faces;
int faces_num;
size_t undo_size;

View File

@ -388,7 +388,6 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
Object *ob = BKE_view_layer_active_object_get(view_layer);
SculptSession *ss = ob->sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
int *index;
if (unode->maxvert) {
/* Regular mesh restore. */
@ -412,14 +411,14 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
}
/* No need for float comparison here (memory is exactly equal or not). */
index = unode->index;
const Span<int> index = unode->index;
blender::MutableSpan<blender::float3> positions = ss->vert_positions;
if (ss->shapekey_active) {
float(*vertCos)[3];
vertCos = BKE_keyblock_convert_to_vertcos(ob, ss->shapekey_active);
if (unode->orig_co) {
if (!unode->orig_co.is_empty()) {
if (ss->deform_modifiers_active) {
for (int i = 0; i < unode->totvert; i++) {
sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]);
@ -447,7 +446,7 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
MEM_freeN(vertCos);
}
else {
if (unode->orig_co) {
if (!unode->orig_co.is_empty()) {
if (ss->deform_modifiers_active) {
for (int i = 0; i < unode->totvert; i++) {
sculpt_undo_restore_deformed(ss, unode, i, index[i], positions[index[i]]);
@ -473,19 +472,20 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
/* Multires restore. */
CCGElem **grids, *grid;
CCGKey key;
float(*co)[3];
int gridsize;
grids = subdiv_ccg->grids;
gridsize = subdiv_ccg->grid_size;
BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
co = unode->co;
blender::MutableSpan<blender::float3> co = unode->co;
int index = 0;
for (int j = 0; j < unode->totgrid; j++) {
grid = grids[unode->grids[j]];
for (int i = 0; i < gridsize * gridsize; i++, co++) {
swap_v3_v3(CCG_elem_offset_co(&key, grid, i), co[0]);
for (int i = 0; i < gridsize * gridsize; i++) {
swap_v3_v3(CCG_elem_offset_co(&key, grid, i), co[index]);
index++;
}
}
}
@ -508,7 +508,7 @@ static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode, bool
for (int i = 0; i < unode->totvert; i++) {
const int vert_index = unode->index[i];
if ((BLI_BITMAP_TEST(unode->vert_hidden, i) != 0) != hide_vert[vert_index]) {
BLI_BITMAP_FLIP(unode->vert_hidden, i);
unode->vert_hidden[i].set(!unode->vert_hidden[i].test());
hide_vert[vert_index] = !hide_vert[vert_index];
modified_vertices[vert_index] = true;
}
@ -537,15 +537,15 @@ static bool sculpt_undo_restore_color(bContext *C, SculptUndoNode *unode, bool *
/* NOTE: even with loop colors we still store derived
* vertex colors for original data lookup. */
if (unode->col && !unode->loop_col) {
BKE_pbvh_swap_colors(ss->pbvh, unode->index, unode->totvert, unode->col);
if (!unode->col.is_empty() && unode->loop_col.is_empty()) {
BKE_pbvh_swap_colors(ss->pbvh, unode->index, unode->col);
modified = true;
}
Mesh *me = BKE_object_get_original_mesh(ob);
if (unode->loop_col && unode->maxloop == me->totloop) {
BKE_pbvh_swap_colors(ss->pbvh, unode->loop_index, unode->totloop, unode->loop_col);
if (!unode->loop_col.is_empty() && unode->maxloop == me->totloop) {
BKE_pbvh_swap_colors(ss->pbvh, unode->loop_index, unode->loop_col);
modified = true;
}
@ -568,7 +568,6 @@ static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode, bool *m
Mesh *mesh = BKE_object_get_original_mesh(ob);
SculptSession *ss = ob->sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
int *index;
if (unode->maxvert) {
/* Regular mesh restore. */
@ -576,7 +575,7 @@ static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode, bool *m
CustomData_get_layer_for_write(&mesh->vert_data, CD_PAINT_MASK, mesh->totvert));
ss->vmask = vmask;
index = unode->index;
const Span<int> index = unode->index;
for (int i = 0; i < unode->totvert; i++) {
if (vmask[index[i]] != unode->mask[i]) {
@ -589,19 +588,20 @@ static bool sculpt_undo_restore_mask(bContext *C, SculptUndoNode *unode, bool *m
/* Multires restore. */
CCGElem **grids, *grid;
CCGKey key;
float *mask;
int gridsize;
grids = subdiv_ccg->grids;
gridsize = subdiv_ccg->grid_size;
BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
mask = unode->mask;
blender::MutableSpan<float> mask = unode->mask;
int index = 0;
for (int j = 0; j < unode->totgrid; j++) {
grid = grids[unode->grids[j]];
for (int i = 0; i < gridsize * gridsize; i++, mask++) {
SWAP(float, *CCG_elem_offset_mask(&key, grid, i), *mask);
for (int i = 0; i < gridsize * gridsize; i++) {
SWAP(float, *CCG_elem_offset_mask(&key, grid, i), mask[index]);
index++;
}
}
}
@ -1094,36 +1094,7 @@ static void sculpt_undo_free_list(ListBase *lb)
SculptUndoNode *unode = static_cast<SculptUndoNode *>(lb->first);
while (unode != nullptr) {
SculptUndoNode *unode_next = unode->next;
if (unode->co) {
MEM_freeN(unode->co);
}
if (unode->col) {
MEM_freeN(unode->col);
}
if (unode->loop_col) {
MEM_freeN(unode->loop_col);
}
if (unode->no) {
MEM_freeN(unode->no);
}
if (unode->index) {
MEM_freeN(unode->index);
}
if (unode->faces) {
MEM_freeN(unode->faces);
}
if (unode->loop_index) {
MEM_freeN(unode->loop_index);
}
if (unode->grids) {
MEM_freeN(unode->grids);
}
if (unode->orig_co) {
MEM_freeN(unode->orig_co);
}
if (unode->vert_hidden) {
MEM_freeN(unode->vert_hidden);
}
if (unode->grid_hidden) {
for (int i = 0; i < unode->totgrid; i++) {
if (unode->grid_hidden[i]) {
@ -1132,9 +1103,6 @@ static void sculpt_undo_free_list(ListBase *lb)
}
MEM_freeN(unode->grid_hidden);
}
if (unode->mask) {
MEM_freeN(unode->mask);
}
if (unode->bm_entry) {
BM_log_entry_drop(unode->bm_entry);
@ -1144,11 +1112,7 @@ static void sculpt_undo_free_list(ListBase *lb)
sculpt_undo_geometry_free_data(&unode->geometry_modified);
sculpt_undo_geometry_free_data(&unode->geometry_bmesh_enter);
if (unode->face_sets) {
MEM_freeN(unode->face_sets);
}
MEM_freeN(unode);
MEM_delete(unode);
unode = unode_next;
}
@ -1236,7 +1200,7 @@ static size_t sculpt_undo_alloc_and_store_hidden(PBVH *pbvh, SculptUndoNode *uno
static SculptUndoNode *sculpt_undo_alloc_node_type(Object *object, SculptUndoType type)
{
const size_t alloc_size = sizeof(SculptUndoNode);
SculptUndoNode *unode = static_cast<SculptUndoNode *>(MEM_callocN(alloc_size, "SculptUndoNode"));
SculptUndoNode *unode = MEM_new<SculptUndoNode>(__func__);
STRNCPY(unode->idname, object->id.name);
unode->type = type;
@ -1273,8 +1237,7 @@ static void sculpt_undo_store_faces(SculptSession *ss, SculptUndoNode *unode)
}
BKE_pbvh_face_iter_end(fd);
unode->faces = static_cast<PBVHFaceRef *>(
MEM_malloc_arrayN(sizeof(*unode->faces), unode->faces_num, __func__));
unode->faces.reinitialize(unode->faces_num);
BKE_pbvh_face_iter_begin (ss->pbvh, static_cast<PBVHNode *>(unode->node), fd) {
unode->faces[fd.i] = fd.face;
}
@ -1310,30 +1273,26 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
BKE_pbvh_node_num_loops(ss->pbvh, node, &totloop);
unode->loop_index = static_cast<int *>(MEM_calloc_arrayN(totloop, sizeof(int), __func__));
unode->loop_index.reinitialize(totloop);
unode->maxloop = 0;
unode->totloop = totloop;
size_t alloc_size = sizeof(int) * size_t(totloop);
usculpt->undo_size += alloc_size;
usculpt->undo_size += unode->loop_index.as_span().size_in_bytes();
}
if (need_faces) {
sculpt_undo_store_faces(ss, unode);
const size_t alloc_size = sizeof(*unode->faces) * size_t(unode->faces_num);
usculpt->undo_size += alloc_size;
usculpt->undo_size += unode->faces.as_span().size_in_bytes();
}
switch (type) {
case SCULPT_UNDO_COORDS: {
size_t alloc_size = sizeof(*unode->co) * size_t(allvert);
unode->co = static_cast<float(*)[3]>(MEM_callocN(alloc_size, "SculptUndoNode.co"));
usculpt->undo_size += alloc_size;
unode->co.reinitialize(allvert);
usculpt->undo_size += unode->co.as_span().size_in_bytes();
/* Needed for original data lookup. */
alloc_size = sizeof(*unode->no) * size_t(allvert);
unode->no = static_cast<float(*)[3]>(MEM_callocN(alloc_size, "SculptUndoNode.no"));
usculpt->undo_size += alloc_size;
unode->no.reinitialize(allvert);
usculpt->undo_size += unode->no.as_span().size_in_bytes();
break;
}
case SCULPT_UNDO_HIDDEN: {
@ -1341,32 +1300,27 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
usculpt->undo_size += sculpt_undo_alloc_and_store_hidden(ss->pbvh, unode);
}
else {
unode->vert_hidden = BLI_BITMAP_NEW(allvert, "SculptUndoNode.vert_hidden");
unode->vert_hidden.resize(allvert);
usculpt->undo_size += BLI_BITMAP_SIZE(allvert);
}
break;
}
case SCULPT_UNDO_MASK: {
const size_t alloc_size = sizeof(*unode->mask) * size_t(allvert);
unode->mask = static_cast<float *>(MEM_callocN(alloc_size, "SculptUndoNode.mask"));
usculpt->undo_size += alloc_size;
unode->mask.reinitialize(allvert);
usculpt->undo_size += unode->mask.as_span().size_in_bytes();
break;
}
case SCULPT_UNDO_COLOR: {
/* Allocate vertex colors, even for loop colors we still
* need this for original data lookup. */
const size_t alloc_size = sizeof(*unode->col) * size_t(allvert);
unode->col = static_cast<float(*)[4]>(MEM_callocN(alloc_size, "SculptUndoNode.col"));
usculpt->undo_size += alloc_size;
unode->col.reinitialize(allvert);
usculpt->undo_size += unode->col.as_span().size_in_bytes();
/* Allocate loop colors separately too. */
if (ss->vcol_domain == ATTR_DOMAIN_CORNER) {
size_t alloc_size_loop = sizeof(float) * 4 * size_t(unode->totloop);
unode->loop_col = static_cast<float(*)[4]>(
MEM_calloc_arrayN(unode->totloop, sizeof(float) * 4, "SculptUndoNode.loop_col"));
usculpt->undo_size += alloc_size_loop;
unode->loop_col.reinitialize(unode->totloop);
unode->undo_size += unode->loop_col.as_span().size_in_bytes();
}
break;
}
@ -1378,8 +1332,8 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
case SCULPT_UNDO_GEOMETRY:
break;
case SCULPT_UNDO_FACE_SETS: {
const size_t alloc_size = sizeof(*unode->face_sets) * size_t(unode->faces_num);
usculpt->undo_size += alloc_size;
unode->face_sets.reinitialize(unode->faces_num);
usculpt->undo_size += unode->face_sets.as_span().size_in_bytes();
break;
}
}
@ -1390,23 +1344,19 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
unode->totgrid = totgrid;
unode->gridsize = gridsize;
const size_t alloc_size = sizeof(*unode->grids) * size_t(totgrid);
unode->grids = static_cast<int *>(MEM_callocN(alloc_size, "SculptUndoNode.grids"));
usculpt->undo_size += alloc_size;
unode->grids.reinitialize(totgrid);
usculpt->undo_size += unode->grids.as_span().size_in_bytes();
}
else {
/* Regular mesh. */
unode->maxvert = ss->totvert;
const size_t alloc_size = sizeof(*unode->index) * size_t(allvert);
unode->index = static_cast<int *>(MEM_callocN(alloc_size, "SculptUndoNode.index"));
usculpt->undo_size += alloc_size;
unode->index.reinitialize(allvert);
usculpt->undo_size += unode->index.as_span().size_in_bytes();
}
if (ss->deform_modifiers_active) {
const size_t alloc_size = sizeof(*unode->orig_co) * size_t(allvert);
unode->orig_co = static_cast<float(*)[3]>(MEM_callocN(alloc_size, "undoSculpt orig_cos"));
usculpt->undo_size += alloc_size;
unode->orig_co.reinitialize(allvert);
usculpt->undo_size += unode->orig_co.as_span().size_in_bytes();
}
return unode;
@ -1443,13 +1393,13 @@ static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
return;
}
if (unode->grids) {
if (!unode->grids.is_empty()) {
/* Already stored during allocation. */
}
else {
const blender::Span<int> verts = BKE_pbvh_node_get_vert_indices(node);
for (const int i : verts.index_range())
BLI_BITMAP_SET(unode->vert_hidden, i, hide_vert[verts[i]]);
unode->vert_hidden[i].set(hide_vert[verts[i]]);
}
}
@ -1470,15 +1420,12 @@ static void sculpt_undo_store_color(Object *ob, SculptUndoNode *unode)
BLI_assert(BKE_pbvh_type(ss->pbvh) == PBVH_FACES);
int allvert;
BKE_pbvh_node_num_verts(ss->pbvh, static_cast<PBVHNode *>(unode->node), nullptr, &allvert);
/* NOTE: even with loop colors we still store (derived)
* vertex colors for original data lookup. */
BKE_pbvh_store_colors_vertex(ss->pbvh, unode->index, allvert, unode->col);
BKE_pbvh_store_colors_vertex(ss->pbvh, unode->index, unode->col);
if (unode->loop_col && unode->totloop) {
BKE_pbvh_store_colors(ss->pbvh, unode->loop_index, unode->totloop, unode->loop_col);
if (!unode->loop_col.is_empty() && unode->totloop) {
BKE_pbvh_store_colors(ss->pbvh, unode->loop_index, unode->loop_col);
}
}
@ -1507,8 +1454,7 @@ static SculptUndoNode *sculpt_undo_geometry_push(Object *object, SculptUndoType
static void sculpt_undo_store_face_sets(SculptSession *ss, SculptUndoNode *unode)
{
unode->face_sets = static_cast<int *>(
MEM_malloc_arrayN(sizeof(*unode->face_sets), unode->faces_num, __func__));
unode->face_sets.reinitialize(unode->faces_num);
PBVHFaceIter fd;
BKE_pbvh_face_iter_begin (ss->pbvh, static_cast<PBVHNode *>(unode->node), fd) {
@ -1526,7 +1472,7 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, Sculpt
SculptUndoNode *unode = static_cast<SculptUndoNode *>(usculpt->nodes.first);
if (unode == nullptr) {
unode = MEM_cnew<SculptUndoNode>(__func__);
unode = MEM_new<SculptUndoNode>(__func__);
STRNCPY(unode->idname, ob->id.name);
unode->type = type;
@ -1629,27 +1575,24 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
* fully initialized.
*/
if (unode->grids) {
if (!unode->grids.is_empty()) {
int totgrid;
const int *grids;
BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid, nullptr, nullptr, nullptr);
memcpy(unode->grids, grids, sizeof(int) * totgrid);
unode->grids.as_mutable_span().copy_from({grids, totgrid});
}
else {
const int *loop_indices;
int allvert, allloop;
unode->index.as_mutable_span().copy_from(BKE_pbvh_node_get_vert_indices(node));
BKE_pbvh_node_num_verts(ss->pbvh, static_cast<PBVHNode *>(unode->node), nullptr, &allvert);
const blender::Span<int> vert_indices = BKE_pbvh_node_get_vert_indices(node);
memcpy(unode->index, vert_indices.data(), sizeof(int) * allvert);
if (unode->loop_index) {
if (!unode->loop_index.is_empty()) {
const int *loop_indices;
int allloop;
BKE_pbvh_node_num_loops(ss->pbvh, static_cast<PBVHNode *>(unode->node), &allloop);
BKE_pbvh_node_get_loops(
ss->pbvh, static_cast<PBVHNode *>(unode->node), &loop_indices, nullptr);
if (allloop) {
memcpy(unode->loop_index, loop_indices, sizeof(int) * allloop);
unode->loop_index.as_mutable_span().copy_from({loop_indices, allloop});
unode->maxloop = BKE_object_get_original_mesh(ob)->totloop;
}
@ -1776,11 +1719,8 @@ void SCULPT_undo_push_end_ex(Object *ob, const bool use_nested_undo)
/* We don't need normals in the undo stack. */
LISTBASE_FOREACH (SculptUndoNode *, unode, &usculpt->nodes) {
if (unode->no) {
usculpt->undo_size -= MEM_allocN_len(unode->no);
MEM_freeN(unode->no);
unode->no = nullptr;
}
usculpt->undo_size -= unode->no.as_span().size_in_bytes();
unode->no = {};
}
/* We could remove this and enforce all callers run in an operator using 'OPTYPE_UNDO'. */