Cleanup: use normalize_v#_length
[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
1465         /* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA
1466          * which makes the loop skip it, even the derived mesh will never change
1467          *
1468          * To solve that problem, we do it first as an exception.
1469          * */
1470         Base *base_act = sctx->scene->basact;
1471         if (base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT) {
1472                 Object *ob = base_act->object;
1473
1474                 retval |= snapObject(
1475                         sctx, ob, ob->obmat, ob_index++,
1476                         false, snap_to,
1477                         ray_origin, ray_start, ray_normal, ray_depth_range,
1478                         ray_depth, dist_to_ray_sq,
1479                         r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
1480         }
1481
1482         bool ignore_object_selected = false, ignore_object_active = false;
1483         switch (snap_select) {
1484                 case SNAP_ALL:
1485                         break;
1486                 case SNAP_NOT_SELECTED:
1487                         ignore_object_selected = true;
1488                         break;
1489                 case SNAP_NOT_ACTIVE:
1490                         ignore_object_active = true;
1491                         break;
1492         }
1493         for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) {
1494                 if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) &&
1495                     (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 &&
1496
1497                     !((ignore_object_selected && (base->flag & (SELECT | BA_WAS_SEL))) ||
1498                       (ignore_object_active && base == base_act)))
1499                 {
1500                         Object *ob = base->object;
1501
1502                         if (ob->transflag & OB_DUPLI) {
1503                                 DupliObject *dupli_ob;
1504                                 ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, ob);
1505
1506                                 for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
1507                                         bool use_obedit_dupli = (obedit && dupli_ob->ob->data == obedit->data);
1508                                         Object *dupli_snap = (use_obedit_dupli) ? obedit : dupli_ob->ob;
1509
1510                                         retval |= snapObject(
1511                                                 sctx, dupli_snap, dupli_ob->mat, ob_index++,
1512                                                 use_obedit_dupli, snap_to,
1513                                                 ray_origin, ray_start, ray_normal, ray_depth_range,
1514                                                 ray_depth, dist_to_ray_sq,
1515                                                 r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
1516                                 }
1517
1518                                 free_object_duplilist(lb);
1519                         }
1520
1521                         bool use_obedit = (obedit != NULL) && (ob->data == obedit->data);
1522                         Object *ob_snap = use_obedit ? obedit : ob;
1523
1524                         retval |= snapObject(
1525                                 sctx, ob_snap, ob->obmat, ob_index++,
1526                                 use_obedit, snap_to,
1527                                 ray_origin, ray_start, ray_normal, ray_depth_range,
1528                                 ray_depth, dist_to_ray_sq,
1529                                 r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
1530                 }
1531         }
1532
1533         return retval;
1534 }
1535
1536 /** \} */
1537
1538
1539 /* -------------------------------------------------------------------- */
1540
1541 /** \name Public Object Snapping API
1542  * \{ */
1543
1544 SnapObjectContext *ED_transform_snap_object_context_create(
1545         Main *bmain, Scene *scene, int flag)
1546 {
1547         SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
1548
1549         sctx->flag = flag;
1550
1551         sctx->bmain = bmain;
1552         sctx->scene = scene;
1553
1554         return sctx;
1555 }
1556
1557 SnapObjectContext *ED_transform_snap_object_context_create_view3d(
1558         Main *bmain, Scene *scene, int flag,
1559         /* extra args for view3d */
1560         const ARegion *ar, const View3D *v3d)
1561 {
1562         SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, flag);
1563
1564         sctx->use_v3d = true;
1565         sctx->v3d_data.ar = ar;
1566         sctx->v3d_data.v3d = v3d;
1567
1568         if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
1569                 sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
1570                 sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
1571         }
1572
1573         return sctx;
1574 }
1575
1576 static void snap_object_data_free(void *sod_v)
1577 {
1578         switch (((SnapObjectData *)sod_v)->type) {
1579                 case SNAP_MESH:
1580                 {
1581                         SnapObjectData_Mesh *sod = sod_v;
1582                         for (int i = 0; i < ARRAY_SIZE(sod->bvh_trees); i++) {
1583                                 if (sod->bvh_trees[i]) {
1584                                         free_bvhtree_from_mesh(sod->bvh_trees[i]);
1585                                 }
1586                         }
1587                         break;
1588                 }
1589                 case SNAP_EDIT_MESH:
1590                 {
1591                         SnapObjectData_EditMesh *sod = sod_v;
1592                         for (int i = 0; i < ARRAY_SIZE(sod->bvh_trees); i++) {
1593                                 if (sod->bvh_trees[i]) {
1594                                         free_bvhtree_from_editmesh(sod->bvh_trees[i]);
1595                                 }
1596                         }
1597                         break;
1598                 }
1599         }
1600 }
1601
1602 void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
1603 {
1604         if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
1605                 BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free);
1606                 BLI_memarena_free(sctx->cache.mem_arena);
1607         }
1608
1609         MEM_freeN(sctx);
1610 }
1611
1612 void ED_transform_snap_object_context_set_editmesh_callbacks(
1613         SnapObjectContext *sctx,
1614         bool (*test_vert_fn)(BMVert *, void *user_data),
1615         bool (*test_edge_fn)(BMEdge *, void *user_data),
1616         bool (*test_face_fn)(BMFace *, void *user_data),
1617         void *user_data)
1618 {
1619         sctx->callbacks.edit_mesh.test_vert_fn = test_vert_fn;
1620         sctx->callbacks.edit_mesh.test_edge_fn = test_edge_fn;
1621         sctx->callbacks.edit_mesh.test_face_fn = test_face_fn;
1622
1623         sctx->callbacks.edit_mesh.user_data = user_data;
1624 }
1625
1626 bool ED_transform_snap_object_project_ray_ex(
1627         SnapObjectContext *sctx,
1628         const unsigned short snap_to,
1629         const struct SnapObjectParams *params,
1630         const float ray_start[3], const float ray_normal[3],
1631         float *ray_depth,
1632         float r_loc[3], float r_no[3], int *r_index,
1633         Object **r_ob, float r_obmat[4][4])
1634 {
1635         float dist_to_ray_sq = 0.0f;
1636
1637         return snapObjectsRay(
1638                 sctx,
1639                 snap_to, params->snap_select, params->use_object_edit_cage,
1640                 ray_start, ray_start, ray_normal,
1641                 ray_depth, &dist_to_ray_sq,
1642                 r_loc, r_no, r_index, r_ob, r_obmat, NULL);
1643 }
1644
1645 /**
1646  * Fill in a list of all hits.
1647  *
1648  * \param ray_depth: Only depths in this range are considered, -1.0 for maximum.
1649  * \param sort: Optionally sort the hits by depth.
1650  * \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
1651  */
1652 bool ED_transform_snap_object_project_ray_all(
1653         SnapObjectContext *sctx,
1654         const unsigned short snap_to,
1655         const struct SnapObjectParams *params,
1656         const float ray_start[3], const float ray_normal[3],
1657         float ray_depth, bool sort,
1658         ListBase *r_hit_list)
1659 {
1660         float dist_to_ray_sq = 0.0f;
1661
1662         if (ray_depth == -1.0f) {
1663                 ray_depth = BVH_RAYCAST_DIST_MAX;
1664         }
1665
1666 #ifdef DEBUG
1667         float ray_depth_prev = ray_depth;
1668 #endif
1669
1670         bool retval = snapObjectsRay(
1671                 sctx,
1672                 snap_to, params->snap_select, params->use_object_edit_cage,
1673                 ray_start, ray_start, ray_normal,
1674                 &ray_depth, &dist_to_ray_sq,
1675                 NULL, NULL, NULL, NULL, NULL,
1676                 r_hit_list);
1677
1678         /* meant to be readonly for 'all' hits, ensure it is */
1679 #ifdef DEBUG
1680         BLI_assert(ray_depth_prev == ray_depth);
1681 #endif
1682
1683         if (sort) {
1684                 BLI_listbase_sort(r_hit_list, hit_depth_cmp);
1685         }
1686
1687         return retval;
1688 }
1689
1690 /**
1691  * Convenience function for snap ray-casting.
1692  *
1693  * Given a ray, cast it into the scene (snapping to faces).
1694  *
1695  * \return Snap success
1696  */
1697 static bool transform_snap_context_project_ray_impl(
1698         SnapObjectContext *sctx,
1699         const struct SnapObjectParams *params,
1700         const float ray_start[3], const float ray_normal[3], float *ray_depth,
1701         float r_co[3], float r_no[3])
1702 {
1703         bool ret;
1704
1705         /* try snap edge, then face if it fails */
1706         ret = ED_transform_snap_object_project_ray_ex(
1707                 sctx,
1708                 SCE_SNAP_MODE_FACE,
1709                 params,
1710                 ray_start, ray_normal, ray_depth,
1711                 r_co, r_no, NULL,
1712                 NULL, NULL);
1713
1714         return ret;
1715 }
1716
1717 bool ED_transform_snap_object_project_ray(
1718         SnapObjectContext *sctx,
1719         const struct SnapObjectParams *params,
1720         const float ray_origin[3], const float ray_direction[3], float *ray_depth,
1721         float r_co[3], float r_no[3])
1722 {
1723         float ray_depth_fallback;
1724         if (ray_depth == NULL) {
1725                 ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
1726                 ray_depth = &ray_depth_fallback;
1727         }
1728
1729         float no_fallback[3];
1730         if (r_no == NULL) {
1731                 r_no = no_fallback;
1732         }
1733
1734         return transform_snap_context_project_ray_impl(
1735                 sctx,
1736                 params,
1737                 ray_origin, ray_direction, ray_depth,
1738                 r_co, r_no);
1739 }
1740
1741 static bool transform_snap_context_project_view3d_mixed_impl(
1742         SnapObjectContext *sctx,
1743         const unsigned short snap_to_flag,
1744         const struct SnapObjectParams *params,
1745         const float mval[2], float *dist_px,
1746         bool use_depth,
1747         float r_co[3], float r_no[3])
1748 {
1749         float ray_depth = BVH_RAYCAST_DIST_MAX;
1750         bool is_hit = false;
1751
1752         float r_no_dummy[3];
1753         if (r_no == NULL) {
1754                 r_no = r_no_dummy;
1755         }
1756
1757         const int  elem_type[3] = {SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE, SCE_SNAP_MODE_FACE};
1758
1759         BLI_assert(snap_to_flag != 0);
1760         BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0);
1761
1762         for (int i = 0; i < 3; i++) {
1763                 if ((snap_to_flag & (1 << i)) && (is_hit == false || use_depth)) {
1764                         if (use_depth == false) {
1765                                 ray_depth = BVH_RAYCAST_DIST_MAX;
1766                         }
1767
1768                         if (ED_transform_snap_object_project_view3d(
1769                                 sctx,
1770                                 elem_type[i], params,
1771                                 mval, dist_px, &ray_depth,
1772                                 r_co, r_no))
1773                         {
1774                                 is_hit = true;
1775                         }
1776                 }
1777         }
1778
1779         return is_hit;
1780 }
1781
1782 /**
1783  * From a threshold (maximum distance to snap in pixels) returns:
1784  *
1785  * - The *real* distance (3D) if you are in orthographic-view.
1786  * - The *tangent* (view cone radius at distance 1.0) if you are in perspective-view.
1787  */
1788 static float dist_px_to_dist3d_or_tangent(const ARegion *ar, const float dist_px)
1789 {
1790         const RegionView3D *rv3d = ar->regiondata;
1791         if (ar->winx >= ar->winy)
1792                 return 2 * (dist_px / ar->winx) / rv3d->winmat[0][0];
1793         else
1794                 return 2 * (dist_px / ar->winy) / rv3d->winmat[1][1];
1795 }
1796
1797 /**
1798  * Convenience function for performing snapping.
1799  *
1800  * Given a 2D region value, snap to vert/edge/face.
1801  *
1802  * \param sctx: Snap context.
1803  * \param mval_fl: Screenspace coordinate.
1804  * \param dist_px: Maximum distance to snap (in pixels).
1805  * \param use_depth: Snap to the closest element, use when using more than one snap type.
1806  * \param r_co: hit location.
1807  * \param r_no: hit normal (optional).
1808  * \return Snap success
1809  */
1810 bool ED_transform_snap_object_project_view3d_mixed(
1811         SnapObjectContext *sctx,
1812         const unsigned short snap_to_flag,
1813         const struct SnapObjectParams *params,
1814         const float mval_fl[2], float *dist_px,
1815         bool use_depth,
1816         float r_co[3], float r_no[3])
1817 {
1818         return transform_snap_context_project_view3d_mixed_impl(
1819                 sctx,
1820                 snap_to_flag, params,
1821                 mval_fl, dist_px, use_depth,
1822                 r_co, r_no);
1823 }
1824
1825 bool ED_transform_snap_object_project_view3d_ex(
1826         SnapObjectContext *sctx,
1827         const unsigned short snap_to,
1828         const struct SnapObjectParams *params,
1829         const float mval[2], float *dist_px,
1830         float *ray_depth,
1831         float r_loc[3], float r_no[3], int *r_index)
1832 {
1833         float ray_start[3], ray_normal[3], ray_origin[3];
1834
1835         float ray_depth_fallback;
1836         if (ray_depth == NULL) {
1837                 ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
1838                 ray_depth = &ray_depth_fallback;
1839         }
1840
1841         if (!ED_view3d_win_to_ray_ex(
1842                 sctx->v3d_data.ar, sctx->v3d_data.v3d,
1843                 mval, ray_origin, ray_normal, ray_start, true))
1844         {
1845                 return false;
1846         }
1847
1848         float radius, dist_to_ray_sq = 0.0f;
1849         if (dist_px) {
1850                 radius = dist_px_to_dist3d_or_tangent(sctx->v3d_data.ar, *dist_px);
1851                 /**
1852                  * Workaround to use of cone (Instead of project the radius on view plane):
1853                  * In perspective view, the radius of the cone may decrease depending on the ray direction.
1854                  * This is more evident with small values of the `Viewport lens angle`.
1855                  * The threshold becomes distorted that way.
1856                  */
1857                 RegionView3D *rv3d = sctx->v3d_data.ar->regiondata;
1858                 if (rv3d->is_persp) {
1859                         float view_dir[3];
1860                         negate_v3_v3(view_dir, rv3d->viewinv[2]);
1861                         normalize_v3(view_dir);
1862                         radius *= dot_v3v3(ray_normal, view_dir);
1863                 }
1864
1865                 dist_to_ray_sq = SQUARE(radius);
1866         }
1867
1868         if (snapObjectsRay(
1869                 sctx,
1870                 snap_to, params->snap_select, params->use_object_edit_cage,
1871                 ray_origin, ray_start, ray_normal,
1872                 ray_depth, &dist_to_ray_sq,
1873                 r_loc, r_no, r_index, NULL, NULL, NULL))
1874         {
1875                 if (dist_px) {
1876                         *dist_px *= sqrtf(dist_to_ray_sq) / radius;
1877                 }
1878                 return true;
1879         }
1880
1881         return false;
1882 }
1883
1884 bool ED_transform_snap_object_project_view3d(
1885         SnapObjectContext *sctx,
1886         const unsigned short snap_to,
1887         const struct SnapObjectParams *params,
1888         const float mval[2], float *dist_px,
1889         float *ray_depth,
1890         float r_loc[3], float r_no[3])
1891 {
1892         return ED_transform_snap_object_project_view3d_ex(
1893                 sctx,
1894                 snap_to,
1895                 params,
1896                 mval, dist_px,
1897                 ray_depth,
1898                 r_loc, r_no, NULL);
1899 }
1900
1901 /**
1902  * see: #ED_transform_snap_object_project_ray_all
1903  */
1904 bool ED_transform_snap_object_project_all_view3d_ex(
1905         SnapObjectContext *sctx,
1906         const struct SnapObjectParams *params,
1907         const float mval[2],
1908         float ray_depth, bool sort,
1909         ListBase *r_hit_list)
1910 {
1911         float ray_start[3], ray_normal[3];
1912
1913         if (!ED_view3d_win_to_ray_ex(
1914                 sctx->v3d_data.ar, sctx->v3d_data.v3d,
1915                 mval, NULL, ray_normal, ray_start, true))
1916         {
1917                 return false;
1918         }
1919
1920         return ED_transform_snap_object_project_ray_all(
1921                 sctx,
1922                 SCE_SNAP_MODE_FACE,
1923                 params,
1924                 ray_start, ray_normal, ray_depth, sort,
1925                 r_hit_list);
1926 }
1927
1928 /** \} */