Sculpt: fix multires crashing

This commit is contained in:
Joseph Eagar 2021-09-30 10:54:11 -07:00
parent 966c4eedc4
commit 5e3d84eed7
4 changed files with 94 additions and 8 deletions

View File

@ -791,7 +791,7 @@ void BKE_sculptsession_free_deformMats(struct SculptSession *ss);
void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss);
void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder);
void BKE_sculptsession_bm_to_me_for_render(struct Object *object);
bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, int totvert);
bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, struct PBVH *pbvh, int totvert);
/* Create new color layer on object if it doesn't have one and if experimental feature set has
* sculpt vertex color enabled. Returns truth if new layer has been added, false otherwise. */

View File

@ -135,6 +135,7 @@ struct MPoly;
struct MVert;
struct Mesh;
struct PBVH;
struct MEdge;
struct PBVHNode;
struct SubdivCCG;
struct TaskParallelSettings;
@ -933,6 +934,11 @@ void BKE_pbvh_update_vert_boundary_faces(int *face_sets,
struct MDynTopoVert *mdyntopo_verts,
struct MeshElemMap *pmap,
SculptVertRef vertex);
void BKE_pbvh_update_vert_boundary_grids(PBVH *pbvh,
struct SubdivCCG *subdiv_ccg,
SculptVertRef vertex);
void BKE_pbvh_set_mdyntopo_verts(PBVH *pbvh, struct MDynTopoVert *mdyntopoverts);
#ifdef __cplusplus
}

View File

@ -86,7 +86,7 @@ void SCULPT_dyntopo_node_layers_add(SculptSession *ss);
BMesh *SCULPT_dyntopo_empty_bmesh();
void SCULPT_undo_ensure_bmlog(Object *ob);
static void init_mdyntopo_layer(SculptSession *ss, int totvert);
static void init_mdyntopo_layer(SculptSession *ss, PBVH *pbvh, int totvert);
static void palette_init_data(ID *id)
{
@ -2201,7 +2201,9 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
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);
@ -2228,7 +2230,7 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
false);
}
BKE_sculptsession_check_mdyntopo(ob->sculpt, me->totvert);
BKE_sculptsession_check_mdyntopo(ob->sculpt, pbvh, me->totvert);
BKE_pbvh_build_mesh(pbvh,
me,
@ -2277,24 +2279,24 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect
subdiv_ccg->grid_hidden,
ob->sculpt->fast_draw);
BKE_sculptsession_check_mdyntopo(ob->sculpt, BKE_pbvh_get_grid_num_vertices(pbvh));
BKE_sculptsession_check_mdyntopo(ob->sculpt, pbvh, BKE_pbvh_get_grid_num_vertices(pbvh));
pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
return pbvh;
}
bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, int totvert)
ATTR_NO_OPT bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, PBVH *pbvh, int totvert)
{
if (!ss->bm && (!ss->mdyntopo_verts || totvert != ss->mdyntopo_verts_size)) {
init_mdyntopo_layer(ss, totvert);
init_mdyntopo_layer(ss, pbvh, totvert);
return true;
}
return false;
}
static void init_mdyntopo_layer(SculptSession *ss, int totvert)
ATTR_NO_OPT static void init_mdyntopo_layer_faces(SculptSession *ss, PBVH *pbvh, int totvert)
{
if (ss->mdyntopo_verts) {
MEM_freeN(ss->mdyntopo_verts);
@ -2303,6 +2305,8 @@ static void init_mdyntopo_layer(SculptSession *ss, int totvert)
ss->mdyntopo_verts = MEM_calloc_arrayN(totvert, sizeof(*ss->mdyntopo_verts), "mdyntopo_verts");
ss->mdyntopo_verts_size = totvert;
BKE_pbvh_set_mdyntopo_verts(pbvh, ss->mdyntopo_verts);
MDynTopoVert *mv = ss->mdyntopo_verts;
for (int i = 0; i < totvert; i++, mv++) {
@ -2310,6 +2314,7 @@ static void init_mdyntopo_layer(SculptSession *ss, int totvert)
mv->stroke_id = -1;
SculptVertRef vertex = {.i = i};
BKE_pbvh_update_vert_boundary_faces(ss->face_sets,
ss->mvert,
ss->medge,
@ -2320,6 +2325,40 @@ static void init_mdyntopo_layer(SculptSession *ss, int totvert)
vertex);
}
}
ATTR_NO_OPT static void init_mdyntopo_layer_grids(SculptSession *ss, PBVH *pbvh, int totvert)
{
if (ss->mdyntopo_verts) {
MEM_freeN(ss->mdyntopo_verts);
}
ss->mdyntopo_verts = MEM_calloc_arrayN(totvert, sizeof(*ss->mdyntopo_verts), "mdyntopo_verts");
ss->mdyntopo_verts_size = totvert;
BKE_pbvh_set_mdyntopo_verts(pbvh, ss->mdyntopo_verts);
MDynTopoVert *mv = ss->mdyntopo_verts;
for (int i = 0; i < totvert; i++, mv++) {
mv->flag = DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_VALENCE | DYNVERT_NEED_DISK_SORT;
mv->stroke_id = -1;
SculptVertRef vertex = {.i = i};
BKE_pbvh_update_vert_boundary_grids(pbvh, ss->subdiv_ccg, vertex);
}
}
ATTR_NO_OPT static void init_mdyntopo_layer(SculptSession *ss, PBVH *pbvh, int totvert)
{
if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
init_mdyntopo_layer_faces(ss, pbvh, totvert);
}
else if (BKE_pbvh_type(pbvh) == PBVH_GRIDS) {
init_mdyntopo_layer_grids(ss, pbvh, totvert);
}
}
PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
{
if (ob == NULL || ob->sculpt == NULL) {

View File

@ -4127,6 +4127,47 @@ void BKE_pbvh_set_symmetry(PBVH *pbvh, int symmetry, int boundary_symmetry)
}
}
void BKE_pbvh_set_mdyntopo_verts(PBVH *pbvh, struct MDynTopoVert *mdyntopoverts)
{
pbvh->mdyntopo_verts = mdyntopoverts;
}
void BKE_pbvh_update_vert_boundary_grids(PBVH *pbvh,
struct SubdivCCG *subdiv_ccg,
SculptVertRef vertex)
{
MDynTopoVert *mv = pbvh->mdyntopo_verts + vertex.i;
int last_fset = 0;
int last_fset2 = 0;
mv->flag &= ~(DYNVERT_BOUNDARY | DYNVERT_FSET_BOUNDARY | DYNVERT_NEED_BOUNDARY |
DYNVERT_FSET_CORNER | DYNVERT_CORNER | DYNVERT_SEAM_BOUNDARY |
DYNVERT_SHARP_BOUNDARY | DYNVERT_SEAM_CORNER | DYNVERT_SHARP_CORNER);
int totsharp = 0, totseam = 0;
int visible = false;
int index = (int)vertex.i;
/* TODO: optimize this. We could fill #SculptVertexNeighborIter directly,
* maybe provide coordinate and mask pointers directly rather than converting
* back and forth between #CCGElem and global index. */
const CCGKey *key = BKE_pbvh_get_grid_key(pbvh);
const int grid_index = index / key->grid_area;
const int vertex_index = index - grid_index * key->grid_area;
SubdivCCGCoord coord = {.grid_index = grid_index,
.x = vertex_index % key->grid_size,
.y = vertex_index / key->grid_size};
SubdivCCGNeighbors neighbors;
BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, &coord, false, &neighbors);
mv->valence = neighbors.size;
mv->flag &= ~DYNVERT_NEED_VALENCE;
}
void BKE_pbvh_update_vert_boundary_faces(int *face_sets,
MVert *mvert,
MEdge *medge,