Blender  V2.93
transform_snap_object.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include <stdlib.h>
22 
23 #include "MEM_guardedalloc.h"
24 
25 #include "BLI_ghash.h"
26 #include "BLI_kdopbvh.h"
27 #include "BLI_listbase.h"
28 #include "BLI_math.h"
29 #include "BLI_memarena.h"
30 #include "BLI_utildefines.h"
31 
32 #include "DNA_armature_types.h"
33 #include "DNA_curve_types.h"
34 #include "DNA_mesh_types.h"
35 #include "DNA_meshdata_types.h"
36 #include "DNA_object_types.h"
37 #include "DNA_scene_types.h"
38 #include "DNA_screen_types.h"
39 #include "DNA_view3d_types.h"
40 
41 #include "BKE_armature.h"
42 #include "BKE_bvhutils.h"
43 #include "BKE_curve.h"
44 #include "BKE_duplilist.h"
45 #include "BKE_editmesh.h"
46 #include "BKE_geometry_set.h"
47 #include "BKE_layer.h"
48 #include "BKE_mesh.h"
49 #include "BKE_mesh_runtime.h"
50 #include "BKE_object.h"
51 #include "BKE_tracking.h"
52 
53 #include "DEG_depsgraph_query.h"
54 
55 #include "ED_armature.h"
57 #include "ED_view3d.h"
58 
59 /* -------------------------------------------------------------------- */
63 #define MAX_CLIPPLANE_LEN 3
64 
65 enum eViewProj {
69 };
70 
71 typedef struct SnapData {
72  float mval[2];
73  float pmat[4][4]; /* perspective matrix */
74  float win_size[2]; /* win x and y */
75  enum eViewProj view_proj;
78  short snap_to_flag;
79  bool has_occlusion_plane; /* Ignore plane of occlusion in curves. */
81 
82 typedef struct SnapObjectData {
83  enum {
84  SNAP_MESH = 1,
86  } type;
87 
88  BVHTree *bvhtree[2]; /* MESH: loose edges, loose verts
89  * EDIT_MESH: verts, edges. */
90  bool cached[2];
91 
92  union {
93  struct {
94  /* SNAP_MESH */
96  const struct MPoly *poly;
100  };
101  struct {
102  /* SNAP_EDIT_MESH */
104  float min[3], max[3];
106  };
107  };
109 
112 
113  int flag;
114 
115  /* Optional: when performing screen-space projection.
116  * otherwise this doesn't take viewport into account. */
117  bool use_v3d;
118  struct {
119  const struct View3D *v3d;
120  const struct ARegion *region;
122 
123  /* Object -> SnapObjectData map */
124  struct {
129  } cache;
130 
131  /* Filter data, returns true to check this value */
132  struct {
133  struct {
134  bool (*test_vert_fn)(BMVert *, void *user_data);
135  bool (*test_edge_fn)(BMEdge *, void *user_data);
136  bool (*test_face_fn)(BMFace *, void *user_data);
137  void *user_data;
140 };
141 
144 /* -------------------------------------------------------------------- */
149 {
151 }
152 
155 /* -------------------------------------------------------------------- */
162 static void bm_mesh_minmax(BMesh *bm, float r_min[3], float r_max[3])
163 {
164  INIT_MINMAX(r_min, r_max);
165  BMIter iter;
166  BMVert *v;
167 
168  BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
169  minmax_v3v3_v3(r_min, r_max, v->co);
170  }
171 }
172 
174 {
175  BLI_assert(sod->type == SNAP_MESH);
176  for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) {
177  if (!sod->cached[i]) {
178  BLI_bvhtree_free(sod->bvhtree[i]);
179  }
180  sod->bvhtree[i] = NULL;
181  }
183 }
184 
186 {
187  BLI_assert(sod->type == SNAP_EDIT_MESH);
188  for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) {
189  if (!sod->cached[i]) {
190  BLI_bvhtree_free(sod->bvhtree[i]);
191  }
192  sod->bvhtree[i] = NULL;
193  }
195 }
196 
198 {
199  switch (sod->type) {
200  case SNAP_MESH: {
202  break;
203  }
204  case SNAP_EDIT_MESH: {
206  break;
207  }
208  }
209  memset(&sod->type, 0x0, sizeof(*sod) - offsetof(SnapObjectData, type));
210 }
211 
213 {
215  if (sod == NULL) {
216  if (sctx->cache.data_to_object_map != NULL) {
218  /* Could be NULl when mixing edit-mode and non edit-mode objects. */
219  if (ob != NULL) {
220  sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
221  }
222  }
223  }
224  return sod;
225 }
226 
228 {
229  SnapObjectData *sod;
230  void **sod_p;
231  bool init = false;
232 
233  if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
234  sod = *sod_p;
235  if (sod->type != SNAP_MESH) {
237  init = true;
238  }
239  }
240  else {
241  sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
242  init = true;
243  }
244 
245  if (init) {
246  sod->type = SNAP_MESH;
247  /* start assuming that it has each of these element types */
248  sod->has_looptris = true;
249  sod->has_loose_edge = true;
250  sod->has_loose_vert = true;
251  }
252 
253  return sod;
254 }
255 
257 {
259  if (em->mesh_eval_final) {
260  return &em->mesh_eval_final->runtime;
261  }
262  if (em->mesh_eval_cage) {
263  return &em->mesh_eval_cage->runtime;
264  }
265 
266  return &((Mesh *)ob->data)->runtime;
267 }
268 
270  Object *ob,
271  BMEditMesh *em)
272 {
273  SnapObjectData *sod;
274  void **sod_p;
275  bool init = false, init_min_max = true, clear_cache = false;
276 
277  {
278  /* Use object-data as the key in ghash since the editmesh
279  * is used to create bvhtree and is the same for each linked object. */
280  if (sctx->cache.data_to_object_map == NULL) {
281  sctx->cache.data_to_object_map = BLI_ghash_ptr_new(__func__);
282  }
283  void **ob_p;
284  if (BLI_ghash_ensure_p(sctx->cache.data_to_object_map, ob->data, &ob_p)) {
285  ob = *ob_p;
286  }
287  else {
288  *ob_p = ob;
289  }
290  }
291 
292  if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
293  sod = *sod_p;
294  bool clear = false;
295  /* Check if the geometry has changed. */
296  if (sod->type != SNAP_EDIT_MESH) {
297  clear = true;
298  }
299  else if (sod->treedata_editmesh.em != em) {
300  clear_cache = true;
301  init = true;
302  }
303  else if (sod->mesh_runtime) {
305  clear_cache = true;
306  init = true;
307  }
308  else if (sod->treedata_editmesh.tree && sod->treedata_editmesh.cached &&
310  /* The tree is owned by the EditMesh and may have been freed since we last used! */
311  clear = true;
312  }
313  else if (sod->bvhtree[0] && sod->cached[0] &&
314  !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->bvhtree[0])) {
315  /* The tree is owned by the EditMesh and may have been freed since we last used! */
316  clear = true;
317  }
318  else if (sod->bvhtree[1] && sod->cached[1] &&
319  !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->bvhtree[1])) {
320  /* The tree is owned by the EditMesh and may have been freed since we last used! */
321  clear = true;
322  }
323  }
324 
325  if (clear) {
327  init = true;
328  }
329  }
330  else {
331  sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
332  init = true;
333  }
334 
335  if (init) {
336  sod->type = SNAP_EDIT_MESH;
337  sod->treedata_editmesh.em = em;
338 
339  if (clear_cache) {
340  /* Only init min and max when you have a non-custom bvhtree pending. */
341  init_min_max = false;
342  if (sod->treedata_editmesh.cached) {
343  sod->treedata_editmesh.tree = NULL;
344  init_min_max = true;
345  }
346  for (int i = 0; i < ARRAY_SIZE(sod->bvhtree); i++) {
347  if (sod->cached[i]) {
348  sod->bvhtree[i] = NULL;
349  init_min_max = true;
350  }
351  }
352  }
353 
354  if (init_min_max) {
355  bm_mesh_minmax(em->bm, sod->min, sod->max);
356  }
357 
359  }
360 
361  return sod;
362 }
363 
366 /* -------------------------------------------------------------------- */
371  Object *ob,
372  float obmat[4][4],
373  bool use_obedit,
374  bool use_backface_culling,
375  bool is_object_active,
376  void *data);
377 
383  const struct SnapObjectParams *params,
384  IterSnapObjsCallback sob_callback,
385  void *data)
386 {
388  const View3D *v3d = sctx->v3d_data.v3d;
389  const eSnapSelect snap_select = params->snap_select;
390  const bool use_object_edit_cage = params->use_object_edit_cage;
391  const bool use_backface_culling = params->use_backface_culling;
392 
393  Base *base_act = view_layer->basact;
394  for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
395  if (!BASE_VISIBLE(v3d, base)) {
396  continue;
397  }
398 
399  if (base->flag_legacy & BA_TRANSFORM_LOCKED_IN_PLACE) {
400  /* pass */
401  }
402  else if (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) {
403  continue;
404  }
405 
406  const bool is_object_active = (base == base_act);
407  if (snap_select == SNAP_NOT_SELECTED) {
408  if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) {
409  continue;
410  }
411  }
412  else if (snap_select == SNAP_NOT_ACTIVE) {
413  if (is_object_active) {
414  continue;
415  }
416  }
417 
418  Object *obj_eval = DEG_get_evaluated_object(depsgraph, base->object);
419  if (obj_eval->transflag & OB_DUPLI ||
420  (obj_eval->runtime.geometry_set_eval != NULL &&
422  ListBase *lb = object_duplilist(depsgraph, sctx->scene, obj_eval);
423  for (DupliObject *dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
424  BLI_assert(DEG_is_evaluated_object(dupli_ob->ob));
425  sob_callback(sctx,
426  dupli_ob->ob,
427  dupli_ob->mat,
428  use_object_edit_cage,
429  use_backface_culling,
430  is_object_active,
431  data);
432  }
434  }
435 
436  sob_callback(sctx,
437  obj_eval,
438  obj_eval->obmat,
439  use_object_edit_cage,
440  use_backface_culling,
441  is_object_active,
442  data);
443  }
444 }
445 
448 /* -------------------------------------------------------------------- */
452 /* Store all ray-hits
453  * Support for storing all depths, not just the first (raycast 'all') */
454 
456  void *bvhdata;
457 
458  /* internal vars for adding depths */
460 
461  const float (*obmat)[4];
462  const float (*timat)[3];
463 
464  float len_diff;
465  float local_scale;
466 
469 
470  /* output data */
472  bool retval;
473 };
474 
475 static struct SnapObjectHitDepth *hit_depth_create(const float depth,
476  const float co[3],
477  const float no[3],
478  int index,
479  Object *ob,
480  const float obmat[4][4],
481  uint ob_uuid)
482 {
483  struct SnapObjectHitDepth *hit = MEM_mallocN(sizeof(*hit), __func__);
484 
485  hit->depth = depth;
486  copy_v3_v3(hit->co, co);
487  copy_v3_v3(hit->no, no);
488  hit->index = index;
489 
490  hit->ob = ob;
491  copy_m4_m4(hit->obmat, (float(*)[4])obmat);
492  hit->ob_uuid = ob_uuid;
493 
494  return hit;
495 }
496 
497 static int hit_depth_cmp(const void *arg1, const void *arg2)
498 {
499  const struct SnapObjectHitDepth *h1 = arg1;
500  const struct SnapObjectHitDepth *h2 = arg2;
501  int val = 0;
502 
503  if (h1->depth < h2->depth) {
504  val = -1;
505  }
506  else if (h1->depth > h2->depth) {
507  val = 1;
508  }
509 
510  return val;
511 }
512 
513 static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
514 {
515  struct RayCastAll_Data *data = userdata;
516  data->raycast_callback(data->bvhdata, index, ray, hit);
517  if (hit->index != -1) {
518  /* get all values in worldspace */
519  float location[3], normal[3];
520  float depth;
521 
522  /* worldspace location */
523  mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co);
524  depth = (hit->dist + data->len_diff) / data->local_scale;
525 
526  /* worldspace normal */
527  copy_v3_v3(normal, hit->no);
528  mul_m3_v3((float(*)[3])data->timat, normal);
530 
531  struct SnapObjectHitDepth *hit_item = hit_depth_create(
532  depth, location, normal, hit->index, data->ob, data->obmat, data->ob_uuid);
533  BLI_addtail(data->hit_list, hit_item);
534  }
535 }
536 
538  const float dir[3], const float v0[3], const float v1[3], const float v2[3], float no[3])
539 {
540  cross_tri_v3(no, v0, v1, v2);
541  return dot_v3v3(no, dir) < 0.0f;
542 }
543 
544 /* Callback to raycast with backface culling (Mesh). */
545 static void mesh_looptri_raycast_backface_culling_cb(void *userdata,
546  int index,
547  const BVHTreeRay *ray,
548  BVHTreeRayHit *hit)
549 {
550  const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
551  const MVert *vert = data->vert;
552  const MLoopTri *lt = &data->looptri[index];
553  const float *vtri_co[3] = {
554  vert[data->loop[lt->tri[0]].v].co,
555  vert[data->loop[lt->tri[1]].v].co,
556  vert[data->loop[lt->tri[2]].v].co,
557  };
558  float dist = bvhtree_ray_tri_intersection(ray, hit->dist, UNPACK3(vtri_co));
559 
560  if (dist >= 0 && dist < hit->dist) {
561  float no[3];
562  if (raycast_tri_backface_culling_test(ray->direction, UNPACK3(vtri_co), no)) {
563  hit->index = index;
564  hit->dist = dist;
565  madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
566  normalize_v3_v3(hit->no, no);
567  }
568  }
569 }
570 
571 /* Callback to raycast with backface culling (EditMesh). */
573  int index,
574  const BVHTreeRay *ray,
575  BVHTreeRayHit *hit)
576 {
577  const BVHTreeFromEditMesh *data = (BVHTreeFromEditMesh *)userdata;
578  BMEditMesh *em = data->em;
579  const BMLoop **ltri = (const BMLoop **)em->looptris[index];
580 
581  const float *t0, *t1, *t2;
582  t0 = ltri[0]->v->co;
583  t1 = ltri[1]->v->co;
584  t2 = ltri[2]->v->co;
585 
586  {
587  float dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
588 
589  if (dist >= 0 && dist < hit->dist) {
590  float no[3];
591  if (raycast_tri_backface_culling_test(ray->direction, t0, t1, t2, no)) {
592  hit->index = index;
593  hit->dist = dist;
594  madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
595  normalize_v3_v3(hit->no, no);
596  }
597  }
598  }
599 }
600 
601 static bool raycastMesh(SnapObjectContext *sctx,
602  const float ray_start[3],
603  const float ray_dir[3],
604  Object *ob,
605  Mesh *me,
606  const float obmat[4][4],
607  const uint ob_index,
608  bool use_hide,
609  bool use_backface_culling,
610  /* read/write args */
611  float *ray_depth,
612  /* return args */
613  float r_loc[3],
614  float r_no[3],
615  int *r_index,
616  ListBase *r_hit_list)
617 {
618  bool retval = false;
619 
620  if (me->totpoly == 0) {
621  return retval;
622  }
623 
624  float imat[4][4];
625  float ray_start_local[3], ray_normal_local[3];
626  float local_scale, local_depth, len_diff = 0.0f;
627 
628  invert_m4_m4(imat, obmat);
629 
630  copy_v3_v3(ray_start_local, ray_start);
631  copy_v3_v3(ray_normal_local, ray_dir);
632 
633  mul_m4_v3(imat, ray_start_local);
634  mul_mat3_m4_v3(imat, ray_normal_local);
635 
636  /* local scale in normal direction */
637  local_scale = normalize_v3(ray_normal_local);
638  local_depth = *ray_depth;
639  if (local_depth != BVH_RAYCAST_DIST_MAX) {
640  local_depth *= local_scale;
641  }
642 
643  /* Test BoundBox */
645  if (bb) {
646  /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
648  ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, NULL)) {
649  return retval;
650  }
651  }
652  /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
653  * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358.
654  */
655  if (len_diff > 400.0f) {
656  len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
657  madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
658  local_depth -= len_diff;
659  }
660  else {
661  len_diff = 0.0f;
662  }
663 
665 
666  BVHTreeFromMesh *treedata = &sod->treedata_mesh;
667 
668  /* The tree is owned by the Mesh and may have been freed since we last used. */
669  if (treedata->tree) {
670  BLI_assert(treedata->cached);
671  if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
672  free_bvhtree_from_mesh(treedata);
673  }
674  else {
675  /* Update Pointers. */
676  if (treedata->vert && treedata->vert_allocated == false) {
677  treedata->vert = me->mvert;
678  }
679  if (treedata->loop && treedata->loop_allocated == false) {
680  treedata->loop = me->mloop;
681  }
682  if (treedata->looptri && treedata->looptri_allocated == false) {
684  }
685  /* required for snapping with occlusion. */
686  treedata->edge = me->medge;
687  sod->poly = me->mpoly;
688  }
689  }
690 
691  if (treedata->tree == NULL) {
692  if (use_hide) {
694  }
695  else {
697  }
698 
699  /* required for snapping with occlusion. */
700  treedata->edge = me->medge;
701  sod->poly = me->mpoly;
702 
703  if (treedata->tree == NULL) {
704  return retval;
705  }
706  }
707 
708  float timat[3][3]; /* transpose inverse matrix for normals */
709  transpose_m3_m4(timat, imat);
710 
711  if (r_hit_list) {
712  struct RayCastAll_Data data;
713 
714  data.bvhdata = treedata;
715  data.raycast_callback = treedata->raycast_callback;
716  data.obmat = obmat;
717  data.timat = timat;
718  data.len_diff = len_diff;
719  data.local_scale = local_scale;
720  data.ob = ob;
721  data.ob_uuid = ob_index;
722  data.hit_list = r_hit_list;
723  data.retval = retval;
724 
725  BLI_bvhtree_ray_cast_all(treedata->tree,
726  ray_start_local,
727  ray_normal_local,
728  0.0f,
729  *ray_depth,
731  &data);
732 
733  retval = data.retval;
734  }
735  else {
736  BVHTreeRayHit hit = {
737  .index = -1,
738  .dist = local_depth,
739  };
740 
741  if (BLI_bvhtree_ray_cast(treedata->tree,
742  ray_start_local,
743  ray_normal_local,
744  0.0f,
745  &hit,
746  use_backface_culling ? mesh_looptri_raycast_backface_culling_cb :
747  treedata->raycast_callback,
748  treedata) != -1) {
749  hit.dist += len_diff;
750  hit.dist /= local_scale;
751  if (hit.dist <= *ray_depth) {
752  *ray_depth = hit.dist;
753  copy_v3_v3(r_loc, hit.co);
754 
755  /* back to worldspace */
756  mul_m4_v3(obmat, r_loc);
757 
758  if (r_no) {
759  copy_v3_v3(r_no, hit.no);
760  mul_m3_v3(timat, r_no);
761  normalize_v3(r_no);
762  }
763 
764  retval = true;
765 
766  if (r_index) {
767  *r_index = treedata->looptri[hit.index].poly;
768  }
769  }
770  }
771  }
772 
773  return retval;
774 }
775 
777  const float ray_start[3],
778  const float ray_dir[3],
779  Object *ob,
780  BMEditMesh *em,
781  const float obmat[4][4],
782  const uint ob_index,
783  bool use_backface_culling,
784  /* read/write args */
785  float *ray_depth,
786  /* return args */
787  float r_loc[3],
788  float r_no[3],
789  int *r_index,
790  ListBase *r_hit_list)
791 {
792  bool retval = false;
793  if (em->bm->totface == 0) {
794  return retval;
795  }
796 
797  float imat[4][4];
798  float ray_start_local[3], ray_normal_local[3];
799  float local_scale, local_depth, len_diff = 0.0f;
800 
801  invert_m4_m4(imat, obmat);
802 
803  copy_v3_v3(ray_start_local, ray_start);
804  copy_v3_v3(ray_normal_local, ray_dir);
805 
806  mul_m4_v3(imat, ray_start_local);
807  mul_mat3_m4_v3(imat, ray_normal_local);
808 
809  /* local scale in normal direction */
810  local_scale = normalize_v3(ray_normal_local);
811  local_depth = *ray_depth;
812  if (local_depth != BVH_RAYCAST_DIST_MAX) {
813  local_depth *= local_scale;
814  }
815 
817 
818  /* Test BoundBox */
819 
820  /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
822  ray_start_local, ray_normal_local, sod->min, sod->max, &len_diff, NULL)) {
823  return retval;
824  }
825 
826  /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
827  * very far away ray_start values (as returned in case of ortho view3d), see T50486, T38358.
828  */
829  if (len_diff > 400.0f) {
830  len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
831  madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
832  local_depth -= len_diff;
833  }
834  else {
835  len_diff = 0.0f;
836  }
837 
838  BVHTreeFromEditMesh *treedata = &sod->treedata_editmesh;
839 
840  if (treedata->tree == NULL) {
841  /* Operators only update the editmesh looptris of the original mesh. */
843  em = sod->treedata_editmesh.em;
844 
845  if (sctx->callbacks.edit_mesh.test_face_fn) {
846  BMesh *bm = em->bm;
848 
849  BLI_bitmap *elem_mask = BLI_BITMAP_NEW(em->tottri, __func__);
850  int looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
851  bm,
852  elem_mask,
853  sctx->callbacks.edit_mesh.test_face_fn,
854  sctx->callbacks.edit_mesh.user_data);
855 
857  treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL, NULL);
858 
859  MEM_freeN(elem_mask);
860  }
861  else {
862  /* Only cache if bvhtree is created without a mask.
863  * This helps keep a standardized bvhtree in cache. */
865  em,
866  4,
868  &sod->mesh_runtime->bvh_cache,
869  sod->mesh_runtime->eval_mutex);
870  }
871 
872  if (treedata->tree == NULL) {
873  return retval;
874  }
875  }
876 
877  float timat[3][3]; /* transpose inverse matrix for normals */
878  transpose_m3_m4(timat, imat);
879 
880  if (r_hit_list) {
881  struct RayCastAll_Data data;
882 
883  data.bvhdata = treedata;
884  data.raycast_callback = treedata->raycast_callback;
885  data.obmat = obmat;
886  data.timat = timat;
887  data.len_diff = len_diff;
888  data.local_scale = local_scale;
889  data.ob = ob;
890  data.ob_uuid = ob_index;
891  data.hit_list = r_hit_list;
892  data.retval = retval;
893 
894  BLI_bvhtree_ray_cast_all(treedata->tree,
895  ray_start_local,
896  ray_normal_local,
897  0.0f,
898  *ray_depth,
900  &data);
901 
902  retval = data.retval;
903  }
904  else {
905  BVHTreeRayHit hit = {
906  .index = -1,
907  .dist = local_depth,
908  };
909 
910  if (BLI_bvhtree_ray_cast(treedata->tree,
911  ray_start_local,
912  ray_normal_local,
913  0.0f,
914  &hit,
915  use_backface_culling ? editmesh_looptri_raycast_backface_culling_cb :
916  treedata->raycast_callback,
917  treedata) != -1) {
918  hit.dist += len_diff;
919  hit.dist /= local_scale;
920  if (hit.dist <= *ray_depth) {
921  *ray_depth = hit.dist;
922  copy_v3_v3(r_loc, hit.co);
923 
924  /* back to worldspace */
925  mul_m4_v3(obmat, r_loc);
926 
927  if (r_no) {
928  copy_v3_v3(r_no, hit.no);
929  mul_m3_v3(timat, r_no);
930  normalize_v3(r_no);
931  }
932 
933  retval = true;
934 
935  if (r_index) {
936  em = sod->treedata_editmesh.em;
937 
938  *r_index = BM_elem_index_get(em->looptris[hit.index][0]->f);
939  }
940  }
941  }
942  }
943 
944  return retval;
945 }
946 
948  const float *ray_start;
949  const float *ray_dir;
951  /* read/write args */
952  float *ray_depth;
953  /* return args */
954  float *r_loc;
955  float *r_no;
956  int *r_index;
958  float (*r_obmat)[4];
961  bool ret;
962 };
963 
970  Object *ob,
971  float obmat[4][4],
972  bool use_obedit,
973  bool use_backface_culling,
974  bool is_object_active,
975  void *data)
976 {
977  struct RaycastObjUserData *dt = data;
978  const uint ob_index = dt->ob_index++;
980  /* read/write args */
981  float *ray_depth = dt->ray_depth;
982 
983  bool retval = false;
984  if (use_occlusion_test) {
985  if (use_obedit && sctx->use_v3d && XRAY_FLAG_ENABLED(sctx->v3d_data.v3d)) {
986  /* Use of occlude geometry in editing mode disabled. */
987  return;
988  }
989 
990  if (ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE)) {
991  /* Do not hit objects that are in wire or bounding box
992  * display mode. */
993  return;
994  }
995  }
996 
997  switch (ob->type) {
998  case OB_MESH: {
999  Mesh *me = ob->data;
1000  bool use_hide = false;
1001  if (BKE_object_is_in_editmode(ob)) {
1002  if (use_obedit || editmesh_eval_final_is_bmesh(me->edit_mesh)) {
1003  /* Operators only update the editmesh looptris of the original mesh. */
1005  retval = raycastEditMesh(sctx,
1006  dt->ray_start,
1007  dt->ray_dir,
1008  ob,
1009  em_orig,
1010  obmat,
1011  ob_index,
1012  use_backface_culling,
1013  ray_depth,
1014  dt->r_loc,
1015  dt->r_no,
1016  dt->r_index,
1017  dt->r_hit_list);
1018  break;
1019  }
1020 
1022  if (em->mesh_eval_final) {
1023  me = em->mesh_eval_final;
1024  use_hide = true;
1025  }
1026  }
1027  retval = raycastMesh(sctx,
1028  dt->ray_start,
1029  dt->ray_dir,
1030  ob,
1031  me,
1032  obmat,
1033  ob_index,
1034  use_hide,
1035  use_backface_culling,
1036  ray_depth,
1037  dt->r_loc,
1038  dt->r_no,
1039  dt->r_index,
1040  dt->r_hit_list);
1041  break;
1042  }
1043  case OB_CURVE:
1044  case OB_SURF:
1045  case OB_FONT: {
1046  if (!is_object_active) {
1047  Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
1048  if (mesh_eval) {
1049  retval = raycastMesh(sctx,
1050  dt->ray_start,
1051  dt->ray_dir,
1052  ob,
1053  mesh_eval,
1054  obmat,
1055  ob_index,
1056  false,
1057  use_backface_culling,
1058  ray_depth,
1059  dt->r_loc,
1060  dt->r_no,
1061  dt->r_index,
1062  dt->r_hit_list);
1063  }
1064  }
1065  break;
1066  }
1067  }
1068 
1069  if (retval) {
1070  if (dt->r_ob) {
1071  *dt->r_ob = ob;
1072  }
1073  if (dt->r_obmat) {
1074  copy_m4_m4(dt->r_obmat, obmat);
1075  }
1076  dt->ret = true;
1077  }
1078 }
1079 
1108  const struct SnapObjectParams *params,
1109  const float ray_start[3],
1110  const float ray_dir[3],
1111  /* read/write args */
1112  /* Parameters below cannot be const, because they are assigned to a
1113  * non-const variable (readability-non-const-parameter). */
1114  float *ray_depth /* NOLINT */,
1115  /* return args */
1116  float r_loc[3] /* NOLINT */,
1117  float r_no[3] /* NOLINT */,
1118  int *r_index /* NOLINT */,
1119  Object **r_ob,
1120  float r_obmat[4][4],
1122 {
1123  struct RaycastObjUserData data = {
1124  .ray_start = ray_start,
1125  .ray_dir = ray_dir,
1126  .ob_index = 0,
1127  .ray_depth = ray_depth,
1128  .r_loc = r_loc,
1129  .r_no = r_no,
1130  .r_index = r_index,
1131  .r_ob = r_ob,
1132  .r_obmat = r_obmat,
1133  .r_hit_list = r_hit_list,
1134  .use_occlusion_test = params->use_occlusion_test,
1135  .ret = false,
1136  };
1137 
1139 
1140  return data.ret;
1141 }
1142 
1145 /* -------------------------------------------------------------------- */
1149 /* Test BoundBox */
1150 static bool snap_bound_box_check_dist(const float min[3],
1151  const float max[3],
1152  const float lpmat[4][4],
1153  const float win_size[2],
1154  const float mval[2],
1155  float dist_px_sq)
1156 {
1157  /* In vertex and edges you need to get the pixel distance from ray to BoundBox,
1158  * see: T46099, T46816 */
1159 
1160  struct DistProjectedAABBPrecalc data_precalc;
1161  dist_squared_to_projected_aabb_precalc(&data_precalc, lpmat, win_size, mval);
1162 
1163  bool dummy[3];
1164  float bb_dist_px_sq = dist_squared_to_projected_aabb(&data_precalc, min, max, dummy);
1165 
1166  if (bb_dist_px_sq > dist_px_sq) {
1167  return false;
1168  }
1169  return true;
1170 }
1171 
1172 static void cb_mvert_co_get(const int index, const float **co, const BVHTreeFromMesh *data)
1173 {
1174  *co = data->vert[index].co;
1175 }
1176 
1177 static void cb_bvert_co_get(const int index, const float **co, const BMEditMesh *data)
1178 {
1179  BMVert *eve = BM_vert_at_index(data->bm, index);
1180  *co = eve->co;
1181 }
1182 
1183 static void cb_mvert_no_copy(const int index, float r_no[3], const BVHTreeFromMesh *data)
1184 {
1185  const MVert *vert = data->vert + index;
1186 
1187  normal_short_to_float_v3(r_no, vert->no);
1188 }
1189 
1190 static void cb_bvert_no_copy(const int index, float r_no[3], const BMEditMesh *data)
1191 {
1192  BMVert *eve = BM_vert_at_index(data->bm, index);
1193 
1194  copy_v3_v3(r_no, eve->no);
1195 }
1196 
1197 static void cb_medge_verts_get(const int index, int v_index[2], const BVHTreeFromMesh *data)
1198 {
1199  const MEdge *edge = &data->edge[index];
1200 
1201  v_index[0] = edge->v1;
1202  v_index[1] = edge->v2;
1203 }
1204 
1205 static void cb_bedge_verts_get(const int index, int v_index[2], const BMEditMesh *data)
1206 {
1207  BMEdge *eed = BM_edge_at_index(data->bm, index);
1208 
1209  v_index[0] = BM_elem_index_get(eed->v1);
1210  v_index[1] = BM_elem_index_get(eed->v2);
1211 }
1212 
1213 static void cb_mlooptri_edges_get(const int index, int v_index[3], const BVHTreeFromMesh *data)
1214 {
1215  const MEdge *medge = data->edge;
1216  const MLoop *mloop = data->loop;
1217  const MLoopTri *lt = &data->looptri[index];
1218  for (int j = 2, j_next = 0; j_next < 3; j = j_next++) {
1219  const MEdge *ed = &medge[mloop[lt->tri[j]].e];
1220  const uint tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v};
1221  if (ELEM(ed->v1, tri_edge[0], tri_edge[1]) && ELEM(ed->v2, tri_edge[0], tri_edge[1])) {
1222  // printf("real edge found\n");
1223  v_index[j] = mloop[lt->tri[j]].e;
1224  }
1225  else {
1226  v_index[j] = -1;
1227  }
1228  }
1229 }
1230 
1231 static void cb_mlooptri_verts_get(const int index, int v_index[3], const BVHTreeFromMesh *data)
1232 {
1233  const MLoop *loop = data->loop;
1234  const MLoopTri *looptri = &data->looptri[index];
1235 
1236  v_index[0] = loop[looptri->tri[0]].v;
1237  v_index[1] = loop[looptri->tri[1]].v;
1238  v_index[2] = loop[looptri->tri[2]].v;
1239 }
1240 
1241 static bool test_projected_vert_dist(const struct DistProjectedAABBPrecalc *precalc,
1242  const float (*clip_plane)[4],
1243  const int clip_plane_len,
1244  const bool is_persp,
1245  const float co[3],
1246  float *dist_px_sq,
1247  float r_co[3])
1248 {
1249  if (!isect_point_planes_v3_negated(clip_plane, clip_plane_len, co)) {
1250  return false;
1251  }
1252 
1253  float co2d[2] = {
1254  (dot_m4_v3_row_x(precalc->pmat, co) + precalc->pmat[3][0]),
1255  (dot_m4_v3_row_y(precalc->pmat, co) + precalc->pmat[3][1]),
1256  };
1257 
1258  if (is_persp) {
1259  float w = mul_project_m4_v3_zfac(precalc->pmat, co);
1260  mul_v2_fl(co2d, 1.0f / w);
1261  }
1262 
1263  const float dist_sq = len_squared_v2v2(precalc->mval, co2d);
1264  if (dist_sq < *dist_px_sq) {
1265  copy_v3_v3(r_co, co);
1266  *dist_px_sq = dist_sq;
1267  return true;
1268  }
1269  return false;
1270 }
1271 
1272 static bool test_projected_edge_dist(const struct DistProjectedAABBPrecalc *precalc,
1273  const float (*clip_plane)[4],
1274  const int clip_plane_len,
1275  const bool is_persp,
1276  const float va[3],
1277  const float vb[3],
1278  float *dist_px_sq,
1279  float r_co[3])
1280 {
1281  float near_co[3], lambda;
1282  if (!isect_ray_line_v3(precalc->ray_origin, precalc->ray_direction, va, vb, &lambda)) {
1283  copy_v3_v3(near_co, va);
1284  }
1285  else {
1286  if (lambda <= 0.0f) {
1287  copy_v3_v3(near_co, va);
1288  }
1289  else if (lambda >= 1.0f) {
1290  copy_v3_v3(near_co, vb);
1291  }
1292  else {
1293  interp_v3_v3v3(near_co, va, vb, lambda);
1294  }
1295  }
1296 
1297  return test_projected_vert_dist(
1298  precalc, clip_plane, clip_plane_len, is_persp, near_co, dist_px_sq, r_co);
1299 }
1300 
1303 /* -------------------------------------------------------------------- */
1307 typedef void (*Nearest2DGetVertCoCallback)(const int index, const float **co, void *data);
1308 typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, const int v_index[2], void *data);
1309 typedef void (*Nearest2DGetTriVertsCallback)(const int index, const int v_index[3], void *data);
1310 /* Equal the previous one */
1311 typedef void (*Nearest2DGetTriEdgesCallback)(const int index, const int e_index[3], void *data);
1312 typedef void (*Nearest2DCopyVertNoCallback)(const int index, const float r_no[3], void *data);
1313 
1314 typedef struct Nearest2dUserData {
1315  void *userdata;
1321 
1322  bool is_persp;
1325 
1326 static void cb_snap_vert(void *userdata,
1327  int index,
1328  const struct DistProjectedAABBPrecalc *precalc,
1329  const float (*clip_plane)[4],
1330  const int clip_plane_len,
1331  BVHTreeNearest *nearest)
1332 {
1333  struct Nearest2dUserData *data = userdata;
1334 
1335  const float *co;
1336  data->get_vert_co(index, &co, data->userdata);
1337 
1338  if (test_projected_vert_dist(precalc,
1339  clip_plane,
1340  clip_plane_len,
1341  data->is_persp,
1342  co,
1343  &nearest->dist_sq,
1344  nearest->co)) {
1345  data->copy_vert_no(index, nearest->no, data->userdata);
1346  nearest->index = index;
1347  }
1348 }
1349 
1350 static void cb_snap_edge(void *userdata,
1351  int index,
1352  const struct DistProjectedAABBPrecalc *precalc,
1353  const float (*clip_plane)[4],
1354  const int clip_plane_len,
1355  BVHTreeNearest *nearest)
1356 {
1357  struct Nearest2dUserData *data = userdata;
1358 
1359  int vindex[2];
1360  data->get_edge_verts_index(index, vindex, data->userdata);
1361 
1362  const float *v_pair[2];
1363  data->get_vert_co(vindex[0], &v_pair[0], data->userdata);
1364  data->get_vert_co(vindex[1], &v_pair[1], data->userdata);
1365 
1366  if (test_projected_edge_dist(precalc,
1367  clip_plane,
1368  clip_plane_len,
1369  data->is_persp,
1370  v_pair[0],
1371  v_pair[1],
1372  &nearest->dist_sq,
1373  nearest->co)) {
1374  sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
1375  nearest->index = index;
1376  }
1377 }
1378 
1379 static void cb_snap_edge_verts(void *userdata,
1380  int index,
1381  const struct DistProjectedAABBPrecalc *precalc,
1382  const float (*clip_plane)[4],
1383  const int clip_plane_len,
1384  BVHTreeNearest *nearest)
1385 {
1386  struct Nearest2dUserData *data = userdata;
1387 
1388  int vindex[2];
1389  data->get_edge_verts_index(index, vindex, data->userdata);
1390 
1391  for (int i = 2; i--;) {
1392  if (vindex[i] == nearest->index) {
1393  continue;
1394  }
1395  cb_snap_vert(userdata, vindex[i], precalc, clip_plane, clip_plane_len, nearest);
1396  }
1397 }
1398 
1399 static void cb_snap_tri_edges(void *userdata,
1400  int index,
1401  const struct DistProjectedAABBPrecalc *precalc,
1402  const float (*clip_plane)[4],
1403  const int clip_plane_len,
1404  BVHTreeNearest *nearest)
1405 {
1406  struct Nearest2dUserData *data = userdata;
1407 
1408  if (data->use_backface_culling) {
1409  int vindex[3];
1410  data->get_tri_verts_index(index, vindex, data->userdata);
1411 
1412  const float *t0, *t1, *t2;
1413  data->get_vert_co(vindex[0], &t0, data->userdata);
1414  data->get_vert_co(vindex[1], &t1, data->userdata);
1415  data->get_vert_co(vindex[2], &t2, data->userdata);
1416  float dummy[3];
1417  if (raycast_tri_backface_culling_test(precalc->ray_direction, t0, t1, t2, dummy)) {
1418  return;
1419  }
1420  }
1421 
1422  int eindex[3];
1423  data->get_tri_edges_index(index, eindex, data->userdata);
1424  for (int i = 3; i--;) {
1425  if (eindex[i] != -1) {
1426  if (eindex[i] == nearest->index) {
1427  continue;
1428  }
1429  cb_snap_edge(userdata, eindex[i], precalc, clip_plane, clip_plane_len, nearest);
1430  }
1431  }
1432 }
1433 
1434 static void cb_snap_tri_verts(void *userdata,
1435  int index,
1436  const struct DistProjectedAABBPrecalc *precalc,
1437  const float (*clip_plane)[4],
1438  const int clip_plane_len,
1439  BVHTreeNearest *nearest)
1440 {
1441  struct Nearest2dUserData *data = userdata;
1442 
1443  int vindex[3];
1444  data->get_tri_verts_index(index, vindex, data->userdata);
1445 
1446  if (data->use_backface_culling) {
1447  const float *t0, *t1, *t2;
1448  data->get_vert_co(vindex[0], &t0, data->userdata);
1449  data->get_vert_co(vindex[1], &t1, data->userdata);
1450  data->get_vert_co(vindex[2], &t2, data->userdata);
1451  float dummy[3];
1452  if (raycast_tri_backface_culling_test(precalc->ray_direction, t0, t1, t2, dummy)) {
1453  return;
1454  }
1455  }
1456 
1457  for (int i = 3; i--;) {
1458  if (vindex[i] == nearest->index) {
1459  continue;
1460  }
1461  cb_snap_vert(userdata, vindex[i], precalc, clip_plane, clip_plane_len, nearest);
1462  }
1463 }
1464 
1467 /* -------------------------------------------------------------------- */
1472  SnapData *snapdata,
1473  Object *ob,
1474  const float obmat[4][4],
1475  bool use_backface_culling,
1476  /* read/write args */
1477  float *dist_px,
1478  /* return args */
1479  float r_loc[3],
1480  float r_no[3],
1481  int *r_index)
1482 {
1483  short elem = 0;
1484 
1485  float lpmat[4][4];
1486  mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
1487 
1488  struct DistProjectedAABBPrecalc neasrest_precalc;
1490  &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
1491 
1492  float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
1493  transpose_m4_m4(tobmat, obmat);
1494  for (int i = snapdata->clip_plane_len; i--;) {
1495  mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
1496  }
1497 
1498  Nearest2dUserData nearest2d = {
1499  .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
1500  .use_backface_culling = use_backface_culling,
1501  };
1502 
1503  BVHTreeNearest nearest = {
1504  .index = -1,
1505  .dist_sq = square_f(*dist_px),
1506  };
1507 
1508  SnapObjectData *sod = snap_object_data_lookup(sctx, ob);
1509 
1510  BLI_assert(sod != NULL);
1511 
1512  if (sod->type == SNAP_MESH) {
1513  BVHTreeFromMesh *treedata = &sod->treedata_mesh;
1514 
1515  nearest2d.userdata = treedata;
1519 
1520  const MPoly *mp = &sod->poly[*r_index];
1521  const MLoop *ml = &treedata->loop[mp->loopstart];
1522  if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
1523  elem = SCE_SNAP_MODE_EDGE;
1524  BLI_assert(treedata->edge != NULL);
1525  for (int i = mp->totloop; i--; ml++) {
1526  cb_snap_edge(&nearest2d,
1527  ml->e,
1528  &neasrest_precalc,
1529  clip_planes_local,
1530  snapdata->clip_plane_len,
1531  &nearest);
1532  }
1533  }
1534  else {
1535  elem = SCE_SNAP_MODE_VERTEX;
1536  for (int i = mp->totloop; i--; ml++) {
1537  cb_snap_vert(&nearest2d,
1538  ml->v,
1539  &neasrest_precalc,
1540  clip_planes_local,
1541  snapdata->clip_plane_len,
1542  &nearest);
1543  }
1544  }
1545  }
1546  else {
1547  BLI_assert(sod->type == SNAP_EDIT_MESH);
1548  BMEditMesh *em = sod->treedata_editmesh.em;
1549 
1550  nearest2d.userdata = em;
1554 
1556  BMFace *f = BM_face_at_index(em->bm, *r_index);
1557  BMLoop *l_iter, *l_first;
1558  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
1559  if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
1560  elem = SCE_SNAP_MODE_EDGE;
1563  do {
1564  cb_snap_edge(&nearest2d,
1565  BM_elem_index_get(l_iter->e),
1566  &neasrest_precalc,
1567  clip_planes_local,
1568  snapdata->clip_plane_len,
1569  &nearest);
1570  } while ((l_iter = l_iter->next) != l_first);
1571  }
1572  else {
1573  elem = SCE_SNAP_MODE_VERTEX;
1576  do {
1577  cb_snap_vert(&nearest2d,
1578  BM_elem_index_get(l_iter->v),
1579  &neasrest_precalc,
1580  clip_planes_local,
1581  snapdata->clip_plane_len,
1582  &nearest);
1583  } while ((l_iter = l_iter->next) != l_first);
1584  }
1585  }
1586 
1587  if (nearest.index != -1) {
1588  *dist_px = sqrtf(nearest.dist_sq);
1589 
1590  copy_v3_v3(r_loc, nearest.co);
1591  mul_m4_v3(obmat, r_loc);
1592 
1593  if (r_no) {
1594  float imat[4][4];
1595  invert_m4_m4(imat, obmat);
1596 
1597  copy_v3_v3(r_no, nearest.no);
1598  mul_transposed_mat3_m4_v3(imat, r_no);
1599  normalize_v3(r_no);
1600  }
1601 
1602  *r_index = nearest.index;
1603  return elem;
1604  }
1605 
1606  return 0;
1607 }
1608 
1610  SnapData *snapdata,
1611  Object *ob,
1612  const float obmat[4][4],
1613  float original_dist_px,
1614  const float prev_co[3],
1615  bool use_backface_culling,
1616  /* read/write args */
1617  float *dist_px,
1618  /* return args */
1619  float r_loc[3],
1620  float r_no[3],
1621  int *r_index)
1622 {
1623  short elem = SCE_SNAP_MODE_EDGE;
1624 
1625  if (ob->type != OB_MESH) {
1626  return elem;
1627  }
1628 
1629  SnapObjectData *sod = snap_object_data_lookup(sctx, ob);
1630 
1631  BLI_assert(sod != NULL);
1632 
1633  Nearest2dUserData nearest2d;
1634  {
1635  nearest2d.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
1636  nearest2d.use_backface_culling = use_backface_culling;
1637  if (sod->type == SNAP_MESH) {
1638  nearest2d.userdata = &sod->treedata_mesh;
1642  }
1643  else {
1644  BLI_assert(sod->type == SNAP_EDIT_MESH);
1645  nearest2d.userdata = sod->treedata_editmesh.em;
1649  }
1650  }
1651 
1652  int vindex[2];
1653  nearest2d.get_edge_verts_index(*r_index, vindex, nearest2d.userdata);
1654 
1655  const float *v_pair[2];
1656  nearest2d.get_vert_co(vindex[0], &v_pair[0], nearest2d.userdata);
1657  nearest2d.get_vert_co(vindex[1], &v_pair[1], nearest2d.userdata);
1658 
1659  struct DistProjectedAABBPrecalc neasrest_precalc;
1660  {
1661  float lpmat[4][4];
1662  mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
1663 
1665  &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
1666  }
1667 
1668  BVHTreeNearest nearest = {
1669  .index = -1,
1670  .dist_sq = square_f(original_dist_px),
1671  };
1672 
1673  float lambda;
1674  if (!isect_ray_line_v3(neasrest_precalc.ray_origin,
1675  neasrest_precalc.ray_direction,
1676  v_pair[0],
1677  v_pair[1],
1678  &lambda)) {
1679  /* do nothing */
1680  }
1681  else {
1682  short snap_to_flag = snapdata->snap_to_flag;
1683  int e_mode_len = ((snap_to_flag & SCE_SNAP_MODE_EDGE) != 0) +
1684  ((snap_to_flag & SCE_SNAP_MODE_VERTEX) != 0) +
1685  ((snap_to_flag & SCE_SNAP_MODE_EDGE_MIDPOINT) != 0);
1686 
1687  float range = 1.0f / (2 * e_mode_len - 1);
1688  if (snap_to_flag & SCE_SNAP_MODE_VERTEX) {
1689  if (lambda < (range) || (1.0f - range) < lambda) {
1690  int v_id = lambda < 0.5f ? 0 : 1;
1691 
1692  if (test_projected_vert_dist(&neasrest_precalc,
1693  NULL,
1694  0,
1695  nearest2d.is_persp,
1696  v_pair[v_id],
1697  &nearest.dist_sq,
1698  nearest.co)) {
1699  nearest.index = vindex[v_id];
1700  elem = SCE_SNAP_MODE_VERTEX;
1701  if (r_no) {
1702  float imat[4][4];
1703  invert_m4_m4(imat, obmat);
1704  nearest2d.copy_vert_no(vindex[v_id], r_no, nearest2d.userdata);
1705  mul_transposed_mat3_m4_v3(imat, r_no);
1706  normalize_v3(r_no);
1707  }
1708  }
1709  }
1710  }
1711 
1712  if (snap_to_flag & SCE_SNAP_MODE_EDGE_MIDPOINT) {
1713  range *= e_mode_len - 1;
1714  if ((range) < lambda && lambda < (1.0f - range)) {
1715  float vmid[3];
1716  mid_v3_v3v3(vmid, v_pair[0], v_pair[1]);
1717 
1718  if (test_projected_vert_dist(&neasrest_precalc,
1719  NULL,
1720  0,
1721  nearest2d.is_persp,
1722  vmid,
1723  &nearest.dist_sq,
1724  nearest.co)) {
1725  nearest.index = *r_index;
1727  }
1728  }
1729  }
1730 
1731  if (prev_co && (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
1732  float v_near[3], va_g[3], vb_g[3];
1733 
1734  mul_v3_m4v3(va_g, obmat, v_pair[0]);
1735  mul_v3_m4v3(vb_g, obmat, v_pair[1]);
1736  lambda = line_point_factor_v3(prev_co, va_g, vb_g);
1737 
1738  if (IN_RANGE(lambda, 0.0f, 1.0f)) {
1739  interp_v3_v3v3(v_near, va_g, vb_g, lambda);
1740 
1741  if (len_squared_v3v3(prev_co, v_near) > FLT_EPSILON) {
1743  &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
1744 
1745  if (test_projected_vert_dist(&neasrest_precalc,
1746  NULL,
1747  0,
1748  nearest2d.is_persp,
1749  v_near,
1750  &nearest.dist_sq,
1751  nearest.co)) {
1752  nearest.index = *r_index;
1754  }
1755  }
1756  }
1757  }
1758  }
1759 
1760  if (nearest.index != -1) {
1761  *dist_px = sqrtf(nearest.dist_sq);
1762 
1763  copy_v3_v3(r_loc, nearest.co);
1764  if (elem != SCE_SNAP_MODE_EDGE_PERPENDICULAR) {
1765  mul_m4_v3(obmat, r_loc);
1766  }
1767 
1768  *r_index = nearest.index;
1769  }
1770 
1771  return elem;
1772 }
1773 
1774 static short snapArmature(SnapData *snapdata,
1775  Object *ob,
1776  const float obmat[4][4],
1777  bool use_obedit,
1778  /* read/write args */
1779  float *dist_px,
1780  /* return args */
1781  float r_loc[3],
1782  float *UNUSED(r_no),
1783  int *r_index)
1784 {
1785  short retval = 0;
1786 
1787  if (snapdata->snap_to_flag == SCE_SNAP_MODE_FACE) { /* Currently only edge and vert */
1788  return retval;
1789  }
1790 
1791  float lpmat[4][4], dist_px_sq = square_f(*dist_px);
1792  mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
1793 
1794  struct DistProjectedAABBPrecalc neasrest_precalc;
1796  &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
1797 
1798  use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
1799 
1800  if (use_obedit == false) {
1801  /* Test BoundBox */
1803  if (bb && !snap_bound_box_check_dist(
1804  bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
1805  return retval;
1806  }
1807  }
1808 
1809  float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
1810  transpose_m4_m4(tobmat, obmat);
1811  for (int i = snapdata->clip_plane_len; i--;) {
1812  mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
1813  }
1814 
1815  bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
1816 
1817  bArmature *arm = ob->data;
1818  if (arm->edbo) {
1819  LISTBASE_FOREACH (EditBone *, eBone, arm->edbo) {
1820  if (eBone->layer & arm->layer) {
1821  /* skip hidden or moving (selected) bones */
1822  if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
1823  bool has_vert_snap = false;
1824 
1825  if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
1826  has_vert_snap = test_projected_vert_dist(&neasrest_precalc,
1827  clip_planes_local,
1828  snapdata->clip_plane_len,
1829  is_persp,
1830  eBone->head,
1831  &dist_px_sq,
1832  r_loc);
1833  has_vert_snap |= test_projected_vert_dist(&neasrest_precalc,
1834  clip_planes_local,
1835  snapdata->clip_plane_len,
1836  is_persp,
1837  eBone->tail,
1838  &dist_px_sq,
1839  r_loc);
1840 
1841  if (has_vert_snap) {
1842  retval = SCE_SNAP_MODE_VERTEX;
1843  }
1844  }
1845  if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
1846  if (test_projected_edge_dist(&neasrest_precalc,
1847  clip_planes_local,
1848  snapdata->clip_plane_len,
1849  is_persp,
1850  eBone->head,
1851  eBone->tail,
1852  &dist_px_sq,
1853  r_loc)) {
1854  retval = SCE_SNAP_MODE_EDGE;
1855  }
1856  }
1857  }
1858  }
1859  }
1860  }
1861  else if (ob->pose && ob->pose->chanbase.first) {
1862  LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
1863  Bone *bone = pchan->bone;
1864  /* skip hidden bones */
1865  if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
1866  bool has_vert_snap = false;
1867  const float *head_vec = pchan->pose_head;
1868  const float *tail_vec = pchan->pose_tail;
1869 
1870  if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
1871  has_vert_snap = test_projected_vert_dist(&neasrest_precalc,
1872  clip_planes_local,
1873  snapdata->clip_plane_len,
1874  is_persp,
1875  head_vec,
1876  &dist_px_sq,
1877  r_loc);
1878  has_vert_snap |= test_projected_vert_dist(&neasrest_precalc,
1879  clip_planes_local,
1880  snapdata->clip_plane_len,
1881  is_persp,
1882  tail_vec,
1883  &dist_px_sq,
1884  r_loc);
1885 
1886  if (has_vert_snap) {
1887  retval = SCE_SNAP_MODE_VERTEX;
1888  }
1889  }
1890  if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
1891  if (test_projected_edge_dist(&neasrest_precalc,
1892  clip_planes_local,
1893  snapdata->clip_plane_len,
1894  is_persp,
1895  head_vec,
1896  tail_vec,
1897  &dist_px_sq,
1898  r_loc)) {
1899  retval = SCE_SNAP_MODE_EDGE;
1900  }
1901  }
1902  }
1903  }
1904  }
1905 
1906  if (retval) {
1907  *dist_px = sqrtf(dist_px_sq);
1908  mul_m4_v3(obmat, r_loc);
1909  if (r_index) {
1910  /* Does not support index. */
1911  *r_index = -1;
1912  }
1913  return retval;
1914  }
1915 
1916  return 0;
1917 }
1918 
1919 static short snapCurve(SnapData *snapdata,
1920  Object *ob,
1921  const float obmat[4][4],
1922  bool use_obedit,
1923  /* read/write args */
1924  float *dist_px,
1925  /* return args */
1926  float r_loc[3],
1927  float *UNUSED(r_no),
1928  int *r_index)
1929 {
1930  bool has_snap = false;
1931 
1932  /* only vertex snapping mode (eg control points and handles) supported for now) */
1933  if ((snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) == 0) {
1934  return 0;
1935  }
1936 
1937  Curve *cu = ob->data;
1938  float dist_px_sq = square_f(*dist_px);
1939 
1940  float lpmat[4][4];
1941  mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
1942 
1943  struct DistProjectedAABBPrecalc neasrest_precalc;
1945  &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
1946 
1947  use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
1948 
1949  if (use_obedit == false) {
1950  /* Test BoundBox */
1951  BoundBox *bb = BKE_curve_boundbox_get(ob);
1952  if (bb && !snap_bound_box_check_dist(
1953  bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
1954  return 0;
1955  }
1956  }
1957 
1958  float tobmat[4][4];
1959  transpose_m4_m4(tobmat, obmat);
1960 
1961  float(*clip_planes)[4] = snapdata->clip_plane;
1962  int clip_plane_len = snapdata->clip_plane_len;
1963 
1964  if (snapdata->has_occlusion_plane) {
1965  /* We snap to vertices even if occluded. */
1966  clip_planes++;
1967  clip_plane_len--;
1968  }
1969 
1970  float clip_planes_local[MAX_CLIPPLANE_LEN][4];
1971  for (int i = clip_plane_len; i--;) {
1972  mul_v4_m4v4(clip_planes_local[i], tobmat, clip_planes[i]);
1973  }
1974 
1975  bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
1976 
1977  for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
1978  for (int u = 0; u < nu->pntsu; u++) {
1979  if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
1980  if (use_obedit) {
1981  if (nu->bezt) {
1982  /* don't snap to selected (moving) or hidden */
1983  if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
1984  continue;
1985  }
1986  has_snap |= test_projected_vert_dist(&neasrest_precalc,
1987  clip_planes_local,
1988  clip_plane_len,
1989  is_persp,
1990  nu->bezt[u].vec[1],
1991  &dist_px_sq,
1992  r_loc);
1993  /* Don't snap if handle is selected (moving),
1994  * or if it is aligning to a moving handle. */
1995  if (!(nu->bezt[u].f1 & SELECT) &&
1996  !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT)) {
1997  has_snap |= test_projected_vert_dist(&neasrest_precalc,
1998  clip_planes_local,
1999  clip_plane_len,
2000  is_persp,
2001  nu->bezt[u].vec[0],
2002  &dist_px_sq,
2003  r_loc);
2004  }
2005  if (!(nu->bezt[u].f3 & SELECT) &&
2006  !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT)) {
2007  has_snap |= test_projected_vert_dist(&neasrest_precalc,
2008  clip_planes_local,
2009  clip_plane_len,
2010  is_persp,
2011  nu->bezt[u].vec[2],
2012  &dist_px_sq,
2013  r_loc);
2014  }
2015  }
2016  else {
2017  /* don't snap to selected (moving) or hidden */
2018  if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
2019  continue;
2020  }
2021  has_snap |= test_projected_vert_dist(&neasrest_precalc,
2022  clip_planes_local,
2023  clip_plane_len,
2024  is_persp,
2025  nu->bp[u].vec,
2026  &dist_px_sq,
2027  r_loc);
2028  }
2029  }
2030  else {
2031  /* curve is not visible outside editmode if nurb length less than two */
2032  if (nu->pntsu > 1) {
2033  if (nu->bezt) {
2034  has_snap |= test_projected_vert_dist(&neasrest_precalc,
2035  clip_planes_local,
2036  clip_plane_len,
2037  is_persp,
2038  nu->bezt[u].vec[1],
2039  &dist_px_sq,
2040  r_loc);
2041  }
2042  else {
2043  has_snap |= test_projected_vert_dist(&neasrest_precalc,
2044  clip_planes_local,
2045  clip_plane_len,
2046  is_persp,
2047  nu->bp[u].vec,
2048  &dist_px_sq,
2049  r_loc);
2050  }
2051  }
2052  }
2053  }
2054  }
2055  }
2056  if (has_snap) {
2057  *dist_px = sqrtf(dist_px_sq);
2058  mul_m4_v3(obmat, r_loc);
2059  if (r_index) {
2060  /* Does not support index yet. */
2061  *r_index = -1;
2062  }
2063  return SCE_SNAP_MODE_VERTEX;
2064  }
2065 
2066  return 0;
2067 }
2068 
2069 /* may extend later (for now just snaps to empty center) */
2070 static short snap_object_center(SnapData *snapdata,
2071  Object *ob,
2072  const float obmat[4][4],
2073  /* read/write args */
2074  float *dist_px,
2075  /* return args */
2076  float r_loc[3],
2077  float *UNUSED(r_no),
2078  int *r_index)
2079 {
2080  short retval = 0;
2081 
2082  if (ob->transflag & OB_DUPLI) {
2083  return retval;
2084  }
2085 
2086  /* for now only vertex supported */
2087  if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
2088  struct DistProjectedAABBPrecalc neasrest_precalc;
2090  &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
2091 
2092  float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
2093  transpose_m4_m4(tobmat, obmat);
2094  for (int i = snapdata->clip_plane_len; i--;) {
2095  mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
2096  }
2097 
2098  bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
2099  float dist_px_sq = square_f(*dist_px);
2100  float co[3];
2101  copy_v3_v3(co, obmat[3]);
2102  if (test_projected_vert_dist(&neasrest_precalc,
2103  clip_planes_local,
2104  snapdata->clip_plane_len,
2105  is_persp,
2106  co,
2107  &dist_px_sq,
2108  r_loc)) {
2109  *dist_px = sqrtf(dist_px_sq);
2110  retval = SCE_SNAP_MODE_VERTEX;
2111  }
2112  }
2113 
2114  if (retval) {
2115  if (r_index) {
2116  /* Does not support index. */
2117  *r_index = -1;
2118  }
2119  return retval;
2120  }
2121 
2122  return 0;
2123 }
2124 
2125 static short snapCamera(const SnapObjectContext *sctx,
2126  SnapData *snapdata,
2127  Object *object,
2128  float obmat[4][4],
2129  /* read/write args */
2130  float *dist_px,
2131  /* return args */
2132  float r_loc[3],
2133  float *r_no,
2134  int *r_index)
2135 {
2136  short retval = 0;
2137 
2138  Scene *scene = sctx->scene;
2139 
2140  bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
2141  float dist_px_sq = square_f(*dist_px);
2142 
2143  float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
2144  MovieClip *clip = BKE_object_movieclip_get(scene, object, false);
2145  MovieTracking *tracking;
2146 
2147  if (clip == NULL) {
2148  return snap_object_center(snapdata, object, obmat, dist_px, r_loc, r_no, r_index);
2149  }
2150  if (object->transflag & OB_DUPLI) {
2151  return retval;
2152  }
2153 
2154  tracking = &clip->tracking;
2155 
2156  BKE_tracking_get_camera_object_matrix(object, orig_camera_mat);
2157 
2158  invert_m4_m4(orig_camera_imat, orig_camera_mat);
2159  invert_m4_m4(imat, obmat);
2160 
2161  if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
2162  struct DistProjectedAABBPrecalc neasrest_precalc;
2164  &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
2165 
2166  MovieTrackingObject *tracking_object;
2167  for (tracking_object = tracking->objects.first; tracking_object;
2168  tracking_object = tracking_object->next) {
2169  ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
2170  MovieTrackingTrack *track;
2171  float reconstructed_camera_mat[4][4], reconstructed_camera_imat[4][4];
2172  float(*vertex_obmat)[4];
2173 
2174  if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
2176  tracking, tracking_object, CFRA, reconstructed_camera_mat);
2177 
2178  invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat);
2179  }
2180 
2181  for (track = tracksbase->first; track; track = track->next) {
2182  float bundle_pos[3];
2183 
2184  if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
2185  continue;
2186  }
2187 
2188  copy_v3_v3(bundle_pos, track->bundle_pos);
2189  if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
2190  vertex_obmat = orig_camera_mat;
2191  }
2192  else {
2193  mul_m4_v3(reconstructed_camera_imat, bundle_pos);
2194  vertex_obmat = obmat;
2195  }
2196 
2197  mul_m4_v3(vertex_obmat, bundle_pos);
2198  if (test_projected_vert_dist(&neasrest_precalc,
2199  snapdata->clip_plane,
2200  snapdata->clip_plane_len,
2201  is_persp,
2202  bundle_pos,
2203  &dist_px_sq,
2204  r_loc)) {
2205  retval = SCE_SNAP_MODE_VERTEX;
2206  }
2207  }
2208  }
2209  }
2210 
2211  if (retval) {
2212  *dist_px = sqrtf(dist_px_sq);
2213  if (r_index) {
2214  /* Does not support index. */
2215  *r_index = -1;
2216  }
2217  return retval;
2218  }
2219 
2220  return 0;
2221 }
2222 
2223 static short snapMesh(SnapObjectContext *sctx,
2224  SnapData *snapdata,
2225  Object *ob,
2226  Mesh *me,
2227  const float obmat[4][4],
2228  bool use_backface_culling,
2229  /* read/write args */
2230  float *dist_px,
2231  /* return args */
2232  float r_loc[3],
2233  float r_no[3],
2234  int *r_index)
2235 {
2237  if (me->totvert == 0) {
2238  return 0;
2239  }
2240  if (me->totedge == 0 && !(snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
2241  return 0;
2242  }
2243 
2244  float lpmat[4][4];
2245  mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
2246 
2247  float dist_px_sq = square_f(*dist_px);
2248 
2249  /* Test BoundBox */
2250  BoundBox *bb = BKE_mesh_boundbox_get(ob);
2251  if (bb && !snap_bound_box_check_dist(
2252  bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
2253  return 0;
2254  }
2255 
2256  SnapObjectData *sod = snap_object_data_mesh_get(sctx, ob);
2257 
2258  BVHTreeFromMesh *treedata, dummy_treedata;
2259  treedata = &sod->treedata_mesh;
2260 
2261  /* The tree is owned by the Mesh and may have been freed since we last used! */
2262  if (treedata->cached && treedata->tree &&
2263  !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
2264  free_bvhtree_from_mesh(treedata);
2265  }
2266  if (sod->cached[0] && sod->bvhtree[0] &&
2267  !bvhcache_has_tree(me->runtime.bvh_cache, sod->bvhtree[0])) {
2268  sod->bvhtree[0] = NULL;
2269  }
2270  if (sod->cached[1] && sod->bvhtree[1] &&
2271  !bvhcache_has_tree(me->runtime.bvh_cache, sod->bvhtree[1])) {
2272  sod->bvhtree[1] = NULL;
2273  }
2274 
2275  if (sod->has_looptris && treedata->tree == NULL) {
2277  sod->has_looptris = (treedata->tree != NULL);
2278  if (sod->has_looptris) {
2279  /* Make sure that the array of edges is referenced in the callbacks. */
2280  treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
2281  }
2282  }
2283  if (sod->has_loose_edge && sod->bvhtree[0] == NULL) {
2284  sod->bvhtree[0] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEEDGES, 2);
2285  sod->has_loose_edge = sod->bvhtree[0] != NULL;
2286  sod->cached[0] = dummy_treedata.cached;
2287 
2288  if (sod->has_loose_edge) {
2289  BLI_assert(treedata->vert_allocated == false);
2290  treedata->vert = dummy_treedata.vert;
2291  treedata->vert_allocated = dummy_treedata.vert_allocated;
2292 
2293  BLI_assert(treedata->edge_allocated == false);
2294  treedata->edge = dummy_treedata.edge;
2295  treedata->edge_allocated = dummy_treedata.edge_allocated;
2296  }
2297  }
2298  if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
2299  if (sod->has_loose_vert && sod->bvhtree[1] == NULL) {
2300  sod->bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2);
2301  sod->has_loose_vert = sod->bvhtree[1] != NULL;
2302  sod->cached[1] = dummy_treedata.cached;
2303 
2304  if (sod->has_loose_vert) {
2305  BLI_assert(treedata->vert_allocated == false);
2306  treedata->vert = dummy_treedata.vert;
2307  treedata->vert_allocated = dummy_treedata.vert_allocated;
2308  }
2309  }
2310  }
2311  else {
2312  /* Not necessary, just to keep the data more consistent. */
2313  sod->has_loose_vert = false;
2314  }
2315 
2316  /* Update pointers. */
2317  if (treedata->vert_allocated == false) {
2318  treedata->vert = me->mvert; /* CustomData_get_layer(&me->vdata, CD_MVERT);? */
2319  }
2320  if (treedata->tree || sod->bvhtree[0]) {
2321  if (treedata->edge_allocated == false) {
2322  /* If raycast has been executed before, `treedata->edge` can be NULL. */
2323  treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
2324  }
2325  if (treedata->loop && treedata->loop_allocated == false) {
2326  treedata->loop = me->mloop; /* CustomData_get_layer(&me->edata, CD_MLOOP);? */
2327  }
2328  if (treedata->looptri && treedata->looptri_allocated == false) {
2329  treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
2330  }
2331  }
2332 
2333  Nearest2dUserData nearest2d = {
2334  .userdata = treedata,
2336  .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get,
2337  .get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get,
2338  .get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get,
2340  .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
2341  .use_backface_culling = use_backface_culling,
2342  };
2343 
2344  BVHTreeNearest nearest = {
2345  .index = -1,
2346  .dist_sq = dist_px_sq,
2347  };
2348  int last_index = nearest.index;
2349  short elem = SCE_SNAP_MODE_VERTEX;
2350 
2351  float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
2352  transpose_m4_m4(tobmat, obmat);
2353  for (int i = snapdata->clip_plane_len; i--;) {
2354  mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
2355  }
2356 
2357  if (sod->bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
2358  /* snap to loose verts */
2360  lpmat,
2361  snapdata->win_size,
2362  snapdata->mval,
2363  clip_planes_local,
2364  snapdata->clip_plane_len,
2365  &nearest,
2366  cb_snap_vert,
2367  &nearest2d);
2368 
2369  last_index = nearest.index;
2370  }
2371 
2372  if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
2373  if (sod->bvhtree[0]) {
2374  /* snap to loose edges */
2376  lpmat,
2377  snapdata->win_size,
2378  snapdata->mval,
2379  clip_planes_local,
2380  snapdata->clip_plane_len,
2381  &nearest,
2382  cb_snap_edge,
2383  &nearest2d);
2384  }
2385 
2386  if (treedata->tree) {
2387  /* snap to looptris */
2389  lpmat,
2390  snapdata->win_size,
2391  snapdata->mval,
2392  clip_planes_local,
2393  snapdata->clip_plane_len,
2394  &nearest,
2396  &nearest2d);
2397  }
2398 
2399  if (last_index != nearest.index) {
2400  elem = SCE_SNAP_MODE_EDGE;
2401  }
2402  }
2403  else {
2405  if (sod->bvhtree[0]) {
2406  /* snap to loose edge verts */
2408  lpmat,
2409  snapdata->win_size,
2410  snapdata->mval,
2411  clip_planes_local,
2412  snapdata->clip_plane_len,
2413  &nearest,
2415  &nearest2d);
2416  }
2417 
2418  if (treedata->tree) {
2419  /* snap to looptri verts */
2421  lpmat,
2422  snapdata->win_size,
2423  snapdata->mval,
2424  clip_planes_local,
2425  snapdata->clip_plane_len,
2426  &nearest,
2428  &nearest2d);
2429  }
2430  }
2431 
2432  if (nearest.index != -1) {
2433  *dist_px = sqrtf(nearest.dist_sq);
2434 
2435  copy_v3_v3(r_loc, nearest.co);
2436  mul_m4_v3(obmat, r_loc);
2437 
2438  if (r_no) {
2439  float imat[4][4];
2440  invert_m4_m4(imat, obmat);
2441 
2442  copy_v3_v3(r_no, nearest.no);
2443  mul_transposed_mat3_m4_v3(imat, r_no);
2444  normalize_v3(r_no);
2445  }
2446  if (r_index) {
2447  *r_index = nearest.index;
2448  }
2449 
2450  return elem;
2451  }
2452 
2453  return 0;
2454 }
2455 
2456 static short snapEditMesh(SnapObjectContext *sctx,
2457  SnapData *snapdata,
2458  Object *ob,
2459  BMEditMesh *em,
2460  const float obmat[4][4],
2461  bool use_backface_culling,
2462  /* read/write args */
2463  float *dist_px,
2464  /* return args */
2465  float r_loc[3],
2466  float r_no[3],
2467  int *r_index)
2468 {
2470 
2471  if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_VERTEX) {
2472  if (em->bm->totvert == 0) {
2473  return 0;
2474  }
2475  }
2476  else {
2477  if (em->bm->totedge == 0) {
2478  return 0;
2479  }
2480  }
2481 
2482  float lpmat[4][4];
2483  mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
2484 
2485  float dist_px_sq = square_f(*dist_px);
2486 
2487  SnapObjectData *sod = snap_object_data_editmesh_get(sctx, ob, em);
2488 
2489  /* Test BoundBox */
2490 
2491  /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
2493  sod->min, sod->max, lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
2494  return 0;
2495  }
2496 
2497  if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
2498  BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[0]};
2499 
2500  if (treedata.tree == NULL) {
2501  BLI_bitmap *verts_mask = NULL;
2502  int verts_num_active = -1;
2503  if (sctx->callbacks.edit_mesh.test_vert_fn) {
2504  verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
2505  verts_num_active = BM_iter_mesh_bitmap_from_filter(
2507  em->bm,
2508  verts_mask,
2509  (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
2510  sctx->callbacks.edit_mesh.user_data);
2511 
2513  &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL, NULL);
2514  MEM_freeN(verts_mask);
2515  }
2516  else {
2518  em,
2519  2,
2521  &sod->mesh_runtime->bvh_cache,
2523  }
2524  sod->bvhtree[0] = treedata.tree;
2525  sod->cached[0] = treedata.cached;
2526  }
2527  }
2528 
2529  if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
2530  BVHTreeFromEditMesh treedata = {.tree = sod->bvhtree[1]};
2531 
2532  if (treedata.tree == NULL) {
2533  BLI_bitmap *edges_mask = NULL;
2534  int edges_num_active = -1;
2535  if (sctx->callbacks.edit_mesh.test_edge_fn) {
2536  edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
2537  edges_num_active = BM_iter_mesh_bitmap_from_filter(
2539  em->bm,
2540  edges_mask,
2541  (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
2542  sctx->callbacks.edit_mesh.user_data);
2543 
2545  &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL, NULL);
2546  MEM_freeN(edges_mask);
2547  }
2548  else {
2550  em,
2551  2,
2553  &sod->mesh_runtime->bvh_cache,
2554  sod->mesh_runtime->eval_mutex);
2555  }
2556  sod->bvhtree[1] = treedata.tree;
2557  sod->cached[1] = treedata.cached;
2558  }
2559  }
2560 
2561  Nearest2dUserData nearest2d = {
2562  .userdata = em,
2564  .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get,
2566  .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
2567  .use_backface_culling = use_backface_culling,
2568  };
2569 
2570  BVHTreeNearest nearest = {
2571  .index = -1,
2572  .dist_sq = dist_px_sq,
2573  };
2574  short elem = SCE_SNAP_MODE_VERTEX;
2575 
2576  float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
2577  transpose_m4_m4(tobmat, obmat);
2578 
2579  for (int i = snapdata->clip_plane_len; i--;) {
2580  mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
2581  }
2582 
2583  if (sod->bvhtree[0] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
2587  lpmat,
2588  snapdata->win_size,
2589  snapdata->mval,
2590  clip_planes_local,
2591  snapdata->clip_plane_len,
2592  &nearest,
2593  cb_snap_vert,
2594  &nearest2d);
2595  }
2596 
2597  if (sod->bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE)) {
2598  int last_index = nearest.index;
2599  nearest.index = -1;
2603  lpmat,
2604  snapdata->win_size,
2605  snapdata->mval,
2606  clip_planes_local,
2607  snapdata->clip_plane_len,
2608  &nearest,
2609  cb_snap_edge,
2610  &nearest2d);
2611 
2612  if (nearest.index != -1) {
2613  elem = SCE_SNAP_MODE_EDGE;
2614  }
2615  else {
2616  nearest.index = last_index;
2617  }
2618  }
2619 
2620  if (nearest.index != -1) {
2621  *dist_px = sqrtf(nearest.dist_sq);
2622 
2623  copy_v3_v3(r_loc, nearest.co);
2624  mul_m4_v3(obmat, r_loc);
2625  if (r_no) {
2626  float imat[4][4];
2627  invert_m4_m4(imat, obmat);
2628 
2629  copy_v3_v3(r_no, nearest.no);
2630  mul_transposed_mat3_m4_v3(imat, r_no);
2631  normalize_v3(r_no);
2632  }
2633  if (r_index) {
2634  *r_index = nearest.index;
2635  }
2636 
2637  return elem;
2638  }
2639 
2640  return 0;
2641 }
2642 
2645  /* read/write args */
2646  float *dist_px;
2647  /* return args */
2648  float *r_loc;
2649  float *r_no;
2650  int *r_index;
2653  short ret;
2654 };
2655 
2661 static void snap_obj_fn(SnapObjectContext *sctx,
2662  Object *ob,
2663  float obmat[4][4],
2664  bool use_obedit,
2665  bool use_backface_culling,
2666  bool UNUSED(is_object_active),
2667  void *data)
2668 {
2669  struct SnapObjUserData *dt = data;
2670  short retval = 0;
2671 
2672  switch (ob->type) {
2673  case OB_MESH: {
2674  Mesh *me = ob->data;
2675  if (BKE_object_is_in_editmode(ob)) {
2676  if (use_obedit || editmesh_eval_final_is_bmesh(me->edit_mesh)) {
2677  /* Operators only update the editmesh looptris of the original mesh. */
2679  retval = snapEditMesh(sctx,
2680  dt->snapdata,
2681  ob,
2682  em_orig,
2683  obmat,
2684  use_backface_culling,
2685  dt->dist_px,
2686  dt->r_loc,
2687  dt->r_no,
2688  dt->r_index);
2689  break;
2690  }
2691 
2693  if (em->mesh_eval_final) {
2694  me = em->mesh_eval_final;
2695  }
2696  }
2697  else if (ob->dt == OB_BOUNDBOX) {
2698  /* Do not snap to objects that are in bounding box display mode */
2699  return;
2700  }
2701 
2702  retval = snapMesh(sctx,
2703  dt->snapdata,
2704  ob,
2705  me,
2706  obmat,
2707  use_backface_culling,
2708  dt->dist_px,
2709  dt->r_loc,
2710  dt->r_no,
2711  dt->r_index);
2712  break;
2713  }
2714  case OB_ARMATURE:
2715  retval = snapArmature(
2716  dt->snapdata, ob, obmat, use_obedit, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
2717  break;
2718  case OB_CURVE:
2719  retval = snapCurve(
2720  dt->snapdata, ob, obmat, use_obedit, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
2721  break; /* Use ATTR_FALLTHROUGH if we want to snap to the generated mesh. */
2722  case OB_SURF:
2723  case OB_FONT: {
2724  Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
2725  if (mesh_eval) {
2726  retval |= snapMesh(sctx,
2727  dt->snapdata,
2728  ob,
2729  mesh_eval,
2730  obmat,
2731  use_backface_culling,
2732  dt->dist_px,
2733  dt->r_loc,
2734  dt->r_no,
2735  dt->r_index);
2736  }
2737  break;
2738  }
2739  case OB_EMPTY:
2740  case OB_GPENCIL:
2741  case OB_LAMP:
2742  retval = snap_object_center(
2743  dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
2744  break;
2745  case OB_CAMERA:
2746  retval = snapCamera(
2747  sctx, dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
2748  break;
2749  }
2750 
2751  if (retval) {
2752  if (dt->r_ob) {
2753  *dt->r_ob = ob;
2754  }
2755  if (dt->r_obmat) {
2756  copy_m4_m4(dt->r_obmat, obmat);
2757  }
2758  dt->ret = retval;
2759  }
2760 }
2761 
2789  SnapData *snapdata,
2790  const struct SnapObjectParams *params,
2791  /* read/write args */
2792  /* Parameters below cannot be const, because they are assigned to a
2793  * non-const variable (readability-non-const-parameter). */
2794  float *dist_px /* NOLINT */,
2795  /* return args */
2796  float r_loc[3] /* NOLINT */,
2797  float r_no[3] /* NOLINT */,
2798  int *r_index /* NOLINT */,
2799  Object **r_ob,
2800  float r_obmat[4][4])
2801 {
2802  struct SnapObjUserData data = {
2803  .snapdata = snapdata,
2804  .dist_px = dist_px,
2805  .r_loc = r_loc,
2806  .r_no = r_no,
2807  .r_ob = r_ob,
2808  .r_index = r_index,
2809  .r_obmat = r_obmat,
2810  .ret = 0,
2811  };
2812 
2814 
2815  return data.ret;
2816 }
2817 
2820 /* -------------------------------------------------------------------- */
2825 {
2826  SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
2827 
2828  sctx->flag = flag;
2829 
2830  sctx->scene = scene;
2831 
2832  sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
2833  /* Initialize as needed (edit-mode only). */
2834  sctx->cache.data_to_object_map = NULL;
2836 
2837  return sctx;
2838 }
2839 
2841  int flag,
2842  /* extra args for view3d */
2843  const ARegion *region,
2844  const View3D *v3d)
2845 {
2847 
2848  sctx->use_v3d = true;
2849  sctx->v3d_data.region = region;
2850  sctx->v3d_data.v3d = v3d;
2851 
2852  return sctx;
2853 }
2854 
2855 static void snap_object_data_free(void *sod_v)
2856 {
2857  SnapObjectData *sod = sod_v;
2859 }
2860 
2862 {
2864  if (sctx->cache.data_to_object_map != NULL) {
2866  }
2868 
2869  MEM_freeN(sctx);
2870 }
2871 
2873  SnapObjectContext *sctx,
2874  bool (*test_vert_fn)(BMVert *, void *user_data),
2875  bool (*test_edge_fn)(BMEdge *, void *user_data),
2876  bool (*test_face_fn)(BMFace *, void *user_data),
2877  void *user_data)
2878 {
2879  sctx->callbacks.edit_mesh.test_vert_fn = test_vert_fn;
2880  sctx->callbacks.edit_mesh.test_edge_fn = test_edge_fn;
2881  sctx->callbacks.edit_mesh.test_face_fn = test_face_fn;
2882 
2883  sctx->callbacks.edit_mesh.user_data = user_data;
2884 }
2885 
2888  const struct SnapObjectParams *params,
2889  const float ray_start[3],
2890  const float ray_normal[3],
2891  float *ray_depth,
2892  float r_loc[3],
2893  float r_no[3],
2894  int *r_index,
2895  Object **r_ob,
2896  float r_obmat[4][4])
2897 {
2898  return raycastObjects(sctx,
2899  depsgraph,
2900  params,
2901  ray_start,
2902  ray_normal,
2903  ray_depth,
2904  r_loc,
2905  r_no,
2906  r_index,
2907  r_ob,
2908  r_obmat,
2909  NULL);
2910 }
2911 
2921  const struct SnapObjectParams *params,
2922  const float ray_start[3],
2923  const float ray_normal[3],
2924  float ray_depth,
2925  bool sort,
2926  ListBase *r_hit_list)
2927 {
2928  if (ray_depth == -1.0f) {
2929  ray_depth = BVH_RAYCAST_DIST_MAX;
2930  }
2931 
2932 #ifdef DEBUG
2933  float ray_depth_prev = ray_depth;
2934 #endif
2935 
2936  bool retval = raycastObjects(sctx,
2937  depsgraph,
2938  params,
2939  ray_start,
2940  ray_normal,
2941  &ray_depth,
2942  NULL,
2943  NULL,
2944  NULL,
2945  NULL,
2946  NULL,
2947  r_hit_list);
2948 
2949  /* meant to be readonly for 'all' hits, ensure it is */
2950 #ifdef DEBUG
2951  BLI_assert(ray_depth_prev == ray_depth);
2952 #endif
2953 
2954  if (sort) {
2955  BLI_listbase_sort(r_hit_list, hit_depth_cmp);
2956  }
2957 
2958  return retval;
2959 }
2960 
2970  const struct SnapObjectParams *params,
2971  const float ray_start[3],
2972  const float ray_normal[3],
2973  float *ray_depth,
2974  float r_co[3],
2975  float r_no[3])
2976 {
2977  bool ret;
2978 
2979  /* try snap edge, then face if it fails */
2981  sctx, depsgraph, params, ray_start, ray_normal, ray_depth, r_co, r_no, NULL, NULL, NULL);
2982 
2983  return ret;
2984 }
2985 
2988  const struct SnapObjectParams *params,
2989  const float ray_origin[3],
2990  const float ray_direction[3],
2991  float *ray_depth,
2992  float r_co[3],
2993  float r_no[3])
2994 {
2995  float ray_depth_fallback;
2996  if (ray_depth == NULL) {
2997  ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
2998  ray_depth = &ray_depth_fallback;
2999  }
3000 
3002  sctx, depsgraph, params, ray_origin, ray_direction, ray_depth, r_co, r_no);
3003 }
3004 
3006  SnapObjectContext *sctx,
3008  const ushort snap_to_flag,
3009  const struct SnapObjectParams *params,
3010  const float mval[2],
3011  const float prev_co[3],
3012  float *dist_px,
3013  float r_loc[3],
3014  float r_no[3],
3015  int *r_index,
3016  Object **r_ob,
3017  float r_obmat[4][4])
3018 {
3021  0);
3022 
3023  short retval = 0;
3024 
3025  bool has_hit = false;
3026  Object *ob = NULL;
3027  float loc[3];
3028  /* Not all snapping callbacks set the normal,
3029  * initialize this since any hit copies both the `loc` and `no`. */
3030  float no[3] = {0.0f, 0.0f, 0.0f};
3031  float obmat[4][4];
3032  int index = -1;
3033 
3034  const ARegion *region = sctx->v3d_data.region;
3035  const RegionView3D *rv3d = region->regiondata;
3036 
3037  bool use_occlusion_test = params->use_occlusion_test && !XRAY_ENABLED(sctx->v3d_data.v3d);
3038 
3039  if (snap_to_flag & SCE_SNAP_MODE_FACE || use_occlusion_test) {
3040  float ray_start[3], ray_normal[3];
3042  sctx->v3d_data.region,
3043  sctx->v3d_data.v3d,
3044  mval,
3045  NULL,
3046  ray_normal,
3047  ray_start,
3048  true)) {
3049  return 0;
3050  }
3051 
3052  float dummy_ray_depth = BVH_RAYCAST_DIST_MAX;
3053 
3054  has_hit = raycastObjects(sctx,
3055  depsgraph,
3056  params,
3057  ray_start,
3058  ray_normal,
3059  &dummy_ray_depth,
3060  loc,
3061  no,
3062  &index,
3063  &ob,
3064  obmat,
3065  NULL);
3066 
3067  if (has_hit && (snap_to_flag & SCE_SNAP_MODE_FACE)) {
3068  retval = SCE_SNAP_MODE_FACE;
3069 
3070  copy_v3_v3(r_loc, loc);
3071  if (r_no) {
3072  copy_v3_v3(r_no, no);
3073  }
3074  if (r_ob) {
3075  *r_ob = ob;
3076  }
3077  if (r_obmat) {
3078  copy_m4_m4(r_obmat, obmat);
3079  }
3080  if (r_index) {
3081  *r_index = index;
3082  }
3083  }
3084  }
3085 
3088  short elem_test, elem = 0;
3089  float dist_px_tmp = *dist_px;
3090 
3092  copy_m4_m4(snapdata.pmat, rv3d->persmat);
3093  snapdata.win_size[0] = region->winx;
3094  snapdata.win_size[1] = region->winy;
3095  copy_v2_v2(snapdata.mval, mval);
3097 
3098  /* First snap to edge instead of middle or perpendicular. */
3102  }
3103 
3106 
3108  snapdata.has_occlusion_plane = false;
3109 
3110  /* By convention we only snap to the original elements of a curve. */
3111  if (has_hit && ob->type != OB_CURVE) {
3112  /* Compute the new clip_pane but do not add it yet. */
3113  float new_clipplane[4];
3114  plane_from_point_normal_v3(new_clipplane, loc, no);
3115  if (dot_v3v3(snapdata.clip_plane[0], new_clipplane) > 0.0f) {
3116  /* The plane is facing the wrong direction. */
3117  negate_v4(new_clipplane);
3118  }
3119 
3120  /* Small offset to simulate a kind of volume for edges and vertices. */
3121  new_clipplane[3] += 0.01f;
3122 
3123  /* Try to snap only to the polygon. */
3124  elem_test = snap_mesh_polygon(
3125  sctx, &snapdata, ob, obmat, params->use_backface_culling, &dist_px_tmp, loc, no, &index);
3126  if (elem_test) {
3127  elem = elem_test;
3128  }
3129 
3130  /* Add the new clip plane to the beginning of the list. */
3131  for (int i = snapdata.clip_plane_len; i != 0; i--) {
3133  }
3134  copy_v4_v4(snapdata.clip_plane[0], new_clipplane);
3137  }
3138 
3139  elem_test = snapObjectsRay(
3140  sctx, depsgraph, &snapdata, params, &dist_px_tmp, loc, no, &index, &ob, obmat);
3141  if (elem_test) {
3142  elem = elem_test;
3143  }
3144 
3145  if ((elem == SCE_SNAP_MODE_EDGE) &&
3148  snapdata.snap_to_flag = snap_to_flag;
3149  elem = snap_mesh_edge_verts_mixed(sctx,
3150  &snapdata,
3151  ob,
3152  obmat,
3153  *dist_px,
3154  prev_co,
3155  params->use_backface_culling,
3156  &dist_px_tmp,
3157  loc,
3158  no,
3159  &index);
3160  }
3161 
3162  if (elem & snap_to_flag) {
3163  retval = elem;
3164 
3165  copy_v3_v3(r_loc, loc);
3166  if (r_no) {
3167  copy_v3_v3(r_no, no);
3168  }
3169  if (r_ob) {
3170  *r_ob = ob;
3171  }
3172  if (r_obmat) {
3173  copy_m4_m4(r_obmat, obmat);
3174  }
3175  if (r_index) {
3176  *r_index = index;
3177  }
3178 
3179  *dist_px = dist_px_tmp;
3180  }
3181  }
3182 
3183  return retval;
3184 }
3185 
3188  const ushort snap_to,
3189  const struct SnapObjectParams *params,
3190  const float mval[2],
3191  const float prev_co[3],
3192  float *dist_px,
3193  float r_loc[3],
3194  float r_no[3],
3195  int *r_index,
3196  Object **r_ob,
3197  float r_obmat[4][4])
3198 {
3200  depsgraph,
3201  snap_to,
3202  params,
3203  mval,
3204  prev_co,
3205  dist_px,
3206  r_loc,
3207  r_no,
3208  r_index,
3209  r_ob,
3210  r_obmat);
3211 }
3212 
3228  const ushort snap_to,
3229  const struct SnapObjectParams *params,
3230  const float mval[2],
3231  const float prev_co[3],
3232  float *dist_px,
3233  float r_loc[3],
3234  float r_no[3])
3235 {
3237  depsgraph,
3238  snap_to,
3239  params,
3240  mval,
3241  prev_co,
3242  dist_px,
3243  r_loc,
3244  r_no,
3245  NULL,
3246  NULL,
3247  NULL) != 0;
3248 }
3249 
3255  const struct SnapObjectParams *params,
3256  const float mval[2],
3257  float ray_depth,
3258  bool sort,
3259  ListBase *r_hit_list)
3260 {
3261  float ray_start[3], ray_normal[3];
3262 
3264  sctx->v3d_data.region,
3265  sctx->v3d_data.v3d,
3266  mval,
3267  NULL,
3268  ray_normal,
3269  ray_start,
3270  true)) {
3271  return false;
3272  }
3273 
3275  sctx, depsgraph, params, ray_start, ray_normal, ray_depth, sort, r_hit_list);
3276 }
3277 
typedef float(TangentPoint)[2]
struct BoundBox * BKE_armature_boundbox_get(struct Object *ob)
Definition: armature.c:2858
BVHTree * BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, struct Mesh *mesh, const BVHCacheType bvh_cache_type, const int tree_type)
Definition: bvhutils.c:1413
float bvhtree_ray_tri_intersection(const BVHTreeRay *ray, const float m_dist, const float v0[3], const float v1[3], const float v2[3])
BVHTree * BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, struct BMEditMesh *em, const int tree_type, const BVHCacheType bvh_cache_type, struct BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex)
Definition: bvhutils.c:1599
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, const BVHCacheType bvh_cache_type, struct BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex)
Definition: bvhutils.c:631
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, const BVHCacheType bvh_cache_type, struct BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex)
Definition: bvhutils.c:1212
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
Definition: bvhutils.c:1701
@ BVHTREE_FROM_EM_EDGES
Definition: BKE_bvhutils.h:100
@ BVHTREE_FROM_LOOPTRI
Definition: BKE_bvhutils.h:93
@ BVHTREE_FROM_LOOSEEDGES
Definition: BKE_bvhutils.h:97
@ BVHTREE_FROM_EM_VERTS
Definition: BKE_bvhutils.h:99
@ BVHTREE_FROM_LOOSEVERTS
Definition: BKE_bvhutils.h:96
@ BVHTREE_FROM_EM_LOOPTRI
Definition: BKE_bvhutils.h:101
@ BVHTREE_FROM_LOOPTRI_NO_HIDDEN
Definition: BKE_bvhutils.h:94
bool bvhcache_has_tree(const struct BVHCache *bvh_cache, const BVHTree *tree)
void free_bvhtree_from_editmesh(struct BVHTreeFromEditMesh *data)
Definition: bvhutils.c:1690
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, const BVHCacheType bvh_cache_type, struct BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex)
Definition: bvhutils.c:843
struct BoundBox * BKE_curve_boundbox_get(struct Object *ob)
Definition: curve.c:496
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:85
bool BKE_geometry_set_has_instances(const struct GeometrySet *geometry_set)
struct BoundBox * BKE_mesh_boundbox_get(struct Object *ob)
Definition: mesh.c:1055
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(struct Mesh *mesh)
Definition: mesh_runtime.c:155
General operations, lookup, etc. for blender objects.
struct MovieClip * BKE_object_movieclip_get(struct Scene *scene, struct Object *ob, bool use_default)
Definition: object.c:5079
struct Mesh * BKE_object_get_evaluated_mesh(struct Object *object)
Definition: object.c:4459
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:399
void BKE_tracking_camera_get_reconstructed_interpolate(struct MovieTracking *tracking, struct MovieTrackingObject *object, float framenr, float mat[4][4])
Definition: tracking.c:2374
struct ListBase * BKE_tracking_object_get_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object)
Definition: tracking.c:2218
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_BITMAP_NEW(_tot, _alloc_string)
Definition: BLI_bitmap.h:50
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:851
void * BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:803
#define BVH_RAYCAST_DIST_MAX
Definition: BLI_kdopbvh.h:105
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:2284
void BLI_bvhtree_free(BVHTree *tree)
Definition: BLI_kdopbvh.c:945
void(* BVHTree_RayCastCallback)(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition: BLI_kdopbvh.h:114
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:2066
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:1984
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
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:110
MINLINE float square_f(float a)
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition: math_geom.c:243
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:875
MINLINE int poly_to_tri_count(const int poly_count, const int corner_count)
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:2123
void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:36
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:3308
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:823
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3449
void planes_from_projmat(const float mat[4][4], float left[4], float right[4], float top[4], float bottom[4], float near[4], float far[4])
Definition: math_geom.c:4911
bool isect_point_planes_v3_negated(const float(*planes)[4], const int totplane, const float p[3])
Definition: math_geom.c:2169
void mul_v4_m4v4(float r[4], const float M[4][4], const float v[4])
Definition: math_matrix.c:854
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:930
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:262
void transpose_m4_m4(float R[4][4], const float M[4][4])
Definition: math_matrix.c:1384
void mul_mat3_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:794
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
void transpose_m3_m4(float R[3][3], const float M[4][4])
Definition: math_matrix.c:1343
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
void mul_transposed_mat3_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:950
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
MINLINE void copy_v4_v4(float r[4], const float a[4])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], const float t)
Definition: math_vector.c:49
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:1020
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 normal_short_to_float_v3(float r[3], const short n[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 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
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:270
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 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])
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:109
#define BLI_MEMARENA_STD_BUFSIZE
Definition: BLI_memarena.h:36
struct MemArena * BLI_memarena_new(const size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:79
void * BLI_memarena_calloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:168
unsigned int uint
Definition: BLI_sys_types.h:83
unsigned short ushort
Definition: BLI_sys_types.h:84
pthread_mutex_t ThreadMutex
Definition: BLI_threads.h:83
#define INIT_MINMAX(min, max)
#define ARRAY_SIZE(arr)
#define IN_RANGE(a, b, c)
#define UNUSED(x)
#define UNPACK3(a)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
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_HIDDEN_A
@ BONE_HIDDEN_P
@ BONE_TIPSEL
@ BONE_HIDDEN_PG
@ HD_ALIGN
@ BASE_SELECTED
@ ME_WRAPPER_TYPE_BMESH
@ OB_WIRE
@ OB_BOUNDBOX
Object is a sort of wrapper for general info.
@ OB_DUPLI
#define BA_TRANSFORM_LOCKED_IN_PLACE
@ OB_EMPTY
@ OB_SURF
@ OB_CAMERA
@ OB_FONT
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ OB_CURVE
@ OB_GPENCIL
@ BA_WAS_SEL
@ BA_SNAP_FIX_DEPS_FIASCO
#define CFRA
#define SCE_SNAP_MODE_FACE
#define SCE_SNAP_MODE_EDGE_PERPENDICULAR
#define SCE_SNAP_MODE_EDGE_MIDPOINT
#define SCE_SNAP_MODE_VERTEX
#define SCE_SNAP_MODE_EDGE
#define BASE_VISIBLE(v3d, base)
@ TRACK_HAS_BUNDLE
@ TRACKING_OBJECT_CAMERA
#define XRAY_ENABLED(v3d)
Definition: ED_view3d.h:710
#define XRAY_FLAG_ENABLED(v3d)
Definition: ED_view3d.h:709
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)
_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 type
_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
Read Guarded memory(de)allocation.
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:553
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
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.c:2276
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2152
BLI_INLINE BMFace * BM_face_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:110
BLI_INLINE BMEdge * BM_edge_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:104
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:98
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
#define SELECT
Scene scene
const Depsgraph * depsgraph
void * user_data
IconTextureDrawCall normal
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define sqrtf(x)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static void clear(Message *msg)
Definition: msgfmt.c:294
return ret
#define min(a, b)
Definition: sort.c:51
void * regiondata
BMVert * v1
Definition: bmesh_class.h:134
BMVert * v2
Definition: bmesh_class.h:134
struct Mesh * mesh_eval_final
Definition: BKE_editmesh.h:63
struct Mesh * mesh_eval_cage
Definition: BKE_editmesh.h:63
struct BMLoop *(* looptris)[3]
Definition: BKE_editmesh.h:60
struct BMesh * bm
Definition: BKE_editmesh.h:52
struct BMVert * v
Definition: bmesh_class.h:165
struct BMEdge * e
Definition: bmesh_class.h:176
struct BMFace * f
Definition: bmesh_class.h:183
struct BMLoop * next
Definition: bmesh_class.h:245
float co[3]
Definition: bmesh_class.h:99
float no[3]
Definition: bmesh_class.h:100
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:49
struct BMEditMesh * em
Definition: BKE_bvhutils.h:55
BVHTree_RayCastCallback raycast_callback
Definition: BKE_bvhutils.h:53
BVHTree_RayCastCallback raycast_callback
Definition: BKE_bvhutils.h:70
const struct MEdge * edge
Definition: BKE_bvhutils.h:74
bool looptri_allocated
Definition: BKE_bvhutils.h:82
const struct MLoop * loop
Definition: BKE_bvhutils.h:76
struct BVHTree * tree
Definition: BKE_bvhutils.h:66
const struct MVert * vert
Definition: BKE_bvhutils.h:73
const struct MLoopTri * looptri
Definition: BKE_bvhutils.h:77
float co[3]
Definition: BLI_kdopbvh.h:59
float no[3]
Definition: BLI_kdopbvh.h:62
float co[3]
Definition: BLI_kdopbvh.h:84
float no[3]
Definition: BLI_kdopbvh.h:86
float origin[3]
Definition: BLI_kdopbvh.h:70
float direction[3]
Definition: BLI_kdopbvh.h:72
float vec[8][3]
EditNurb * editnurb
ListBase nurb
ListBase nurbs
void * first
Definition: DNA_listBase.h:47
unsigned int v1
unsigned int v2
unsigned int poly
unsigned int tri[3]
unsigned int e
unsigned int v
float co[3]
short no[3]
struct BVHCache * bvh_cache
void * eval_mutex
struct MEdge * medge
struct BMEditMesh * edit_mesh
struct MVert * mvert
int totedge
int totvert
struct MLoop * mloop
Mesh_Runtime runtime
int totpoly
struct MPoly * mpoly
struct MovieTracking tracking
struct MovieTrackingObject * next
struct MovieTrackingTrack * next
Nearest2DCopyVertNoCallback copy_vert_no
Nearest2DGetTriVertsCallback get_tri_verts_index
Nearest2DGetTriEdgesCallback get_tri_edges_index
Nearest2DGetEdgeVertsCallback get_edge_verts_index
Nearest2DGetVertCoCallback get_vert_co
struct Nurb * next
struct GeometrySet * geometry_set_eval
short transflag
struct bPose * pose
Object_Runtime runtime
float obmat[4][4]
void * data
const float(* timat)[3]
const float(* obmat)[4]
BVHTree_RayCastCallback raycast_callback
float persmat[4][4]
float pmat[4][4]
float clip_plane[MAX_CLIPPLANE_LEN][4]
enum eViewProj view_proj
const struct ARegion * region
struct SnapObjectContext::@599::@600 edit_mesh
struct SnapObjectContext::@598 cache
struct SnapObjectContext::@597 v3d_data
bool(* test_face_fn)(BMFace *, void *user_data)
bool(* test_edge_fn)(BMEdge *, void *user_data)
bool(* test_vert_fn)(BMVert *, void *user_data)
const struct View3D * v3d
struct SnapObjectContext::@599 callbacks
const struct MPoly * poly
BVHTreeFromEditMesh treedata_editmesh
BVHTreeFromMesh treedata_mesh
struct Mesh_Runtime * mesh_runtime
enum SnapObjectData::@590 type
struct Base * basact
ListBase object_bases
unsigned int layer
ListBase * edbo
ListBase chanbase
float max
static bool raycastEditMesh(SnapObjectContext *sctx, const float ray_start[3], const float ray_dir[3], Object *ob, BMEditMesh *em, const float obmat[4][4], const uint ob_index, bool use_backface_culling, float *ray_depth, float r_loc[3], float r_no[3], int *r_index, ListBase *r_hit_list)
static short snapMesh(SnapObjectContext *sctx, SnapData *snapdata, Object *ob, Mesh *me, const float obmat[4][4], bool use_backface_culling, float *dist_px, float r_loc[3], float r_no[3], int *r_index)
static short snap_object_center(SnapData *snapdata, Object *ob, const float obmat[4][4], float *dist_px, float r_loc[3], float *UNUSED(r_no), int *r_index)
@ VIEW_PROJ_PERSP
@ VIEW_PROJ_NONE
@ VIEW_PROJ_ORTHO
static bool test_projected_edge_dist(const struct 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])
static void cb_bvert_no_copy(const int index, float r_no[3], const BMEditMesh *data)
static short snapCamera(const SnapObjectContext *sctx, SnapData *snapdata, Object *object, float obmat[4][4], float *dist_px, float r_loc[3], float *r_no, int *r_index)
void(* Nearest2DGetTriVertsCallback)(const int index, const int v_index[3], void *data)
static short snap_mesh_polygon(SnapObjectContext *sctx, SnapData *snapdata, Object *ob, const float obmat[4][4], bool use_backface_culling, float *dist_px, float r_loc[3], float r_no[3], int *r_index)
static void bm_mesh_minmax(BMesh *bm, float r_min[3], float r_max[3])
static bool editmesh_eval_final_is_bmesh(const BMEditMesh *em)
static bool transform_snap_context_project_ray_impl(SnapObjectContext *sctx, Depsgraph *depsgraph, const struct 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 cb_mlooptri_verts_get(const int index, int v_index[3], const BVHTreeFromMesh *data)
bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx, Depsgraph *depsgraph, const struct SnapObjectParams *params, const float ray_start[3], const float ray_normal[3], float ray_depth, bool sort, ListBase *r_hit_list)
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)
static void snap_object_data_free(void *sod_v)
static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
static short transform_snap_context_project_view3d_mixed_impl(SnapObjectContext *sctx, Depsgraph *depsgraph, const ushort snap_to_flag, const struct SnapObjectParams *params, 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])
static bool raycastMesh(SnapObjectContext *sctx, const float ray_start[3], const float ray_dir[3], Object *ob, Mesh *me, const float obmat[4][4], const uint ob_index, bool use_hide, bool use_backface_culling, float *ray_depth, float r_loc[3], float r_no[3], int *r_index, ListBase *r_hit_list)
static void snap_object_data_clear(SnapObjectData *sod)
static void cb_bvert_co_get(const int index, const float **co, const BMEditMesh *data)
void(* Nearest2DGetTriEdgesCallback)(const int index, const int e_index[3], void *data)
static void cb_snap_tri_verts(void *userdata, int index, const struct DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], const int clip_plane_len, BVHTreeNearest *nearest)
short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx, Depsgraph *depsgraph, const ushort snap_to, const struct SnapObjectParams *params, 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])
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 raycast_obj_fn(SnapObjectContext *sctx, Object *ob, float obmat[4][4], bool use_obedit, bool use_backface_culling, bool is_object_active, void *data)
static short snapCurve(SnapData *snapdata, Object *ob, const float obmat[4][4], bool use_obedit, float *dist_px, float r_loc[3], float *UNUSED(r_no), int *r_index)
#define MAX_CLIPPLANE_LEN
bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx, Depsgraph *depsgraph, const struct SnapObjectParams *params, const float ray_origin[3], const float ray_direction[3], float *ray_depth, float r_co[3], float r_no[3])
static SnapObjectData * snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob)
SnapObjectContext * ED_transform_snap_object_context_create(Scene *scene, int flag)
static struct SnapObjectHitDepth * hit_depth_create(const float depth, const float co[3], const float no[3], int index, Object *ob, const float obmat[4][4], uint ob_uuid)
void(* Nearest2DGetVertCoCallback)(const int index, const float **co, void *data)
void(* IterSnapObjsCallback)(SnapObjectContext *sctx, Object *ob, float obmat[4][4], bool use_obedit, bool use_backface_culling, bool is_object_active, void *data)
static short snapArmature(SnapData *snapdata, Object *ob, const float obmat[4][4], bool use_obedit, float *dist_px, float r_loc[3], float *UNUSED(r_no), int *r_index)
struct Nearest2dUserData Nearest2dUserData
static void cb_medge_verts_get(const int index, int v_index[2], const BVHTreeFromMesh *data)
struct SnapData SnapData
static void editmesh_looptri_raycast_backface_culling_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
static void snap_obj_fn(SnapObjectContext *sctx, Object *ob, float obmat[4][4], bool use_obedit, bool use_backface_culling, bool UNUSED(is_object_active), void *data)
static void snap_object_data_mesh_clear(SnapObjectData *sod)
static void cb_bedge_verts_get(const int index, int v_index[2], const BMEditMesh *data)
static void cb_mlooptri_edges_get(const int index, int v_index[3], const BVHTreeFromMesh *data)
static void snap_object_data_editmesh_clear(SnapObjectData *sod)
static void cb_snap_edge_verts(void *userdata, int index, const struct DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], const int clip_plane_len, BVHTreeNearest *nearest)
static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx, SnapData *snapdata, Object *ob, const float obmat[4][4], float original_dist_px, const float prev_co[3], bool use_backface_culling, float *dist_px, float r_loc[3], float r_no[3], int *r_index)
static short snapObjectsRay(SnapObjectContext *sctx, Depsgraph *depsgraph, SnapData *snapdata, const struct 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 SnapObjectData * snap_object_data_lookup(SnapObjectContext *sctx, Object *ob)
static void cb_mvert_no_copy(const int index, float r_no[3], const BVHTreeFromMesh *data)
bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx, Depsgraph *depsgraph, const struct SnapObjectParams *params, const float mval[2], float ray_depth, bool sort, ListBase *r_hit_list)
struct SnapObjectData SnapObjectData
bool ED_transform_snap_object_project_view3d(SnapObjectContext *sctx, Depsgraph *depsgraph, const ushort snap_to, const struct SnapObjectParams *params, const float mval[2], const float prev_co[3], float *dist_px, float r_loc[3], float r_no[3])
static void cb_snap_tri_edges(void *userdata, int index, const struct DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], const int clip_plane_len, BVHTreeNearest *nearest)
static SnapObjectData * snap_object_data_editmesh_get(SnapObjectContext *sctx, Object *ob, BMEditMesh *em)
static short snapEditMesh(SnapObjectContext *sctx, SnapData *snapdata, Object *ob, BMEditMesh *em, const float obmat[4][4], bool use_backface_culling, float *dist_px, float r_loc[3], float r_no[3], int *r_index)
static bool raycastObjects(SnapObjectContext *sctx, Depsgraph *depsgraph, const struct 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 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)
static struct Mesh_Runtime * snap_object_data_editmesh_runtime_get(Object *ob)
static void cb_snap_vert(void *userdata, int index, const struct DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], const int clip_plane_len, BVHTreeNearest *nearest)
bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx, Depsgraph *depsgraph, const struct 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 void mesh_looptri_raycast_backface_culling_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
static void iter_snap_objects(SnapObjectContext *sctx, Depsgraph *depsgraph, const struct SnapObjectParams *params, IterSnapObjsCallback sob_callback, void *data)
static void cb_snap_edge(void *userdata, int index, const struct DistProjectedAABBPrecalc *precalc, const float(*clip_plane)[4], const int clip_plane_len, BVHTreeNearest *nearest)
void(* Nearest2DCopyVertNoCallback)(const int index, const float r_no[3], void *data)
void(* Nearest2DGetEdgeVertsCallback)(const int index, const int v_index[2], void *data)
static int hit_depth_cmp(const void *arg1, const void *arg2)
SnapObjectContext * ED_transform_snap_object_context_create_view3d(Scene *scene, int flag, const ARegion *region, const View3D *v3d)
static void cb_mvert_co_get(const int index, const float **co, const BVHTreeFromMesh *data)
static bool test_projected_vert_dist(const struct 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])