diff options
author | Germano Cavalcante <germano.costa@ig.com.br> | 2020-03-03 06:08:16 +0300 |
---|---|---|
committer | Germano Cavalcante <germano.costa@ig.com.br> | 2020-03-03 06:08:16 +0300 |
commit | 3e1aa6cbf3df6f9f0f96380386a7c8d64c07cc64 (patch) | |
tree | 45ffc63d775b19beb441a76067b22427ae8eb20f /source/blender/editors/transform/transform_snap_object.c | |
parent | a976fe42ef74e77744f571578bf52998af491cb9 (diff) |
Transform Snap: Clear 'SnapObjectData' after changes in the geometry
Differential Revision: https://developer.blender.org/D6927
Diffstat (limited to 'source/blender/editors/transform/transform_snap_object.c')
-rw-r--r-- | source/blender/editors/transform/transform_snap_object.c | 126 |
1 files changed, 80 insertions, 46 deletions
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index ecd267d6f2a..3992c3a3036 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -104,6 +104,7 @@ typedef struct SnapObjectData { /* SNAP_EDIT_MESH */ BVHTreeFromEditMesh treedata_editmesh; float min[3], max[3]; + struct LinkNode **bvh_cache_p; }; }; } SnapObjectData; @@ -218,14 +219,23 @@ static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object * static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob) { + SnapObjectData *sod; void **sod_p; + bool init = false; + if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { - BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_MESH); + sod = *sod_p; + if (sod->type != SNAP_MESH) { + snap_object_data_clear(sod); + init = true; + } } else { - SnapObjectData *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + init = true; + } - /* Init. */ + if (init) { sod->type = SNAP_MESH; /* start assuming that it has each of these element types */ sod->has_looptris = true; @@ -233,14 +243,16 @@ static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object sod->has_loose_vert = true; } - return *sod_p; + return sod; } static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, Object *ob, BMEditMesh *em) { + SnapObjectData *sod; void **sod_p; + bool init = false, init_min_max = true; { /* Use object-data as the key in ghash since the editmesh @@ -258,18 +270,70 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, } if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { - BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_EDIT_MESH); + sod = *sod_p; + bool clear = false; + /* Check if the geometry has changed. */ + if (sod->type != SNAP_EDIT_MESH) { + clear = true; + } + else if (sod->treedata_editmesh.em != em) { + /* Clear only cached. */ + init_min_max = false; + for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) { + if (sod->cached[i]) { + sod->bvhtree[i] = NULL; + /* Only init min and max when you have a non-custom bvhtree pending. */ + init_min_max = true; + } + } + init = true; + } + else if (sod->bvh_cache_p) { + if (sod->treedata_editmesh.tree && sod->treedata_editmesh.cached && + !bvhcache_has_tree(*sod->bvh_cache_p, sod->treedata_editmesh.tree)) { + /* The tree is owned by the EditMesh and may have been freed since we last used! */ + clear = true; + } + else if (sod->bvhtree[0] && sod->cached[0] && + !bvhcache_has_tree(*sod->bvh_cache_p, sod->bvhtree[0])) { + /* The tree is owned by the EditMesh and may have been freed since we last used! */ + clear = true; + } + else if (sod->bvhtree[1] && sod->cached[1] && + !bvhcache_has_tree(*sod->bvh_cache_p, sod->bvhtree[1])) { + /* The tree is owned by the EditMesh and may have been freed since we last used! */ + clear = true; + } + } + + if (clear) { + snap_object_data_clear(sod); + init = true; + } } else { - SnapObjectData *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); + init = true; + } - /* Init. */ + if (init) { sod->type = SNAP_EDIT_MESH; sod->treedata_editmesh.em = em; - bm_mesh_minmax(em->bm, sod->min, sod->max); + if (init_min_max) { + bm_mesh_minmax(em->bm, sod->min, sod->max); + } + if (em->mesh_eval_final) { + sod->bvh_cache_p = &em->mesh_eval_final->runtime.bvh_cache; + } + else if (em->mesh_eval_cage) { + sod->bvh_cache_p = &em->mesh_eval_cage->runtime.bvh_cache; + } + else { + sod->bvh_cache_p = &((Mesh *)ob->data)->runtime.bvh_cache; + } } - return *sod_p; + return sod; } /** \} */ @@ -737,18 +801,9 @@ static bool raycastEditMesh(SnapObjectContext *sctx, BVHTreeFromEditMesh *treedata = &sod->treedata_editmesh; - BVHCache **em_bvh_cache = &((Mesh *)ob->data)->runtime.bvh_cache; - - if (treedata->tree && treedata->cached) { - /* The tree is owned by the Mesh and may have been freed since we last used! */ - if (!bvhcache_has_tree(*em_bvh_cache, treedata->tree)) { - treedata->tree = NULL; - } - } - if (treedata->tree == NULL) { /* Get original version of the edit_mesh. */ - BLI_assert(sod->treedata_editmesh.em == BKE_editmesh_from_object(DEG_get_original_object(ob))); + BLI_assert(sod->treedata_editmesh.em == BKE_editmesh_from_object(ob)); BMEditMesh *em_orig = sod->treedata_editmesh.em; if (sctx->callbacks.edit_mesh.test_face_fn) { @@ -770,7 +825,8 @@ static bool raycastEditMesh(SnapObjectContext *sctx, else { /* Only cache if bvhtree is created without a mask. * This helps keep a standardized bvhtree in cache. */ - BKE_bvhtree_from_editmesh_get(treedata, em_orig, 4, BVHTREE_FROM_EM_LOOPTRI, em_bvh_cache); + BKE_bvhtree_from_editmesh_get( + treedata, em_orig, 4, BVHTREE_FROM_EM_LOOPTRI, sod->bvh_cache_p); } if (treedata->tree == NULL) { @@ -892,10 +948,7 @@ static bool raycastObj(SnapObjectContext *sctx, Mesh *me = ob->data; bool use_hide = false; if (BKE_object_is_in_editmode(ob)) { - /* Strange, sometimes the `em` of the evaluated object has - * uninitialized memory. Need to be investigated. - * Use the `em` of the original object then. */ - BMEditMesh *em = BKE_editmesh_from_object(DEG_get_original_object(ob)); + BMEditMesh *em = BKE_editmesh_from_object(ob); if (use_obedit) { retval = raycastEditMesh(sctx, ray_start, @@ -2447,18 +2500,9 @@ static short snapEditMesh(SnapObjectContext *sctx, return 0; } - BVHCache **em_bvh_cache = &((Mesh *)ob->data)->runtime.bvh_cache; - if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) { BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[0]}; - if (treedata.tree && sod->cached[0]) { - /* The tree is owned by the Mesh and may have been freed since we last used! */ - if (!bvhcache_has_tree(*em_bvh_cache, treedata.tree)) { - treedata.tree = sod->bvhtree[0] = NULL; - } - } - if (treedata.tree == NULL) { BLI_bitmap *verts_mask = NULL; int verts_num_active = -1; @@ -2476,7 +2520,7 @@ static short snapEditMesh(SnapObjectContext *sctx, MEM_freeN(verts_mask); } else { - BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_VERTS, em_bvh_cache); + BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_VERTS, sod->bvh_cache_p); } sod->bvhtree[0] = treedata.tree; sod->cached[0] = treedata.cached; @@ -2486,13 +2530,6 @@ static short snapEditMesh(SnapObjectContext *sctx, if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[1]}; - if (treedata.tree && sod->cached[1]) { - /* The tree is owned by the Mesh and may have been freed since we last used! */ - if (!bvhcache_has_tree(*em_bvh_cache, treedata.tree)) { - treedata.tree = sod->bvhtree[1] = NULL; - } - } - if (treedata.tree == NULL) { BLI_bitmap *edges_mask = NULL; int edges_num_active = -1; @@ -2510,7 +2547,7 @@ static short snapEditMesh(SnapObjectContext *sctx, MEM_freeN(edges_mask); } else { - BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_EDGES, em_bvh_cache); + BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_EDGES, sod->bvh_cache_p); } sod->bvhtree[1] = treedata.tree; sod->cached[1] = treedata.cached; @@ -2625,10 +2662,7 @@ static short snapObject(SnapObjectContext *sctx, case OB_MESH: { Mesh *me = ob->data; if (BKE_object_is_in_editmode(ob)) { - /* Strange, sometimes the `em` of the evaluated object has - * uninitialized memory. Need to be investigated. - * Use the `em` of the original object then. */ - BMEditMesh *em = BKE_editmesh_from_object(DEG_get_original_object(ob)); + BMEditMesh *em = BKE_editmesh_from_object(ob); if (use_obedit) { retval = snapEditMesh( sctx, snapdata, ob, em, obmat, use_backface_culling, dist_px, r_loc, r_no, r_index); |