Sculpt-dev: fix crash in pbvh cache

This commit is contained in:
Joseph Eagar 2022-03-23 23:59:29 -07:00
parent 307f13aee5
commit b53339edfa
11 changed files with 157 additions and 116 deletions

View File

@ -722,8 +722,7 @@ typedef struct SculptSession {
/* Mesh connectivity maps. */
/* Vertices to adjacent polys. */
struct MeshElemMap *pmap;
int *pmap_mem;
SculptPMap *pmap;
/* Edges to adjacent polys. */
struct MeshElemMap *epmap;

View File

@ -50,6 +50,12 @@ typedef struct SculptFaceRef {
#define SCULPT_REF_NONE ((intptr_t)-1)
typedef struct SculptPMap {
struct MeshElemMap *pmap;
int *pmap_mem;
int refcount;
} SculptPMap;
#if 0
typedef struct SculptLoopRef {
intptr_t i;
@ -288,7 +294,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
int looptri_num,
bool fast_draw,
float *face_areas,
struct MeshElemMap *pmap);
SculptPMap *pmap);
/**
* Do a full rebuild with on Grids data structure.
*/
@ -1128,17 +1134,23 @@ 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_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_set_pmap(PBVH *pbvh, SculptPMap *pmap);
SculptPMap *BKE_pbvh_get_pmap(PBVH *pbvh);
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();
SculptPMap *BKE_pbvh_make_pmap(const struct Mesh *me);
void BKE_pbvh_pmap_aquire(SculptPMap *pmap);
bool BKE_pbvh_pmap_release(SculptPMap *pmap);

View File

@ -460,9 +460,8 @@ void multires_force_sculpt_rebuild(Object *object)
object->sculpt->pbvh = NULL;
}
MEM_SAFE_FREE(ss->pmap);
MEM_SAFE_FREE(ss->pmap_mem);
BKE_pbvh_pmap_release(ss->pmap);
ss->pmap = NULL;
}
void multires_force_external_reload(Object *object)

View File

@ -1451,10 +1451,6 @@ static void sculptsession_free_pbvh(Object *object)
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);
@ -1525,8 +1521,7 @@ void BKE_sculptsession_free(Object *ob)
CustomData_free(&ss->temp_pdata, ss->temp_pdata_elems);
if (!ss->pbvh) {
MEM_SAFE_FREE(ss->pmap);
MEM_SAFE_FREE(ss->pmap_mem);
BKE_pbvh_pmap_release(ss->pmap);
}
sculptsession_free_pbvh(ob);
@ -1827,23 +1822,18 @@ static void sculpt_update_object(Depsgraph *depsgraph,
if (need_pmap && ob->type == OB_MESH && !ss->pmap) {
if (!ss->pmap && ss->pbvh) {
ss->pmap = BKE_pbvh_get_pmap_ex(ss->pbvh, &ss->pmap_mem);
ss->pmap = BKE_pbvh_get_pmap(ss->pbvh);
if (ss->pmap) {
BKE_pbvh_pmap_aquire(ss->pmap);
}
}
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);
ss->pmap = BKE_pbvh_make_pmap(me);
if (ss->pbvh) {
BKE_pbvh_set_pmap(ss->pbvh, ss->pmap, ss->pmap_mem);
BKE_pbvh_set_pmap(ss->pbvh, ss->pmap);
}
}
}
@ -2471,23 +2461,13 @@ ATTR_NO_OPT static PBVH *build_pbvh_from_regular_mesh(Object *ob,
PBVH *pbvh = BKE_pbvh_get_or_free_cached(ob, me, PBVH_FACES);
struct MeshElemMap *BKE_pbvh_get_pmap_ex(PBVH * pbvh, int **r_mem);
if (!ss->pmap && pbvh) {
ss->pmap = BKE_pbvh_get_pmap_ex(pbvh, &ss->pmap_mem);
ss->pmap = BKE_pbvh_get_pmap(pbvh);
BKE_pbvh_pmap_aquire(ss->pmap);
}
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);
ss->pmap = BKE_pbvh_make_pmap(me);
}
if (!pbvh) {
@ -2519,7 +2499,7 @@ ATTR_NO_OPT static PBVH *build_pbvh_from_regular_mesh(Object *ob,
pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
}
BKE_pbvh_set_pmap(pbvh, ss->pmap, ss->pmap_mem);
BKE_pbvh_set_pmap(pbvh, ss->pmap);
BKE_sculptsession_check_sculptverts(ob->sculpt, pbvh, me->totvert);
MEM_SAFE_FREE(ss->face_areas);
@ -2632,7 +2612,7 @@ static void init_mdyntopo_layer_faces(SculptSession *ss, PBVH *pbvh, int totvert
ss->mloop,
ss->mpoly,
ss->mdyntopo_verts,
ss->pmap,
ss->pmap->pmap,
vertex);
// can't fully update boundary here, so still flag for update

View File

@ -663,7 +663,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
int looptri_num,
bool fast_draw,
float *face_areas,
struct MeshElemMap *pmap)
SculptPMap *pmap)
{
BBC *prim_bbc = NULL;
BB cb;
@ -794,6 +794,8 @@ PBVH *BKE_pbvh_new(void)
ATTR_NO_OPT void BKE_pbvh_free(PBVH *pbvh)
{
BKE_pbvh_cache_remove(pbvh);
for (int i = 0; i < pbvh->totnode; i++) {
PBVHNode *node = &pbvh->nodes[i];
@ -832,6 +834,8 @@ ATTR_NO_OPT void BKE_pbvh_free(PBVH *pbvh)
MEM_freeN((void *)pbvh->verts);
}
pbvh->verts = NULL;
}
if (pbvh->looptri) {
@ -848,8 +852,10 @@ ATTR_NO_OPT void BKE_pbvh_free(PBVH *pbvh)
MEM_SAFE_FREE(pbvh->vert_bitmap);
MEM_SAFE_FREE(pbvh->pmap);
MEM_SAFE_FREE(pbvh->pmap_mem);
BKE_pbvh_pmap_release(pbvh->pmap);
pbvh->pmap = NULL;
pbvh->invalid = true;
MEM_freeN(pbvh);
}
@ -4420,7 +4426,7 @@ void BKE_pbvh_pmap_to_edges(PBVH *pbvh,
bool *r_heap_alloc,
int **r_polys)
{
MeshElemMap *map = pbvh->pmap + vertex.i;
MeshElemMap *map = pbvh->pmap->pmap + vertex.i;
int len = 0;
for (int i = 0; i < map->count; i++) {
@ -4793,6 +4799,11 @@ bool BKE_pbvh_cache(const struct Mesh *me, PBVH *pbvh)
{
memset(&pbvh->cached_data, 0, sizeof(pbvh->cached_data));
if (pbvh->invalid) {
printf("invalid pbvh!\n");
return false;
}
switch (pbvh->type) {
case PBVH_BMESH:
if (!pbvh->bm) {
@ -4850,6 +4861,10 @@ ATTR_NO_OPT bool BKE_pbvh_cache_is_valid(const Object *ob,
const PBVH *pbvh,
PBVHType pbvh_type)
{
if (pbvh->invalid) {
printf("pbvh invalid!\n");
}
if (pbvh->type != pbvh_type) {
return false;
}
@ -4968,7 +4983,10 @@ ATTR_NO_OPT PBVH *BKE_pbvh_get_or_free_cached(Object *ob, Mesh *me, PBVHType pbv
case PBVH_FACES:
pbvh->vert_normals = BKE_mesh_vertex_normals_for_write(me);
case PBVH_GRIDS:
pbvh->verts = me->mvert;
if (!pbvh->deformed) {
pbvh->verts = me->mvert;
}
pbvh->mloop = me->mloop;
pbvh->mpoly = me->mpoly;
pbvh->vdata = &me->vdata;
@ -4993,6 +5011,14 @@ ATTR_NO_OPT void BKE_pbvh_set_cached(Object *ob, PBVH *pbvh)
PBVH *exist = BLI_ghash_lookup(cached_pbvhs, ob_orig->id.name);
if (pbvh->invalid) {
printf("pbvh invalid!");
}
if (exist && exist->invalid) {
printf("pbvh invalid!");
}
if (!exist || exist != pbvh) {
pbvh_clear_cached_pbvhs(pbvh);
BLI_ghash_insert(cached_pbvhs, BLI_strdup(ob_orig->id.name), pbvh);
@ -5001,24 +5027,18 @@ ATTR_NO_OPT void BKE_pbvh_set_cached(Object *ob, PBVH *pbvh)
BKE_pbvh_cache(BKE_object_get_original_mesh(ob_orig), pbvh);
}
struct MeshElemMap *BKE_pbvh_get_pmap(PBVH *pbvh)
struct SculptPMap *BKE_pbvh_get_pmap(PBVH *pbvh)
{
return pbvh->pmap;
}
struct MeshElemMap *BKE_pbvh_get_pmap_ex(PBVH *pbvh, int **r_mem)
void BKE_pbvh_set_pmap(PBVH *pbvh, SculptPMap *pmap)
{
if (r_mem) {
*r_mem = (int *)pbvh->pmap_mem;
if (pbvh->pmap != pmap) {
BKE_pbvh_pmap_aquire(pmap);
}
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. */
@ -5097,3 +5117,43 @@ void BKE_pbvh_system_exit()
pbvh_clear_cached_pbvhs(NULL);
BLI_ghash_free(cached_pbvhs, NULL, NULL);
}
SculptPMap *BKE_pbvh_make_pmap(const struct Mesh *me)
{
SculptPMap *pmap = MEM_callocN(sizeof(*pmap), "SculptPMap");
BKE_mesh_vert_poly_map_create(&pmap->pmap,
&pmap->pmap_mem,
me->mvert,
me->medge,
me->mpoly,
me->mloop,
me->totvert,
me->totpoly,
me->totloop,
false);
pmap->refcount = 1;
return pmap;
}
void BKE_pbvh_pmap_aquire(SculptPMap *pmap)
{
pmap->refcount++;
}
bool BKE_pbvh_pmap_release(SculptPMap *pmap)
{
pmap->refcount--;
if (pmap->refcount == 0) {
MEM_SAFE_FREE(pmap->pmap);
MEM_SAFE_FREE(pmap->pmap_mem);
MEM_SAFE_FREE(pmap);
return true;
}
return false;
}

View File

@ -145,8 +145,9 @@ struct PBVH {
int depth_limit;
/* Mesh data */
struct MeshElemMap *pmap, *vemap;
void *pmap_mem;
struct MeshElemMap *vemap;
SculptPMap *pmap;
const struct Mesh *mesh;
/* Note: Normals are not const because they can be updated for drawing by sculpt code. */
@ -231,6 +232,8 @@ struct PBVH {
int totvert, totedge, totloop, totpoly;
struct BMesh *bm;
} cached_data;
bool invalid;
};
/* pbvh.c */

View File

@ -415,9 +415,9 @@ bool SCULPT_vertex_color_get(const SculptSession *ss, SculptVertRef vertex, floa
if (ss->vcol_domain == ATTR_DOMAIN_CORNER) {
zero_v4(out);
int count = ss->pmap[vertex.i].count;
int count = ss->pmap->pmap[vertex.i].count;
for (int i = 0; i < count; i++) {
MPoly *mp = ss->mpoly + ss->pmap[vertex.i].indices[i];
MPoly *mp = ss->mpoly + ss->pmap->pmap[vertex.i].indices[i];
MLoop *ml = ss->mloop + mp->loopstart;
int li = mp->loopstart;
@ -555,9 +555,9 @@ void SCULPT_vertex_color_set(const SculptSession *ss, SculptVertRef vertex, floa
}
if (ss->vcol_domain == ATTR_DOMAIN_CORNER) {
int count = ss->pmap[vertex.i].count;
int count = ss->pmap->pmap[vertex.i].count;
for (int i = 0; i < count; i++) {
MPoly *mp = ss->mpoly + ss->pmap[vertex.i].indices[i];
MPoly *mp = ss->mpoly + ss->pmap->pmap[vertex.i].indices[i];
MLoop *ml = ss->mloop + mp->loopstart;
int li = mp->loopstart;
@ -1137,8 +1137,8 @@ bool SCULPT_vertex_any_face_set_visible_get(SculptSession *ss, SculptVertRef ind
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
MeshElemMap *vert_map = &ss->pmap[index.i];
for (int j = 0; j < ss->pmap[index.i].count; j++) {
MeshElemMap *vert_map = &ss->pmap->pmap[index.i];
for (int j = 0; j < ss->pmap->pmap[index.i].count; j++) {
if (ss->face_sets[vert_map->indices[j]] > 0) {
return true;
}
@ -1169,8 +1169,8 @@ bool SCULPT_vertex_all_face_sets_visible_get(const SculptSession *ss, SculptVert
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
MeshElemMap *vert_map = &ss->pmap[index.i];
for (int j = 0; j < ss->pmap[index.i].count; j++) {
MeshElemMap *vert_map = &ss->pmap->pmap[index.i];
for (int j = 0; j < ss->pmap->pmap[index.i].count; j++) {
if (ss->face_sets[vert_map->indices[j]] < 0) {
return false;
}
@ -1205,12 +1205,12 @@ void SCULPT_vertex_face_set_set(SculptSession *ss, SculptVertRef index, int face
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
MeshElemMap *vert_map = &ss->pmap[index.i];
MeshElemMap *vert_map = &ss->pmap->pmap[index.i];
MSculptVert *mv = ss->mdyntopo_verts + index.i;
MV_ADD_FLAG(mv, SCULPTVERT_NEED_BOUNDARY);
for (int j = 0; j < ss->pmap[index.i].count; j++) {
for (int j = 0; j < ss->pmap->pmap[index.i].count; j++) {
MPoly *mp = ss->mpoly + vert_map->indices[j];
MLoop *ml = ss->mloop + mp->loopstart;
@ -1261,8 +1261,8 @@ void SCULPT_vertex_face_set_increase(SculptSession *ss, SculptVertRef vertex, co
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
int index = (int)vertex.i;
MeshElemMap *vert_map = &ss->pmap[index];
for (int j = 0; j < ss->pmap[index].count; j++) {
MeshElemMap *vert_map = &ss->pmap->pmap[index];
for (int j = 0; j < ss->pmap->pmap[index].count; j++) {
if (ss->face_sets[vert_map->indices[j]] > 0) {
ss->face_sets[vert_map->indices[j]] += increase;
}
@ -1303,9 +1303,9 @@ int SCULPT_vertex_face_set_get(SculptSession *ss, SculptVertRef index)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
MeshElemMap *vert_map = &ss->pmap[index.i];
MeshElemMap *vert_map = &ss->pmap->pmap[index.i];
int face_set = 0;
for (int i = 0; i < ss->pmap[index.i].count; i++) {
for (int i = 0; i < ss->pmap->pmap[index.i].count; i++) {
if (ss->face_sets[vert_map->indices[i]] > face_set) {
face_set = abs(ss->face_sets[vert_map->indices[i]]);
}
@ -1343,8 +1343,8 @@ bool SCULPT_vertex_has_face_set(SculptSession *ss, SculptVertRef index, int face
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
MeshElemMap *vert_map = &ss->pmap[index.i];
for (int i = 0; i < ss->pmap[index.i].count; i++) {
MeshElemMap *vert_map = &ss->pmap->pmap[index.i];
for (int i = 0; i < ss->pmap->pmap[index.i].count; i++) {
if (ss->face_sets[vert_map->indices[i]] == face_set) {
return true;
}
@ -1504,10 +1504,10 @@ static void UNUSED_FUNCTION(sculpt_visibility_sync_vertex_to_face_sets)(SculptSe
SculptVertRef vertex)
{
int index = (int)vertex.i;
MeshElemMap *vert_map = &ss->pmap[index];
MeshElemMap *vert_map = &ss->pmap->pmap[index];
const bool visible = SCULPT_vertex_visible_get(ss, vertex);
for (int i = 0; i < ss->pmap[index].count; i++) {
for (int i = 0; i < ss->pmap->pmap[index].count; i++) {
if (visible) {
ss->face_sets[vert_map->indices[i]] = abs(ss->face_sets[vert_map->indices[i]]);
}
@ -1584,19 +1584,19 @@ static SculptCornerType sculpt_check_corner_in_base_mesh(const SculptSession *ss
{
int index = BKE_pbvh_vertex_index_to_table(ss->pbvh, vertex);
MeshElemMap *vert_map = &ss->pmap[index];
MeshElemMap *vert_map = &ss->pmap->pmap[index];
int face_set = -1;
int last1 = -1;
int last2 = -1;
int ret = 0;
if (sculpt_check_boundary_vertex_in_base_mesh(ss, vertex) && ss->pmap[index].count < 4) {
if (sculpt_check_boundary_vertex_in_base_mesh(ss, vertex) && ss->pmap->pmap[index].count < 4) {
ret |= SCULPT_CORNER_MESH;
}
if (check_facesets) {
for (int i = 0; i < ss->pmap[index].count; i++) {
for (int i = 0; i < ss->pmap->pmap[index].count; i++) {
if (check_facesets) {
if (last2 != last1) {
last2 = last1;
@ -1624,9 +1624,9 @@ static bool sculpt_check_unique_face_set_in_base_mesh(const SculptSession *ss,
{
int index = BKE_pbvh_vertex_index_to_table(ss->pbvh, vertex);
MeshElemMap *vert_map = &ss->pmap[index];
MeshElemMap *vert_map = &ss->pmap->pmap[index];
int face_set = -1;
for (int i = 0; i < ss->pmap[index].count; i++) {
for (int i = 0; i < ss->pmap->pmap[index].count; i++) {
if (face_set == -1) {
face_set = abs(ss->face_sets[vert_map->indices[i]]);
}
@ -1647,9 +1647,9 @@ static bool sculpt_check_unique_face_set_for_edge_in_base_mesh(const SculptSessi
int v1,
int v2)
{
MeshElemMap *vert_map = &ss->pmap[v1];
MeshElemMap *vert_map = &ss->pmap->pmap[v1];
int p1 = -1, p2 = -1;
for (int i = 0; i < ss->pmap[v1].count; i++) {
for (int i = 0; i < ss->pmap->pmap[v1].count; i++) {
MPoly *p = &ss->mpoly[vert_map->indices[i]];
for (int l = 0; l < p->totloop; l++) {
MLoop *loop = &ss->mloop[p->loopstart + l];
@ -1877,7 +1877,7 @@ static void sculpt_vertex_neighbors_get_faces(const SculptSession *ss,
MEM_freeN(edges);
}
#if 0
for (int i = 0; i < ss->pmap[index].count; i++) {
for (int i = 0; i < ss->pmap->pmap[index].count; i++) {
if (ss->face_sets[vert_map->indices[i]] < 0) {
/* Skip connectivity from hidden faces. */
continue;
@ -2393,7 +2393,7 @@ static void faces_update_boundary_flags(const SculptSession *ss, const SculptVer
ss->mloop,
ss->mpoly,
ss->mdyntopo_verts,
ss->pmap,
ss->pmap->pmap,
vertex);
// have to handle boundary here
MSculptVert *mv = ss->mdyntopo_verts + vertex.i;
@ -2403,11 +2403,11 @@ static void faces_update_boundary_flags(const SculptSession *ss, const SculptVer
if (sculpt_check_boundary_vertex_in_base_mesh(ss, vertex)) {
mv->flag |= SCULPTVERT_BOUNDARY;
if (ss->pmap[vertex.i].count < 4) {
if (ss->pmap->pmap[vertex.i].count < 4) {
bool ok = true;
for (int i = 0; i < ss->pmap[vertex.i].count; i++) {
MPoly *mp = ss->mpoly + ss->pmap[vertex.i].indices[i];
for (int i = 0; i < ss->pmap->pmap[vertex.i].count; i++) {
MPoly *mp = ss->mpoly + ss->pmap->pmap[vertex.i].indices[i];
if (mp->totloop < 4) {
ok = false;
}

View File

@ -471,6 +471,9 @@ void SCULPT_pbvh_clear(Object *ob, bool cache_pbvh)
{
SculptSession *ss = ob->sculpt;
BKE_pbvh_pmap_release(ss->pmap);
ss->pmap = NULL;
/* Clear out any existing DM and PBVH. */
if (ss->pbvh) {
if (cache_pbvh) {
@ -482,12 +485,6 @@ void SCULPT_pbvh_clear(Object *ob, bool cache_pbvh)
}
ss->pbvh = NULL;
ss->pmap = NULL;
ss->pmap_mem = NULL;
}
else {
MEM_SAFE_FREE(ss->pmap);
MEM_SAFE_FREE(ss->pmap_mem);
}
BKE_object_free_derived_caches(ob);
@ -611,9 +608,9 @@ void SCULPT_dynamic_topology_enable_ex(Main *bmain, Depsgraph *depsgraph, Scene
/* clear any non-dyntopo PBVH cache */
if (ss->pbvh) {
// pmap is freed by pbvh
ss->pmap = NULL;
ss->pmap_mem = NULL;
if (ss->pmap) {
BKE_pbvh_pmap_release(ss->pmap);
}
/* Remove existing pbvh so we can free it ourselves. */
BKE_pbvh_cache_remove(ss->pbvh);

View File

@ -746,8 +746,8 @@ static float *sculpt_expand_diagonals_falloff_create(Object *ob, const SculptVer
}
}
else {
for (int j = 0; j < ss->pmap[v_next_i].count; j++) {
MPoly *p = &ss->mpoly[ss->pmap[v_next_i].indices[j]];
for (int j = 0; j < ss->pmap->pmap[v_next_i].count; j++) {
MPoly *p = &ss->mpoly[ss->pmap->pmap[v_next_i].indices[j]];
for (int l = 0; l < p->totloop; l++) {
const int neighbor_v = mesh->mloop[p->loopstart + l].v;
@ -2226,7 +2226,7 @@ static void sculpt_expand_delete_face_set_id(int *r_face_sets,
}
const int totface = ss->totfaces;
MeshElemMap *pmap = ss->pmap;
MeshElemMap *pmap = ss->pmap->pmap;
/* Check that all the face sets IDs in the mesh are not equal to `delete_id`
* before attempting to delete it. */

View File

@ -402,8 +402,8 @@ void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
MeshElemMap *vert_map = &ss->pmap[vd.index];
for (int j = 0; j < ss->pmap[vd.index].count; j++) {
MeshElemMap *vert_map = &ss->pmap->pmap[vd.index];
for (int j = 0; j < ss->pmap->pmap[vd.index].count; j++) {
const MPoly *p = &ss->mpoly[vert_map->indices[j]];
float poly_center[3];
@ -1680,7 +1680,7 @@ static void sculpt_face_set_grow(Object *ob,
const MPoly *c_poly = &mesh->mpoly[p];
for (int l = 0; l < c_poly->totloop; l++) {
const MLoop *c_loop = &mesh->mloop[c_poly->loopstart + l];
const MeshElemMap *vert_map = &ss->pmap[c_loop->v];
const MeshElemMap *vert_map = &ss->pmap->pmap[c_loop->v];
for (int i = 0; i < vert_map->count; i++) {
const int neighbor_face_index = vert_map->indices[i];
if (neighbor_face_index == p) {
@ -1803,7 +1803,7 @@ static void sculpt_face_set_shrink(Object *ob,
const MPoly *c_poly = &mesh->mpoly[p];
for (int l = 0; l < c_poly->totloop; l++) {
const MLoop *c_loop = &mesh->mloop[c_poly->loopstart + l];
const MeshElemMap *vert_map = &ss->pmap[c_loop->v];
const MeshElemMap *vert_map = &ss->pmap->pmap[c_loop->v];
for (int i = 0; i < vert_map->count; i++) {
const int neighbor_face_index = vert_map->indices[i];
if (neighbor_face_index == p) {

View File

@ -359,16 +359,7 @@ static bool sculpt_undo_restore_color(bContext *C, SculptUndoNode *unode)
if (!ss->pmap) {
Mesh *me = BKE_object_get_original_mesh(ob);
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);
ss->pmap = BKE_pbvh_make_pmap(me);
}
if (unode->maxvert) {