Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/transform/transform_snap_object.c
| Show First 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | |||||
| #include "ED_armature.h" | #include "ED_armature.h" | ||||
| #include "transform.h" | #include "transform.h" | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** Internal Data Types | /** Internal Data Types | ||||
| * \{ */ | * \{ */ | ||||
| #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 SnapData { | typedef struct SnapData { | ||||
| short snap_to; | short snap_to; | ||||
| float mval[2]; | float mval[2]; | ||||
| float ray_start[3]; | |||||
| float ray_dir[3]; | |||||
| float pmat[4][4]; /* perspective matrix */ | float pmat[4][4]; /* perspective matrix */ | ||||
| float win_size[2];/* win x and y */ | float win_size[2];/* win x and y */ | ||||
| enum eViewProj view_proj; | enum eViewProj view_proj; | ||||
| float depth_range[2]; | float clip_plane[MAX_CLIPPLANE_LEN][4]; | ||||
| short clip_plane_len; | |||||
| } SnapData; | } SnapData; | ||||
| typedef struct SnapObjectData { | typedef struct SnapObjectData { | ||||
| enum { | enum { | ||||
| SNAP_MESH = 1, | SNAP_MESH = 1, | ||||
| SNAP_EDIT_MESH, | SNAP_EDIT_MESH, | ||||
| } type; | } type; | ||||
| } SnapObjectData; | } SnapObjectData; | ||||
| ▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | if ((BASE_VISIBLE(base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 && | ||||
| use_obedit = obedit && obj->data == obedit->data; | use_obedit = obedit && obj->data == obedit->data; | ||||
| sob_callback(sctx, use_obedit, use_obedit ? obedit : obj, obj->obmat, data); | sob_callback(sctx, use_obedit, use_obedit ? obedit : obj, obj->obmat, data); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Generates a struct with the immutable parameters that will be used on all objects. | |||||
| * | |||||
| * \param snap_to: Element to snap, Vertice, Edge or Face. | |||||
| * \param view_proj: ORTHO or PERSP. | |||||
| * Currently only works one at a time, but can eventually operate as flag. | |||||
| * | |||||
| * \param mval: Mouse coords. | |||||
| * (When NULL, ray-casting is handled without any projection matrix correction.) | |||||
| * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min. | |||||
| * \param ray_start: ray_origin moved for the start clipping plane (clip_min). | |||||
| * \param ray_direction: Unit length direction of the ray. | |||||
| * \param depth_range: distances of clipe plane min and clip plane max; | |||||
| */ | |||||
| static void snap_data_set( | |||||
| SnapData *snapdata, | |||||
| const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj, | |||||
| const float mval[2], const float ray_start[3], const float ray_direction[3], | |||||
| const float depth_range[2]) | |||||
| { | |||||
| copy_m4_m4(snapdata->pmat, ((RegionView3D *)ar->regiondata)->persmat); | |||||
| snapdata->win_size[0] = ar->winx; | |||||
| snapdata->win_size[1] = ar->winy; | |||||
| copy_v2_v2(snapdata->mval, mval); | |||||
| snapdata->snap_to = snap_to; | |||||
| copy_v3_v3(snapdata->ray_start, ray_start); | |||||
| copy_v3_v3(snapdata->ray_dir, ray_direction); | |||||
| snapdata->view_proj = view_proj; | |||||
| copy_v2_v2(snapdata->depth_range, depth_range); | |||||
| } | |||||
| MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3]) | MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3]) | ||||
| { | { | ||||
| float dvec[3]; | float dvec[3]; | ||||
| sub_v3_v3v3(dvec, co, ray_start); | sub_v3_v3v3(dvec, co, ray_start); | ||||
| return dot_v3v3(dvec, ray_dir); | return dot_v3v3(dvec, ray_dir); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 438 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 bool raycastObj( | static bool raycastObj( | ||||
| SnapObjectContext *sctx, | SnapObjectContext *sctx, | ||||
| const float ray_start[3], const float ray_dir[3], | const float ray_start[3], const float ray_dir[3], | ||||
| Object *ob, float obmat[4][4], const unsigned int ob_index, | Object *ob, float obmat[4][4], const unsigned int ob_index, | ||||
| bool use_obedit, | bool use_obedit, bool use_occlusion_test, | ||||
| /* read/write args */ | /* read/write args */ | ||||
| float *ray_depth, | float *ray_depth, | ||||
| /* return args */ | /* return args */ | ||||
| float r_loc[3], float r_no[3], int *r_index, | float r_loc[3], float r_no[3], int *r_index, | ||||
| Object **r_ob, float r_obmat[4][4], | Object **r_ob, float r_obmat[4][4], | ||||
| ListBase *r_hit_list) | ListBase *r_hit_list) | ||||
| { | { | ||||
| bool retval = false; | bool retval = false; | ||||
| if (use_occlusion_test) { | |||||
| if (use_obedit && sctx->use_v3d && | |||||
| !(sctx->v3d_data.v3d->flag & V3D_ZBUF_SELECT)) | |||||
| { | |||||
| /* Use of occlude geometry in editing mode disabled. */ | |||||
| return; | |||||
| } | |||||
| } | |||||
| switch (ob->type) { | switch (ob->type) { | ||||
| case OB_MESH: | case OB_MESH: | ||||
| if (use_obedit) { | if (use_obedit) { | ||||
| BMEditMesh *em = BKE_editmesh_from_object(ob); | BMEditMesh *em = BKE_editmesh_from_object(ob); | ||||
| retval = raycastEditMesh( | retval = raycastEditMesh( | ||||
| sctx, | sctx, | ||||
| ray_start, ray_dir, | ray_start, ray_dir, | ||||
| ob, em, obmat, ob_index, | ob, em, obmat, ob_index, | ||||
| Show All 31 Lines | struct RaycastObjUserData { | ||||
| float *ray_depth; | float *ray_depth; | ||||
| /* return args */ | /* return args */ | ||||
| float *r_loc; | float *r_loc; | ||||
| float *r_no; | float *r_no; | ||||
| int *r_index; | int *r_index; | ||||
| Object **r_ob; | Object **r_ob; | ||||
| float (*r_obmat)[4]; | float (*r_obmat)[4]; | ||||
| ListBase *r_hit_list; | ListBase *r_hit_list; | ||||
| bool use_occlusion_test; | |||||
| bool ret; | bool ret; | ||||
| }; | }; | ||||
| static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data) | static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data) | ||||
| { | { | ||||
| struct RaycastObjUserData *dt = data; | struct RaycastObjUserData *dt = data; | ||||
| dt->ret |= raycastObj( | dt->ret |= raycastObj( | ||||
| sctx, | sctx, | ||||
| dt->ray_start, dt->ray_dir, | dt->ray_start, dt->ray_dir, | ||||
| ob, obmat, dt->ob_index++, is_obedit, | ob, obmat, dt->ob_index++, | ||||
campbellbarton: This seems like a high level check to add in low level raycast callback. | |||||
| is_obedit, dt->use_occlusion_test, | |||||
| dt->ray_depth, | dt->ray_depth, | ||||
| dt->r_loc, dt->r_no, dt->r_index, | dt->r_loc, dt->r_no, dt->r_index, | ||||
| dt->r_ob, dt->r_obmat, | dt->r_ob, dt->r_obmat, | ||||
| dt->r_hit_list); | dt->r_hit_list); | ||||
| } | } | ||||
| /** | /** | ||||
| * Main RayCast Function | * Main RayCast Function | ||||
| Show All 40 Lines | struct RaycastObjUserData data = { | ||||
| .ob_index = 0, | .ob_index = 0, | ||||
| .ray_depth = ray_depth, | .ray_depth = ray_depth, | ||||
| .r_loc = r_loc, | .r_loc = r_loc, | ||||
| .r_no = r_no, | .r_no = r_no, | ||||
| .r_index = r_index, | .r_index = r_index, | ||||
| .r_ob = r_ob, | .r_ob = r_ob, | ||||
| .r_obmat = r_obmat, | .r_obmat = r_obmat, | ||||
| .r_hit_list = r_hit_list, | .r_hit_list = r_hit_list, | ||||
| .use_occlusion_test = params->use_occlusion_test, | |||||
| .ret = false, | .ret = false, | ||||
| }; | }; | ||||
| iter_snap_objects(sctx, params, raycast_obj_cb, &data); | iter_snap_objects(sctx, params, raycast_obj_cb, &data); | ||||
| return data.ret; | return data.ret; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | static void cb_mlooptri_verts_get( | ||||
| const MLoopTri *looptri = &data->looptri[index]; | const MLoopTri *looptri = &data->looptri[index]; | ||||
| v_index[0] = loop[looptri->tri[0]].v; | v_index[0] = loop[looptri->tri[0]].v; | ||||
| v_index[1] = loop[looptri->tri[1]].v; | v_index[1] = loop[looptri->tri[1]].v; | ||||
| v_index[2] = loop[looptri->tri[2]].v; | v_index[2] = loop[looptri->tri[2]].v; | ||||
| } | } | ||||
| static bool test_projected_vert_dist( | static bool test_projected_vert_dist( | ||||
| const struct DistProjectedAABBPrecalc *neasrest_precalc, | const struct DistProjectedAABBPrecalc *precalc, | ||||
| const float depth_range[2], | const float (*clip_plane)[4], const int clip_plane_len, | ||||
| const bool is_persp, const float co[3], | const bool is_persp, const float co[3], | ||||
| float *dist_px_sq, float r_co[3]) | float *dist_px_sq, float r_co[3]) | ||||
| { | { | ||||
| float w; | if (!isect_point_planes_v3_negated(clip_plane, clip_plane_len, co)) { | ||||
| if (is_persp) { | |||||
| w = mul_project_m4_v3_zfac(neasrest_precalc->pmat, co); | |||||
| if (w < depth_range[0] || w > depth_range[1]) { | |||||
| return false; | return false; | ||||
Done Inline Actionsremove. campbellbarton: remove. | |||||
| } | } | ||||
| } | |||||
| float co2d[2] = { | float co2d[2] = { | ||||
| (dot_m4_v3_row_x(neasrest_precalc->pmat, co) + neasrest_precalc->pmat[3][0]), | (dot_m4_v3_row_x(precalc->pmat, co) + precalc->pmat[3][0]), | ||||
| (dot_m4_v3_row_y(neasrest_precalc->pmat, co) + neasrest_precalc->pmat[3][1]), | (dot_m4_v3_row_y(precalc->pmat, co) + precalc->pmat[3][1]), | ||||
| }; | }; | ||||
| if (is_persp) { | if (is_persp) { | ||||
| float w = mul_project_m4_v3_zfac(precalc->pmat, co); | |||||
| mul_v2_fl(co2d, 1.0f / w); | mul_v2_fl(co2d, 1.0f / w); | ||||
| } | } | ||||
| const float dist_sq = len_squared_v2v2(neasrest_precalc->mval, co2d); | const float dist_sq = len_squared_v2v2(precalc->mval, co2d); | ||||
| if (dist_sq < *dist_px_sq) { | if (dist_sq < *dist_px_sq) { | ||||
| copy_v3_v3(r_co, co); | copy_v3_v3(r_co, co); | ||||
| *dist_px_sq = dist_sq; | *dist_px_sq = dist_sq; | ||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| static bool test_projected_edge_dist( | static bool test_projected_edge_dist( | ||||
| const struct DistProjectedAABBPrecalc *neasrest_precalc, | const struct DistProjectedAABBPrecalc *precalc, | ||||
| const float depth_range[2], const bool is_persp, | const float (*clip_plane)[4], const int clip_plane_len, | ||||
| const float va[3], const float vb[3], | const bool is_persp, const float va[3], const float vb[3], | ||||
| float *dist_px_sq, float r_co[3]) | float *dist_px_sq, float r_co[3]) | ||||
| { | { | ||||
| float near_co[3], dummy_depth; | float near_co[3], dummy_depth; | ||||
| dist_squared_ray_to_seg_v3( | dist_squared_ray_to_seg_v3( | ||||
| neasrest_precalc->ray_origin, | precalc->ray_origin, | ||||
| neasrest_precalc->ray_direction, | precalc->ray_direction, | ||||
| va, vb, near_co, &dummy_depth); | va, vb, near_co, &dummy_depth); | ||||
| return test_projected_vert_dist( | return test_projected_vert_dist( | ||||
| neasrest_precalc, depth_range, | precalc, clip_plane, clip_plane_len, | ||||
| is_persp, near_co, dist_px_sq, r_co); | is_persp, near_co, dist_px_sq, r_co); | ||||
| } | } | ||||
| static bool snapMeshPolygon( | |||||
| SnapObjectContext *sctx, SnapData *snapdata, | |||||
| Object *ob, float obmat[4][4], | |||||
| /* read/write args */ | |||||
| float *dist_px, | |||||
| /* return args */ | |||||
| float r_loc[3], float r_no[3], int *r_index) | |||||
| { | |||||
| bool retval = false; | |||||
| float lpmat[4][4], dist_px_sq = SQUARE(*dist_px); | |||||
| mul_m4_m4m4(lpmat, snapdata->pmat, obmat); | |||||
| struct DistProjectedAABBPrecalc neasrest_precalc; | |||||
| dist_squared_to_projected_aabb_precalc( | |||||
| &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval); | |||||
| float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | |||||
| transpose_m4_m4(tobmat, obmat); | |||||
| for (int i = snapdata->clip_plane_len; i--;) { | |||||
| mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]); | |||||
| } | |||||
| bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; | |||||
| SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob); | |||||
| BLI_assert(sod != NULL); | |||||
Done Inline ActionsLooks like this should be a lookup BLI_ghash_lookup - since ensure is never assigning to the target. campbellbarton: Looks like this should be a lookup `BLI_ghash_lookup` - since ensure is never assigning to the… | |||||
| if (sod->type == SNAP_MESH) { | |||||
| Mesh *me = ob->data; | |||||
| MPoly *mp = &me->mpoly[*r_index]; | |||||
| const MLoop *ml = &me->mloop[mp->loopstart]; | |||||
| for (int i = mp->totloop; i--; ml++) { | |||||
| if (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) { | |||||
| const MVert *vert = &me->mvert[ml->v]; | |||||
| if (test_projected_vert_dist( | |||||
| &neasrest_precalc, | |||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, vert->co, | |||||
| &dist_px_sq, r_loc)) | |||||
| { | |||||
| normal_short_to_float_v3(r_no, vert->no); | |||||
| *r_index = ml->v; | |||||
| retval = true; | |||||
| } | |||||
| } | |||||
| else { | |||||
| float co_pair[2][3]; | |||||
| const MEdge *edge = &me->medge[ml->e]; | |||||
| copy_v3_v3(co_pair[0], me->mvert[edge->v1].co); | |||||
| copy_v3_v3(co_pair[1], me->mvert[edge->v2].co); | |||||
| if (test_projected_edge_dist( | |||||
| &neasrest_precalc, | |||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, co_pair[0], co_pair[1], | |||||
| &dist_px_sq, r_loc)) | |||||
| { | |||||
| sub_v3_v3v3(r_no, co_pair[0], co_pair[1]); | |||||
| *r_index = ml->e; | |||||
| retval = true; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| else { | |||||
Not Done Inline Actionsthis can be changed to BLI_assert(sod->type == SNAP_EDIT_MESH); campbellbarton: this can be changed to `BLI_assert(sod->type == SNAP_EDIT_MESH);` | |||||
| BLI_assert(sod->type == SNAP_EDIT_MESH); | |||||
| BMEditMesh *em = BKE_editmesh_from_object(ob); | |||||
| BM_mesh_elem_table_ensure(em->bm, BM_FACE); | |||||
| BMFace *f = BM_face_at_index(em->bm, *r_index); | |||||
| BMLoop *l_iter, *l_first; | |||||
| l_iter = l_first = BM_FACE_FIRST_LOOP(f); | |||||
| do { | |||||
| if (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) { | |||||
| const float *co = l_iter->v->co; | |||||
| if (test_projected_vert_dist( | |||||
| &neasrest_precalc, | |||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, co, | |||||
| &dist_px_sq, r_loc)) | |||||
| { | |||||
| copy_v3_v3(r_no, l_iter->v->no); | |||||
| *r_index = BM_elem_index_get(l_iter->v); | |||||
| retval = true; | |||||
| } | |||||
| } | |||||
| else { | |||||
| float co_pair[2][3]; | |||||
| copy_v3_v3(co_pair[0], l_iter->e->v1->co); | |||||
| copy_v3_v3(co_pair[1], l_iter->e->v2->co); | |||||
| if (test_projected_edge_dist( | |||||
| &neasrest_precalc, | |||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, co_pair[0], co_pair[1], | |||||
| &dist_px_sq, r_loc)) | |||||
| { | |||||
| sub_v3_v3v3(r_no, co_pair[0], co_pair[1]); | |||||
| *r_index = BM_elem_index_get(l_iter->e); | |||||
| retval = true; | |||||
| } | |||||
| } | |||||
| } while ((l_iter = l_iter->next) != l_first); | |||||
| } | |||||
| if (retval) { | |||||
| float imat[4][4]; | |||||
| invert_m4_m4(imat, obmat); | |||||
| mul_m4_v3(obmat, r_loc); | |||||
| mul_transposed_mat3_m4_v3(obmat, r_no); | |||||
| normalize_v3(r_no); | |||||
| *dist_px = sqrtf(dist_px_sq); | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** Walk DFS | /** Walk DFS | ||||
| * \{ */ | * \{ */ | ||||
| typedef void (*Nearest2DGetVertCoCallback)(const int index, const float **co, void *data); | typedef void (*Nearest2DGetVertCoCallback)(const int index, const float **co, void *data); | ||||
| typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, int v_index[2], void *data); | typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, int v_index[2], void *data); | ||||
| typedef void (*Nearest2DGetTriVertsCallback)(const int index, int v_index[3], void *data); | typedef void (*Nearest2DGetTriVertsCallback)(const int index, int v_index[3], void *data); | ||||
| typedef void (*Nearest2DGetTriEdgesCallback)(const int index, int e_index[3], void *data); /* Equal the previous one */ | typedef void (*Nearest2DGetTriEdgesCallback)(const int index, int e_index[3], void *data); /* Equal the previous one */ | ||||
| typedef void (*Nearest2DCopyVertNoCallback)(const int index, float r_no[3], void *data); | typedef void (*Nearest2DCopyVertNoCallback)(const int index, float r_no[3], void *data); | ||||
| typedef struct Nearest2dUserData { | typedef struct Nearest2dUserData { | ||||
| bool is_persp; | bool is_persp; | ||||
| float depth_range[2]; | |||||
| short snap_to; | short snap_to; | ||||
| void *userdata; | void *userdata; | ||||
| 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; | ||||
| } Nearest2dUserData; | } Nearest2dUserData; | ||||
| static void cb_walk_leaf_snap_vert( | static void cb_walk_leaf_snap_vert( | ||||
| void *userdata, int index, | void *userdata, int index, | ||||
| const struct DistProjectedAABBPrecalc *precalc, | const struct DistProjectedAABBPrecalc *precalc, | ||||
| const float (*clip_plane)[4], const int clip_plane_len, | |||||
| BVHTreeNearest *nearest) | BVHTreeNearest *nearest) | ||||
| { | { | ||||
| struct Nearest2dUserData *data = userdata; | struct Nearest2dUserData *data = userdata; | ||||
| const float *co; | const float *co; | ||||
| data->get_vert_co(index, &co, data->userdata); | data->get_vert_co(index, &co, data->userdata); | ||||
| if (test_projected_vert_dist( | if (test_projected_vert_dist( | ||||
| precalc, | precalc, | ||||
| data->depth_range, | clip_plane, | ||||
| data->is_persp, | clip_plane_len, | ||||
| co, | data->is_persp, co, | ||||
| &nearest->dist_sq, | &nearest->dist_sq, | ||||
| nearest->co)) | nearest->co)) | ||||
| { | { | ||||
| data->copy_vert_no(index, nearest->no, data->userdata); | data->copy_vert_no(index, nearest->no, data->userdata); | ||||
| nearest->index = index; | nearest->index = index; | ||||
| } | } | ||||
| } | } | ||||
| static void cb_walk_leaf_snap_edge( | static void cb_walk_leaf_snap_edge( | ||||
| void *userdata, int index, | void *userdata, int index, | ||||
| const struct DistProjectedAABBPrecalc *precalc, | const struct DistProjectedAABBPrecalc *precalc, | ||||
| const float (*clip_plane)[4], const int clip_plane_len, | |||||
| BVHTreeNearest *nearest) | BVHTreeNearest *nearest) | ||||
| { | { | ||||
| struct Nearest2dUserData *data = userdata; | struct Nearest2dUserData *data = userdata; | ||||
| int vindex[2]; | int vindex[2]; | ||||
| data->get_edge_verts_index(index, vindex, data->userdata); | data->get_edge_verts_index(index, vindex, data->userdata); | ||||
| if (data->snap_to == SCE_SNAP_MODE_EDGE) { | if (data->snap_to == SCE_SNAP_MODE_EDGE) { | ||||
| const float *v_pair[2]; | const float *v_pair[2]; | ||||
| data->get_vert_co(vindex[0], &v_pair[0], data->userdata); | data->get_vert_co(vindex[0], &v_pair[0], data->userdata); | ||||
| data->get_vert_co(vindex[1], &v_pair[1], data->userdata); | data->get_vert_co(vindex[1], &v_pair[1], data->userdata); | ||||
| if (test_projected_edge_dist( | if (test_projected_edge_dist( | ||||
| precalc, | precalc, | ||||
| data->depth_range, | clip_plane, | ||||
| clip_plane_len, | |||||
| data->is_persp, | data->is_persp, | ||||
| v_pair[0], v_pair[1], | v_pair[0], v_pair[1], | ||||
| &nearest->dist_sq, | &nearest->dist_sq, | ||||
| nearest->co)) | nearest->co)) | ||||
| { | { | ||||
| sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]); | sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]); | ||||
| nearest->index = index; | nearest->index = index; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| for (int i = 0; i < 2; i++) { | for (int i = 0; i < 2; i++) { | ||||
| if (vindex[i] == nearest->index) { | if (vindex[i] == nearest->index) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| cb_walk_leaf_snap_vert(userdata, vindex[i], precalc, nearest); | cb_walk_leaf_snap_vert( | ||||
| userdata, vindex[i], precalc, | |||||
| clip_plane, clip_plane_len, nearest); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void cb_walk_leaf_snap_tri( | static void cb_walk_leaf_snap_tri( | ||||
| void *userdata, int index, | void *userdata, int index, | ||||
| const struct DistProjectedAABBPrecalc *precalc, | const struct DistProjectedAABBPrecalc *precalc, | ||||
| const float (*clip_plane)[4], const int clip_plane_len, | |||||
| BVHTreeNearest *nearest) | BVHTreeNearest *nearest) | ||||
| { | { | ||||
| struct Nearest2dUserData *data = userdata; | struct Nearest2dUserData *data = userdata; | ||||
| if (data->snap_to == SCE_SNAP_MODE_EDGE) { | if (data->snap_to == SCE_SNAP_MODE_EDGE) { | ||||
| int eindex[3]; | int eindex[3]; | ||||
| data->get_tri_edges_index(index, eindex, data->userdata); | data->get_tri_edges_index(index, eindex, data->userdata); | ||||
| for (int i = 0; i < 3; i++) { | for (int i = 0; i < 3; i++) { | ||||
| if (eindex[i] != -1) { | if (eindex[i] != -1) { | ||||
| if (eindex[i] == nearest->index) { | if (eindex[i] == nearest->index) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| cb_walk_leaf_snap_edge(userdata, eindex[i], precalc, nearest); | cb_walk_leaf_snap_edge( | ||||
| userdata, eindex[i], precalc, | |||||
| clip_plane, clip_plane_len, nearest); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| int vindex[3]; | int vindex[3]; | ||||
| data->get_tri_verts_index(index, vindex, data->userdata); | data->get_tri_verts_index(index, vindex, data->userdata); | ||||
| for (int i = 0; i < 3; i++) { | for (int i = 0; i < 3; i++) { | ||||
| if (vindex[i] == nearest->index) { | if (vindex[i] == nearest->index) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| cb_walk_leaf_snap_vert(userdata, vindex[i], precalc, nearest); | cb_walk_leaf_snap_vert( | ||||
| userdata, vindex[i], precalc, | |||||
| clip_plane, clip_plane_len, nearest); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Internal Object Snapping API | /** \name Internal Object Snapping API | ||||
| * \{ */ | * \{ */ | ||||
| static bool snapArmature( | static bool snapArmature( | ||||
| SnapData *snapdata, | SnapData *snapdata, | ||||
| Object *ob, bArmature *arm, float obmat[4][4], | Object *ob, bArmature *arm, float obmat[4][4], | ||||
| /* read/write args */ | /* read/write args */ | ||||
| float *ray_depth, float *dist_px, | float *dist_px, | ||||
| /* return args */ | /* return args */ | ||||
| float r_loc[3], float *UNUSED(r_no)) | float r_loc[3], float *UNUSED(r_no), int *r_index) | ||||
| { | { | ||||
| bool retval = false; | bool retval = false; | ||||
| if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { /* Currently only edge and vert */ | if (snapdata->snap_to == SCE_SNAP_MODE_FACE) { /* Currently only edge and vert */ | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| float lpmat[4][4], dist_px_sq = SQUARE(*dist_px); | float lpmat[4][4], dist_px_sq = SQUARE(*dist_px); | ||||
| Show All 11 Lines | if (bb) { | ||||
| float bb_dist_px_sq = dist_squared_to_projected_aabb( | float bb_dist_px_sq = dist_squared_to_projected_aabb( | ||||
| &neasrest_precalc, bb->vec[0], bb->vec[6], dummy); | &neasrest_precalc, bb->vec[0], bb->vec[6], dummy); | ||||
| if (bb_dist_px_sq > dist_px_sq) { | if (bb_dist_px_sq > dist_px_sq) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| } | } | ||||
| float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | |||||
| transpose_m4_m4(tobmat, obmat); | |||||
| for (int i = snapdata->clip_plane_len; i--;) { | |||||
| mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]); | |||||
| } | |||||
| bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; | bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; | ||||
| if (arm->edbo) { | if (arm->edbo) { | ||||
| for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) { | for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) { | ||||
| if (eBone->layer & arm->layer) { | if (eBone->layer & arm->layer) { | ||||
| /* skip hidden or moving (selected) bones */ | /* skip hidden or moving (selected) bones */ | ||||
| if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) { | if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) { | ||||
| switch (snapdata->snap_to) { | switch (snapdata->snap_to) { | ||||
| case SCE_SNAP_MODE_VERTEX: | case SCE_SNAP_MODE_VERTEX: | ||||
| retval |= test_projected_vert_dist( | retval |= test_projected_vert_dist( | ||||
| &neasrest_precalc, snapdata->depth_range, | &neasrest_precalc, | ||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, eBone->head, &dist_px_sq, r_loc); | is_persp, eBone->head, &dist_px_sq, r_loc); | ||||
| retval |= test_projected_vert_dist( | retval |= test_projected_vert_dist( | ||||
| &neasrest_precalc, snapdata->depth_range, | &neasrest_precalc, | ||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, eBone->tail, &dist_px_sq, r_loc); | is_persp, eBone->tail, &dist_px_sq, r_loc); | ||||
| break; | break; | ||||
| case SCE_SNAP_MODE_EDGE: | case SCE_SNAP_MODE_EDGE: | ||||
| retval |= test_projected_edge_dist( | retval |= test_projected_edge_dist( | ||||
| &neasrest_precalc, snapdata->depth_range, | &neasrest_precalc, | ||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, eBone->head, eBone->tail, | is_persp, eBone->head, eBone->tail, | ||||
| &dist_px_sq, r_loc); | &dist_px_sq, r_loc); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else if (ob->pose && ob->pose->chanbase.first) { | else if (ob->pose && ob->pose->chanbase.first) { | ||||
| for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { | for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { | ||||
| Bone *bone = pchan->bone; | Bone *bone = pchan->bone; | ||||
| /* skip hidden bones */ | /* skip hidden bones */ | ||||
| if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) { | if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) { | ||||
| const float *head_vec = pchan->pose_head; | const float *head_vec = pchan->pose_head; | ||||
| const float *tail_vec = pchan->pose_tail; | const float *tail_vec = pchan->pose_tail; | ||||
| switch (snapdata->snap_to) { | switch (snapdata->snap_to) { | ||||
| case SCE_SNAP_MODE_VERTEX: | case SCE_SNAP_MODE_VERTEX: | ||||
| retval |= test_projected_vert_dist( | retval |= test_projected_vert_dist( | ||||
| &neasrest_precalc, snapdata->depth_range, | &neasrest_precalc, | ||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, head_vec, &dist_px_sq, r_loc); | is_persp, head_vec, &dist_px_sq, r_loc); | ||||
| retval |= test_projected_vert_dist( | retval |= test_projected_vert_dist( | ||||
| &neasrest_precalc, snapdata->depth_range, | &neasrest_precalc, | ||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, tail_vec, &dist_px_sq, r_loc); | is_persp, tail_vec, &dist_px_sq, r_loc); | ||||
| break; | break; | ||||
| case SCE_SNAP_MODE_EDGE: | case SCE_SNAP_MODE_EDGE: | ||||
| retval |= test_projected_edge_dist( | retval |= test_projected_edge_dist( | ||||
| &neasrest_precalc, snapdata->depth_range, | &neasrest_precalc, | ||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, head_vec, tail_vec, | is_persp, head_vec, tail_vec, | ||||
| &dist_px_sq, r_loc); | &dist_px_sq, r_loc); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (retval) { | if (retval) { | ||||
| *dist_px = sqrtf(dist_px_sq); | *dist_px = sqrtf(dist_px_sq); | ||||
| mul_m4_v3(obmat, r_loc); | mul_m4_v3(obmat, r_loc); | ||||
| *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); | if (r_index) { | ||||
| /* Does not support index. */ | |||||
| *r_index = -1; | |||||
| } | |||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| static bool snapCurve( | static bool snapCurve( | ||||
| SnapData *snapdata, | SnapData *snapdata, | ||||
| Object *ob, float obmat[4][4], bool use_obedit, | Object *ob, float obmat[4][4], bool use_obedit, | ||||
| /* read/write args */ | /* read/write args */ | ||||
| float *ray_depth, float *dist_px, | float *dist_px, | ||||
| /* return args */ | /* return args */ | ||||
| float r_loc[3], float *UNUSED(r_no)) | float r_loc[3], float *UNUSED(r_no), int *r_index) | ||||
| { | { | ||||
| bool retval = false; | bool retval = 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 (snapdata->snap_to != SCE_SNAP_MODE_VERTEX) { | if (snapdata->snap_to != SCE_SNAP_MODE_VERTEX) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| Show All 15 Lines | if (bb) { | ||||
| float bb_dist_px_sq = dist_squared_to_projected_aabb( | float bb_dist_px_sq = dist_squared_to_projected_aabb( | ||||
| &neasrest_precalc, bb->vec[0], bb->vec[6], dummy); | &neasrest_precalc, bb->vec[0], bb->vec[6], dummy); | ||||
| if (bb_dist_px_sq > dist_px_sq) { | if (bb_dist_px_sq > dist_px_sq) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| } | } | ||||
| float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | |||||
| transpose_m4_m4(tobmat, obmat); | |||||
| for (int i = snapdata->clip_plane_len; i--;) { | |||||
| mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]); | |||||
| } | |||||
| bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; | bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; | ||||
| for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) { | for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) { | ||||
| for (int u = 0; u < nu->pntsu; u++) { | for (int u = 0; u < nu->pntsu; u++) { | ||||
| switch (snapdata->snap_to) { | switch (snapdata->snap_to) { | ||||
| case SCE_SNAP_MODE_VERTEX: | case SCE_SNAP_MODE_VERTEX: | ||||
| { | { | ||||
| if (use_obedit) { | if (use_obedit) { | ||||
| if (nu->bezt) { | if (nu->bezt) { | ||||
| /* don't snap to selected (moving) or hidden */ | /* don't snap to selected (moving) or hidden */ | ||||
| if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) { | if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) { | ||||
| break; | break; | ||||
| } | } | ||||
| retval |= test_projected_vert_dist( | retval |= test_projected_vert_dist( | ||||
| &neasrest_precalc, snapdata->depth_range, | &neasrest_precalc, | ||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, nu->bezt[u].vec[1], &dist_px_sq, | is_persp, nu->bezt[u].vec[1], &dist_px_sq, | ||||
| r_loc); | r_loc); | ||||
| /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */ | /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */ | ||||
| if (!(nu->bezt[u].f1 & SELECT) && | if (!(nu->bezt[u].f1 & SELECT) && | ||||
| !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT)) | !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT)) | ||||
| { | { | ||||
| retval |= test_projected_vert_dist( | retval |= test_projected_vert_dist( | ||||
| &neasrest_precalc, snapdata->depth_range, | &neasrest_precalc, | ||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, nu->bezt[u].vec[0], &dist_px_sq, | is_persp, nu->bezt[u].vec[0], &dist_px_sq, | ||||
| r_loc); | r_loc); | ||||
| } | } | ||||
| if (!(nu->bezt[u].f3 & SELECT) && | if (!(nu->bezt[u].f3 & SELECT) && | ||||
| !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT)) | !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT)) | ||||
| { | { | ||||
| retval |= test_projected_vert_dist( | retval |= test_projected_vert_dist( | ||||
| &neasrest_precalc, snapdata->depth_range, | &neasrest_precalc, | ||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, nu->bezt[u].vec[2], &dist_px_sq, | is_persp, nu->bezt[u].vec[2], &dist_px_sq, | ||||
| r_loc); | r_loc); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* don't snap to selected (moving) or hidden */ | /* don't snap to selected (moving) or hidden */ | ||||
| if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) { | if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) { | ||||
| break; | break; | ||||
| } | } | ||||
| retval |= test_projected_vert_dist( | retval |= test_projected_vert_dist( | ||||
| &neasrest_precalc, snapdata->depth_range, | &neasrest_precalc, | ||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, nu->bp[u].vec, &dist_px_sq, | is_persp, nu->bp[u].vec, &dist_px_sq, | ||||
| r_loc); | r_loc); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* curve is not visible outside editmode if nurb length less than two */ | /* curve is not visible outside editmode if nurb length less than two */ | ||||
| if (nu->pntsu > 1) { | if (nu->pntsu > 1) { | ||||
| if (nu->bezt) { | if (nu->bezt) { | ||||
| retval |= test_projected_vert_dist( | retval |= test_projected_vert_dist( | ||||
| &neasrest_precalc, snapdata->depth_range, | &neasrest_precalc, | ||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, nu->bezt[u].vec[1], &dist_px_sq, | is_persp, nu->bezt[u].vec[1], &dist_px_sq, | ||||
| r_loc); | r_loc); | ||||
| } | } | ||||
| else { | else { | ||||
| retval |= test_projected_vert_dist( | retval |= test_projected_vert_dist( | ||||
| &neasrest_precalc, snapdata->depth_range, | &neasrest_precalc, | ||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, nu->bp[u].vec, &dist_px_sq, | is_persp, nu->bp[u].vec, &dist_px_sq, | ||||
| r_loc); | r_loc); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (retval) { | if (retval) { | ||||
| *dist_px = sqrtf(dist_px_sq); | *dist_px = sqrtf(dist_px_sq); | ||||
| mul_m4_v3(obmat, r_loc); | mul_m4_v3(obmat, r_loc); | ||||
| *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); | if (r_index) { | ||||
| /* Does not support index yet. */ | |||||
| *r_index = -1; | |||||
| } | |||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* may extend later (for now just snaps to empty center) */ | /* may extend later (for now just snaps to empty center) */ | ||||
| static bool snapEmpty( | static bool snapEmpty( | ||||
| SnapData *snapdata, | SnapData *snapdata, | ||||
| Object *ob, float obmat[4][4], | Object *ob, float obmat[4][4], | ||||
| /* read/write args */ | /* read/write args */ | ||||
| float *ray_depth, float *dist_px, | float *dist_px, | ||||
| /* return args */ | /* return args */ | ||||
| float r_loc[3], float *UNUSED(r_no)) | float r_loc[3], float *UNUSED(r_no), int *r_index) | ||||
| { | { | ||||
| bool retval = false; | bool retval = false; | ||||
| if (ob->transflag & OB_DUPLI) { | if (ob->transflag & OB_DUPLI) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| /* for now only vertex supported */ | /* for now only vertex supported */ | ||||
| switch (snapdata->snap_to) { | switch (snapdata->snap_to) { | ||||
| case SCE_SNAP_MODE_VERTEX: | case 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, snapdata->pmat, snapdata->win_size, snapdata->mval); | &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval); | ||||
| float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | |||||
| transpose_m4_m4(tobmat, obmat); | |||||
| for (int i = snapdata->clip_plane_len; i--;) { | |||||
| mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]); | |||||
| } | |||||
| bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; | bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; | ||||
| float dist_px_sq = SQUARE(*dist_px); | float dist_px_sq = SQUARE(*dist_px); | ||||
| float co[3]; | float co[3]; | ||||
| copy_v3_v3(co, obmat[3]); | copy_v3_v3(co, obmat[3]); | ||||
| if (test_projected_vert_dist( | if (test_projected_vert_dist( | ||||
| &neasrest_precalc, snapdata->depth_range, | &neasrest_precalc, | ||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, co, &dist_px_sq, r_loc)) | is_persp, co, &dist_px_sq, r_loc)) | ||||
| { | { | ||||
| *dist_px = sqrtf(dist_px_sq); | *dist_px = sqrtf(dist_px_sq); | ||||
| *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); | |||||
| retval = true; | retval = true; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| return retval; | if (retval && r_index) { | ||||
| /* Does not support index. */ | |||||
| *r_index = -1; | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | } | ||||
| static bool snapCamera( | static bool snapCamera( | ||||
| const SnapObjectContext *sctx, SnapData *snapdata, | const SnapObjectContext *sctx, SnapData *snapdata, | ||||
| Object *object, float obmat[4][4], | Object *object, float obmat[4][4], | ||||
| /* read/write args */ | /* read/write args */ | ||||
| float *ray_depth, float *dist_px, | float *dist_px, | ||||
| /* return args */ | /* return args */ | ||||
| float r_loc[3], float *UNUSED(r_no)) | float r_loc[3], float *UNUSED(r_no), int *r_index) | ||||
| { | { | ||||
| Scene *scene = sctx->scene; | Scene *scene = sctx->scene; | ||||
| bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; | bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP; | ||||
| float dist_px_sq = SQUARE(*dist_px); | float dist_px_sq = SQUARE(*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]; | ||||
| bool retval = false; | bool retval = false; | ||||
| 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 == NULL) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| if (object->transflag & OB_DUPLI) { | if (object->transflag & OB_DUPLI) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | |||||
| transpose_m4_m4(tobmat, obmat); | |||||
| for (int i = snapdata->clip_plane_len; i--;) { | |||||
| mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]); | |||||
| } | |||||
| tracking = &clip->tracking; | tracking = &clip->tracking; | ||||
| BKE_tracking_get_camera_object_matrix(scene, object, orig_camera_mat); | BKE_tracking_get_camera_object_matrix(scene, 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); | ||||
| switch (snapdata->snap_to) { | switch (snapdata->snap_to) { | ||||
| Show All 34 Lines | case SCE_SNAP_MODE_VERTEX: | ||||
| } | } | ||||
| else { | else { | ||||
| mul_m4_v3(reconstructed_camera_imat, bundle_pos); | mul_m4_v3(reconstructed_camera_imat, bundle_pos); | ||||
| vertex_obmat = obmat; | vertex_obmat = obmat; | ||||
| } | } | ||||
| mul_m4_v3(vertex_obmat, bundle_pos); | mul_m4_v3(vertex_obmat, bundle_pos); | ||||
| retval |= test_projected_vert_dist( | retval |= test_projected_vert_dist( | ||||
| &neasrest_precalc, snapdata->depth_range, | &neasrest_precalc, | ||||
| clip_planes_local, snapdata->clip_plane_len, | |||||
| is_persp, bundle_pos, &dist_px_sq, r_loc); | is_persp, bundle_pos, &dist_px_sq, r_loc); | ||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (retval) { | if (retval) { | ||||
| *dist_px = sqrtf(dist_px_sq); | *dist_px = sqrtf(dist_px_sq); | ||||
| *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); | if (r_index) { | ||||
| /* Does not support index. */ | |||||
| *r_index = -1; | |||||
| } | |||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| static bool snapMesh( | static bool snapMesh( | ||||
| SnapObjectContext *sctx, SnapData *snapdata, | SnapObjectContext *sctx, SnapData *snapdata, | ||||
| Object *ob, Mesh *me, float obmat[4][4], | Object *ob, Mesh *me, float obmat[4][4], | ||||
| /* read/write args */ | /* read/write args */ | ||||
| float *ray_depth, float *dist_px, | float *dist_px, | ||||
| /* return args */ | /* return args */ | ||||
| float r_loc[3], float r_no[3]) | float r_loc[3], float r_no[3], int *r_index) | ||||
| { | { | ||||
| bool retval = false; | bool retval = false; | ||||
| if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) { | if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) { | ||||
| if (me->totedge == 0) { | if (me->totedge == 0) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | if (treedata->tree || bvhtree[0]) { | ||||
| if (treedata->loop && treedata->loop_allocated == false) { | if (treedata->loop && treedata->loop_allocated == false) { | ||||
| treedata->loop = me->mloop; /* CustomData_get_layer(&me->edata, CD_MLOOP);? */ | treedata->loop = me->mloop; /* CustomData_get_layer(&me->edata, CD_MLOOP);? */ | ||||
| } | } | ||||
| if (treedata->looptri && treedata->looptri_allocated == false) { | if (treedata->looptri && treedata->looptri_allocated == false) { | ||||
| treedata->looptri = BKE_mesh_runtime_looptri_ensure(me); | treedata->looptri = BKE_mesh_runtime_looptri_ensure(me); | ||||
| } | } | ||||
| } | } | ||||
| /* Warning: the depth_max is currently being used only in perspective view. | |||||
| * It is not correct to limit the maximum depth for elements obtained with nearest | |||||
| * since this limitation depends on the normal and the size of the occlusion face. | |||||
| * And more... ray_depth is being confused with Z-depth here... (varies only the precision) */ | |||||
| const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0]; | |||||
| Nearest2dUserData neasrest2d = { | Nearest2dUserData neasrest2d = { | ||||
| .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, | .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, | ||||
| .depth_range = {snapdata->depth_range[0], ray_depth_max_global}, | |||||
| .snap_to = snapdata->snap_to, | .snap_to = snapdata->snap_to, | ||||
| .userdata = treedata, | .userdata = treedata, | ||||
| .get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get, | .get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get, | ||||
| .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get, | .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get, | ||||
| .get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get, | .get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get, | ||||
| .get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get, | .get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get, | ||||
| .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy, | .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy, | ||||
| }; | }; | ||||
| BVHTreeNearest nearest = { | BVHTreeNearest nearest = { | ||||
| .index = -1, | .index = -1, | ||||
| .dist_sq = dist_px_sq, | .dist_sq = dist_px_sq, | ||||
| }; | }; | ||||
| float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | |||||
| transpose_m4_m4(tobmat, obmat); | |||||
| for (int i = snapdata->clip_plane_len; i--;) { | |||||
| mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]); | |||||
| } | |||||
| if (bvhtree[1]) { | if (bvhtree[1]) { | ||||
| /* snap to loose verts */ | /* snap to loose verts */ | ||||
| BLI_bvhtree_find_nearest_projected( | BLI_bvhtree_find_nearest_projected( | ||||
| bvhtree[1], lpmat, snapdata->win_size, snapdata->mval, | bvhtree[1], lpmat, snapdata->win_size, snapdata->mval, | ||||
| NULL, 0, &nearest, cb_walk_leaf_snap_vert, &neasrest2d); | clip_planes_local, snapdata->clip_plane_len, | ||||
| &nearest, cb_walk_leaf_snap_vert, &neasrest2d); | |||||
| } | } | ||||
| if (bvhtree[0]) { | if (bvhtree[0]) { | ||||
| /* snap to loose edges */ | /* snap to loose edges */ | ||||
| BLI_bvhtree_find_nearest_projected( | BLI_bvhtree_find_nearest_projected( | ||||
| bvhtree[0], lpmat, snapdata->win_size, snapdata->mval, | bvhtree[0], lpmat, snapdata->win_size, snapdata->mval, | ||||
| NULL, 0, &nearest, cb_walk_leaf_snap_edge, &neasrest2d); | clip_planes_local, snapdata->clip_plane_len, | ||||
| &nearest, cb_walk_leaf_snap_edge, &neasrest2d); | |||||
| } | } | ||||
| if (treedata->tree) { | if (treedata->tree) { | ||||
| /* snap to looptris */ | /* snap to looptris */ | ||||
| BLI_bvhtree_find_nearest_projected( | BLI_bvhtree_find_nearest_projected( | ||||
| treedata->tree, lpmat, snapdata->win_size, snapdata->mval, | treedata->tree, lpmat, snapdata->win_size, snapdata->mval, | ||||
| NULL, 0, &nearest, cb_walk_leaf_snap_tri, &neasrest2d); | clip_planes_local, snapdata->clip_plane_len, | ||||
| &nearest, cb_walk_leaf_snap_tri, &neasrest2d); | |||||
| } | } | ||||
| if (nearest.index != -1) { | if (nearest.index != -1) { | ||||
| float imat[4][4]; | *dist_px = sqrtf(nearest.dist_sq); | ||||
| float timat[3][3]; /* transpose inverse matrix for normals */ | |||||
| invert_m4_m4(imat, obmat); | |||||
| transpose_m3_m4(timat, imat); | |||||
| copy_v3_v3(r_loc, nearest.co); | copy_v3_v3(r_loc, nearest.co); | ||||
| mul_m4_v3(obmat, r_loc); | mul_m4_v3(obmat, r_loc); | ||||
| if (r_no) { | if (r_no) { | ||||
| float imat[4][4]; | |||||
| invert_m4_m4(imat, obmat); | |||||
| copy_v3_v3(r_no, nearest.no); | copy_v3_v3(r_no, nearest.no); | ||||
| mul_m3_v3(timat, r_no); | mul_transposed_mat3_m4_v3(obmat, r_no); | ||||
| normalize_v3(r_no); | normalize_v3(r_no); | ||||
| } | } | ||||
| *dist_px = sqrtf(nearest.dist_sq); | if (r_index) { | ||||
| *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); | *r_index = nearest.index; | ||||
| } | |||||
| retval = true; | retval = true; | ||||
| } | } | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| static bool snapEditMesh( | static bool snapEditMesh( | ||||
| SnapObjectContext *sctx, SnapData *snapdata, | SnapObjectContext *sctx, SnapData *snapdata, | ||||
| Object *ob, BMEditMesh *em, float obmat[4][4], | Object *ob, BMEditMesh *em, float obmat[4][4], | ||||
| /* read/write args */ | /* read/write args */ | ||||
| float *ray_depth, float *dist_px, | float *dist_px, | ||||
| /* return args */ | /* return args */ | ||||
| float r_loc[3], float r_no[3]) | float r_loc[3], float r_no[3], int *r_index) | ||||
| { | { | ||||
| bool retval = false; | bool retval = false; | ||||
| if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) { | if (snapdata->snap_to == SCE_SNAP_MODE_EDGE) { | ||||
| if (em->bm->totedge == 0) { | if (em->bm->totedge == 0) { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | if (treedata) { | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| Nearest2dUserData neasrest2d = { | Nearest2dUserData neasrest2d = { | ||||
| .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, | .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, | ||||
| .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]}, | |||||
| .snap_to = snapdata->snap_to, | .snap_to = snapdata->snap_to, | ||||
| .userdata = treedata->em, | .userdata = treedata->em, | ||||
| .get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get, | .get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get, | ||||
| .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get, | .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get, | ||||
| .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy, | .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy, | ||||
| }; | }; | ||||
| BVHTreeNearest nearest = { | BVHTreeNearest nearest = { | ||||
| .index = -1, | .index = -1, | ||||
| .dist_sq = SQUARE(*dist_px), | .dist_sq = SQUARE(*dist_px), | ||||
| }; | }; | ||||
| BVHTree_NearestProjectedCallback cb_walk_leaf; | BVHTree_NearestProjectedCallback cb_walk_leaf; | ||||
| if (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) { | if (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) { | ||||
| cb_walk_leaf = cb_walk_leaf_snap_vert; | cb_walk_leaf = cb_walk_leaf_snap_vert; | ||||
| BM_mesh_elem_table_ensure(em->bm, BM_VERT); | BM_mesh_elem_table_ensure(em->bm, BM_VERT); | ||||
| } | } | ||||
| else { | else { | ||||
| cb_walk_leaf = cb_walk_leaf_snap_edge; | cb_walk_leaf = cb_walk_leaf_snap_edge; | ||||
| BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT); | BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT); | ||||
| } | } | ||||
| float lpmat[4][4]; | float lpmat[4][4], tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4]; | ||||
| mul_m4_m4m4(lpmat, snapdata->pmat, obmat); | mul_m4_m4m4(lpmat, snapdata->pmat, obmat); | ||||
| transpose_m4_m4(tobmat, obmat); | |||||
| for (int i = snapdata->clip_plane_len; i--;) { | |||||
| mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]); | |||||
| } | |||||
| BLI_bvhtree_find_nearest_projected( | BLI_bvhtree_find_nearest_projected( | ||||
| treedata->tree, lpmat, snapdata->win_size, snapdata->mval, | treedata->tree, lpmat, snapdata->win_size, snapdata->mval, | ||||
| NULL, 0, &nearest, cb_walk_leaf, &neasrest2d); | clip_planes_local, snapdata->clip_plane_len, | ||||
| &nearest, cb_walk_leaf, &neasrest2d); | |||||
| if (nearest.index != -1) { | if (nearest.index != -1) { | ||||
| float imat[4][4]; | *dist_px = sqrtf(nearest.dist_sq); | ||||
| float timat[3][3]; /* transpose inverse matrix for normals */ | |||||
| invert_m4_m4(imat, obmat); | |||||
| transpose_m3_m4(timat, imat); | |||||
| copy_v3_v3(r_loc, nearest.co); | copy_v3_v3(r_loc, nearest.co); | ||||
| mul_m4_v3(obmat, r_loc); | mul_m4_v3(obmat, r_loc); | ||||
| if (r_no) { | if (r_no) { | ||||
| float imat[4][4]; | |||||
| invert_m4_m4(imat, obmat); | |||||
| copy_v3_v3(r_no, nearest.no); | copy_v3_v3(r_no, nearest.no); | ||||
| mul_m3_v3(timat, r_no); | mul_transposed_mat3_m4_v3(obmat, r_no); | ||||
| normalize_v3(r_no); | normalize_v3(r_no); | ||||
| } | } | ||||
| *dist_px = sqrtf(nearest.dist_sq); | if (r_index) { | ||||
| *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); | *r_index = nearest.index; | ||||
| } | |||||
| retval = true; | retval = true; | ||||
| } | } | ||||
| return retval; | return retval; | ||||
| } | } | ||||
| /** | /** | ||||
| * \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 bool snapObject( | static bool snapObject( | ||||
| SnapObjectContext *sctx, SnapData *snapdata, | SnapObjectContext *sctx, SnapData *snapdata, | ||||
| Object *ob, float obmat[4][4], bool use_obedit, | Object *ob, float obmat[4][4], bool use_obedit, | ||||
| /* read/write args */ | /* read/write args */ | ||||
| float *ray_depth, float *dist_px, | float *dist_px, | ||||
| /* return args */ | /* return args */ | ||||
| float r_loc[3], float r_no[3], | float r_loc[3], float r_no[3], int *r_index, | ||||
| Object **r_ob, float r_obmat[4][4]) | Object **r_ob, float r_obmat[4][4]) | ||||
| { | { | ||||
| bool retval = false; | bool retval = false; | ||||
| switch (ob->type) { | switch (ob->type) { | ||||
| case OB_MESH: | case OB_MESH: | ||||
| if (use_obedit) { | if (use_obedit) { | ||||
| BMEditMesh *em = BKE_editmesh_from_object(ob); | BMEditMesh *em = BKE_editmesh_from_object(ob); | ||||
| retval = snapEditMesh( | retval = snapEditMesh( | ||||
| sctx, snapdata, ob, em, obmat, | sctx, snapdata, ob, em, obmat, | ||||
| ray_depth, dist_px, | dist_px, | ||||
| r_loc, r_no); | r_loc, r_no, r_index); | ||||
| } | } | ||||
| else { | else { | ||||
| retval = snapMesh( | retval = snapMesh( | ||||
| sctx, snapdata, ob, ob->data, obmat, | sctx, snapdata, ob, ob->data, obmat, | ||||
| ray_depth, dist_px, | dist_px, | ||||
| r_loc, r_no); | r_loc, r_no, r_index); | ||||
| } | } | ||||
| break; | break; | ||||
| case OB_ARMATURE: | case OB_ARMATURE: | ||||
| retval = snapArmature( | retval = snapArmature( | ||||
| snapdata, | snapdata, | ||||
| ob, ob->data, obmat, | ob, ob->data, obmat, | ||||
| ray_depth, dist_px, | dist_px, | ||||
| r_loc, r_no); | r_loc, r_no, r_index); | ||||
| break; | break; | ||||
| case OB_CURVE: | case OB_CURVE: | ||||
| retval = snapCurve( | retval = snapCurve( | ||||
| snapdata, | snapdata, | ||||
| ob, obmat, use_obedit, | ob, obmat, use_obedit, | ||||
| ray_depth, dist_px, | dist_px, | ||||
| r_loc, r_no); | r_loc, r_no, r_index); | ||||
| break; | break; | ||||
| case OB_EMPTY: | case OB_EMPTY: | ||||
| retval = snapEmpty( | retval = snapEmpty( | ||||
| snapdata, ob, obmat, | snapdata, ob, obmat, | ||||
| ray_depth, dist_px, | dist_px, | ||||
| r_loc, r_no); | r_loc, r_no, r_index); | ||||
| break; | break; | ||||
| case OB_CAMERA: | case OB_CAMERA: | ||||
| retval = snapCamera( | retval = snapCamera( | ||||
| sctx, snapdata, ob, obmat, | sctx, snapdata, ob, obmat, | ||||
| ray_depth, dist_px, | dist_px, | ||||
| r_loc, r_no); | r_loc, r_no, r_index); | ||||
| break; | break; | ||||
| } | } | ||||
| if (retval) { | if (retval) { | ||||
| if (r_ob) { | if (r_ob) { | ||||
| *r_ob = ob; | *r_ob = ob; | ||||
| } | } | ||||
| if (r_obmat) { | if (r_obmat) { | ||||
| copy_m4_m4(r_obmat, obmat); | copy_m4_m4(r_obmat, obmat); | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| struct SnapObjUserData { | struct SnapObjUserData { | ||||
| SnapData *snapdata; | SnapData *snapdata; | ||||
| /* read/write args */ | /* read/write args */ | ||||
| float *ray_depth; | |||||
| float *dist_px; | float *dist_px; | ||||
| /* return args */ | /* return args */ | ||||
| float *r_loc; | float *r_loc; | ||||
| float *r_no; | float *r_no; | ||||
| int *r_index; | |||||
| Object **r_ob; | Object **r_ob; | ||||
| float (*r_obmat)[4]; | float (*r_obmat)[4]; | ||||
| bool ret; | bool ret; | ||||
| }; | }; | ||||
| static void sanp_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data) | static void sanp_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data) | ||||
| { | { | ||||
| struct SnapObjUserData *dt = data; | struct SnapObjUserData *dt = data; | ||||
| dt->ret |= snapObject( | dt->ret |= snapObject( | ||||
| sctx, dt->snapdata, | sctx, dt->snapdata, | ||||
| ob, obmat, is_obedit, | ob, obmat, is_obedit, | ||||
| /* read/write args */ | /* read/write args */ | ||||
| dt->ray_depth, dt->dist_px, | dt->dist_px, | ||||
| /* return args */ | /* return args */ | ||||
| dt->r_loc, dt->r_no, | dt->r_loc, dt->r_no, dt->r_index, | ||||
| dt->r_ob, dt->r_obmat); | dt->r_ob, dt->r_obmat); | ||||
| } | } | ||||
| /** | /** | ||||
| * Main Snapping Function | * Main Snapping Function | ||||
| * ====================== | * ====================== | ||||
| * | * | ||||
| Show All 20 Lines | |||||
| * \param r_ob: Hit object. | * \param r_ob: Hit object. | ||||
| * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances). | * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances). | ||||
| * | * | ||||
| */ | */ | ||||
| static bool snapObjectsRay( | static bool snapObjectsRay( | ||||
| SnapObjectContext *sctx, SnapData *snapdata, | SnapObjectContext *sctx, SnapData *snapdata, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| /* read/write args */ | /* read/write args */ | ||||
| float *ray_depth, float *dist_px, | float *dist_px, | ||||
| /* return args */ | /* return args */ | ||||
| float r_loc[3], float r_no[3], | float r_loc[3], float r_no[3], int *r_index, | ||||
| Object **r_ob, float r_obmat[4][4]) | Object **r_ob, float r_obmat[4][4]) | ||||
| { | { | ||||
| struct SnapObjUserData data = { | struct SnapObjUserData data = { | ||||
| .snapdata = snapdata, | .snapdata = snapdata, | ||||
| .ray_depth = ray_depth, | |||||
| .dist_px = dist_px, | .dist_px = dist_px, | ||||
| .r_loc = r_loc, | .r_loc = r_loc, | ||||
| .r_no = r_no, | .r_no = r_no, | ||||
| .r_ob = r_ob, | .r_ob = r_ob, | ||||
| .r_index = r_index, | |||||
| .r_obmat = r_obmat, | .r_obmat = r_obmat, | ||||
| .ret = false, | .ret = false, | ||||
| }; | }; | ||||
| iter_snap_objects(sctx, params, sanp_obj_cb, &data); | iter_snap_objects(sctx, params, sanp_obj_cb, &data); | ||||
| return data.ret; | return data.ret; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 182 Lines • ▼ Show 20 Lines | |||||
| static bool transform_snap_context_project_view3d_mixed_impl( | static bool transform_snap_context_project_view3d_mixed_impl( | ||||
| SnapObjectContext *sctx, | SnapObjectContext *sctx, | ||||
| const unsigned short snap_to_flag, | const unsigned short snap_to_flag, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| const float mval[2], float *dist_px, | const float mval[2], float *dist_px, | ||||
| float r_co[3], float r_no[3]) | float r_co[3], float r_no[3]) | ||||
| { | { | ||||
| float ray_depth = BVH_RAYCAST_DIST_MAX; | |||||
| bool is_hit = false; | |||||
| const int elem_type[3] = {SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE, SCE_SNAP_MODE_FACE}; | const int elem_type[3] = {SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE, SCE_SNAP_MODE_FACE}; | ||||
| BLI_assert(snap_to_flag != 0); | BLI_assert(snap_to_flag != 0); | ||||
| BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0); | BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0); | ||||
| if (params->use_occlusion_test) { | |||||
| const float dist_px_orig = dist_px ? *dist_px : 0; | |||||
| for (int i = 2; i >= 0; i--) { | |||||
| if (snap_to_flag & (1 << i)) { | |||||
| if (i == 0) { | |||||
| BLI_assert(dist_px != NULL); | |||||
| *dist_px = dist_px_orig; | |||||
| } | |||||
| if (ED_transform_snap_object_project_view3d( | |||||
| sctx, | |||||
| elem_type[i], params, | |||||
| mval, dist_px, &ray_depth, | |||||
| r_co, r_no)) | |||||
| { | |||||
| /* 0.01 is a random but small value to prioritizing | |||||
| * the first elements of the loop */ | |||||
| ray_depth += 0.01f; | |||||
| is_hit = true; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| else { | |||||
| for (int i = 0; i < 3; i++) { | for (int i = 0; i < 3; i++) { | ||||
| if (snap_to_flag & (1 << i)) { | if (snap_to_flag & (1 << i)) { | ||||
| if (ED_transform_snap_object_project_view3d( | if (ED_transform_snap_object_project_view3d( | ||||
| sctx, | sctx, | ||||
| elem_type[i], params, | elem_type[i], params, | ||||
| mval, dist_px, &ray_depth, | mval, dist_px, NULL, | ||||
| r_co, r_no)) | r_co, r_no)) | ||||
| { | { | ||||
| is_hit = true; | return true; | ||||
| break; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return is_hit; | return false; | ||||
| } | } | ||||
| /** | /** | ||||
| * Convenience function for performing snapping. | * Convenience function for performing snapping. | ||||
| * | * | ||||
| * Given a 2D region value, snap to vert/edge/face. | * Given a 2D region value, snap to vert/edge/face. | ||||
| * | * | ||||
| * \param sctx: Snap context. | * \param sctx: Snap context. | ||||
| Show All 21 Lines | bool ED_transform_snap_object_project_view3d_ex( | ||||
| SnapObjectContext *sctx, | SnapObjectContext *sctx, | ||||
| const unsigned short snap_to, | const unsigned short snap_to, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| const float mval[2], float *dist_px, | const float mval[2], float *dist_px, | ||||
| float *ray_depth, | float *ray_depth, | ||||
| float r_loc[3], float r_no[3], int *r_index, | float r_loc[3], float r_no[3], int *r_index, | ||||
| Object **r_ob, float r_obmat[4][4]) | Object **r_ob, float r_obmat[4][4]) | ||||
| { | { | ||||
| float loc[3], no[3], obmat[4][4]; | |||||
| Object *ob = NULL; | |||||
| int index_fallback; | |||||
| if (r_index == NULL) { | |||||
| r_index = &index_fallback; | |||||
| } | |||||
| bool has_hit = false, retval = false; | |||||
| const ARegion *ar = sctx->v3d_data.ar; | const ARegion *ar = sctx->v3d_data.ar; | ||||
| const RegionView3D *rv3d = ar->regiondata; | const RegionView3D *rv3d = ar->regiondata; | ||||
| if (snap_to == SCE_SNAP_MODE_FACE || params->use_occlusion_test) { | |||||
| float ray_origin[3], ray_end[3], ray_start[3], ray_normal[3], depth_range[2]; | float ray_origin[3], ray_end[3], ray_start[3], ray_normal[3], depth_range[2]; | ||||
| ED_view3d_win_to_origin(ar, mval, ray_origin); | ED_view3d_win_to_origin(ar, mval, ray_origin); | ||||
| ED_view3d_win_to_vector(ar, mval, ray_normal); | ED_view3d_win_to_vector(ar, mval, ray_normal); | ||||
| ED_view3d_clip_range_get( | ED_view3d_clip_range_get( | ||||
| sctx->depsgraph, | sctx->depsgraph, | ||||
| sctx->v3d_data.v3d, sctx->v3d_data.ar->regiondata, | sctx->v3d_data.v3d, sctx->v3d_data.ar->regiondata, | ||||
| &depth_range[0], &depth_range[1], false); | &depth_range[0], &depth_range[1], false); | ||||
| madd_v3_v3v3fl(ray_start, ray_origin, ray_normal, depth_range[0]); | madd_v3_v3v3fl(ray_start, ray_origin, ray_normal, depth_range[0]); | ||||
| madd_v3_v3v3fl(ray_end, ray_origin, ray_normal, depth_range[1]); | madd_v3_v3v3fl(ray_end, ray_origin, ray_normal, depth_range[1]); | ||||
| if (!ED_view3d_clip_segment(rv3d, ray_start, ray_end)) { | if (!ED_view3d_clip_segment(rv3d, ray_start, ray_end)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| float ray_depth_fallback; | float ray_depth_fallback; | ||||
| if (ray_depth == NULL) { | if (ray_depth == NULL) { | ||||
| ray_depth_fallback = BVH_RAYCAST_DIST_MAX; | ray_depth_fallback = BVH_RAYCAST_DIST_MAX; | ||||
| ray_depth = &ray_depth_fallback; | ray_depth = &ray_depth_fallback; | ||||
| } | } | ||||
| if (snap_to == SCE_SNAP_MODE_FACE) { | has_hit = raycastObjects( | ||||
| return raycastObjects( | |||||
| sctx, params, | sctx, params, | ||||
| ray_start, ray_normal, | ray_start, ray_normal, | ||||
| ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL); | &ray_depth_fallback, loc, no, | ||||
| r_index, &ob, obmat, NULL); | |||||
| retval = has_hit && (snap_to == SCE_SNAP_MODE_FACE); | |||||
| } | } | ||||
| else { | |||||
| if (ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { | |||||
| SnapData snapdata; | SnapData snapdata; | ||||
| const enum eViewProj view_proj = rv3d->is_persp ? | |||||
| VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO; | |||||
| snap_data_set( | copy_m4_m4(snapdata.pmat, rv3d->persmat); | ||||
| &snapdata, ar, snap_to, view_proj, mval, | snapdata.win_size[0] = ar->winx; | ||||
| ray_start, ray_normal, depth_range); | snapdata.win_size[1] = ar->winy; | ||||
| copy_v2_v2(snapdata.mval, mval); | |||||
| snapdata.snap_to = snap_to; | |||||
| snapdata.view_proj = rv3d->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO; | |||||
| planes_from_projmat( | |||||
| snapdata.pmat, | |||||
| NULL, NULL, NULL, NULL, | |||||
| snapdata.clip_plane[0], snapdata.clip_plane[1]); | |||||
| snapdata.clip_plane_len = 2; | |||||
| if (has_hit) { | |||||
| /* Compute the new clip_pane but do not add it yet. */ | |||||
| float new_clipplane[4]; | |||||
| plane_from_point_normal_v3(new_clipplane, loc, no); | |||||
| /* Try to snap only to the polygon. */ | |||||
| retval |= snapMeshPolygon( | |||||
| sctx, &snapdata, ob, obmat, | |||||
| dist_px, loc, no, r_index); | |||||
| /* Add the new clip plane to the beginning of the list. */ | |||||
| 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[0], new_clipplane); | |||||
| snapdata.clip_plane_len++; | |||||
| } | |||||
| return snapObjectsRay( | retval |= snapObjectsRay( | ||||
| sctx, &snapdata, params, | sctx, &snapdata, params, | ||||
| ray_depth, dist_px, r_loc, r_no, r_ob, r_obmat); | dist_px, loc, no, r_index, &ob, obmat); | ||||
| } | } | ||||
| if (retval) { | |||||
| copy_v3_v3(r_loc, loc); | |||||
| if (r_no) { | |||||
| copy_v3_v3(r_no, no); | |||||
| } | |||||
| if (r_ob) { | |||||
| *r_ob = ob; | |||||
| } | |||||
| if (r_obmat) { | |||||
| copy_m4_m4(r_obmat, obmat); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | } | ||||
| bool ED_transform_snap_object_project_view3d( | bool ED_transform_snap_object_project_view3d( | ||||
| SnapObjectContext *sctx, | SnapObjectContext *sctx, | ||||
| const unsigned short snap_to, | const unsigned short snap_to, | ||||
| const struct SnapObjectParams *params, | const struct SnapObjectParams *params, | ||||
| const float mval[2], float *dist_px, | const float mval[2], float *dist_px, | ||||
| float *ray_depth, | float *ray_depth, | ||||
| Show All 40 Lines | |||||
This seems like a high level check to add in low level raycast callback.