Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGermano Cavalcante <germano.costa@ig.com.br>2020-03-03 06:08:16 +0300
committerGermano Cavalcante <germano.costa@ig.com.br>2020-03-03 06:08:16 +0300
commit3e1aa6cbf3df6f9f0f96380386a7c8d64c07cc64 (patch)
tree45ffc63d775b19beb441a76067b22427ae8eb20f /source/blender/editors
parenta976fe42ef74e77744f571578bf52998af491cb9 (diff)
Transform Snap: Clear 'SnapObjectData' after changes in the geometry
Differential Revision: https://developer.blender.org/D6927
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/transform/transform_snap_object.c126
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);