Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/transform/transform_snap_object.c
| Show First 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | typedef struct SnapObjectData_Mesh { | ||||
| uint has_loose_edge : 1; | uint has_loose_edge : 1; | ||||
| uint has_loose_vert : 1; | uint has_loose_vert : 1; | ||||
| } SnapObjectData_Mesh; | } SnapObjectData_Mesh; | ||||
| typedef struct SnapObjectData_EditMesh { | typedef struct SnapObjectData_EditMesh { | ||||
| SnapObjectData sd; | SnapObjectData sd; | ||||
| BVHTreeFromEditMesh *bvh_trees[3]; | BVHTreeFromEditMesh *bvh_trees[3]; | ||||
| float min[3], max[3]; | |||||
campbellbarton: It should be noted here why the min/max is needed (not just in patch description). | |||||
| } SnapObjectData_EditMesh; | } SnapObjectData_EditMesh; | ||||
| struct SnapObjectContext { | struct SnapObjectContext { | ||||
| Main *bmain; | Main *bmain; | ||||
| Scene *scene; | Scene *scene; | ||||
| Depsgraph *depsgraph; | Depsgraph *depsgraph; | ||||
| Show All 30 Lines | |||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** Common Utilities | /** Common Utilities | ||||
| * \{ */ | * \{ */ | ||||
| typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data); | typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data); | ||||
| static void min_max_from_bmesh( | |||||
| BMesh *bm, float r_min[3], float r_max[3]) | |||||
| { | |||||
| BMIter iter; | |||||
| BMVert *eve; | |||||
| INIT_MINMAX(r_min, r_max); | |||||
| BM_ITER_MESH(eve, &iter, bm, BM_VERTS_OF_MESH) { | |||||
| minmax_v3v3_v3(r_min, r_max, eve->co); | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Walks through all objects in the scene to create the list of objets to snap. | * Walks through all objects in the scene to create the list of objets to snap. | ||||
| * | * | ||||
| * \param sctx: Snap context to store data. | * \param sctx: Snap context to store data. | ||||
| * \param snap_select : from enum eSnapSelect. | * \param snap_select : from enum eSnapSelect. | ||||
| * \param obedit : Object Edited to use its coordinates of BMesh(if any) to do the snapping. | * \param obedit : Object Edited to use its coordinates of BMesh(if any) to do the snapping. | ||||
| */ | */ | ||||
| static void iter_snap_objects( | static void iter_snap_objects( | ||||
| SnapObjectContext *sctx, | SnapObjectContext *sctx, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| IterSnapObjsCallback sob_callback, | IterSnapObjsCallback sob_callback, | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| ViewLayer *view_layer = DEG_get_evaluated_view_layer(sctx->depsgraph); | ViewLayer *view_layer = DEG_get_evaluated_view_layer(sctx->depsgraph); | ||||
| Object *obedit = params->use_object_edit_cage ? OBEDIT_FROM_VIEW_LAYER(view_layer) : NULL; | |||||
| const eSnapSelect snap_select = params->snap_select; | const eSnapSelect snap_select = params->snap_select; | ||||
| const bool use_object_edit_cage = params->use_object_edit_cage; | |||||
| Base *base_act = view_layer->basact; | Base *base_act = view_layer->basact; | ||||
| for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) { | for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) { | ||||
| if ((BASE_VISIBLE(base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 && | if ((BASE_VISIBLE(base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 && | ||||
| !((snap_select == SNAP_NOT_SELECTED && ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) || | !((snap_select == SNAP_NOT_SELECTED && ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) || | ||||
| (snap_select == SNAP_NOT_ACTIVE && base == base_act))) | (snap_select == SNAP_NOT_ACTIVE && base == base_act))) | ||||
| { | { | ||||
| bool use_obedit; | |||||
| Object *obj = base->object; | Object *obj = base->object; | ||||
| if (obj->transflag & OB_DUPLI) { | if (obj->transflag & OB_DUPLI) { | ||||
| DupliObject *dupli_ob; | DupliObject *dupli_ob; | ||||
| ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj); | ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj); | ||||
| for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { | for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { | ||||
| use_obedit = obedit && dupli_ob->ob->data == obedit->data; | sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data); | ||||
| sob_callback(sctx, use_obedit, use_obedit ? obedit : dupli_ob->ob, dupli_ob->mat, data); | |||||
| } | } | ||||
| free_object_duplilist(lb); | free_object_duplilist(lb); | ||||
| } | } | ||||
| use_obedit = obedit && obj->data == obedit->data; | sob_callback(sctx, use_object_edit_cage, obj, obj->obmat, data); | ||||
| sob_callback(sctx, use_obedit, use_obedit ? obedit : obj, obj->obmat, data); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static bool walk_parent_bvhroot_cb(const BVHTreeAxisRange *bounds, void *userdata) | static bool walk_parent_bvhroot_cb(const BVHTreeAxisRange *bounds, void *userdata) | ||||
| { | { | ||||
| BVHTreeRay *ray = userdata; | BVHTreeRay *ray = userdata; | ||||
| ▲ Show 20 Lines • Show All 159 Lines • ▼ Show 20 Lines | if (bb) { | ||||
| { | { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| } | } | ||||
| SnapObjectData_Mesh *sod = NULL; | SnapObjectData_Mesh *sod = NULL; | ||||
| void **sod_p; | void **sod_p; | ||||
| if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { | if (BLI_ghash_ensure_p(sctx->cache.object_map, me, &sod_p)) { | ||||
| sod = *sod_p; | sod = *sod_p; | ||||
| } | } | ||||
| else { | else { | ||||
| sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); | sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); | ||||
| sod->sd.type = SNAP_MESH; | sod->sd.type = SNAP_MESH; | ||||
| } | } | ||||
| BVHTreeFromMesh *treedata = &sod->treedata; | BVHTreeFromMesh *treedata = &sod->treedata; | ||||
| /* The tree is owned by the DM and may have been freed since we last used. */ | /* The tree is owned by the Mesh and may have been freed since we last used. */ | ||||
| if (treedata->tree) { | if (treedata->tree) { | ||||
| BLI_assert(treedata->cached); | BLI_assert(treedata->cached); | ||||
| if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) { | if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) { | ||||
| free_bvhtree_from_mesh(treedata); | free_bvhtree_from_mesh(treedata); | ||||
| } | } | ||||
| else { | else { | ||||
| /* Update Pointers. */ | /* Update Pointers. */ | ||||
| if (treedata->vert && treedata->vert_allocated == false) { | if (treedata->vert && treedata->vert_allocated == false) { | ||||
| ▲ Show 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | static bool raycastEditMesh( | ||||
| float r_loc[3], float r_no[3], int *r_index, | float r_loc[3], float r_no[3], int *r_index, | ||||
| ListBase *r_hit_list) | ListBase *r_hit_list) | ||||
| { | { | ||||
| bool retval = false; | bool retval = false; | ||||
| if (em->bm->totface == 0) { | if (em->bm->totface == 0) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| Mesh *me = ob->data; | |||||
| SnapObjectData_EditMesh *sod = NULL; | SnapObjectData_EditMesh *sod = NULL; | ||||
| BVHTreeFromEditMesh *treedata = NULL; | BVHTreeFromEditMesh *treedata = NULL; | ||||
| void **sod_p; | void **sod_p; | ||||
| if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { | if (BLI_ghash_ensure_p(sctx->cache.object_map, em, &sod_p)) { | ||||
| sod = *sod_p; | sod = *sod_p; | ||||
| } | } | ||||
| else { | else { | ||||
| sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); | sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); | ||||
| sod->sd.type = SNAP_EDIT_MESH; | sod->sd.type = SNAP_EDIT_MESH; | ||||
| min_max_from_bmesh(em->bm, sod->min, sod->max); | |||||
| } | |||||
| { | |||||
| float min[3], max[3]; | |||||
| mul_v3_m4v3(min, obmat, sod->min); | |||||
| mul_v3_m4v3(max, obmat, sod->max); | |||||
| if (!isect_ray_aabb_v3_simple( | |||||
| ray_start, ray_dir, min, max, NULL, NULL)) | |||||
| { | |||||
| return retval; | |||||
| } | |||||
| } | } | ||||
| if (sod->bvh_trees[2] == NULL) { | if (sod->bvh_trees[2] == NULL) { | ||||
| sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); | sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata)); | ||||
| } | } | ||||
| treedata = sod->bvh_trees[2]; | treedata = sod->bvh_trees[2]; | ||||
| if (sctx->callbacks.edit_mesh.test_face_fn == NULL) { | |||||
| /* The tree is owned by the Mesh and may have been freed since we last used! */ | |||||
| if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) { | |||||
| free_bvhtree_from_editmesh(treedata); | |||||
| } | |||||
| } | |||||
| if (treedata->tree == NULL) { | if (treedata->tree == NULL) { | ||||
| BVHCache **bvh_cache = NULL; | |||||
| BLI_bitmap *elem_mask = NULL; | BLI_bitmap *elem_mask = NULL; | ||||
| int looptri_num_active = -1; | int looptri_num_active = -1; | ||||
| if (sctx->callbacks.edit_mesh.test_face_fn) { | if (sctx->callbacks.edit_mesh.test_face_fn) { | ||||
| elem_mask = BLI_BITMAP_NEW(em->tottri, __func__); | elem_mask = BLI_BITMAP_NEW(em->tottri, __func__); | ||||
| looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( | looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( | ||||
| em->bm, elem_mask, | em->bm, elem_mask, | ||||
| sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data); | sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data); | ||||
| } | } | ||||
| bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL); | else { | ||||
| /* Only cache if bvhtree is created without a mask. | |||||
| * This helps keep a standardized bvhtree in cache. */ | |||||
| bvh_cache = &me->runtime.bvh_cache; | |||||
| } | |||||
| bvhtree_from_editmesh_looptri_ex( | |||||
| treedata, em, elem_mask, looptri_num_active, | |||||
| 0.0f, 4, 6, bvh_cache); | |||||
| if (elem_mask) { | if (elem_mask) { | ||||
| MEM_freeN(elem_mask); | MEM_freeN(elem_mask); | ||||
| } | } | ||||
| if (treedata->tree == NULL) { | if (treedata->tree == NULL) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | if (use_occlusion_test) { | ||||
| { | { | ||||
| /* Use of occlude geometry in editing mode disabled. */ | /* Use of occlude geometry in editing mode disabled. */ | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| switch (ob->type) { | switch (ob->type) { | ||||
| case OB_MESH: | case OB_MESH: | ||||
| if (use_obedit) { | if (use_obedit && BKE_object_is_in_editmode(ob)) { | ||||
| BMEditMesh *em = BKE_editmesh_from_object(ob); | BMEditMesh *em = BKE_editmesh_from_object(ob); | ||||
| retval = raycastEditMesh( | retval = raycastEditMesh( | ||||
| sctx, | sctx, | ||||
| ray_start, ray_dir, | ray_start, ray_dir, | ||||
| ob, em, obmat, ob_index, | ob, em, obmat, ob_index, | ||||
| ray_depth, r_loc, r_no, r_index, r_hit_list); | ray_depth, r_loc, r_no, r_index, r_hit_list); | ||||
| } | } | ||||
| else { | else { | ||||
| Show All 32 Lines | struct RaycastObjUserData { | ||||
| int *r_index; | int *r_index; | ||||
| Object **r_ob; | Object **r_ob; | ||||
| float (*r_obmat)[4]; | float (*r_obmat)[4]; | ||||
| ListBase *r_hit_list; | ListBase *r_hit_list; | ||||
| bool use_occlusion_test; | bool use_occlusion_test; | ||||
| bool ret; | bool ret; | ||||
| }; | }; | ||||
| static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data) | static void raycast_obj_cb(SnapObjectContext *sctx, bool use_obedit, Object *ob, float obmat[4][4], void *data) | ||||
| { | { | ||||
| struct RaycastObjUserData *dt = data; | struct RaycastObjUserData *dt = data; | ||||
| dt->ret |= raycastObj( | dt->ret |= raycastObj( | ||||
| sctx, | sctx, | ||||
| dt->ray_start, dt->ray_dir, | dt->ray_start, dt->ray_dir, | ||||
| ob, obmat, dt->ob_index++, | ob, obmat, dt->ob_index++, | ||||
| is_obedit, dt->use_occlusion_test, | use_obedit, dt->use_occlusion_test, | ||||
| dt->ray_depth, | dt->ray_depth, | ||||
| dt->r_loc, dt->r_no, dt->r_index, | dt->r_loc, dt->r_no, dt->r_index, | ||||
| dt->r_ob, dt->r_obmat, | dt->r_ob, dt->r_obmat, | ||||
| dt->r_hit_list); | dt->r_hit_list); | ||||
| } | } | ||||
| /** | /** | ||||
| * Main RayCast Function | * Main RayCast Function | ||||
| ▲ Show 20 Lines • Show All 592 Lines • ▼ Show 20 Lines | static short snapArmature( | ||||
| float lpmat[4][4], dist_px_sq = SQUARE(*dist_px); | float lpmat[4][4], dist_px_sq = SQUARE(*dist_px); | ||||
| mul_m4_m4m4(lpmat, snapdata->pmat, obmat); | mul_m4_m4m4(lpmat, snapdata->pmat, obmat); | ||||
| struct DistProjectedAABBPrecalc neasrest_precalc; | struct DistProjectedAABBPrecalc neasrest_precalc; | ||||
| dist_squared_to_projected_aabb_precalc( | dist_squared_to_projected_aabb_precalc( | ||||
| &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval); | &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval); | ||||
| use_obedit = use_obedit && BKE_object_is_in_editmode(ob); | |||||
| if (use_obedit == false) { | if (use_obedit == false) { | ||||
| /* Test BoundBox */ | /* Test BoundBox */ | ||||
| BoundBox *bb = BKE_armature_boundbox_get(ob); | BoundBox *bb = BKE_armature_boundbox_get(ob); | ||||
| if (bb) { | if (bb) { | ||||
| bool dummy[3]; | bool dummy[3]; | ||||
| /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */ | /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */ | ||||
| float bb_dist_px_sq = dist_squared_to_projected_aabb( | float bb_dist_px_sq = dist_squared_to_projected_aabb( | ||||
| &neasrest_precalc, bb->vec[0], bb->vec[6], dummy); | &neasrest_precalc, bb->vec[0], bb->vec[6], dummy); | ||||
| ▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | static short snapCurve( | ||||
| float lpmat[4][4]; | float lpmat[4][4]; | ||||
| mul_m4_m4m4(lpmat, snapdata->pmat, obmat); | mul_m4_m4m4(lpmat, snapdata->pmat, obmat); | ||||
| struct DistProjectedAABBPrecalc neasrest_precalc; | struct DistProjectedAABBPrecalc neasrest_precalc; | ||||
| dist_squared_to_projected_aabb_precalc( | dist_squared_to_projected_aabb_precalc( | ||||
| &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval); | &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval); | ||||
| use_obedit = use_obedit && BKE_object_is_in_editmode(ob); | |||||
| if (use_obedit == false) { | if (use_obedit == false) { | ||||
| /* Test BoundBox */ | /* Test BoundBox */ | ||||
| BoundBox *bb = BKE_curve_boundbox_get(ob); | BoundBox *bb = BKE_curve_boundbox_get(ob); | ||||
| if (bb) { | if (bb) { | ||||
| bool dummy[3]; | bool dummy[3]; | ||||
| /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */ | /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */ | ||||
| float bb_dist_px_sq = dist_squared_to_projected_aabb( | float bb_dist_px_sq = dist_squared_to_projected_aabb( | ||||
| &neasrest_precalc, bb->vec[0], bb->vec[6], dummy); | &neasrest_precalc, bb->vec[0], bb->vec[6], dummy); | ||||
| ▲ Show 20 Lines • Show All 290 Lines • ▼ Show 20 Lines | if (bb) { | ||||
| if (bb_dist_px_sq > dist_px_sq) { | if (bb_dist_px_sq > dist_px_sq) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| SnapObjectData_Mesh *sod = NULL; | SnapObjectData_Mesh *sod = NULL; | ||||
| void **sod_p; | void **sod_p; | ||||
| if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { | if (BLI_ghash_ensure_p(sctx->cache.object_map, me, &sod_p)) { | ||||
| sod = *sod_p; | sod = *sod_p; | ||||
| } | } | ||||
| else { | else { | ||||
| sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); | sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); | ||||
| sod->sd.type = SNAP_MESH; | sod->sd.type = SNAP_MESH; | ||||
| /* start assuming that it has each of these element types */ | /* start assuming that it has each of these element types */ | ||||
| sod->has_looptris = true; | sod->has_looptris = true; | ||||
| sod->has_loose_edge = true; | sod->has_loose_edge = true; | ||||
| sod->has_loose_vert = true; | sod->has_loose_vert = true; | ||||
| } | } | ||||
| BVHTreeFromMesh *treedata, dummy_treedata; | BVHTreeFromMesh *treedata, dummy_treedata; | ||||
| BVHTree **bvhtree; | BVHTree **bvhtree; | ||||
| treedata = &sod->treedata; | treedata = &sod->treedata; | ||||
| bvhtree = sod->bvhtree; | bvhtree = sod->bvhtree; | ||||
| /* the tree is owned by the DM and may have been freed since we last used! */ | /* 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)) || | 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_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]))) | (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(!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[0] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0])); | ||||
| BLI_assert(!bvhtree[1] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1])); | BLI_assert(!bvhtree[1] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1])); | ||||
| ▲ Show 20 Lines • Show All 171 Lines • ▼ Show 20 Lines | if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) { | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| if (em->bm->totvert == 0) { | if (em->bm->totvert == 0) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| Mesh *me = ob->data; | |||||
| SnapObjectData_EditMesh *sod = NULL; | SnapObjectData_EditMesh *sod = NULL; | ||||
| BVHTreeFromEditMesh *treedata_vert = NULL, *treedata_edge = NULL; | BVHTreeFromEditMesh *treedata_vert = NULL, *treedata_edge = NULL; | ||||
| void **sod_p; | void **sod_p; | ||||
| if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) { | if (BLI_ghash_ensure_p(sctx->cache.object_map, em, &sod_p)) { | ||||
| sod = *sod_p; | sod = *sod_p; | ||||
| } | } | ||||
| else { | else { | ||||
| sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); | sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); | ||||
| sod->sd.type = SNAP_EDIT_MESH; | sod->sd.type = SNAP_EDIT_MESH; | ||||
| min_max_from_bmesh(em->bm, sod->min, sod->max); | |||||
| } | |||||
| float dist_px_sq = SQUARE(*dist_px); | |||||
| { | |||||
| float min[3], max[3]; | |||||
| mul_v3_m4v3(min, obmat, sod->min); | |||||
| mul_v3_m4v3(max, obmat, sod->max); | |||||
| /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */ | |||||
| struct DistProjectedAABBPrecalc data_precalc; | |||||
| dist_squared_to_projected_aabb_precalc( | |||||
| &data_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval); | |||||
| bool dummy[3]; | |||||
| float bb_dist_px_sq = dist_squared_to_projected_aabb( | |||||
| &data_precalc, min, max, dummy); | |||||
| if (bb_dist_px_sq > dist_px_sq) { | |||||
| return 0; | |||||
| } | |||||
| } | } | ||||
| if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) { | if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) { | ||||
| if (sod->bvh_trees[0] == NULL) { | if (sod->bvh_trees[0] == NULL) { | ||||
| sod->bvh_trees[0] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees)); | sod->bvh_trees[0] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees)); | ||||
| } | } | ||||
| treedata_vert = sod->bvh_trees[0]; | treedata_vert = sod->bvh_trees[0]; | ||||
| if (sctx->callbacks.edit_mesh.test_vert_fn == NULL) { | |||||
| /* The tree is owned by the Mesh and may have been freed since we last used! */ | |||||
| if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata_vert->tree)) { | |||||
| free_bvhtree_from_editmesh(treedata_vert); | |||||
| } | |||||
| } | |||||
| if (treedata_vert->tree == NULL) { | if (treedata_vert->tree == NULL) { | ||||
| BLI_bitmap *verts_mask = NULL; | BLI_bitmap *verts_mask = NULL; | ||||
| int verts_num_active = -1; | int verts_num_active = -1; | ||||
| if (sctx->callbacks.edit_mesh.test_vert_fn) { | if (sctx->callbacks.edit_mesh.test_vert_fn) { | ||||
| verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); | verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); | ||||
| verts_num_active = BM_iter_mesh_bitmap_from_filter( | verts_num_active = BM_iter_mesh_bitmap_from_filter( | ||||
| BM_VERTS_OF_MESH, em->bm, verts_mask, | BM_VERTS_OF_MESH, em->bm, verts_mask, | ||||
| (bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn, | (bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn, | ||||
| sctx->callbacks.edit_mesh.user_data); | sctx->callbacks.edit_mesh.user_data); | ||||
| } | |||||
| bvhtree_from_editmesh_verts_ex(treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6); | bvhtree_from_editmesh_verts_ex(treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6); | ||||
| MEM_SAFE_FREE(verts_mask); | MEM_freeN(verts_mask); | ||||
| } | |||||
| else { | |||||
| bvhtree_from_editmesh_verts(treedata_vert, em, 0.0f, 2, 6, &me->runtime.bvh_cache); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { | if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { | ||||
| if (sod->bvh_trees[1] == NULL) { | if (sod->bvh_trees[1] == NULL) { | ||||
| sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees)); | sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees)); | ||||
| } | } | ||||
| treedata_edge = sod->bvh_trees[1]; | treedata_edge = sod->bvh_trees[1]; | ||||
| if (sctx->callbacks.edit_mesh.test_edge_fn == NULL) { | |||||
| /* The tree is owned by the Mesh and may have been freed since we last used! */ | |||||
| if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata_edge->tree)) { | |||||
| free_bvhtree_from_editmesh(treedata_edge); | |||||
| } | |||||
| } | |||||
| if (treedata_edge->tree == NULL) { | if (treedata_edge->tree == NULL) { | ||||
| BLI_bitmap *edges_mask = NULL; | BLI_bitmap *edges_mask = NULL; | ||||
| int edges_num_active = -1; | int edges_num_active = -1; | ||||
| if (sctx->callbacks.edit_mesh.test_edge_fn) { | if (sctx->callbacks.edit_mesh.test_edge_fn) { | ||||
| edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__); | edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__); | ||||
| edges_num_active = BM_iter_mesh_bitmap_from_filter( | edges_num_active = BM_iter_mesh_bitmap_from_filter( | ||||
| BM_EDGES_OF_MESH, em->bm, edges_mask, | BM_EDGES_OF_MESH, em->bm, edges_mask, | ||||
| (bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn, | (bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn, | ||||
| sctx->callbacks.edit_mesh.user_data); | sctx->callbacks.edit_mesh.user_data); | ||||
| } | |||||
| bvhtree_from_editmesh_edges_ex(treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6); | bvhtree_from_editmesh_edges_ex(treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6); | ||||
| MEM_SAFE_FREE(edges_mask); | MEM_freeN(edges_mask); | ||||
| } | |||||
| else { | |||||
| bvhtree_from_editmesh_edges(treedata_edge, em, 0.0f, 2, 6, &me->runtime.bvh_cache); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| Nearest2dUserData nearest2d = { | Nearest2dUserData nearest2d = { | ||||
| .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, | .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, | ||||
| .userdata = em, | .userdata = em, | ||||
| .get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get, | .get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get, | ||||
| .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get, | .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get, | ||||
| .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy, | .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy, | ||||
| }; | }; | ||||
| BVHTreeNearest nearest = { | BVHTreeNearest nearest = { | ||||
| .index = -1, | .index = -1, | ||||
| .dist_sq = SQUARE(*dist_px), | .dist_sq = dist_px_sq, | ||||
| }; | }; | ||||
| int last_index = nearest.index; | int last_index = nearest.index; | ||||
| short elem = SCE_SNAP_MODE_VERTEX; | short elem = SCE_SNAP_MODE_VERTEX; | ||||
| float lpmat[4][4], tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | float lpmat[4][4], tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | ||||
| mul_m4_m4m4(lpmat, snapdata->pmat, obmat); | mul_m4_m4m4(lpmat, snapdata->pmat, obmat); | ||||
| transpose_m4_m4(tobmat, obmat); | transpose_m4_m4(tobmat, obmat); | ||||
| ▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | static short snapObject( | ||||
| /* return args */ | /* return args */ | ||||
| float r_loc[3], float r_no[3], int *r_index, | float r_loc[3], float r_no[3], int *r_index, | ||||
| Object **r_ob, float r_obmat[4][4]) | Object **r_ob, float r_obmat[4][4]) | ||||
| { | { | ||||
| short retval = 0; | short retval = 0; | ||||
| switch (ob->type) { | switch (ob->type) { | ||||
| case OB_MESH: | case OB_MESH: | ||||
| if (use_obedit) { | if (use_obedit && BKE_object_is_in_editmode(ob)) { | ||||
| BMEditMesh *em = BKE_editmesh_from_object(ob); | BMEditMesh *em = BKE_editmesh_from_object(ob); | ||||
| retval = snapEditMesh( | retval = snapEditMesh( | ||||
| sctx, snapdata, ob, em, obmat, | sctx, snapdata, ob, em, obmat, | ||||
| dist_px, | dist_px, | ||||
| r_loc, r_no, r_index); | r_loc, r_no, r_index); | ||||
| } | } | ||||
| else { | else { | ||||
| retval = snapMesh( | retval = snapMesh( | ||||
| ▲ Show 20 Lines • Show All 526 Lines • Show Last 20 Lines | |||||
It should be noted here why the min/max is needed (not just in patch description).