Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/transform/transform_snap_object.cc
- This file was moved from source/blender/editors/transform/transform_snap_object.c.
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||||
| /** \file | /** \file | ||||
| * \ingroup edtransform | * \ingroup edtransform | ||||
| */ | */ | ||||
| #include <stdlib.h> | #include <cstdlib> | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "BLI_ghash.h" | #include "BLI_ghash.h" | ||||
| #include "BLI_kdopbvh.h" | #include "BLI_kdopbvh.h" | ||||
| #include "BLI_listbase.h" | #include "BLI_listbase.h" | ||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| #include "BLI_memarena.h" | #include "BLI_memarena.h" | ||||
| Show All 34 Lines | |||||
| #define MAX_CLIPPLANE_LEN 3 | #define MAX_CLIPPLANE_LEN 3 | ||||
| enum eViewProj { | enum eViewProj { | ||||
| VIEW_PROJ_NONE = -1, | VIEW_PROJ_NONE = -1, | ||||
| VIEW_PROJ_ORTHO = 0, | VIEW_PROJ_ORTHO = 0, | ||||
| VIEW_PROJ_PERSP = -1, | VIEW_PROJ_PERSP = -1, | ||||
| }; | }; | ||||
| typedef struct SnapObjectData { | struct SnapObjectData { | ||||
| enum { | enum class Type { | ||||
| SNAP_MESH = 1, | Mesh, | ||||
| SNAP_EDIT_MESH, | EditMesh, | ||||
| } type; | }; | ||||
| Type type; | |||||
| BVHTree *bvhtree[2]; /* MESH: loose edges, loose verts | BVHTree *bvhtree[2]; /* MESH: loose edges, loose verts | ||||
| * EDIT_MESH: verts, edges. */ | * EDIT_MESH: verts, edges. */ | ||||
| bool cached[2]; | bool cached[2]; | ||||
| union { | union { | ||||
| struct { | struct { | ||||
| /* SNAP_MESH */ | /* Type::Mesh */ | ||||
| BVHTreeFromMesh treedata_mesh; | BVHTreeFromMesh treedata_mesh; | ||||
| const struct MPoly *poly; | const struct MPoly *poly; | ||||
| uint has_looptris : 1; | uint has_looptris : 1; | ||||
| uint has_loose_edge : 1; | uint has_loose_edge : 1; | ||||
| uint has_loose_vert : 1; | uint has_loose_vert : 1; | ||||
| }; | }; | ||||
| struct { | struct { | ||||
| /* SNAP_EDIT_MESH */ | /* Type::EditMesh */ | ||||
| BVHTreeFromEditMesh treedata_editmesh; | BVHTreeFromEditMesh treedata_editmesh; | ||||
| float min[3], max[3]; | float min[3], max[3]; | ||||
| struct Mesh_Runtime *mesh_runtime; | struct Mesh_Runtime *mesh_runtime; | ||||
| }; | }; | ||||
| }; | }; | ||||
| } SnapObjectData; | }; | ||||
| struct SnapObjectContext { | struct SnapObjectContext { | ||||
| Scene *scene; | Scene *scene; | ||||
| int flag; | int flag; | ||||
| /* Object -> SnapObjectData map */ | /* Object -> SnapObjectData map */ | ||||
| struct { | struct { | ||||
| Show All 31 Lines | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Utilities | /** \name Utilities | ||||
| * \{ */ | * \{ */ | ||||
| /* Mesh used for snapping. | /* Mesh used for snapping. | ||||
| * If NULL the BMesh should be used. */ | * If nullptr 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 = BKE_object_get_evaluated_mesh(ob_eval); | Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval); | ||||
| 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 (edit_mode_type == SNAP_GEOM_EDIT) { | ||||
| return NULL; | return nullptr; | ||||
| } | } | ||||
| Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob_eval); | Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob_eval); | ||||
| Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval); | Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval); | ||||
| if ((edit_mode_type == SNAP_GEOM_FINAL) && editmesh_eval_final) { | if ((edit_mode_type == SNAP_GEOM_FINAL) && editmesh_eval_final) { | ||||
| if (editmesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) { | if (editmesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) { | ||||
| return NULL; | return nullptr; | ||||
| } | } | ||||
| me_eval = editmesh_eval_final; | me_eval = editmesh_eval_final; | ||||
| use_hide = true; | use_hide = true; | ||||
| } | } | ||||
| else if ((edit_mode_type == SNAP_GEOM_CAGE) && editmesh_eval_cage) { | else if ((edit_mode_type == SNAP_GEOM_CAGE) && editmesh_eval_cage) { | ||||
| if (editmesh_eval_cage->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) { | if (editmesh_eval_cage->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) { | ||||
| return NULL; | return nullptr; | ||||
| } | } | ||||
| me_eval = editmesh_eval_cage; | me_eval = editmesh_eval_cage; | ||||
| use_hide = true; | use_hide = true; | ||||
| } | } | ||||
| } | } | ||||
| if (r_use_hide) { | if (r_use_hide) { | ||||
| *r_use_hide = use_hide; | *r_use_hide = use_hide; | ||||
| } | } | ||||
| Show All 17 Lines | static void bm_mesh_minmax(BMesh *bm, float r_min[3], float r_max[3]) | ||||
| BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { | BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { | ||||
| minmax_v3v3_v3(r_min, r_max, v->co); | minmax_v3v3_v3(r_min, r_max, v->co); | ||||
| } | } | ||||
| } | } | ||||
| static void snap_object_data_mesh_clear(SnapObjectData *sod) | static void snap_object_data_mesh_clear(SnapObjectData *sod) | ||||
| { | { | ||||
| BLI_assert(sod->type == SNAP_MESH); | BLI_assert(sod->type == SnapObjectData::Type::Mesh); | ||||
| for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) { | for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) { | ||||
| if (!sod->cached[i]) { | if (!sod->cached[i]) { | ||||
| BLI_bvhtree_free(sod->bvhtree[i]); | BLI_bvhtree_free(sod->bvhtree[i]); | ||||
| } | } | ||||
| sod->bvhtree[i] = NULL; | sod->bvhtree[i] = nullptr; | ||||
| } | } | ||||
| free_bvhtree_from_mesh(&sod->treedata_mesh); | free_bvhtree_from_mesh(&sod->treedata_mesh); | ||||
| } | } | ||||
| static void snap_object_data_editmesh_clear(SnapObjectData *sod) | static void snap_object_data_editmesh_clear(SnapObjectData *sod) | ||||
| { | { | ||||
| BLI_assert(sod->type == SNAP_EDIT_MESH); | BLI_assert(sod->type == SnapObjectData::Type::EditMesh); | ||||
| for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) { | for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) { | ||||
| if (!sod->cached[i]) { | if (!sod->cached[i]) { | ||||
| BLI_bvhtree_free(sod->bvhtree[i]); | BLI_bvhtree_free(sod->bvhtree[i]); | ||||
| } | } | ||||
| sod->bvhtree[i] = NULL; | sod->bvhtree[i] = nullptr; | ||||
| } | } | ||||
| free_bvhtree_from_editmesh(&sod->treedata_editmesh); | free_bvhtree_from_editmesh(&sod->treedata_editmesh); | ||||
| } | } | ||||
| static void snap_object_data_clear(SnapObjectData *sod) | static void snap_object_data_clear(SnapObjectData *sod) | ||||
| { | { | ||||
| switch (sod->type) { | switch (sod->type) { | ||||
| case SNAP_MESH: { | case SnapObjectData::Type::Mesh: { | ||||
| snap_object_data_mesh_clear(sod); | snap_object_data_mesh_clear(sod); | ||||
| break; | break; | ||||
| } | } | ||||
| case SNAP_EDIT_MESH: { | case SnapObjectData::Type::EditMesh: { | ||||
| snap_object_data_editmesh_clear(sod); | snap_object_data_editmesh_clear(sod); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| memset(&sod->type, 0x0, sizeof(*sod) - offsetof(SnapObjectData, type)); | memset(&sod->type, 0x0, sizeof(*sod) - offsetof(SnapObjectData, type)); | ||||
| } | } | ||||
| static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *ob_eval) | static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *ob_eval) | ||||
| { | { | ||||
| SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob_eval); | SnapObjectData *sod = static_cast<SnapObjectData *>( | ||||
| if (sod == NULL) { | BLI_ghash_lookup(sctx->cache.object_map, ob_eval)); | ||||
| if (sctx->cache.data_to_object_map != NULL) { | if (sod == nullptr) { | ||||
| ob_eval = BLI_ghash_lookup(sctx->cache.data_to_object_map, ob_eval->data); | if (sctx->cache.data_to_object_map != nullptr) { | ||||
| ob_eval = static_cast<Object *>( | |||||
| BLI_ghash_lookup(sctx->cache.data_to_object_map, ob_eval->data)); | |||||
| /* Could be NULl when mixing edit-mode and non edit-mode objects. */ | /* Could be NULl when mixing edit-mode and non edit-mode objects. */ | ||||
| if (ob_eval != NULL) { | if (ob_eval != nullptr) { | ||||
| sod = BLI_ghash_lookup(sctx->cache.object_map, ob_eval); | sod = static_cast<SnapObjectData *>(BLI_ghash_lookup(sctx->cache.object_map, ob_eval)); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return sod; | return sod; | ||||
| } | } | ||||
| static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, | static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, | ||||
| Object *ob_eval, | Object *ob_eval, | ||||
| const Mesh *me_eval, | const Mesh *me_eval, | ||||
| bool use_hide) | bool use_hide) | ||||
| { | { | ||||
| SnapObjectData *sod; | SnapObjectData *sod; | ||||
| void **sod_p; | void **sod_p; | ||||
| bool init = false; | bool init = false; | ||||
| 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 = static_cast<SnapObjectData *>(*sod_p); | ||||
| bool is_dirty = false; | bool is_dirty = false; | ||||
| if (sod->type != SNAP_MESH) { | if (sod->type != SnapObjectData::Type::Mesh) { | ||||
| is_dirty = true; | is_dirty = true; | ||||
| } | } | ||||
| else if (sod->treedata_mesh.tree && sod->treedata_mesh.cached && | else if (sod->treedata_mesh.tree && sod->treedata_mesh.cached && | ||||
| !bvhcache_has_tree(me_eval->runtime.bvh_cache, sod->treedata_mesh.tree)) { | !bvhcache_has_tree(me_eval->runtime.bvh_cache, sod->treedata_mesh.tree)) { | ||||
| /* The tree is owned by the Mesh 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. */ | ||||
| is_dirty = true; | is_dirty = true; | ||||
| } | } | ||||
| else if (sod->bvhtree[0] && sod->cached[0] && | else if (sod->bvhtree[0] && sod->cached[0] && | ||||
| Show All 24 Lines | if (BLI_ghash_ensure_p(sctx->cache.object_map, ob_eval, &sod_p)) { | ||||
| } | } | ||||
| if (is_dirty) { | if (is_dirty) { | ||||
| snap_object_data_clear(sod); | snap_object_data_clear(sod); | ||||
| init = true; | init = true; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); | *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); | ||||
| sod = static_cast<SnapObjectData *>(*sod_p); | |||||
| init = true; | init = true; | ||||
| } | } | ||||
| if (init) { | if (init) { | ||||
| sod->type = SNAP_MESH; | sod->type = SnapObjectData::Type::Mesh; | ||||
| /* The BVHTree from looptris is always required. */ | /* The BVHTree from looptris is always required. */ | ||||
| BLI_assert(sod->treedata_mesh.tree == NULL); | BLI_assert(sod->treedata_mesh.tree == nullptr); | ||||
| BKE_bvhtree_from_mesh_get(&sod->treedata_mesh, | BKE_bvhtree_from_mesh_get(&sod->treedata_mesh, | ||||
| me_eval, | me_eval, | ||||
| use_hide ? BVHTREE_FROM_LOOPTRI_NO_HIDDEN : BVHTREE_FROM_LOOPTRI, | use_hide ? BVHTREE_FROM_LOOPTRI_NO_HIDDEN : BVHTREE_FROM_LOOPTRI, | ||||
| 4); | 4); | ||||
| if (sod->treedata_mesh.tree == NULL) { | if (sod->treedata_mesh.tree == nullptr) { | ||||
| sod->treedata_mesh.vert = me_eval->mvert; | sod->treedata_mesh.vert = me_eval->mvert; | ||||
| sod->treedata_mesh.vert_normals = BKE_mesh_vertex_normals_ensure(me_eval); | sod->treedata_mesh.vert_normals = BKE_mesh_vertex_normals_ensure(me_eval); | ||||
| sod->treedata_mesh.loop = me_eval->mloop; | sod->treedata_mesh.loop = me_eval->mloop; | ||||
| sod->treedata_mesh.looptri = BKE_mesh_runtime_looptri_ensure(me_eval); | sod->treedata_mesh.looptri = BKE_mesh_runtime_looptri_ensure(me_eval); | ||||
| BLI_assert(sod->has_looptris == false); | BLI_assert(sod->has_looptris == false); | ||||
| } | } | ||||
| else { | else { | ||||
| BLI_assert(sod->treedata_mesh.vert != NULL); | BLI_assert(sod->treedata_mesh.vert != nullptr); | ||||
| BLI_assert(sod->treedata_mesh.vert_normals != NULL); | BLI_assert(sod->treedata_mesh.vert_normals != nullptr); | ||||
| BLI_assert(sod->treedata_mesh.loop != NULL); | BLI_assert(sod->treedata_mesh.loop != nullptr); | ||||
| BLI_assert(sod->treedata_mesh.looptri != NULL); | BLI_assert(sod->treedata_mesh.looptri != nullptr); | ||||
| sod->has_looptris = true; | sod->has_looptris = true; | ||||
| } | } | ||||
| /* Required for snapping with occlusion. */ | /* Required for snapping with occlusion. */ | ||||
| sod->treedata_mesh.edge = me_eval->medge; | sod->treedata_mesh.edge = me_eval->medge; | ||||
| sod->poly = me_eval->mpoly; | sod->poly = me_eval->mpoly; | ||||
| /* Start assuming that it has each of these element types. */ | /* Start assuming that it has each of these element types. */ | ||||
| Show All 25 Lines | |||||
| { | { | ||||
| 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 == nullptr) { | ||||
| 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 = static_cast<Object *>(*ob_p); | ||||
| } | } | ||||
| else { | else { | ||||
| *ob_p = ob_eval; | *ob_p = ob_eval; | ||||
| } | } | ||||
| } | } | ||||
| 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 = static_cast<SnapObjectData *>(*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 != SnapObjectData::Type::EditMesh) { | ||||
| 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->mesh_runtime) { | else if (sod->mesh_runtime) { | ||||
| if (sod->mesh_runtime != snap_object_data_editmesh_runtime_get(ob_eval)) { | if (sod->mesh_runtime != snap_object_data_editmesh_runtime_get(ob_eval)) { | ||||
| if (G.moving) { | if (G.moving) { | ||||
| Show All 23 Lines | if (BLI_ghash_ensure_p(sctx->cache.object_map, ob_eval, &sod_p)) { | ||||
| } | } | ||||
| if (is_dirty) { | if (is_dirty) { | ||||
| snap_object_data_clear(sod); | snap_object_data_clear(sod); | ||||
| init = true; | init = true; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); | *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod)); | ||||
| sod = static_cast<SnapObjectData *>(*sod_p); | |||||
| init = true; | init = true; | ||||
| } | } | ||||
| if (init) { | if (init) { | ||||
| sod->type = SNAP_EDIT_MESH; | sod->type = SnapObjectData::Type::EditMesh; | ||||
| sod->treedata_editmesh.em = em; | sod->treedata_editmesh.em = em; | ||||
| sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob_eval); | sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob_eval); | ||||
| 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, | using IterSnapObjsCallback = void (*)(SnapObjectContext *sctx, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| Object *ob_eval, | Object *ob_eval, | ||||
| float obmat[4][4], | float obmat[4][4], | ||||
| bool is_object_active, | bool is_object_active, | ||||
| void *data); | void *data); | ||||
| static bool snap_object_is_snappable(const SnapObjectContext *sctx, | static bool snap_object_is_snappable(const SnapObjectContext *sctx, | ||||
| const eSnapSelect snap_select, | const eSnapSelect snap_select, | ||||
| const Base *base_act, | const Base *base_act, | ||||
| const Base *base, | const Base *base, | ||||
| const bool is_in_object_mode) | const bool is_in_object_mode) | ||||
| { | { | ||||
| if (!BASE_VISIBLE(sctx->runtime.v3d, base)) { | if (!BASE_VISIBLE(sctx->runtime.v3d, base)) { | ||||
| ▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | static void iter_snap_objects(SnapObjectContext *sctx, | ||||
| 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(sctx->runtime.depsgraph, base_act->object); | Object *obj_eval = DEG_get_evaluated_object(sctx->runtime.depsgraph, base_act->object); | ||||
| sob_callback(sctx, params, obj_eval, obj_eval->obmat, true, data); | sob_callback(sctx, params, obj_eval, obj_eval->obmat, true, data); | ||||
| return; | return; | ||||
| } | } | ||||
| const bool is_in_object_mode = !base_act || base_act->object->mode == OB_MODE_OBJECT; | const bool is_in_object_mode = !base_act || base_act->object->mode == OB_MODE_OBJECT; | ||||
| for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) { | LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { | ||||
| if (!snap_object_is_snappable(sctx, snap_select, base_act, base, is_in_object_mode)) { | if (!snap_object_is_snappable(sctx, snap_select, base_act, base, is_in_object_mode)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| const bool is_object_active = (base == base_act); | const bool is_object_active = (base == base_act); | ||||
| Object *obj_eval = DEG_get_evaluated_object(sctx->runtime.depsgraph, base->object); | Object *obj_eval = DEG_get_evaluated_object(sctx->runtime.depsgraph, base->object); | ||||
| if (obj_eval->transflag & OB_DUPLI || BKE_object_has_geometry_set_instances(obj_eval)) { | if (obj_eval->transflag & OB_DUPLI || BKE_object_has_geometry_set_instances(obj_eval)) { | ||||
| ListBase *lb = object_duplilist(sctx->runtime.depsgraph, sctx->scene, obj_eval); | ListBase *lb = object_duplilist(sctx->runtime.depsgraph, sctx->scene, obj_eval); | ||||
| for (DupliObject *dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { | LISTBASE_FOREACH (DupliObject *, dupli_ob, lb) { | ||||
| BLI_assert(DEG_is_evaluated_object(dupli_ob->ob)); | BLI_assert(DEG_is_evaluated_object(dupli_ob->ob)); | ||||
| sob_callback(sctx, params, dupli_ob->ob, dupli_ob->mat, is_object_active, data); | sob_callback(sctx, params, dupli_ob->ob, dupli_ob->mat, is_object_active, data); | ||||
| } | } | ||||
| free_object_duplilist(lb); | free_object_duplilist(lb); | ||||
| } | } | ||||
| sob_callback(sctx, params, obj_eval, obj_eval->obmat, is_object_active, data); | sob_callback(sctx, params, obj_eval, obj_eval->obmat, is_object_active, data); | ||||
| } | } | ||||
| Show All 31 Lines | |||||
| static struct SnapObjectHitDepth *hit_depth_create(const float depth, | static struct SnapObjectHitDepth *hit_depth_create(const float depth, | ||||
| const float co[3], | const float co[3], | ||||
| const float no[3], | const float no[3], | ||||
| int index, | int index, | ||||
| Object *ob_eval, | Object *ob_eval, | ||||
| const float obmat[4][4], | const float obmat[4][4], | ||||
| uint ob_uuid) | uint ob_uuid) | ||||
| { | { | ||||
| struct SnapObjectHitDepth *hit = MEM_mallocN(sizeof(*hit), __func__); | struct SnapObjectHitDepth *hit = MEM_new<SnapObjectHitDepth>(__func__); | ||||
| hit->depth = depth; | hit->depth = depth; | ||||
| copy_v3_v3(hit->co, co); | copy_v3_v3(hit->co, co); | ||||
| copy_v3_v3(hit->no, no); | copy_v3_v3(hit->no, no); | ||||
| hit->index = index; | hit->index = index; | ||||
| hit->ob_eval = ob_eval; | hit->ob_eval = ob_eval; | ||||
| copy_m4_m4(hit->obmat, (float(*)[4])obmat); | copy_m4_m4(hit->obmat, (float(*)[4])obmat); | ||||
| hit->ob_uuid = ob_uuid; | hit->ob_uuid = ob_uuid; | ||||
| return hit; | return hit; | ||||
| } | } | ||||
| static int hit_depth_cmp(const void *arg1, const void *arg2) | static int hit_depth_cmp(const void *arg1, const void *arg2) | ||||
| { | { | ||||
| const struct SnapObjectHitDepth *h1 = arg1; | const struct SnapObjectHitDepth *h1 = static_cast<const struct SnapObjectHitDepth *>(arg1); | ||||
| const struct SnapObjectHitDepth *h2 = arg2; | const struct SnapObjectHitDepth *h2 = static_cast<const struct SnapObjectHitDepth *>(arg2); | ||||
| int val = 0; | int val = 0; | ||||
| if (h1->depth < h2->depth) { | if (h1->depth < h2->depth) { | ||||
| val = -1; | val = -1; | ||||
| } | } | ||||
| else if (h1->depth > h2->depth) { | else if (h1->depth > h2->depth) { | ||||
| val = 1; | val = 1; | ||||
| } | } | ||||
| return val; | return val; | ||||
| } | } | ||||
| static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) | static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) | ||||
| { | { | ||||
| struct RayCastAll_Data *data = userdata; | struct RayCastAll_Data *data = static_cast<struct RayCastAll_Data *>(userdata); | ||||
| data->raycast_callback(data->bvhdata, index, ray, hit); | data->raycast_callback(data->bvhdata, index, ray, hit); | ||||
| if (hit->index != -1) { | if (hit->index != -1) { | ||||
| /* Get all values in world-space. */ | /* Get all values in world-space. */ | ||||
| float location[3], normal[3]; | float location[3], normal[3]; | ||||
| float depth; | float depth; | ||||
| /* World-space location. */ | /* World-space location. */ | ||||
| mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co); | mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co); | ||||
| ▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | if (local_depth != BVH_RAYCAST_DIST_MAX) { | ||||
| local_depth *= local_scale; | local_depth *= local_scale; | ||||
| } | } | ||||
| /* Test BoundBox */ | /* Test BoundBox */ | ||||
| BoundBox *bb = BKE_object_boundbox_get(ob_eval); | BoundBox *bb = BKE_object_boundbox_get(ob_eval); | ||||
| if (bb) { | if (bb) { | ||||
| /* 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, bb->vec[0], bb->vec[6], &len_diff, NULL)) { | ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, nullptr)) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| } | } | ||||
| /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with | /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with | ||||
| * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358. | * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358. | ||||
| */ | */ | ||||
| if (len_diff > 400.0f) { | if (len_diff > 400.0f) { | ||||
| len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ | len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ | ||||
| madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff); | madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff); | ||||
| local_depth -= len_diff; | local_depth -= len_diff; | ||||
| } | } | ||||
| else { | else { | ||||
| len_diff = 0.0f; | len_diff = 0.0f; | ||||
| } | } | ||||
| SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob_eval, me_eval, use_hide); | SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob_eval, me_eval, use_hide); | ||||
| BVHTreeFromMesh *treedata = &sod->treedata_mesh; | BVHTreeFromMesh *treedata = &sod->treedata_mesh; | ||||
| if (treedata->tree == NULL) { | if (treedata->tree == nullptr) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| float timat[3][3]; /* transpose inverse matrix for normals */ | float timat[3][3]; /* transpose inverse matrix for normals */ | ||||
| transpose_m3_m4(timat, imat); | transpose_m3_m4(timat, imat); | ||||
| BLI_assert(treedata->raycast_callback != NULL); | BLI_assert(treedata->raycast_callback != nullptr); | ||||
| if (r_hit_list) { | if (r_hit_list) { | ||||
| struct RayCastAll_Data data; | struct RayCastAll_Data data; | ||||
| data.bvhdata = treedata; | data.bvhdata = treedata; | ||||
| data.raycast_callback = treedata->raycast_callback; | data.raycast_callback = treedata->raycast_callback; | ||||
| data.obmat = obmat; | data.obmat = obmat; | ||||
| data.timat = timat; | data.timat = timat; | ||||
| data.len_diff = len_diff; | data.len_diff = len_diff; | ||||
| Show All 9 Lines | BLI_bvhtree_ray_cast_all(treedata->tree, | ||||
| 0.0f, | 0.0f, | ||||
| *ray_depth, | *ray_depth, | ||||
| raycast_all_cb, | raycast_all_cb, | ||||
| &data); | &data); | ||||
| retval = data.retval; | retval = data.retval; | ||||
| } | } | ||||
| else { | else { | ||||
| BVHTreeRayHit hit = { | BVHTreeRayHit hit{}; | ||||
| .index = -1, | hit.index = -1; | ||||
| .dist = local_depth, | hit.dist = local_depth; | ||||
| }; | |||||
| if (BLI_bvhtree_ray_cast(treedata->tree, | if (BLI_bvhtree_ray_cast(treedata->tree, | ||||
| ray_start_local, | ray_start_local, | ||||
| ray_normal_local, | ray_normal_local, | ||||
| 0.0f, | 0.0f, | ||||
| &hit, | &hit, | ||||
| params->use_backface_culling ? | params->use_backface_culling ? | ||||
| mesh_looptri_raycast_backface_culling_cb : | mesh_looptri_raycast_backface_culling_cb : | ||||
| ▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | static bool raycastEditMesh(SnapObjectContext *sctx, | ||||
| } | } | ||||
| SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob_eval, em); | SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob_eval, em); | ||||
| /* 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, nullptr)) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with | /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with | ||||
| * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358. | * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358. | ||||
| */ | */ | ||||
| if (len_diff > 400.0f) { | if (len_diff > 400.0f) { | ||||
| len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ | len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ | ||||
| madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff); | madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff); | ||||
| local_depth -= len_diff; | local_depth -= len_diff; | ||||
| } | } | ||||
| 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 == nullptr) { | ||||
| /* 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 == | BLI_assert(sod->treedata_editmesh.em == | ||||
| BKE_editmesh_from_object(DEG_get_original_object(ob_eval))); | 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 (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 = BLI_BITMAP_NEW(em->tottri, __func__); | ||||
| int looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface( | int 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, | |||||
| BVHTREE_FROM_VERTS, | |||||
mano-wii: This parameter is not actually being used, but if we are going to choose a value, let it be… | |||||
| nullptr, | |||||
| nullptr); | |||||
| 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, | ||||
| sod->mesh_runtime->eval_mutex); | static_cast<ThreadMutex *>(sod->mesh_runtime->eval_mutex)); | ||||
| } | } | ||||
| if (treedata->tree == NULL) { | if (treedata->tree == nullptr) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| } | } | ||||
| float timat[3][3]; /* transpose inverse matrix for normals */ | float timat[3][3]; /* transpose inverse matrix for normals */ | ||||
| transpose_m3_m4(timat, imat); | transpose_m3_m4(timat, imat); | ||||
| if (r_hit_list) { | if (r_hit_list) { | ||||
| Show All 16 Lines | BLI_bvhtree_ray_cast_all(treedata->tree, | ||||
| 0.0f, | 0.0f, | ||||
| *ray_depth, | *ray_depth, | ||||
| raycast_all_cb, | raycast_all_cb, | ||||
| &data); | &data); | ||||
| retval = data.retval; | retval = data.retval; | ||||
| } | } | ||||
| else { | else { | ||||
| BVHTreeRayHit hit = { | BVHTreeRayHit hit{}; | ||||
| .index = -1, | hit.index = -1; | ||||
| .dist = local_depth, | hit.dist = local_depth; | ||||
| }; | |||||
| if (BLI_bvhtree_ray_cast(treedata->tree, | if (BLI_bvhtree_ray_cast(treedata->tree, | ||||
| ray_start_local, | ray_start_local, | ||||
| ray_normal_local, | ray_normal_local, | ||||
| 0.0f, | 0.0f, | ||||
| &hit, | &hit, | ||||
| params->use_backface_culling ? | params->use_backface_culling ? | ||||
| editmesh_looptri_raycast_backface_culling_cb : | editmesh_looptri_raycast_backface_culling_cb : | ||||
| ▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | |||||
| */ | */ | ||||
| static void raycast_obj_fn(SnapObjectContext *sctx, | static void raycast_obj_fn(SnapObjectContext *sctx, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| Object *ob_eval, | Object *ob_eval, | ||||
| float obmat[4][4], | float obmat[4][4], | ||||
| bool is_object_active, | bool is_object_active, | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| struct RaycastObjUserData *dt = data; | RaycastObjUserData *dt = static_cast<RaycastObjUserData *>(data); | ||||
| const uint ob_index = dt->ob_index++; | const uint ob_index = dt->ob_index++; | ||||
| bool use_occlusion_test = dt->use_occlusion_test; | bool use_occlusion_test = dt->use_occlusion_test; | ||||
| /* read/write args */ | /* read/write args */ | ||||
| float *ray_depth = dt->ray_depth; | float *ray_depth = dt->ray_depth; | ||||
| bool retval = false; | bool retval = false; | ||||
| if (use_occlusion_test) { | if (use_occlusion_test) { | ||||
| if (ELEM(ob_eval->dt, OB_BOUNDBOX, OB_WIRE)) { | if (ELEM(ob_eval->dt, OB_BOUNDBOX, OB_WIRE)) { | ||||
| /* Do not hit objects that are in wire or bounding box | /* Do not hit objects that are in wire or bounding box | ||||
| * display mode. */ | * display mode. */ | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| switch (ob_eval->type) { | switch (ob_eval->type) { | ||||
| case OB_MESH: { | case OB_MESH: { | ||||
| const eSnapEditType edit_mode_type = params->edit_mode_type; | const eSnapEditType edit_mode_type = params->edit_mode_type; | ||||
| 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 == nullptr) { | ||||
| /* 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, | ||||
| params, | params, | ||||
| dt->ray_start, | dt->ray_start, | ||||
| dt->ray_dir, | dt->ray_dir, | ||||
| ob_eval, | ob_eval, | ||||
| em_orig, | em_orig, | ||||
| ▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | static bool raycastObjects(SnapObjectContext *sctx, | ||||
| if (params->use_occlusion_test && v3d && XRAY_FLAG_ENABLED(v3d)) { | if (params->use_occlusion_test && v3d && XRAY_FLAG_ENABLED(v3d)) { | ||||
| /* General testing of occlusion geometry is disabled if the snap is not intended for the edit | /* General testing of occlusion geometry is disabled if the snap is not intended for the edit | ||||
| * cage. */ | * cage. */ | ||||
| if (params->edit_mode_type == SNAP_GEOM_EDIT) { | if (params->edit_mode_type == SNAP_GEOM_EDIT) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| struct RaycastObjUserData data = { | RaycastObjUserData data = {}; | ||||
| .ray_start = ray_start, | data.ray_start = ray_start; | ||||
| .ray_dir = ray_dir, | data.ray_dir = ray_dir; | ||||
| .ob_index = 0, | data.ob_index = 0; | ||||
| .ray_depth = ray_depth, | data.ray_depth = ray_depth; | ||||
| .r_loc = r_loc, | data.r_loc = r_loc; | ||||
| .r_no = r_no, | data.r_no = r_no; | ||||
| .r_index = r_index, | data.r_index = r_index; | ||||
| .r_ob = r_ob, | data.r_ob = r_ob; | ||||
| .r_obmat = r_obmat, | data.r_obmat = r_obmat; | ||||
| .r_hit_list = r_hit_list, | data.r_hit_list = r_hit_list; | ||||
| .use_occlusion_test = params->use_occlusion_test, | data.use_occlusion_test = params->use_occlusion_test; | ||||
| .ret = false, | data.ret = false; | ||||
| }; | |||||
| iter_snap_objects(sctx, params, raycast_obj_fn, &data); | iter_snap_objects(sctx, params, raycast_obj_fn, &data); | ||||
| return data.ret; | return data.ret; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| Show All 27 Lines | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Callbacks | /** \name Callbacks | ||||
| * \{ */ | * \{ */ | ||||
| struct Nearest2dUserData; | struct Nearest2dUserData; | ||||
| typedef void (*Nearest2DGetVertCoCallback)(const int index, | using Nearest2DGetVertCoCallback = void (*)(const int index, | ||||
| const struct Nearest2dUserData *data, | const struct Nearest2dUserData *data, | ||||
| const float **r_co); | const float **r_co); | ||||
| typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, | using Nearest2DGetEdgeVertsCallback = void (*)(const int index, | ||||
| const struct Nearest2dUserData *data, | const struct Nearest2dUserData *data, | ||||
| int r_v_index[2]); | int r_v_index[2]); | ||||
| typedef void (*Nearest2DGetTriVertsCallback)(const int index, | using Nearest2DGetTriVertsCallback = void (*)(const int index, | ||||
| const struct Nearest2dUserData *data, | const struct Nearest2dUserData *data, | ||||
| int r_v_index[3]); | int r_v_index[3]); | ||||
| /* Equal the previous one */ | /* Equal the previous one */ | ||||
| typedef void (*Nearest2DGetTriEdgesCallback)(const int index, | using Nearest2DGetTriEdgesCallback = void (*)(const int index, | ||||
| const struct Nearest2dUserData *data, | const struct Nearest2dUserData *data, | ||||
| int r_e_index[3]); | int r_e_index[3]); | ||||
| typedef void (*Nearest2DCopyVertNoCallback)(const int index, | using Nearest2DCopyVertNoCallback = void (*)(const int index, | ||||
| const struct Nearest2dUserData *data, | const struct Nearest2dUserData *data, | ||||
| float r_no[3]); | float r_no[3]); | ||||
| typedef struct Nearest2dUserData { | struct Nearest2dUserData { | ||||
| Nearest2DGetVertCoCallback get_vert_co; | Nearest2DGetVertCoCallback get_vert_co; | ||||
| Nearest2DGetEdgeVertsCallback get_edge_verts_index; | Nearest2DGetEdgeVertsCallback get_edge_verts_index; | ||||
| Nearest2DGetTriVertsCallback get_tri_verts_index; | Nearest2DGetTriVertsCallback get_tri_verts_index; | ||||
| Nearest2DGetTriEdgesCallback get_tri_edges_index; | Nearest2DGetTriEdgesCallback get_tri_edges_index; | ||||
| Nearest2DCopyVertNoCallback copy_vert_no; | Nearest2DCopyVertNoCallback copy_vert_no; | ||||
| union { | union { | ||||
| struct { | struct { | ||||
| struct BMesh *bm; | struct BMesh *bm; | ||||
| }; | }; | ||||
| struct { | struct { | ||||
| const struct MVert *vert; | const struct MVert *vert; | ||||
| const float (*vert_normals)[3]; | const float (*vert_normals)[3]; | ||||
| const struct MEdge *edge; /* only used for #BVHTreeFromMeshEdges */ | const struct MEdge *edge; /* only used for #BVHTreeFromMeshEdges */ | ||||
| const struct MLoop *loop; | const struct MLoop *loop; | ||||
| const struct MLoopTri *looptri; | const struct MLoopTri *looptri; | ||||
| }; | }; | ||||
| }; | }; | ||||
| bool is_persp; | bool is_persp; | ||||
| bool use_backface_culling; | bool use_backface_culling; | ||||
| } Nearest2dUserData; | }; | ||||
| static void cb_mvert_co_get(const int index, const Nearest2dUserData *data, const float **r_co) | static void cb_mvert_co_get(const int index, const Nearest2dUserData *data, const float **r_co) | ||||
| { | { | ||||
| *r_co = data->vert[index].co; | *r_co = data->vert[index].co; | ||||
| } | } | ||||
| static void cb_bvert_co_get(const int index, const Nearest2dUserData *data, const float **r_co) | static void cb_bvert_co_get(const int index, const Nearest2dUserData *data, const float **r_co) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 119 Lines • ▼ Show 20 Lines | |||||
| static void cb_snap_vert(void *userdata, | static void cb_snap_vert(void *userdata, | ||||
| int index, | int index, | ||||
| const struct DistProjectedAABBPrecalc *precalc, | const struct DistProjectedAABBPrecalc *precalc, | ||||
| const float (*clip_plane)[4], | const float (*clip_plane)[4], | ||||
| const int clip_plane_len, | const int clip_plane_len, | ||||
| BVHTreeNearest *nearest) | BVHTreeNearest *nearest) | ||||
| { | { | ||||
| Nearest2dUserData *data = userdata; | Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata); | ||||
| const float *co; | const float *co; | ||||
| data->get_vert_co(index, data, &co); | data->get_vert_co(index, data, &co); | ||||
| if (test_projected_vert_dist(precalc, | if (test_projected_vert_dist(precalc, | ||||
| clip_plane, | clip_plane, | ||||
| clip_plane_len, | clip_plane_len, | ||||
| data->is_persp, | data->is_persp, | ||||
| co, | co, | ||||
| &nearest->dist_sq, | &nearest->dist_sq, | ||||
| nearest->co)) { | nearest->co)) { | ||||
| data->copy_vert_no(index, data, nearest->no); | data->copy_vert_no(index, data, nearest->no); | ||||
| nearest->index = index; | nearest->index = index; | ||||
| } | } | ||||
| } | } | ||||
| static void cb_snap_edge(void *userdata, | static void cb_snap_edge(void *userdata, | ||||
| int index, | int index, | ||||
| const struct DistProjectedAABBPrecalc *precalc, | const struct DistProjectedAABBPrecalc *precalc, | ||||
| const float (*clip_plane)[4], | const float (*clip_plane)[4], | ||||
| const int clip_plane_len, | const int clip_plane_len, | ||||
| BVHTreeNearest *nearest) | BVHTreeNearest *nearest) | ||||
| { | { | ||||
| struct Nearest2dUserData *data = userdata; | Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata); | ||||
| int vindex[2]; | int vindex[2]; | ||||
| data->get_edge_verts_index(index, data, vindex); | data->get_edge_verts_index(index, data, vindex); | ||||
| const float *v_pair[2]; | const float *v_pair[2]; | ||||
| data->get_vert_co(vindex[0], data, &v_pair[0]); | data->get_vert_co(vindex[0], data, &v_pair[0]); | ||||
| data->get_vert_co(vindex[1], data, &v_pair[1]); | data->get_vert_co(vindex[1], data, &v_pair[1]); | ||||
| Show All 12 Lines | |||||
| static void cb_snap_edge_verts(void *userdata, | static void cb_snap_edge_verts(void *userdata, | ||||
| int index, | int index, | ||||
| const struct DistProjectedAABBPrecalc *precalc, | const struct DistProjectedAABBPrecalc *precalc, | ||||
| const float (*clip_plane)[4], | const float (*clip_plane)[4], | ||||
| const int clip_plane_len, | const int clip_plane_len, | ||||
| BVHTreeNearest *nearest) | BVHTreeNearest *nearest) | ||||
| { | { | ||||
| struct Nearest2dUserData *data = userdata; | Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata); | ||||
| int vindex[2]; | int vindex[2]; | ||||
| data->get_edge_verts_index(index, data, vindex); | data->get_edge_verts_index(index, data, vindex); | ||||
| for (int i = 2; i--;) { | for (int i = 2; i--;) { | ||||
| if (vindex[i] == nearest->index) { | if (vindex[i] == nearest->index) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| cb_snap_vert(userdata, vindex[i], precalc, clip_plane, clip_plane_len, nearest); | cb_snap_vert(userdata, vindex[i], precalc, clip_plane, clip_plane_len, nearest); | ||||
| } | } | ||||
| } | } | ||||
| static void cb_snap_tri_edges(void *userdata, | static void cb_snap_tri_edges(void *userdata, | ||||
| int index, | int index, | ||||
| const struct DistProjectedAABBPrecalc *precalc, | const struct DistProjectedAABBPrecalc *precalc, | ||||
| const float (*clip_plane)[4], | const float (*clip_plane)[4], | ||||
| const int clip_plane_len, | const int clip_plane_len, | ||||
| BVHTreeNearest *nearest) | BVHTreeNearest *nearest) | ||||
| { | { | ||||
| Nearest2dUserData *data = userdata; | Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata); | ||||
| if (data->use_backface_culling) { | if (data->use_backface_culling) { | ||||
| int vindex[3]; | int vindex[3]; | ||||
| data->get_tri_verts_index(index, data, vindex); | data->get_tri_verts_index(index, data, vindex); | ||||
| const float *t0, *t1, *t2; | const float *t0, *t1, *t2; | ||||
| data->get_vert_co(vindex[0], data, &t0); | data->get_vert_co(vindex[0], data, &t0); | ||||
| data->get_vert_co(vindex[1], data, &t1); | data->get_vert_co(vindex[1], data, &t1); | ||||
| Show All 18 Lines | |||||
| static void cb_snap_tri_verts(void *userdata, | static void cb_snap_tri_verts(void *userdata, | ||||
| int index, | int index, | ||||
| const struct DistProjectedAABBPrecalc *precalc, | const struct DistProjectedAABBPrecalc *precalc, | ||||
| const float (*clip_plane)[4], | const float (*clip_plane)[4], | ||||
| const int clip_plane_len, | const int clip_plane_len, | ||||
| BVHTreeNearest *nearest) | BVHTreeNearest *nearest) | ||||
| { | { | ||||
| struct Nearest2dUserData *data = userdata; | Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata); | ||||
| int vindex[3]; | int vindex[3]; | ||||
| data->get_tri_verts_index(index, data, vindex); | data->get_tri_verts_index(index, data, vindex); | ||||
| if (data->use_backface_culling) { | if (data->use_backface_culling) { | ||||
| const float *t0, *t1, *t2; | const float *t0, *t1, *t2; | ||||
| data->get_vert_co(vindex[0], data, &t0); | data->get_vert_co(vindex[0], data, &t0); | ||||
| data->get_vert_co(vindex[1], data, &t1); | data->get_vert_co(vindex[1], data, &t1); | ||||
| Show All 12 Lines | static void cb_snap_tri_verts(void *userdata, | ||||
| } | } | ||||
| } | } | ||||
| static void nearest2d_data_init(SnapObjectData *sod, | static void nearest2d_data_init(SnapObjectData *sod, | ||||
| bool is_persp, | bool is_persp, | ||||
| bool use_backface_culling, | bool use_backface_culling, | ||||
| Nearest2dUserData *r_nearest2d) | Nearest2dUserData *r_nearest2d) | ||||
| { | { | ||||
| if (sod->type == SNAP_MESH) { | if (sod->type == SnapObjectData::Type::Mesh) { | ||||
| r_nearest2d->get_vert_co = cb_mvert_co_get; | r_nearest2d->get_vert_co = cb_mvert_co_get; | ||||
| r_nearest2d->get_edge_verts_index = cb_medge_verts_get; | r_nearest2d->get_edge_verts_index = cb_medge_verts_get; | ||||
| r_nearest2d->copy_vert_no = cb_mvert_no_copy; | r_nearest2d->copy_vert_no = cb_mvert_no_copy; | ||||
| r_nearest2d->get_tri_verts_index = cb_mlooptri_verts_get; | r_nearest2d->get_tri_verts_index = cb_mlooptri_verts_get; | ||||
| r_nearest2d->get_tri_edges_index = cb_mlooptri_edges_get; | r_nearest2d->get_tri_edges_index = cb_mlooptri_edges_get; | ||||
| r_nearest2d->vert = sod->treedata_mesh.vert; | r_nearest2d->vert = sod->treedata_mesh.vert; | ||||
| r_nearest2d->vert_normals = sod->treedata_mesh.vert_normals; | r_nearest2d->vert_normals = sod->treedata_mesh.vert_normals; | ||||
| r_nearest2d->edge = sod->treedata_mesh.edge; | r_nearest2d->edge = sod->treedata_mesh.edge; | ||||
| r_nearest2d->loop = sod->treedata_mesh.loop; | r_nearest2d->loop = sod->treedata_mesh.loop; | ||||
| r_nearest2d->looptri = sod->treedata_mesh.looptri; | r_nearest2d->looptri = sod->treedata_mesh.looptri; | ||||
| } | } | ||||
| else { | else { | ||||
| BLI_assert(sod->type == SNAP_EDIT_MESH); | BLI_assert(sod->type == SnapObjectData::Type::EditMesh); | ||||
| r_nearest2d->get_vert_co = cb_bvert_co_get; | r_nearest2d->get_vert_co = cb_bvert_co_get; | ||||
| r_nearest2d->get_edge_verts_index = cb_bedge_verts_get; | r_nearest2d->get_edge_verts_index = cb_bedge_verts_get; | ||||
| r_nearest2d->copy_vert_no = cb_bvert_no_copy; | r_nearest2d->copy_vert_no = cb_bvert_no_copy; | ||||
| r_nearest2d->get_tri_verts_index = NULL; | r_nearest2d->get_tri_verts_index = nullptr; | ||||
| r_nearest2d->get_tri_edges_index = NULL; | r_nearest2d->get_tri_edges_index = nullptr; | ||||
| r_nearest2d->bm = sod->treedata_editmesh.em->bm; | r_nearest2d->bm = sod->treedata_editmesh.em->bm; | ||||
| } | } | ||||
| 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 All 24 Lines | dist_squared_to_projected_aabb_precalc( | ||||
| &neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval); | &neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval); | ||||
| float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | ||||
| transpose_m4_m4(tobmat, obmat); | transpose_m4_m4(tobmat, obmat); | ||||
| for (int i = sctx->runtime.clip_plane_len; i--;) { | for (int i = sctx->runtime.clip_plane_len; i--;) { | ||||
| mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]); | mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]); | ||||
| } | } | ||||
| BVHTreeNearest nearest = { | BVHTreeNearest nearest{}; | ||||
| .index = -1, | nearest.index = -1; | ||||
| .dist_sq = square_f(*dist_px), | nearest.dist_sq = square_f(*dist_px); | ||||
| }; | |||||
| SnapObjectData *sod = snap_object_data_lookup(sctx, ob_eval); | SnapObjectData *sod = snap_object_data_lookup(sctx, ob_eval); | ||||
| BLI_assert(sod != NULL); | BLI_assert(sod != nullptr); | ||||
| Nearest2dUserData nearest2d; | Nearest2dUserData nearest2d; | ||||
| nearest2d_data_init( | nearest2d_data_init( | ||||
| sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d); | sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d); | ||||
| if (sod->type == SNAP_MESH) { | if (sod->type == SnapObjectData::Type::Mesh) { | ||||
| BVHTreeFromMesh *treedata = &sod->treedata_mesh; | BVHTreeFromMesh *treedata = &sod->treedata_mesh; | ||||
| const MPoly *mp = &sod->poly[*r_index]; | const MPoly *mp = &sod->poly[*r_index]; | ||||
| const MLoop *ml = &treedata->loop[mp->loopstart]; | const MLoop *ml = &treedata->loop[mp->loopstart]; | ||||
| if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) { | if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) { | ||||
| elem = SCE_SNAP_MODE_EDGE; | elem = SCE_SNAP_MODE_EDGE; | ||||
| BLI_assert(treedata->edge != NULL); | BLI_assert(treedata->edge != nullptr); | ||||
| for (int i = mp->totloop; i--; ml++) { | for (int i = mp->totloop; i--; ml++) { | ||||
| cb_snap_edge(&nearest2d, | cb_snap_edge(&nearest2d, | ||||
| ml->e, | ml->e, | ||||
| &neasrest_precalc, | &neasrest_precalc, | ||||
| clip_planes_local, | clip_planes_local, | ||||
| sctx->runtime.clip_plane_len, | sctx->runtime.clip_plane_len, | ||||
| &nearest); | &nearest); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| elem = SCE_SNAP_MODE_VERTEX; | elem = SCE_SNAP_MODE_VERTEX; | ||||
| for (int i = mp->totloop; i--; ml++) { | for (int i = mp->totloop; i--; ml++) { | ||||
| cb_snap_vert(&nearest2d, | cb_snap_vert(&nearest2d, | ||||
| ml->v, | ml->v, | ||||
| &neasrest_precalc, | &neasrest_precalc, | ||||
| clip_planes_local, | clip_planes_local, | ||||
| sctx->runtime.clip_plane_len, | sctx->runtime.clip_plane_len, | ||||
| &nearest); | &nearest); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| BLI_assert(sod->type == SNAP_EDIT_MESH); | BLI_assert(sod->type == SnapObjectData::Type::EditMesh); | ||||
| BMEditMesh *em = sod->treedata_editmesh.em; | BMEditMesh *em = sod->treedata_editmesh.em; | ||||
| BM_mesh_elem_table_ensure(em->bm, BM_FACE); | BM_mesh_elem_table_ensure(em->bm, BM_FACE); | ||||
| BMFace *f = BM_face_at_index(em->bm, *r_index); | BMFace *f = BM_face_at_index(em->bm, *r_index); | ||||
| BMLoop *l_iter, *l_first; | BMLoop *l_iter, *l_first; | ||||
| l_iter = l_first = BM_FACE_FIRST_LOOP(f); | l_iter = l_first = BM_FACE_FIRST_LOOP(f); | ||||
| if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) { | if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) { | ||||
| elem = SCE_SNAP_MODE_EDGE; | elem = SCE_SNAP_MODE_EDGE; | ||||
| ▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| short elem = SCE_SNAP_MODE_EDGE; | short elem = SCE_SNAP_MODE_EDGE; | ||||
| if (ob_eval->type != OB_MESH) { | if (ob_eval->type != OB_MESH) { | ||||
| return elem; | return elem; | ||||
| } | } | ||||
| SnapObjectData *sod = snap_object_data_lookup(sctx, ob_eval); | SnapObjectData *sod = snap_object_data_lookup(sctx, ob_eval); | ||||
| BLI_assert(sod != NULL); | BLI_assert(sod != nullptr); | ||||
| Nearest2dUserData nearest2d; | Nearest2dUserData nearest2d; | ||||
| nearest2d_data_init( | nearest2d_data_init( | ||||
| sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d); | sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d); | ||||
| int vindex[2]; | int vindex[2]; | ||||
| nearest2d.get_edge_verts_index(*r_index, &nearest2d, vindex); | nearest2d.get_edge_verts_index(*r_index, &nearest2d, vindex); | ||||
| const float *v_pair[2]; | const float *v_pair[2]; | ||||
| nearest2d.get_vert_co(vindex[0], &nearest2d, &v_pair[0]); | nearest2d.get_vert_co(vindex[0], &nearest2d, &v_pair[0]); | ||||
| nearest2d.get_vert_co(vindex[1], &nearest2d, &v_pair[1]); | nearest2d.get_vert_co(vindex[1], &nearest2d, &v_pair[1]); | ||||
| struct DistProjectedAABBPrecalc neasrest_precalc; | struct DistProjectedAABBPrecalc neasrest_precalc; | ||||
| { | { | ||||
| float lpmat[4][4]; | float lpmat[4][4]; | ||||
| mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat); | mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat); | ||||
| dist_squared_to_projected_aabb_precalc( | dist_squared_to_projected_aabb_precalc( | ||||
| &neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval); | &neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval); | ||||
| } | } | ||||
| BVHTreeNearest nearest = { | BVHTreeNearest nearest{}; | ||||
| .index = -1, | nearest.index = -1; | ||||
| .dist_sq = square_f(original_dist_px), | nearest.dist_sq = square_f(original_dist_px); | ||||
| }; | |||||
| float lambda; | float lambda; | ||||
| if (!isect_ray_line_v3(neasrest_precalc.ray_origin, | if (!isect_ray_line_v3(neasrest_precalc.ray_origin, | ||||
| neasrest_precalc.ray_direction, | neasrest_precalc.ray_direction, | ||||
| v_pair[0], | v_pair[0], | ||||
| v_pair[1], | v_pair[1], | ||||
| &lambda)) { | &lambda)) { | ||||
| /* do nothing */ | /* do nothing */ | ||||
| } | } | ||||
| else { | else { | ||||
| short snap_to_flag = sctx->runtime.snap_to_flag; | short snap_to_flag = sctx->runtime.snap_to_flag; | ||||
| int e_mode_len = ((snap_to_flag & SCE_SNAP_MODE_EDGE) != 0) + | int e_mode_len = ((snap_to_flag & SCE_SNAP_MODE_EDGE) != 0) + | ||||
| ((snap_to_flag & SCE_SNAP_MODE_VERTEX) != 0) + | ((snap_to_flag & SCE_SNAP_MODE_VERTEX) != 0) + | ||||
| ((snap_to_flag & SCE_SNAP_MODE_EDGE_MIDPOINT) != 0); | ((snap_to_flag & SCE_SNAP_MODE_EDGE_MIDPOINT) != 0); | ||||
| float range = 1.0f / (2 * e_mode_len - 1); | float range = 1.0f / (2 * e_mode_len - 1); | ||||
| if (snap_to_flag & SCE_SNAP_MODE_VERTEX) { | if (snap_to_flag & SCE_SNAP_MODE_VERTEX) { | ||||
| if (lambda < (range) || (1.0f - range) < lambda) { | if (lambda < (range) || (1.0f - range) < lambda) { | ||||
| int v_id = lambda < 0.5f ? 0 : 1; | int v_id = lambda < 0.5f ? 0 : 1; | ||||
| if (test_projected_vert_dist(&neasrest_precalc, | if (test_projected_vert_dist(&neasrest_precalc, | ||||
| NULL, | nullptr, | ||||
| 0, | 0, | ||||
| nearest2d.is_persp, | nearest2d.is_persp, | ||||
| v_pair[v_id], | v_pair[v_id], | ||||
| &nearest.dist_sq, | &nearest.dist_sq, | ||||
| nearest.co)) { | nearest.co)) { | ||||
| nearest.index = vindex[v_id]; | nearest.index = vindex[v_id]; | ||||
| elem = SCE_SNAP_MODE_VERTEX; | elem = SCE_SNAP_MODE_VERTEX; | ||||
| if (r_no) { | if (r_no) { | ||||
| Show All 9 Lines | else { | ||||
| if (snap_to_flag & SCE_SNAP_MODE_EDGE_MIDPOINT) { | if (snap_to_flag & SCE_SNAP_MODE_EDGE_MIDPOINT) { | ||||
| range *= e_mode_len - 1; | range *= e_mode_len - 1; | ||||
| if ((range) < lambda && lambda < (1.0f - range)) { | if ((range) < lambda && lambda < (1.0f - range)) { | ||||
| float vmid[3]; | float vmid[3]; | ||||
| mid_v3_v3v3(vmid, v_pair[0], v_pair[1]); | mid_v3_v3v3(vmid, v_pair[0], v_pair[1]); | ||||
| if (test_projected_vert_dist(&neasrest_precalc, | if (test_projected_vert_dist(&neasrest_precalc, | ||||
| NULL, | nullptr, | ||||
| 0, | 0, | ||||
| nearest2d.is_persp, | nearest2d.is_persp, | ||||
| vmid, | vmid, | ||||
| &nearest.dist_sq, | &nearest.dist_sq, | ||||
| nearest.co)) { | nearest.co)) { | ||||
| nearest.index = *r_index; | nearest.index = *r_index; | ||||
| elem = SCE_SNAP_MODE_EDGE_MIDPOINT; | elem = SCE_SNAP_MODE_EDGE_MIDPOINT; | ||||
| } | } | ||||
| Show All 10 Lines | if (prev_co && (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { | ||||
| if (IN_RANGE(lambda, 0.0f, 1.0f)) { | if (IN_RANGE(lambda, 0.0f, 1.0f)) { | ||||
| interp_v3_v3v3(v_near, va_g, vb_g, lambda); | interp_v3_v3v3(v_near, va_g, vb_g, lambda); | ||||
| if (len_squared_v3v3(prev_co, v_near) > FLT_EPSILON) { | if (len_squared_v3v3(prev_co, v_near) > FLT_EPSILON) { | ||||
| dist_squared_to_projected_aabb_precalc( | dist_squared_to_projected_aabb_precalc( | ||||
| &neasrest_precalc, sctx->runtime.pmat, sctx->runtime.win_size, sctx->runtime.mval); | &neasrest_precalc, sctx->runtime.pmat, sctx->runtime.win_size, sctx->runtime.mval); | ||||
| if (test_projected_vert_dist(&neasrest_precalc, | if (test_projected_vert_dist(&neasrest_precalc, | ||||
| NULL, | nullptr, | ||||
| 0, | 0, | ||||
| nearest2d.is_persp, | nearest2d.is_persp, | ||||
| v_near, | v_near, | ||||
| &nearest.dist_sq, | &nearest.dist_sq, | ||||
| nearest.co)) { | nearest.co)) { | ||||
| nearest.index = *r_index; | nearest.index = *r_index; | ||||
| elem = SCE_SNAP_MODE_EDGE_PERPENDICULAR; | elem = SCE_SNAP_MODE_EDGE_PERPENDICULAR; | ||||
| } | } | ||||
| Show All 36 Lines | static short snapArmature(SnapObjectContext *sctx, | ||||
| float lpmat[4][4], dist_px_sq = square_f(*dist_px); | float lpmat[4][4], dist_px_sq = square_f(*dist_px); | ||||
| mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat); | mul_m4_m4m4(lpmat, sctx->runtime.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, sctx->runtime.win_size, sctx->runtime.mval); | &neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval); | ||||
| bArmature *arm = ob_eval->data; | bArmature *arm = static_cast<bArmature *>(ob_eval->data); | ||||
| const bool is_editmode = arm->edbo != NULL; | const bool is_editmode = arm->edbo != nullptr; | ||||
| if (is_editmode == false) { | if (is_editmode == false) { | ||||
| /* Test BoundBox */ | /* Test BoundBox */ | ||||
| BoundBox *bb = BKE_armature_boundbox_get(ob_eval); | BoundBox *bb = BKE_armature_boundbox_get(ob_eval); | ||||
| if (bb && !snap_bound_box_check_dist(bb->vec[0], | if (bb && !snap_bound_box_check_dist(bb->vec[0], | ||||
| bb->vec[6], | bb->vec[6], | ||||
| lpmat, | lpmat, | ||||
| sctx->runtime.win_size, | sctx->runtime.win_size, | ||||
| ▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| bool has_snap = false; | bool has_snap = false; | ||||
| /* only vertex snapping mode (eg control points and handles) supported for now) */ | /* only vertex snapping mode (eg control points and handles) supported for now) */ | ||||
| if ((sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) == 0) { | if ((sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) == 0) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| Curve *cu = ob_eval->data; | Curve *cu = static_cast<Curve *>(ob_eval->data); | ||||
| float dist_px_sq = square_f(*dist_px); | float dist_px_sq = square_f(*dist_px); | ||||
| float lpmat[4][4]; | float lpmat[4][4]; | ||||
| mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat); | mul_m4_m4m4(lpmat, sctx->runtime.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, sctx->runtime.win_size, sctx->runtime.mval); | &neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval); | ||||
| Show All 28 Lines | static short snapCurve(SnapObjectContext *sctx, | ||||
| float clip_planes_local[MAX_CLIPPLANE_LEN][4]; | float clip_planes_local[MAX_CLIPPLANE_LEN][4]; | ||||
| for (int i = clip_plane_len; i--;) { | for (int i = clip_plane_len; i--;) { | ||||
| mul_v4_m4v4(clip_planes_local[i], tobmat, clip_planes[i]); | mul_v4_m4v4(clip_planes_local[i], tobmat, clip_planes[i]); | ||||
| } | } | ||||
| bool is_persp = sctx->runtime.view_proj == VIEW_PROJ_PERSP; | bool is_persp = sctx->runtime.view_proj == VIEW_PROJ_PERSP; | ||||
| bool skip_selected = params->snap_select == SNAP_NOT_SELECTED; | bool skip_selected = params->snap_select == SNAP_NOT_SELECTED; | ||||
| for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) { | LISTBASE_FOREACH (Nurb *, nu, (use_obedit ? &cu->editnurb->nurbs : &cu->nurb)) { | ||||
| for (int u = 0; u < nu->pntsu; u++) { | for (int u = 0; u < nu->pntsu; u++) { | ||||
| if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) { | if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) { | ||||
| if (use_obedit) { | if (use_obedit) { | ||||
| if (nu->bezt) { | if (nu->bezt) { | ||||
| if (nu->bezt[u].hide) { | if (nu->bezt[u].hide) { | ||||
| /* Skip hidden. */ | /* Skip hidden. */ | ||||
| continue; | continue; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 166 Lines • ▼ Show 20 Lines | static short snapCamera(const SnapObjectContext *sctx, | ||||
| bool is_persp = sctx->runtime.view_proj == VIEW_PROJ_PERSP; | bool is_persp = sctx->runtime.view_proj == VIEW_PROJ_PERSP; | ||||
| float dist_px_sq = square_f(*dist_px); | float dist_px_sq = square_f(*dist_px); | ||||
| float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4]; | float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4]; | ||||
| MovieClip *clip = BKE_object_movieclip_get(scene, object, false); | MovieClip *clip = BKE_object_movieclip_get(scene, object, false); | ||||
| MovieTracking *tracking; | MovieTracking *tracking; | ||||
| if (clip == NULL) { | if (clip == nullptr) { | ||||
| return snap_object_center(sctx, object, obmat, dist_px, r_loc, r_no, r_index); | return snap_object_center(sctx, object, obmat, dist_px, r_loc, r_no, r_index); | ||||
| } | } | ||||
| if (object->transflag & OB_DUPLI) { | if (object->transflag & OB_DUPLI) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| tracking = &clip->tracking; | tracking = &clip->tracking; | ||||
| BKE_tracking_get_camera_object_matrix(object, orig_camera_mat); | BKE_tracking_get_camera_object_matrix(object, orig_camera_mat); | ||||
| invert_m4_m4(orig_camera_imat, orig_camera_mat); | invert_m4_m4(orig_camera_imat, orig_camera_mat); | ||||
| invert_m4_m4(imat, obmat); | invert_m4_m4(imat, obmat); | ||||
| if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) { | if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) { | ||||
| struct DistProjectedAABBPrecalc neasrest_precalc; | struct DistProjectedAABBPrecalc neasrest_precalc; | ||||
| dist_squared_to_projected_aabb_precalc( | dist_squared_to_projected_aabb_precalc( | ||||
| &neasrest_precalc, sctx->runtime.pmat, sctx->runtime.win_size, sctx->runtime.mval); | &neasrest_precalc, sctx->runtime.pmat, sctx->runtime.win_size, sctx->runtime.mval); | ||||
| MovieTrackingObject *tracking_object; | LISTBASE_FOREACH (MovieTrackingObject *, tracking_object, &tracking->objects) { | ||||
| for (tracking_object = tracking->objects.first; tracking_object; | |||||
| tracking_object = tracking_object->next) { | |||||
| ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object); | ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object); | ||||
| MovieTrackingTrack *track; | |||||
| float reconstructed_camera_mat[4][4], reconstructed_camera_imat[4][4]; | float reconstructed_camera_mat[4][4], reconstructed_camera_imat[4][4]; | ||||
| float(*vertex_obmat)[4]; | float(*vertex_obmat)[4]; | ||||
| if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) { | if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) { | ||||
| BKE_tracking_camera_get_reconstructed_interpolate( | BKE_tracking_camera_get_reconstructed_interpolate( | ||||
| tracking, tracking_object, CFRA, reconstructed_camera_mat); | tracking, tracking_object, CFRA, reconstructed_camera_mat); | ||||
| invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat); | invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat); | ||||
| } | } | ||||
| for (track = tracksbase->first; track; track = track->next) { | LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { | ||||
| float bundle_pos[3]; | float bundle_pos[3]; | ||||
| if ((track->flag & TRACK_HAS_BUNDLE) == 0) { | if ((track->flag & TRACK_HAS_BUNDLE) == 0) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| copy_v3_v3(bundle_pos, track->bundle_pos); | copy_v3_v3(bundle_pos, track->bundle_pos); | ||||
| if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { | if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { | ||||
| ▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | if (bb && | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob_eval, me_eval, use_hide); | SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob_eval, me_eval, use_hide); | ||||
| BVHTreeFromMesh *treedata, treedata_tmp; | BVHTreeFromMesh *treedata, treedata_tmp; | ||||
| treedata = &sod->treedata_mesh; | treedata = &sod->treedata_mesh; | ||||
| if (sod->has_loose_edge && sod->bvhtree[0] == NULL) { | if (sod->has_loose_edge && sod->bvhtree[0] == nullptr) { | ||||
| sod->bvhtree[0] = BKE_bvhtree_from_mesh_get( | sod->bvhtree[0] = BKE_bvhtree_from_mesh_get( | ||||
| &treedata_tmp, me_eval, BVHTREE_FROM_LOOSEEDGES, 2); | &treedata_tmp, me_eval, BVHTREE_FROM_LOOSEEDGES, 2); | ||||
| if (sod->bvhtree[0] == NULL) { | if (sod->bvhtree[0] == nullptr) { | ||||
| sod->has_loose_edge = false; | sod->has_loose_edge = false; | ||||
| } | } | ||||
| sod->cached[0] = treedata_tmp.cached; | sod->cached[0] = treedata_tmp.cached; | ||||
| BLI_assert(!ELEM(true, | BLI_assert(!ELEM(true, | ||||
| treedata_tmp.vert_allocated, | treedata_tmp.vert_allocated, | ||||
| treedata_tmp.edge_allocated, | treedata_tmp.edge_allocated, | ||||
| treedata_tmp.face_allocated, | treedata_tmp.face_allocated, | ||||
| treedata_tmp.loop_allocated, | treedata_tmp.loop_allocated, | ||||
| treedata_tmp.looptri_allocated)); | treedata_tmp.looptri_allocated)); | ||||
| } | } | ||||
| if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) { | if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) { | ||||
| if (sod->has_loose_vert && sod->bvhtree[1] == NULL) { | if (sod->has_loose_vert && sod->bvhtree[1] == nullptr) { | ||||
| sod->bvhtree[1] = BKE_bvhtree_from_mesh_get( | sod->bvhtree[1] = BKE_bvhtree_from_mesh_get( | ||||
| &treedata_tmp, me_eval, BVHTREE_FROM_LOOSEVERTS, 2); | &treedata_tmp, me_eval, BVHTREE_FROM_LOOSEVERTS, 2); | ||||
| if (sod->bvhtree[1] == NULL) { | if (sod->bvhtree[1] == nullptr) { | ||||
| sod->has_loose_vert = false; | sod->has_loose_vert = false; | ||||
| } | } | ||||
| sod->cached[1] = treedata_tmp.cached; | sod->cached[1] = treedata_tmp.cached; | ||||
| BLI_assert(!ELEM(true, | BLI_assert(!ELEM(true, | ||||
| treedata_tmp.vert_allocated, | treedata_tmp.vert_allocated, | ||||
| treedata_tmp.edge_allocated, | treedata_tmp.edge_allocated, | ||||
| treedata_tmp.face_allocated, | treedata_tmp.face_allocated, | ||||
| treedata_tmp.loop_allocated, | treedata_tmp.loop_allocated, | ||||
| treedata_tmp.looptri_allocated)); | treedata_tmp.looptri_allocated)); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* Not necessary, just to keep the data more consistent. */ | /* Not necessary, just to keep the data more consistent. */ | ||||
| sod->has_loose_vert = false; | sod->has_loose_vert = false; | ||||
| } | } | ||||
| Nearest2dUserData nearest2d; | Nearest2dUserData nearest2d; | ||||
| nearest2d_data_init( | nearest2d_data_init( | ||||
| sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d); | sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d); | ||||
| BVHTreeNearest nearest = { | BVHTreeNearest nearest{}; | ||||
| .index = -1, | nearest.index = -1; | ||||
| .dist_sq = dist_px_sq, | nearest.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 tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | ||||
| transpose_m4_m4(tobmat, obmat); | transpose_m4_m4(tobmat, obmat); | ||||
| for (int i = sctx->runtime.clip_plane_len; i--;) { | for (int i = sctx->runtime.clip_plane_len; i--;) { | ||||
| mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]); | mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 133 Lines • ▼ Show 20 Lines | static short snapEditMesh(SnapObjectContext *sctx, | ||||
| /* 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, sctx->runtime.win_size, sctx->runtime.mval, dist_px_sq)) { | sod->min, sod->max, lpmat, sctx->runtime.win_size, sctx->runtime.mval, dist_px_sq)) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) { | if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) { | ||||
| BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[0]}; | BVHTreeFromEditMesh treedata{}; | ||||
| treedata.tree = sod->bvhtree[0]; | |||||
| if (treedata.tree == NULL) { | if (treedata.tree == nullptr) { | ||||
| BLI_bitmap *verts_mask = NULL; | BLI_bitmap *verts_mask = nullptr; | ||||
| 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( | bvhtree_from_editmesh_verts_ex(&treedata, | ||||
| &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL, NULL); | em, | ||||
| verts_mask, | |||||
| verts_num_active, | |||||
| 0.0f, | |||||
| 2, | |||||
| 6, | |||||
| BVHTREE_FROM_VERTS, | |||||
| nullptr, | |||||
| nullptr); | |||||
| 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 (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) { | if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) { | ||||
| BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[1]}; | BVHTreeFromEditMesh treedata{}; | ||||
| treedata.tree = sod->bvhtree[1]; | |||||
| if (treedata.tree == NULL) { | if (treedata.tree == nullptr) { | ||||
| BLI_bitmap *edges_mask = NULL; | BLI_bitmap *edges_mask = nullptr; | ||||
| 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( | bvhtree_from_editmesh_edges_ex(&treedata, | ||||
| &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL, NULL); | em, | ||||
| edges_mask, | |||||
| edges_num_active, | |||||
| 0.0f, | |||||
| 2, | |||||
| 6, | |||||
| BVHTREE_FROM_VERTS, | |||||
| nullptr, | |||||
| nullptr); | |||||
| 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); | static_cast<ThreadMutex *>(sod->mesh_runtime->eval_mutex)); | ||||
| } | } | ||||
| sod->bvhtree[1] = treedata.tree; | sod->bvhtree[1] = treedata.tree; | ||||
| sod->cached[1] = treedata.cached; | sod->cached[1] = treedata.cached; | ||||
| } | } | ||||
| } | } | ||||
| Nearest2dUserData nearest2d; | Nearest2dUserData nearest2d; | ||||
| nearest2d_data_init( | nearest2d_data_init( | ||||
| sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d); | sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d); | ||||
| BVHTreeNearest nearest = { | BVHTreeNearest nearest{}; | ||||
| .index = -1, | nearest.index = -1; | ||||
| .dist_sq = dist_px_sq, | nearest.dist_sq = dist_px_sq; | ||||
| }; | |||||
| short elem = SCE_SNAP_MODE_VERTEX; | short elem = SCE_SNAP_MODE_VERTEX; | ||||
| float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | ||||
| transpose_m4_m4(tobmat, obmat); | transpose_m4_m4(tobmat, obmat); | ||||
| for (int i = sctx->runtime.clip_plane_len; i--;) { | for (int i = sctx->runtime.clip_plane_len; i--;) { | ||||
| mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]); | mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | |||||
| */ | */ | ||||
| static void snap_obj_fn(SnapObjectContext *sctx, | static void snap_obj_fn(SnapObjectContext *sctx, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| Object *ob_eval, | Object *ob_eval, | ||||
| float obmat[4][4], | float obmat[4][4], | ||||
| bool is_object_active, | bool is_object_active, | ||||
| void *data) | void *data) | ||||
| { | { | ||||
| struct SnapObjUserData *dt = data; | SnapObjUserData *dt = static_cast<SnapObjUserData *>(data); | ||||
| short retval = 0; | short retval = 0; | ||||
| switch (ob_eval->type) { | switch (ob_eval->type) { | ||||
| case OB_MESH: { | case OB_MESH: { | ||||
| const eSnapEditType edit_mode_type = params->edit_mode_type; | const eSnapEditType edit_mode_type = params->edit_mode_type; | ||||
| 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 == nullptr) { | ||||
| /* 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( | retval = snapEditMesh( | ||||
| sctx, params, ob_eval, em_orig, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); | sctx, params, ob_eval, em_orig, obmat, dt->dist_px, dt->r_loc, dt->r_no, 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 97 Lines • ▼ Show 20 Lines | static short snapObjectsRay(SnapObjectContext *sctx, | ||||
| float *dist_px /* NOLINT */, | float *dist_px /* NOLINT */, | ||||
| /* return args */ | /* return args */ | ||||
| float r_loc[3] /* NOLINT */, | float r_loc[3] /* NOLINT */, | ||||
| float r_no[3] /* NOLINT */, | float r_no[3] /* NOLINT */, | ||||
| int *r_index /* NOLINT */, | int *r_index /* NOLINT */, | ||||
| Object **r_ob, | Object **r_ob, | ||||
| float r_obmat[4][4]) | float r_obmat[4][4]) | ||||
| { | { | ||||
| struct SnapObjUserData data = { | SnapObjUserData data = {}; | ||||
| .dist_px = dist_px, | data.dist_px = dist_px; | ||||
| .r_loc = r_loc, | data.r_loc = r_loc; | ||||
| .r_no = r_no, | data.r_no = r_no; | ||||
| .r_ob = r_ob, | data.r_ob = r_ob; | ||||
| .r_index = r_index, | data.r_index = r_index; | ||||
| .r_obmat = r_obmat, | data.r_obmat = r_obmat; | ||||
| .ret = 0, | data.ret = 0; | ||||
| }; | |||||
| iter_snap_objects(sctx, params, snap_obj_fn, &data); | iter_snap_objects(sctx, params, snap_obj_fn, &data); | ||||
| return data.ret; | return data.ret; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Public Object Snapping API | /** \name Public Object Snapping API | ||||
| * \{ */ | * \{ */ | ||||
| SnapObjectContext *ED_transform_snap_object_context_create(Scene *scene, int flag) | SnapObjectContext *ED_transform_snap_object_context_create(Scene *scene, int flag) | ||||
| { | { | ||||
| SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__); | SnapObjectContext *sctx = MEM_cnew<SnapObjectContext>(__func__); | ||||
| sctx->flag = flag; | sctx->flag = flag; | ||||
| sctx->scene = scene; | sctx->scene = scene; | ||||
| sctx->cache.object_map = BLI_ghash_ptr_new(__func__); | sctx->cache.object_map = BLI_ghash_ptr_new(__func__); | ||||
| /* Initialize as needed (edit-mode only). */ | /* Initialize as needed (edit-mode only). */ | ||||
| sctx->cache.data_to_object_map = NULL; | sctx->cache.data_to_object_map = nullptr; | ||||
| sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); | sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); | ||||
| return sctx; | return sctx; | ||||
| } | } | ||||
| static void snap_object_data_free(void *sod_v) | static void snap_object_data_free(void *sod_v) | ||||
| { | { | ||||
| SnapObjectData *sod = sod_v; | SnapObjectData *sod = static_cast<SnapObjectData *>(sod_v); | ||||
| snap_object_data_clear(sod); | snap_object_data_clear(sod); | ||||
| } | } | ||||
| void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx) | void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx) | ||||
| { | { | ||||
| BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free); | BLI_ghash_free(sctx->cache.object_map, nullptr, snap_object_data_free); | ||||
| if (sctx->cache.data_to_object_map != NULL) { | if (sctx->cache.data_to_object_map != nullptr) { | ||||
| BLI_ghash_free(sctx->cache.data_to_object_map, NULL, NULL); | BLI_ghash_free(sctx->cache.data_to_object_map, nullptr, nullptr); | ||||
| } | } | ||||
| BLI_memarena_free(sctx->cache.mem_arena); | BLI_memarena_free(sctx->cache.mem_arena); | ||||
| MEM_freeN(sctx); | MEM_freeN(sctx); | ||||
| } | } | ||||
| void ED_transform_snap_object_context_set_editmesh_callbacks( | void ED_transform_snap_object_context_set_editmesh_callbacks( | ||||
| SnapObjectContext *sctx, | SnapObjectContext *sctx, | ||||
| Show All 20 Lines | bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx, | ||||
| float r_no[3], | float r_no[3], | ||||
| int *r_index, | int *r_index, | ||||
| Object **r_ob, | Object **r_ob, | ||||
| float r_obmat[4][4]) | float r_obmat[4][4]) | ||||
| { | { | ||||
| sctx->runtime.depsgraph = depsgraph; | sctx->runtime.depsgraph = depsgraph; | ||||
| sctx->runtime.v3d = v3d; | sctx->runtime.v3d = v3d; | ||||
| return raycastObjects( | return raycastObjects(sctx, | ||||
| sctx, params, ray_start, ray_normal, ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL); | params, | ||||
| ray_start, | |||||
| ray_normal, | |||||
| ray_depth, | |||||
| r_loc, | |||||
| r_no, | |||||
| r_index, | |||||
| r_ob, | |||||
| r_obmat, | |||||
| nullptr); | |||||
| } | } | ||||
| bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx, | bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx, | ||||
| Depsgraph *depsgraph, | Depsgraph *depsgraph, | ||||
| const View3D *v3d, | const View3D *v3d, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| const float ray_start[3], | const float ray_start[3], | ||||
| const float ray_normal[3], | const float ray_normal[3], | ||||
| float ray_depth, | float ray_depth, | ||||
| bool sort, | bool sort, | ||||
| ListBase *r_hit_list) | ListBase *r_hit_list) | ||||
| { | { | ||||
| sctx->runtime.depsgraph = depsgraph; | sctx->runtime.depsgraph = depsgraph; | ||||
| sctx->runtime.v3d = v3d; | sctx->runtime.v3d = v3d; | ||||
| if (ray_depth == -1.0f) { | if (ray_depth == -1.0f) { | ||||
| ray_depth = BVH_RAYCAST_DIST_MAX; | ray_depth = BVH_RAYCAST_DIST_MAX; | ||||
| } | } | ||||
| #ifdef DEBUG | #ifdef DEBUG | ||||
| float ray_depth_prev = ray_depth; | float ray_depth_prev = ray_depth; | ||||
| #endif | #endif | ||||
| bool retval = raycastObjects( | bool retval = raycastObjects(sctx, | ||||
| sctx, params, ray_start, ray_normal, &ray_depth, NULL, NULL, NULL, NULL, NULL, r_hit_list); | params, | ||||
| ray_start, | |||||
| ray_normal, | |||||
| &ray_depth, | |||||
| nullptr, | |||||
| nullptr, | |||||
| nullptr, | |||||
| nullptr, | |||||
| nullptr, | |||||
| r_hit_list); | |||||
| /* meant to be readonly for 'all' hits, ensure it is */ | /* meant to be readonly for 'all' hits, ensure it is */ | ||||
| #ifdef DEBUG | #ifdef DEBUG | ||||
| BLI_assert(ray_depth_prev == ray_depth); | BLI_assert(ray_depth_prev == ray_depth); | ||||
| #endif | #endif | ||||
| if (sort) { | if (sort) { | ||||
| BLI_listbase_sort(r_hit_list, hit_depth_cmp); | BLI_listbase_sort(r_hit_list, hit_depth_cmp); | ||||
| Show All 26 Lines | ret = ED_transform_snap_object_project_ray_ex(sctx, | ||||
| depsgraph, | depsgraph, | ||||
| v3d, | v3d, | ||||
| params, | params, | ||||
| ray_start, | ray_start, | ||||
| ray_normal, | ray_normal, | ||||
| ray_depth, | ray_depth, | ||||
| r_co, | r_co, | ||||
| r_no, | r_no, | ||||
| NULL, | nullptr, | ||||
| NULL, | nullptr, | ||||
| NULL); | nullptr); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx, | bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx, | ||||
| Depsgraph *depsgraph, | Depsgraph *depsgraph, | ||||
| const View3D *v3d, | const View3D *v3d, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| const float ray_origin[3], | const float ray_origin[3], | ||||
| const float ray_direction[3], | const float ray_direction[3], | ||||
| float *ray_depth, | float *ray_depth, | ||||
| float r_co[3], | float r_co[3], | ||||
| float r_no[3]) | float r_no[3]) | ||||
| { | { | ||||
| float ray_depth_fallback; | float ray_depth_fallback; | ||||
| if (ray_depth == NULL) { | if (ray_depth == nullptr) { | ||||
| ray_depth_fallback = BVH_RAYCAST_DIST_MAX; | ray_depth_fallback = BVH_RAYCAST_DIST_MAX; | ||||
| ray_depth = &ray_depth_fallback; | ray_depth = &ray_depth_fallback; | ||||
| } | } | ||||
| return transform_snap_context_project_ray_impl( | return transform_snap_context_project_ray_impl( | ||||
| sctx, depsgraph, v3d, params, ray_origin, ray_direction, ray_depth, r_co, r_no); | sctx, depsgraph, v3d, params, ray_origin, ray_direction, ray_depth, r_co, r_no); | ||||
| } | } | ||||
| Show All 20 Lines | static short transform_snap_context_project_view3d_mixed_impl( | ||||
| BLI_assert((snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | | BLI_assert((snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | | ||||
| SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) != | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) != | ||||
| 0); | 0); | ||||
| short retval = 0; | short retval = 0; | ||||
| bool has_hit = false; | bool has_hit = false; | ||||
| Object *ob_eval = NULL; | Object *ob_eval = nullptr; | ||||
| float loc[3]; | float loc[3]; | ||||
| /* Not all snapping callbacks set the normal, | /* Not all snapping callbacks set the normal, | ||||
| * initialize this since any hit copies both the `loc` and `no`. */ | * initialize this since any hit copies both the `loc` and `no`. */ | ||||
| float no[3] = {0.0f, 0.0f, 0.0f}; | float no[3] = {0.0f, 0.0f, 0.0f}; | ||||
| float obmat[4][4]; | float obmat[4][4]; | ||||
| int index = -1; | int index = -1; | ||||
| const RegionView3D *rv3d = region->regiondata; | const RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata); | ||||
| bool use_occlusion_test = params->use_occlusion_test && !XRAY_ENABLED(v3d); | bool use_occlusion_test = params->use_occlusion_test && !XRAY_ENABLED(v3d); | ||||
| if (snap_to_flag & SCE_SNAP_MODE_FACE || use_occlusion_test) { | if (snap_to_flag & SCE_SNAP_MODE_FACE || use_occlusion_test) { | ||||
| float ray_start[3], ray_normal[3]; | float ray_start[3], ray_normal[3]; | ||||
| if (!ED_view3d_win_to_ray_clipped_ex( | if (!ED_view3d_win_to_ray_clipped_ex( | ||||
| depsgraph, region, v3d, mval, NULL, ray_normal, ray_start, true)) { | depsgraph, region, v3d, mval, nullptr, ray_normal, ray_start, true)) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| float dummy_ray_depth = BVH_RAYCAST_DIST_MAX; | float dummy_ray_depth = BVH_RAYCAST_DIST_MAX; | ||||
| has_hit = raycastObjects(sctx, | has_hit = raycastObjects(sctx, | ||||
| params, | params, | ||||
| ray_start, | ray_start, | ||||
| ray_normal, | ray_normal, | ||||
| &dummy_ray_depth, | &dummy_ray_depth, | ||||
| loc, | loc, | ||||
| no, | no, | ||||
| &index, | &index, | ||||
| &ob_eval, | &ob_eval, | ||||
| obmat, | obmat, | ||||
| NULL); | nullptr); | ||||
| if (has_hit) { | if (has_hit) { | ||||
| if (r_face_nor) { | if (r_face_nor) { | ||||
| copy_v3_v3(r_face_nor, no); | copy_v3_v3(r_face_nor, no); | ||||
| } | } | ||||
| if ((snap_to_flag & SCE_SNAP_MODE_FACE)) { | if ((snap_to_flag & SCE_SNAP_MODE_FACE)) { | ||||
| retval = SCE_SNAP_MODE_FACE; | retval = SCE_SNAP_MODE_FACE; | ||||
| Show All 28 Lines | if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | | ||||
| /* First snap to edge instead of middle or perpendicular. */ | /* First snap to edge instead of middle or perpendicular. */ | ||||
| sctx->runtime.snap_to_flag = snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE); | sctx->runtime.snap_to_flag = snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE); | ||||
| if (snap_to_flag & (SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { | if (snap_to_flag & (SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { | ||||
| sctx->runtime.snap_to_flag |= SCE_SNAP_MODE_EDGE; | sctx->runtime.snap_to_flag |= SCE_SNAP_MODE_EDGE; | ||||
| } | } | ||||
| planes_from_projmat(sctx->runtime.pmat, | planes_from_projmat(sctx->runtime.pmat, | ||||
| NULL, | nullptr, | ||||
| NULL, | nullptr, | ||||
| NULL, | nullptr, | ||||
| NULL, | nullptr, | ||||
| sctx->runtime.clip_plane[0], | sctx->runtime.clip_plane[0], | ||||
| sctx->runtime.clip_plane[1]); | sctx->runtime.clip_plane[1]); | ||||
| sctx->runtime.clip_plane_len = 2; | sctx->runtime.clip_plane_len = 2; | ||||
| sctx->runtime.has_occlusion_plane = false; | sctx->runtime.has_occlusion_plane = false; | ||||
| /* By convention we only snap to the original elements of a curve. */ | /* By convention we only snap to the original elements of a curve. */ | ||||
| if (has_hit && ob_eval->type != OB_CURVES_LEGACY) { | if (has_hit && ob_eval->type != OB_CURVES_LEGACY) { | ||||
| ▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | return ED_transform_snap_object_project_view3d_ex(sctx, | ||||
| v3d, | v3d, | ||||
| snap_to, | snap_to, | ||||
| params, | params, | ||||
| mval, | mval, | ||||
| prev_co, | prev_co, | ||||
| dist_px, | dist_px, | ||||
| r_loc, | r_loc, | ||||
| r_no, | r_no, | ||||
| NULL, | nullptr, | ||||
| NULL, | nullptr, | ||||
| NULL, | nullptr, | ||||
| NULL); | nullptr); | ||||
| } | } | ||||
| bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx, | bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx, | ||||
| Depsgraph *depsgraph, | Depsgraph *depsgraph, | ||||
| const ARegion *region, | const ARegion *region, | ||||
| const View3D *v3d, | const View3D *v3d, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| const float mval[2], | const float mval[2], | ||||
| float ray_depth, | float ray_depth, | ||||
| bool sort, | bool sort, | ||||
| ListBase *r_hit_list) | ListBase *r_hit_list) | ||||
| { | { | ||||
| float ray_start[3], ray_normal[3]; | float ray_start[3], ray_normal[3]; | ||||
| if (!ED_view3d_win_to_ray_clipped_ex( | if (!ED_view3d_win_to_ray_clipped_ex( | ||||
| depsgraph, region, v3d, mval, NULL, ray_normal, ray_start, true)) { | depsgraph, region, v3d, mval, nullptr, ray_normal, ray_start, true)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| return ED_transform_snap_object_project_ray_all( | return ED_transform_snap_object_project_ray_all( | ||||
| sctx, depsgraph, v3d, params, ray_start, ray_normal, ray_depth, sort, r_hit_list); | sctx, depsgraph, v3d, params, ray_start, ray_normal, ray_depth, sort, r_hit_list); | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
This parameter is not actually being used, but if we are going to choose a value, let it be BVHTREE_FROM_EM_LOOPTRI or create a new like... BVHTREE_UNUSED?