Blender  V3.3
transform_snap_object.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <cstdlib>
8 
9 #include "MEM_guardedalloc.h"
10 
11 #include "BLI_float4x4.hh"
12 #include "BLI_kdopbvh.h"
13 #include "BLI_listbase.h"
14 #include "BLI_map.hh"
15 #include "BLI_math.h"
16 #include "BLI_math_vector.hh"
17 #include "BLI_utildefines.h"
18 
19 #include "DNA_armature_types.h"
20 #include "DNA_curve_types.h"
21 #include "DNA_mesh_types.h"
22 #include "DNA_meshdata_types.h"
23 #include "DNA_object_types.h"
24 #include "DNA_scene_types.h"
25 #include "DNA_screen_types.h"
26 #include "DNA_view3d_types.h"
27 
28 #include "BKE_armature.h"
29 #include "BKE_bvhutils.h"
30 #include "BKE_curve.h"
31 #include "BKE_duplilist.h"
32 #include "BKE_editmesh.h"
33 #include "BKE_geometry_set.h"
34 #include "BKE_global.h"
35 #include "BKE_layer.h"
36 #include "BKE_mesh.h"
37 #include "BKE_mesh_runtime.h"
38 #include "BKE_object.h"
39 #include "BKE_tracking.h"
40 
41 #include "DEG_depsgraph_query.h"
42 
43 #include "ED_armature.h"
45 #include "ED_view3d.h"
46 
47 using blender::float3;
48 using blender::float4x4;
49 using blender::Map;
50 
51 /* -------------------------------------------------------------------- */
55 #define MAX_CLIPPLANE_LEN 3
56 
57 enum eViewProj {
61 };
62 
63 /* SnapObjectContext.cache.mesh_map */
64 struct SnapData_Mesh {
65  /* Loose edges, loose verts. */
67  bool cached[2];
68 
69  /* Looptris. */
71 
72  const MPoly *poly;
76 
77  void clear()
78  {
79  for (int i = 0; i < ARRAY_SIZE(this->bvhtree); i++) {
80  if (!this->cached[i]) {
81  BLI_bvhtree_free(this->bvhtree[i]);
82  }
83  this->bvhtree[i] = nullptr;
84  }
85  free_bvhtree_from_mesh(&this->treedata_mesh);
86  }
87 
89  {
90  this->clear();
91  }
92 
93 #ifdef WITH_CXX_GUARDEDALLOC
94  MEM_CXX_CLASS_ALLOC_FUNCS("SnapData_Mesh")
95 #endif
96 };
97 
98 /* SnapObjectContext.cache.editmesh_map */
100  /* Verts, Edges. */
102  bool cached[2];
103 
104  /* Looptris. */
106 
108  float min[3], max[3];
109 
110  void clear()
111  {
112  for (int i = 0; i < ARRAY_SIZE(this->bvhtree); i++) {
113  if (!this->cached[i]) {
114  BLI_bvhtree_free(this->bvhtree[i]);
115  }
116  this->bvhtree[i] = nullptr;
117  }
118  free_bvhtree_from_editmesh(&this->treedata_editmesh);
119  }
120 
122  {
123  this->clear();
124  }
125 
126 #ifdef WITH_CXX_GUARDEDALLOC
127  MEM_CXX_CLASS_ALLOC_FUNCS("SnapData_EditMesh")
128 #endif
129 };
130 
133 
134  int flag;
135 
138 
139  /* Filter data, returns true to check this value */
140  struct {
141  struct {
145  void *user_data;
148 
149  struct {
151  const ARegion *region;
152  const View3D *v3d;
153 
154  float mval[2];
155  float pmat[4][4]; /* perspective matrix */
156  float win_size[2]; /* win x and y */
157  enum eViewProj view_proj;
161  bool has_occlusion_plane; /* Ignore plane of occlusion in curves. */
163 };
164 
167 /* -------------------------------------------------------------------- */
178 static const Mesh *mesh_for_snap(Object *ob_eval, eSnapEditType edit_mode_type, bool *r_use_hide)
179 {
180  const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
181  bool use_hide = false;
182  if (BKE_object_is_in_editmode(ob_eval)) {
183  if (edit_mode_type == SNAP_GEOM_EDIT) {
184  return nullptr;
185  }
186 
187  const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob_eval);
188  const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval);
189 
190  if ((edit_mode_type == SNAP_GEOM_FINAL) && editmesh_eval_final) {
191  if (editmesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
192  return nullptr;
193  }
194  me_eval = editmesh_eval_final;
195  use_hide = true;
196  }
197  else if ((edit_mode_type == SNAP_GEOM_CAGE) && editmesh_eval_cage) {
198  if (editmesh_eval_cage->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
199  return nullptr;
200  }
201  me_eval = editmesh_eval_cage;
202  use_hide = true;
203  }
204  }
205  if (r_use_hide) {
206  *r_use_hide = use_hide;
207  }
208  return me_eval;
209 }
210 
213 /* -------------------------------------------------------------------- */
221  BMesh *bm,
222  float r_min[3],
223  float r_max[3])
224 {
225  INIT_MINMAX(r_min, r_max);
226  BMIter iter;
227  BMVert *v;
228 
229  BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
230  if (sctx->callbacks.edit_mesh.test_vert_fn &&
231  !sctx->callbacks.edit_mesh.test_vert_fn(v, sctx->callbacks.edit_mesh.user_data)) {
232  continue;
233  }
234  minmax_v3v3_v3(r_min, r_max, v->co);
235  }
236 }
237 
239  Object *ob_eval,
240  const Mesh *me_eval,
241  bool use_hide)
242 {
243  SnapData_Mesh *sod;
244  bool init = false;
245 
246  if (std::unique_ptr<SnapData_Mesh> *sod_p = sctx->mesh_caches.lookup_ptr(ob_eval)) {
247  sod = sod_p->get();
248  bool is_dirty = false;
249  if (sod->treedata_mesh.tree && sod->treedata_mesh.cached &&
251  /* The tree is owned by the Mesh and may have been freed since we last used. */
252  is_dirty = true;
253  }
254  else if (sod->bvhtree[0] && sod->cached[0] &&
255  !bvhcache_has_tree(me_eval->runtime.bvh_cache, sod->bvhtree[0])) {
256  /* The tree is owned by the Mesh and may have been freed since we last used. */
257  is_dirty = true;
258  }
259  else if (sod->bvhtree[1] && sod->cached[1] &&
260  !bvhcache_has_tree(me_eval->runtime.bvh_cache, sod->bvhtree[1])) {
261  /* The tree is owned by the Mesh and may have been freed since we last used. */
262  is_dirty = true;
263  }
264  else if (sod->treedata_mesh.looptri != me_eval->runtime.looptris.array) {
265  is_dirty = true;
266  }
267  else if (sod->treedata_mesh.vert != me_eval->mvert) {
268  is_dirty = true;
269  }
270  else if (sod->treedata_mesh.loop != me_eval->mloop) {
271  is_dirty = true;
272  }
273  else if (sod->treedata_mesh.edge != me_eval->medge) {
274  is_dirty = true;
275  }
276  else if (sod->poly != me_eval->mpoly) {
277  is_dirty = true;
278  }
279 
280  if (is_dirty) {
281  sod->clear();
282  init = true;
283  }
284  }
285  else {
286  if (ob_eval->type == OB_MESH) {
287  /* Any existing #SnapData_EditMesh is now invalid. */
289  }
290 
291  std::unique_ptr<SnapData_Mesh> sod_ptr = std::make_unique<SnapData_Mesh>();
292  sod = sod_ptr.get();
293  sctx->mesh_caches.add_new(ob_eval, std::move(sod_ptr));
294 
295  init = true;
296  }
297 
298  if (init) {
299  /* The BVHTree from looptris is always required. */
300  BLI_assert(sod->treedata_mesh.tree == nullptr);
302  me_eval,
304  4);
305 
306  BLI_assert(sod->treedata_mesh.vert == me_eval->mvert);
307  BLI_assert(!me_eval->mvert || sod->treedata_mesh.vert_normals);
308  BLI_assert(sod->treedata_mesh.loop == me_eval->mloop);
309  BLI_assert(!me_eval->mpoly || sod->treedata_mesh.looptri);
310 
311  sod->has_looptris = sod->treedata_mesh.tree != nullptr;
312 
313  /* Required for snapping with occlusion. */
314  sod->treedata_mesh.edge = me_eval->medge;
315  sod->poly = me_eval->mpoly;
316 
317  /* Start assuming that it has each of these element types. */
318  sod->has_loose_edge = true;
319  sod->has_loose_vert = true;
320  }
321 
322  return sod;
323 }
324 
325 /* Searches for the #Mesh_Runtime associated with the object that is most likely to be updated due
326  * to changes in the `edit_mesh`. */
328 {
329  Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob_eval);
330  if (editmesh_eval_final) {
331  return &editmesh_eval_final->runtime;
332  }
333 
334  Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval);
335  if (editmesh_eval_cage) {
336  return &editmesh_eval_cage->runtime;
337  }
338 
339  return &((Mesh *)ob_eval->data)->runtime;
340 }
341 
343  Object *ob_eval,
344  BMEditMesh *em)
345 {
346  SnapData_EditMesh *sod;
347  bool init = false;
348 
349  /* Any existing #SnapData_Mesh is now invalid. */
350  sctx->mesh_caches.remove(ob_eval);
351 
352  if (std::unique_ptr<SnapData_EditMesh> *sod_p = sctx->editmesh_caches.lookup_ptr(em)) {
353  sod = sod_p->get();
354  bool is_dirty = false;
355  /* Check if the geometry has changed. */
356  if (sod->treedata_editmesh.em != em) {
357  is_dirty = true;
358  }
359  else if (sod->mesh_runtime) {
361  if (G.moving) {
362  /* Hack to avoid updating while transforming. */
363  BLI_assert(!sod->treedata_editmesh.cached && !sod->cached[0] && !sod->cached[1]);
365  }
366  else {
367  is_dirty = true;
368  }
369  }
370  else if (sod->treedata_editmesh.tree && sod->treedata_editmesh.cached &&
372  /* The tree is owned by the EditMesh and may have been freed since we last used! */
373  is_dirty = true;
374  }
375  else if (sod->bvhtree[0] && sod->cached[0] &&
376  !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->bvhtree[0])) {
377  /* The tree is owned by the EditMesh and may have been freed since we last used! */
378  is_dirty = true;
379  }
380  else if (sod->bvhtree[1] && sod->cached[1] &&
381  !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->bvhtree[1])) {
382  /* The tree is owned by the EditMesh and may have been freed since we last used! */
383  is_dirty = true;
384  }
385  }
386 
387  if (is_dirty) {
388  sod->clear();
389  init = true;
390  }
391  }
392  else {
393  std::unique_ptr<SnapData_EditMesh> sod_ptr = std::make_unique<SnapData_EditMesh>();
394  sod = sod_ptr.get();
395  sctx->editmesh_caches.add_new(em, std::move(sod_ptr));
396  init = true;
397  }
398 
399  if (init) {
400  sod->treedata_editmesh.em = em;
402  snap_editmesh_minmax(sctx, em->bm, sod->min, sod->max);
403  }
404 
405  return sod;
406 }
407 
409  Object *ob_eval,
410  const Mesh *me_eval,
411  bool use_hide)
412 {
413  SnapData_Mesh *sod = snap_object_data_mesh_get(sctx, ob_eval, me_eval, use_hide);
414  return &sod->treedata_mesh;
415 }
416 
418  Object *ob_eval,
419  BMEditMesh *em)
420 {
421  SnapData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob_eval, em);
422 
423  BVHTreeFromEditMesh *treedata = &sod->treedata_editmesh;
424 
425  if (treedata->tree == nullptr) {
426  /* Operators only update the editmesh looptris of the original mesh. */
429  em = sod->treedata_editmesh.em;
430 
431  if (sctx->callbacks.edit_mesh.test_face_fn) {
432  BMesh *bm = em->bm;
434 
435  BLI_bitmap *elem_mask = BLI_BITMAP_NEW(em->tottri, __func__);
436  int looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
437  bm,
438  elem_mask,
439  sctx->callbacks.edit_mesh.test_face_fn,
440  sctx->callbacks.edit_mesh.user_data);
441 
442  bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6);
443 
444  MEM_freeN(elem_mask);
445  }
446  else {
447  /* Only cache if BVH-tree is created without a mask.
448  * This helps keep a standardized BVH-tree in cache. */
450  em,
451  4,
453  &sod->mesh_runtime->bvh_cache,
454  static_cast<ThreadMutex *>(sod->mesh_runtime->eval_mutex));
455  }
456  }
457  if (treedata == nullptr || treedata->tree == nullptr) {
458  return nullptr;
459  }
460 
461  return treedata;
462 }
463 
466 /* -------------------------------------------------------------------- */
471  const SnapObjectParams *params,
472  Object *ob_eval,
473  const float obmat[4][4],
474  bool is_object_active,
475  void *data);
476 
478  const eSnapTargetSelect snap_target_select,
479  const Base *base_act,
480  const Base *base)
481 {
482  if (!BASE_VISIBLE(sctx->runtime.v3d, base)) {
483  return false;
484  }
485 
486  if ((snap_target_select == SCE_SNAP_TARGET_ALL) ||
488  return true;
489  }
490 
491  if (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) {
492  return false;
493  }
494 
495  /* Get attributes of potential target. */
496  const bool is_active = (base_act == base);
497  const bool is_selected = (base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL);
498  const bool is_edited = (base->object->mode == OB_MODE_EDIT);
499  const bool is_selectable = (base->flag & BASE_SELECTABLE);
500  /* Get attributes of state. */
501  const bool is_in_object_mode = (base_act == NULL) || (base_act->object->mode == OB_MODE_OBJECT);
502 
503  if (is_in_object_mode) {
504  /* Handle target selection options that make sense for object mode. */
505  if ((snap_target_select & SCE_SNAP_TARGET_NOT_SELECTED) && is_selected) {
506  /* What is selectable or not is part of the object and depends on the mode. */
507  return false;
508  }
509  }
510  else {
511  /* Handle target selection options that make sense for edit/pose mode. */
512  if ((snap_target_select & SCE_SNAP_TARGET_NOT_ACTIVE) && is_active) {
513  return false;
514  }
515  if ((snap_target_select & SCE_SNAP_TARGET_NOT_EDITED) && is_edited && !is_active) {
516  /* Base is edited, but not active. */
517  return false;
518  }
519  if ((snap_target_select & SCE_SNAP_TARGET_NOT_NONEDITED) && !is_edited) {
520  return false;
521  }
522  }
523 
524  if ((snap_target_select & SCE_SNAP_TARGET_ONLY_SELECTABLE) && !is_selectable) {
525  return false;
526  }
527 
528  return true;
529 }
530 
535  const SnapObjectParams *params,
536  IterSnapObjsCallback sob_callback,
537  void *data)
538 {
540  const eSnapTargetSelect snap_target_select = params->snap_target_select;
541  Base *base_act = view_layer->basact;
542 
543  LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
544  if (!snap_object_is_snappable(sctx, snap_target_select, base_act, base)) {
545  continue;
546  }
547 
548  const bool is_object_active = (base == base_act);
549  Object *obj_eval = DEG_get_evaluated_object(sctx->runtime.depsgraph, base->object);
550  if (obj_eval->transflag & OB_DUPLI || BKE_object_has_geometry_set_instances(obj_eval)) {
551  ListBase *lb = object_duplilist(sctx->runtime.depsgraph, sctx->scene, obj_eval);
552  LISTBASE_FOREACH (DupliObject *, dupli_ob, lb) {
553  BLI_assert(DEG_is_evaluated_object(dupli_ob->ob));
554  sob_callback(sctx, params, dupli_ob->ob, dupli_ob->mat, is_object_active, data);
555  }
557  }
558 
559  sob_callback(sctx, params, obj_eval, obj_eval->obmat, is_object_active, data);
560  }
561 }
562 
565 /* -------------------------------------------------------------------- */
569 /* Store all ray-hits
570  * Support for storing all depths, not just the first (ray-cast 'all'). */
571 
573  void *bvhdata;
574 
575  /* internal vars for adding depths */
577 
578  const float (*obmat)[4];
579  const float (*timat)[3];
580 
581  float len_diff;
582  float local_scale;
583 
586 
587  /* output data */
589  bool retval;
590 };
591 
592 static SnapObjectHitDepth *hit_depth_create(const float depth,
593  const float co[3],
594  const float no[3],
595  int index,
596  Object *ob_eval,
597  const float obmat[4][4],
598  uint ob_uuid)
599 {
600  SnapObjectHitDepth *hit = MEM_new<SnapObjectHitDepth>(__func__);
601 
602  hit->depth = depth;
603  copy_v3_v3(hit->co, co);
604  copy_v3_v3(hit->no, no);
605  hit->index = index;
606 
607  hit->ob_eval = ob_eval;
608  copy_m4_m4(hit->obmat, (float(*)[4])obmat);
609  hit->ob_uuid = ob_uuid;
610 
611  return hit;
612 }
613 
614 static int hit_depth_cmp(const void *arg1, const void *arg2)
615 {
616  const SnapObjectHitDepth *h1 = static_cast<const SnapObjectHitDepth *>(arg1);
617  const SnapObjectHitDepth *h2 = static_cast<const SnapObjectHitDepth *>(arg2);
618  int val = 0;
619 
620  if (h1->depth < h2->depth) {
621  val = -1;
622  }
623  else if (h1->depth > h2->depth) {
624  val = 1;
625  }
626 
627  return val;
628 }
629 
630 static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
631 {
632  RayCastAll_Data *data = static_cast<RayCastAll_Data *>(userdata);
633  data->raycast_callback(data->bvhdata, index, ray, hit);
634  if (hit->index != -1) {
635  /* Get all values in world-space. */
636  float location[3], normal[3];
637  float depth;
638 
639  /* World-space location. */
640  mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co);
641  depth = (hit->dist + data->len_diff) / data->local_scale;
642 
643  /* World-space normal. */
644  copy_v3_v3(normal, hit->no);
645  mul_m3_v3((float(*)[3])data->timat, normal);
647 
649  depth, location, normal, hit->index, data->ob_eval, data->obmat, data->ob_uuid);
650  BLI_addtail(data->hit_list, hit_item);
651  }
652 }
653 
655  const float dir[3], const float v0[3], const float v1[3], const float v2[3], float no[3])
656 {
657  cross_tri_v3(no, v0, v1, v2);
658  return dot_v3v3(no, dir) < 0.0f;
659 }
660 
661 /* Callback to ray-cast with back-face culling (#Mesh). */
662 static void mesh_looptri_raycast_backface_culling_cb(void *userdata,
663  int index,
664  const BVHTreeRay *ray,
665  BVHTreeRayHit *hit)
666 {
667  const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
668  const MVert *vert = data->vert;
669  const MLoopTri *lt = &data->looptri[index];
670  const float *vtri_co[3] = {
671  vert[data->loop[lt->tri[0]].v].co,
672  vert[data->loop[lt->tri[1]].v].co,
673  vert[data->loop[lt->tri[2]].v].co,
674  };
675  float dist = bvhtree_ray_tri_intersection(ray, hit->dist, UNPACK3(vtri_co));
676 
677  if (dist >= 0 && dist < hit->dist) {
678  float no[3];
679  if (raycast_tri_backface_culling_test(ray->direction, UNPACK3(vtri_co), no)) {
680  hit->index = index;
681  hit->dist = dist;
682  madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
683  normalize_v3_v3(hit->no, no);
684  }
685  }
686 }
687 
688 /* Callback to ray-cast with back-face culling (#EditMesh). */
690  int index,
691  const BVHTreeRay *ray,
692  BVHTreeRayHit *hit)
693 {
694  const BVHTreeFromEditMesh *data = (BVHTreeFromEditMesh *)userdata;
695  BMEditMesh *em = data->em;
696  const BMLoop **ltri = (const BMLoop **)em->looptris[index];
697 
698  const float *t0, *t1, *t2;
699  t0 = ltri[0]->v->co;
700  t1 = ltri[1]->v->co;
701  t2 = ltri[2]->v->co;
702 
703  {
704  float dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
705 
706  if (dist >= 0 && dist < hit->dist) {
707  float no[3];
708  if (raycast_tri_backface_culling_test(ray->direction, t0, t1, t2, no)) {
709  hit->index = index;
710  hit->dist = dist;
711  madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
712  normalize_v3_v3(hit->no, no);
713  }
714  }
715  }
716 }
717 
718 static bool raycastMesh(SnapObjectContext *sctx,
719  const SnapObjectParams *params,
720  const float ray_start[3],
721  const float ray_dir[3],
722  Object *ob_eval,
723  const Mesh *me_eval,
724  const float obmat[4][4],
725  const uint ob_index,
726  bool use_hide,
727  /* read/write args */
728  float *ray_depth,
729  /* return args */
730  float r_loc[3],
731  float r_no[3],
732  int *r_index,
733  ListBase *r_hit_list)
734 {
735  bool retval = false;
736 
737  if (me_eval->totpoly == 0) {
738  return retval;
739  }
740 
741  float imat[4][4];
742  float ray_start_local[3], ray_normal_local[3];
743  float local_scale, local_depth, len_diff = 0.0f;
744 
745  invert_m4_m4(imat, obmat);
746 
747  copy_v3_v3(ray_start_local, ray_start);
748  copy_v3_v3(ray_normal_local, ray_dir);
749 
750  mul_m4_v3(imat, ray_start_local);
751  mul_mat3_m4_v3(imat, ray_normal_local);
752 
753  /* local scale in normal direction */
754  local_scale = normalize_v3(ray_normal_local);
755  local_depth = *ray_depth;
756  if (local_depth != BVH_RAYCAST_DIST_MAX) {
757  local_depth *= local_scale;
758  }
759 
760  /* Test BoundBox */
761  const BoundBox *bb = BKE_object_boundbox_get(ob_eval);
762  if (bb) {
763  /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
765  ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, nullptr)) {
766  return retval;
767  }
768  }
769  /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
770  * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358.
771  */
772  if (len_diff > 400.0f) {
773  len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
774  madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
775  local_depth -= len_diff;
776  }
777  else {
778  len_diff = 0.0f;
779  }
780 
781  SnapData_Mesh *sod = snap_object_data_mesh_get(sctx, ob_eval, me_eval, use_hide);
782 
783  BVHTreeFromMesh *treedata = &sod->treedata_mesh;
784 
785  if (treedata->tree == nullptr) {
786  return retval;
787  }
788 
789  float timat[3][3]; /* transpose inverse matrix for normals */
790  transpose_m3_m4(timat, imat);
791 
792  BLI_assert(treedata->raycast_callback != nullptr);
793  if (r_hit_list) {
795 
796  data.bvhdata = treedata;
797  data.raycast_callback = treedata->raycast_callback;
798  data.obmat = obmat;
799  data.timat = timat;
800  data.len_diff = len_diff;
801  data.local_scale = local_scale;
802  data.ob_eval = ob_eval;
803  data.ob_uuid = ob_index;
804  data.hit_list = r_hit_list;
805  data.retval = retval;
806 
807  BLI_bvhtree_ray_cast_all(treedata->tree,
808  ray_start_local,
809  ray_normal_local,
810  0.0f,
811  *ray_depth,
813  &data);
814 
815  retval = data.retval;
816  }
817  else {
818  BVHTreeRayHit hit{};
819  hit.index = -1;
820  hit.dist = local_depth;
821 
822  if (BLI_bvhtree_ray_cast(treedata->tree,
823  ray_start_local,
824  ray_normal_local,
825  0.0f,
826  &hit,
827  params->use_backface_culling ?
829  treedata->raycast_callback,
830  treedata) != -1) {
831  hit.dist += len_diff;
832  hit.dist /= local_scale;
833  if (hit.dist <= *ray_depth) {
834  *ray_depth = hit.dist;
835  copy_v3_v3(r_loc, hit.co);
836 
837  /* Back to world-space. */
838  mul_m4_v3(obmat, r_loc);
839 
840  if (r_no) {
841  copy_v3_v3(r_no, hit.no);
842  mul_m3_v3(timat, r_no);
843  normalize_v3(r_no);
844  }
845 
846  retval = true;
847 
848  if (r_index) {
849  *r_index = treedata->looptri[hit.index].poly;
850  }
851  }
852  }
853  }
854 
855  return retval;
856 }
857 
859  const SnapObjectParams *params,
860  const float ray_start[3],
861  const float ray_dir[3],
862  Object *ob_eval,
863  BMEditMesh *em,
864  const float obmat[4][4],
865  const uint ob_index,
866  /* read/write args */
867  float *ray_depth,
868  /* return args */
869  float r_loc[3],
870  float r_no[3],
871  int *r_index,
872  ListBase *r_hit_list)
873 {
874  bool retval = false;
875  if (em->bm->totface == 0) {
876  return retval;
877  }
878 
879  float imat[4][4];
880  float ray_start_local[3], ray_normal_local[3];
881  float local_scale, local_depth, len_diff = 0.0f;
882 
883  invert_m4_m4(imat, obmat);
884 
885  copy_v3_v3(ray_start_local, ray_start);
886  copy_v3_v3(ray_normal_local, ray_dir);
887 
888  mul_m4_v3(imat, ray_start_local);
889  mul_mat3_m4_v3(imat, ray_normal_local);
890 
891  /* local scale in normal direction */
892  local_scale = normalize_v3(ray_normal_local);
893  local_depth = *ray_depth;
894  if (local_depth != BVH_RAYCAST_DIST_MAX) {
895  local_depth *= local_scale;
896  }
897 
898  SnapData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob_eval, em);
899 
900  /* Test BoundBox */
901 
902  /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
904  ray_start_local, ray_normal_local, sod->min, sod->max, &len_diff, nullptr)) {
905  return retval;
906  }
907 
908  /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
909  * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358.
910  */
911  if (len_diff > 400.0f) {
912  len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
913  madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
914  local_depth -= len_diff;
915  }
916  else {
917  len_diff = 0.0f;
918  }
919 
920  BVHTreeFromEditMesh *treedata = snap_object_data_editmesh_treedata_get(sctx, ob_eval, em);
921  if (treedata == nullptr) {
922  return retval;
923  }
924 
925  float timat[3][3]; /* transpose inverse matrix for normals */
926  transpose_m3_m4(timat, imat);
927 
928  if (r_hit_list) {
930 
931  data.bvhdata = treedata;
932  data.raycast_callback = treedata->raycast_callback;
933  data.obmat = obmat;
934  data.timat = timat;
935  data.len_diff = len_diff;
936  data.local_scale = local_scale;
937  data.ob_eval = ob_eval;
938  data.ob_uuid = ob_index;
939  data.hit_list = r_hit_list;
940  data.retval = retval;
941 
942  BLI_bvhtree_ray_cast_all(treedata->tree,
943  ray_start_local,
944  ray_normal_local,
945  0.0f,
946  *ray_depth,
948  &data);
949 
950  retval = data.retval;
951  }
952  else {
953  BVHTreeRayHit hit{};
954  hit.index = -1;
955  hit.dist = local_depth;
956 
957  if (BLI_bvhtree_ray_cast(treedata->tree,
958  ray_start_local,
959  ray_normal_local,
960  0.0f,
961  &hit,
962  params->use_backface_culling ?
964  treedata->raycast_callback,
965  treedata) != -1) {
966  hit.dist += len_diff;
967  hit.dist /= local_scale;
968  if (hit.dist <= *ray_depth) {
969  *ray_depth = hit.dist;
970  copy_v3_v3(r_loc, hit.co);
971 
972  /* Back to world-space. */
973  mul_m4_v3(obmat, r_loc);
974 
975  if (r_no) {
976  copy_v3_v3(r_no, hit.no);
977  mul_m3_v3(timat, r_no);
978  normalize_v3(r_no);
979  }
980 
981  retval = true;
982 
983  if (r_index) {
984  em = sod->treedata_editmesh.em;
985 
986  *r_index = BM_elem_index_get(em->looptris[hit.index][0]->f);
987  }
988  }
989  }
990  }
991 
992  return retval;
993 }
994 
996  const float *ray_start;
997  const float *ray_dir;
999  /* read/write args */
1000  float *ray_depth;
1001  /* return args */
1002  float *r_loc;
1003  float *r_no;
1004  int *r_index;
1009  bool ret;
1010 };
1011 
1016  const SnapObjectParams *params,
1017  Object *ob_eval,
1018  const float obmat[4][4],
1019  bool is_object_active,
1020  void *data)
1021 {
1022  RaycastObjUserData *dt = static_cast<RaycastObjUserData *>(data);
1023  const uint ob_index = dt->ob_index++;
1024  bool use_occlusion_test = dt->use_occlusion_test;
1025  /* read/write args */
1026  float *ray_depth = dt->ray_depth;
1027 
1028  bool retval = false;
1029  if (use_occlusion_test) {
1030  if (ELEM(ob_eval->dt, OB_BOUNDBOX, OB_WIRE)) {
1031  /* Do not hit objects that are in wire or bounding box
1032  * display mode. */
1033  return;
1034  }
1035  }
1036 
1037  switch (ob_eval->type) {
1038  case OB_MESH: {
1039  const eSnapEditType edit_mode_type = params->edit_mode_type;
1040  bool use_hide = false;
1041  const Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide);
1042  if (me_eval == nullptr) {
1043  BMEditMesh *em = BKE_editmesh_from_object(ob_eval);
1044  if (UNLIKELY(!em)) { /* See #mesh_for_snap doc-string. */
1045  return;
1046  }
1048  "Make sure there is only one pointer for looptris");
1049  retval = raycastEditMesh(sctx,
1050  params,
1051  dt->ray_start,
1052  dt->ray_dir,
1053  ob_eval,
1054  em,
1055  obmat,
1056  ob_index,
1057  ray_depth,
1058  dt->r_loc,
1059  dt->r_no,
1060  dt->r_index,
1061  dt->r_hit_list);
1062  break;
1063  }
1064  retval = raycastMesh(sctx,
1065  params,
1066  dt->ray_start,
1067  dt->ray_dir,
1068  ob_eval,
1069  me_eval,
1070  obmat,
1071  ob_index,
1072  use_hide,
1073  ray_depth,
1074  dt->r_loc,
1075  dt->r_no,
1076  dt->r_index,
1077  dt->r_hit_list);
1078  break;
1079  }
1080  case OB_CURVES_LEGACY:
1081  case OB_SURF:
1082  case OB_FONT: {
1083  if (!is_object_active) {
1084  const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
1085  if (mesh_eval) {
1086  retval = raycastMesh(sctx,
1087  params,
1088  dt->ray_start,
1089  dt->ray_dir,
1090  ob_eval,
1091  mesh_eval,
1092  obmat,
1093  ob_index,
1094  false,
1095  ray_depth,
1096  dt->r_loc,
1097  dt->r_no,
1098  dt->r_index,
1099  dt->r_hit_list);
1100  }
1101  }
1102  break;
1103  }
1104  }
1105 
1106  if (retval) {
1107  if (dt->r_ob) {
1108  *dt->r_ob = ob_eval;
1109  }
1110  if (dt->r_obmat) {
1111  copy_m4_m4(dt->r_obmat, obmat);
1112  }
1113  dt->ret = true;
1114  }
1115 }
1116 
1143  const SnapObjectParams *params,
1144  const float ray_start[3],
1145  const float ray_dir[3],
1146  /* read/write args */
1147  /* Parameters below cannot be const, because they are assigned to a
1148  * non-const variable (readability-non-const-parameter). */
1149  float *ray_depth /* NOLINT */,
1150  /* return args */
1151  float r_loc[3] /* NOLINT */,
1152  float r_no[3] /* NOLINT */,
1153  int *r_index /* NOLINT */,
1154  Object **r_ob,
1155  float r_obmat[4][4],
1156  ListBase *r_hit_list)
1157 {
1158  const View3D *v3d = sctx->runtime.v3d;
1159  if (params->use_occlusion_test && v3d && XRAY_FLAG_ENABLED(v3d)) {
1160  /* General testing of occlusion geometry is disabled if the snap is not intended for the edit
1161  * cage. */
1162  if (params->edit_mode_type == SNAP_GEOM_EDIT) {
1163  return false;
1164  }
1165  }
1166 
1167  RaycastObjUserData data = {};
1168  data.ray_start = ray_start;
1169  data.ray_dir = ray_dir;
1170  data.ob_index = 0;
1171  data.ray_depth = ray_depth;
1172  data.r_loc = r_loc;
1173  data.r_no = r_no;
1174  data.r_index = r_index;
1175  data.r_ob = r_ob;
1176  data.r_obmat = r_obmat;
1177  data.r_hit_list = r_hit_list;
1178  data.use_occlusion_test = params->use_occlusion_test;
1179  data.ret = false;
1180 
1182 
1183  return data.ret;
1184 }
1185 
1188 /* -------------------------------------------------------------------- */
1193  const float *init_co;
1194  const float *curr_co;
1195  /* return args */
1196  float *r_loc;
1197  float *r_no;
1198  int *r_index;
1199  float r_dist_sq;
1203  bool ret;
1204 };
1205 
1207  BVHTree_NearestPointCallback nearest_cb,
1208  void *treedata,
1209  float co[3],
1210  float r_co[3],
1211  float r_no[3],
1212  int *r_index,
1213  float *r_dist_sq)
1214 {
1215  BVHTreeNearest nearest = {};
1216  nearest.index = -1;
1217  copy_v3_fl(nearest.co, FLT_MAX);
1218  nearest.dist_sq = FLT_MAX;
1219 
1220  BLI_bvhtree_find_nearest(tree, co, &nearest, nearest_cb, treedata);
1221 
1222  if (r_co) {
1223  copy_v3_v3(r_co, nearest.co);
1224  }
1225  if (r_no) {
1226  copy_v3_v3(r_no, nearest.no);
1227  }
1228  if (r_index) {
1229  *r_index = nearest.index;
1230  }
1231  if (r_dist_sq) {
1232  float diff[3];
1233  sub_v3_v3v3(diff, co, nearest.co);
1234  *r_dist_sq = len_squared_v3(diff);
1235  }
1236 }
1237 
1239  const struct SnapObjectParams *params,
1240  BVHTree *tree,
1241  BVHTree_NearestPointCallback nearest_cb,
1242  void *treedata,
1243  const float (*obmat)[4],
1244  const float init_co[3],
1245  const float curr_co[3],
1246  float *r_dist_sq,
1247  float *r_loc,
1248  float *r_no,
1249  int *r_index)
1250 {
1251  if (curr_co == nullptr || init_co == nullptr) {
1252  /* No location to work with, so just return. */
1253  return false;
1254  }
1255 
1256  float imat[4][4];
1257  invert_m4_m4(imat, obmat);
1258 
1259  float timat[3][3]; /* transpose inverse matrix for normals */
1260  transpose_m3_m4(timat, imat);
1261 
1262  /* compute offset between init co and prev co in local space */
1263  float init_co_local[3], curr_co_local[3];
1264  float delta_local[3];
1265  mul_v3_m4v3(init_co_local, imat, init_co);
1266  mul_v3_m4v3(curr_co_local, imat, curr_co);
1267  sub_v3_v3v3(delta_local, curr_co_local, init_co_local);
1268 
1269  float dist_sq;
1270  if (params->keep_on_same_target) {
1272  tree, nearest_cb, treedata, init_co_local, nullptr, nullptr, nullptr, &dist_sq);
1273  }
1274  else {
1275  /* NOTE: when `params->face_nearest_steps == 1`, the return variables of function below contain
1276  * the answer. We could return immediately after updating r_loc, r_no, r_index, but that would
1277  * also complicate the code. Foregoing slight optimization for code clarity. */
1279  tree, nearest_cb, treedata, curr_co_local, nullptr, nullptr, nullptr, &dist_sq);
1280  }
1281  if (*r_dist_sq <= dist_sq) {
1282  return false;
1283  }
1284  *r_dist_sq = dist_sq;
1285 
1286  /* scale to make `snap_face_nearest_steps` steps */
1287  float step_scale_factor = 1.0f / max_ff(1.0f, (float)params->face_nearest_steps);
1288  mul_v3_fl(delta_local, step_scale_factor);
1289 
1290  float co_local[3];
1291  float no_local[3];
1292  int index;
1293 
1294  copy_v3_v3(co_local, init_co_local);
1295 
1296  for (int i = 0; i < params->face_nearest_steps; i++) {
1297  add_v3_v3(co_local, delta_local);
1299  tree, nearest_cb, treedata, co_local, co_local, no_local, &index, nullptr);
1300  }
1301 
1302  mul_v3_m4v3(r_loc, obmat, co_local);
1303 
1304  if (r_no) {
1305  mul_v3_m3v3(r_no, timat, no_local);
1306  normalize_v3(r_no);
1307  }
1308 
1309  if (r_index) {
1310  *r_index = index;
1311  }
1312 
1313  return true;
1314 }
1315 
1317  const struct SnapObjectParams *params,
1318  Object *ob_eval,
1319  const Mesh *me_eval,
1320  const float (*obmat)[4],
1321  bool use_hide,
1322  const float init_co[3],
1323  const float curr_co[3],
1324  float *r_dist_sq,
1325  float *r_loc,
1326  float *r_no,
1327  int *r_index)
1328 {
1329  BVHTreeFromMesh *treedata = snap_object_data_mesh_treedata_get(sctx, ob_eval, me_eval, use_hide);
1330  if (treedata == nullptr || treedata->tree == nullptr) {
1331  return false;
1332  }
1333 
1334  return nearest_world_tree(sctx,
1335  params,
1336  treedata->tree,
1337  treedata->nearest_callback,
1338  treedata,
1339  obmat,
1340  init_co,
1341  curr_co,
1342  r_dist_sq,
1343  r_loc,
1344  r_no,
1345  r_index);
1346 }
1347 
1349  const struct SnapObjectParams *params,
1350  Object *ob_eval,
1351  BMEditMesh *em,
1352  const float (*obmat)[4],
1353  const float init_co[3],
1354  const float curr_co[3],
1355  float *r_dist_sq,
1356  float *r_loc,
1357  float *r_no,
1358  int *r_index)
1359 {
1360  BVHTreeFromEditMesh *treedata = snap_object_data_editmesh_treedata_get(sctx, ob_eval, em);
1361  if (treedata == nullptr || treedata->tree == nullptr) {
1362  return false;
1363  }
1364 
1365  return nearest_world_tree(sctx,
1366  params,
1367  treedata->tree,
1368  treedata->nearest_callback,
1369  treedata,
1370  obmat,
1371  init_co,
1372  curr_co,
1373  r_dist_sq,
1374  r_loc,
1375  r_no,
1376  r_index);
1377 }
1379  const struct SnapObjectParams *params,
1380  Object *ob_eval,
1381  const float obmat[4][4],
1382  bool is_object_active,
1383  void *data)
1384 {
1385  struct NearestWorldObjUserData *dt = static_cast<NearestWorldObjUserData *>(data);
1386 
1387  bool retval = false;
1388  switch (ob_eval->type) {
1389  case OB_MESH: {
1390  const eSnapEditType edit_mode_type = params->edit_mode_type;
1391  bool use_hide = false;
1392  const Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide);
1393  if (me_eval) {
1394  retval = nearest_world_mesh(sctx,
1395  params,
1396  ob_eval,
1397  me_eval,
1398  obmat,
1399  use_hide,
1400  dt->init_co,
1401  dt->curr_co,
1402  &dt->r_dist_sq,
1403  dt->r_loc,
1404  dt->r_no,
1405  dt->r_index);
1406  }
1407  else {
1408  BMEditMesh *em = BKE_editmesh_from_object(ob_eval);
1410  "Make sure there is only one pointer for looptris");
1411  retval = nearest_world_editmesh(sctx,
1412  params,
1413  ob_eval,
1414  em,
1415  obmat,
1416  dt->init_co,
1417  dt->curr_co,
1418  &dt->r_dist_sq,
1419  dt->r_loc,
1420  dt->r_no,
1421  dt->r_index);
1422  }
1423  break;
1424  }
1425  case OB_CURVES_LEGACY:
1426  case OB_SURF:
1427  case OB_FONT:
1428  if (!is_object_active) {
1429  const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
1430  if (me_eval) {
1431  retval = nearest_world_mesh(sctx,
1432  params,
1433  ob_eval,
1434  me_eval,
1435  obmat,
1436  false,
1437  dt->init_co,
1438  dt->curr_co,
1439  &dt->r_dist_sq,
1440  dt->r_loc,
1441  dt->r_no,
1442  dt->r_index);
1443  }
1444  }
1445  break;
1446  }
1447 
1448  if (retval) {
1449  if (dt->r_ob) {
1450  *dt->r_ob = ob_eval;
1451  }
1452  if (dt->r_obmat) {
1453  copy_m4_m4(dt->r_obmat, obmat);
1454  }
1455  dt->ret = true;
1456  }
1457 }
1458 
1480  const struct SnapObjectParams *params,
1481  const float init_co[3],
1482  const float curr_co[3],
1483  float *r_loc /* NOLINT */,
1484  float *r_no /* NOLINT */,
1485  int *r_index /* NOLINT */,
1486  Object **r_ob,
1487  float r_obmat[4][4])
1488 {
1490  data.init_co = init_co;
1491  data.curr_co = curr_co;
1492  data.r_loc = r_loc;
1493  data.r_no = r_no;
1494  data.r_index = r_index;
1495  data.r_dist_sq = FLT_MAX;
1496  data.r_ob = r_ob;
1497  data.r_obmat = r_obmat;
1498  data.ret = false;
1499 
1501  return data.ret;
1502 }
1503 
1506 /* -------------------------------------------------------------------- */
1510 /* Test BoundBox */
1511 static bool snap_bound_box_check_dist(const float min[3],
1512  const float max[3],
1513  const float lpmat[4][4],
1514  const float win_size[2],
1515  const float mval[2],
1516  float dist_px_sq)
1517 {
1518  /* In vertex and edges you need to get the pixel distance from ray to BoundBox,
1519  * see: T46099, T46816 */
1520 
1521  DistProjectedAABBPrecalc data_precalc;
1522  dist_squared_to_projected_aabb_precalc(&data_precalc, lpmat, win_size, mval);
1523 
1524  bool dummy[3];
1525  float bb_dist_px_sq = dist_squared_to_projected_aabb(&data_precalc, min, max, dummy);
1526 
1527  if (bb_dist_px_sq > dist_px_sq) {
1528  return false;
1529  }
1530  return true;
1531 }
1532 
1535 /* -------------------------------------------------------------------- */
1539 struct Nearest2dUserData;
1540 
1541 using Nearest2DGetVertCoCallback = void (*)(const int index,
1542  const Nearest2dUserData *data,
1543  const float **r_co);
1544 using Nearest2DGetEdgeVertsCallback = void (*)(const int index,
1545  const Nearest2dUserData *data,
1546  int r_v_index[2]);
1547 using Nearest2DGetTriVertsCallback = void (*)(const int index,
1548  const Nearest2dUserData *data,
1549  int r_v_index[3]);
1550 /* Equal the previous one */
1551 using Nearest2DGetTriEdgesCallback = void (*)(const int index,
1552  const Nearest2dUserData *data,
1553  int r_e_index[3]);
1554 using Nearest2DCopyVertNoCallback = void (*)(const int index,
1555  const Nearest2dUserData *data,
1556  float r_no[3]);
1557 
1564 
1565  union {
1566  struct {
1568  };
1569  struct {
1570  const MVert *vert;
1571  const float (*vert_normals)[3];
1572  const MEdge *edge; /* only used for #BVHTreeFromMeshEdges */
1573  const MLoop *loop;
1575  };
1576  };
1577 
1578  bool is_persp;
1580 };
1581 
1582 static void cb_mvert_co_get(const int index, const Nearest2dUserData *data, const float **r_co)
1583 {
1584  *r_co = data->vert[index].co;
1585 }
1586 
1587 static void cb_bvert_co_get(const int index, const Nearest2dUserData *data, const float **r_co)
1588 {
1589  BMVert *eve = BM_vert_at_index(data->bm, index);
1590  *r_co = eve->co;
1591 }
1592 
1593 static void cb_mvert_no_copy(const int index, const Nearest2dUserData *data, float r_no[3])
1594 {
1595  copy_v3_v3(r_no, data->vert_normals[index]);
1596 }
1597 
1598 static void cb_bvert_no_copy(const int index, const Nearest2dUserData *data, float r_no[3])
1599 {
1600  BMVert *eve = BM_vert_at_index(data->bm, index);
1601 
1602  copy_v3_v3(r_no, eve->no);
1603 }
1604 
1605 static void cb_medge_verts_get(const int index, const Nearest2dUserData *data, int r_v_index[2])
1606 {
1607  const MEdge *edge = &data->edge[index];
1608 
1609  r_v_index[0] = edge->v1;
1610  r_v_index[1] = edge->v2;
1611 }
1612 
1613 static void cb_bedge_verts_get(const int index, const Nearest2dUserData *data, int r_v_index[2])
1614 {
1615  BMEdge *eed = BM_edge_at_index(data->bm, index);
1616 
1617  r_v_index[0] = BM_elem_index_get(eed->v1);
1618  r_v_index[1] = BM_elem_index_get(eed->v2);
1619 }
1620 
1621 static void cb_mlooptri_edges_get(const int index, const Nearest2dUserData *data, int r_v_index[3])
1622 {
1623  const MEdge *medge = data->edge;
1624  const MLoop *mloop = data->loop;
1625  const MLoopTri *lt = &data->looptri[index];
1626  for (int j = 2, j_next = 0; j_next < 3; j = j_next++) {
1627  const MEdge *ed = &medge[mloop[lt->tri[j]].e];
1628  const uint tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v};
1629  if (ELEM(ed->v1, tri_edge[0], tri_edge[1]) && ELEM(ed->v2, tri_edge[0], tri_edge[1])) {
1630  // printf("real edge found\n");
1631  r_v_index[j] = mloop[lt->tri[j]].e;
1632  }
1633  else {
1634  r_v_index[j] = -1;
1635  }
1636  }
1637 }
1638 
1639 static void cb_mlooptri_verts_get(const int index, const Nearest2dUserData *data, int r_v_index[3])
1640 {
1641  const MLoop *loop = data->loop;
1642  const MLoopTri *looptri = &data->looptri[index];
1643 
1644  r_v_index[0] = loop[looptri->tri[0]].v;
1645  r_v_index[1] = loop[looptri->tri[1]].v;
1646  r_v_index[2] = loop[looptri->tri[2]].v;
1647 }
1648 
1650  const float (*clip_plane)[4],
1651  const int clip_plane_len,
1652  const bool is_persp,
1653  const float co[3],
1654  float *dist_px_sq,
1655  float r_co[3])
1656 {
1657  if (!isect_point_planes_v3_negated(clip_plane, clip_plane_len, co)) {
1658  return false;
1659  }
1660 
1661  float co2d[2] = {
1662  (dot_m4_v3_row_x(precalc->pmat, co) + precalc->pmat[3][0]),
1663  (dot_m4_v3_row_y(precalc->pmat, co) + precalc->pmat[3][1]),
1664  };
1665 
1666  if (is_persp) {
1667  float w = mul_project_m4_v3_zfac(precalc->pmat, co);
1668  mul_v2_fl(co2d, 1.0f / w);
1669  }
1670 
1671  const float dist_sq = len_squared_v2v2(precalc->mval, co2d);
1672  if (dist_sq < *dist_px_sq) {
1673  copy_v3_v3(r_co, co);
1674  *dist_px_sq = dist_sq;
1675  return true;
1676  }
1677  return false;
1678 }
1679 
1681  const float (*clip_plane)[4],
1682  const int clip_plane_len,
1683  const bool is_persp,
1684  const float va[3],
1685  const float vb[3],
1686  float *dist_px_sq,
1687  float r_co[3])
1688 {
1689  float near_co[3], lambda;
1690  if (!isect_ray_line_v3(precalc->ray_origin, precalc->ray_direction, va, vb, &lambda)) {
1691  copy_v3_v3(near_co, va);
1692  }
1693  else {
1694  if (lambda <= 0.0f) {
1695  copy_v3_v3(near_co, va);
1696  }
1697  else if (lambda >= 1.0f) {
1698  copy_v3_v3(near_co, vb);
1699  }
1700  else {
1701  interp_v3_v3v3(near_co, va, vb, lambda);
1702  }
1703  }
1704 
1705  return test_projected_vert_dist(
1706  precalc, clip_plane, clip_plane_len, is_persp, near_co, dist_px_sq, r_co);
1707 }
1708 
1709 static void cb_snap_vert(void *userdata,
1710  int index,
1711  const DistProjectedAABBPrecalc *precalc,
1712  const float (*clip_plane)[4],
1713  const int clip_plane_len,
1714  BVHTreeNearest *nearest)
1715 {
1716  Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata);
1717 
1718  const float *co;
1719  data->get_vert_co(index, data, &co);
1720 
1721  if (test_projected_vert_dist(precalc,
1722  clip_plane,
1723  clip_plane_len,
1724  data->is_persp,
1725  co,
1726  &nearest->dist_sq,
1727  nearest->co)) {
1728  data->copy_vert_no(index, data, nearest->no);
1729  nearest->index = index;
1730  }
1731 }
1732 
1733 static void cb_snap_edge(void *userdata,
1734  int index,
1735  const DistProjectedAABBPrecalc *precalc,
1736  const float (*clip_plane)[4],
1737  const int clip_plane_len,
1738  BVHTreeNearest *nearest)
1739 {
1740  Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata);
1741 
1742  int vindex[2];
1743  data->get_edge_verts_index(index, data, vindex);
1744 
1745  const float *v_pair[2];
1746  data->get_vert_co(vindex[0], data, &v_pair[0]);
1747  data->get_vert_co(vindex[1], data, &v_pair[1]);
1748 
1749  if (test_projected_edge_dist(precalc,
1750  clip_plane,
1751  clip_plane_len,
1752  data->is_persp,
1753  v_pair[0],
1754  v_pair[1],
1755  &nearest->dist_sq,
1756  nearest->co)) {
1757  sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
1758  nearest->index = index;
1759  }
1760 }
1761 
1762 static void cb_snap_edge_verts(void *userdata,
1763  int index,
1764  const DistProjectedAABBPrecalc *precalc,
1765  const float (*clip_plane)[4],
1766  const int clip_plane_len,
1767  BVHTreeNearest *nearest)
1768 {
1769  Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata);
1770 
1771  int vindex[2];
1772  data->get_edge_verts_index(index, data, vindex);
1773 
1774  for (int i = 2; i--;) {
1775  if (vindex[i] == nearest->index) {
1776  continue;
1777  }
1778  cb_snap_vert(userdata, vindex[i], precalc, clip_plane, clip_plane_len, nearest);
1779  }
1780 }
1781 
1782 static void cb_snap_tri_edges(void *userdata,
1783  int index,
1784  const DistProjectedAABBPrecalc *precalc,
1785  const float (*clip_plane)[4],
1786  const int clip_plane_len,
1787  BVHTreeNearest *nearest)
1788 {
1789  Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata);
1790 
1791  if (data->use_backface_culling) {
1792  int vindex[3];
1793  data->get_tri_verts_index(index, data, vindex);
1794 
1795  const float *t0, *t1, *t2;
1796  data->get_vert_co(vindex[0], data, &t0);
1797  data->get_vert_co(vindex[1], data, &t1);
1798  data->get_vert_co(vindex[2], data, &t2);
1799  float dummy[3];
1800  if (raycast_tri_backface_culling_test(precalc->ray_direction, t0, t1, t2, dummy)) {
1801  return;
1802  }
1803  }
1804 
1805  int eindex[3];
1806  data->get_tri_edges_index(index, data, eindex);
1807  for (int i = 3; i--;) {
1808  if (eindex[i] != -1) {
1809  if (eindex[i] == nearest->index) {
1810  continue;
1811  }
1812  cb_snap_edge(userdata, eindex[i], precalc, clip_plane, clip_plane_len, nearest);
1813  }
1814  }
1815 }
1816 
1817 static void cb_snap_tri_verts(void *userdata,
1818  int index,
1819  const DistProjectedAABBPrecalc *precalc,
1820  const float (*clip_plane)[4],
1821  const int clip_plane_len,
1822  BVHTreeNearest *nearest)
1823 {
1824  Nearest2dUserData *data = static_cast<Nearest2dUserData *>(userdata);
1825 
1826  int vindex[3];
1827  data->get_tri_verts_index(index, data, vindex);
1828 
1829  if (data->use_backface_culling) {
1830  const float *t0, *t1, *t2;
1831  data->get_vert_co(vindex[0], data, &t0);
1832  data->get_vert_co(vindex[1], data, &t1);
1833  data->get_vert_co(vindex[2], data, &t2);
1834  float dummy[3];
1835  if (raycast_tri_backface_culling_test(precalc->ray_direction, t0, t1, t2, dummy)) {
1836  return;
1837  }
1838  }
1839 
1840  for (int i = 3; i--;) {
1841  if (vindex[i] == nearest->index) {
1842  continue;
1843  }
1844  cb_snap_vert(userdata, vindex[i], precalc, clip_plane, clip_plane_len, nearest);
1845  }
1846 }
1847 
1849  bool is_persp,
1850  bool use_backface_culling,
1851  Nearest2dUserData *r_nearest2d)
1852 {
1853  r_nearest2d->get_vert_co = cb_mvert_co_get;
1855  r_nearest2d->copy_vert_no = cb_mvert_no_copy;
1858 
1859  r_nearest2d->vert = sod->treedata_mesh.vert;
1860  r_nearest2d->vert_normals = sod->treedata_mesh.vert_normals;
1861  r_nearest2d->edge = sod->treedata_mesh.edge;
1862  r_nearest2d->loop = sod->treedata_mesh.loop;
1863  r_nearest2d->looptri = sod->treedata_mesh.looptri;
1864 
1865  r_nearest2d->is_persp = is_persp;
1866  r_nearest2d->use_backface_culling = use_backface_culling;
1867 }
1868 
1870  bool is_persp,
1871  bool use_backface_culling,
1872  Nearest2dUserData *r_nearest2d)
1873 {
1874  r_nearest2d->get_vert_co = cb_bvert_co_get;
1876  r_nearest2d->copy_vert_no = cb_bvert_no_copy;
1877  r_nearest2d->get_tri_verts_index = nullptr;
1878  r_nearest2d->get_tri_edges_index = nullptr;
1879 
1880  r_nearest2d->bm = sod->treedata_editmesh.em->bm;
1881 
1882  r_nearest2d->is_persp = is_persp;
1883  r_nearest2d->use_backface_culling = use_backface_culling;
1884 }
1885 
1888 /* -------------------------------------------------------------------- */
1893  const SnapObjectParams *params,
1894  Object *ob_eval,
1895  const float obmat[4][4],
1896  /* read/write args */
1897  float *dist_px,
1898  /* return args */
1899  float r_loc[3],
1900  float r_no[3],
1901  int *r_index)
1902 {
1904 
1905  float lpmat[4][4];
1906  mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat);
1907 
1908  DistProjectedAABBPrecalc neasrest_precalc;
1910  &neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval);
1911 
1912  float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
1913  transpose_m4_m4(tobmat, obmat);
1914  for (int i = sctx->runtime.clip_plane_len; i--;) {
1915  mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]);
1916  }
1917 
1918  BVHTreeNearest nearest{};
1919  nearest.index = -1;
1920  nearest.dist_sq = square_f(*dist_px);
1921 
1922  Nearest2dUserData nearest2d;
1923  std::unique_ptr<SnapData_Mesh> *sod_mesh = sctx->mesh_caches.lookup_ptr(ob_eval);
1924  if (sod_mesh) {
1925  nearest2d_data_init_mesh(sod_mesh->get(),
1927  params->use_backface_culling,
1928  &nearest2d);
1929 
1930  BVHTreeFromMesh *treedata = &sod_mesh->get()->treedata_mesh;
1931 
1932  const MPoly *mp = &sod_mesh->get()->poly[*r_index];
1933  const MLoop *ml = &treedata->loop[mp->loopstart];
1934  if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) {
1935  elem = SCE_SNAP_MODE_EDGE;
1936  BLI_assert(treedata->edge != nullptr);
1937  for (int i = mp->totloop; i--; ml++) {
1938  cb_snap_edge(&nearest2d,
1939  ml->e,
1940  &neasrest_precalc,
1941  clip_planes_local,
1942  sctx->runtime.clip_plane_len,
1943  &nearest);
1944  }
1945  }
1946  else {
1947  elem = SCE_SNAP_MODE_VERTEX;
1948  for (int i = mp->totloop; i--; ml++) {
1949  cb_snap_vert(&nearest2d,
1950  ml->v,
1951  &neasrest_precalc,
1952  clip_planes_local,
1953  sctx->runtime.clip_plane_len,
1954  &nearest);
1955  }
1956  }
1957  }
1958  else {
1959  /* The object's #BMEditMesh was used to snap instead. */
1960  std::unique_ptr<SnapData_EditMesh> &sod_editmesh = sctx->editmesh_caches.lookup(
1961  BKE_editmesh_from_object(ob_eval));
1962  BLI_assert(sod_editmesh.get() != nullptr);
1963 
1964  nearest2d_data_init_editmesh(sod_editmesh.get(),
1966  params->use_backface_culling,
1967  &nearest2d);
1968 
1969  BMEditMesh *em = sod_editmesh->treedata_editmesh.em;
1970 
1972  BMFace *f = BM_face_at_index(em->bm, *r_index);
1973  BMLoop *l_iter, *l_first;
1974  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
1975  if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) {
1976  elem = SCE_SNAP_MODE_EDGE;
1979  do {
1980  cb_snap_edge(&nearest2d,
1981  BM_elem_index_get(l_iter->e),
1982  &neasrest_precalc,
1983  clip_planes_local,
1984  sctx->runtime.clip_plane_len,
1985  &nearest);
1986  } while ((l_iter = l_iter->next) != l_first);
1987  }
1988  else {
1989  elem = SCE_SNAP_MODE_VERTEX;
1992  do {
1993  cb_snap_vert(&nearest2d,
1994  BM_elem_index_get(l_iter->v),
1995  &neasrest_precalc,
1996  clip_planes_local,
1997  sctx->runtime.clip_plane_len,
1998  &nearest);
1999  } while ((l_iter = l_iter->next) != l_first);
2000  }
2001  }
2002 
2003  if (nearest.index != -1) {
2004  *dist_px = sqrtf(nearest.dist_sq);
2005 
2006  copy_v3_v3(r_loc, nearest.co);
2007  mul_m4_v3(obmat, r_loc);
2008 
2009  if (r_no) {
2010  float imat[4][4];
2011  invert_m4_m4(imat, obmat);
2012 
2013  copy_v3_v3(r_no, nearest.no);
2014  mul_transposed_mat3_m4_v3(imat, r_no);
2015  normalize_v3(r_no);
2016  }
2017 
2018  *r_index = nearest.index;
2019  return elem;
2020  }
2021 
2022  return SCE_SNAP_MODE_NONE;
2023 }
2024 
2026  const SnapObjectParams *params,
2027  Object *ob_eval,
2028  const float obmat[4][4],
2029  float original_dist_px,
2030  const float prev_co[3],
2031  /* read/write args */
2032  float *dist_px,
2033  /* return args */
2034  float r_loc[3],
2035  float r_no[3],
2036  int *r_index)
2037 {
2039 
2040  if (ob_eval->type != OB_MESH) {
2041  return elem;
2042  }
2043 
2044  Nearest2dUserData nearest2d;
2045  {
2046  std::unique_ptr<SnapData_Mesh> *sod_mesh = sctx->mesh_caches.lookup_ptr(ob_eval);
2047  if (sod_mesh) {
2048  nearest2d_data_init_mesh(sod_mesh->get(),
2050  params->use_backface_culling,
2051  &nearest2d);
2052  }
2053  else {
2054  /* The object's #BMEditMesh was used to snap instead. */
2055  std::unique_ptr<SnapData_EditMesh> &sod_editmesh = sctx->editmesh_caches.lookup(
2056  BKE_editmesh_from_object(ob_eval));
2057  nearest2d_data_init_editmesh(sod_editmesh.get(),
2059  params->use_backface_culling,
2060  &nearest2d);
2061  }
2062  }
2063 
2064  int vindex[2];
2065  nearest2d.get_edge_verts_index(*r_index, &nearest2d, vindex);
2066 
2067  const float *v_pair[2];
2068  nearest2d.get_vert_co(vindex[0], &nearest2d, &v_pair[0]);
2069  nearest2d.get_vert_co(vindex[1], &nearest2d, &v_pair[1]);
2070 
2071  DistProjectedAABBPrecalc neasrest_precalc;
2072  {
2073  float lpmat[4][4];
2074  mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat);
2075 
2077  &neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval);
2078  }
2079 
2080  BVHTreeNearest nearest{};
2081  nearest.index = -1;
2082  nearest.dist_sq = square_f(original_dist_px);
2083 
2084  float lambda;
2085  if (!isect_ray_line_v3(neasrest_precalc.ray_origin,
2086  neasrest_precalc.ray_direction,
2087  v_pair[0],
2088  v_pair[1],
2089  &lambda)) {
2090  /* do nothing */
2091  }
2092  else {
2093  short snap_to_flag = sctx->runtime.snap_to_flag;
2094  int e_mode_len = ((snap_to_flag & SCE_SNAP_MODE_EDGE) != 0) +
2095  ((snap_to_flag & SCE_SNAP_MODE_VERTEX) != 0) +
2096  ((snap_to_flag & SCE_SNAP_MODE_EDGE_MIDPOINT) != 0);
2097 
2098  float range = 1.0f / (2 * e_mode_len - 1);
2099  if (snap_to_flag & SCE_SNAP_MODE_VERTEX) {
2100  if (lambda < (range) || (1.0f - range) < lambda) {
2101  int v_id = lambda < 0.5f ? 0 : 1;
2102 
2103  if (test_projected_vert_dist(&neasrest_precalc,
2104  nullptr,
2105  0,
2106  nearest2d.is_persp,
2107  v_pair[v_id],
2108  &nearest.dist_sq,
2109  nearest.co)) {
2110  nearest.index = vindex[v_id];
2111  elem = SCE_SNAP_MODE_VERTEX;
2112  if (r_no) {
2113  float imat[4][4];
2114  invert_m4_m4(imat, obmat);
2115  nearest2d.copy_vert_no(vindex[v_id], &nearest2d, r_no);
2116  mul_transposed_mat3_m4_v3(imat, r_no);
2117  normalize_v3(r_no);
2118  }
2119  }
2120  }
2121  }
2122 
2123  if (snap_to_flag & SCE_SNAP_MODE_EDGE_MIDPOINT) {
2124  range *= e_mode_len - 1;
2125  if ((range) < lambda && lambda < (1.0f - range)) {
2126  float vmid[3];
2127  mid_v3_v3v3(vmid, v_pair[0], v_pair[1]);
2128 
2129  if (test_projected_vert_dist(&neasrest_precalc,
2130  nullptr,
2131  0,
2132  nearest2d.is_persp,
2133  vmid,
2134  &nearest.dist_sq,
2135  nearest.co)) {
2136  nearest.index = *r_index;
2138  }
2139  }
2140  }
2141 
2142  if (prev_co && (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
2143  float v_near[3], va_g[3], vb_g[3];
2144 
2145  mul_v3_m4v3(va_g, obmat, v_pair[0]);
2146  mul_v3_m4v3(vb_g, obmat, v_pair[1]);
2147  lambda = line_point_factor_v3(prev_co, va_g, vb_g);
2148 
2149  if (IN_RANGE(lambda, 0.0f, 1.0f)) {
2150  interp_v3_v3v3(v_near, va_g, vb_g, lambda);
2151 
2152  if (len_squared_v3v3(prev_co, v_near) > FLT_EPSILON) {
2154  &neasrest_precalc, sctx->runtime.pmat, sctx->runtime.win_size, sctx->runtime.mval);
2155 
2156  if (test_projected_vert_dist(&neasrest_precalc,
2157  nullptr,
2158  0,
2159  nearest2d.is_persp,
2160  v_near,
2161  &nearest.dist_sq,
2162  nearest.co)) {
2163  nearest.index = *r_index;
2165  }
2166  }
2167  }
2168  }
2169  }
2170 
2171  if (nearest.index != -1) {
2172  *dist_px = sqrtf(nearest.dist_sq);
2173 
2174  copy_v3_v3(r_loc, nearest.co);
2175  if (elem != SCE_SNAP_MODE_EDGE_PERPENDICULAR) {
2176  mul_m4_v3(obmat, r_loc);
2177  }
2178 
2179  *r_index = nearest.index;
2180  }
2181 
2182  return elem;
2183 }
2184 
2186  const SnapObjectParams *params,
2187  Object *ob_eval,
2188  const float obmat[4][4],
2189  bool is_object_active,
2190  /* read/write args */
2191  float *dist_px,
2192  /* return args */
2193  float r_loc[3],
2194  float *UNUSED(r_no),
2195  int *r_index)
2196 {
2197  eSnapMode retval = SCE_SNAP_MODE_NONE;
2198 
2200  /* Currently only edge and vert */
2201  return retval;
2202  }
2203 
2204  float lpmat[4][4], dist_px_sq = square_f(*dist_px);
2205  mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat);
2206 
2207  DistProjectedAABBPrecalc neasrest_precalc;
2209  &neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval);
2210 
2211  bArmature *arm = static_cast<bArmature *>(ob_eval->data);
2212  const bool is_editmode = arm->edbo != nullptr;
2213 
2214  if (is_editmode == false) {
2215  /* Test BoundBox */
2216  const BoundBox *bb = BKE_armature_boundbox_get(ob_eval);
2217  if (bb && !snap_bound_box_check_dist(bb->vec[0],
2218  bb->vec[6],
2219  lpmat,
2220  sctx->runtime.win_size,
2221  sctx->runtime.mval,
2222  dist_px_sq)) {
2223  return retval;
2224  }
2225  }
2226 
2227  float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
2228  transpose_m4_m4(tobmat, obmat);
2229  for (int i = sctx->runtime.clip_plane_len; i--;) {
2230  mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]);
2231  }
2232 
2233  const bool is_posemode = is_object_active && (ob_eval->mode & OB_MODE_POSE);
2234  const bool skip_selected = (is_editmode || is_posemode) &&
2235  (params->snap_target_select & SCE_SNAP_TARGET_NOT_SELECTED);
2236  const bool is_persp = sctx->runtime.view_proj == VIEW_PROJ_PERSP;
2237 
2238  if (arm->edbo) {
2239  LISTBASE_FOREACH (EditBone *, eBone, arm->edbo) {
2240  if (eBone->layer & arm->layer) {
2241  if (eBone->flag & BONE_HIDDEN_A) {
2242  /* Skip hidden bones. */
2243  continue;
2244  }
2245 
2246  const bool is_selected = (eBone->flag & (BONE_ROOTSEL | BONE_TIPSEL)) != 0;
2247  if (is_selected && skip_selected) {
2248  continue;
2249  }
2250  bool has_vert_snap = false;
2251 
2253  has_vert_snap = test_projected_vert_dist(&neasrest_precalc,
2254  clip_planes_local,
2255  sctx->runtime.clip_plane_len,
2256  is_persp,
2257  eBone->head,
2258  &dist_px_sq,
2259  r_loc);
2260  has_vert_snap |= test_projected_vert_dist(&neasrest_precalc,
2261  clip_planes_local,
2262  sctx->runtime.clip_plane_len,
2263  is_persp,
2264  eBone->tail,
2265 
2266  &dist_px_sq,
2267  r_loc);
2268 
2269  if (has_vert_snap) {
2270  retval = SCE_SNAP_MODE_VERTEX;
2271  }
2272  }
2273  if (!has_vert_snap && sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) {
2274  if (test_projected_edge_dist(&neasrest_precalc,
2275  clip_planes_local,
2276  sctx->runtime.clip_plane_len,
2277  is_persp,
2278  eBone->head,
2279  eBone->tail,
2280  &dist_px_sq,
2281  r_loc)) {
2282  retval = SCE_SNAP_MODE_EDGE;
2283  }
2284  }
2285  }
2286  }
2287  }
2288  else if (ob_eval->pose && ob_eval->pose->chanbase.first) {
2289  LISTBASE_FOREACH (bPoseChannel *, pchan, &ob_eval->pose->chanbase) {
2290  Bone *bone = pchan->bone;
2291  if (!bone || (bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
2292  /* Skip hidden bones. */
2293  continue;
2294  }
2295 
2296  const bool is_selected = (bone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) != 0;
2297  if (is_selected && skip_selected) {
2298  continue;
2299  }
2300 
2301  bool has_vert_snap = false;
2302  const float *head_vec = pchan->pose_head;
2303  const float *tail_vec = pchan->pose_tail;
2304 
2306  has_vert_snap = test_projected_vert_dist(&neasrest_precalc,
2307  clip_planes_local,
2308  sctx->runtime.clip_plane_len,
2309  is_persp,
2310  head_vec,
2311  &dist_px_sq,
2312  r_loc);
2313  has_vert_snap |= test_projected_vert_dist(&neasrest_precalc,
2314  clip_planes_local,
2315  sctx->runtime.clip_plane_len,
2316  is_persp,
2317  tail_vec,
2318  &dist_px_sq,
2319  r_loc);
2320 
2321  if (has_vert_snap) {
2322  retval = SCE_SNAP_MODE_VERTEX;
2323  }
2324  }
2325  if (!has_vert_snap && sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) {
2326  if (test_projected_edge_dist(&neasrest_precalc,
2327  clip_planes_local,
2328  sctx->runtime.clip_plane_len,
2329  is_persp,
2330  head_vec,
2331  tail_vec,
2332  &dist_px_sq,
2333  r_loc)) {
2334  retval = SCE_SNAP_MODE_EDGE;
2335  }
2336  }
2337  }
2338  }
2339 
2340  if (retval) {
2341  *dist_px = sqrtf(dist_px_sq);
2342  mul_m4_v3(obmat, r_loc);
2343  if (r_index) {
2344  /* Does not support index. */
2345  *r_index = -1;
2346  }
2347  return retval;
2348  }
2349 
2350  return SCE_SNAP_MODE_NONE;
2351 }
2352 
2354  const SnapObjectParams *params,
2355  Object *ob_eval,
2356  const float obmat[4][4],
2357  /* read/write args */
2358  float *dist_px,
2359  /* return args */
2360  float r_loc[3],
2361  float *UNUSED(r_no),
2362  int *r_index)
2363 {
2364  bool has_snap = false;
2365 
2366  /* only vertex snapping mode (eg control points and handles) supported for now) */
2367  if ((sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) == 0) {
2368  return SCE_SNAP_MODE_NONE;
2369  }
2370 
2371  Curve *cu = static_cast<Curve *>(ob_eval->data);
2372  float dist_px_sq = square_f(*dist_px);
2373 
2374  float lpmat[4][4];
2375  mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat);
2376 
2377  DistProjectedAABBPrecalc neasrest_precalc;
2379  &neasrest_precalc, lpmat, sctx->runtime.win_size, sctx->runtime.mval);
2380 
2381  const bool use_obedit = BKE_object_is_in_editmode(ob_eval);
2382 
2383  if (use_obedit == false) {
2384  /* Test BoundBox */
2385  BoundBox *bb = BKE_curve_boundbox_get(ob_eval);
2386  if (bb && !snap_bound_box_check_dist(bb->vec[0],
2387  bb->vec[6],
2388  lpmat,
2389  sctx->runtime.win_size,
2390  sctx->runtime.mval,
2391  dist_px_sq)) {
2392  return SCE_SNAP_MODE_NONE;
2393  }
2394  }
2395 
2396  float tobmat[4][4];
2397  transpose_m4_m4(tobmat, obmat);
2398 
2399  float(*clip_planes)[4] = sctx->runtime.clip_plane;
2400  int clip_plane_len = sctx->runtime.clip_plane_len;
2401 
2402  if (sctx->runtime.has_occlusion_plane) {
2403  /* We snap to vertices even if occluded. */
2404  clip_planes++;
2405  clip_plane_len--;
2406  }
2407 
2408  float clip_planes_local[MAX_CLIPPLANE_LEN][4];
2409  for (int i = clip_plane_len; i--;) {
2410  mul_v4_m4v4(clip_planes_local[i], tobmat, clip_planes[i]);
2411  }
2412 
2413  bool is_persp = sctx->runtime.view_proj == VIEW_PROJ_PERSP;
2414  bool skip_selected = params->snap_target_select & SCE_SNAP_TARGET_NOT_SELECTED;
2415 
2416  LISTBASE_FOREACH (Nurb *, nu, (use_obedit ? &cu->editnurb->nurbs : &cu->nurb)) {
2417  for (int u = 0; u < nu->pntsu; u++) {
2419  if (use_obedit) {
2420  if (nu->bezt) {
2421  if (nu->bezt[u].hide) {
2422  /* Skip hidden. */
2423  continue;
2424  }
2425 
2426  bool is_selected = (nu->bezt[u].f2 & SELECT) != 0;
2427  if (is_selected && skip_selected) {
2428  continue;
2429  }
2430  has_snap |= test_projected_vert_dist(&neasrest_precalc,
2431  clip_planes_local,
2432  clip_plane_len,
2433  is_persp,
2434  nu->bezt[u].vec[1],
2435  &dist_px_sq,
2436  r_loc);
2437 
2438  /* Don't snap if handle is selected (moving),
2439  * or if it is aligning to a moving handle. */
2440  bool is_selected_h1 = (nu->bezt[u].f1 & SELECT) != 0;
2441  bool is_selected_h2 = (nu->bezt[u].f3 & SELECT) != 0;
2442  bool is_autoalign_h1 = (nu->bezt[u].h1 & HD_ALIGN) != 0;
2443  bool is_autoalign_h2 = (nu->bezt[u].h2 & HD_ALIGN) != 0;
2444  if (!skip_selected || !(is_selected_h1 || (is_autoalign_h1 && is_selected_h2))) {
2445  has_snap |= test_projected_vert_dist(&neasrest_precalc,
2446  clip_planes_local,
2447  clip_plane_len,
2448  is_persp,
2449  nu->bezt[u].vec[0],
2450  &dist_px_sq,
2451  r_loc);
2452  }
2453 
2454  if (!skip_selected || !(is_selected_h2 || (is_autoalign_h2 && is_selected_h1))) {
2455  has_snap |= test_projected_vert_dist(&neasrest_precalc,
2456  clip_planes_local,
2457  clip_plane_len,
2458  is_persp,
2459  nu->bezt[u].vec[2],
2460  &dist_px_sq,
2461  r_loc);
2462  }
2463  }
2464  else {
2465  if (nu->bp[u].hide) {
2466  /* Skip hidden. */
2467  continue;
2468  }
2469 
2470  bool is_selected = (nu->bp[u].f1 & SELECT) != 0;
2471  if (is_selected && skip_selected) {
2472  continue;
2473  }
2474 
2475  has_snap |= test_projected_vert_dist(&neasrest_precalc,
2476  clip_planes_local,
2477  clip_plane_len,
2478  is_persp,
2479  nu->bp[u].vec,
2480  &dist_px_sq,
2481  r_loc);
2482  }
2483  }
2484  else {
2485  /* curve is not visible outside editmode if nurb length less than two */
2486  if (nu->pntsu > 1) {
2487  if (nu->bezt) {
2488  has_snap |= test_projected_vert_dist(&neasrest_precalc,
2489  clip_planes_local,
2490  clip_plane_len,
2491  is_persp,
2492  nu->bezt[u].vec[1],
2493  &dist_px_sq,
2494  r_loc);
2495  }
2496  else {
2497  has_snap |= test_projected_vert_dist(&neasrest_precalc,
2498  clip_planes_local,
2499  clip_plane_len,
2500  is_persp,
2501  nu->bp[u].vec,
2502  &dist_px_sq,
2503  r_loc);
2504  }
2505  }
2506  }
2507  }
2508  }
2509  }
2510  if (has_snap) {
2511  *dist_px = sqrtf(dist_px_sq);
2512  mul_m4_v3(obmat, r_loc);
2513  if (r_index) {
2514  /* Does not support index yet. */
2515  *r_index = -1;
2516  }
2517  return SCE_SNAP_MODE_VERTEX;
2518  }
2519 
2520  return SCE_SNAP_MODE_NONE;
2521 }
2522 
2523 /* may extend later (for now just snaps to empty center) */
2525  Object *ob_eval,
2526  const float obmat[4][4],
2527  /* read/write args */
2528  float *dist_px,
2529  /* return args */
2530  float r_loc[3],
2531  float *UNUSED(r_no),
2532  int *r_index)
2533 {
2534  eSnapMode retval = SCE_SNAP_MODE_NONE;
2535 
2536  if (ob_eval->transflag & OB_DUPLI) {
2537  return retval;
2538  }
2539 
2540  /* for now only vertex supported */
2541  if ((sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) == 0) {
2542  return retval;
2543  }
2544 
2545  DistProjectedAABBPrecalc neasrest_precalc;
2547  &neasrest_precalc, sctx->runtime.pmat, sctx->runtime.win_size, sctx->runtime.mval);
2548 
2549  bool is_persp = sctx->runtime.view_proj == VIEW_PROJ_PERSP;
2550  float dist_px_sq = square_f(*dist_px);
2551 
2552  if (test_projected_vert_dist(&neasrest_precalc,
2553  sctx->runtime.clip_plane,
2554  sctx->runtime.clip_plane_len,
2555  is_persp,
2556  obmat[3],
2557  &dist_px_sq,
2558  r_loc)) {
2559  *dist_px = sqrtf(dist_px_sq);
2560  retval = SCE_SNAP_MODE_VERTEX;
2561  }
2562 
2563  if (retval) {
2564  if (r_index) {
2565  /* Does not support index. */
2566  *r_index = -1;
2567  }
2568  return retval;
2569  }
2570 
2571  return SCE_SNAP_MODE_NONE;
2572 }
2573 
2575  Object *object,
2576  const float obmat[4][4],
2577  /* read/write args */
2578  float *dist_px,
2579  /* return args */
2580  float r_loc[3],
2581  float *r_no,
2582  int *r_index)
2583 {
2584  eSnapMode retval = SCE_SNAP_MODE_NONE;
2585 
2586  Scene *scene = sctx->scene;
2587 
2588  bool is_persp = sctx->runtime.view_proj == VIEW_PROJ_PERSP;
2589  float dist_px_sq = square_f(*dist_px);
2590 
2591  float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
2592  MovieClip *clip = BKE_object_movieclip_get(scene, object, false);
2593  MovieTracking *tracking;
2594 
2595  if (clip == nullptr) {
2596  return snap_object_center(sctx, object, obmat, dist_px, r_loc, r_no, r_index);
2597  }
2598  if (object->transflag & OB_DUPLI) {
2599  return retval;
2600  }
2601 
2602  tracking = &clip->tracking;
2603 
2604  BKE_tracking_get_camera_object_matrix(object, orig_camera_mat);
2605 
2606  invert_m4_m4(orig_camera_imat, orig_camera_mat);
2607  invert_m4_m4(imat, obmat);
2608 
2610  DistProjectedAABBPrecalc neasrest_precalc;
2612  &neasrest_precalc, sctx->runtime.pmat, sctx->runtime.win_size, sctx->runtime.mval);
2613 
2614  LISTBASE_FOREACH (MovieTrackingObject *, tracking_object, &tracking->objects) {
2615  ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
2616  float reconstructed_camera_mat[4][4], reconstructed_camera_imat[4][4];
2617  const float(*vertex_obmat)[4];
2618 
2619  if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
2621  tracking, tracking_object, scene->r.cfra, reconstructed_camera_mat);
2622 
2623  invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat);
2624  }
2625 
2626  LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
2627  float bundle_pos[3];
2628 
2629  if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
2630  continue;
2631  }
2632 
2633  copy_v3_v3(bundle_pos, track->bundle_pos);
2634  if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
2635  vertex_obmat = orig_camera_mat;
2636  }
2637  else {
2638  mul_m4_v3(reconstructed_camera_imat, bundle_pos);
2639  vertex_obmat = obmat;
2640  }
2641 
2642  mul_m4_v3(vertex_obmat, bundle_pos);
2643  if (test_projected_vert_dist(&neasrest_precalc,
2644  sctx->runtime.clip_plane,
2645  sctx->runtime.clip_plane_len,
2646  is_persp,
2647  bundle_pos,
2648  &dist_px_sq,
2649  r_loc)) {
2650  retval = SCE_SNAP_MODE_VERTEX;
2651  }
2652  }
2653  }
2654  }
2655 
2656  if (retval) {
2657  *dist_px = sqrtf(dist_px_sq);
2658  if (r_index) {
2659  /* Does not support index. */
2660  *r_index = -1;
2661  }
2662  return retval;
2663  }
2664 
2665  return SCE_SNAP_MODE_NONE;
2666 }
2667 
2669  const SnapObjectParams *params,
2670  Object *ob_eval,
2671  const Mesh *me_eval,
2672  const float obmat[4][4],
2673  bool use_hide,
2674  /* read/write args */
2675  float *dist_px,
2676  /* return args */
2677  float r_loc[3],
2678  float r_no[3],
2679  int *r_index)
2680 {
2682  if (me_eval->totvert == 0) {
2683  return SCE_SNAP_MODE_NONE;
2684  }
2685  if (me_eval->totedge == 0 && !(sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
2686  return SCE_SNAP_MODE_NONE;
2687  }
2688 
2689  float lpmat[4][4];
2690  mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat);
2691 
2692  float dist_px_sq = square_f(*dist_px);
2693 
2694  /* Test BoundBox */
2695  const BoundBox *bb = BKE_object_boundbox_get(ob_eval);
2696  if (bb &&
2698  bb->vec[0], bb->vec[6], lpmat, sctx->runtime.win_size, sctx->runtime.mval, dist_px_sq)) {
2699  return SCE_SNAP_MODE_NONE;
2700  }
2701 
2702  SnapData_Mesh *sod = snap_object_data_mesh_get(sctx, ob_eval, me_eval, use_hide);
2703 
2704  BVHTreeFromMesh *treedata, treedata_tmp;
2705  treedata = &sod->treedata_mesh;
2706 
2707  if (sod->has_loose_edge && sod->bvhtree[0] == nullptr) {
2709  &treedata_tmp, me_eval, BVHTREE_FROM_LOOSEEDGES, 2);
2710  if (sod->bvhtree[0] == nullptr) {
2711  sod->has_loose_edge = false;
2712  }
2713  sod->cached[0] = treedata_tmp.cached;
2714  }
2715 
2717  if (sod->has_loose_vert && sod->bvhtree[1] == nullptr) {
2719  &treedata_tmp, me_eval, BVHTREE_FROM_LOOSEVERTS, 2);
2720  if (sod->bvhtree[1] == nullptr) {
2721  sod->has_loose_vert = false;
2722  }
2723  sod->cached[1] = treedata_tmp.cached;
2724  }
2725  }
2726  else {
2727  /* Not necessary, just to keep the data more consistent. */
2728  sod->has_loose_vert = false;
2729  }
2730 
2731  Nearest2dUserData nearest2d;
2733  sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d);
2734 
2735  BVHTreeNearest nearest{};
2736  nearest.index = -1;
2737  nearest.dist_sq = dist_px_sq;
2738 
2739  int last_index = nearest.index;
2741 
2742  float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
2743  transpose_m4_m4(tobmat, obmat);
2744  for (int i = sctx->runtime.clip_plane_len; i--;) {
2745  mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]);
2746  }
2747 
2748  if (sod->bvhtree[1] && (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
2749  /* snap to loose verts */
2751  lpmat,
2752  sctx->runtime.win_size,
2753  sctx->runtime.mval,
2754  clip_planes_local,
2755  sctx->runtime.clip_plane_len,
2756  &nearest,
2757  cb_snap_vert,
2758  &nearest2d);
2759 
2760  last_index = nearest.index;
2761  }
2762 
2763  if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) {
2764  if (sod->bvhtree[0]) {
2765  /* snap to loose edges */
2767  lpmat,
2768  sctx->runtime.win_size,
2769  sctx->runtime.mval,
2770  clip_planes_local,
2771  sctx->runtime.clip_plane_len,
2772  &nearest,
2773  cb_snap_edge,
2774  &nearest2d);
2775  }
2776 
2777  if (treedata->tree) {
2778  /* snap to looptris */
2780  lpmat,
2781  sctx->runtime.win_size,
2782  sctx->runtime.mval,
2783  clip_planes_local,
2784  sctx->runtime.clip_plane_len,
2785  &nearest,
2787  &nearest2d);
2788  }
2789 
2790  if (last_index != nearest.index) {
2791  elem = SCE_SNAP_MODE_EDGE;
2792  }
2793  }
2794  else {
2796  if (sod->bvhtree[0]) {
2797  /* snap to loose edge verts */
2799  lpmat,
2800  sctx->runtime.win_size,
2801  sctx->runtime.mval,
2802  clip_planes_local,
2803  sctx->runtime.clip_plane_len,
2804  &nearest,
2806  &nearest2d);
2807  }
2808 
2809  if (treedata->tree) {
2810  /* snap to looptri verts */
2812  lpmat,
2813  sctx->runtime.win_size,
2814  sctx->runtime.mval,
2815  clip_planes_local,
2816  sctx->runtime.clip_plane_len,
2817  &nearest,
2819  &nearest2d);
2820  }
2821  }
2822 
2823  if (nearest.index != -1) {
2824  *dist_px = sqrtf(nearest.dist_sq);
2825 
2826  copy_v3_v3(r_loc, nearest.co);
2827  mul_m4_v3(obmat, r_loc);
2828 
2829  if (r_no) {
2830  float imat[4][4];
2831  invert_m4_m4(imat, obmat);
2832 
2833  copy_v3_v3(r_no, nearest.no);
2834  mul_transposed_mat3_m4_v3(imat, r_no);
2835  normalize_v3(r_no);
2836  }
2837  if (r_index) {
2838  *r_index = nearest.index;
2839  }
2840 
2841  return elem;
2842  }
2843 
2844  return SCE_SNAP_MODE_NONE;
2845 }
2846 
2848  const SnapObjectParams *params,
2849  Object *ob_eval,
2850  BMEditMesh *em,
2851  const float obmat[4][4],
2852  /* read/write args */
2853  float *dist_px,
2854  /* return args */
2855  float r_loc[3],
2856  float r_no[3],
2857  int *r_index)
2858 {
2860 
2862  if (em->bm->totvert == 0) {
2863  return SCE_SNAP_MODE_NONE;
2864  }
2865  }
2866  else {
2867  if (em->bm->totedge == 0) {
2868  return SCE_SNAP_MODE_NONE;
2869  }
2870  }
2871 
2872  float lpmat[4][4];
2873  mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat);
2874 
2875  float dist_px_sq = square_f(*dist_px);
2876 
2877  SnapData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob_eval, em);
2878 
2879  /* Test BoundBox */
2880 
2881  /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
2883  sod->min, sod->max, lpmat, sctx->runtime.win_size, sctx->runtime.mval, dist_px_sq)) {
2884  return SCE_SNAP_MODE_NONE;
2885  }
2886 
2888  BVHTreeFromEditMesh treedata{};
2889  treedata.tree = sod->bvhtree[0];
2890 
2891  if (treedata.tree == nullptr) {
2892  BLI_bitmap *verts_mask = nullptr;
2893  int verts_num_active = -1;
2894  if (sctx->callbacks.edit_mesh.test_vert_fn) {
2895  verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
2896  verts_num_active = BM_iter_mesh_bitmap_from_filter(
2898  em->bm,
2899  verts_mask,
2900  (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
2901  sctx->callbacks.edit_mesh.user_data);
2902 
2903  bvhtree_from_editmesh_verts_ex(&treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6);
2904  MEM_freeN(verts_mask);
2905  }
2906  else {
2908  em,
2909  2,
2911  &sod->mesh_runtime->bvh_cache,
2913  }
2914  sod->bvhtree[0] = treedata.tree;
2915  sod->cached[0] = treedata.cached;
2916  }
2917  }
2918 
2919  if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) {
2920  BVHTreeFromEditMesh treedata{};
2921  treedata.tree = sod->bvhtree[1];
2922 
2923  if (treedata.tree == nullptr) {
2924  BLI_bitmap *edges_mask = nullptr;
2925  int edges_num_active = -1;
2926  if (sctx->callbacks.edit_mesh.test_edge_fn) {
2927  edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
2928  edges_num_active = BM_iter_mesh_bitmap_from_filter(
2930  em->bm,
2931  edges_mask,
2932  (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
2933  sctx->callbacks.edit_mesh.user_data);
2934 
2935  bvhtree_from_editmesh_edges_ex(&treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6);
2936  MEM_freeN(edges_mask);
2937  }
2938  else {
2940  em,
2941  2,
2943  &sod->mesh_runtime->bvh_cache,
2944  static_cast<ThreadMutex *>(sod->mesh_runtime->eval_mutex));
2945  }
2946  sod->bvhtree[1] = treedata.tree;
2947  sod->cached[1] = treedata.cached;
2948  }
2949  }
2950 
2951  Nearest2dUserData nearest2d;
2953  sod, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d);
2954 
2955  BVHTreeNearest nearest{};
2956  nearest.index = -1;
2957  nearest.dist_sq = dist_px_sq;
2958 
2960 
2961  float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
2962  transpose_m4_m4(tobmat, obmat);
2963 
2964  for (int i = sctx->runtime.clip_plane_len; i--;) {
2965  mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]);
2966  }
2967 
2968  if (sod->bvhtree[0] && (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
2972  lpmat,
2973  sctx->runtime.win_size,
2974  sctx->runtime.mval,
2975  clip_planes_local,
2976  sctx->runtime.clip_plane_len,
2977  &nearest,
2978  cb_snap_vert,
2979  &nearest2d);
2980  }
2981 
2982  if (sod->bvhtree[1] && (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE)) {
2983  int last_index = nearest.index;
2984  nearest.index = -1;
2988  lpmat,
2989  sctx->runtime.win_size,
2990  sctx->runtime.mval,
2991  clip_planes_local,
2992  sctx->runtime.clip_plane_len,
2993  &nearest,
2994  cb_snap_edge,
2995  &nearest2d);
2996 
2997  if (nearest.index != -1) {
2998  elem = SCE_SNAP_MODE_EDGE;
2999  }
3000  else {
3001  nearest.index = last_index;
3002  }
3003  }
3004 
3005  if (nearest.index != -1) {
3006  *dist_px = sqrtf(nearest.dist_sq);
3007 
3008  copy_v3_v3(r_loc, nearest.co);
3009  mul_m4_v3(obmat, r_loc);
3010  if (r_no) {
3011  float imat[4][4];
3012  invert_m4_m4(imat, obmat);
3013 
3014  copy_v3_v3(r_no, nearest.no);
3015  mul_transposed_mat3_m4_v3(imat, r_no);
3016  normalize_v3(r_no);
3017  }
3018  if (r_index) {
3019  *r_index = nearest.index;
3020  }
3021 
3022  return elem;
3023  }
3024 
3025  return SCE_SNAP_MODE_NONE;
3026 }
3027 
3029  /* read/write args */
3030  float *dist_px;
3031  /* return args */
3032  float *r_loc;
3033  float *r_no;
3034  int *r_index;
3038 };
3039 
3043 static void snap_obj_fn(SnapObjectContext *sctx,
3044  const SnapObjectParams *params,
3045  Object *ob_eval,
3046  const float obmat[4][4],
3047  bool is_object_active,
3048  void *data)
3049 {
3050  SnapObjUserData *dt = static_cast<SnapObjUserData *>(data);
3051  eSnapMode retval = SCE_SNAP_MODE_NONE;
3052 
3053  switch (ob_eval->type) {
3054  case OB_MESH: {
3055  const eSnapEditType edit_mode_type = params->edit_mode_type;
3056  bool use_hide;
3057  const Mesh *me_eval = mesh_for_snap(ob_eval, edit_mode_type, &use_hide);
3058  if (me_eval == nullptr) {
3059  BMEditMesh *em = BKE_editmesh_from_object(ob_eval);
3060  if (UNLIKELY(!em)) { /* See #mesh_for_snap doc-string. */
3061  return;
3062  }
3064  "Make sure there is only one pointer for looptris");
3065  retval = snapEditMesh(
3066  sctx, params, ob_eval, em, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
3067  break;
3068  }
3069  if (ob_eval->dt == OB_BOUNDBOX) {
3070  /* Do not snap to objects that are in bounding box display mode */
3071  return;
3072  }
3073 
3074  retval = snapMesh(sctx,
3075  params,
3076  ob_eval,
3077  me_eval,
3078  obmat,
3079  use_hide,
3080  dt->dist_px,
3081  dt->r_loc,
3082  dt->r_no,
3083  dt->r_index);
3084  break;
3085  }
3086  case OB_ARMATURE:
3087  retval = snapArmature(sctx,
3088  params,
3089  ob_eval,
3090  obmat,
3091  is_object_active,
3092  dt->dist_px,
3093  dt->r_loc,
3094  dt->r_no,
3095  dt->r_index);
3096  break;
3097  case OB_CURVES_LEGACY:
3098  case OB_SURF:
3099  if (ob_eval->type == OB_CURVES_LEGACY || BKE_object_is_in_editmode(ob_eval)) {
3100  retval = snapCurve(
3101  sctx, params, ob_eval, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
3102  if (params->edit_mode_type != SNAP_GEOM_FINAL) {
3103  break;
3104  }
3105  }
3107  case OB_FONT: {
3108  const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
3109  if (mesh_eval) {
3110  retval |= snapMesh(sctx,
3111  params,
3112  ob_eval,
3113  mesh_eval,
3114  obmat,
3115  false,
3116  dt->dist_px,
3117  dt->r_loc,
3118  dt->r_no,
3119  dt->r_index);
3120  }
3121  break;
3122  }
3123  case OB_EMPTY:
3124  case OB_GPENCIL:
3125  case OB_LAMP:
3126  retval = snap_object_center(
3127  sctx, ob_eval, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
3128  break;
3129  case OB_CAMERA:
3130  retval = snapCamera(sctx, ob_eval, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
3131  break;
3132  }
3133 
3134  if (retval) {
3135  if (dt->r_ob) {
3136  *dt->r_ob = ob_eval;
3137  }
3138  if (dt->r_obmat) {
3139  copy_m4_m4(dt->r_obmat, obmat);
3140  }
3141  dt->ret = retval;
3142  }
3143 }
3144 
3169  const SnapObjectParams *params,
3170  /* read/write args */
3171  /* Parameters below cannot be const, because they are assigned to a
3172  * non-const variable (readability-non-const-parameter). */
3173  float *dist_px /* NOLINT */,
3174  /* return args */
3175  float r_loc[3] /* NOLINT */,
3176  float r_no[3] /* NOLINT */,
3177  int *r_index /* NOLINT */,
3178  Object **r_ob,
3179  float r_obmat[4][4])
3180 {
3181  SnapObjUserData data = {};
3182  data.dist_px = dist_px;
3183  data.r_loc = r_loc;
3184  data.r_no = r_no;
3185  data.r_ob = r_ob;
3186  data.r_index = r_index;
3187  data.r_obmat = r_obmat;
3188  data.ret = SCE_SNAP_MODE_NONE;
3189 
3191 
3192  return data.ret;
3193 }
3194 
3197 /* -------------------------------------------------------------------- */
3202 {
3203  SnapObjectContext *sctx = MEM_new<SnapObjectContext>(__func__);
3204 
3205  sctx->flag = flag;
3206 
3207  sctx->scene = scene;
3208 
3209  return sctx;
3210 }
3211 
3213 {
3214  MEM_delete(sctx);
3215 }
3216 
3218  SnapObjectContext *sctx,
3219  bool (*test_vert_fn)(BMVert *, void *user_data),
3220  bool (*test_edge_fn)(BMEdge *, void *user_data),
3221  bool (*test_face_fn)(BMFace *, void *user_data),
3222  void *user_data)
3223 {
3224  sctx->callbacks.edit_mesh.test_vert_fn = test_vert_fn;
3225  sctx->callbacks.edit_mesh.test_edge_fn = test_edge_fn;
3226  sctx->callbacks.edit_mesh.test_face_fn = test_face_fn;
3227 
3228  sctx->callbacks.edit_mesh.user_data = user_data;
3229 }
3230 
3233  const View3D *v3d,
3234  const SnapObjectParams *params,
3235  const float ray_start[3],
3236  const float ray_normal[3],
3237  float *ray_depth,
3238  float r_loc[3],
3239  float r_no[3],
3240  int *r_index,
3241  Object **r_ob,
3242  float r_obmat[4][4])
3243 {
3244  sctx->runtime.depsgraph = depsgraph;
3245  sctx->runtime.v3d = v3d;
3246 
3247  return raycastObjects(sctx,
3248  params,
3249  ray_start,
3250  ray_normal,
3251  ray_depth,
3252  r_loc,
3253  r_no,
3254  r_index,
3255  r_ob,
3256  r_obmat,
3257  nullptr);
3258 }
3259 
3262  const View3D *v3d,
3263  const SnapObjectParams *params,
3264  const float ray_start[3],
3265  const float ray_normal[3],
3266  float ray_depth,
3267  bool sort,
3268  ListBase *r_hit_list)
3269 {
3270  sctx->runtime.depsgraph = depsgraph;
3271  sctx->runtime.v3d = v3d;
3272 
3273  if (ray_depth == -1.0f) {
3274  ray_depth = BVH_RAYCAST_DIST_MAX;
3275  }
3276 
3277 #ifdef DEBUG
3278  float ray_depth_prev = ray_depth;
3279 #endif
3280 
3281  bool retval = raycastObjects(sctx,
3282  params,
3283  ray_start,
3284  ray_normal,
3285  &ray_depth,
3286  nullptr,
3287  nullptr,
3288  nullptr,
3289  nullptr,
3290  nullptr,
3291  r_hit_list);
3292 
3293  /* meant to be readonly for 'all' hits, ensure it is */
3294 #ifdef DEBUG
3295  BLI_assert(ray_depth_prev == ray_depth);
3296 #endif
3297 
3298  if (sort) {
3299  BLI_listbase_sort(r_hit_list, hit_depth_cmp);
3300  }
3301 
3302  return retval;
3303 }
3304 
3314  const View3D *v3d,
3315  const SnapObjectParams *params,
3316  const float ray_start[3],
3317  const float ray_normal[3],
3318  float *ray_depth,
3319  float r_co[3],
3320  float r_no[3])
3321 {
3322  bool ret;
3323 
3324  /* try snap edge, then face if it fails */
3326  depsgraph,
3327  v3d,
3328  params,
3329  ray_start,
3330  ray_normal,
3331  ray_depth,
3332  r_co,
3333  r_no,
3334  nullptr,
3335  nullptr,
3336  nullptr);
3337 
3338  return ret;
3339 }
3340 
3343  const View3D *v3d,
3344  const SnapObjectParams *params,
3345  const float ray_origin[3],
3346  const float ray_direction[3],
3347  float *ray_depth,
3348  float r_co[3],
3349  float r_no[3])
3350 {
3351  float ray_depth_fallback;
3352  if (ray_depth == nullptr) {
3353  ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
3354  ray_depth = &ray_depth_fallback;
3355  }
3356 
3358  sctx, depsgraph, v3d, params, ray_origin, ray_direction, ray_depth, r_co, r_no);
3359 }
3360 
3363  const ARegion *region,
3364  const View3D *v3d,
3365  const eSnapMode snap_to_flag,
3366  const SnapObjectParams *params,
3367  const float init_co[3],
3368  const float mval[2],
3369  const float prev_co[3],
3370  float *dist_px,
3371  float r_loc[3],
3372  float r_no[3],
3373  int *r_index,
3374  Object **r_ob,
3375  float r_obmat[4][4],
3376  float r_face_nor[3])
3377 {
3378  sctx->runtime.depsgraph = depsgraph;
3379  sctx->runtime.region = region;
3380  sctx->runtime.v3d = v3d;
3381 
3382  BLI_assert((snap_to_flag & SCE_SNAP_MODE_GEOM) != 0);
3383 
3384  eSnapMode retval = SCE_SNAP_MODE_NONE;
3385 
3386  bool has_hit = false;
3387  Object *ob_eval = nullptr;
3388  float loc[3];
3389  /* Not all snapping callbacks set the normal,
3390  * initialize this since any hit copies both the `loc` and `no`. */
3391  float no[3] = {0.0f, 0.0f, 0.0f};
3392  float obmat[4][4];
3393  int index = -1;
3394 
3395  const RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
3396 
3397  bool use_occlusion_test = params->use_occlusion_test && !XRAY_ENABLED(v3d);
3398 
3399  /* Note: if both face raycast and face nearest are enabled, first find result of nearest, then
3400  * override with raycast. */
3401  if ((snap_to_flag & SCE_SNAP_MODE_FACE_NEAREST) && !has_hit) {
3402  has_hit = nearestWorldObjects(
3403  sctx, params, init_co, prev_co, loc, no, &index, &ob_eval, obmat);
3404 
3405  if (has_hit) {
3406  retval = SCE_SNAP_MODE_FACE_NEAREST;
3407 
3408  copy_v3_v3(r_loc, loc);
3409  if (r_no) {
3410  copy_v3_v3(r_no, no);
3411  }
3412  if (r_ob) {
3413  *r_ob = ob_eval;
3414  }
3415  if (r_obmat) {
3416  copy_m4_m4(r_obmat, obmat);
3417  }
3418  if (r_index) {
3419  *r_index = index;
3420  }
3421  }
3422  }
3423 
3424  if (snap_to_flag & SCE_SNAP_MODE_FACE_RAYCAST || use_occlusion_test) {
3425  float ray_start[3], ray_normal[3];
3427  depsgraph, region, v3d, mval, nullptr, ray_normal, ray_start, true)) {
3428  return retval;
3429  }
3430 
3431  float dummy_ray_depth = BVH_RAYCAST_DIST_MAX;
3432 
3433  has_hit = raycastObjects(sctx,
3434  params,
3435  ray_start,
3436  ray_normal,
3437  &dummy_ray_depth,
3438  loc,
3439  no,
3440  &index,
3441  &ob_eval,
3442  obmat,
3443  nullptr);
3444 
3445  if (has_hit) {
3446  if (r_face_nor) {
3447  copy_v3_v3(r_face_nor, no);
3448  }
3449 
3450  if ((snap_to_flag & SCE_SNAP_MODE_FACE_RAYCAST)) {
3451  retval = SCE_SNAP_MODE_FACE_RAYCAST;
3452 
3453  copy_v3_v3(r_loc, loc);
3454  if (r_no) {
3455  copy_v3_v3(r_no, no);
3456  }
3457  if (r_ob) {
3458  *r_ob = ob_eval;
3459  }
3460  if (r_obmat) {
3461  copy_m4_m4(r_obmat, obmat);
3462  }
3463  if (r_index) {
3464  *r_index = index;
3465  }
3466  }
3467  }
3468  }
3469 
3472  eSnapMode elem_test, elem = SCE_SNAP_MODE_NONE;
3473  float dist_px_tmp = *dist_px;
3474 
3475  copy_m4_m4(sctx->runtime.pmat, rv3d->persmat);
3476  sctx->runtime.win_size[0] = region->winx;
3477  sctx->runtime.win_size[1] = region->winy;
3478  copy_v2_v2(sctx->runtime.mval, mval);
3480 
3481  /* First snap to edge instead of middle or perpendicular. */
3482  sctx->runtime.snap_to_flag = static_cast<eSnapMode>(
3483  snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE));
3485  sctx->runtime.snap_to_flag = static_cast<eSnapMode>(sctx->runtime.snap_to_flag |
3487  }
3488 
3490  nullptr,
3491  nullptr,
3492  nullptr,
3493  nullptr,
3494  sctx->runtime.clip_plane[0],
3495  sctx->runtime.clip_plane[1]);
3496 
3497  sctx->runtime.clip_plane_len = 2;
3498  sctx->runtime.has_occlusion_plane = false;
3499 
3500  /* By convention we only snap to the original elements of a curve. */
3501  if (has_hit && ob_eval->type != OB_CURVES_LEGACY) {
3502  /* Compute the new clip_pane but do not add it yet. */
3503  float new_clipplane[4];
3504  BLI_ASSERT_UNIT_V3(no);
3505  plane_from_point_normal_v3(new_clipplane, loc, no);
3506  if (dot_v3v3(sctx->runtime.clip_plane[0], new_clipplane) > 0.0f) {
3507  /* The plane is facing the wrong direction. */
3508  negate_v4(new_clipplane);
3509  }
3510 
3511  /* Small offset to simulate a kind of volume for edges and vertices. */
3512  new_clipplane[3] += 0.01f;
3513 
3514  /* Try to snap only to the polygon. */
3515  elem_test = snap_mesh_polygon(sctx, params, ob_eval, obmat, &dist_px_tmp, loc, no, &index);
3516  if (elem_test) {
3517  elem = elem_test;
3518  }
3519 
3520  /* Add the new clip plane to the beginning of the list. */
3521  for (int i = sctx->runtime.clip_plane_len; i != 0; i--) {
3522  copy_v4_v4(sctx->runtime.clip_plane[i], sctx->runtime.clip_plane[i - 1]);
3523  }
3524  copy_v4_v4(sctx->runtime.clip_plane[0], new_clipplane);
3525  sctx->runtime.clip_plane_len++;
3526  sctx->runtime.has_occlusion_plane = true;
3527  }
3528 
3529  elem_test = snapObjectsRay(sctx, params, &dist_px_tmp, loc, no, &index, &ob_eval, obmat);
3530  if (elem_test) {
3531  elem = elem_test;
3532  }
3533 
3534  if ((elem == SCE_SNAP_MODE_EDGE) &&
3537  sctx->runtime.snap_to_flag = snap_to_flag;
3539  sctx, params, ob_eval, obmat, *dist_px, prev_co, &dist_px_tmp, loc, no, &index);
3540  }
3541 
3542  if (elem & snap_to_flag) {
3543  retval = elem;
3544 
3545  copy_v3_v3(r_loc, loc);
3546  if (r_no) {
3547  copy_v3_v3(r_no, no);
3548  }
3549  if (r_ob) {
3550  *r_ob = ob_eval;
3551  }
3552  if (r_obmat) {
3553  copy_m4_m4(r_obmat, obmat);
3554  }
3555  if (r_index) {
3556  *r_index = index;
3557  }
3558 
3559  *dist_px = dist_px_tmp;
3560  }
3561  }
3562 
3563  return retval;
3564 }
3565 
3568  const ARegion *region,
3569  const View3D *v3d,
3570  const eSnapMode snap_to,
3571  const SnapObjectParams *params,
3572  const float init_co[3],
3573  const float mval[2],
3574  const float prev_co[3],
3575  float *dist_px,
3576  float r_loc[3],
3577  float r_no[3],
3578  int *r_index,
3579  Object **r_ob,
3580  float r_obmat[4][4],
3581  float r_face_nor[3])
3582 {
3584  depsgraph,
3585  region,
3586  v3d,
3587  snap_to,
3588  params,
3589  init_co,
3590  mval,
3591  prev_co,
3592  dist_px,
3593  r_loc,
3594  r_no,
3595  r_index,
3596  r_ob,
3597  r_obmat,
3598  r_face_nor);
3599 }
3600 
3603  const ARegion *region,
3604  const View3D *v3d,
3605  const eSnapMode snap_to,
3606  const SnapObjectParams *params,
3607  const float init_co[3],
3608  const float mval[2],
3609  const float prev_co[3],
3610  float *dist_px,
3611  float r_loc[3],
3612  float r_no[3])
3613 {
3615  depsgraph,
3616  region,
3617  v3d,
3618  snap_to,
3619  params,
3620  init_co,
3621  mval,
3622  prev_co,
3623  dist_px,
3624  r_loc,
3625  r_no,
3626  nullptr,
3627  nullptr,
3628  nullptr,
3629  nullptr);
3630 }
3631 
3634  const ARegion *region,
3635  const View3D *v3d,
3636  const SnapObjectParams *params,
3637  const float mval[2],
3638  float ray_depth,
3639  bool sort,
3640  ListBase *r_hit_list)
3641 {
3642  float ray_start[3], ray_normal[3];
3643 
3645  depsgraph, region, v3d, mval, nullptr, ray_normal, ray_start, true)) {
3646  return false;
3647  }
3648 
3650  sctx, depsgraph, v3d, params, ray_start, ray_normal, ray_depth, sort, r_hit_list);
3651 }
3652 
typedef float(TangentPoint)[2]
struct BoundBox * BKE_armature_boundbox_get(struct Object *ob)
Definition: armature.c:2657
BVHTree * bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data, struct BMEditMesh *em, const BLI_bitmap *edges_mask, int edges_num_active, float epsilon, int tree_type, int axis)
Definition: bvhutils.cc:866
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
Definition: bvhutils.cc:1410
BVHTree * bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data, struct BMEditMesh *em, const BLI_bitmap *mask, int verts_num_active, float epsilon, int tree_type, int axis)
Definition: bvhutils.cc:732
BVHTree * BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, struct BMEditMesh *em, int tree_type, BVHCacheType bvh_cache_type, struct BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex)
Definition: bvhutils.cc:1327
BVHTree * bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, struct BMEditMesh *em, const BLI_bitmap *mask, int looptri_num_active, float epsilon, int tree_type, int axis)
Definition: bvhutils.cc:1071
@ BVHTREE_FROM_EM_EDGES
Definition: BKE_bvhutils.h:80
@ BVHTREE_FROM_LOOPTRI
Definition: BKE_bvhutils.h:73
@ BVHTREE_FROM_LOOSEEDGES
Definition: BKE_bvhutils.h:77
@ BVHTREE_FROM_EM_VERTS
Definition: BKE_bvhutils.h:79
@ BVHTREE_FROM_LOOSEVERTS
Definition: BKE_bvhutils.h:76
@ BVHTREE_FROM_EM_LOOPTRI
Definition: BKE_bvhutils.h:81
@ BVHTREE_FROM_LOOPTRI_NO_HIDDEN
Definition: BKE_bvhutils.h:74
float bvhtree_ray_tri_intersection(const BVHTreeRay *ray, float m_dist, const float v0[3], const float v1[3], const float v2[3])
BVHTree * BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, const struct Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
Definition: bvhutils.cc:1213
bool bvhcache_has_tree(const struct BVHCache *bvh_cache, const BVHTree *tree)
void free_bvhtree_from_editmesh(struct BVHTreeFromEditMesh *data)
Definition: bvhutils.cc:1400
struct BoundBox * BKE_curve_boundbox_get(struct Object *ob)
Definition: curve.cc:494
struct ListBase * object_duplilist(struct Depsgraph *depsgraph, struct Scene *sce, struct Object *ob)
void free_object_duplilist(struct ListBase *lb)
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:58
bool BKE_object_has_geometry_set_instances(const struct Object *ob)
General operations, lookup, etc. for blender objects.
struct MovieClip * BKE_object_movieclip_get(struct Scene *scene, struct Object *ob, bool use_default)
Definition: object.cc:5042
struct Mesh * BKE_object_get_editmesh_eval_final(const struct Object *object)
struct Mesh * BKE_object_get_evaluated_mesh(const struct Object *object)
const struct BoundBox * BKE_object_boundbox_get(struct Object *ob)
Definition: object.cc:3684
struct Mesh * BKE_object_get_editmesh_eval_cage(const struct Object *object)
bool BKE_object_is_in_editmode(const struct Object *ob)
void BKE_tracking_get_camera_object_matrix(struct Object *camera_object, float mat[4][4])
Definition: tracking.c:375
void BKE_tracking_camera_get_reconstructed_interpolate(struct MovieTracking *tracking, struct MovieTrackingObject *object, float framenr, float mat[4][4])
Definition: tracking.c:2269
struct ListBase * BKE_tracking_object_get_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object)
Definition: tracking.c:2112
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition: BLI_bitmap.h:40
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:16
#define ATTR_FALLTHROUGH
#define BVH_RAYCAST_DIST_MAX
Definition: BLI_kdopbvh.h:89
int BLI_bvhtree_find_nearest_projected(BVHTree *tree, float projmat[4][4], float winsize[2], float mval[2], float clip_planes[6][4], int clip_plane_len, BVHTreeNearest *nearest, BVHTree_NearestProjectedCallback callback, void *userdata)
Definition: BLI_kdopbvh.c:2233
void BLI_bvhtree_free(BVHTree *tree)
Definition: BLI_kdopbvh.c:926
void(* BVHTree_RayCastCallback)(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition: BLI_kdopbvh.h:102
void(* BVHTree_NearestPointCallback)(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
Definition: BLI_kdopbvh.h:94
void BLI_bvhtree_ray_cast_all(BVHTree *tree, const float co[3], const float dir[3], float radius, float hit_dist, BVHTree_RayCastCallback callback, void *userdata)
Definition: BLI_kdopbvh.c:2015
int BLI_bvhtree_ray_cast(BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
Definition: BLI_kdopbvh.c:1942
int BLI_bvhtree_find_nearest(BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
Definition: BLI_kdopbvh.c:1616
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void void BLI_listbase_sort(struct ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
MINLINE float max_ff(float a, float b)
MINLINE float square_f(float a)
#define BLI_ASSERT_UNIT_V3(v)
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition: math_geom.c:209
float dist_squared_to_projected_aabb(struct DistProjectedAABBPrecalc *data, const float bbmin[3], const float bbmax[3], bool r_axis_closest[3])
Definition: math_geom.c:823
bool isect_ray_line_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], float *r_lambda)
Definition: math_geom.c:2028
bool isect_point_planes_v3_negated(const float(*planes)[4], int totplane, const float p[3])
Definition: math_geom.c:2067
void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:18
bool isect_ray_aabb_v3_simple(const float orig[3], const float dir[3], const float bb_min[3], const float bb_max[3], float *tmin, float *tmax)
Definition: math_geom.c:3124
void dist_squared_to_projected_aabb_precalc(struct DistProjectedAABBPrecalc *precalc, const float projmat[4][4], const float winsize[2], const float mval[2])
Definition: math_geom.c:772
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3254
void planes_from_projmat(const float mat[4][4], float left[4], float right[4], float bottom[4], float top[4], float near[4], float far[4])
Definition: math_geom.c:4615
void mul_v4_m4v4(float r[4], const float M[4][4], const float v[4])
Definition: math_matrix.c:850
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void transpose_m4_m4(float R[4][4], const float M[4][4])
Definition: math_matrix.c:1403
void mul_mat3_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:790
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
void transpose_m3_m4(float R[3][3], const float M[4][4])
Definition: math_matrix.c:1362
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void mul_transposed_mat3_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:946
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:897
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:867
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3(float r[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:237
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE float dot_m4_v3_row_x(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float dot_m4_v3_row_y(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void negate_v4(float r[4])
unsigned int uint
Definition: BLI_sys_types.h:67
pthread_mutex_t ThreadMutex
Definition: BLI_threads.h:82
#define INIT_MINMAX(min, max)
#define ARRAY_SIZE(arr)
#define IN_RANGE(a, b, c)
#define UNUSED(x)
#define UNPACK3(a)
#define UNLIKELY(x)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
struct Object * DEG_get_original_object(struct Object *object)
bool DEG_is_evaluated_object(const struct Object *object)
struct ViewLayer * DEG_get_input_view_layer(const Depsgraph *graph)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ BONE_ROOTSEL
@ BONE_SELECTED
@ BONE_HIDDEN_A
@ BONE_HIDDEN_P
@ BONE_TIPSEL
@ BONE_HIDDEN_PG
@ HD_ALIGN
@ BASE_SELECTABLE
@ BASE_SELECTED
@ ME_WRAPPER_TYPE_BMESH
@ OB_WIRE
@ OB_BOUNDBOX
@ OB_MODE_EDIT
@ OB_MODE_POSE
@ OB_MODE_OBJECT
Object is a sort of wrapper for general info.
@ OB_EMPTY
@ OB_SURF
@ OB_CAMERA
@ OB_FONT
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ OB_CURVES_LEGACY
@ OB_GPENCIL
@ BA_WAS_SEL
@ BA_SNAP_FIX_DEPS_FIASCO
@ OB_DUPLI
#define BA_TRANSFORM_LOCKED_IN_PLACE
eSnapTargetSelect
@ SCE_SNAP_TARGET_NOT_ACTIVE
@ SCE_SNAP_TARGET_NOT_NONEDITED
@ SCE_SNAP_TARGET_ONLY_SELECTABLE
@ SCE_SNAP_TARGET_ALL
@ SCE_SNAP_TARGET_NOT_SELECTED
@ SCE_SNAP_TARGET_NOT_EDITED
eSnapMode
@ SCE_SNAP_MODE_FACE_NEAREST
@ SCE_SNAP_MODE_EDGE_MIDPOINT
@ SCE_SNAP_MODE_VERTEX
@ SCE_SNAP_MODE_EDGE
@ SCE_SNAP_MODE_FACE_RAYCAST
@ SCE_SNAP_MODE_EDGE_PERPENDICULAR
@ SCE_SNAP_MODE_NONE
@ SCE_SNAP_MODE_GEOM
#define BASE_VISIBLE(v3d, base)
@ TRACKING_OBJECT_CAMERA
@ TRACK_HAS_BUNDLE
#define XRAY_ENABLED(v3d)
Definition: ED_view3d.h:1299
bool ED_view3d_win_to_ray_clipped_ex(struct Depsgraph *depsgraph, const struct ARegion *region, const struct View3D *v3d, const float mval[2], float r_ray_co[3], float r_ray_normal[3], float r_ray_start[3], bool do_clip_planes)
#define XRAY_FLAG_ENABLED(v3d)
Definition: ED_view3d.h:1298
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
float float4x4[4][4]
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Map
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:622
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
int BM_iter_mesh_bitmap_from_filter_tessface(BMesh *bm, BLI_bitmap *bitmap, bool(*test_fn)(BMFace *, void *user_data), void *user_data)
int BM_iter_mesh_bitmap_from_filter(const char itype, BMesh *bm, BLI_bitmap *bitmap, bool(*test_fn)(BMElem *, void *user_data), void *user_data)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.cc:558
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.cc:446
BLI_INLINE BMFace * BM_face_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:115
BLI_INLINE BMEdge * BM_edge_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:109
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:103
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
const Value & lookup(const Key &key) const
Definition: BLI_map.hh:485
void add_new(const Key &key, const Value &value)
Definition: BLI_map.hh:220
bool remove(const Key &key)
Definition: BLI_map.hh:323
const Value * lookup_ptr(const Key &key) const
Definition: BLI_map.hh:463
#define SELECT
Scene scene
const Depsgraph * depsgraph
void * user_data
SyclQueue void void size_t num_bytes void
void * tree
IconTextureDrawCall normal
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
#define G(x, y, z)
#define sqrtf(x)
Definition: metal/compat.h:243
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt=1)
vec_base< float, 3 > float3
return ret
#define min(a, b)
Definition: sort.c:35
void * regiondata
BMVert * v1
Definition: bmesh_class.h:122
BMVert * v2
Definition: bmesh_class.h:122
struct BMLoop *(* looptris)[3]
Definition: BKE_editmesh.h:48
struct BMesh * bm
Definition: BKE_editmesh.h:40
struct BMVert * v
Definition: bmesh_class.h:153
struct BMEdge * e
Definition: bmesh_class.h:164
struct BMFace * f
Definition: bmesh_class.h:171
struct BMLoop * next
Definition: bmesh_class.h:233
float co[3]
Definition: bmesh_class.h:87
float no[3]
Definition: bmesh_class.h:88
int totvert
Definition: bmesh_class.h:297
int totedge
Definition: bmesh_class.h:297
int totloop
Definition: bmesh_class.h:297
int totface
Definition: bmesh_class.h:297
struct BVHTree * tree
Definition: BKE_bvhutils.h:33
struct BMEditMesh * em
Definition: BKE_bvhutils.h:39
BVHTree_NearestPointCallback nearest_callback
Definition: BKE_bvhutils.h:36
BVHTree_RayCastCallback raycast_callback
Definition: BKE_bvhutils.h:37
BVHTree_RayCastCallback raycast_callback
Definition: BKE_bvhutils.h:54
const struct MEdge * edge
Definition: BKE_bvhutils.h:59
const float(* vert_normals)[3]
Definition: BKE_bvhutils.h:58
const struct MLoop * loop
Definition: BKE_bvhutils.h:61
struct BVHTree * tree
Definition: BKE_bvhutils.h:50
const struct MVert * vert
Definition: BKE_bvhutils.h:57
BVHTree_NearestPointCallback nearest_callback
Definition: BKE_bvhutils.h:53
const struct MLoopTri * looptri
Definition: BKE_bvhutils.h:62
float co[3]
Definition: BLI_kdopbvh.h:43
float no[3]
Definition: BLI_kdopbvh.h:46
float co[3]
Definition: BLI_kdopbvh.h:68
float no[3]
Definition: BLI_kdopbvh.h:70
float origin[3]
Definition: BLI_kdopbvh.h:54
float direction[3]
Definition: BLI_kdopbvh.h:56
short flag
int flag_legacy
struct Object * object
float vec[8][3]
EditNurb * editnurb
ListBase nurb
ListBase nurbs
void * first
Definition: DNA_listBase.h:31
unsigned int v1
unsigned int v2
struct MLoopTri * array
unsigned int poly
unsigned int tri[3]
unsigned int e
unsigned int v
float co[3]
struct BVHCache * bvh_cache
struct MLoopTri_Store looptris
void * eval_mutex
struct MEdge * medge
struct MVert * mvert
int totedge
int totvert
struct MLoop * mloop
Mesh_Runtime runtime
int totpoly
struct MPoly * mpoly
struct MovieTracking tracking
Nearest2DCopyVertNoCallback copy_vert_no
const float(* vert_normals)[3]
Nearest2DGetTriVertsCallback get_tri_verts_index
Nearest2DGetTriEdgesCallback get_tri_edges_index
Nearest2DGetEdgeVertsCallback get_edge_verts_index
Nearest2DGetVertCoCallback get_vert_co
short transflag
struct bPose * pose
float obmat[4][4]
void * data
const float(* timat)[3]
const float(* obmat)[4]
BVHTree_RayCastCallback raycast_callback
float persmat[4][4]
struct RenderData r
struct Mesh_Runtime * mesh_runtime
BVHTreeFromEditMesh treedata_editmesh
BVHTreeFromMesh treedata_mesh
struct SnapObjectContext::@620 callbacks
Map< const Object *, std::unique_ptr< SnapData_Mesh > > mesh_caches
struct SnapObjectContext::@621 runtime
float clip_plane[MAX_CLIPPLANE_LEN][4]
bool(* test_face_fn)(BMFace *, void *user_data)
bool(* test_edge_fn)(BMEdge *, void *user_data)
bool(* test_vert_fn)(BMVert *, void *user_data)
Map< const BMEditMesh *, std::unique_ptr< SnapData_EditMesh > > editmesh_caches
struct SnapObjectContext::@620::@622 edit_mesh
struct Base * basact
ListBase object_bases
unsigned int layer
ListBase * edbo
ListBase chanbase
float max
static SnapObjectHitDepth * hit_depth_create(const float depth, const float co[3], const float no[3], int index, Object *ob_eval, const float obmat[4][4], uint ob_uuid)
static void cb_mlooptri_edges_get(const int index, const Nearest2dUserData *data, int r_v_index[3])
void(*)(const int index, const Nearest2dUserData *data, int r_v_index[2]) Nearest2DGetEdgeVertsCallback
static void cb_snap_tri_verts(void *userdata, int index, const DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], const int clip_plane_len, BVHTreeNearest *nearest)
static bool nearest_world_mesh(SnapObjectContext *sctx, const struct SnapObjectParams *params, Object *ob_eval, const Mesh *me_eval, const float(*obmat)[4], bool use_hide, const float init_co[3], const float curr_co[3], float *r_dist_sq, float *r_loc, float *r_no, int *r_index)
@ VIEW_PROJ_PERSP
@ VIEW_PROJ_NONE
@ VIEW_PROJ_ORTHO
void(*)(SnapObjectContext *sctx, const SnapObjectParams *params, Object *ob_eval, const float obmat[4][4], bool is_object_active, void *data) IterSnapObjsCallback
static void nearest_world_object_fn(SnapObjectContext *sctx, const struct SnapObjectParams *params, Object *ob_eval, const float obmat[4][4], bool is_object_active, void *data)
eSnapMode ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const eSnapMode snap_to, const SnapObjectParams *params, const float init_co[3], const float mval[2], const float prev_co[3], float *dist_px, float r_loc[3], float r_no[3], int *r_index, Object **r_ob, float r_obmat[4][4], float r_face_nor[3])
static void cb_bvert_co_get(const int index, const Nearest2dUserData *data, const float **r_co)
static bool snap_object_is_snappable(const SnapObjectContext *sctx, const eSnapTargetSelect snap_target_select, const Base *base_act, const Base *base)
void ED_transform_snap_object_context_set_editmesh_callbacks(SnapObjectContext *sctx, bool(*test_vert_fn)(BMVert *, void *user_data), bool(*test_edge_fn)(BMEdge *, void *user_data), bool(*test_face_fn)(BMFace *, void *user_data), void *user_data)
bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx, Depsgraph *depsgraph, const View3D *v3d, const SnapObjectParams *params, const float ray_start[3], const float ray_normal[3], float *ray_depth, float r_loc[3], float r_no[3], int *r_index, Object **r_ob, float r_obmat[4][4])
static eSnapMode snapCamera(const SnapObjectContext *sctx, Object *object, const float obmat[4][4], float *dist_px, float r_loc[3], float *r_no, int *r_index)
void(*)(const int index, const Nearest2dUserData *data, const float **r_co) Nearest2DGetVertCoCallback
static void cb_medge_verts_get(const int index, const Nearest2dUserData *data, int r_v_index[2])
static void snap_editmesh_minmax(SnapObjectContext *sctx, BMesh *bm, float r_min[3], float r_max[3])
static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx, Depsgraph *depsgraph, const View3D *v3d, const SnapObjectParams *params, const float ray_start[3], const float ray_normal[3], float ray_depth, bool sort, ListBase *r_hit_list)
static void cb_bvert_no_copy(const int index, const Nearest2dUserData *data, float r_no[3])
static bool nearest_world_editmesh(SnapObjectContext *sctx, const struct SnapObjectParams *params, Object *ob_eval, BMEditMesh *em, const float(*obmat)[4], const float init_co[3], const float curr_co[3], float *r_dist_sq, float *r_loc, float *r_no, int *r_index)
static void cb_snap_tri_edges(void *userdata, int index, const DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], const int clip_plane_len, BVHTreeNearest *nearest)
static eSnapMode snapCurve(SnapObjectContext *sctx, const SnapObjectParams *params, Object *ob_eval, const float obmat[4][4], float *dist_px, float r_loc[3], float *UNUSED(r_no), int *r_index)
void(*)(const int index, const Nearest2dUserData *data, float r_no[3]) Nearest2DCopyVertNoCallback
static bool snap_bound_box_check_dist(const float min[3], const float max[3], const float lpmat[4][4], const float win_size[2], const float mval[2], float dist_px_sq)
static void cb_snap_edge_verts(void *userdata, int index, const DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], const int clip_plane_len, BVHTreeNearest *nearest)
static BVHTreeFromEditMesh * snap_object_data_editmesh_treedata_get(SnapObjectContext *sctx, Object *ob_eval, BMEditMesh *em)
bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx, Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const SnapObjectParams *params, const float mval[2], float ray_depth, bool sort, ListBase *r_hit_list)
#define MAX_CLIPPLANE_LEN
static Mesh_Runtime * snap_object_data_editmesh_runtime_get(Object *ob_eval)
static eSnapMode transform_snap_context_project_view3d_mixed_impl(SnapObjectContext *sctx, Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const eSnapMode snap_to_flag, const SnapObjectParams *params, const float init_co[3], const float mval[2], const float prev_co[3], float *dist_px, float r_loc[3], float r_no[3], int *r_index, Object **r_ob, float r_obmat[4][4], float r_face_nor[3])
SnapObjectContext * ED_transform_snap_object_context_create(Scene *scene, int flag)
static eSnapMode snapEditMesh(SnapObjectContext *sctx, const SnapObjectParams *params, Object *ob_eval, BMEditMesh *em, const float obmat[4][4], float *dist_px, float r_loc[3], float r_no[3], int *r_index)
static BVHTreeFromMesh * snap_object_data_mesh_treedata_get(SnapObjectContext *sctx, Object *ob_eval, const Mesh *me_eval, bool use_hide)
static void nearest2d_data_init_mesh(SnapData_Mesh *sod, bool is_persp, bool use_backface_culling, Nearest2dUserData *r_nearest2d)
static bool test_projected_edge_dist(const DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], const int clip_plane_len, const bool is_persp, const float va[3], const float vb[3], float *dist_px_sq, float r_co[3])
bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx, Depsgraph *depsgraph, const View3D *v3d, const SnapObjectParams *params, const float ray_origin[3], const float ray_direction[3], float *ray_depth, float r_co[3], float r_no[3])
static bool raycastMesh(SnapObjectContext *sctx, const SnapObjectParams *params, const float ray_start[3], const float ray_dir[3], Object *ob_eval, const Mesh *me_eval, const float obmat[4][4], const uint ob_index, bool use_hide, float *ray_depth, float r_loc[3], float r_no[3], int *r_index, ListBase *r_hit_list)
static void editmesh_looptri_raycast_backface_culling_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
static eSnapMode snap_mesh_polygon(SnapObjectContext *sctx, const SnapObjectParams *params, Object *ob_eval, const float obmat[4][4], float *dist_px, float r_loc[3], float r_no[3], int *r_index)
static void cb_mvert_no_copy(const int index, const Nearest2dUserData *data, float r_no[3])
static eSnapMode snap_object_center(const SnapObjectContext *sctx, Object *ob_eval, const float obmat[4][4], float *dist_px, float r_loc[3], float *UNUSED(r_no), int *r_index)
static const Mesh * mesh_for_snap(Object *ob_eval, eSnapEditType edit_mode_type, bool *r_use_hide)
static bool raycastObjects(SnapObjectContext *sctx, const SnapObjectParams *params, const float ray_start[3], const float ray_dir[3], float *ray_depth, float r_loc[3], float r_no[3], int *r_index, Object **r_ob, float r_obmat[4][4], ListBase *r_hit_list)
static bool test_projected_vert_dist(const DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], const int clip_plane_len, const bool is_persp, const float co[3], float *dist_px_sq, float r_co[3])
static void raycast_obj_fn(SnapObjectContext *sctx, const SnapObjectParams *params, Object *ob_eval, const float obmat[4][4], bool is_object_active, void *data)
static eSnapMode snapMesh(SnapObjectContext *sctx, const SnapObjectParams *params, Object *ob_eval, const Mesh *me_eval, const float obmat[4][4], bool use_hide, float *dist_px, float r_loc[3], float r_no[3], int *r_index)
static eSnapMode snapObjectsRay(SnapObjectContext *sctx, const SnapObjectParams *params, float *dist_px, float r_loc[3], float r_no[3], int *r_index, Object **r_ob, float r_obmat[4][4])
static bool raycastEditMesh(SnapObjectContext *sctx, const SnapObjectParams *params, const float ray_start[3], const float ray_dir[3], Object *ob_eval, BMEditMesh *em, const float obmat[4][4], const uint ob_index, float *ray_depth, float r_loc[3], float r_no[3], int *r_index, ListBase *r_hit_list)
static void cb_mlooptri_verts_get(const int index, const Nearest2dUserData *data, int r_v_index[3])
static void cb_snap_edge(void *userdata, int index, const DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], const int clip_plane_len, BVHTreeNearest *nearest)
static bool raycast_tri_backface_culling_test(const float dir[3], const float v0[3], const float v1[3], const float v2[3], float no[3])
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
eSnapMode ED_transform_snap_object_project_view3d(SnapObjectContext *sctx, Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const eSnapMode snap_to, const SnapObjectParams *params, const float init_co[3], const float mval[2], const float prev_co[3], float *dist_px, float r_loc[3], float r_no[3])
static void mesh_looptri_raycast_backface_culling_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
static void iter_snap_objects(SnapObjectContext *sctx, const SnapObjectParams *params, IterSnapObjsCallback sob_callback, void *data)
static SnapData_Mesh * snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob_eval, const Mesh *me_eval, bool use_hide)
static bool nearest_world_tree(SnapObjectContext *UNUSED(sctx), const struct SnapObjectParams *params, BVHTree *tree, BVHTree_NearestPointCallback nearest_cb, void *treedata, const float(*obmat)[4], const float init_co[3], const float curr_co[3], float *r_dist_sq, float *r_loc, float *r_no, int *r_index)
static eSnapMode snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, const SnapObjectParams *params, Object *ob_eval, const float obmat[4][4], float original_dist_px, const float prev_co[3], float *dist_px, float r_loc[3], float r_no[3], int *r_index)
void(*)(const int index, const Nearest2dUserData *data, int r_v_index[3]) Nearest2DGetTriVertsCallback
static void nearest_world_tree_co(BVHTree *tree, BVHTree_NearestPointCallback nearest_cb, void *treedata, float co[3], float r_co[3], float r_no[3], int *r_index, float *r_dist_sq)
static void cb_mvert_co_get(const int index, const Nearest2dUserData *data, const float **r_co)
static SnapData_EditMesh * snap_object_data_editmesh_get(SnapObjectContext *sctx, Object *ob_eval, BMEditMesh *em)
static int hit_depth_cmp(const void *arg1, const void *arg2)
static bool transform_snap_context_project_ray_impl(SnapObjectContext *sctx, Depsgraph *depsgraph, const View3D *v3d, const SnapObjectParams *params, const float ray_start[3], const float ray_normal[3], float *ray_depth, float r_co[3], float r_no[3])
static void nearest2d_data_init_editmesh(SnapData_EditMesh *sod, bool is_persp, bool use_backface_culling, Nearest2dUserData *r_nearest2d)
static bool nearestWorldObjects(SnapObjectContext *sctx, const struct SnapObjectParams *params, const float init_co[3], const float curr_co[3], float *r_loc, float *r_no, int *r_index, Object **r_ob, float r_obmat[4][4])
static void cb_bedge_verts_get(const int index, const Nearest2dUserData *data, int r_v_index[2])
static eSnapMode snapArmature(SnapObjectContext *sctx, const SnapObjectParams *params, Object *ob_eval, const float obmat[4][4], bool is_object_active, float *dist_px, float r_loc[3], float *UNUSED(r_no), int *r_index)
static void snap_obj_fn(SnapObjectContext *sctx, const SnapObjectParams *params, Object *ob_eval, const float obmat[4][4], bool is_object_active, void *data)
static void cb_snap_vert(void *userdata, int index, const DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], const int clip_plane_len, BVHTreeNearest *nearest)
void(*)(const int index, const Nearest2dUserData *data, int r_e_index[3]) Nearest2DGetTriEdgesCallback