From 87dc01e690d12b1cf50aa274c59d584e355f3c86 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 27 Feb 2015 09:46:56 +1100 Subject: [PATCH] Fix T43806: Knife project crashes Need to re-create the bmbvh after executing the cut. --- source/blender/editors/mesh/editmesh_knife.c | 57 ++++++++++++++------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index e8a5202029b..b6b5dfd0d93 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -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 */