Transform Snap: Unify SnapObjectData struct

This simplifies the code, and will allow to switch modes.
This commit is contained in:
Germano Cavalcante 2020-02-27 08:42:44 -03:00
parent 6d705693a3
commit edb5e19442
1 changed files with 159 additions and 136 deletions

View File

@ -19,9 +19,6 @@
*/
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include <stdio.h>
#include "MEM_guardedalloc.h"
@ -34,10 +31,10 @@
#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
@ -50,19 +47,16 @@
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_tracking.h"
#include "BKE_context.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
#include "ED_transform.h"
#include "ED_transform_snap_object_context.h"
#include "ED_view3d.h"
#include "ED_armature.h"
#include "transform.h"
#include "ED_transform.h"
/* -------------------------------------------------------------------- */
/** \name Internal Data Types
@ -92,26 +86,28 @@ typedef struct SnapObjectData {
SNAP_MESH = 1,
SNAP_EDIT_MESH,
} type;
BVHTree *bvhtree[2]; /* MESH: loose edges, loose verts
* EDIT_MESH: verts, edges. */
bool cached[2];
union {
struct {
/* SNAP_MESH */
BVHTreeFromMesh treedata_mesh;
const struct MPoly *poly;
uint has_looptris : 1;
uint has_loose_edge : 1;
uint has_loose_vert : 1;
};
struct {
/* SNAP_EDIT_MESH */
BVHTreeFromEditMesh treedata_editmesh;
float min[3], max[3];
};
};
} SnapObjectData;
typedef struct SnapObjectData_Mesh {
SnapObjectData sd;
BVHTreeFromMesh treedata;
const struct MPoly *poly;
BVHTree *bvhtree[2]; /* from loose verts and from loose edges */
uint has_looptris : 1;
uint has_loose_edge : 1;
uint has_loose_vert : 1;
} SnapObjectData_Mesh;
typedef struct SnapObjectData_EditMesh {
SnapObjectData sd;
BVHTreeFromEditMesh *bvh_trees[3];
float min[3], max[3];
} SnapObjectData_EditMesh;
struct SnapObjectContext {
Main *bmain;
Scene *scene;
@ -149,7 +145,7 @@ struct SnapObjectContext {
/** \} */
/* -------------------------------------------------------------------- */
/** \name Common Utilities
/** \name Snap Object Data
* \{ */
/**
@ -166,6 +162,45 @@ static void bm_mesh_minmax(BMesh *bm, float r_min[3], float r_max[3])
}
}
static void snap_object_data_mesh_clear(SnapObjectData *sod)
{
BLI_assert(sod->type == SNAP_MESH);
for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) {
if (!sod->cached[i]) {
BLI_bvhtree_free(sod->bvhtree[i]);
}
sod->bvhtree[i] = NULL;
}
free_bvhtree_from_mesh(&sod->treedata_mesh);
}
static void snap_object_data_editmesh_clear(SnapObjectData *sod)
{
BLI_assert(sod->type == SNAP_EDIT_MESH);
for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) {
if (!sod->cached[i]) {
BLI_bvhtree_free(sod->bvhtree[i]);
}
sod->bvhtree[i] = NULL;
}
free_bvhtree_from_editmesh(&sod->treedata_editmesh);
}
static void snap_object_data_clear(SnapObjectData *sod)
{
switch (sod->type) {
case SNAP_MESH: {
snap_object_data_mesh_clear(sod);
break;
}
case SNAP_EDIT_MESH: {
snap_object_data_editmesh_clear(sod);
break;
}
}
memset(&sod->type, 0x0, sizeof(*sod) - offsetof(SnapObjectData, type));
}
static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *ob)
{
SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
@ -181,15 +216,17 @@ static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *
return sod;
}
static SnapObjectData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob)
static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob)
{
void **sod_p;
if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_MESH);
}
else {
SnapObjectData_Mesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
sod->sd.type = SNAP_MESH;
SnapObjectData *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
/* Init. */
sod->type = SNAP_MESH;
/* start assuming that it has each of these element types */
sod->has_looptris = true;
sod->has_loose_edge = true;
@ -199,9 +236,9 @@ static SnapObjectData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, O
return *sod_p;
}
static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx,
Object *ob,
BMEditMesh *em)
static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
Object *ob,
BMEditMesh *em)
{
void **sod_p;
@ -224,15 +261,23 @@ static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext
BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_EDIT_MESH);
}
else {
SnapObjectData_EditMesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena,
sizeof(*sod));
sod->sd.type = SNAP_EDIT_MESH;
SnapObjectData *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
/* Init. */
sod->type = SNAP_EDIT_MESH;
sod->treedata_editmesh.em = em;
bm_mesh_minmax(em->bm, sod->min, sod->max);
}
return *sod_p;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Iterator
* \{ */
typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx,
bool is_obedit,
bool use_backface_culling,
@ -516,9 +561,9 @@ static bool raycastMesh(SnapObjectContext *sctx,
len_diff = 0.0f;
}
SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob);
BVHTreeFromMesh *treedata = &sod->treedata;
BVHTreeFromMesh *treedata = &sod->treedata_mesh;
/* The tree is owned by the Mesh and may have been freed since we last used. */
if (treedata->tree) {
@ -668,7 +713,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
local_depth *= local_scale;
}
SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob, em);
SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob, em);
/* Test BoundBox */
@ -690,24 +735,21 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
len_diff = 0.0f;
}
if (sod->bvh_trees[2] == NULL) {
sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(BVHTreeFromEditMesh));
}
BVHTreeFromEditMesh *treedata = sod->bvh_trees[2];
BVHTreeFromEditMesh *treedata = &sod->treedata_editmesh;
BVHCache **em_bvh_cache = &((Mesh *)ob->data)->runtime.bvh_cache;
if (sctx->callbacks.edit_mesh.test_face_fn == NULL) {
if (treedata->tree && treedata->cached) {
/* The tree is owned by the Mesh and may have been freed since we last used! */
if (treedata->tree && !bvhcache_has_tree(*em_bvh_cache, treedata->tree)) {
free_bvhtree_from_editmesh(treedata);
if (!bvhcache_has_tree(*em_bvh_cache, treedata->tree)) {
treedata->tree = NULL;
}
}
if (treedata->tree == NULL) {
/* Get original version of the edit_mesh. */
BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
BLI_assert(sod->treedata_editmesh.em == BKE_editmesh_from_object(DEG_get_original_object(ob)));
BMEditMesh *em_orig = sod->treedata_editmesh.em;
if (sctx->callbacks.edit_mesh.test_face_fn) {
BMesh *bm = em_orig->bm;
@ -796,7 +838,7 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
if (r_index) {
/* Get original version of the edit_mesh. */
BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
BMEditMesh *em_orig = sod->treedata_editmesh.em;
*r_index = BM_elem_index_get(em_orig->looptris[hit.index][0]->f);
}
@ -850,7 +892,10 @@ static bool raycastObj(SnapObjectContext *sctx,
Mesh *me = ob->data;
bool use_hide = false;
if (BKE_object_is_in_editmode(ob)) {
BMEditMesh *em = BKE_editmesh_from_object(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));
if (use_obedit) {
retval = raycastEditMesh(sctx,
ray_start,
@ -1400,14 +1445,14 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
BLI_assert(sod != NULL);
if (sod->type == SNAP_MESH) {
BVHTreeFromMesh *treedata = &((SnapObjectData_Mesh *)sod)->treedata;
BVHTreeFromMesh *treedata = &sod->treedata_mesh;
nearest2d.userdata = treedata;
nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
const MPoly *mp = &((SnapObjectData_Mesh *)sod)->poly[*r_index];
const MPoly *mp = &sod->poly[*r_index];
const MLoop *ml = &treedata->loop[mp->loopstart];
if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
elem = SCE_SNAP_MODE_EDGE;
@ -1435,7 +1480,7 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
}
else {
BLI_assert(sod->type == SNAP_EDIT_MESH);
BMEditMesh *em = BKE_editmesh_from_object(ob);
BMEditMesh *em = sod->treedata_editmesh.em;
nearest2d.userdata = em;
nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
@ -1525,14 +1570,14 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
nearest2d.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
nearest2d.use_backface_culling = use_backface_culling;
if (sod->type == SNAP_MESH) {
nearest2d.userdata = &((SnapObjectData_Mesh *)sod)->treedata;
nearest2d.userdata = &sod->treedata_mesh;
nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
}
else {
BLI_assert(sod->type == SNAP_EDIT_MESH);
nearest2d.userdata = BKE_editmesh_from_object(ob);
nearest2d.userdata = sod->treedata_editmesh.em;
nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get;
nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy;
@ -2160,27 +2205,23 @@ static short snapMesh(SnapObjectContext *sctx,
return 0;
}
SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob);
BVHTreeFromMesh *treedata, dummy_treedata;
BVHTree **bvhtree;
treedata = &sod->treedata;
bvhtree = sod->bvhtree;
treedata = &sod->treedata_mesh;
/* The tree is owned by the Mesh and may have been freed since we last used! */
if ((sod->has_looptris && treedata->tree &&
!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) ||
(sod->has_loose_edge && bvhtree[0] &&
!bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0])) ||
(sod->has_loose_vert && bvhtree[1] &&
!bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]))) {
BLI_assert(!treedata->tree || !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree));
BLI_assert(!bvhtree[0] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0]));
BLI_assert(!bvhtree[1] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]));
if (treedata->cached && treedata->tree &&
!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
free_bvhtree_from_mesh(treedata);
bvhtree[0] = NULL;
bvhtree[1] = NULL;
}
if (sod->cached[0] && sod->bvhtree[0] &&
!bvhcache_has_tree(me->runtime.bvh_cache, sod->bvhtree[0])) {
sod->bvhtree[0] = NULL;
}
if (sod->cached[1] && sod->bvhtree[1] &&
!bvhcache_has_tree(me->runtime.bvh_cache, sod->bvhtree[1])) {
sod->bvhtree[1] = NULL;
}
if (sod->has_looptris && treedata->tree == NULL) {
@ -2191,9 +2232,10 @@ static short snapMesh(SnapObjectContext *sctx,
treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
}
}
if (sod->has_loose_edge && bvhtree[0] == NULL) {
bvhtree[0] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEEDGES, 2);
sod->has_loose_edge = bvhtree[0] != NULL;
if (sod->has_loose_edge && sod->bvhtree[0] == NULL) {
sod->bvhtree[0] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEEDGES, 2);
sod->has_loose_edge = sod->bvhtree[0] != NULL;
sod->cached[0] = dummy_treedata.cached;
if (sod->has_loose_edge) {
BLI_assert(treedata->vert_allocated == false);
@ -2206,9 +2248,10 @@ static short snapMesh(SnapObjectContext *sctx,
}
}
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
if (sod->has_loose_vert && bvhtree[1] == NULL) {
bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2);
sod->has_loose_vert = bvhtree[1] != NULL;
if (sod->has_loose_vert && sod->bvhtree[1] == NULL) {
sod->bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2);
sod->has_loose_vert = sod->bvhtree[1] != NULL;
sod->cached[1] = dummy_treedata.cached;
if (sod->has_loose_vert) {
BLI_assert(treedata->vert_allocated == false);
@ -2226,7 +2269,7 @@ static short snapMesh(SnapObjectContext *sctx,
if (treedata->vert_allocated == false) {
treedata->vert = me->mvert; /* CustomData_get_layer(&me->vdata, CD_MVERT);? */
}
if (treedata->tree || bvhtree[0]) {
if (treedata->tree || sod->bvhtree[0]) {
if (treedata->edge_allocated == false) {
/* If raycast has been executed before, `treedata->edge` can be NULL. */
treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
@ -2263,9 +2306,9 @@ static short snapMesh(SnapObjectContext *sctx,
mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
}
if (bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
if (sod->bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
/* snap to loose verts */
BLI_bvhtree_find_nearest_projected(bvhtree[1],
BLI_bvhtree_find_nearest_projected(sod->bvhtree[1],
lpmat,
snapdata->win_size,
snapdata->mval,
@ -2279,9 +2322,9 @@ static short snapMesh(SnapObjectContext *sctx,
}
if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
if (bvhtree[0]) {
if (sod->bvhtree[0]) {
/* snap to loose edges */
BLI_bvhtree_find_nearest_projected(bvhtree[0],
BLI_bvhtree_find_nearest_projected(sod->bvhtree[0],
lpmat,
snapdata->win_size,
snapdata->mval,
@ -2311,9 +2354,9 @@ static short snapMesh(SnapObjectContext *sctx,
}
else {
BLI_assert(snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX);
if (bvhtree[0]) {
/* snap to loose edges */
BLI_bvhtree_find_nearest_projected(bvhtree[0],
if (sod->bvhtree[0]) {
/* snap to loose edge verts */
BLI_bvhtree_find_nearest_projected(sod->bvhtree[0],
lpmat,
snapdata->win_size,
snapdata->mval,
@ -2325,7 +2368,7 @@ static short snapMesh(SnapObjectContext *sctx,
}
if (treedata->tree) {
/* snap to looptris */
/* snap to looptri verts */
BLI_bvhtree_find_nearest_projected(treedata->tree,
lpmat,
snapdata->win_size,
@ -2388,17 +2431,12 @@ static short snapEditMesh(SnapObjectContext *sctx,
}
}
BVHTreeFromEditMesh *treedata_vert = NULL, *treedata_edge = NULL;
BLI_assert(BKE_object_get_pre_modified_mesh(ob) == BKE_object_get_pre_modified_mesh(ob));
UNUSED_VARS_NDEBUG(ob);
float lpmat[4][4];
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
float dist_px_sq = SQUARE(*dist_px);
SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob, em);
SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob, em);
/* Test BoundBox */
@ -2411,19 +2449,16 @@ static short snapEditMesh(SnapObjectContext *sctx,
BVHCache **em_bvh_cache = &((Mesh *)ob->data)->runtime.bvh_cache;
if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
if (sod->bvh_trees[0] == NULL) {
sod->bvh_trees[0] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
}
treedata_vert = sod->bvh_trees[0];
BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[0]};
if (sctx->callbacks.edit_mesh.test_vert_fn == NULL) {
if (treedata.tree && sod->cached[0]) {
/* The tree is owned by the Mesh and may have been freed since we last used! */
if (treedata_vert->tree && !bvhcache_has_tree(*em_bvh_cache, treedata_vert->tree)) {
free_bvhtree_from_editmesh(treedata_vert);
if (!bvhcache_has_tree(*em_bvh_cache, treedata.tree)) {
treedata.tree = sod->bvhtree[0] = NULL;
}
}
if (treedata_vert->tree == NULL) {
if (treedata.tree == NULL) {
BLI_bitmap *verts_mask = NULL;
int verts_num_active = -1;
if (sctx->callbacks.edit_mesh.test_vert_fn) {
@ -2436,29 +2471,28 @@ static short snapEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_verts_ex(
treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL);
&treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL);
MEM_freeN(verts_mask);
}
else {
BKE_bvhtree_from_editmesh_get(treedata_vert, em, 2, BVHTREE_FROM_EM_VERTS, em_bvh_cache);
BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_VERTS, em_bvh_cache);
}
sod->bvhtree[0] = treedata.tree;
sod->cached[0] = treedata.cached;
}
}
if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
if (sod->bvh_trees[1] == NULL) {
sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
}
treedata_edge = sod->bvh_trees[1];
BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[1]};
if (sctx->callbacks.edit_mesh.test_edge_fn == NULL) {
if (treedata.tree && sod->cached[1]) {
/* The tree is owned by the Mesh and may have been freed since we last used! */
if (treedata_edge->tree && !bvhcache_has_tree(*em_bvh_cache, treedata_edge->tree)) {
free_bvhtree_from_editmesh(treedata_edge);
if (!bvhcache_has_tree(*em_bvh_cache, treedata.tree)) {
treedata.tree = sod->bvhtree[1] = NULL;
}
}
if (treedata_edge->tree == NULL) {
if (treedata.tree == NULL) {
BLI_bitmap *edges_mask = NULL;
int edges_num_active = -1;
if (sctx->callbacks.edit_mesh.test_edge_fn) {
@ -2471,12 +2505,14 @@ static short snapEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_edges_ex(
treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL);
&treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL);
MEM_freeN(edges_mask);
}
else {
BKE_bvhtree_from_editmesh_get(treedata_edge, em, 2, BVHTREE_FROM_EM_EDGES, em_bvh_cache);
BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_EDGES, em_bvh_cache);
}
sod->bvhtree[1] = treedata.tree;
sod->cached[1] = treedata.cached;
}
}
@ -2502,10 +2538,10 @@ static short snapEditMesh(SnapObjectContext *sctx,
mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
}
if (treedata_vert && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
if (sod->bvhtree[0] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
BLI_bvhtree_find_nearest_projected(treedata_vert->tree,
BLI_bvhtree_find_nearest_projected(sod->bvhtree[0],
lpmat,
snapdata->win_size,
snapdata->mval,
@ -2516,12 +2552,12 @@ static short snapEditMesh(SnapObjectContext *sctx,
&nearest2d);
}
if (treedata_edge && (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE)) {
if (sod->bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE)) {
int last_index = nearest.index;
nearest.index = -1;
BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
BM_mesh_elem_index_ensure(em->bm, BM_EDGE | BM_VERT);
BLI_bvhtree_find_nearest_projected(treedata_edge->tree,
BLI_bvhtree_find_nearest_projected(sod->bvhtree[1],
lpmat,
snapdata->win_size,
snapdata->mval,
@ -2588,7 +2624,10 @@ static short snapObject(SnapObjectContext *sctx,
case OB_MESH: {
Mesh *me = ob->data;
if (BKE_object_is_in_editmode(ob)) {
BMEditMesh *em = BKE_editmesh_from_object(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));
if (use_obedit) {
retval = snapEditMesh(
sctx, snapdata, ob, em, obmat, use_backface_culling, dist_px, r_loc, r_no, r_index);
@ -2794,24 +2833,8 @@ SnapObjectContext *ED_transform_snap_object_context_create_view3d(Main *bmain,
static void snap_object_data_free(void *sod_v)
{
switch (((SnapObjectData *)sod_v)->type) {
case SNAP_MESH: {
SnapObjectData_Mesh *sod = sod_v;
if (sod->treedata.tree) {
free_bvhtree_from_mesh(&sod->treedata);
}
break;
}
case SNAP_EDIT_MESH: {
SnapObjectData_EditMesh *sod = sod_v;
for (int i = 0; i < ARRAY_SIZE(sod->bvh_trees); i++) {
if (sod->bvh_trees[i]) {
free_bvhtree_from_editmesh(sod->bvh_trees[i]);
}
}
break;
}
}
SnapObjectData *sod = sod_v;
snap_object_data_clear(sod);
}
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)