Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/transform/transform_snap_object.c
| Show First 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | |||||
| /* Mesh used for snapping. | /* Mesh used for snapping. | ||||
| * If NULL the BMesh should be used. */ | * If NULL the BMesh should be used. */ | ||||
| static Mesh *mesh_for_snap(Object *ob_eval, eSnapEditType edit_mode_type, bool *r_use_hide) | static Mesh *mesh_for_snap(Object *ob_eval, eSnapEditType edit_mode_type, bool *r_use_hide) | ||||
| { | { | ||||
| Mesh *me_eval = ob_eval->data; | Mesh *me_eval = ob_eval->data; | ||||
| bool use_hide = false; | bool use_hide = false; | ||||
| if (BKE_object_is_in_editmode(ob_eval)) { | if (BKE_object_is_in_editmode(ob_eval)) { | ||||
| if (edit_mode_type == SNAP_GEOM_EDIT) { | if (ELEM(edit_mode_type, SNAP_GEOM_EDIT, SNAP_GEOM_EDIT_DEFORMED)) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| BMEditMesh *em_eval = BKE_editmesh_from_object(ob_eval); | BMEditMesh *em_eval = BKE_editmesh_from_object(ob_eval); | ||||
| if ((edit_mode_type == SNAP_GEOM_FINAL) && em_eval->mesh_eval_final) { | if ((edit_mode_type == SNAP_GEOM_FINAL) && em_eval->mesh_eval_final) { | ||||
| if (em_eval->mesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) { | if (em_eval->mesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 175 Lines • ▼ Show 20 Lines | if (init) { | ||||
| /* Start assuming that it has each of these element types. */ | /* Start assuming that it has each of these element types. */ | ||||
| sod->has_loose_edge = true; | sod->has_loose_edge = true; | ||||
| sod->has_loose_vert = true; | sod->has_loose_vert = true; | ||||
| } | } | ||||
| return sod; | return sod; | ||||
| } | } | ||||
| static struct Mesh_Runtime *snap_object_data_editmesh_runtime_get(Object *ob_eval) | static SnapObjectData *snap_object_data_editmesh_get( | ||||
| { | SnapObjectContext *sctx, Depsgraph *depsgraph, Object *ob_eval, BMEditMesh *em, bool do_cageco) | ||||
| BMEditMesh *em_eval = BKE_editmesh_from_object(ob_eval); | |||||
| if (em_eval->mesh_eval_final) { | |||||
| return &em_eval->mesh_eval_final->runtime; | |||||
| } | |||||
| if (em_eval->mesh_eval_cage) { | |||||
| return &em_eval->mesh_eval_cage->runtime; | |||||
| } | |||||
| return &((Mesh *)ob_eval->data)->runtime; | |||||
| } | |||||
| static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, | |||||
| Object *ob_eval, | |||||
| BMEditMesh *em) | |||||
| { | { | ||||
| SnapObjectData *sod; | SnapObjectData *sod; | ||||
| void **sod_p; | void **sod_p; | ||||
| bool init = false; | bool init = false; | ||||
| { | { | ||||
| /* Use object-data as the key in ghash since the editmesh | /* Use object-data as the key in ghash since the editmesh | ||||
| * is used to create bvhtree and is the same for each linked object. */ | * is used to create bvhtree and is the same for each linked object. */ | ||||
| if (sctx->cache.data_to_object_map == NULL) { | if (sctx->cache.data_to_object_map == NULL) { | ||||
| sctx->cache.data_to_object_map = BLI_ghash_ptr_new(__func__); | sctx->cache.data_to_object_map = BLI_ghash_ptr_new(__func__); | ||||
| } | } | ||||
| void **ob_p; | void **ob_p; | ||||
| if (BLI_ghash_ensure_p(sctx->cache.data_to_object_map, ob_eval->data, &ob_p)) { | if (BLI_ghash_ensure_p(sctx->cache.data_to_object_map, ob_eval->data, &ob_p)) { | ||||
| ob_eval = *ob_p; | ob_eval = *ob_p; | ||||
| } | } | ||||
| else { | else { | ||||
| *ob_p = ob_eval; | *ob_p = ob_eval; | ||||
| } | } | ||||
| } | } | ||||
| BMEditMesh *em_eval = BKE_editmesh_from_object(ob_eval); | |||||
| Mesh *mesh_eval_cage = em_eval->mesh_eval_cage; | |||||
| Mesh_Runtime *mesh_runtime = mesh_eval_cage ? &mesh_eval_cage->runtime : | |||||
| em_eval->mesh_eval_final ? &em_eval->mesh_eval_final->runtime : | |||||
| &((Mesh *)ob_eval->data)->runtime; | |||||
| if (BLI_ghash_ensure_p(sctx->cache.object_map, ob_eval, &sod_p)) { | if (BLI_ghash_ensure_p(sctx->cache.object_map, ob_eval, &sod_p)) { | ||||
| sod = *sod_p; | sod = *sod_p; | ||||
| bool is_dirty = false; | bool is_dirty = false; | ||||
| /* Check if the geometry has changed. */ | /* Check if the geometry has changed. */ | ||||
| if (sod->type != SNAP_EDIT_MESH) { | if (sod->type != SNAP_EDIT_MESH) { | ||||
| is_dirty = true; | is_dirty = true; | ||||
| } | } | ||||
| else if (sod->treedata_editmesh.em != em) { | else if (sod->treedata_editmesh.em != em) { | ||||
| is_dirty = true; | is_dirty = true; | ||||
| } | } | ||||
| else if ((sod->treedata_editmesh.cageco != NULL) && !do_cageco) { | |||||
| is_dirty = true; | |||||
| } | |||||
| else if (do_cageco && sod->treedata_editmesh.cageco && !mesh_eval_cage || | |||||
| !mesh_runtime->edit_data || | |||||
| mesh_runtime->edit_data->vertexCos != sod->treedata_editmesh.cageco) { | |||||
| is_dirty = true; | |||||
| } | |||||
| else if (sod->mesh_runtime) { | else if (sod->mesh_runtime) { | ||||
| if (sod->mesh_runtime != snap_object_data_editmesh_runtime_get(ob_eval)) { | if (sod->mesh_runtime != mesh_runtime) { | ||||
| if (G.moving) { | if (G.moving) { | ||||
| /* Hack to avoid updating while transforming. */ | /* Hack to avoid updating while transforming. */ | ||||
| BLI_assert(!sod->treedata_editmesh.cached && !sod->cached[0] && !sod->cached[1]); | BLI_assert(!sod->treedata_editmesh.cached && !sod->cached[0] && !sod->cached[1]); | ||||
| sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob_eval); | sod->mesh_runtime = mesh_runtime; | ||||
| } | } | ||||
| else { | else { | ||||
| is_dirty = true; | is_dirty = true; | ||||
| } | } | ||||
| } | } | ||||
| else if (sod->treedata_editmesh.tree && sod->treedata_editmesh.cached && | else if (sod->treedata_editmesh.tree && sod->treedata_editmesh.cached && | ||||
| !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->treedata_editmesh.tree)) { | !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->treedata_editmesh.tree)) { | ||||
| /* The tree is owned by the EditMesh and may have been freed since we last used! */ | /* The tree is owned by the EditMesh and may have been freed since we last used! */ | ||||
| Show All 19 Lines | static SnapObjectData *snap_object_data_editmesh_get( | ||||
| 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)); | ||||
| init = true; | init = true; | ||||
| } | } | ||||
| if (init) { | if (init) { | ||||
| sod->type = SNAP_EDIT_MESH; | sod->type = SNAP_EDIT_MESH; | ||||
| sod->treedata_editmesh.em = em; | sod->treedata_editmesh.em = em; | ||||
| sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob_eval); | sod->mesh_runtime = mesh_runtime; | ||||
| if (do_cageco && mesh_eval_cage && !mesh_runtime->edit_data || | |||||
| mesh_runtime->edit_data->vertexCos) { | |||||
| BLI_assert(sod->treedata_editmesh.cageco == NULL); | |||||
| BKE_mesh_runtime_ensure_edit_data(em_eval->mesh_eval_cage); | |||||
| if (mesh_runtime->edit_data->vertexCos == NULL) { | |||||
| Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &sctx->scene->id); | |||||
| mesh_runtime->edit_data->vertexCos = BKE_editmesh_vert_coords_alloc( | |||||
| depsgraph, em_eval, scene_eval, ob_eval, NULL); | |||||
| } | |||||
| sod->treedata_editmesh.cageco = mesh_runtime->edit_data->vertexCos; | |||||
| INIT_MINMAX(sod->min, sod->max); | |||||
| minmax_v3v3_v3_array(sod->min, sod->max, sod->treedata_editmesh.cageco, em->bm->totvert); | |||||
| } | |||||
| else { | |||||
| bm_mesh_minmax(em->bm, sod->min, sod->max); | bm_mesh_minmax(em->bm, sod->min, sod->max); | ||||
| } | } | ||||
| } | |||||
| return sod; | return sod; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Iterator | /** \name Iterator | ||||
| * \{ */ | * \{ */ | ||||
| typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx, | typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx, | ||||
| Depsgraph *depsgraph, | |||||
| Object *ob_eval, | Object *ob_eval, | ||||
| float obmat[4][4], | float obmat[4][4], | ||||
| eSnapEditType edit_mode_type, | eSnapEditType edit_mode_type, | ||||
| bool use_backface_culling, | bool use_backface_culling, | ||||
| bool is_object_active, | bool is_object_active, | ||||
| void *data); | void *data); | ||||
| /** | /** | ||||
| Show All 9 Lines | static void iter_snap_objects(SnapObjectContext *sctx, | ||||
| const View3D *v3d = sctx->v3d_data.v3d; | const View3D *v3d = sctx->v3d_data.v3d; | ||||
| const eSnapSelect snap_select = params->snap_select; | const eSnapSelect snap_select = params->snap_select; | ||||
| const eSnapEditType edit_mode_type = params->edit_mode_type; | const eSnapEditType edit_mode_type = params->edit_mode_type; | ||||
| const bool use_backface_culling = params->use_backface_culling; | const bool use_backface_culling = params->use_backface_culling; | ||||
| Base *base_act = view_layer->basact; | Base *base_act = view_layer->basact; | ||||
| if (snap_select == SNAP_ONLY_ACTIVE) { | if (snap_select == SNAP_ONLY_ACTIVE) { | ||||
| Object *obj_eval = DEG_get_evaluated_object(depsgraph, base_act->object); | Object *obj_eval = DEG_get_evaluated_object(depsgraph, base_act->object); | ||||
| sob_callback( | sob_callback(sctx, | ||||
| sctx, obj_eval, obj_eval->obmat, edit_mode_type, use_backface_culling, true, data); | depsgraph, | ||||
| obj_eval, | |||||
| obj_eval->obmat, | |||||
| edit_mode_type, | |||||
| use_backface_culling, | |||||
| true, | |||||
| data); | |||||
| return; | return; | ||||
| } | } | ||||
| 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(v3d, base)) { | if (!BASE_VISIBLE(v3d, base)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| Show All 17 Lines | for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) { | ||||
| } | } | ||||
| Object *obj_eval = DEG_get_evaluated_object(depsgraph, base->object); | Object *obj_eval = DEG_get_evaluated_object(depsgraph, base->object); | ||||
| if (obj_eval->transflag & OB_DUPLI) { | if (obj_eval->transflag & OB_DUPLI) { | ||||
| DupliObject *dupli_ob; | DupliObject *dupli_ob; | ||||
| ListBase *lb = object_duplilist(depsgraph, sctx->scene, obj_eval); | ListBase *lb = object_duplilist(depsgraph, sctx->scene, obj_eval); | ||||
| for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { | for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { | ||||
| sob_callback(sctx, | sob_callback(sctx, | ||||
| depsgraph, | |||||
| dupli_ob->ob, | dupli_ob->ob, | ||||
| dupli_ob->mat, | dupli_ob->mat, | ||||
| edit_mode_type, | edit_mode_type, | ||||
| use_backface_culling, | use_backface_culling, | ||||
| is_object_active, | is_object_active, | ||||
| data); | data); | ||||
| } | } | ||||
| free_object_duplilist(lb); | free_object_duplilist(lb); | ||||
| } | } | ||||
| sob_callback(sctx, | sob_callback(sctx, | ||||
| depsgraph, | |||||
| obj_eval, | obj_eval, | ||||
| obj_eval->obmat, | obj_eval->obmat, | ||||
| edit_mode_type, | edit_mode_type, | ||||
| use_backface_culling, | use_backface_culling, | ||||
| is_object_active, | is_object_active, | ||||
| data); | data); | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 129 Lines • ▼ Show 20 Lines | static void editmesh_looptri_raycast_backface_culling_cb(void *userdata, | ||||
| const BVHTreeRay *ray, | const BVHTreeRay *ray, | ||||
| BVHTreeRayHit *hit) | BVHTreeRayHit *hit) | ||||
| { | { | ||||
| const BVHTreeFromEditMesh *data = (BVHTreeFromEditMesh *)userdata; | const BVHTreeFromEditMesh *data = (BVHTreeFromEditMesh *)userdata; | ||||
| BMEditMesh *em = data->em; | BMEditMesh *em = data->em; | ||||
| const BMLoop **ltri = (const BMLoop **)em->looptris[index]; | const BMLoop **ltri = (const BMLoop **)em->looptris[index]; | ||||
| const float *t0, *t1, *t2; | const float *t0, *t1, *t2; | ||||
| if (data->cageco) { | |||||
| t0 = data->cageco[BM_elem_index_get(ltri[0]->v)]; | |||||
| t1 = data->cageco[BM_elem_index_get(ltri[1]->v)]; | |||||
| t2 = data->cageco[BM_elem_index_get(ltri[2]->v)]; | |||||
| } | |||||
| else { | |||||
| t0 = ltri[0]->v->co; | t0 = ltri[0]->v->co; | ||||
| t1 = ltri[1]->v->co; | t1 = ltri[1]->v->co; | ||||
| t2 = ltri[2]->v->co; | t2 = ltri[2]->v->co; | ||||
| } | |||||
| { | { | ||||
| float dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2); | float dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2); | ||||
| if (dist >= 0 && dist < hit->dist) { | if (dist >= 0 && dist < hit->dist) { | ||||
| float no[3]; | float no[3]; | ||||
| if (raycast_tri_backface_culling_test(ray->direction, t0, t1, t2, no)) { | if (raycast_tri_backface_culling_test(ray->direction, t0, t1, t2, no)) { | ||||
| hit->index = index; | hit->index = index; | ||||
| ▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | if (BLI_bvhtree_ray_cast(treedata->tree, | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| static bool raycastEditMesh(SnapObjectContext *sctx, | static bool raycastEditMesh(SnapObjectContext *sctx, | ||||
| Depsgraph *depsgraph, | |||||
| const float ray_start[3], | const float ray_start[3], | ||||
| const float ray_dir[3], | const float ray_dir[3], | ||||
| Object *ob_eval, | Object *ob_eval, | ||||
| BMEditMesh *em, | BMEditMesh *em, | ||||
| const float obmat[4][4], | const float obmat[4][4], | ||||
| const uint ob_index, | const uint ob_index, | ||||
| bool use_backface_culling, | bool use_backface_culling, | ||||
| bool do_cageco, | |||||
| /* read/write args */ | /* read/write args */ | ||||
| float *ray_depth, | float *ray_depth, | ||||
| /* return args */ | /* return args */ | ||||
| float r_loc[3], | float r_loc[3], | ||||
| float r_no[3], | float r_no[3], | ||||
| int *r_index, | int *r_index, | ||||
| ListBase *r_hit_list) | ListBase *r_hit_list) | ||||
| { | { | ||||
| Show All 16 Lines | static bool raycastEditMesh(SnapObjectContext *sctx, | ||||
| /* local scale in normal direction */ | /* local scale in normal direction */ | ||||
| local_scale = normalize_v3(ray_normal_local); | local_scale = normalize_v3(ray_normal_local); | ||||
| local_depth = *ray_depth; | local_depth = *ray_depth; | ||||
| if (local_depth != BVH_RAYCAST_DIST_MAX) { | if (local_depth != BVH_RAYCAST_DIST_MAX) { | ||||
| local_depth *= local_scale; | local_depth *= local_scale; | ||||
| } | } | ||||
| SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob_eval, em); | SnapObjectData *sod = snap_object_data_editmesh_get(sctx, depsgraph, ob_eval, em, do_cageco); | ||||
| /* Test BoundBox */ | /* Test BoundBox */ | ||||
| /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ | /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ | ||||
| if (!isect_ray_aabb_v3_simple( | if (!isect_ray_aabb_v3_simple( | ||||
| ray_start_local, ray_normal_local, sod->min, sod->max, &len_diff, NULL)) { | ray_start_local, ray_normal_local, sod->min, sod->max, &len_diff, NULL)) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| Show All 9 Lines | static bool raycastEditMesh(SnapObjectContext *sctx, | ||||
| else { | else { | ||||
| len_diff = 0.0f; | len_diff = 0.0f; | ||||
| } | } | ||||
| BVHTreeFromEditMesh *treedata = &sod->treedata_editmesh; | BVHTreeFromEditMesh *treedata = &sod->treedata_editmesh; | ||||
| if (treedata->tree == NULL) { | if (treedata->tree == NULL) { | ||||
| /* Operators only update the editmesh looptris of the original mesh. */ | /* Operators only update the editmesh looptris of the original mesh. */ | ||||
| BLI_assert(sod->treedata_editmesh.em == BKE_editmesh_from_object(DEG_get_original_object(ob_eval))); | BLI_assert(sod->treedata_editmesh.em == | ||||
| BKE_editmesh_from_object(DEG_get_original_object(ob_eval))); | |||||
| em = sod->treedata_editmesh.em; | em = sod->treedata_editmesh.em; | ||||
| if (sctx->callbacks.edit_mesh.test_face_fn) { | if (do_cageco || sctx->callbacks.edit_mesh.test_face_fn) { | ||||
| BMesh *bm = em->bm; | BMesh *bm = em->bm; | ||||
| BLI_assert(poly_to_tri_count(bm->totface, bm->totloop) == em->tottri); | BLI_assert(poly_to_tri_count(bm->totface, bm->totloop) == em->tottri); | ||||
| BLI_bitmap *elem_mask = BLI_BITMAP_NEW(em->tottri, __func__); | BLI_bitmap *elem_mask = NULL; | ||||
| int looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( | int looptri_num_active = -1; | ||||
| if (sctx->callbacks.edit_mesh.test_face_fn) { | |||||
| elem_mask = BLI_BITMAP_NEW(em->tottri, __func__); | |||||
| looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( | |||||
| bm, | bm, | ||||
| elem_mask, | elem_mask, | ||||
| sctx->callbacks.edit_mesh.test_face_fn, | sctx->callbacks.edit_mesh.test_face_fn, | ||||
| sctx->callbacks.edit_mesh.user_data); | sctx->callbacks.edit_mesh.user_data); | ||||
| } | |||||
| bvhtree_from_editmesh_looptri_ex( | bvhtree_from_editmesh_looptri_ex(treedata, | ||||
| treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL, NULL); | em, | ||||
| elem_mask, | |||||
| looptri_num_active, | |||||
| 0.0f, | |||||
| 4, | |||||
| 6, | |||||
| sod->treedata_editmesh.cageco, | |||||
| 0, | |||||
| NULL, | |||||
| NULL); | |||||
| if (elem_mask) { | |||||
| MEM_freeN(elem_mask); | MEM_freeN(elem_mask); | ||||
| } | } | ||||
| } | |||||
| else { | else { | ||||
| /* Only cache if bvhtree is created without a mask. | /* Only cache if bvhtree is created without a mask. | ||||
| * This helps keep a standardized bvhtree in cache. */ | * This helps keep a standardized bvhtree in cache. */ | ||||
| BKE_bvhtree_from_editmesh_get(treedata, | BKE_bvhtree_from_editmesh_get(treedata, | ||||
| em, | em, | ||||
| 4, | 4, | ||||
| BVHTREE_FROM_EM_LOOPTRI, | BVHTREE_FROM_EM_LOOPTRI, | ||||
| &sod->mesh_runtime->bvh_cache, | &sod->mesh_runtime->bvh_cache, | ||||
| ▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | |||||
| }; | }; | ||||
| /** | /** | ||||
| * \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping; | * \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping; | ||||
| * | * | ||||
| * \note Duplicate args here are documented at #snapObjectsRay | * \note Duplicate args here are documented at #snapObjectsRay | ||||
| */ | */ | ||||
| static void raycast_obj_fn(SnapObjectContext *sctx, | static void raycast_obj_fn(SnapObjectContext *sctx, | ||||
| Depsgraph *depsgraph, | |||||
| Object *ob_eval, | Object *ob_eval, | ||||
| float obmat[4][4], | float obmat[4][4], | ||||
| eSnapEditType edit_mode_type, | eSnapEditType edit_mode_type, | ||||
| bool use_backface_culling, | bool use_backface_culling, | ||||
| bool is_object_active, | bool is_object_active, | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| struct RaycastObjUserData *dt = data; | struct RaycastObjUserData *dt = data; | ||||
| Show All 20 Lines | static void raycast_obj_fn(SnapObjectContext *sctx, | ||||
| switch (ob_eval->type) { | switch (ob_eval->type) { | ||||
| case OB_MESH: { | case OB_MESH: { | ||||
| bool use_hide = false; | bool use_hide = false; | ||||
| Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide); | Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide); | ||||
| if (me_eval == NULL) { | if (me_eval == NULL) { | ||||
| /* Operators only update the editmesh looptris of the original mesh. */ | /* Operators only update the editmesh looptris of the original mesh. */ | ||||
| BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob_eval)); | BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob_eval)); | ||||
| retval = raycastEditMesh(sctx, | retval = raycastEditMesh(sctx, | ||||
| depsgraph, | |||||
| dt->ray_start, | dt->ray_start, | ||||
| dt->ray_dir, | dt->ray_dir, | ||||
| ob_eval, | ob_eval, | ||||
| em_orig, | em_orig, | ||||
| obmat, | obmat, | ||||
| ob_index, | ob_index, | ||||
| use_backface_culling, | use_backface_culling, | ||||
| edit_mode_type == SNAP_GEOM_EDIT_DEFORMED, | |||||
| ray_depth, | ray_depth, | ||||
| dt->r_loc, | dt->r_loc, | ||||
| dt->r_no, | dt->r_no, | ||||
| dt->r_index, | dt->r_index, | ||||
| dt->r_hit_list); | dt->r_hit_list); | ||||
| break; | break; | ||||
| } | } | ||||
| retval = raycastMesh(sctx, | retval = raycastMesh(sctx, | ||||
| ▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | static bool snap_bound_box_check_dist(const float min[3], | ||||
| return true; | return true; | ||||
| } | } | ||||
| static void cb_mvert_co_get(const int index, const float **co, const BVHTreeFromMesh *data) | static void cb_mvert_co_get(const int index, const float **co, const BVHTreeFromMesh *data) | ||||
| { | { | ||||
| *co = data->vert[index].co; | *co = data->vert[index].co; | ||||
| } | } | ||||
| static void cb_bvert_co_get(const int index, const float **co, const BMEditMesh *data) | static void cb_bvert_co_get(const int index, const float **co, const BVHTreeFromEditMesh *data) | ||||
| { | { | ||||
| BMVert *eve = BM_vert_at_index(data->bm, index); | BMVert *eve = BM_vert_at_index(data->em->bm, index); | ||||
| *co = eve->co; | *co = eve->co; | ||||
| } | } | ||||
| static void cb_cageco_get(const int index, const float **co, const BVHTreeFromEditMesh *data) | |||||
| { | |||||
| *co = data->cageco[index]; | |||||
| } | |||||
| static void cb_mvert_no_copy(const int index, float r_no[3], const BVHTreeFromMesh *data) | static void cb_mvert_no_copy(const int index, float r_no[3], const BVHTreeFromMesh *data) | ||||
| { | { | ||||
| const MVert *vert = data->vert + index; | const MVert *vert = data->vert + index; | ||||
| normal_short_to_float_v3(r_no, vert->no); | normal_short_to_float_v3(r_no, vert->no); | ||||
| } | } | ||||
| static void cb_bvert_no_copy(const int index, float r_no[3], const BMEditMesh *data) | static void cb_bvert_no_copy(const int index, float r_no[3], const BVHTreeFromEditMesh *data) | ||||
| { | { | ||||
| BMVert *eve = BM_vert_at_index(data->bm, index); | BMVert *eve = BM_vert_at_index(data->em->bm, index); | ||||
| copy_v3_v3(r_no, eve->no); | copy_v3_v3(r_no, eve->no); | ||||
| } | } | ||||
| static void cb_medge_verts_get(const int index, int v_index[2], const BVHTreeFromMesh *data) | static void cb_medge_verts_get(const int index, int v_index[2], const BVHTreeFromMesh *data) | ||||
| { | { | ||||
| const MEdge *edge = &data->edge[index]; | const MEdge *edge = &data->edge[index]; | ||||
| v_index[0] = edge->v1; | v_index[0] = edge->v1; | ||||
| v_index[1] = edge->v2; | v_index[1] = edge->v2; | ||||
| } | } | ||||
| static void cb_bedge_verts_get(const int index, int v_index[2], const BMEditMesh *data) | static void cb_bedge_verts_get(const int index, int v_index[2], const BVHTreeFromEditMesh *data) | ||||
| { | { | ||||
| BMEdge *eed = BM_edge_at_index(data->bm, index); | BMEdge *eed = BM_edge_at_index(data->em->bm, index); | ||||
| v_index[0] = BM_elem_index_get(eed->v1); | v_index[0] = BM_elem_index_get(eed->v1); | ||||
| v_index[1] = BM_elem_index_get(eed->v2); | v_index[1] = BM_elem_index_get(eed->v2); | ||||
| } | } | ||||
| static void cb_mlooptri_edges_get(const int index, int v_index[3], const BVHTreeFromMesh *data) | static void cb_mlooptri_edges_get(const int index, int v_index[3], const BVHTreeFromMesh *data) | ||||
| { | { | ||||
| const MEdge *medge = data->edge; | const MEdge *medge = data->edge; | ||||
| ▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | if (sod->type == SNAP_MESH) { | ||||
| r_nearest2d->get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get; | r_nearest2d->get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get; | ||||
| r_nearest2d->get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get; | r_nearest2d->get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get; | ||||
| r_nearest2d->copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy; | r_nearest2d->copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy; | ||||
| r_nearest2d->get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get; | r_nearest2d->get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get; | ||||
| r_nearest2d->get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get; | r_nearest2d->get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get; | ||||
| } | } | ||||
| else { | else { | ||||
| BLI_assert(sod->type == SNAP_EDIT_MESH); | BLI_assert(sod->type == SNAP_EDIT_MESH); | ||||
| r_nearest2d->userdata = sod->treedata_editmesh.em; | r_nearest2d->userdata = &sod->treedata_editmesh; | ||||
| r_nearest2d->get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get; | r_nearest2d->get_vert_co = (Nearest2DGetVertCoCallback)( | ||||
| sod->treedata_editmesh.cageco ? cb_cageco_get : cb_bvert_co_get); | |||||
| r_nearest2d->get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get; | r_nearest2d->get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get; | ||||
| r_nearest2d->copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy; | r_nearest2d->copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy; | ||||
| r_nearest2d->get_tri_verts_index = NULL; | r_nearest2d->get_tri_verts_index = NULL; | ||||
| r_nearest2d->get_tri_edges_index = NULL; | r_nearest2d->get_tri_edges_index = NULL; | ||||
| } | } | ||||
| r_nearest2d->is_persp = is_persp; | r_nearest2d->is_persp = is_persp; | ||||
| r_nearest2d->use_backface_culling = use_backface_culling; | r_nearest2d->use_backface_culling = use_backface_culling; | ||||
| ▲ Show 20 Lines • Show All 1,054 Lines • ▼ Show 20 Lines | if (nearest.index != -1) { | ||||
| return elem; | return elem; | ||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| static short snapEditMesh(SnapObjectContext *sctx, | static short snapEditMesh(SnapObjectContext *sctx, | ||||
| Depsgraph *depsgraph, | |||||
| SnapData *snapdata, | SnapData *snapdata, | ||||
| Object *ob_eval, | Object *ob_eval, | ||||
| BMEditMesh *em, | BMEditMesh *em, | ||||
| const float obmat[4][4], | const float obmat[4][4], | ||||
| bool use_backface_culling, | bool use_backface_culling, | ||||
| bool do_cageco, | |||||
| /* read/write args */ | /* read/write args */ | ||||
| float *dist_px, | float *dist_px, | ||||
| /* return args */ | /* return args */ | ||||
| float r_loc[3], | float r_loc[3], | ||||
| float r_no[3], | float r_no[3], | ||||
| int *r_index) | int *r_index) | ||||
| { | { | ||||
| BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE); | BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE); | ||||
| Show All 9 Lines | else { | ||||
| } | } | ||||
| } | } | ||||
| float lpmat[4][4]; | float lpmat[4][4]; | ||||
| mul_m4_m4m4(lpmat, snapdata->pmat, obmat); | mul_m4_m4m4(lpmat, snapdata->pmat, obmat); | ||||
| float dist_px_sq = square_f(*dist_px); | float dist_px_sq = square_f(*dist_px); | ||||
| SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob_eval, em); | SnapObjectData *sod = snap_object_data_editmesh_get(sctx, depsgraph, ob_eval, em, do_cageco); | ||||
| /* Test BoundBox */ | /* Test BoundBox */ | ||||
| /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ | /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */ | ||||
| if (!snap_bound_box_check_dist( | if (!snap_bound_box_check_dist( | ||||
| sod->min, sod->max, lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) { | sod->min, sod->max, lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) { | if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) { | ||||
| BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[0]}; | BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[0]}; | ||||
| if (treedata.tree == NULL) { | if (treedata.tree == NULL) { | ||||
| if (do_cageco || sctx->callbacks.edit_mesh.test_vert_fn) { | |||||
| 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, | BM_VERTS_OF_MESH, | ||||
| em->bm, | em->bm, | ||||
| verts_mask, | 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, | |||||
| em, | |||||
| verts_mask, | |||||
| verts_num_active, | |||||
| 0.0f, | |||||
| 2, | |||||
| 6, | |||||
| sod->treedata_editmesh.cageco, | |||||
| 0, | |||||
| NULL, | |||||
| NULL); | |||||
| bvhtree_from_editmesh_verts_ex( | if (verts_mask) { | ||||
| &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL, NULL); | |||||
| MEM_freeN(verts_mask); | MEM_freeN(verts_mask); | ||||
| } | } | ||||
| } | |||||
| else { | else { | ||||
| BKE_bvhtree_from_editmesh_get(&treedata, | BKE_bvhtree_from_editmesh_get(&treedata, | ||||
| em, | em, | ||||
| 2, | 2, | ||||
| BVHTREE_FROM_EM_VERTS, | BVHTREE_FROM_EM_VERTS, | ||||
| &sod->mesh_runtime->bvh_cache, | &sod->mesh_runtime->bvh_cache, | ||||
| (ThreadMutex *)sod->mesh_runtime->eval_mutex); | (ThreadMutex *)sod->mesh_runtime->eval_mutex); | ||||
| } | } | ||||
| sod->bvhtree[0] = treedata.tree; | sod->bvhtree[0] = treedata.tree; | ||||
| sod->cached[0] = treedata.cached; | sod->cached[0] = treedata.cached; | ||||
| } | } | ||||
| } | } | ||||
| if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { | if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) { | ||||
| BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[1]}; | BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[1]}; | ||||
| if (treedata.tree == NULL) { | if (treedata.tree == NULL) { | ||||
| if (do_cageco || sctx->callbacks.edit_mesh.test_edge_fn) { | |||||
| 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, | BM_EDGES_OF_MESH, | ||||
| em->bm, | em->bm, | ||||
| edges_mask, | 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, | |||||
| em, | |||||
| edges_mask, | |||||
| edges_num_active, | |||||
| 0.0f, | |||||
| 2, | |||||
| 6, | |||||
| sod->treedata_editmesh.cageco, | |||||
| 0, | |||||
| NULL, | |||||
| NULL); | |||||
| bvhtree_from_editmesh_edges_ex( | if (edges_mask) { | ||||
| &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL, NULL); | |||||
| MEM_freeN(edges_mask); | MEM_freeN(edges_mask); | ||||
| } | } | ||||
| } | |||||
| else { | else { | ||||
| BKE_bvhtree_from_editmesh_get(&treedata, | BKE_bvhtree_from_editmesh_get(&treedata, | ||||
| em, | em, | ||||
| 2, | 2, | ||||
| BVHTREE_FROM_EM_EDGES, | BVHTREE_FROM_EM_EDGES, | ||||
| &sod->mesh_runtime->bvh_cache, | &sod->mesh_runtime->bvh_cache, | ||||
| sod->mesh_runtime->eval_mutex); | sod->mesh_runtime->eval_mutex); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | |||||
| }; | }; | ||||
| /** | /** | ||||
| * \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping; | * \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping; | ||||
| * | * | ||||
| * \note Duplicate args here are documented at #snapObjectsRay | * \note Duplicate args here are documented at #snapObjectsRay | ||||
| */ | */ | ||||
| static void snap_obj_fn(SnapObjectContext *sctx, | static void snap_obj_fn(SnapObjectContext *sctx, | ||||
| Depsgraph *depsgraph, | |||||
| Object *ob_eval, | Object *ob_eval, | ||||
| float obmat[4][4], | float obmat[4][4], | ||||
| eSnapEditType edit_mode_type, | eSnapEditType edit_mode_type, | ||||
| bool use_backface_culling, | bool use_backface_culling, | ||||
| bool UNUSED(is_object_active), | bool UNUSED(is_object_active), | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| struct SnapObjUserData *dt = data; | struct SnapObjUserData *dt = data; | ||||
| short retval = 0; | short retval = 0; | ||||
| switch (ob_eval->type) { | switch (ob_eval->type) { | ||||
| case OB_MESH: { | case OB_MESH: { | ||||
| bool use_hide; | bool use_hide; | ||||
| Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide); | Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide); | ||||
| if (me_eval == NULL) { | if (me_eval == NULL) { | ||||
| /* Operators only update the editmesh looptris of the original mesh. */ | /* Operators only update the editmesh looptris of the original mesh. */ | ||||
| BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob_eval)); | BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob_eval)); | ||||
| retval = snapEditMesh(sctx, | retval = snapEditMesh(sctx, | ||||
| depsgraph, | |||||
| dt->snapdata, | dt->snapdata, | ||||
| ob_eval, | ob_eval, | ||||
| em_orig, | em_orig, | ||||
| obmat, | obmat, | ||||
| use_backface_culling, | use_backface_culling, | ||||
| edit_mode_type == SNAP_GEOM_EDIT_DEFORMED, | |||||
| dt->dist_px, | dt->dist_px, | ||||
| dt->r_loc, | dt->r_loc, | ||||
| dt->r_no, | dt->r_no, | ||||
| dt->r_index); | dt->r_index); | ||||
| break; | break; | ||||
| } | } | ||||
| if (ob_eval->dt == OB_BOUNDBOX) { | if (ob_eval->dt == OB_BOUNDBOX) { | ||||
| /* Do not snap to objects that are in bounding box display mode */ | /* Do not snap to objects that are in bounding box display mode */ | ||||
| ▲ Show 20 Lines • Show All 426 Lines • ▼ Show 20 Lines | if (has_hit && ob_eval->type != OB_CURVE) { | ||||
| /* The plane is facing the wrong direction. */ | /* The plane is facing the wrong direction. */ | ||||
| negate_v4(new_clipplane); | negate_v4(new_clipplane); | ||||
| } | } | ||||
| /* Small offset to simulate a kind of volume for edges and vertices. */ | /* Small offset to simulate a kind of volume for edges and vertices. */ | ||||
| new_clipplane[3] += 0.01f; | new_clipplane[3] += 0.01f; | ||||
| /* Try to snap only to the polygon. */ | /* Try to snap only to the polygon. */ | ||||
| elem_test = snap_mesh_polygon( | elem_test = snap_mesh_polygon(sctx, | ||||
| sctx, &snapdata, ob_eval, obmat, params->use_backface_culling, &dist_px_tmp, loc, no, &index); | &snapdata, | ||||
| ob_eval, | |||||
| obmat, | |||||
| params->use_backface_culling, | |||||
| &dist_px_tmp, | |||||
| loc, | |||||
| no, | |||||
| &index); | |||||
| if (elem_test) { | if (elem_test) { | ||||
| elem = elem_test; | elem = elem_test; | ||||
| } | } | ||||
| /* Add the new clip plane to the beginning of the list. */ | /* Add the new clip plane to the beginning of the list. */ | ||||
| for (int i = snapdata.clip_plane_len; i != 0; i--) { | for (int i = snapdata.clip_plane_len; i != 0; i--) { | ||||
| copy_v4_v4(snapdata.clip_plane[i], snapdata.clip_plane[i - 1]); | copy_v4_v4(snapdata.clip_plane[i], snapdata.clip_plane[i - 1]); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 145 Lines • Show Last 20 Lines | |||||