Refactor: Store PBVH in unique_ptr

This requires adding a destructor and deleting move and copy assignment
for SculptSession, because (for now at least) we want to keep the PBVH
as an opaque type (though with one exception for including pbvh_intern.hh
in paint.cc for the SculptSession destructor).

Pull Request: https://projects.blender.org/blender/blender/pulls/121227
This commit is contained in:
Hans Goudey
2024-04-29 13:10:15 -04:00
committed by Gitea
parent 7c56e16e44
commit 76a151b9d6
13 changed files with 162 additions and 143 deletions

View File

@@ -15,6 +15,7 @@
#include "BLI_offset_indices.hh"
#include "BLI_ordered_edge.hh"
#include "BLI_set.hh"
#include "BLI_utility_mixins.hh"
#include "DNA_brush_enums.h"
#include "DNA_customdata_types.h"
@@ -411,33 +412,34 @@ struct SculptAttributeParams {
struct SculptAttribute {
/* Domain, data type and name */
blender::bke::AttrDomain domain;
eCustomDataType proptype;
char name[MAX_CUSTOMDATA_LAYER_NAME];
eCustomDataType proptype = eCustomDataType(0);
char name[MAX_CUSTOMDATA_LAYER_NAME] = "";
/* Source layer on mesh/bmesh, if any. */
CustomDataLayer *layer;
CustomDataLayer *layer = nullptr;
/* Data stored as flat array. */
void *data;
int elem_size, elem_num;
bool data_for_bmesh; /* Temporary data store as array outside of bmesh. */
void *data = nullptr;
int elem_size = 0;
int elem_num = 0;
bool data_for_bmesh = false; /* Temporary data store as array outside of bmesh. */
/* Data is a flat array outside the CustomData system.
* This will be true if simple_array is requested in
* SculptAttributeParams, or the PBVH type is PBVH_GRIDS or PBVH_BMESH.
*/
bool simple_array;
bool simple_array = false;
/* Data stored per BMesh element. */
int bmesh_cd_offset;
int bmesh_cd_offset = 0;
/* Sculpt usage */
SculptAttributeParams params;
SculptAttributeParams params = {};
/**
* Used to keep track of which pre-allocated SculptAttribute instances
* inside of SculptSession.temp_attribute are used.
*/
bool used;
bool used = false;
};
#define SCULPT_MAX_ATTRIBUTES 64
@@ -456,34 +458,34 @@ struct SculptAttribute {
struct SculptAttributePointers {
/* Persistent base. */
SculptAttribute *persistent_co;
SculptAttribute *persistent_no;
SculptAttribute *persistent_disp;
SculptAttribute *persistent_co = nullptr;
SculptAttribute *persistent_no = nullptr;
SculptAttribute *persistent_disp = nullptr;
/* Precomputed auto-mask factor indexed by vertex, owned by the auto-masking system and
* initialized in #auto_mask::cache_init when needed. */
SculptAttribute *automasking_factor;
SculptAttribute *automasking_occlusion; /* CD_PROP_INT8. */
SculptAttribute *automasking_stroke_id;
SculptAttribute *automasking_cavity;
SculptAttribute *automasking_factor = nullptr;
SculptAttribute *automasking_occlusion = nullptr; /* CD_PROP_INT8. */
SculptAttribute *automasking_stroke_id = nullptr;
SculptAttribute *automasking_cavity = nullptr;
SculptAttribute *topology_island_key; /* CD_PROP_INT8 */
SculptAttribute *topology_island_key = nullptr; /* CD_PROP_INT8 */
/* BMesh */
SculptAttribute *dyntopo_node_id_vertex;
SculptAttribute *dyntopo_node_id_face;
SculptAttribute *dyntopo_node_id_vertex = nullptr;
SculptAttribute *dyntopo_node_id_face = nullptr;
};
struct SculptSession {
struct SculptSession : blender::NonCopyable, blender::NonMovable {
/* Mesh data (not copied) can come either directly from a Mesh, or from a MultiresDM */
struct { /* Special handling for multires meshes */
bool active;
MultiresModifierData *modifier;
int level;
} multires;
} multires = {};
/* Depsgraph for the Cloth Brush solver to get the colliders. */
Depsgraph *depsgraph;
Depsgraph *depsgraph = nullptr;
/* These are always assigned to base mesh data when using PBVH_FACES and PBVH_GRIDS. */
blender::MutableSpan<blender::float3> vert_positions;
@@ -491,14 +493,15 @@ struct SculptSession {
blender::Span<int> corner_verts;
/* These contain the vertex and poly counts of the final mesh. */
int totvert, faces_num;
int totvert = 0;
int faces_num = 0;
KeyBlock *shapekey_active;
MPropCol *vcol;
MLoopCol *mcol;
KeyBlock *shapekey_active = nullptr;
MPropCol *vcol = nullptr;
MLoopCol *mcol = nullptr;
blender::bke::AttrDomain vcol_domain;
eCustomDataType vcol_type;
eCustomDataType vcol_type = CD_PROP_COLOR;
/* Mesh connectivity maps. */
/* Vertices to adjacent polys. */
@@ -516,32 +519,32 @@ struct SculptSession {
/* Mesh Face Sets */
/* Total number of faces of the base mesh. */
int totfaces;
int totfaces = 0;
/* The 0 ID is not used by the tools or the visibility system, it is just used when creating new
* geometry (the trim tool, for example) to detect which geometry was just added, so it can be
* assigned a valid Face Set after creation. Tools are not intended to run with Face Sets IDs set
* to 0. */
const int *face_sets;
const int *face_sets = nullptr;
/**
* A reference to the ".hide_poly" attribute, to store whether (base) faces are hidden.
* May be null.
*/
const bool *hide_poly;
const bool *hide_poly = nullptr;
/* BMesh for dynamic topology sculpting */
BMesh *bm;
BMesh *bm = nullptr;
/* Undo/redo log for dynamic topology sculpting */
BMLog *bm_log;
BMLog *bm_log = nullptr;
/* Limit surface/grids. */
SubdivCCG *subdiv_ccg;
SubdivCCG *subdiv_ccg = nullptr;
/* PBVH acceleration structure */
PBVH *pbvh;
std::unique_ptr<PBVH> pbvh;
/* Object is deformed with some modifiers. */
bool deform_modifiers_active;
bool deform_modifiers_active = false;
/* Coords of un-deformed mesh. */
blender::Array<blender::float3> orig_cos;
/* Coords of deformed mesh but without stroke displacement. */
@@ -550,46 +553,46 @@ struct SculptSession {
blender::Array<blender::float3x3, 0> deform_imats;
/* Pool for texture evaluations. */
ImagePool *tex_pool;
ImagePool *tex_pool = nullptr;
blender::ed::sculpt_paint::StrokeCache *cache;
blender::ed::sculpt_paint::filter::Cache *filter_cache;
blender::ed::sculpt_paint::expand::Cache *expand_cache;
blender::ed::sculpt_paint::StrokeCache *cache = nullptr;
blender::ed::sculpt_paint::filter::Cache *filter_cache = nullptr;
blender::ed::sculpt_paint::expand::Cache *expand_cache = nullptr;
/* Cursor data and active vertex for tools */
PBVHVertRef active_vertex;
PBVHVertRef active_vertex = PBVHVertRef{PBVH_REF_NONE};
int active_face_index;
int active_grid_index;
int active_face_index = -1;
int active_grid_index = -1;
/* When active, the cursor draws with faded colors, indicating that there is an action
* enabled.
*/
bool draw_faded_cursor;
float cursor_radius;
bool draw_faded_cursor = false;
float cursor_radius = 0.0f;
blender::float3 cursor_location;
blender::float3 cursor_normal;
blender::float3 cursor_sampled_normal;
blender::float3 cursor_view_normal;
/* TODO(jbakker): Replace rv3d and v3d with ViewContext */
RegionView3D *rv3d;
View3D *v3d;
Scene *scene;
RegionView3D *rv3d = nullptr;
View3D *v3d = nullptr;
Scene *scene = nullptr;
/* Dynamic mesh preview */
PBVHVertRef *preview_vert_list;
int preview_vert_count;
PBVHVertRef *preview_vert_list = nullptr;
int preview_vert_count = 0;
/* Pose Brush Preview */
blender::float3 pose_origin;
std::unique_ptr<SculptPoseIKChain> pose_ik_chain_preview;
/* Boundary Brush Preview */
SculptBoundary *boundary_preview;
SculptBoundary *boundary_preview = nullptr;
SculptVertexInfo vertex_info;
SculptFakeNeighbors fake_neighbors;
SculptVertexInfo vertex_info = {};
SculptFakeNeighbors fake_neighbors = {};
/* Transform operator */
blender::float3 pivot_pos;
@@ -621,17 +624,17 @@ struct SculptSession {
/* TODO: identify sculpt-only fields */
// struct { ... } sculpt;
} mode;
} mode = {};
eObjectMode mode_type;
/* This flag prevents PBVH from being freed when creating the vp_handle for texture paint. */
bool building_vp_handle;
bool building_vp_handle = false;
/**
* ID data is older than sculpt-mode data.
* Set #Main.is_memfile_undo_flush_needed when enabling.
*/
char needs_flush_to_id;
char needs_flush_to_id = false;
/* This is a fixed-size array so we can pass pointers to its elements
* to client code. This is important to keep bmesh offsets up to date.
@@ -647,19 +650,22 @@ struct SculptSession {
*
* NOTE: This setting is temporarily until paint mode is added.
*/
bool sticky_shading_color;
bool sticky_shading_color = false;
uchar stroke_id;
uchar stroke_id = 0;
/**
* Last used painting canvas key.
*/
char *last_paint_canvas_key;
char *last_paint_canvas_key = nullptr;
blender::float3 last_normal;
int last_automasking_settings_hash;
uchar last_automask_stroke_id;
bool islands_valid; /* Is attrs.topology_island_key valid? */
int last_automasking_settings_hash = 0;
uchar last_automask_stroke_id = 0;
bool islands_valid = false; /* Is attrs.topology_island_key valid? */
SculptSession();
~SculptSession();
};
void BKE_sculptsession_free(Object *ob);

View File

@@ -123,21 +123,24 @@ namespace blender::bke::pbvh {
/**
* Do a full rebuild with on Mesh data structure.
*/
PBVH *build_mesh(Mesh *mesh);
std::unique_ptr<PBVH> build_mesh(Mesh *mesh);
void update_mesh_pointers(PBVH &pbvh, Mesh *mesh);
/**
* Do a full rebuild with on Grids data structure.
*/
PBVH *build_grids(const CCGKey *key, Mesh *mesh, SubdivCCG *subdiv_ccg);
std::unique_ptr<PBVH> build_grids(const CCGKey *key, Mesh *mesh, SubdivCCG *subdiv_ccg);
/**
* Build a PBVH from a BMesh.
*/
PBVH *build_bmesh(BMesh *bm, BMLog *log, int cd_vert_node_offset, int cd_face_node_offset);
std::unique_ptr<PBVH> build_bmesh(BMesh *bm,
BMLog *log,
int cd_vert_node_offset,
int cd_face_node_offset);
void update_bmesh_offsets(PBVH &pbvh, int cd_vert_node_offset, int cd_face_node_offset);
void build_pixels(PBVH &pbvh, Mesh *mesh, Image *image, ImageUser *image_user);
void free(PBVH *pbvh);
void free(std::unique_ptr<PBVH> &pbvh);
/* Hierarchical Search in the BVH, two methods:
* - For each hit calling a callback.

View File

@@ -454,11 +454,7 @@ void multires_force_sculpt_rebuild(Object *object)
}
SculptSession *ss = object->sculpt;
if (ss->pbvh != nullptr) {
bke::pbvh::free(ss->pbvh);
object->sculpt->pbvh = nullptr;
}
bke::pbvh::free(ss->pbvh);
}
void multires_force_external_reload(Object *object)

View File

@@ -76,6 +76,9 @@
#include "bmesh.hh"
/* For #PBVH::~PBVH(). */
#include "pbvh_intern.hh"
using blender::float3;
using blender::MutableSpan;
using blender::Span;
@@ -1422,16 +1425,11 @@ static void sculptsession_free_pbvh(Object *object)
{
using namespace blender;
SculptSession *ss = object->sculpt;
if (!ss) {
return;
}
if (ss->pbvh) {
bke::pbvh::free(ss->pbvh);
ss->pbvh = nullptr;
}
bke::pbvh::free(ss->pbvh);
ss->vert_to_face_map = {};
ss->edge_to_face_offsets = {};
ss->edge_to_face_indices = {};
@@ -1484,32 +1482,45 @@ void BKE_sculptsession_free(Object *ob)
sculptsession_free_pbvh(ob);
if (ss->bm_log) {
BM_log_free(ss->bm_log);
}
if (ss->tex_pool) {
BKE_image_pool_free(ss->tex_pool);
}
if (ss->boundary_preview) {
MEM_SAFE_FREE(ss->boundary_preview->verts);
MEM_SAFE_FREE(ss->boundary_preview->edges);
MEM_SAFE_FREE(ss->boundary_preview->distance);
MEM_SAFE_FREE(ss->boundary_preview->edit_info);
MEM_SAFE_FREE(ss->boundary_preview);
}
BKE_sculptsession_free_vwpaint_data(ob->sculpt);
MEM_SAFE_FREE(ss->last_paint_canvas_key);
MEM_delete(ss);
ob->sculpt = nullptr;
}
}
SculptSession::SculptSession()
{
/* Code expects attribute domains to be zero initialized. Avoid exposing #AttrDomain definition
* in header. */
this->vcol_domain = blender::bke::AttrDomain::Point;
for (const int i : blender::IndexRange(ARRAY_SIZE(this->temp_attributes))) {
this->temp_attributes[i].domain = blender::bke::AttrDomain::Point;
}
}
SculptSession::~SculptSession()
{
if (this->bm_log) {
BM_log_free(this->bm_log);
}
if (this->tex_pool) {
BKE_image_pool_free(this->tex_pool);
}
if (this->boundary_preview) {
MEM_SAFE_FREE(this->boundary_preview->verts);
MEM_SAFE_FREE(this->boundary_preview->edges);
MEM_SAFE_FREE(this->boundary_preview->distance);
MEM_SAFE_FREE(this->boundary_preview->edit_info);
MEM_SAFE_FREE(this->boundary_preview);
}
BKE_sculptsession_free_vwpaint_data(this);
MEM_SAFE_FREE(this->last_paint_canvas_key);
}
static MultiresModifierData *sculpt_multires_modifier_get(const Scene *scene,
Object *ob,
const bool auto_create_mdisps)
@@ -1723,7 +1734,7 @@ static void sculpt_update_object(Depsgraph *depsgraph,
ss->subdiv_ccg = mesh_eval->runtime->subdiv_ccg.get();
PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
BLI_assert(pbvh == ss->pbvh);
BLI_assert(pbvh == ss->pbvh.get());
UNUSED_VARS_NDEBUG(pbvh);
BKE_pbvh_subdiv_cgg_set(*ss->pbvh, ss->subdiv_ccg);
@@ -2094,7 +2105,7 @@ void BKE_sculpt_sync_face_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv_ccg)
namespace blender::bke {
static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
static std::unique_ptr<PBVH> build_pbvh_for_dynamic_topology(Object *ob)
{
sculptsession_bmesh_add_layers(ob);
@@ -2104,10 +2115,10 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
ob->sculpt->attrs.dyntopo_node_id_face->bmesh_cd_offset);
}
static PBVH *build_pbvh_from_regular_mesh(Object *ob, const Mesh *me_eval_deform)
static std::unique_ptr<PBVH> build_pbvh_from_regular_mesh(Object *ob, const Mesh *me_eval_deform)
{
Mesh *mesh = BKE_object_get_original_mesh(ob);
PBVH *pbvh = pbvh::build_mesh(mesh);
std::unique_ptr<PBVH> pbvh = pbvh::build_mesh(mesh);
const bool is_deformed = check_sculpt_object_deformed(ob, true);
if (is_deformed && me_eval_deform != nullptr) {
@@ -2117,7 +2128,7 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, const Mesh *me_eval_deform
return pbvh;
}
static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg)
static std::unique_ptr<PBVH> build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg)
{
const CCGKey key = BKE_subdiv_ccg_key_top_level(*subdiv_ccg);
Mesh *base_mesh = BKE_mesh_from_object(ob);
@@ -2135,21 +2146,20 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
return nullptr;
}
PBVH *pbvh = ob->sculpt->pbvh;
if (pbvh != nullptr) {
if (ob->sculpt->pbvh) {
/* NOTE: It is possible that pointers to grids or other geometry data changed. Need to update
* those pointers. */
const PBVHType pbvh_type = BKE_pbvh_type(*pbvh);
const PBVHType pbvh_type = BKE_pbvh_type(*ob->sculpt->pbvh);
switch (pbvh_type) {
case PBVH_FACES: {
pbvh::update_mesh_pointers(*pbvh, BKE_object_get_original_mesh(ob));
pbvh::update_mesh_pointers(*ob->sculpt->pbvh, BKE_object_get_original_mesh(ob));
break;
}
case PBVH_GRIDS: {
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
Mesh *mesh_eval = static_cast<Mesh *>(object_eval->data);
if (SubdivCCG *subdiv_ccg = mesh_eval->runtime->subdiv_ccg.get()) {
BKE_sculpt_bvh_update_from_ccg(*pbvh, subdiv_ccg);
BKE_sculpt_bvh_update_from_ccg(*ob->sculpt->pbvh, subdiv_ccg);
}
break;
}
@@ -2158,35 +2168,34 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
}
}
BKE_pbvh_update_active_vcol(*pbvh, BKE_object_get_original_mesh(ob));
BKE_pbvh_pmap_set(*pbvh, ob->sculpt->vert_to_face_map);
BKE_pbvh_update_active_vcol(*ob->sculpt->pbvh, BKE_object_get_original_mesh(ob));
BKE_pbvh_pmap_set(*ob->sculpt->pbvh, ob->sculpt->vert_to_face_map);
return pbvh;
return ob->sculpt->pbvh.get();
}
ob->sculpt->islands_valid = false;
if (ob->sculpt->bm != nullptr) {
/* Sculpting on a BMesh (dynamic-topology) gets a special PBVH. */
pbvh = build_pbvh_for_dynamic_topology(ob);
ob->sculpt->pbvh = build_pbvh_for_dynamic_topology(ob);
}
else {
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
Mesh *mesh_eval = static_cast<Mesh *>(object_eval->data);
if (mesh_eval->runtime->subdiv_ccg != nullptr) {
pbvh = build_pbvh_from_ccg(ob, mesh_eval->runtime->subdiv_ccg.get());
ob->sculpt->pbvh = build_pbvh_from_ccg(ob, mesh_eval->runtime->subdiv_ccg.get());
}
else if (ob->type == OB_MESH) {
const Mesh *me_eval_deform = BKE_object_get_mesh_deform_eval(object_eval);
pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform);
ob->sculpt->pbvh = build_pbvh_from_regular_mesh(ob, me_eval_deform);
}
}
BKE_pbvh_pmap_set(*pbvh, ob->sculpt->vert_to_face_map);
ob->sculpt->pbvh = pbvh;
BKE_pbvh_pmap_set(*ob->sculpt->pbvh, ob->sculpt->vert_to_face_map);
sculpt_attribute_update_refs(ob, BKE_pbvh_type(*pbvh));
return pbvh;
sculpt_attribute_update_refs(ob, BKE_pbvh_type(*ob->sculpt->pbvh));
return ob->sculpt->pbvh.get();
}
PBVH *BKE_object_sculpt_pbvh_get(Object *object)
@@ -2194,7 +2203,7 @@ PBVH *BKE_object_sculpt_pbvh_get(Object *object)
if (!object->sculpt) {
return nullptr;
}
return object->sculpt->pbvh;
return object->sculpt->pbvh.get();
}
bool BKE_object_sculpt_use_dyntopo(const Object *object)

View File

@@ -703,7 +703,7 @@ void update_mesh_pointers(PBVH &pbvh, Mesh *mesh)
}
}
PBVH *build_mesh(Mesh *mesh)
std::unique_ptr<PBVH> build_mesh(Mesh *mesh)
{
std::unique_ptr<PBVH> pbvh = std::make_unique<PBVH>();
pbvh->header.type = PBVH_FACES;
@@ -784,10 +784,10 @@ PBVH *build_mesh(Mesh *mesh)
pbvh_validate_node_prims(pbvh);
#endif
return pbvh.release();
return pbvh;
}
PBVH *build_grids(const CCGKey *key, Mesh *mesh, SubdivCCG *subdiv_ccg)
std::unique_ptr<PBVH> build_grids(const CCGKey *key, Mesh *mesh, SubdivCCG *subdiv_ccg)
{
std::unique_ptr<PBVH> pbvh = std::make_unique<PBVH>();
pbvh->header.type = PBVH_GRIDS;
@@ -847,12 +847,14 @@ PBVH *build_grids(const CCGKey *key, Mesh *mesh, SubdivCCG *subdiv_ccg)
pbvh_validate_node_prims(pbvh);
#endif
return pbvh.release();
return pbvh;
}
void free(PBVH *pbvh)
} // namespace blender::bke::pbvh
PBVH::~PBVH()
{
for (PBVHNode &node : pbvh->nodes) {
for (PBVHNode &node : this->nodes) {
if (node.flag & PBVH_Leaf) {
if (node.draw_batches) {
blender::draw::pbvh::node_free(node.draw_batches);
@@ -860,13 +862,18 @@ void free(PBVH *pbvh)
}
if (node.flag & (PBVH_Leaf | PBVH_TexLeaf)) {
node_pixels_free(&node);
blender::bke::pbvh::node_pixels_free(&node);
}
}
pixels_free(pbvh);
blender::bke::pbvh::pixels_free(this);
}
delete pbvh;
namespace blender::bke::pbvh {
void free(std::unique_ptr<PBVH> &pbvh)
{
pbvh.reset();
}
static void pbvh_iter_begin(PBVHIter *iter, PBVH &pbvh, FunctionRef<bool(PBVHNode &)> scb)

View File

@@ -2141,10 +2141,10 @@ void update_bmesh_offsets(PBVH &pbvh, int cd_vert_node_offset, int cd_face_node_
pbvh.cd_face_node_offset = cd_face_node_offset;
}
PBVH *build_bmesh(BMesh *bm,
BMLog *log,
const int cd_vert_node_offset,
const int cd_face_node_offset)
std::unique_ptr<PBVH> build_bmesh(BMesh *bm,
BMLog *log,
const int cd_vert_node_offset,
const int cd_face_node_offset)
{
std::unique_ptr<PBVH> pbvh = std::make_unique<PBVH>();
pbvh->header.type = PBVH_BMESH;
@@ -2162,7 +2162,7 @@ PBVH *build_bmesh(BMesh *bm,
pbvh::update_bmesh_offsets(*pbvh, cd_vert_node_offset, cd_face_node_offset);
if (bm->totface == 0) {
return pbvh.release();
return pbvh;
}
/* bounding box array of all faces, no need to recalculate every time. */
@@ -2212,7 +2212,7 @@ PBVH *build_bmesh(BMesh *bm,
pbvh_bmesh_create_nodes_fast_recursive(pbvh.get(), nodeinfo, face_bounds, &rootnode, 0);
BLI_memarena_free(arena);
return pbvh.release();
return pbvh;
}
bool bmesh_update_topology(PBVH &pbvh,

View File

@@ -195,6 +195,8 @@ struct PBVH {
PBVHGPUFormat *vbo_id;
PBVHPixels pixels;
~PBVH();
};
/* pbvh.cc */

View File

@@ -37,7 +37,7 @@ void OVERLAY_sculpt_cache_populate(OVERLAY_Data *vedata, Object *ob)
OVERLAY_PrivateData *pd = vedata->stl->pd;
const DRWContextState *draw_ctx = DRW_context_state_get();
blender::gpu::Batch *sculpt_overlays;
PBVH *pbvh = ob->sculpt->pbvh;
PBVH *pbvh = ob->sculpt->pbvh.get();
const bool use_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d);

View File

@@ -1328,7 +1328,7 @@ static void drw_sculpt_generate_calls(DRWSculptCallbackData *scd)
{
using namespace blender;
/* PBVH should always exist for non-empty meshes, created by depsgraph eval. */
PBVH *pbvh = (scd->ob->sculpt) ? scd->ob->sculpt->pbvh : nullptr;
PBVH *pbvh = (scd->ob->sculpt) ? scd->ob->sculpt->pbvh.get() : nullptr;
if (!pbvh) {
return;
}

View File

@@ -42,7 +42,7 @@ static Vector<SculptBatch> sculpt_batches_get_ex(const Object *ob,
const Span<pbvh::AttributeRequest> attrs)
{
/* PBVH should always exist for non-empty meshes, created by depsgraph eval. */
PBVH *pbvh = ob->sculpt ? ob->sculpt->pbvh : nullptr;
PBVH *pbvh = ob->sculpt ? ob->sculpt->pbvh.get() : nullptr;
if (!pbvh) {
return {};
}

View File

@@ -1556,7 +1556,7 @@ static void sculpt_extend_redraw_rect_previous(Object *ob, rcti *rect)
bool SCULPT_get_redraw_rect(ARegion *region, RegionView3D *rv3d, Object *ob, rcti *rect)
{
using namespace blender;
PBVH *pbvh = ob->sculpt->pbvh;
PBVH *pbvh = ob->sculpt->pbvh.get();
if (!pbvh) {
return false;
}

View File

@@ -46,12 +46,8 @@ void SCULPT_pbvh_clear(Object *ob)
{
using namespace blender;
SculptSession *ss = ob->sculpt;
/* Clear out any existing DM and PBVH. */
if (ss->pbvh) {
bke::pbvh::free(ss->pbvh);
ss->pbvh = nullptr;
}
bke::pbvh::free(ss->pbvh);
BKE_object_free_derived_caches(ob);

View File

@@ -1041,7 +1041,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, UndoSculpt &usculpt)
data.changed_position = changed_position;
data.changed_hide_vert = changed_hide_vert;
data.changed_mask = changed_mask;
data.pbvh = ss->pbvh;
data.pbvh = ss->pbvh.get();
data.modified_grids = modified_grids;
data.modified_position_verts = modified_verts_position;
data.modified_hidden_verts = modified_verts_hide;