Fix T43806: Knife project crashes

Need to re-create the bmbvh after executing the cut.
This commit is contained in:
Campbell Barton 2015-02-27 09:46:56 +11:00
parent 90cc2643e9
commit 87dc01e690
Notes: blender-bot 2023-02-14 09:26:12 +01:00
Referenced by issue #43806, Knife Project Crashes Blender
1 changed files with 41 additions and 16 deletions

View File

@ -158,6 +158,7 @@ typedef struct KnifeTool_OpData {
float mval[2]; /* mouse value with snapping applied */
//bContext *C;
Scene *scene;
Object *ob;
BMEditMesh *em;
@ -242,6 +243,8 @@ static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2],
static bool knife_verts_edge_in_face(KnifeVert *v1, KnifeVert *v2, BMFace *f);
static void knifetool_free_bmbvh(KnifeTool_OpData *kcd);
static void knife_update_header(bContext *C, KnifeTool_OpData *kcd)
{
#define HEADER_LENGTH 256
@ -2776,6 +2779,9 @@ static void knifetool_finish_ex(KnifeTool_OpData *kcd)
EDBM_selectmode_flush(kcd->em);
EDBM_mesh_normals_update(kcd->em);
EDBM_update_generic(kcd->em, true, true);
/* re-tessellating makes this invalid, dont use again by accident */
knifetool_free_bmbvh(kcd);
}
static void knifetool_finish(wmOperator *op)
{
@ -2820,14 +2826,12 @@ static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd)
BLI_ghash_free(kcd->kedgefacemap, NULL, NULL);
BLI_ghash_free(kcd->facetrimap, NULL, NULL);
BKE_bmbvh_free(kcd->bmbvh);
BLI_memarena_free(kcd->arena);
/* tag for redraw */
ED_region_tag_redraw(kcd->ar);
if (kcd->cagecos)
MEM_freeN((void *)kcd->cagecos);
knifetool_free_bmbvh(kcd);
if (kcd->linehits)
MEM_freeN(kcd->linehits);
@ -2858,6 +2862,29 @@ static void knifetool_update_mval_i(KnifeTool_OpData *kcd, const int mval_i[2])
knifetool_update_mval(kcd, mval);
}
static void knifetool_init_bmbvh(KnifeTool_OpData *kcd)
{
BM_mesh_elem_index_ensure(kcd->em->bm, BM_VERT);
kcd->cagecos = (const float (*)[3])BKE_editmesh_vertexCos_get(kcd->em, kcd->scene, NULL);
kcd->bmbvh = BKE_bmbvh_new_from_editmesh(
kcd->em,
BMBVH_RETURN_ORIG |
((kcd->only_select && kcd->cut_through) ? BMBVH_RESPECT_SELECT : BMBVH_RESPECT_HIDDEN),
kcd->cagecos, false);
}
static void knifetool_free_bmbvh(KnifeTool_OpData *kcd)
{
if (kcd->bmbvh) {
BKE_bmbvh_free(kcd->bmbvh);
kcd->bmbvh = NULL;
}
MEM_SAFE_FREE(kcd->cagecos);
}
/* called when modal loop selection gets set up... */
static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
const bool only_select, const bool cut_through, const bool is_interactive)
@ -2866,6 +2893,7 @@ static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
Object *obedit = CTX_data_edit_object(C);
/* assign the drawing handle for drawing preview line... */
kcd->scene = scene;
kcd->ob = obedit;
kcd->ar = CTX_wm_region(C);
@ -2873,15 +2901,12 @@ static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
kcd->em = BKE_editmesh_from_object(kcd->ob);
BM_mesh_elem_index_ensure(kcd->em->bm, BM_VERT);
/* cut all the way through the mesh if use_occlude_geometry button not pushed */
kcd->is_interactive = is_interactive;
kcd->cut_through = cut_through;
kcd->only_select = only_select;
kcd->cagecos = (const float (*)[3])BKE_editmesh_vertexCos_get(kcd->em, scene, NULL);
kcd->bmbvh = BKE_bmbvh_new_from_editmesh(
kcd->em,
BMBVH_RETURN_ORIG |
((only_select && cut_through) ? BMBVH_RESPECT_SELECT : BMBVH_RESPECT_HIDDEN),
kcd->cagecos, false);
knifetool_init_bmbvh(kcd);
kcd->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 15), "knife");
kcd->vthresh = KMAXDIST - 1;
@ -2900,11 +2925,6 @@ static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
kcd->kedgefacemap = BLI_ghash_ptr_new("knife kedgefacemap");
kcd->facetrimap = BLI_ghash_ptr_new("knife facetrimap");
/* cut all the way through the mesh if use_occlude_geometry button not pushed */
kcd->is_interactive = is_interactive;
kcd->cut_through = cut_through;
kcd->only_select = only_select;
/* can't usefully select resulting edges in face mode */
kcd->select_result = (kcd->em->selectmode != SCE_SELECT_FACE);
@ -3362,6 +3382,11 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
bool keep_search;
/* freed on knifetool_finish_ex, but we need again to check if points are visible */
if (kcd->cut_through == false) {
knifetool_init_bmbvh(kcd);
}
ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, projmat);
/* use face-loop tag to store if we have intersected */