Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / transform / transform_snap_object.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/editors/transform/transform_snap_object.c
22  *  \ingroup edtransform
23  */
24
25 #include <stdlib.h>
26 #include <math.h>
27 #include <float.h>
28 #include <stdio.h>
29
30 #include "MEM_guardedalloc.h"
31
32 #include "BLI_math.h"
33 #include "BLI_kdopbvh.h"
34 #include "BLI_memarena.h"
35 #include "BLI_ghash.h"
36 #include "BLI_linklist.h"
37 #include "BLI_listbase.h"
38 #include "BLI_utildefines.h"
39
40 #include "DNA_armature_types.h"
41 #include "DNA_curve_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_object_types.h"
44 #include "DNA_meshdata_types.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_view3d_types.h"
47
48 #include "BKE_DerivedMesh.h"
49 #include "BKE_object.h"
50 #include "BKE_anim.h"  /* for duplis */
51 #include "BKE_editmesh.h"
52 #include "BKE_main.h"
53 #include "BKE_tracking.h"
54
55 #include "ED_transform.h"
56 #include "ED_transform_snap_object_context.h"
57 #include "ED_view3d.h"
58 #include "ED_armature.h"
59
60 #include "transform.h"
61
62 typedef struct SnapObjectData {
63         enum {
64                 SNAP_MESH = 1,
65                 SNAP_EDIT_MESH,
66         } type;
67 } SnapObjectData;
68
69 typedef struct SnapObjectData_Mesh {
70         SnapObjectData sd;
71         BVHTreeFromMesh *bvh_trees[3];
72
73 } SnapObjectData_Mesh;
74
75 typedef struct SnapObjectData_EditMesh {
76         SnapObjectData sd;
77         BVHTreeFromEditMesh *bvh_trees[3];
78
79 } SnapObjectData_EditMesh;
80
81 struct SnapObjectContext {
82         Main *bmain;
83         Scene *scene;
84         int flag;
85
86         /* Optional: when performing screen-space projection.
87          * otherwise this doesn't take viewport into account. */
88         bool use_v3d;
89         struct {
90                 const struct View3D *v3d;
91                 const struct ARegion *ar;
92         } v3d_data;
93
94
95         /* Object -> SnapObjectData map */
96         struct {
97                 GHash *object_map;
98                 MemArena *mem_arena;
99         } cache;
100
101         /* Filter data, returns true to check this value */
102         struct {
103                 struct {
104                         bool (*test_vert_fn)(BMVert *, void *user_data);
105                         bool (*test_edge_fn)(BMEdge *, void *user_data);
106                         bool (*test_face_fn)(BMFace *, void *user_data);
107                         void *user_data;
108                 } edit_mesh;
109         } callbacks;
110
111 };
112
113 static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt);
114
115
116 /* -------------------------------------------------------------------- */
117
118 /** \name Support for storing all depths, not just the first (raycast 'all')
119  *
120  * This uses a list of #SnapObjectHitDepth structs.
121  *
122  * \{ */
123
124 /* Store all ray-hits */
125 struct RayCastAll_Data {
126         void *bvhdata;
127
128         /* internal vars for adding depths */
129         BVHTree_RayCastCallback raycast_callback;
130
131         const float(*obmat)[4];
132         const float(*timat)[3];
133
134         float len_diff;
135         float local_scale;
136
137         Object *ob;
138         unsigned int ob_uuid;
139
140         /* DerivedMesh only */
141         DerivedMesh *dm;
142         const struct MLoopTri *dm_looptri;
143
144         /* output data */
145         ListBase *hit_list;
146         bool retval;
147 };
148
149 static struct SnapObjectHitDepth *hit_depth_create(
150         const float depth, const float co[3], const float no[3], int index,
151         Object *ob, const float obmat[4][4], unsigned int ob_uuid)
152 {
153         struct SnapObjectHitDepth *hit = MEM_mallocN(sizeof(*hit), __func__);
154
155         hit->depth = depth;
156         copy_v3_v3(hit->co, co);
157         copy_v3_v3(hit->no, no);
158         hit->index = index;
159
160         hit->ob = ob;
161         copy_m4_m4(hit->obmat, (float(*)[4])obmat);
162         hit->ob_uuid = ob_uuid;
163
164         return hit;
165 }
166
167 static int hit_depth_cmp(const void *arg1, const void *arg2)
168 {
169         const struct SnapObjectHitDepth *h1 = arg1;
170         const struct SnapObjectHitDepth *h2 = arg2;
171         int val = 0;
172
173         if (h1->depth < h2->depth) {
174                 val = -1;
175         }
176         else if (h1->depth > h2->depth) {
177                 val = 1;
178         }
179
180         return val;
181 }
182
183 static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
184 {
185         struct RayCastAll_Data *data = userdata;
186         data->raycast_callback(data->bvhdata, index, ray, hit);
187         if (hit->index != -1) {
188                 /* get all values in worldspace */
189                 float location[3], normal[3];
190                 float depth;
191
192                 /* worldspace location */
193                 mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co);
194                 depth = (hit->dist + data->len_diff) / data->local_scale;
195
196                 /* worldspace normal */
197                 copy_v3_v3(normal, hit->no);
198                 mul_m3_v3((float(*)[3])data->timat, normal);
199                 normalize_v3(normal);
200
201                 /* currently unused, and causes issues when looptri's haven't been calculated.
202                  * since theres some overhead in ensuring this data is valid, it may need to be optional. */
203 #if 0
204                 if (data->dm) {
205                         hit->index = dm_looptri_to_poly_index(data->dm, &data->dm_looptri[hit->index]);
206                 }
207 #endif
208
209                 struct SnapObjectHitDepth *hit_item = hit_depth_create(
210                         depth, location, normal, hit->index,
211                         data->ob, data->obmat, data->ob_uuid);
212                 BLI_addtail(data->hit_list, hit_item);
213         }
214 }
215
216 /** \} */
217
218
219 /* -------------------------------------------------------------------- */
220
221 /** \name Internal Object Snapping API
222  * \{ */
223
224 #define V3_MUL_ELEM(a, b) \
225         (a)[0] * (b)[0], \
226         (a)[1] * (b)[1], \
227         (a)[2] * (b)[2]
228
229 static bool test_vert(
230         const float vco[3], const float vno[3], const float ray_co[3], const float ray_dir[3],
231         const float ray_depth_range[2], const float scale[3], const bool is_persp,
232         /* read/write args */
233         float *ray_depth, float *dist_to_ray_sq,
234         /* return args */
235         float r_co[3], float r_no[3])
236 {
237         const float vco_sc[3]   = {V3_MUL_ELEM(vco, scale)};
238         const float co_sc[3]    = {V3_MUL_ELEM(ray_co, scale)};
239         const float dir_sc[3]   = {V3_MUL_ELEM(ray_dir, scale)};
240
241         float depth;
242         float dist_sq = dist_squared_to_ray_v3(co_sc, dir_sc, vco_sc, &depth);
243
244         if (depth < ray_depth_range[0]) {
245                 return false;
246         }
247
248         if (is_persp) {
249                 dist_sq /= SQUARE(depth);
250         }
251
252         if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) {
253                 *dist_to_ray_sq = dist_sq;
254
255                 copy_v3_v3(r_co, vco);
256
257                 if (vno) {
258                         copy_v3_v3(r_no, vno);
259                 }
260
261                 *ray_depth = depth;
262                 return true;
263         }
264         return false;
265 }
266
267 static bool test_edge(
268         const float v1[3], const float v2[3], const float ray_co[3], const float ray_dir[3],
269         const float ray_depth_range[2], const float scale[3], const bool is_persp,
270         /* read/write args */
271         float *ray_depth, float *dist_to_ray_sq,
272         /* return args */
273         float r_co[3], float r_no[3])
274 {
275         const float v1_sc[3]    = {V3_MUL_ELEM(v1, scale)};
276         const float v2_sc[3]    = {V3_MUL_ELEM(v2, scale)};
277         const float co_sc[3]    = {V3_MUL_ELEM(ray_co, scale)};
278         const float dir_sc[3]   = {V3_MUL_ELEM(ray_dir, scale)};
279
280         float tmp_co[3], depth;
281         float dist_sq = dist_squared_ray_to_seg_v3(co_sc, dir_sc, v1_sc, v2_sc, tmp_co, &depth);
282
283         if (depth < ray_depth_range[0]) {
284                 return false;
285         }
286
287         if (is_persp) {
288                 dist_sq /= SQUARE(depth);
289         }
290
291         if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) {
292                 *dist_to_ray_sq = dist_sq;
293
294                 tmp_co[0] /= scale[0];
295                 tmp_co[1] /= scale[1];
296                 tmp_co[2] /= scale[2];
297
298                 copy_v3_v3(r_co, tmp_co);
299
300                 if (r_no) {
301                         sub_v3_v3v3(r_no, v1, v2);
302                 }
303
304                 *ray_depth = depth;
305                 return true;
306         }
307         return false;
308 }
309
310 #undef V3_MUL_ELEM
311
312 static bool snapArmature(
313         Object *ob, bArmature *arm, float obmat[4][4],
314         const short snap_to, const bool is_persp,
315         const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2],
316         /* read/write args */
317         float *ray_depth, float *dist_to_ray_sq,
318         /* return args */
319         float r_loc[3], float *UNUSED(r_no))
320 {
321         float imat[4][4];
322         float ray_origin_local[3], ray_normal_local[3];
323         bool retval = false;
324
325         invert_m4_m4(imat, obmat);
326
327         mul_v3_m4v3(ray_origin_local, imat, ray_origin);
328         mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
329
330         float ob_scale[3];
331         mat4_to_size(ob_scale, obmat);
332
333         if (arm->edbo) {
334                 EditBone *eBone;
335
336                 for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
337                         if (eBone->layer & arm->layer) {
338                                 /* skip hidden or moving (selected) bones */
339                                 if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
340                                         switch (snap_to) {
341                                                 case SCE_SNAP_MODE_VERTEX:
342                                                         retval |= test_vert(
343                                                                 eBone->head, NULL, ray_origin_local, ray_normal_local,
344                                                                 ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
345                                                                 r_loc, NULL);
346                                                         retval |= test_vert(
347                                                                 eBone->tail, NULL, ray_origin_local, ray_normal_local,
348                                                                 ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
349                                                                 r_loc, NULL);
350                                                         break;
351                                                 case SCE_SNAP_MODE_EDGE:
352                                                         retval |= test_edge(
353                                                                 eBone->head, eBone->tail, ray_origin_local, ray_normal_local,
354                                                                 ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
355                                                                 r_loc, NULL);
356                                                         break;
357                                         }
358                                 }
359                         }
360                 }
361         }
362         else if (ob->pose && ob->pose->chanbase.first) {
363                 bPoseChannel *pchan;
364                 Bone *bone;
365
366                 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
367                         bone = pchan->bone;
368                         /* skip hidden bones */
369                         if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
370                                 const float *head_vec = pchan->pose_head;
371                                 const float *tail_vec = pchan->pose_tail;
372
373                                 switch (snap_to) {
374                                         case SCE_SNAP_MODE_VERTEX:
375                                                 retval |= test_vert(
376                                                         head_vec, NULL, ray_origin_local, ray_normal_local,
377                                                         ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
378                                                         r_loc, NULL);
379                                                 retval |= test_vert(
380                                                         tail_vec, NULL, ray_origin_local, ray_normal_local,
381                                                         ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
382                                                         r_loc, NULL);
383                                                 break;
384                                         case SCE_SNAP_MODE_EDGE:
385                                                 retval |= test_edge(
386                                                         head_vec, tail_vec, ray_origin_local, ray_normal_local,
387                                                         ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
388                                                         r_loc, NULL);
389                                                 break;
390                                 }
391                         }
392                 }
393         }
394         if (retval) {
395                 mul_m4_v3(obmat, r_loc);
396                 return true;
397         }
398         return false;
399 }
400
401 static bool snapCurve(
402         Object *ob, Curve *cu, float obmat[4][4],
403         const short snap_to, const bool is_persp,
404         const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2],
405         /* read/write args */
406         float *ray_depth, float *dist_to_ray_sq,
407         /* return args */
408         float r_loc[3], float *UNUSED(r_no))
409 {
410         float imat[4][4];
411         float ray_origin_local[3], ray_normal_local[3];
412         bool retval = false;
413         int u;
414
415         Nurb *nu;
416
417         /* only vertex snapping mode (eg control points and handles) supported for now) */
418         if (snap_to != SCE_SNAP_MODE_VERTEX) {
419                 return retval;
420         }
421
422         invert_m4_m4(imat, obmat);
423
424         copy_v3_v3(ray_origin_local, ray_origin);
425         copy_v3_v3(ray_normal_local, ray_normal);
426
427         mul_m4_v3(imat, ray_origin_local);
428         mul_mat3_m4_v3(imat, ray_normal_local);
429
430         float ob_scale[3];
431         mat4_to_size(ob_scale, obmat);
432
433         for (nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
434                 for (u = 0; u < nu->pntsu; u++) {
435                         switch (snap_to) {
436                                 case SCE_SNAP_MODE_VERTEX:
437                                 {
438                                         if (ob->mode == OB_MODE_EDIT) {
439                                                 if (nu->bezt) {
440                                                         /* don't snap to selected (moving) or hidden */
441                                                         if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
442                                                                 break;
443                                                         }
444                                                         retval |= test_vert(
445                                                                 nu->bezt[u].vec[1], NULL, ray_origin_local, ray_normal_local,
446                                                                 ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
447                                                                 r_loc, NULL);
448                                                         /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
449                                                         if (!(nu->bezt[u].f1 & SELECT) &&
450                                                             !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT))
451                                                         {
452                                                                 retval |= test_vert(
453                                                                         nu->bezt[u].vec[0], NULL, ray_origin_local, ray_normal_local,
454                                                                         ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
455                                                                         r_loc, NULL);
456                                                         }
457                                                         if (!(nu->bezt[u].f3 & SELECT) &&
458                                                             !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT))
459                                                         {
460                                                                 retval |= test_vert(
461                                                                         nu->bezt[u].vec[2], NULL, ray_origin_local, ray_normal_local,
462                                                                         ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
463                                                                         r_loc, NULL);
464                                                         }
465                                                 }
466                                                 else {
467                                                         /* don't snap to selected (moving) or hidden */
468                                                         if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
469                                                                 break;
470                                                         }
471                                                         retval |= test_vert(
472                                                                 nu->bp[u].vec, NULL, ray_origin_local, ray_normal_local,
473                                                                 ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
474                                                                 r_loc, NULL);
475                                                 }
476                                         }
477                                         else {
478                                                 /* curve is not visible outside editmode if nurb length less than two */
479                                                 if (nu->pntsu > 1) {
480                                                         if (nu->bezt) {
481                                                                 retval |= test_vert(
482                                                                         nu->bezt[u].vec[1], NULL, ray_origin_local, ray_normal_local,
483                                                                         ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
484                                                                         r_loc, NULL);
485                                                         }
486                                                         else {
487                                                                 retval |= test_vert(
488                                                                         nu->bp[u].vec, NULL, ray_origin_local, ray_normal_local,
489                                                                         ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
490                                                                         r_loc, NULL);
491                                                         }
492                                                 }
493                                         }
494                                         break;
495                                 }
496                                 default:
497                                         break;
498                         }
499                 }
500         }
501         if (retval) {
502                 mul_m4_v3(obmat, r_loc);
503                 return true;
504         }
505         return false;
506 }
507
508 /* may extend later (for now just snaps to empty center) */
509 static bool snapEmpty(
510         Object *ob, float obmat[4][4],
511         const short snap_to, const bool is_persp,
512         const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2],
513         /* read/write args */
514         float *ray_depth, float *dist_to_ray_sq,
515         /* return args */
516         float r_loc[3], float *UNUSED(r_no))
517 {
518         bool retval = false;
519
520         if (ob->transflag & OB_DUPLI) {
521                 return retval;
522         }
523         /* for now only vertex supported */
524         switch (snap_to) {
525                 case SCE_SNAP_MODE_VERTEX:
526                 {
527                         float ob_loc[3], ob_scale[3] = {1.0, 1.0, 1.0};
528                         copy_v3_v3(ob_loc, obmat[3]);
529
530                         retval |= test_vert(
531                                 ob_loc, NULL, ray_origin, ray_normal,
532                                 ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
533                                 r_loc, NULL);
534                         break;
535                 }
536                 default:
537                         break;
538         }
539
540         return retval;
541 }
542
543 static bool snapCamera(
544         Scene *scene, Object *object, float obmat[4][4],
545         const short snap_to, const bool is_persp,
546         const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2],
547         /* read/write args */
548         float *ray_depth, float *dist_to_ray_sq,
549         /* return args */
550         float r_loc[3], float *UNUSED(r_no))
551 {
552         float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
553         bool retval = false;
554         MovieClip *clip = BKE_object_movieclip_get(scene, object, false);
555         MovieTracking *tracking;
556         float ray_origin_local[3], ray_normal_local[3];
557
558         if (clip == NULL) {
559                 return retval;
560         }
561         if (object->transflag & OB_DUPLI) {
562                 return retval;
563         }
564
565         tracking = &clip->tracking;
566
567         BKE_tracking_get_camera_object_matrix(scene, object, orig_camera_mat);
568
569         invert_m4_m4(orig_camera_imat, orig_camera_mat);
570         invert_m4_m4(imat, obmat);
571
572         switch (snap_to) {
573                 case SCE_SNAP_MODE_VERTEX:
574                 {
575                         MovieTrackingObject *tracking_object;
576
577                         for (tracking_object = tracking->objects.first;
578                              tracking_object;
579                              tracking_object = tracking_object->next)
580                         {
581                                 ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
582                                 MovieTrackingTrack *track;
583                                 float reconstructed_camera_mat[4][4],
584                                       reconstructed_camera_imat[4][4];
585                                 float (*vertex_obmat)[4];
586
587                                 copy_v3_v3(ray_origin_local, ray_origin);
588                                 copy_v3_v3(ray_normal_local, ray_normal);
589
590                                 if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
591                                         BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object,
592                                                                                           CFRA, reconstructed_camera_mat);
593
594                                         invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat);
595                                 }
596
597                                 for (track = tracksbase->first; track; track = track->next) {
598                                         float bundle_pos[3];
599
600                                         if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
601                                                 continue;
602                                         }
603
604                                         copy_v3_v3(bundle_pos, track->bundle_pos);
605                                         if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
606                                                 mul_m4_v3(orig_camera_imat, ray_origin_local);
607                                                 mul_mat3_m4_v3(orig_camera_imat, ray_normal_local);
608                                                 vertex_obmat = orig_camera_mat;
609                                         }
610                                         else {
611                                                 mul_m4_v3(reconstructed_camera_imat, bundle_pos);
612                                                 mul_m4_v3(imat, ray_origin_local);
613                                                 mul_mat3_m4_v3(imat, ray_normal_local);
614                                                 vertex_obmat = obmat;
615                                         }
616
617                                         float ob_scale[3];
618                                         mat4_to_size(ob_scale, vertex_obmat);
619
620                                         retval |= test_vert(
621                                                 bundle_pos, NULL, ray_origin_local, ray_normal_local,
622                                                 ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
623                                                 r_loc, NULL);
624
625                                         mul_m4_v3(vertex_obmat, r_loc);
626                                 }
627                         }
628
629                         break;
630                 }
631                 default:
632                         break;
633         }
634
635         return retval;
636 }
637
638 static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
639 {
640         const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
641         return index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
642 }
643
644 struct NearestDM_Data {
645         void *bvhdata;
646         bool is_persp;
647         const float *ray_depth_range;
648
649         float *ray_depth;
650 };
651
652 static void test_vert_depth_cb(
653         void *userdata, const float origin[3], const float dir[3],
654         const float scale[3], int index, BVHTreeNearest *nearest)
655 {
656         struct NearestDM_Data *ndata = userdata;
657         const BVHTreeFromMesh *data = ndata->bvhdata;
658         const MVert *vert = data->vert + index;
659
660         if (test_vert(
661                 vert->co, NULL, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp,
662                 ndata->ray_depth, &nearest->dist_sq,
663                 nearest->co, NULL))
664         {
665                 normal_short_to_float_v3(nearest->no, vert->no);
666                 nearest->index = index;
667         }
668 }
669
670 static void test_edge_depth_cb(
671         void *userdata, const float origin[3], const float dir[3],
672         const float scale[3], int index, BVHTreeNearest *nearest)
673 {
674         struct NearestDM_Data *ndata = userdata;
675         const BVHTreeFromMesh *data = ndata->bvhdata;
676         const MVert *vert = data->vert;
677         const MEdge *edge = data->edge + index;
678
679         if (test_edge(
680                 vert[edge->v1].co, vert[edge->v2].co, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp,
681                 ndata->ray_depth, &nearest->dist_sq,
682                 nearest->co, nearest->no))
683         {
684                 nearest->index = index;
685         }
686 }
687
688 static bool snapDerivedMesh(
689         SnapObjectContext *sctx,
690         Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index,
691         const short snap_to, const bool is_persp, bool do_bb,
692         const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2],
693         /* read/write args */
694         float *ray_depth, float *dist_to_ray_sq,
695         /* return args */
696         float r_loc[3], float r_no[3], int *r_index,
697         ListBase *r_hit_list)
698 {
699         bool retval = false;
700
701         if (snap_to == SCE_SNAP_MODE_FACE) {
702                 if (dm->getNumPolys(dm) == 0) {
703                         return retval;
704                 }
705         }
706         if (snap_to == SCE_SNAP_MODE_EDGE) {
707                 if (dm->getNumEdges(dm) == 0) {
708                         return retval;
709                 }
710         }
711         else {
712                 if (dm->getNumVerts(dm) == 0) {
713                         return retval;
714                 }
715         }
716
717         {
718                 bool need_ray_start_correction_init = (snap_to == SCE_SNAP_MODE_FACE) && sctx->use_v3d && !is_persp;
719
720                 float imat[4][4];
721                 float timat[3][3]; /* transpose inverse matrix for normals */
722                 float ray_start_local[3], ray_normal_local[3];
723                 float local_scale, local_depth, len_diff;
724
725                 invert_m4_m4(imat, obmat);
726                 transpose_m3_m4(timat, imat);
727
728                 copy_v3_v3(ray_start_local, ray_start);
729                 copy_v3_v3(ray_normal_local, ray_normal);
730
731                 mul_m4_v3(imat, ray_start_local);
732                 mul_mat3_m4_v3(imat, ray_normal_local);
733
734                 /* local scale in normal direction */
735                 local_scale = normalize_v3(ray_normal_local);
736                 local_depth = *ray_depth;
737                 if (local_depth != BVH_RAYCAST_DIST_MAX) {
738                         local_depth *= local_scale;
739                 }
740
741                 if (do_bb) {
742                         BoundBox *bb = BKE_object_boundbox_get(ob);
743
744                         if (bb) {
745                                 BoundBox bb_temp;
746
747                                 /* We cannot afford a bounding box with some null dimension, which may happen in some cases...
748                                  * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
749                                 bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
750
751                                 /* Exact value here is arbitrary (ideally we would scale in pixel-space based on 'dist_px'),
752                                  * scale up so we can snap against verts & edges on the boundbox, see T46816. */
753                                 if (ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
754                                         BKE_boundbox_scale(&bb_temp, bb, 1.0f + 1e-1f);
755                                         bb = &bb_temp;
756                                 }
757
758                                 /* was local_depth, see: T47838 */
759                                 len_diff = BVH_RAYCAST_DIST_MAX;
760
761                                 if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) {
762                                         return retval;
763                                 }
764                                 need_ray_start_correction_init = false;
765                         }
766                 }
767
768                 SnapObjectData_Mesh *sod = NULL;
769                 BVHTreeFromMesh *treedata = NULL, treedata_stack;
770
771                 if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
772                         void **sod_p;
773                         if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
774                                 sod = *sod_p;
775                         }
776                         else {
777                                 sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
778                                 sod->sd.type = SNAP_MESH;
779                         }
780
781                         int tree_index = -1;
782                         switch (snap_to) {
783                                 case SCE_SNAP_MODE_FACE:
784                                         tree_index = 2;
785                                         break;
786                                 case SCE_SNAP_MODE_EDGE:
787                                         tree_index = 1;
788                                         break;
789                                 case SCE_SNAP_MODE_VERTEX:
790                                         tree_index = 0;
791                                         break;
792                         }
793                         if (tree_index != -1) {
794                                 if (sod->bvh_trees[tree_index] == NULL) {
795                                         sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
796                                 }
797                                 treedata = sod->bvh_trees[tree_index];
798
799                                 /* the tree is owned by the DM and may have been freed since we last used! */
800                                 if (treedata && treedata->tree) {
801                                         if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) {
802                                                 free_bvhtree_from_mesh(treedata);
803                                         }
804                                 }
805                         }
806                 }
807                 else {
808                         treedata = &treedata_stack;
809                         memset(treedata, 0, sizeof(*treedata));
810                 }
811
812                 if (treedata && treedata->tree == NULL) {
813                         switch (snap_to) {
814                                 case SCE_SNAP_MODE_FACE:
815                                         bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6);
816                                         break;
817                                 case SCE_SNAP_MODE_EDGE:
818                                         bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6);
819                                         break;
820                                 case SCE_SNAP_MODE_VERTEX:
821                                         bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6);
822                                         break;
823                         }
824                 }
825
826                 if (snap_to == SCE_SNAP_MODE_FACE) {
827                         /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
828                          * been *inside* boundbox, leading to snap failures (see T38409).
829                          * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
830                          */
831                         if (sctx->use_v3d && !is_persp) { /* do_ray_start_correction */
832                                 if (need_ray_start_correction_init) {
833                                         /* We *need* a reasonably valid len_diff in this case.
834                                          * Use BHVTree to find the closest face from ray_start_local.
835                                          */
836                                         if (treedata && treedata->tree != NULL) {
837                                                 BVHTreeNearest nearest;
838                                                 nearest.index = -1;
839                                                 nearest.dist_sq = FLT_MAX;
840                                                 /* Compute and store result. */
841                                                 BLI_bvhtree_find_nearest(
842                                                         treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata);
843                                                 if (nearest.index != -1) {
844                                                         float dvec[3];
845                                                         sub_v3_v3v3(dvec, nearest.co, ray_start_local);
846                                                         len_diff = dot_v3v3(dvec, ray_normal_local);
847                                                 }
848                                         }
849                                 }
850                                 float ray_org_local[3];
851
852                                 copy_v3_v3(ray_org_local, ray_origin);
853                                 mul_m4_v3(imat, ray_org_local);
854
855                                 /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with very far
856                                  * away ray_start values (as returned in case of ortho view3d), see T38358.
857                                  */
858                                 len_diff -= local_scale;  /* make temp start point a bit away from bbox hit point. */
859                                 madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local,
860                                             len_diff + ray_depth_range[0]);
861                                 local_depth -= len_diff;
862                         }
863                         else {
864                                 len_diff = 0.0f;
865                         }
866                         if (r_hit_list) {
867                                 struct RayCastAll_Data data;
868
869                                 data.bvhdata = treedata;
870                                 data.raycast_callback = treedata->raycast_callback;
871                                 data.obmat = obmat;
872                                 data.timat = timat;
873                                 data.len_diff = len_diff;
874                                 data.local_scale = local_scale;
875                                 data.ob = ob;
876                                 data.ob_uuid = ob_index;
877                                 data.dm = dm;
878                                 data.hit_list = r_hit_list;
879                                 data.retval = retval;
880
881                                 BLI_bvhtree_ray_cast_all(
882                                             treedata->tree, ray_start_local, ray_normal_local, 0.0f,
883                                             *ray_depth, raycast_all_cb, &data);
884
885                                 retval = data.retval;
886                         }
887                         else {
888                                 BVHTreeRayHit hit;
889
890                                 hit.index = -1;
891                                 hit.dist = local_depth;
892
893                                 if (treedata->tree &&
894                                     BLI_bvhtree_ray_cast(
895                                         treedata->tree, ray_start_local, ray_normal_local, 0.0f,
896                                         &hit, treedata->raycast_callback, treedata) != -1)
897                                 {
898                                         hit.dist += len_diff;
899                                         hit.dist /= local_scale;
900                                         if (hit.dist <= *ray_depth) {
901                                                 *ray_depth = hit.dist;
902                                                 copy_v3_v3(r_loc, hit.co);
903                                                 copy_v3_v3(r_no, hit.no);
904
905                                                 /* back to worldspace */
906                                                 mul_m4_v3(obmat, r_loc);
907                                                 mul_m3_v3(timat, r_no);
908                                                 normalize_v3(r_no);
909
910                                                 retval = true;
911
912                                                 if (r_index) {
913                                                         *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]);
914                                                 }
915                                         }
916                                 }
917                         }
918                 }
919                 else {
920                         /* Vert & edge use nearly identical logic. */
921                         BLI_assert(ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE));
922
923                         float ray_org_local[3];
924
925                         copy_v3_v3(ray_org_local, ray_origin);
926                         mul_m4_v3(imat, ray_org_local);
927
928                         BVHTreeNearest nearest;
929
930                         nearest.index = -1;
931                         nearest.dist_sq = *dist_to_ray_sq;
932
933                         struct NearestDM_Data userdata;
934                         userdata.bvhdata = treedata;
935                         userdata.is_persp = is_persp;
936                         userdata.ray_depth_range = ray_depth_range;
937                         userdata.ray_depth = ray_depth;
938
939                         float ob_scale[3];
940                         mat4_to_size(ob_scale, obmat);
941
942                         BVHTree_NearestToRayCallback callback =
943                                 (snap_to == SCE_SNAP_MODE_VERTEX) ?
944                                 test_vert_depth_cb : test_edge_depth_cb;
945
946                         if (treedata->tree &&
947                             (is_persp ?
948                              BLI_bvhtree_find_nearest_to_ray_angle(
949                                  treedata->tree, ray_org_local, ray_normal_local,
950                                  true, ob_scale, &nearest, callback, &userdata) :
951                              BLI_bvhtree_find_nearest_to_ray(
952                                  treedata->tree, ray_org_local, ray_normal_local,
953                                  true, ob_scale, &nearest, callback, &userdata)) != -1)
954                         {
955                                 copy_v3_v3(r_loc, nearest.co);
956                                 mul_m4_v3(obmat, r_loc);
957                                 if (r_no) {
958                                         copy_v3_v3(r_no, nearest.no);
959                                         mul_m3_v3(timat, r_no);
960                                         normalize_v3(r_no);
961                                 }
962                                 *dist_to_ray_sq = nearest.dist_sq;
963
964                                 retval = true;
965                         }
966                 }
967
968                 if ((sctx->flag & SNAP_OBJECT_USE_CACHE) == 0) {
969                         if (treedata) {
970                                 free_bvhtree_from_mesh(treedata);
971                         }
972                 }
973         }
974
975         return retval;
976 }
977
978 static void test_bmvert_depth_cb(
979         void *userdata, const float origin[3], const float dir[3],
980         const float scale[3], int index, BVHTreeNearest *nearest)
981 {
982         struct NearestDM_Data *ndata = userdata;
983         const BMEditMesh *em = ndata->bvhdata;
984         BMVert *eve = BM_vert_at_index(em->bm, index);
985
986         if (test_vert(
987                 eve->co, eve->no, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp,
988                 ndata->ray_depth, &nearest->dist_sq,
989                 nearest->co, nearest->no))
990         {
991                 nearest->index = index;
992         }
993 }
994
995 static void test_bmedge_depth_cb(
996         void *userdata, const float origin[3], const float dir[3],
997         const float scale[3], int index, BVHTreeNearest *nearest)
998 {
999         struct NearestDM_Data *ndata = userdata;
1000         const BMEditMesh *em = ndata->bvhdata;
1001         BMEdge *eed = BM_edge_at_index(em->bm, index);
1002
1003         if (test_edge(
1004                 eed->v1->co, eed->v2->co, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp,
1005                 ndata->ray_depth, &nearest->dist_sq,
1006                 nearest->co, nearest->no))
1007         {
1008                 nearest->index = index;
1009         }
1010 }
1011
1012 static bool snapEditMesh(
1013         SnapObjectContext *sctx,
1014         Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index,
1015         const short snap_to, const bool is_persp,
1016         const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2],
1017         /* read/write args */
1018         float *ray_depth, float *dist_to_ray_sq,
1019         /* return args */
1020         float r_loc[3], float r_no[3], int *r_index,
1021         ListBase *r_hit_list)
1022 {
1023         bool retval = false;
1024
1025         if (snap_to == SCE_SNAP_MODE_FACE) {
1026                 if (em->bm->totface == 0) {
1027                         return retval;
1028                 }
1029         }
1030         if (snap_to == SCE_SNAP_MODE_EDGE) {
1031                 if (em->bm->totedge == 0) {
1032                         return retval;
1033                 }
1034         }
1035         else {
1036                 if (em->bm->totvert == 0) {
1037                         return retval;
1038                 }
1039         }
1040
1041         {
1042                 float imat[4][4];
1043                 float timat[3][3]; /* transpose inverse matrix for normals */
1044                 float ray_normal_local[3];
1045
1046                 invert_m4_m4(imat, obmat);
1047                 transpose_m3_m4(timat, imat);
1048
1049                 copy_v3_v3(ray_normal_local, ray_normal);
1050
1051                 mul_mat3_m4_v3(imat, ray_normal_local);
1052
1053                 SnapObjectData_EditMesh *sod = NULL;
1054
1055                 BVHTreeFromEditMesh *treedata = NULL, treedata_stack;
1056
1057                 if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
1058                         void **sod_p;
1059                         if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
1060                                 sod = *sod_p;
1061                         }
1062                         else {
1063                                 sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
1064                                 sod->sd.type = SNAP_EDIT_MESH;
1065                         }
1066
1067                         int tree_index = -1;
1068                         switch (snap_to) {
1069                                 case SCE_SNAP_MODE_FACE:
1070                                         tree_index = 2;
1071                                         break;
1072                                 case SCE_SNAP_MODE_EDGE:
1073                                         tree_index = 1;
1074                                         break;
1075                                 case SCE_SNAP_MODE_VERTEX:
1076                                         tree_index = 0;
1077                                         break;
1078                         }
1079                         if (tree_index != -1) {
1080                                 if (sod->bvh_trees[tree_index] == NULL) {
1081                                         sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
1082                                 }
1083                                 treedata = sod->bvh_trees[tree_index];
1084                         }
1085                 }
1086                 else {
1087                         treedata = &treedata_stack;
1088                         memset(treedata, 0, sizeof(*treedata));
1089                 }
1090
1091                 if (treedata && treedata->tree == NULL) {
1092                         switch (snap_to) {
1093                                 case SCE_SNAP_MODE_FACE:
1094                                 {
1095                                         BLI_bitmap *looptri_mask = NULL;
1096                                         int looptri_num_active = -1;
1097                                         if (sctx->callbacks.edit_mesh.test_face_fn) {
1098                                                 looptri_mask = BLI_BITMAP_NEW(em->tottri, __func__);
1099                                                 looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
1100                                                         em->bm, looptri_mask,
1101                                                         sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data);
1102                                         }
1103                                         bvhtree_from_editmesh_looptri_ex(treedata, em, looptri_mask, looptri_num_active, 0.0f, 4, 6, NULL);
1104                                         if (looptri_mask) {
1105                                                 MEM_freeN(looptri_mask);
1106                                         }
1107                                         break;
1108                                 }
1109                                 case SCE_SNAP_MODE_EDGE:
1110                                 {
1111                                         BLI_bitmap *edges_mask = NULL;
1112                                         int edges_num_active = -1;
1113                                         if (sctx->callbacks.edit_mesh.test_edge_fn) {
1114                                                 edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
1115                                                 edges_num_active = BM_iter_mesh_bitmap_from_filter(
1116                                                         BM_EDGES_OF_MESH, em->bm, edges_mask,
1117                                                         (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
1118                                                         sctx->callbacks.edit_mesh.user_data);
1119                                         }
1120                                         bvhtree_from_editmesh_edges_ex(treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6);
1121                                         if (edges_mask) {
1122                                                 MEM_freeN(edges_mask);
1123                                         }
1124                                         break;
1125                                 }
1126                                 case SCE_SNAP_MODE_VERTEX:
1127                                 {
1128                                         BLI_bitmap *verts_mask = NULL;
1129                                         int verts_num_active = -1;
1130                                         if (sctx->callbacks.edit_mesh.test_vert_fn) {
1131                                                 verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
1132                                                 verts_num_active = BM_iter_mesh_bitmap_from_filter(
1133                                                         BM_VERTS_OF_MESH, em->bm, verts_mask,
1134                                                         (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
1135                                                         sctx->callbacks.edit_mesh.user_data);
1136                                         }
1137                                         bvhtree_from_editmesh_verts_ex(treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6);
1138                                         if (verts_mask) {
1139                                                 MEM_freeN(verts_mask);
1140                                         }
1141                                         break;
1142                                 }
1143                         }
1144                 }
1145
1146                 if (snap_to == SCE_SNAP_MODE_FACE) {
1147                         float ray_start_local[3];
1148                         copy_v3_v3(ray_start_local, ray_start);
1149                         mul_m4_v3(imat, ray_start_local);
1150
1151                         /* local scale in normal direction */
1152                         float local_scale = normalize_v3(ray_normal_local);
1153                         float local_depth = *ray_depth;
1154                         if (local_depth != BVH_RAYCAST_DIST_MAX) {
1155                                 local_depth *= local_scale;
1156                         }
1157
1158                         /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
1159                          * been *inside* boundbox, leading to snap failures (see T38409).
1160                          * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
1161                          */
1162                         float len_diff = 0.0f;
1163                         if (sctx->use_v3d && !is_persp) { /* do_ray_start_correction */
1164                                 /* We *need* a reasonably valid len_diff in this case.
1165                                  * Use BHVTree to find the closest face from ray_start_local.
1166                                  */
1167                                 if (treedata && treedata->tree != NULL) {
1168                                         BVHTreeNearest nearest;
1169                                         nearest.index = -1;
1170                                         nearest.dist_sq = FLT_MAX;
1171                                         /* Compute and store result. */
1172                                         if (BLI_bvhtree_find_nearest(
1173                                                 treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1)
1174                                         {
1175                                                 float dvec[3];
1176                                                 sub_v3_v3v3(dvec, nearest.co, ray_start_local);
1177                                                 len_diff = dot_v3v3(dvec, ray_normal_local);
1178                                                 float ray_org_local[3];
1179
1180                                                 copy_v3_v3(ray_org_local, ray_origin);
1181                                                 mul_m4_v3(imat, ray_org_local);
1182
1183                                                 /* We pass a temp ray_start, set from object's boundbox,
1184                                                  * to avoid precision issues with very far away ray_start values
1185                                                  * (as returned in case of ortho view3d), see T38358.
1186                                                  */
1187                                                 len_diff -= local_scale;  /* make temp start point a bit away from bbox hit point. */
1188                                                 madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local,
1189                                                                len_diff + ray_depth_range[0]);
1190                                                 local_depth -= len_diff;
1191                                         }
1192                                 }
1193                         }
1194                         if (r_hit_list) {
1195                                 struct RayCastAll_Data data;
1196
1197                                 data.bvhdata = treedata;
1198                                 data.raycast_callback = treedata->raycast_callback;
1199                                 data.obmat = obmat;
1200                                 data.timat = timat;
1201                                 data.len_diff = len_diff;
1202                                 data.local_scale = local_scale;
1203                                 data.ob = ob;
1204                                 data.ob_uuid = ob_index;
1205                                 data.dm = NULL;
1206                                 data.hit_list = r_hit_list;
1207                                 data.retval = retval;
1208
1209                                 BLI_bvhtree_ray_cast_all(
1210                                         treedata->tree, ray_start_local, ray_normal_local, 0.0f,
1211                                         *ray_depth, raycast_all_cb, &data);
1212
1213                                 retval = data.retval;
1214                         }
1215                         else {
1216                                 BVHTreeRayHit hit;
1217
1218                                 hit.index = -1;
1219                                 hit.dist = local_depth;
1220
1221                                 if (treedata->tree &&
1222                                     BLI_bvhtree_ray_cast(
1223                                         treedata->tree, ray_start_local, ray_normal_local, 0.0f,
1224                                         &hit, treedata->raycast_callback, treedata) != -1)
1225                                 {
1226                                         hit.dist += len_diff;
1227                                         hit.dist /= local_scale;
1228                                         if (hit.dist <= *ray_depth) {
1229                                                 *ray_depth = hit.dist;
1230                                                 copy_v3_v3(r_loc, hit.co);
1231                                                 copy_v3_v3(r_no, hit.no);
1232
1233                                                 /* back to worldspace */
1234                                                 mul_m4_v3(obmat, r_loc);
1235                                                 mul_m3_v3(timat, r_no);
1236                                                 normalize_v3(r_no);
1237
1238                                                 retval = true;
1239
1240                                                 if (r_index) {
1241                                                         *r_index = hit.index;
1242                                                 }
1243                                         }
1244                                 }
1245                         }
1246                 }
1247                 else {
1248                         /* Vert & edge use nearly identical logic. */
1249                         BLI_assert(ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE));
1250
1251                         float ray_org_local[3];
1252
1253                         copy_v3_v3(ray_org_local, ray_origin);
1254                         mul_m4_v3(imat, ray_org_local);
1255
1256                         BVHTreeNearest nearest;
1257
1258                         nearest.index = -1;
1259                         nearest.dist_sq = *dist_to_ray_sq;
1260
1261                         struct NearestDM_Data userdata;
1262                         userdata.bvhdata = em;
1263                         userdata.is_persp = is_persp;
1264                         userdata.ray_depth_range = ray_depth_range;
1265                         userdata.ray_depth = ray_depth;
1266
1267                         float ob_scale[3];
1268                         mat4_to_size(ob_scale, obmat);
1269
1270                         BVHTree_NearestToRayCallback callback =
1271                                 (snap_to == SCE_SNAP_MODE_VERTEX) ?
1272                                 test_bmvert_depth_cb : test_bmedge_depth_cb;
1273
1274                         if (treedata->tree &&
1275                             (is_persp ?
1276                              BLI_bvhtree_find_nearest_to_ray_angle(
1277                                  treedata->tree, ray_org_local, ray_normal_local,
1278                                  false, ob_scale, &nearest, callback, &userdata) :
1279                              BLI_bvhtree_find_nearest_to_ray(
1280                                  treedata->tree, ray_org_local, ray_normal_local,
1281                                  false, ob_scale, &nearest, callback, &userdata)) != -1)
1282                         {
1283                                 copy_v3_v3(r_loc, nearest.co);
1284                                 mul_m4_v3(obmat, r_loc);
1285                                 if (r_no) {
1286                                         copy_v3_v3(r_no, nearest.no);
1287                                         mul_m3_v3(timat, r_no);
1288                                         normalize_v3(r_no);
1289                                 }
1290                                 *dist_to_ray_sq = nearest.dist_sq;
1291
1292                                 retval = true;
1293                         }
1294                 }
1295
1296                 if ((sctx->flag & SNAP_OBJECT_USE_CACHE) == 0) {
1297                         if (treedata) {
1298                                 free_bvhtree_from_editmesh(treedata);
1299                         }
1300                 }
1301         }
1302
1303         return retval;
1304 }
1305
1306 /**
1307  * \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping;
1308  * \param ray_depth_range:
1309  * - 0: distance from the ray_origin to the clipping plane min (can be negative).
1310  * - 1: maximum distance, elements outside this are ignored.
1311  * \param ray_depth: maximum depth allowed for r_co.
1312  *
1313  * \note Duplicate args here are documented at #snapObjectsRay
1314  */
1315 static bool snapObject(
1316         SnapObjectContext *sctx,
1317         Object *ob, float obmat[4][4], const unsigned int ob_index,
1318         bool use_obedit, const short snap_to,
1319         const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2],
1320         /* read/write args */
1321         float *ray_depth, float *dist_to_ray_sq,
1322         /* return args */
1323         float r_loc[3], float r_no[3], int *r_index,
1324         Object **r_ob, float r_obmat[4][4],
1325         ListBase *r_hit_list)
1326 {
1327         const bool is_persp = sctx->use_v3d && ((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp;
1328         bool retval = false;
1329
1330         if (ob->type == OB_MESH) {
1331                 BMEditMesh *em;
1332
1333                 if (use_obedit) {
1334                         em = BKE_editmesh_from_object(ob);
1335                         retval = snapEditMesh(
1336                                 sctx, ob, em, obmat, ob_index,
1337                                 snap_to, is_persp,
1338                                 ray_origin, ray_start, ray_normal, ray_depth_range,
1339                                 ray_depth, dist_to_ray_sq,
1340                                 r_loc, r_no, r_index,
1341                                 r_hit_list);
1342                 }
1343                 else {
1344                         /* in this case we want the mesh from the editmesh, avoids stale data. see: T45978.
1345                          * still set the 'em' to NULL, since we only want the 'dm'. */
1346                         DerivedMesh *dm;
1347                         em = BKE_editmesh_from_object(ob);
1348                         if (em) {
1349                                 editbmesh_get_derived_cage_and_final(sctx->scene, ob, em, CD_MASK_BAREMESH, &dm);
1350                         }
1351                         else {
1352                                 dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH);
1353                         }
1354                         retval = snapDerivedMesh(
1355                                 sctx, ob, dm, obmat, ob_index,
1356                                 snap_to, is_persp, true,
1357                                 ray_origin, ray_start, ray_normal, ray_depth_range,
1358                                 ray_depth, dist_to_ray_sq,
1359                                 r_loc, r_no,
1360                                 r_index, r_hit_list);
1361
1362                         dm->release(dm);
1363                 }
1364         }
1365         else if (ob->type == OB_ARMATURE) {
1366                 retval = snapArmature(
1367                         ob, ob->data, obmat, snap_to, is_persp,
1368                         ray_origin, ray_normal, ray_depth_range,
1369                         ray_depth, dist_to_ray_sq,
1370                         r_loc, r_no);
1371         }
1372         else if (ob->type == OB_CURVE) {
1373                 retval = snapCurve(
1374                         ob, ob->data, obmat, snap_to, is_persp,
1375                         ray_origin, ray_normal, ray_depth_range,
1376                         ray_depth, dist_to_ray_sq,
1377                         r_loc, r_no);
1378         }
1379         else if (ob->type == OB_EMPTY) {
1380                 retval = snapEmpty(
1381                         ob, obmat, snap_to, is_persp,
1382                         ray_origin, ray_normal, ray_depth_range,
1383                         ray_depth, dist_to_ray_sq,
1384                         r_loc, r_no);
1385         }
1386         else if (ob->type == OB_CAMERA) {
1387                 retval = snapCamera(
1388                         sctx->scene, ob, obmat, snap_to, is_persp,
1389                         ray_origin, ray_normal, ray_depth_range,
1390                         ray_depth, dist_to_ray_sq,
1391                         r_loc, r_no);
1392         }
1393
1394         if (retval) {
1395                 if (r_ob) {
1396                         *r_ob = ob;
1397                         copy_m4_m4(r_obmat, obmat);
1398                 }
1399         }
1400
1401         return retval;
1402 }
1403
1404 /**
1405  * Main Snapping Function
1406  * ======================
1407  *
1408  * Walks through all objects in the scene to find the closest snap element ray.
1409  *
1410  * \param sctx: Snap context to store data.
1411  * \param snap_to: Element to snap, Vertice, Edge or Face.
1412  * Currently only works one at a time, but can eventually operate as flag.
1413  *
1414  * \param snap_select: from enum SnapSelect.
1415  *
1416  * \param use_object_edit_cage: Uses the coordinates of BMesh (if any) to do the snapping.
1417  * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min.
1418  * \param ray_start: ray_origin moved for the start clipping plane (clip_min).
1419  * \param ray_normal: Unit length direction of the ray.
1420  *
1421  * Read/Write Args
1422  * ---------------
1423  *
1424  * \param ray_depth: maximum depth allowed for r_co, elements deeper than this value will be ignored.
1425  * \param dist_to_ray_sq: Real distance (3D) or Tangent (view cone radius at distance 1.0) squared.
1426  * resulting of the function #dist_px_to_dist3d_or_tangent.
1427  *
1428  * Output Args
1429  * -----------
1430  *
1431  * \param r_loc: Hit location.
1432  * \param r_no: Hit normal (optional).
1433  * \param r_index: Hit index or -1 when no valid index is found.
1434  * (currently only set to the polygon index when when using ``snap_to == SCE_SNAP_MODE_FACE``).
1435  * \param r_ob: Hit object.
1436  * \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
1437  * \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
1438  *
1439  */
1440 static bool snapObjectsRay(
1441         SnapObjectContext *sctx,
1442         const unsigned short snap_to, const SnapSelect snap_select,
1443         const bool use_object_edit_cage,
1444         const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
1445         /* read/write args */
1446         float *ray_depth, float *dist_to_ray_sq,
1447         /* return args */
1448         float r_loc[3], float r_no[3], int *r_index,
1449         Object **r_ob, float r_obmat[4][4],
1450         ListBase *r_hit_list)
1451 {
1452         bool retval = false;
1453
1454         float dvec[3];
1455         sub_v3_v3v3(dvec, ray_start, ray_origin);
1456
1457         const float ray_depth_range[2] = {
1458                 dot_v3v3(dvec, ray_normal),
1459                 *ray_depth,
1460         };
1461
1462         unsigned int ob_index = 0;
1463         Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL;
1464         Base *base_act = sctx->scene->basact;
1465
1466         bool ignore_object_selected = false, ignore_object_active = false;
1467         switch (snap_select) {
1468                 case SNAP_ALL:
1469                         break;
1470                 case SNAP_NOT_SELECTED:
1471                         ignore_object_selected = true;
1472                         break;
1473                 case SNAP_NOT_ACTIVE:
1474                         ignore_object_active = true;
1475                         break;
1476         }
1477         for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) {
1478                 if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) &&
1479                     (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 &&
1480
1481                     !((ignore_object_selected && (base->flag & (SELECT | BA_WAS_SEL))) ||
1482                       (ignore_object_active && base == base_act)))
1483                 {
1484                         Object *ob = base->object;
1485
1486                         if (ob->transflag & OB_DUPLI) {
1487                                 DupliObject *dupli_ob;
1488                                 ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, ob);
1489
1490                                 for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
1491                                         bool use_obedit_dupli = (obedit && dupli_ob->ob->data == obedit->data);
1492                                         Object *dupli_snap = (use_obedit_dupli) ? obedit : dupli_ob->ob;
1493
1494                                         retval |= snapObject(
1495                                                 sctx, dupli_snap, dupli_ob->mat, ob_index++,
1496                                                 use_obedit_dupli, snap_to,
1497                                                 ray_origin, ray_start, ray_normal, ray_depth_range,
1498                                                 ray_depth, dist_to_ray_sq,
1499                                                 r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
1500                                 }
1501
1502                                 free_object_duplilist(lb);
1503                         }
1504
1505                         bool use_obedit = (obedit != NULL) && (ob->data == obedit->data);
1506                         Object *ob_snap = use_obedit ? obedit : ob;
1507
1508                         retval |= snapObject(
1509                                 sctx, ob_snap, ob->obmat, ob_index++,
1510                                 use_obedit, snap_to,
1511                                 ray_origin, ray_start, ray_normal, ray_depth_range,
1512                                 ray_depth, dist_to_ray_sq,
1513                                 r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
1514                 }
1515         }
1516
1517         return retval;
1518 }
1519
1520 /** \} */
1521
1522
1523 /* -------------------------------------------------------------------- */
1524
1525 /** \name Public Object Snapping API
1526  * \{ */
1527
1528 SnapObjectContext *ED_transform_snap_object_context_create(
1529         Main *bmain, Scene *scene, int flag)
1530 {
1531         SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
1532
1533         sctx->flag = flag;
1534
1535         sctx->bmain = bmain;
1536         sctx->scene = scene;
1537
1538         return sctx;
1539 }
1540
1541 SnapObjectContext *ED_transform_snap_object_context_create_view3d(
1542         Main *bmain, Scene *scene, int flag,
1543         /* extra args for view3d */
1544         const ARegion *ar, const View3D *v3d)
1545 {
1546         SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, flag);
1547
1548         sctx->use_v3d = true;
1549         sctx->v3d_data.ar = ar;
1550         sctx->v3d_data.v3d = v3d;
1551
1552         if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
1553                 sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
1554                 sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
1555         }
1556
1557         return sctx;
1558 }
1559
1560 static void snap_object_data_free(void *sod_v)
1561 {
1562         switch (((SnapObjectData *)sod_v)->type) {
1563                 case SNAP_MESH:
1564                 {
1565                         SnapObjectData_Mesh *sod = sod_v;
1566                         for (int i = 0; i < ARRAY_SIZE(sod->bvh_trees); i++) {
1567                                 if (sod->bvh_trees[i]) {
1568                                         free_bvhtree_from_mesh(sod->bvh_trees[i]);
1569                                 }
1570                         }
1571                         break;
1572                 }
1573                 case SNAP_EDIT_MESH:
1574                 {
1575                         SnapObjectData_EditMesh *sod = sod_v;
1576                         for (int i = 0; i < ARRAY_SIZE(sod->bvh_trees); i++) {
1577                                 if (sod->bvh_trees[i]) {
1578                                         free_bvhtree_from_editmesh(sod->bvh_trees[i]);
1579                                 }
1580                         }
1581                         break;
1582                 }
1583         }
1584 }
1585
1586 void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
1587 {
1588         if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
1589                 BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free);
1590                 BLI_memarena_free(sctx->cache.mem_arena);
1591         }
1592
1593         MEM_freeN(sctx);
1594 }
1595
1596 void ED_transform_snap_object_context_set_editmesh_callbacks(
1597         SnapObjectContext *sctx,
1598         bool (*test_vert_fn)(BMVert *, void *user_data),
1599         bool (*test_edge_fn)(BMEdge *, void *user_data),
1600         bool (*test_face_fn)(BMFace *, void *user_data),
1601         void *user_data)
1602 {
1603         sctx->callbacks.edit_mesh.test_vert_fn = test_vert_fn;
1604         sctx->callbacks.edit_mesh.test_edge_fn = test_edge_fn;
1605         sctx->callbacks.edit_mesh.test_face_fn = test_face_fn;
1606
1607         sctx->callbacks.edit_mesh.user_data = user_data;
1608 }
1609
1610 bool ED_transform_snap_object_project_ray_ex(
1611         SnapObjectContext *sctx,
1612         const unsigned short snap_to,
1613         const struct SnapObjectParams *params,
1614         const float ray_start[3], const float ray_normal[3],
1615         float *ray_depth,
1616         float r_loc[3], float r_no[3], int *r_index,
1617         Object **r_ob, float r_obmat[4][4])
1618 {
1619         float dist_to_ray_sq = 0.0f;
1620
1621         return snapObjectsRay(
1622                 sctx,
1623                 snap_to, params->snap_select, params->use_object_edit_cage,
1624                 ray_start, ray_start, ray_normal,
1625                 ray_depth, &dist_to_ray_sq,
1626                 r_loc, r_no, r_index, r_ob, r_obmat, NULL);
1627 }
1628
1629 /**
1630  * Fill in a list of all hits.
1631  *
1632  * \param ray_depth: Only depths in this range are considered, -1.0 for maximum.
1633  * \param sort: Optionally sort the hits by depth.
1634  * \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
1635  */
1636 bool ED_transform_snap_object_project_ray_all(
1637         SnapObjectContext *sctx,
1638         const unsigned short snap_to,
1639         const struct SnapObjectParams *params,
1640         const float ray_start[3], const float ray_normal[3],
1641         float ray_depth, bool sort,
1642         ListBase *r_hit_list)
1643 {
1644         float dist_to_ray_sq = 0.0f;
1645
1646         if (ray_depth == -1.0f) {
1647                 ray_depth = BVH_RAYCAST_DIST_MAX;
1648         }
1649
1650 #ifdef DEBUG
1651         float ray_depth_prev = ray_depth;
1652 #endif
1653
1654         bool retval = snapObjectsRay(
1655                 sctx,
1656                 snap_to, params->snap_select, params->use_object_edit_cage,
1657                 ray_start, ray_start, ray_normal,
1658                 &ray_depth, &dist_to_ray_sq,
1659                 NULL, NULL, NULL, NULL, NULL,
1660                 r_hit_list);
1661
1662         /* meant to be readonly for 'all' hits, ensure it is */
1663 #ifdef DEBUG
1664         BLI_assert(ray_depth_prev == ray_depth);
1665 #endif
1666
1667         if (sort) {
1668                 BLI_listbase_sort(r_hit_list, hit_depth_cmp);
1669         }
1670
1671         return retval;
1672 }
1673
1674 /**
1675  * Convenience function for snap ray-casting.
1676  *
1677  * Given a ray, cast it into the scene (snapping to faces).
1678  *
1679  * \return Snap success
1680  */
1681 static bool transform_snap_context_project_ray_impl(
1682         SnapObjectContext *sctx,
1683         const struct SnapObjectParams *params,
1684         const float ray_start[3], const float ray_normal[3], float *ray_depth,
1685         float r_co[3], float r_no[3])
1686 {
1687         bool ret;
1688
1689         /* try snap edge, then face if it fails */
1690         ret = ED_transform_snap_object_project_ray_ex(
1691                 sctx,
1692                 SCE_SNAP_MODE_FACE,
1693                 params,
1694                 ray_start, ray_normal, ray_depth,
1695                 r_co, r_no, NULL,
1696                 NULL, NULL);
1697
1698         return ret;
1699 }
1700
1701 bool ED_transform_snap_object_project_ray(
1702         SnapObjectContext *sctx,
1703         const struct SnapObjectParams *params,
1704         const float ray_origin[3], const float ray_direction[3], float *ray_depth,
1705         float r_co[3], float r_no[3])
1706 {
1707         float ray_depth_fallback;
1708         if (ray_depth == NULL) {
1709                 ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
1710                 ray_depth = &ray_depth_fallback;
1711         }
1712
1713         float no_fallback[3];
1714         if (r_no == NULL) {
1715                 r_no = no_fallback;
1716         }
1717
1718         return transform_snap_context_project_ray_impl(
1719                 sctx,
1720                 params,
1721                 ray_origin, ray_direction, ray_depth,
1722                 r_co, r_no);
1723 }
1724
1725 static bool transform_snap_context_project_view3d_mixed_impl(
1726         SnapObjectContext *sctx,
1727         const unsigned short snap_to_flag,
1728         const struct SnapObjectParams *params,
1729         const float mval[2], float *dist_px,
1730         bool use_depth,
1731         float r_co[3], float r_no[3])
1732 {
1733         float ray_depth = BVH_RAYCAST_DIST_MAX;
1734         bool is_hit = false;
1735
1736         float r_no_dummy[3];
1737         if (r_no == NULL) {
1738                 r_no = r_no_dummy;
1739         }
1740
1741         const int  elem_type[3] = {SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE, SCE_SNAP_MODE_FACE};
1742
1743         BLI_assert(snap_to_flag != 0);
1744         BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0);
1745
1746         for (int i = 0; i < 3; i++) {
1747                 if ((snap_to_flag & (1 << i)) && (is_hit == false || use_depth)) {
1748                         if (use_depth == false) {
1749                                 ray_depth = BVH_RAYCAST_DIST_MAX;
1750                         }
1751
1752                         if (ED_transform_snap_object_project_view3d(
1753                                 sctx,
1754                                 elem_type[i], params,
1755                                 mval, dist_px, &ray_depth,
1756                                 r_co, r_no))
1757                         {
1758                                 is_hit = true;
1759                         }
1760                 }
1761         }
1762
1763         return is_hit;
1764 }
1765
1766 /**
1767  * From a threshold (maximum distance to snap in pixels) returns:
1768  *
1769  * - The *real* distance (3D) if you are in orthographic-view.
1770  * - The *tangent* (view cone radius at distance 1.0) if you are in perspective-view.
1771  */
1772 static float dist_px_to_dist3d_or_tangent(const ARegion *ar, const float dist_px)
1773 {
1774         const RegionView3D *rv3d = ar->regiondata;
1775         if (ar->winx >= ar->winy)
1776                 return 2 * (dist_px / ar->winx) / rv3d->winmat[0][0];
1777         else
1778                 return 2 * (dist_px / ar->winy) / rv3d->winmat[1][1];
1779 }
1780
1781 /**
1782  * Convenience function for performing snapping.
1783  *
1784  * Given a 2D region value, snap to vert/edge/face.
1785  *
1786  * \param sctx: Snap context.
1787  * \param mval_fl: Screenspace coordinate.
1788  * \param dist_px: Maximum distance to snap (in pixels).
1789  * \param use_depth: Snap to the closest element, use when using more than one snap type.
1790  * \param r_co: hit location.
1791  * \param r_no: hit normal (optional).
1792  * \return Snap success
1793  */
1794 bool ED_transform_snap_object_project_view3d_mixed(
1795         SnapObjectContext *sctx,
1796         const unsigned short snap_to_flag,
1797         const struct SnapObjectParams *params,
1798         const float mval_fl[2], float *dist_px,
1799         bool use_depth,
1800         float r_co[3], float r_no[3])
1801 {
1802         return transform_snap_context_project_view3d_mixed_impl(
1803                 sctx,
1804                 snap_to_flag, params,
1805                 mval_fl, dist_px, use_depth,
1806                 r_co, r_no);
1807 }
1808
1809 bool ED_transform_snap_object_project_view3d_ex(
1810         SnapObjectContext *sctx,
1811         const unsigned short snap_to,
1812         const struct SnapObjectParams *params,
1813         const float mval[2], float *dist_px,
1814         float *ray_depth,
1815         float r_loc[3], float r_no[3], int *r_index)
1816 {
1817         float ray_start[3], ray_normal[3], ray_origin[3];
1818
1819         float ray_depth_fallback;
1820         if (ray_depth == NULL) {
1821                 ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
1822                 ray_depth = &ray_depth_fallback;
1823         }
1824
1825         if (!ED_view3d_win_to_ray_ex(
1826                 sctx->v3d_data.ar, sctx->v3d_data.v3d,
1827                 mval, ray_origin, ray_normal, ray_start, true))
1828         {
1829                 return false;
1830         }
1831
1832         float radius, dist_to_ray_sq = 0.0f;
1833         if (dist_px) {
1834                 radius = dist_px_to_dist3d_or_tangent(sctx->v3d_data.ar, *dist_px);
1835                 /**
1836                  * Workaround to use of cone (Instead of project the radius on view plane):
1837                  * In perspective view, the radius of the cone may decrease depending on the ray direction.
1838                  * This is more evident with small values of the `Viewport lens angle`.
1839                  * The threshold becomes distorted that way.
1840                  */
1841                 RegionView3D *rv3d = sctx->v3d_data.ar->regiondata;
1842                 if (rv3d->is_persp) {
1843                         float view_dir[3];
1844                         negate_v3_v3(view_dir, rv3d->viewinv[2]);
1845                         normalize_v3(view_dir);
1846                         radius *= dot_v3v3(ray_normal, view_dir);
1847                 }
1848
1849                 dist_to_ray_sq = SQUARE(radius);
1850         }
1851
1852         if (snapObjectsRay(
1853                 sctx,
1854                 snap_to, params->snap_select, params->use_object_edit_cage,
1855                 ray_origin, ray_start, ray_normal,
1856                 ray_depth, &dist_to_ray_sq,
1857                 r_loc, r_no, r_index, NULL, NULL, NULL))
1858         {
1859                 if (dist_px) {
1860                         *dist_px *= sqrtf(dist_to_ray_sq) / radius;
1861                 }
1862                 return true;
1863         }
1864
1865         return false;
1866 }
1867
1868 bool ED_transform_snap_object_project_view3d(
1869         SnapObjectContext *sctx,
1870         const unsigned short snap_to,
1871         const struct SnapObjectParams *params,
1872         const float mval[2], float *dist_px,
1873         float *ray_depth,
1874         float r_loc[3], float r_no[3])
1875 {
1876         return ED_transform_snap_object_project_view3d_ex(
1877                 sctx,
1878                 snap_to,
1879                 params,
1880                 mval, dist_px,
1881                 ray_depth,
1882                 r_loc, r_no, NULL);
1883 }
1884
1885 /**
1886  * see: #ED_transform_snap_object_project_ray_all
1887  */
1888 bool ED_transform_snap_object_project_all_view3d_ex(
1889         SnapObjectContext *sctx,
1890         const struct SnapObjectParams *params,
1891         const float mval[2],
1892         float ray_depth, bool sort,
1893         ListBase *r_hit_list)
1894 {
1895         float ray_start[3], ray_normal[3];
1896
1897         if (!ED_view3d_win_to_ray_ex(
1898                 sctx->v3d_data.ar, sctx->v3d_data.v3d,
1899                 mval, NULL, ray_normal, ray_start, true))
1900         {
1901                 return false;
1902         }
1903
1904         return ED_transform_snap_object_project_ray_all(
1905                 sctx,
1906                 SCE_SNAP_MODE_FACE,
1907                 params,
1908                 ray_start, ray_normal, ray_depth, sort,
1909                 r_hit_list);
1910 }
1911
1912 /** \} */