Sculpt-dev: new PBVH caching system
* Still experimental * PBVHs are cached in a global map keyed by object name (though at the moment only one pbvh is cached at a time). * ss->pmap is now freed managed by pbvh. * ss->bm is freed by the pbvh cache in some circumstances but is stilled owned by SculptSession.
This commit is contained in:
parent
371a6799c4
commit
307f13aee5
|
@ -767,6 +767,8 @@ typedef struct SculptSession {
|
|||
|
||||
/* PBVH acceleration structure */
|
||||
struct PBVH *pbvh;
|
||||
struct PBVH *last_pbvh;
|
||||
|
||||
bool show_mask;
|
||||
bool show_face_sets;
|
||||
|
||||
|
|
|
@ -80,8 +80,8 @@ BLI_INLINE SculptFaceRef BKE_pbvh_make_fref(intptr_t i)
|
|||
|
||||
typedef struct PBVHTri {
|
||||
int v[3]; // references into PBVHTriBuf->verts
|
||||
intptr_t l[3]; // loops
|
||||
int eflag; // bitmask of which edges in the tri are real edges in the mesh
|
||||
intptr_t l[3]; // loops
|
||||
|
||||
float no[3];
|
||||
SculptFaceRef f;
|
||||
|
@ -323,6 +323,7 @@ void BKE_pbvh_update_offsets(PBVH *pbvh,
|
|||
void BKE_pbvh_free(PBVH *pbvh);
|
||||
|
||||
void BKE_pbvh_set_bm_log(PBVH *pbvh, struct BMLog *log);
|
||||
struct BMLog *BKE_pbvh_get_bm_log(PBVH *pbvh);
|
||||
|
||||
/* update MSculptVerts, doesn't take pbvh argument to allow usage if pbvh doesn't currently exist
|
||||
*/
|
||||
|
@ -1127,3 +1128,17 @@ void BKE_pbvh_pmap_to_edges(PBVH *pbvh,
|
|||
void BKE_pbvh_set_vemap(PBVH *pbvh, struct MeshElemMap *vemap);
|
||||
|
||||
void BKE_pbvh_ignore_uvs_set(PBVH *pbvh, bool value);
|
||||
bool BKE_pbvh_cache_is_valid(const struct Object *ob, const struct Mesh *me, const PBVH *old, int pbvh_type);
|
||||
bool BKE_pbvh_cache(const struct Mesh *me, PBVH *pbvh);
|
||||
PBVH *BKE_pbvh_get_or_free_cached(struct Object *ob, struct Mesh *me, PBVHType pbvh_type);
|
||||
void BKE_pbvh_set_cached(struct Object *ob, PBVH *pbvh);
|
||||
void BKE_pbvh_set_face_areas(PBVH *pbvh, float *face_areas);
|
||||
void BKE_pbvh_set_sculpt_verts(PBVH *pbvh, struct MSculptVert *sverts);
|
||||
void BKE_pbvh_set_pmap(PBVH *pbvh, struct MeshElemMap *pmap, void *pmap_mem);
|
||||
struct MeshElemMap *BKE_pbvh_get_pmap(PBVH *pbvh);
|
||||
struct MeshElemMap *BKE_pbvh_get_pmap_ex(PBVH *pbvh, int **r_mem);
|
||||
void BKE_pbvh_cache_remove(PBVH *pbvh);
|
||||
void BKE_pbvh_set_bmesh(PBVH *pbvh, struct BMesh *bm);
|
||||
void BKE_pbvh_free_bmesh(PBVH *pbvh, struct BMesh *bm);
|
||||
void BKE_pbvh_system_init();
|
||||
void BKE_pbvh_system_exit();
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "BKE_layer.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_pbvh.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
|
@ -76,6 +77,7 @@ void BKE_blender_free(void)
|
|||
DEG_free_node_types();
|
||||
|
||||
BKE_brush_system_exit();
|
||||
BKE_pbvh_system_exit();
|
||||
RE_texture_rng_exit();
|
||||
|
||||
BKE_callback_global_finalize();
|
||||
|
|
|
@ -528,10 +528,19 @@ static void object_blend_write(BlendWriter *writer, ID *id, const void *id_addre
|
|||
ob->mode &= ~OB_MODE_EDIT;
|
||||
}
|
||||
|
||||
PBVH *cached_pbvh = ob->cached_pbvh2;
|
||||
if (!is_undo) {
|
||||
ob->cached_pbvh2 = NULL;
|
||||
}
|
||||
|
||||
/* write LibData */
|
||||
BLO_write_id_struct(writer, Object, id_address, &ob->id);
|
||||
BKE_id_blend_write(writer, &ob->id);
|
||||
|
||||
if (!is_undo) {
|
||||
ob->cached_pbvh2 = cached_pbvh;
|
||||
}
|
||||
|
||||
if (ob->adt) {
|
||||
BKE_animdata_blend_write(writer, ob->adt);
|
||||
}
|
||||
|
@ -4959,6 +4968,8 @@ void BKE_object_runtime_reset_on_copy(Object *object, const int UNUSED(flag))
|
|||
|
||||
runtime->crazyspace_deform_imats = nullptr;
|
||||
runtime->crazyspace_deform_cos = nullptr;
|
||||
|
||||
object->cached_pbvh2 = runtime->cached_pbvh = NULL;
|
||||
}
|
||||
|
||||
void BKE_object_runtime_free_data(Object *object)
|
||||
|
|
|
@ -272,6 +272,8 @@ void BKE_object_sync_to_original(Depsgraph *depsgraph, Object *object)
|
|||
object_orig->transflag = object->transflag;
|
||||
object_orig->flag = object->flag;
|
||||
|
||||
//object_orig->cached_pbvh2 = object->cached_pbvh2;
|
||||
|
||||
/* Copy back error messages from modifiers. */
|
||||
for (ModifierData *md = object->modifiers.first, *md_orig = object_orig->modifiers.first;
|
||||
md != NULL && md_orig != NULL;
|
||||
|
|
|
@ -1448,15 +1448,16 @@ static void sculptsession_free_pbvh(Object *object)
|
|||
}
|
||||
|
||||
if (ss->pbvh) {
|
||||
BKE_pbvh_free(ss->pbvh);
|
||||
BKE_pbvh_set_cached(object, ss->pbvh);
|
||||
ss->pbvh = NULL;
|
||||
}
|
||||
else {
|
||||
MEM_SAFE_FREE(ss->pmap);
|
||||
MEM_SAFE_FREE(ss->pmap_mem);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(ss->face_areas);
|
||||
|
||||
MEM_SAFE_FREE(ss->pmap);
|
||||
MEM_SAFE_FREE(ss->pmap_mem);
|
||||
|
||||
MEM_SAFE_FREE(ss->epmap);
|
||||
MEM_SAFE_FREE(ss->epmap_mem);
|
||||
|
||||
|
@ -1516,21 +1517,24 @@ void BKE_sculptsession_free(Object *ob)
|
|||
SCULPT_on_sculptsession_bmesh_free(ss);
|
||||
|
||||
BKE_sculptsession_bm_to_me(ob, true);
|
||||
BM_mesh_free(ss->bm);
|
||||
ss->bm = NULL;
|
||||
// BM_mesh_free(ss->bm);
|
||||
}
|
||||
|
||||
CustomData_free(&ss->temp_vdata, ss->temp_vdata_elems);
|
||||
CustomData_free(&ss->temp_pdata, ss->temp_pdata_elems);
|
||||
|
||||
if (!ss->pbvh) {
|
||||
MEM_SAFE_FREE(ss->pmap);
|
||||
MEM_SAFE_FREE(ss->pmap_mem);
|
||||
}
|
||||
|
||||
sculptsession_free_pbvh(ob);
|
||||
|
||||
for (int i = 0; i < SCULPT_SCL_LAYER_MAX; i++) {
|
||||
MEM_SAFE_FREE(ss->custom_layers[i]);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(ss->pmap);
|
||||
MEM_SAFE_FREE(ss->pmap_mem);
|
||||
|
||||
MEM_SAFE_FREE(ss->epmap);
|
||||
MEM_SAFE_FREE(ss->epmap_mem);
|
||||
|
||||
|
@ -1822,16 +1826,26 @@ static void sculpt_update_object(Depsgraph *depsgraph,
|
|||
BKE_pbvh_face_sets_color_set(ss->pbvh, me->face_sets_color_seed, me->face_sets_color_default);
|
||||
|
||||
if (need_pmap && ob->type == OB_MESH && !ss->pmap) {
|
||||
BKE_mesh_vert_poly_map_create(&ss->pmap,
|
||||
&ss->pmap_mem,
|
||||
me->mvert,
|
||||
me->medge,
|
||||
me->mpoly,
|
||||
me->mloop,
|
||||
me->totvert,
|
||||
me->totpoly,
|
||||
me->totloop,
|
||||
false);
|
||||
if (!ss->pmap && ss->pbvh) {
|
||||
ss->pmap = BKE_pbvh_get_pmap_ex(ss->pbvh, &ss->pmap_mem);
|
||||
}
|
||||
|
||||
if (!ss->pmap) {
|
||||
BKE_mesh_vert_poly_map_create(&ss->pmap,
|
||||
&ss->pmap_mem,
|
||||
me->mvert,
|
||||
me->medge,
|
||||
me->mpoly,
|
||||
me->mloop,
|
||||
me->totvert,
|
||||
me->totpoly,
|
||||
me->totloop,
|
||||
false);
|
||||
|
||||
if (ss->pbvh) {
|
||||
BKE_pbvh_set_pmap(ss->pbvh, ss->pmap, ss->pmap_mem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pbvh_show_mask_set(ss->pbvh, ss->show_mask);
|
||||
|
@ -2396,42 +2410,72 @@ void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object)
|
|||
DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
|
||||
}
|
||||
|
||||
static PBVH *build_pbvh_for_dynamic_topology(Object *ob, bool update_sculptverts)
|
||||
ATTR_NO_OPT static PBVH *build_pbvh_for_dynamic_topology(Object *ob, bool update_sculptverts)
|
||||
{
|
||||
PBVH *pbvh = BKE_pbvh_new();
|
||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
|
||||
PBVH *pbvh = BKE_pbvh_get_or_free_cached(ob, me, PBVH_BMESH);
|
||||
if (!pbvh) {
|
||||
pbvh = BKE_pbvh_new();
|
||||
|
||||
BKE_pbvh_build_bmesh(pbvh,
|
||||
BKE_object_get_original_mesh(ob),
|
||||
ob->sculpt->bm,
|
||||
ob->sculpt->bm_smooth_shading,
|
||||
ob->sculpt->bm_log,
|
||||
ob->sculpt->cd_vert_node_offset,
|
||||
ob->sculpt->cd_face_node_offset,
|
||||
ob->sculpt->cd_sculpt_vert,
|
||||
ob->sculpt->cd_face_areas,
|
||||
ob->sculpt->fast_draw,
|
||||
update_sculptverts);
|
||||
}
|
||||
else {
|
||||
BMesh *bm = BKE_pbvh_get_bmesh(pbvh);
|
||||
|
||||
if (bm && bm != ob->sculpt->bm) {
|
||||
printf("%s: ss->bm != bm!\n", __func__);
|
||||
|
||||
ob->sculpt->bm = bm;
|
||||
|
||||
if (ob->sculpt->bm_log) {
|
||||
BM_log_set_bm(bm, ob->sculpt->bm_log);
|
||||
}
|
||||
}
|
||||
else if (!bm) {
|
||||
BKE_pbvh_set_bmesh(pbvh, ob->sculpt->bm);
|
||||
}
|
||||
}
|
||||
|
||||
if (ob->sculpt->bm_log) {
|
||||
BKE_pbvh_set_bm_log(pbvh, ob->sculpt->bm_log);
|
||||
}
|
||||
|
||||
BKE_pbvh_set_symmetry(pbvh, 0, (int)BKE_get_fset_boundary_symflag(ob));
|
||||
|
||||
BKE_pbvh_build_bmesh(pbvh,
|
||||
BKE_object_get_original_mesh(ob),
|
||||
ob->sculpt->bm,
|
||||
ob->sculpt->bm_smooth_shading,
|
||||
ob->sculpt->bm_log,
|
||||
ob->sculpt->cd_vert_node_offset,
|
||||
ob->sculpt->cd_face_node_offset,
|
||||
ob->sculpt->cd_sculpt_vert,
|
||||
ob->sculpt->cd_face_areas,
|
||||
ob->sculpt->fast_draw,
|
||||
update_sculptverts);
|
||||
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
|
||||
pbvh_show_face_sets_set(pbvh, false);
|
||||
|
||||
BKE_pbvh_set_cached(ob, pbvh);
|
||||
|
||||
return pbvh;
|
||||
}
|
||||
|
||||
static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool respect_hide)
|
||||
ATTR_NO_OPT static PBVH *build_pbvh_from_regular_mesh(Object *ob,
|
||||
Mesh *me_eval_deform,
|
||||
bool respect_hide)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop);
|
||||
PBVH *pbvh = BKE_pbvh_new();
|
||||
BKE_pbvh_respect_hide_set(pbvh, respect_hide);
|
||||
|
||||
MLoopTri *looptri = MEM_malloc_arrayN(looptris_num, sizeof(*looptri), __func__);
|
||||
PBVH *pbvh = BKE_pbvh_get_or_free_cached(ob, me, PBVH_FACES);
|
||||
|
||||
BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
|
||||
struct MeshElemMap *BKE_pbvh_get_pmap_ex(PBVH * pbvh, int **r_mem);
|
||||
|
||||
BKE_sculpt_sync_face_set_visibility(me, NULL);
|
||||
if (!ss->pmap && pbvh) {
|
||||
ss->pmap = BKE_pbvh_get_pmap_ex(pbvh, &ss->pmap_mem);
|
||||
}
|
||||
|
||||
if (!ss->pmap) {
|
||||
BKE_mesh_vert_poly_map_create(&ss->pmap,
|
||||
|
@ -2446,29 +2490,43 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
|
|||
false);
|
||||
}
|
||||
|
||||
if (!pbvh) {
|
||||
pbvh = BKE_pbvh_new();
|
||||
|
||||
MLoopTri *looptri = MEM_malloc_arrayN(looptris_num, sizeof(*looptri), __func__);
|
||||
|
||||
BKE_pbvh_respect_hide_set(pbvh, respect_hide);
|
||||
BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
|
||||
BKE_sculpt_sync_face_set_visibility(me, NULL);
|
||||
|
||||
BKE_pbvh_build_mesh(pbvh,
|
||||
me,
|
||||
me->mpoly,
|
||||
me->mloop,
|
||||
me->mvert,
|
||||
ss->mdyntopo_verts,
|
||||
me->totvert,
|
||||
&me->vdata,
|
||||
&me->ldata,
|
||||
&me->pdata,
|
||||
looptri,
|
||||
looptris_num,
|
||||
ss->fast_draw,
|
||||
ss->face_areas,
|
||||
ss->pmap);
|
||||
|
||||
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
|
||||
pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
|
||||
}
|
||||
|
||||
BKE_pbvh_set_pmap(pbvh, ss->pmap, ss->pmap_mem);
|
||||
BKE_sculptsession_check_sculptverts(ob->sculpt, pbvh, me->totvert);
|
||||
|
||||
MEM_SAFE_FREE(ss->face_areas);
|
||||
ss->face_areas = MEM_calloc_arrayN(me->totpoly, sizeof(float) * 2, "ss->face_areas");
|
||||
|
||||
BKE_pbvh_build_mesh(pbvh,
|
||||
me,
|
||||
me->mpoly,
|
||||
me->mloop,
|
||||
me->mvert,
|
||||
ss->mdyntopo_verts,
|
||||
me->totvert,
|
||||
&me->vdata,
|
||||
&me->ldata,
|
||||
&me->pdata,
|
||||
looptri,
|
||||
looptris_num,
|
||||
ss->fast_draw,
|
||||
ss->face_areas,
|
||||
ss->pmap);
|
||||
|
||||
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
|
||||
pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
|
||||
BKE_pbvh_set_face_areas(pbvh, ss->face_areas);
|
||||
BKE_pbvh_set_sculpt_verts(pbvh, ss->mdyntopo_verts);
|
||||
|
||||
const bool is_deformed = check_sculpt_object_deformed(ob, true);
|
||||
if (is_deformed && me_eval_deform != NULL) {
|
||||
|
@ -2478,6 +2536,8 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
|
|||
MEM_freeN(v_cos);
|
||||
}
|
||||
|
||||
BKE_pbvh_set_cached(ob, pbvh);
|
||||
|
||||
return pbvh;
|
||||
}
|
||||
|
||||
|
@ -2487,30 +2547,40 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect
|
|||
|
||||
CCGKey key;
|
||||
BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg);
|
||||
PBVH *pbvh = BKE_pbvh_new();
|
||||
BKE_pbvh_respect_hide_set(pbvh, respect_hide);
|
||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||
|
||||
PBVH *pbvh = BKE_pbvh_get_or_free_cached(ob, me, PBVH_GRIDS);
|
||||
Mesh *base_mesh = BKE_mesh_from_object(ob);
|
||||
BKE_sculpt_sync_face_set_visibility(base_mesh, subdiv_ccg);
|
||||
|
||||
int totgridfaces = base_mesh->totpoly * (key.grid_size - 1) * (key.grid_size - 1);
|
||||
|
||||
MEM_SAFE_FREE(ss->face_areas);
|
||||
ss->face_areas = MEM_calloc_arrayN(totgridfaces, sizeof(float) * 2, "ss->face_areas");
|
||||
|
||||
BKE_sculpt_sync_face_set_visibility(base_mesh, subdiv_ccg);
|
||||
|
||||
if (!pbvh) {
|
||||
pbvh = BKE_pbvh_new();
|
||||
|
||||
BKE_pbvh_respect_hide_set(pbvh, respect_hide);
|
||||
|
||||
BKE_pbvh_build_grids(pbvh,
|
||||
subdiv_ccg->grids,
|
||||
subdiv_ccg->num_grids,
|
||||
&key,
|
||||
(void **)subdiv_ccg->grid_faces,
|
||||
subdiv_ccg->grid_flag_mats,
|
||||
subdiv_ccg->grid_hidden,
|
||||
ob->sculpt->fast_draw,
|
||||
ss->face_areas);
|
||||
}
|
||||
|
||||
BKE_pbvh_set_face_areas(pbvh, ss->face_areas);
|
||||
BKE_pbvh_set_sculpt_verts(pbvh, ss->mdyntopo_verts);
|
||||
|
||||
CustomData_reset(&ob->sculpt->temp_vdata);
|
||||
CustomData_reset(&ob->sculpt->temp_pdata);
|
||||
|
||||
BKE_pbvh_build_grids(pbvh,
|
||||
subdiv_ccg->grids,
|
||||
subdiv_ccg->num_grids,
|
||||
&key,
|
||||
(void **)subdiv_ccg->grid_faces,
|
||||
subdiv_ccg->grid_flag_mats,
|
||||
subdiv_ccg->grid_hidden,
|
||||
ob->sculpt->fast_draw,
|
||||
ss->face_areas);
|
||||
|
||||
ss->temp_vdata_elems = BKE_pbvh_get_grid_num_vertices(pbvh);
|
||||
ss->temp_pdata_elems = ss->totfaces;
|
||||
|
||||
|
@ -2519,6 +2589,8 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect
|
|||
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
|
||||
pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
|
||||
|
||||
BKE_pbvh_set_cached(ob, pbvh);
|
||||
|
||||
return pbvh;
|
||||
}
|
||||
|
||||
|
@ -2655,25 +2727,36 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
|||
bool is_dyntopo = (mesh_orig->flag & ME_SCULPT_DYNAMIC_TOPOLOGY);
|
||||
|
||||
if (is_dyntopo) {
|
||||
BMesh *bm = BKE_sculptsession_empty_bmesh_create();
|
||||
/* check if the pbvh cache has a valid bmesh */
|
||||
pbvh = BKE_pbvh_get_or_free_cached(ob, mesh_orig, PBVH_BMESH);
|
||||
BMesh *bm = NULL;
|
||||
|
||||
if (pbvh) {
|
||||
bm = BKE_pbvh_get_bmesh(pbvh);
|
||||
}
|
||||
|
||||
if (!bm) {
|
||||
bm = BKE_sculptsession_empty_bmesh_create();
|
||||
|
||||
BM_mesh_bm_from_me(NULL,
|
||||
bm,
|
||||
mesh_orig,
|
||||
(&(struct BMeshFromMeshParams){.calc_face_normal = true,
|
||||
.use_shapekey = true,
|
||||
.active_shapekey = ob->shapenr,
|
||||
.create_shapekey_layers = true,
|
||||
.ignore_id_layers = false,
|
||||
.copy_temp_cdlayers = true,
|
||||
|
||||
.cd_mask_extra = CD_MASK_DYNTOPO_VERT}));
|
||||
}
|
||||
|
||||
ob->sculpt->bm = bm;
|
||||
|
||||
BM_mesh_bm_from_me(NULL,
|
||||
bm,
|
||||
mesh_orig,
|
||||
(&(struct BMeshFromMeshParams){.calc_face_normal = true,
|
||||
.use_shapekey = true,
|
||||
.active_shapekey = ob->shapenr,
|
||||
.create_shapekey_layers = true,
|
||||
.ignore_id_layers = false,
|
||||
.copy_temp_cdlayers = true,
|
||||
|
||||
.cd_mask_extra = CD_MASK_DYNTOPO_VERT}));
|
||||
|
||||
BKE_sculptsession_bmesh_add_layers(ob);
|
||||
SCULPT_undo_ensure_bmlog(ob);
|
||||
|
||||
/* Note build_pbvh_for_dynamic_topology respects the pbvh cache. */
|
||||
pbvh = build_pbvh_for_dynamic_topology(ob, true);
|
||||
|
||||
BKE_sculptsession_update_attr_refs(ob);
|
||||
|
@ -3295,11 +3378,11 @@ static bool sculpt_attr_get_layer(SculptSession *ss,
|
|||
}
|
||||
|
||||
bool BKE_sculptsession_attr_get_layer(Object *ob,
|
||||
AttributeDomain domain,
|
||||
int proptype,
|
||||
const char *name,
|
||||
SculptCustomLayer *scl,
|
||||
SculptLayerParams *params)
|
||||
AttributeDomain domain,
|
||||
int proptype,
|
||||
const char *name,
|
||||
SculptCustomLayer *scl,
|
||||
SculptLayerParams *params)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
|
|
|
@ -9,10 +9,13 @@
|
|||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLI_alloca.h"
|
||||
#include "BLI_array.h"
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_rand.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_task.h"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
|
@ -24,10 +27,13 @@
|
|||
#include "BKE_ccg.h"
|
||||
#include "BKE_mesh.h" /* for BKE_mesh_calc_normals */
|
||||
#include "BKE_mesh_mapping.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_pbvh.h"
|
||||
#include "BKE_subdiv_ccg.h"
|
||||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "PIL_time.h"
|
||||
|
||||
#include "GPU_buffers.h"
|
||||
|
@ -633,6 +639,16 @@ static void pbvh_build(PBVH *pbvh, BB *cb, BBC *prim_bbc, int totprim)
|
|||
build_sub(pbvh, 0, cb, prim_bbc, 0, totprim, 0);
|
||||
}
|
||||
|
||||
void BKE_pbvh_set_face_areas(PBVH *pbvh, float *face_areas)
|
||||
{
|
||||
pbvh->face_areas = face_areas;
|
||||
}
|
||||
|
||||
void BKE_pbvh_set_sculpt_verts(PBVH *pbvh, MSculptVert *sverts)
|
||||
{
|
||||
pbvh->mdyntopo_verts = sverts;
|
||||
}
|
||||
|
||||
void BKE_pbvh_build_mesh(PBVH *pbvh,
|
||||
Mesh *mesh,
|
||||
const MPoly *mpoly,
|
||||
|
@ -776,7 +792,7 @@ PBVH *BKE_pbvh_new(void)
|
|||
return pbvh;
|
||||
}
|
||||
|
||||
void BKE_pbvh_free(PBVH *pbvh)
|
||||
ATTR_NO_OPT void BKE_pbvh_free(PBVH *pbvh)
|
||||
{
|
||||
for (int i = 0; i < pbvh->totnode; i++) {
|
||||
PBVHNode *node = &pbvh->nodes[i];
|
||||
|
@ -832,6 +848,9 @@ void BKE_pbvh_free(PBVH *pbvh)
|
|||
|
||||
MEM_SAFE_FREE(pbvh->vert_bitmap);
|
||||
|
||||
MEM_SAFE_FREE(pbvh->pmap);
|
||||
MEM_SAFE_FREE(pbvh->pmap_mem);
|
||||
|
||||
MEM_freeN(pbvh);
|
||||
}
|
||||
|
||||
|
@ -1148,9 +1167,8 @@ static void pbvh_update_normals_clear_task_cb(void *__restrict userdata,
|
|||
}
|
||||
}
|
||||
|
||||
static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
|
||||
const int n,
|
||||
const TaskParallelTLS *__restrict UNUSED(tls))
|
||||
ATTR_NO_OPT static void pbvh_update_normals_accum_task_cb(
|
||||
void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
|
||||
{
|
||||
PBVHUpdateData *data = userdata;
|
||||
|
||||
|
@ -1564,6 +1582,9 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
|
|||
|
||||
GPU_pbvh_mesh_buffers_update(node->draw_buffers,
|
||||
pbvh->verts,
|
||||
pbvh->mloop,
|
||||
pbvh->mpoly,
|
||||
pbvh->looptri,
|
||||
vdata,
|
||||
ldata,
|
||||
CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK),
|
||||
|
@ -3568,6 +3589,8 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
|
|||
pbvh_bmesh_check_other_verts(node);
|
||||
}
|
||||
|
||||
vi->mverts = NULL;
|
||||
|
||||
vi->bi = 0;
|
||||
vi->bm_cur_set = node->bm_unique_verts;
|
||||
vi->bm_unique_verts = node->bm_unique_verts;
|
||||
|
@ -4765,3 +4788,312 @@ void BKE_pbvh_ignore_uvs_set(PBVH *pbvh, bool value)
|
|||
|
||||
pbvh_boundaries_flag_update(pbvh);
|
||||
}
|
||||
|
||||
bool BKE_pbvh_cache(const struct Mesh *me, PBVH *pbvh)
|
||||
{
|
||||
memset(&pbvh->cached_data, 0, sizeof(pbvh->cached_data));
|
||||
|
||||
switch (pbvh->type) {
|
||||
case PBVH_BMESH:
|
||||
if (!pbvh->bm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pbvh->cached_data.bm = pbvh->bm;
|
||||
|
||||
pbvh->cached_data.vdata = pbvh->bm->vdata;
|
||||
pbvh->cached_data.edata = pbvh->bm->edata;
|
||||
pbvh->cached_data.ldata = pbvh->bm->ldata;
|
||||
pbvh->cached_data.pdata = pbvh->bm->pdata;
|
||||
|
||||
pbvh->cached_data.totvert = pbvh->bm->totvert;
|
||||
pbvh->cached_data.totedge = pbvh->bm->totedge;
|
||||
pbvh->cached_data.totloop = pbvh->bm->totloop;
|
||||
pbvh->cached_data.totpoly = pbvh->bm->totface;
|
||||
break;
|
||||
case PBVH_GRIDS:
|
||||
pbvh->cached_data.vdata = me->vdata;
|
||||
pbvh->cached_data.edata = me->edata;
|
||||
pbvh->cached_data.ldata = me->ldata;
|
||||
pbvh->cached_data.pdata = me->pdata;
|
||||
|
||||
int grid_side = pbvh->gridkey.grid_size;
|
||||
|
||||
pbvh->cached_data.totvert = pbvh->totgrid * grid_side * grid_side;
|
||||
pbvh->cached_data.totedge = me->totedge;
|
||||
pbvh->cached_data.totloop = me->totloop;
|
||||
pbvh->cached_data.totpoly = pbvh->totgrid * (grid_side - 1) * (grid_side - 1);
|
||||
break;
|
||||
case PBVH_FACES:
|
||||
pbvh->cached_data.vdata = me->vdata;
|
||||
pbvh->cached_data.edata = me->edata;
|
||||
pbvh->cached_data.ldata = me->ldata;
|
||||
pbvh->cached_data.pdata = me->pdata;
|
||||
|
||||
pbvh->cached_data.totvert = me->totvert;
|
||||
pbvh->cached_data.totedge = me->totedge;
|
||||
pbvh->cached_data.totloop = me->totloop;
|
||||
pbvh->cached_data.totpoly = me->totpoly;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool customdata_is_same(const CustomData *a, const CustomData *b)
|
||||
{
|
||||
return memcmp(a, b, sizeof(CustomData)) == 0;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT bool BKE_pbvh_cache_is_valid(const Object *ob,
|
||||
const Mesh *me,
|
||||
const PBVH *pbvh,
|
||||
PBVHType pbvh_type)
|
||||
{
|
||||
if (pbvh->type != pbvh_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
int totvert, totedge, totloop, totpoly;
|
||||
const CustomData *vdata, *edata, *ldata, *pdata;
|
||||
|
||||
switch (pbvh_type) {
|
||||
case PBVH_BMESH:
|
||||
if (!pbvh->bm || pbvh->bm != pbvh->cached_data.bm) {
|
||||
return false;
|
||||
}
|
||||
|
||||
totvert = pbvh->bm->totvert;
|
||||
totedge = pbvh->bm->totedge;
|
||||
totloop = pbvh->bm->totloop;
|
||||
totpoly = pbvh->bm->totface;
|
||||
|
||||
vdata = &pbvh->bm->vdata;
|
||||
edata = &pbvh->bm->edata;
|
||||
ldata = &pbvh->bm->ldata;
|
||||
pdata = &pbvh->bm->pdata;
|
||||
break;
|
||||
case PBVH_FACES:
|
||||
totvert = me->totvert;
|
||||
totedge = me->totedge;
|
||||
totloop = me->totloop;
|
||||
totpoly = me->totpoly;
|
||||
|
||||
vdata = &me->vdata;
|
||||
edata = &me->edata;
|
||||
ldata = &me->ldata;
|
||||
pdata = &me->pdata;
|
||||
break;
|
||||
case PBVH_GRIDS: {
|
||||
MultiresModifierData *mmd = NULL;
|
||||
|
||||
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
|
||||
if (md->type == eModifierType_Multires) {
|
||||
mmd = (MultiresModifierData *)md;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mmd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int grid_side = 1 + (1 << (mmd->sculptlvl - 1));
|
||||
|
||||
totvert = me->totloop * grid_side * grid_side;
|
||||
totedge = me->totedge;
|
||||
totloop = me->totloop;
|
||||
totpoly = me->totloop * (grid_side - 1) * (grid_side - 1);
|
||||
|
||||
vdata = &me->vdata;
|
||||
edata = &me->edata;
|
||||
ldata = &me->ldata;
|
||||
pdata = &me->pdata;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ok = ok && totvert == pbvh->cached_data.totvert;
|
||||
ok = ok && totedge == pbvh->cached_data.totedge;
|
||||
ok = ok && totloop == pbvh->cached_data.totloop;
|
||||
ok = ok && totpoly == pbvh->cached_data.totpoly;
|
||||
|
||||
ok = ok && customdata_is_same(vdata, &pbvh->cached_data.vdata);
|
||||
ok = ok && customdata_is_same(edata, &pbvh->cached_data.edata);
|
||||
ok = ok && customdata_is_same(ldata, &pbvh->cached_data.ldata);
|
||||
ok = ok && customdata_is_same(pdata, &pbvh->cached_data.pdata);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
GHash *cached_pbvhs = NULL;
|
||||
static void pbvh_clear_cached_pbvhs(PBVH *exclude)
|
||||
{
|
||||
GHashIterator iter;
|
||||
GHASH_ITER (iter, cached_pbvhs) {
|
||||
PBVH *pbvh = BLI_ghashIterator_getValue(&iter);
|
||||
|
||||
if (pbvh != exclude) {
|
||||
if (pbvh->bm) {
|
||||
BM_mesh_free(pbvh->bm);
|
||||
}
|
||||
|
||||
BKE_pbvh_free(pbvh);
|
||||
}
|
||||
}
|
||||
|
||||
BLI_ghash_clear(cached_pbvhs, MEM_freeN, NULL);
|
||||
}
|
||||
|
||||
void BKE_pbvh_clear_cache(PBVH *preserve)
|
||||
{
|
||||
pbvh_clear_cached_pbvhs(NULL);
|
||||
}
|
||||
|
||||
ATTR_NO_OPT PBVH *BKE_pbvh_get_or_free_cached(Object *ob, Mesh *me, PBVHType pbvh_type)
|
||||
{
|
||||
Object *ob_orig = DEG_get_original_object(ob);
|
||||
|
||||
PBVH *pbvh = BLI_ghash_lookup(cached_pbvhs, ob_orig->id.name);
|
||||
|
||||
if (!pbvh) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (BKE_pbvh_cache_is_valid(ob, me, pbvh, pbvh_type)) {
|
||||
switch (pbvh_type) {
|
||||
case PBVH_BMESH:
|
||||
break;
|
||||
case PBVH_FACES:
|
||||
pbvh->vert_normals = BKE_mesh_vertex_normals_for_write(me);
|
||||
case PBVH_GRIDS:
|
||||
pbvh->verts = me->mvert;
|
||||
pbvh->mloop = me->mloop;
|
||||
pbvh->mpoly = me->mpoly;
|
||||
pbvh->vdata = &me->vdata;
|
||||
pbvh->ldata = &me->ldata;
|
||||
pbvh->pdata = &me->pdata;
|
||||
|
||||
pbvh->face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return pbvh;
|
||||
}
|
||||
|
||||
pbvh_clear_cached_pbvhs(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BKE_pbvh_set_cached(Object *ob, PBVH *pbvh)
|
||||
{
|
||||
Object *ob_orig = DEG_get_original_object(ob);
|
||||
|
||||
PBVH *exist = BLI_ghash_lookup(cached_pbvhs, ob_orig->id.name);
|
||||
|
||||
if (!exist || exist != pbvh) {
|
||||
pbvh_clear_cached_pbvhs(pbvh);
|
||||
BLI_ghash_insert(cached_pbvhs, BLI_strdup(ob_orig->id.name), pbvh);
|
||||
}
|
||||
|
||||
BKE_pbvh_cache(BKE_object_get_original_mesh(ob_orig), pbvh);
|
||||
}
|
||||
|
||||
struct MeshElemMap *BKE_pbvh_get_pmap(PBVH *pbvh)
|
||||
{
|
||||
return pbvh->pmap;
|
||||
}
|
||||
|
||||
struct MeshElemMap *BKE_pbvh_get_pmap_ex(PBVH *pbvh, int **r_mem)
|
||||
{
|
||||
if (r_mem) {
|
||||
*r_mem = (int *)pbvh->pmap_mem;
|
||||
}
|
||||
|
||||
return pbvh->pmap;
|
||||
}
|
||||
|
||||
void BKE_pbvh_set_pmap(PBVH *pbvh, struct MeshElemMap *pmap, void *pmap_mem)
|
||||
{
|
||||
pbvh->pmap = pmap;
|
||||
pbvh->pmap_mem = pmap_mem;
|
||||
}
|
||||
|
||||
/** Does not free pbvh itself. */
|
||||
void BKE_pbvh_cache_remove(PBVH *pbvh)
|
||||
{
|
||||
char **keys = NULL;
|
||||
BLI_array_staticdeclare(keys, 32);
|
||||
|
||||
GHashIterator iter;
|
||||
GHASH_ITER (iter, cached_pbvhs) {
|
||||
PBVH *pbvh2 = BLI_ghashIterator_getValue(&iter);
|
||||
|
||||
if (pbvh2 == pbvh) {
|
||||
BLI_array_append(keys, (char *)BLI_ghashIterator_getKey(&iter));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < BLI_array_len(keys); i++) {
|
||||
BLI_ghash_remove(cached_pbvhs, keys[i], MEM_freeN, NULL);
|
||||
}
|
||||
|
||||
BLI_array_free(keys);
|
||||
}
|
||||
|
||||
void BKE_pbvh_set_bmesh(PBVH *pbvh, BMesh *bm)
|
||||
{
|
||||
pbvh->bm = bm;
|
||||
}
|
||||
|
||||
void BKE_pbvh_free_bmesh(PBVH *pbvh, BMesh *bm)
|
||||
{
|
||||
if (pbvh) {
|
||||
pbvh->bm = NULL;
|
||||
}
|
||||
|
||||
BM_mesh_free(bm);
|
||||
|
||||
GHashIterator iter;
|
||||
char **keys = NULL;
|
||||
BLI_array_staticdeclare(keys, 32);
|
||||
|
||||
GHASH_ITER (iter, cached_pbvhs) {
|
||||
PBVH *pbvh2 = BLI_ghashIterator_getValue(&iter);
|
||||
|
||||
if (pbvh2->bm == bm) {
|
||||
pbvh2->bm = NULL;
|
||||
|
||||
if (pbvh2 != pbvh) {
|
||||
BKE_pbvh_free(pbvh2);
|
||||
}
|
||||
|
||||
BLI_array_append(keys, BLI_ghashIterator_getKey(&iter));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < BLI_array_len(keys); i++) {
|
||||
BLI_ghash_remove(cached_pbvhs, keys[i], MEM_freeN, NULL);
|
||||
}
|
||||
|
||||
BLI_array_free(keys);
|
||||
}
|
||||
|
||||
struct BMLog *BKE_pbvh_get_bm_log(PBVH *pbvh)
|
||||
{
|
||||
return pbvh->bm_log;
|
||||
}
|
||||
|
||||
void BKE_pbvh_system_init()
|
||||
{
|
||||
cached_pbvhs = BLI_ghash_str_new("pbvh cache ghash");
|
||||
}
|
||||
|
||||
void BKE_pbvh_system_exit()
|
||||
{
|
||||
pbvh_clear_cached_pbvhs(NULL);
|
||||
BLI_ghash_free(cached_pbvhs, NULL, NULL);
|
||||
}
|
||||
|
|
|
@ -2390,8 +2390,15 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
|
|||
|
||||
pbvh->depth_limit = 28;
|
||||
|
||||
int tottri = poly_to_tri_count(bm->totface, bm->totloop);
|
||||
|
||||
/* TODO: choose leaf limit better */
|
||||
pbvh->leaf_limit = 1000;
|
||||
if (tottri > 4 * 1000 * 1000) {
|
||||
pbvh->leaf_limit = 10000;
|
||||
}
|
||||
else {
|
||||
pbvh->leaf_limit = 1000;
|
||||
}
|
||||
|
||||
BMIter iter;
|
||||
BMVert *v;
|
||||
|
@ -2603,7 +2610,7 @@ ATTR_NO_OPT bool BKE_pbvh_bmesh_update_topology_nodes(PBVH *pbvh,
|
|||
updatePBVH,
|
||||
mask_cb,
|
||||
mask_cb_data,
|
||||
0, //is_snake_hook ? 40960 : 0,
|
||||
0, // is_snake_hook ? 40960 : 0,
|
||||
disable_surface_relax,
|
||||
is_snake_hook);
|
||||
|
||||
|
|
|
@ -146,6 +146,7 @@ struct PBVH {
|
|||
|
||||
/* Mesh data */
|
||||
struct MeshElemMap *pmap, *vemap;
|
||||
void *pmap_mem;
|
||||
const struct Mesh *mesh;
|
||||
|
||||
/* Note: Normals are not const because they can be updated for drawing by sculpt code. */
|
||||
|
@ -220,6 +221,16 @@ struct PBVH {
|
|||
|
||||
int balance_counter;
|
||||
int stroke_id; // used to keep origdata up to date in PBVH_BMESH
|
||||
|
||||
bool is_cached;
|
||||
|
||||
/* This data is for validating cached PBVHs;
|
||||
* it is not guaranteed to be valid in any way! */
|
||||
struct {
|
||||
CustomData vdata, edata, ldata, pdata;
|
||||
int totvert, totedge, totloop, totpoly;
|
||||
struct BMesh *bm;
|
||||
} cached_data;
|
||||
};
|
||||
|
||||
/* pbvh.c */
|
||||
|
|
|
@ -3550,7 +3550,7 @@ typedef struct AreaNormalCenterTLSData {
|
|||
int count_co[2];
|
||||
} AreaNormalCenterTLSData;
|
||||
|
||||
static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
|
||||
ATTR_NO_OPT static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
|
||||
const int n,
|
||||
const TaskParallelTLS *__restrict tls)
|
||||
{
|
||||
|
@ -3816,7 +3816,7 @@ void SCULPT_calc_area_normal(
|
|||
SCULPT_pbvh_calc_area_normal(brush, ob, nodes, totnode, true, r_area_no);
|
||||
}
|
||||
|
||||
bool SCULPT_pbvh_calc_area_normal(const Brush *brush,
|
||||
ATTR_NO_OPT bool SCULPT_pbvh_calc_area_normal(const Brush *brush,
|
||||
Object *ob,
|
||||
PBVHNode **nodes,
|
||||
int totnode,
|
||||
|
@ -5604,7 +5604,7 @@ static void SCULPT_run_command(
|
|||
BKE_ptcache_object_reset(CTX_data_scene(C), ob, PTCACHE_RESET_OUTDATED);
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
BKE_scene_graph_update_tagged(CTX_data_ensure_evaluated_depsgraph(C), CTX_data_main(C));
|
||||
SCULPT_pbvh_clear(ob);
|
||||
SCULPT_pbvh_clear(ob, false);
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
|
||||
if (cmd->tool == SCULPT_TOOL_ARRAY) {
|
||||
|
@ -7468,7 +7468,7 @@ float SCULPT_raycast_init(ViewContext *vc,
|
|||
* also updates the active vertex and cursor related data of the SculptSession using the mouse
|
||||
* position
|
||||
*/
|
||||
bool SCULPT_cursor_geometry_info_update(bContext *C,
|
||||
ATTR_NO_OPT bool SCULPT_cursor_geometry_info_update(bContext *C,
|
||||
SculptCursorGeometryInfo *out,
|
||||
const float mouse[2],
|
||||
bool use_sampled_normal,
|
||||
|
@ -8236,7 +8236,7 @@ static void sculpt_stroke_update_step(bContext *C,
|
|||
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
BKE_scene_graph_update_tagged(CTX_data_ensure_evaluated_depsgraph(C), CTX_data_main(C));
|
||||
SCULPT_pbvh_clear(ob);
|
||||
SCULPT_pbvh_clear(ob, false);
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
|
||||
|
||||
|
@ -8678,6 +8678,11 @@ void ED_object_sculptmode_exit_ex(Main *bmain, Depsgraph *depsgraph, Scene *scen
|
|||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
}
|
||||
|
||||
/* Leave sculpt mode. We do this here to prevent
|
||||
* the depsgraph spawning a PBVH_FACES after disabling
|
||||
* dynamic topology below. */
|
||||
ob->mode &= ~mode_flag;
|
||||
|
||||
if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
|
||||
/* Dynamic topology must be disabled before exiting sculpt
|
||||
* mode to ensure the undo stack stays in a consistent
|
||||
|
@ -8688,9 +8693,6 @@ void ED_object_sculptmode_exit_ex(Main *bmain, Depsgraph *depsgraph, Scene *scen
|
|||
me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
|
||||
}
|
||||
|
||||
/* Leave sculpt mode. */
|
||||
ob->mode &= ~mode_flag;
|
||||
|
||||
BKE_sculptsession_free(ob);
|
||||
|
||||
paint_cursor_delete_textures();
|
||||
|
|
|
@ -206,7 +206,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
SCULPT_undo_push_end(ob);
|
||||
|
||||
/* Force rebuild of PBVH for better BB placement. */
|
||||
SCULPT_pbvh_clear(ob);
|
||||
SCULPT_pbvh_clear(ob, false);
|
||||
/* Redraw. */
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
||||
|
||||
|
|
|
@ -467,19 +467,28 @@ void SCULPT_dynamic_topology_triangulate(SculptSession *ss, BMesh *bm)
|
|||
// NULL);
|
||||
}
|
||||
|
||||
void SCULPT_pbvh_clear(Object *ob)
|
||||
void SCULPT_pbvh_clear(Object *ob, bool cache_pbvh)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
/* Clear out any existing DM and PBVH. */
|
||||
if (ss->pbvh) {
|
||||
BKE_pbvh_free(ss->pbvh);
|
||||
if (cache_pbvh) {
|
||||
BKE_pbvh_set_cached(ob, ss->pbvh);
|
||||
}
|
||||
else {
|
||||
BKE_pbvh_cache_remove(ss->pbvh);
|
||||
BKE_pbvh_free(ss->pbvh);
|
||||
}
|
||||
|
||||
ss->pbvh = NULL;
|
||||
ss->pmap = NULL;
|
||||
ss->pmap_mem = NULL;
|
||||
}
|
||||
else {
|
||||
MEM_SAFE_FREE(ss->pmap);
|
||||
MEM_SAFE_FREE(ss->pmap_mem);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(ss->pmap);
|
||||
|
||||
MEM_SAFE_FREE(ss->pmap_mem);
|
||||
|
||||
BKE_object_free_derived_caches(ob);
|
||||
|
||||
|
@ -578,17 +587,55 @@ BMesh *BM_mesh_bm_from_me_threaded(BMesh *bm,
|
|||
const Mesh *me,
|
||||
const struct BMeshFromMeshParams *params);
|
||||
|
||||
static void customdata_strip_templayers(CustomData *cdata, int totelem)
|
||||
{
|
||||
for (int i = 0; i < cdata->totlayer; i++) {
|
||||
CustomDataLayer *layer = cdata->layers + i;
|
||||
|
||||
if (layer->flag & CD_FLAG_TEMPORARY) {
|
||||
CustomData_free_layer(cdata, layer->type, totelem, i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
Mesh *me = ob->data;
|
||||
|
||||
void BKE_pbvh_clear_cache(PBVH * preserve);
|
||||
|
||||
customdata_strip_templayers(&me->vdata, me->totvert);
|
||||
customdata_strip_templayers(&me->pdata, me->totpoly);
|
||||
|
||||
/* clear any non-dyntopo PBVH cache */
|
||||
if (ss->pbvh) {
|
||||
// pmap is freed by pbvh
|
||||
ss->pmap = NULL;
|
||||
ss->pmap_mem = NULL;
|
||||
|
||||
/* Remove existing pbvh so we can free it ourselves. */
|
||||
BKE_pbvh_cache_remove(ss->pbvh);
|
||||
|
||||
/* Free any other pbvhs */
|
||||
BKE_pbvh_clear_cache(NULL);
|
||||
}
|
||||
|
||||
if (ss->bm) {
|
||||
bool ok = ss->bm->totvert == me->totvert && ss->bm->totedge == me->totedge &&
|
||||
ss->bm->totloop == me->totloop && ss->bm->totface == me->totpoly;
|
||||
|
||||
if (!ok) {
|
||||
BM_mesh_free(ss->bm);
|
||||
/* Ensure ss->pbvh is in the cache so it can be destroyed in BKE_pbvh_free_bmesh. */
|
||||
if (ss->pbvh) {
|
||||
BKE_pbvh_set_cached(ob, ss->pbvh);
|
||||
}
|
||||
|
||||
/* Destroy all cached PBVHs with this bmesh. */
|
||||
BKE_pbvh_free_bmesh(NULL, ss->bm);
|
||||
|
||||
ss->pbvh = NULL;
|
||||
ss->bm = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -600,7 +647,7 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
|
|||
SCULPT_clear_scl_pointers(ss);
|
||||
|
||||
if (!ss->bm || !ss->pbvh || BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) {
|
||||
SCULPT_pbvh_clear(ob);
|
||||
SCULPT_pbvh_clear(ob, false);
|
||||
}
|
||||
else {
|
||||
/*sculpt session was set up by paint.c. just call SCULPT_update_customdata_refs to be safe*/
|
||||
|
@ -614,6 +661,19 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
|
|||
return;
|
||||
}
|
||||
|
||||
PBVH *pbvh = BKE_pbvh_get_or_free_cached(ob, BKE_object_get_original_mesh(ob), PBVH_BMESH);
|
||||
if (pbvh) {
|
||||
BMesh *bm = BKE_pbvh_get_bmesh(pbvh);
|
||||
|
||||
if (!ss->bm) {
|
||||
ss->bm = bm;
|
||||
}
|
||||
else if (ss->bm != bm) {
|
||||
printf("%s: bmesh differed!\n");
|
||||
SCULPT_pbvh_clear(ob, false);
|
||||
}
|
||||
}
|
||||
|
||||
const BMAllocTemplate allocsize = {
|
||||
.totvert = 2048 * 16, .totface = 2048 * 16, .totloop = 4196 * 16, .totedge = 2048 * 16};
|
||||
|
||||
|
@ -624,6 +684,11 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
|
|||
ss->mdyntopo_verts = NULL;
|
||||
}
|
||||
|
||||
if (ss->face_areas) {
|
||||
MEM_freeN(ss->face_areas);
|
||||
ss->face_areas = NULL;
|
||||
}
|
||||
|
||||
/* Dynamic topology doesn't ensure selection state is valid, so remove T36280. */
|
||||
BKE_mesh_mselect_clear(me);
|
||||
|
||||
|
@ -722,7 +787,7 @@ static void SCULPT_dynamic_topology_disable_ex(
|
|||
SculptSession *ss = ob->sculpt;
|
||||
Mesh *me = ob->data;
|
||||
|
||||
SCULPT_pbvh_clear(ob);
|
||||
SCULPT_pbvh_clear(ob, true);
|
||||
|
||||
/* destroy non-customdata temporary layers (which are rarely (never?) used for PBVH_BMESH) */
|
||||
SCULPT_release_attributes(ss, ob, true);
|
||||
|
@ -747,7 +812,8 @@ static void SCULPT_dynamic_topology_disable_ex(
|
|||
|
||||
/* Typically valid but with global-undo they can be NULL, see: T36234. */
|
||||
if (ss->bm) {
|
||||
BM_mesh_free(ss->bm);
|
||||
// PBVH now frees this
|
||||
// BM_mesh_free(ss->bm);
|
||||
ss->bm = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -1044,7 +1044,12 @@ bool SCULPT_vertex_colors_poll(struct bContext *C);
|
|||
void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags);
|
||||
void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType update_flags);
|
||||
|
||||
void SCULPT_pbvh_clear(Object *ob);
|
||||
typedef enum PBVHClearFlags {
|
||||
PBVH_CLEAR_CACHE_PBVH = 1<<1,
|
||||
PBVH_CLEAR_FREE_BMESH = 1 << 2,
|
||||
} PBVHClearFlags;
|
||||
|
||||
void SCULPT_pbvh_clear(Object *ob, bool cache_pbvh);
|
||||
|
||||
/**
|
||||
* Flush displacement from deformed PBVH to original layer.
|
||||
|
|
|
@ -166,7 +166,7 @@ static int sculpt_optimize_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
|
||||
SCULPT_pbvh_clear(ob);
|
||||
SCULPT_pbvh_clear(ob, false);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
|
@ -334,7 +334,7 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
/* Redraw. */
|
||||
SCULPT_pbvh_clear(ob);
|
||||
SCULPT_pbvh_clear(ob, false);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
|
|
|
@ -743,7 +743,7 @@ static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, Object *ob,
|
|||
}
|
||||
else {
|
||||
printf("undo triggered pbvh rebuild");
|
||||
SCULPT_pbvh_clear(ob);
|
||||
SCULPT_pbvh_clear(ob, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -753,7 +753,7 @@ static void sculpt_undo_bmesh_enable(Object *ob, SculptUndoNode *unode, bool is_
|
|||
SculptSession *ss = ob->sculpt;
|
||||
Mesh *me = ob->data;
|
||||
|
||||
SCULPT_pbvh_clear(ob);
|
||||
SCULPT_pbvh_clear(ob, false);
|
||||
SCULPT_clear_scl_pointers(ss);
|
||||
|
||||
ss->active_face_index.i = ss->active_vertex_index.i = 0;
|
||||
|
@ -977,7 +977,7 @@ static void sculpt_undo_geometry_free_data(SculptUndoNodeGeometry *geometry)
|
|||
static void sculpt_undo_geometry_restore(SculptUndoNode *unode, Object *object)
|
||||
{
|
||||
if (unode->geometry_clear_pbvh) {
|
||||
SCULPT_pbvh_clear(object);
|
||||
SCULPT_pbvh_clear(object, false);
|
||||
}
|
||||
|
||||
if (unode->applied) {
|
||||
|
@ -1165,7 +1165,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
|
|||
}
|
||||
|
||||
// PBVH is corrupted at this point, destroy it
|
||||
SCULPT_pbvh_clear(ob);
|
||||
SCULPT_pbvh_clear(ob, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2278,6 +2278,10 @@ void sculpt_undo_push_begin_ex(Object *ob, const char *name, bool no_first_entry
|
|||
BKE_pbvh_set_bm_log(ss->pbvh, ss->bm_log);
|
||||
}
|
||||
}
|
||||
|
||||
if (ss->pbvh) {
|
||||
BKE_pbvh_set_cached(ob, ss->pbvh);
|
||||
}
|
||||
}
|
||||
|
||||
void SCULPT_undo_push_begin(Object *ob, const char *name)
|
||||
|
|
|
@ -106,6 +106,9 @@ enum {
|
|||
*/
|
||||
void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
||||
const struct MVert *mvert,
|
||||
const struct MLoop *mloop,
|
||||
const struct MPoly *mpoly,
|
||||
const struct MLoopTri *looptri,
|
||||
const CustomData *vdata,
|
||||
const CustomData *ldata,
|
||||
const float *vmask,
|
||||
|
|
|
@ -240,6 +240,9 @@ static bool gpu_pbvh_is_looptri_visible(const MLoopTri *lt,
|
|||
|
||||
void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
||||
const MVert *mvert,
|
||||
const MLoop *mloop,
|
||||
const MPoly *mpoly,
|
||||
const MLoopTri *looptri,
|
||||
const CustomData *vdata,
|
||||
const CustomData *ldata,
|
||||
const float *vmask,
|
||||
|
@ -255,6 +258,11 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
|||
GPUAttrRef vcol_refs[MAX_GPU_ATTR];
|
||||
GPUAttrRef cd_uvs[MAX_GPU_ATTR];
|
||||
|
||||
buffers->mvert = mvert;
|
||||
buffers->mloop = mloop;
|
||||
buffers->mpoly = mpoly;
|
||||
buffers->looptri = looptri;
|
||||
|
||||
int totcol = gpu_pbvh_make_attr_offs(ATTR_DOMAIN_MASK_POINT | ATTR_DOMAIN_MASK_CORNER,
|
||||
CD_MASK_PROP_COLOR | CD_MASK_MLOOPCOL,
|
||||
vdata,
|
||||
|
|
|
@ -34,6 +34,7 @@ struct Ipo;
|
|||
struct Material;
|
||||
struct Mesh;
|
||||
struct Object;
|
||||
struct PBVH;
|
||||
struct PartDeflect;
|
||||
struct Path;
|
||||
struct RigidBodyOb;
|
||||
|
@ -206,6 +207,9 @@ typedef struct Object_Runtime {
|
|||
int crazyspace_num_verts;
|
||||
|
||||
int _pad3[3];
|
||||
|
||||
struct PBVH *cached_pbvh;
|
||||
void *_pad4;
|
||||
} Object_Runtime;
|
||||
|
||||
typedef struct ObjectLineArt {
|
||||
|
@ -433,7 +437,8 @@ typedef struct Object {
|
|||
ObjectLineArt lineart;
|
||||
|
||||
/** Runtime evaluation data (keep last). */
|
||||
void *_pad9;
|
||||
//void *_pad9;
|
||||
struct PBVH *cached_pbvh2;
|
||||
Object_Runtime runtime;
|
||||
} Object;
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "BKE_modifier.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_pbvh.h"
|
||||
#include "BKE_shader_fx.h"
|
||||
#include "BKE_sound.h"
|
||||
#include "BKE_vfont.h"
|
||||
|
@ -407,6 +408,7 @@ int main(int argc,
|
|||
DEG_register_node_types();
|
||||
|
||||
BKE_brush_system_init();
|
||||
BKE_pbvh_system_init();
|
||||
RE_texture_rng_init();
|
||||
|
||||
BKE_callback_global_init();
|
||||
|
|
Loading…
Reference in New Issue