Blender  V2.93
bvhutils.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  * The Original Code is Copyright (C) Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <math.h>
25 #include <stdio.h>
26 #include <string.h>
27 
28 #include "DNA_mesh_types.h"
29 #include "DNA_meshdata_types.h"
30 #include "DNA_pointcloud_types.h"
31 
32 #include "BLI_linklist.h"
33 #include "BLI_math.h"
34 #include "BLI_threads.h"
35 #include "BLI_utildefines.h"
36 
37 #include "BKE_bvhutils.h"
38 #include "BKE_editmesh.h"
39 #include "BKE_mesh.h"
40 #include "BKE_mesh_runtime.h"
41 
42 #include "MEM_guardedalloc.h"
43 
44 /* -------------------------------------------------------------------- */
48 typedef struct BVHCacheItem {
49  bool is_filled;
52 
53 typedef struct BVHCache {
57 
66 static bool bvhcache_find(BVHCache **bvh_cache_p,
68  BVHTree **r_tree,
69  bool *r_locked,
70  ThreadMutex *mesh_eval_mutex)
71 {
72  bool do_lock = r_locked;
73  if (r_locked) {
74  *r_locked = false;
75  }
76  if (*bvh_cache_p == NULL) {
77  if (!do_lock) {
78  /* Cache does not exist and no lock is requested. */
79  return false;
80  }
81  /* Lazy initialization of the bvh_cache using the `mesh_eval_mutex`. */
82  BLI_mutex_lock(mesh_eval_mutex);
83  if (*bvh_cache_p == NULL) {
84  *bvh_cache_p = bvhcache_init();
85  }
86  BLI_mutex_unlock(mesh_eval_mutex);
87  }
88  BVHCache *bvh_cache = *bvh_cache_p;
89 
90  if (bvh_cache->items[type].is_filled) {
91  *r_tree = bvh_cache->items[type].tree;
92  return true;
93  }
94  if (do_lock) {
95  BLI_mutex_lock(&bvh_cache->mutex);
96  bool in_cache = bvhcache_find(bvh_cache_p, type, r_tree, NULL, NULL);
97  if (in_cache) {
98  BLI_mutex_unlock(&bvh_cache->mutex);
99  return in_cache;
100  }
101  *r_locked = true;
102  }
103  return false;
104 }
105 
106 static void bvhcache_unlock(BVHCache *bvh_cache, bool lock_started)
107 {
108  if (lock_started) {
109  BLI_mutex_unlock(&bvh_cache->mutex);
110  }
111 }
112 
113 bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree)
114 {
115  if (bvh_cache == NULL) {
116  return false;
117  }
118 
119  for (BVHCacheType i = 0; i < BVHTREE_MAX_ITEM; i++) {
120  if (bvh_cache->items[i].tree == tree) {
121  return true;
122  }
123  }
124  return false;
125 }
126 
128 {
129  BVHCache *cache = MEM_callocN(sizeof(BVHCache), __func__);
130  BLI_mutex_init(&cache->mutex);
131  return cache;
132 }
142 {
143  BVHCacheItem *item = &bvh_cache->items[type];
144  BLI_assert(!item->is_filled);
145  item->tree = tree;
146  item->is_filled = true;
147 }
148 
152 void bvhcache_free(BVHCache *bvh_cache)
153 {
154  for (BVHCacheType index = 0; index < BVHTREE_MAX_ITEM; index++) {
155  BVHCacheItem *item = &bvh_cache->items[index];
156  BLI_bvhtree_free(item->tree);
157  item->tree = NULL;
158  }
159  BLI_mutex_end(&bvh_cache->mutex);
160  MEM_freeN(bvh_cache);
161 }
162 
164 /* -------------------------------------------------------------------- */
168 /* Math stuff for ray casting on mesh faces and for nearest surface */
169 
171  const float UNUSED(m_dist),
172  const float v0[3],
173  const float v1[3],
174  const float v2[3])
175 {
176  float dist;
177 
178 #ifdef USE_KDOPBVH_WATERTIGHT
179  if (isect_ray_tri_watertight_v3(ray->origin, ray->isect_precalc, v0, v1, v2, &dist, NULL))
180 #else
181  if (isect_ray_tri_epsilon_v3(ray->origin, ray->direction, v0, v1, v2, &dist, NULL, FLT_EPSILON))
182 #endif
183  {
184  return dist;
185  }
186 
187  return FLT_MAX;
188 }
189 
191  float radius,
192  const float m_dist,
193  const float v0[3],
194  const float v1[3],
195  const float v2[3])
196 {
197 
198  float idist;
199  float p1[3];
200  float hit_point[3];
201 
202  madd_v3_v3v3fl(p1, ray->origin, ray->direction, m_dist);
203  if (isect_sweeping_sphere_tri_v3(ray->origin, p1, radius, v0, v1, v2, &idist, hit_point)) {
204  return idist * m_dist;
205  }
206 
207  return FLT_MAX;
208 }
209 
210 /*
211  * BVH from meshes callbacks
212  */
213 
214 /* Callback to bvh tree nearest point. The tree must have been built using bvhtree_from_mesh_faces.
215  * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
216 static void mesh_faces_nearest_point(void *userdata,
217  int index,
218  const float co[3],
219  BVHTreeNearest *nearest)
220 {
221  const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
222  const MVert *vert = data->vert;
223  const MFace *face = data->face + index;
224 
225  const float *t0, *t1, *t2, *t3;
226  t0 = vert[face->v1].co;
227  t1 = vert[face->v2].co;
228  t2 = vert[face->v3].co;
229  t3 = face->v4 ? vert[face->v4].co : NULL;
230 
231  do {
232  float nearest_tmp[3], dist_sq;
233 
234  closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
235  dist_sq = len_squared_v3v3(co, nearest_tmp);
236 
237  if (dist_sq < nearest->dist_sq) {
238  nearest->index = index;
239  nearest->dist_sq = dist_sq;
240  copy_v3_v3(nearest->co, nearest_tmp);
241  normal_tri_v3(nearest->no, t0, t1, t2);
242  }
243 
244  t1 = t2;
245  t2 = t3;
246  t3 = NULL;
247 
248  } while (t2);
249 }
250 /* copy of function above */
251 static void mesh_looptri_nearest_point(void *userdata,
252  int index,
253  const float co[3],
254  BVHTreeNearest *nearest)
255 {
256  const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
257  const MVert *vert = data->vert;
258  const MLoopTri *lt = &data->looptri[index];
259  const float *vtri_co[3] = {
260  vert[data->loop[lt->tri[0]].v].co,
261  vert[data->loop[lt->tri[1]].v].co,
262  vert[data->loop[lt->tri[2]].v].co,
263  };
264  float nearest_tmp[3], dist_sq;
265 
266  closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(vtri_co));
267  dist_sq = len_squared_v3v3(co, nearest_tmp);
268 
269  if (dist_sq < nearest->dist_sq) {
270  nearest->index = index;
271  nearest->dist_sq = dist_sq;
272  copy_v3_v3(nearest->co, nearest_tmp);
273  normal_tri_v3(nearest->no, UNPACK3(vtri_co));
274  }
275 }
276 /* copy of function above (warning, should de-duplicate with editmesh_bvh.c) */
277 static void editmesh_looptri_nearest_point(void *userdata,
278  int index,
279  const float co[3],
280  BVHTreeNearest *nearest)
281 {
282  const BVHTreeFromEditMesh *data = userdata;
283  BMEditMesh *em = data->em;
284  const BMLoop **ltri = (const BMLoop **)em->looptris[index];
285 
286  const float *t0, *t1, *t2;
287  t0 = ltri[0]->v->co;
288  t1 = ltri[1]->v->co;
289  t2 = ltri[2]->v->co;
290 
291  {
292  float nearest_tmp[3], dist_sq;
293 
294  closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
295  dist_sq = len_squared_v3v3(co, nearest_tmp);
296 
297  if (dist_sq < nearest->dist_sq) {
298  nearest->index = index;
299  nearest->dist_sq = dist_sq;
300  copy_v3_v3(nearest->co, nearest_tmp);
301  normal_tri_v3(nearest->no, t0, t1, t2);
302  }
303  }
304 }
305 
306 /* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_faces.
307  * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
308 static void mesh_faces_spherecast(void *userdata,
309  int index,
310  const BVHTreeRay *ray,
311  BVHTreeRayHit *hit)
312 {
313  const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
314  const MVert *vert = data->vert;
315  const MFace *face = &data->face[index];
316 
317  const float *t0, *t1, *t2, *t3;
318  t0 = vert[face->v1].co;
319  t1 = vert[face->v2].co;
320  t2 = vert[face->v3].co;
321  t3 = face->v4 ? vert[face->v4].co : NULL;
322 
323  do {
324  float dist;
325  if (ray->radius == 0.0f) {
326  dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
327  }
328  else {
329  dist = bvhtree_sphereray_tri_intersection(ray, ray->radius, hit->dist, t0, t1, t2);
330  }
331 
332  if (dist >= 0 && dist < hit->dist) {
333  hit->index = index;
334  hit->dist = dist;
335  madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
336 
337  normal_tri_v3(hit->no, t0, t1, t2);
338  }
339 
340  t1 = t2;
341  t2 = t3;
342  t3 = NULL;
343 
344  } while (t2);
345 }
346 /* copy of function above */
347 static void mesh_looptri_spherecast(void *userdata,
348  int index,
349  const BVHTreeRay *ray,
350  BVHTreeRayHit *hit)
351 {
352  const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
353  const MVert *vert = data->vert;
354  const MLoopTri *lt = &data->looptri[index];
355  const float *vtri_co[3] = {
356  vert[data->loop[lt->tri[0]].v].co,
357  vert[data->loop[lt->tri[1]].v].co,
358  vert[data->loop[lt->tri[2]].v].co,
359  };
360  float dist;
361 
362  if (ray->radius == 0.0f) {
363  dist = bvhtree_ray_tri_intersection(ray, hit->dist, UNPACK3(vtri_co));
364  }
365  else {
366  dist = bvhtree_sphereray_tri_intersection(ray, ray->radius, hit->dist, UNPACK3(vtri_co));
367  }
368 
369  if (dist >= 0 && dist < hit->dist) {
370  hit->index = index;
371  hit->dist = dist;
372  madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
373 
374  normal_tri_v3(hit->no, UNPACK3(vtri_co));
375  }
376 }
377 /* copy of function above (warning, should de-duplicate with editmesh_bvh.c) */
378 static void editmesh_looptri_spherecast(void *userdata,
379  int index,
380  const BVHTreeRay *ray,
381  BVHTreeRayHit *hit)
382 {
383  const BVHTreeFromEditMesh *data = (BVHTreeFromEditMesh *)userdata;
384  BMEditMesh *em = data->em;
385  const BMLoop **ltri = (const BMLoop **)em->looptris[index];
386 
387  const float *t0, *t1, *t2;
388  t0 = ltri[0]->v->co;
389  t1 = ltri[1]->v->co;
390  t2 = ltri[2]->v->co;
391 
392  {
393  float dist;
394  if (ray->radius == 0.0f) {
395  dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
396  }
397  else {
398  dist = bvhtree_sphereray_tri_intersection(ray, ray->radius, hit->dist, t0, t1, t2);
399  }
400 
401  if (dist >= 0 && dist < hit->dist) {
402  hit->index = index;
403  hit->dist = dist;
404  madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
405 
406  normal_tri_v3(hit->no, t0, t1, t2);
407  }
408  }
409 }
410 
411 /* Callback to bvh tree nearest point. The tree must have been built using bvhtree_from_mesh_edges.
412  * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
413 static void mesh_edges_nearest_point(void *userdata,
414  int index,
415  const float co[3],
416  BVHTreeNearest *nearest)
417 {
418  const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
419  const MVert *vert = data->vert;
420  const MEdge *edge = data->edge + index;
421  float nearest_tmp[3], dist_sq;
422 
423  const float *t0, *t1;
424  t0 = vert[edge->v1].co;
425  t1 = vert[edge->v2].co;
426 
427  closest_to_line_segment_v3(nearest_tmp, co, t0, t1);
428  dist_sq = len_squared_v3v3(nearest_tmp, co);
429 
430  if (dist_sq < nearest->dist_sq) {
431  nearest->index = index;
432  nearest->dist_sq = dist_sq;
433  copy_v3_v3(nearest->co, nearest_tmp);
434  sub_v3_v3v3(nearest->no, t0, t1);
435  normalize_v3(nearest->no);
436  }
437 }
438 
439 /* Helper, does all the point-spherecast work actually. */
440 static void mesh_verts_spherecast_do(int index,
441  const float v[3],
442  const BVHTreeRay *ray,
443  BVHTreeRayHit *hit)
444 {
445  float dist;
446  const float *r1;
447  float r2[3], i1[3];
448  r1 = ray->origin;
449  add_v3_v3v3(r2, r1, ray->direction);
450 
451  closest_to_line_segment_v3(i1, v, r1, r2);
452 
453  /* No hit if closest point is 'behind' the origin of the ray, or too far away from it. */
454  if ((dot_v3v3v3(r1, i1, r2) >= 0.0f) && ((dist = len_v3v3(r1, i1)) < hit->dist)) {
455  hit->index = index;
456  hit->dist = dist;
457  copy_v3_v3(hit->co, i1);
458  }
459 }
460 
461 static void editmesh_verts_spherecast(void *userdata,
462  int index,
463  const BVHTreeRay *ray,
464  BVHTreeRayHit *hit)
465 {
466  const BVHTreeFromEditMesh *data = userdata;
467  BMVert *eve = BM_vert_at_index(data->em->bm, index);
468 
469  mesh_verts_spherecast_do(index, eve->co, ray, hit);
470 }
471 
472 /* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_verts.
473  * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
474 static void mesh_verts_spherecast(void *userdata,
475  int index,
476  const BVHTreeRay *ray,
477  BVHTreeRayHit *hit)
478 {
479  const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
480  const float *v = data->vert[index].co;
481 
482  mesh_verts_spherecast_do(index, v, ray, hit);
483 }
484 
485 /* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_edges.
486  * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
487 static void mesh_edges_spherecast(void *userdata,
488  int index,
489  const BVHTreeRay *ray,
490  BVHTreeRayHit *hit)
491 {
492  const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
493  const MVert *vert = data->vert;
494  const MEdge *edge = &data->edge[index];
495 
496  const float radius_sq = square_f(ray->radius);
497  float dist;
498  const float *v1, *v2, *r1;
499  float r2[3], i1[3], i2[3];
500  v1 = vert[edge->v1].co;
501  v2 = vert[edge->v2].co;
502 
503  /* In case we get a zero-length edge, handle it as a point! */
504  if (equals_v3v3(v1, v2)) {
505  mesh_verts_spherecast_do(index, v1, ray, hit);
506  return;
507  }
508 
509  r1 = ray->origin;
510  add_v3_v3v3(r2, r1, ray->direction);
511 
512  if (isect_line_line_v3(v1, v2, r1, r2, i1, i2)) {
513  /* No hit if intersection point is 'behind' the origin of the ray, or too far away from it. */
514  if ((dot_v3v3v3(r1, i2, r2) >= 0.0f) && ((dist = len_v3v3(r1, i2)) < hit->dist)) {
515  const float e_fac = line_point_factor_v3(i1, v1, v2);
516  if (e_fac < 0.0f) {
517  copy_v3_v3(i1, v1);
518  }
519  else if (e_fac > 1.0f) {
520  copy_v3_v3(i1, v2);
521  }
522  /* Ensure ray is really close enough from edge! */
523  if (len_squared_v3v3(i1, i2) <= radius_sq) {
524  hit->index = index;
525  hit->dist = dist;
526  copy_v3_v3(hit->co, i2);
527  }
528  }
529  }
530 }
531 
534 /*
535  * BVH builders
536  */
537 
538 /* -------------------------------------------------------------------- */
543  int tree_type,
544  int axis,
545  BMEditMesh *em,
546  const BLI_bitmap *verts_mask,
547  int verts_num_active)
548 {
550  const int verts_num = em->bm->totvert;
551  if (verts_mask) {
552  BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num));
553  }
554  else {
555  verts_num_active = verts_num;
556  }
557 
558  BVHTree *tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis);
559 
560  if (tree) {
561  for (int i = 0; i < verts_num; i++) {
562  if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) {
563  continue;
564  }
565  BMVert *eve = BM_vert_at_index(em->bm, i);
566  BLI_bvhtree_insert(tree, i, eve->co, 1);
567  }
568  BLI_assert(BLI_bvhtree_get_len(tree) == verts_num_active);
570  }
571 
572  return tree;
573 }
574 
576  int tree_type,
577  int axis,
578  const MVert *vert,
579  const int verts_num,
580  const BLI_bitmap *verts_mask,
581  int verts_num_active)
582 {
583  BVHTree *tree = NULL;
584 
585  if (verts_mask) {
586  BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num));
587  }
588  else {
589  verts_num_active = verts_num;
590  }
591 
592  if (verts_num_active) {
593  tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis);
594 
595  if (tree) {
596  for (int i = 0; i < verts_num; i++) {
597  if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) {
598  continue;
599  }
600  BLI_bvhtree_insert(tree, i, vert[i].co, 1);
601  }
602  BLI_assert(BLI_bvhtree_get_len(tree) == verts_num_active);
604  }
605  }
606 
607  return tree;
608 }
609 
611  BVHTree *tree,
612  const bool is_cached,
613  const MVert *vert,
614  const bool vert_allocated)
615 {
616  memset(data, 0, sizeof(*data));
617 
618  data->tree = tree;
619  data->cached = is_cached;
620 
621  /* a NULL nearest callback works fine
622  * remember the min distance to point is the same as the min distance to BV of point */
623  data->nearest_callback = NULL;
624  data->raycast_callback = mesh_verts_spherecast;
625 
626  data->vert = vert;
627  data->vert_allocated = vert_allocated;
628 }
629 
630 /* Builds a bvh tree where nodes are the vertices of the given em */
632  BMEditMesh *em,
633  const BLI_bitmap *verts_mask,
634  int verts_num_active,
635  float epsilon,
636  int tree_type,
637  int axis,
638  const BVHCacheType bvh_cache_type,
639  BVHCache **bvh_cache_p,
640  ThreadMutex *mesh_eval_mutex)
641 {
642  BVHTree *tree = NULL;
643 
644  if (bvh_cache_p) {
645  bool lock_started = false;
646  data->cached = bvhcache_find(
647  bvh_cache_p, bvh_cache_type, &data->tree, &lock_started, mesh_eval_mutex);
648 
649  if (data->cached == false) {
651  epsilon, tree_type, axis, em, verts_mask, verts_num_active);
652 
653  /* Save on cache for later use */
654  /* printf("BVHTree built and saved on cache\n"); */
655  bvhcache_insert(*bvh_cache_p, tree, bvh_cache_type);
656  data->cached = true;
657  }
658  bvhcache_unlock(*bvh_cache_p, lock_started);
659  }
660  else {
662  epsilon, tree_type, axis, em, verts_mask, verts_num_active);
663  }
664 
665  if (tree) {
666  memset(data, 0, sizeof(*data));
667  data->tree = tree;
668  data->em = em;
669  data->nearest_callback = NULL;
670  data->raycast_callback = editmesh_verts_spherecast;
671  data->cached = bvh_cache_p != NULL;
672  }
673 
674  return tree;
675 }
676 
678  BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
679 {
681  data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL);
682 }
683 
692  const MVert *vert,
693  const int verts_num,
694  const bool vert_allocated,
695  const BLI_bitmap *verts_mask,
696  int verts_num_active,
697  float epsilon,
698  int tree_type,
699  int axis,
700  const BVHCacheType bvh_cache_type,
701  BVHCache **bvh_cache_p,
702  ThreadMutex *mesh_eval_mutex)
703 {
704  bool in_cache = false;
705  bool lock_started = false;
706  BVHTree *tree = NULL;
707  if (bvh_cache_p) {
708  in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
709  }
710 
711  if (in_cache == false) {
713  epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active);
714 
715  if (bvh_cache_p) {
716  /* Save on cache for later use */
717  /* printf("BVHTree built and saved on cache\n"); */
718  BVHCache *bvh_cache = *bvh_cache_p;
719  bvhcache_insert(bvh_cache, tree, bvh_cache_type);
720  in_cache = true;
721  }
722  }
723 
724  if (bvh_cache_p) {
725  bvhcache_unlock(*bvh_cache_p, lock_started);
726  }
727 
728  /* Setup BVHTreeFromMesh */
729  bvhtree_from_mesh_verts_setup_data(data, tree, in_cache, vert, vert_allocated);
730 
731  return tree;
732 }
733 
736 /* -------------------------------------------------------------------- */
741  int tree_type,
742  int axis,
743  BMEditMesh *em,
744  const BLI_bitmap *edges_mask,
745  int edges_num_active)
746 {
748  const int edges_num = em->bm->totedge;
749 
750  if (edges_mask) {
751  BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edges_num));
752  }
753  else {
754  edges_num_active = edges_num;
755  }
756 
757  BVHTree *tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis);
758 
759  if (tree) {
760  int i;
761  BMIter iter;
762  BMEdge *eed;
763  BM_ITER_MESH_INDEX (eed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
764  if (edges_mask && !BLI_BITMAP_TEST_BOOL(edges_mask, i)) {
765  continue;
766  }
767  float co[2][3];
768  copy_v3_v3(co[0], eed->v1->co);
769  copy_v3_v3(co[1], eed->v2->co);
770 
771  BLI_bvhtree_insert(tree, i, co[0], 2);
772  }
773  BLI_assert(BLI_bvhtree_get_len(tree) == edges_num_active);
775  }
776 
777  return tree;
778 }
779 
781  const MEdge *edge,
782  const int edge_num,
783  const BLI_bitmap *edges_mask,
784  int edges_num_active,
785  float epsilon,
786  int tree_type,
787  int axis)
788 {
789  BVHTree *tree = NULL;
790 
791  if (edges_mask) {
792  BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edge_num));
793  }
794  else {
795  edges_num_active = edge_num;
796  }
797 
798  if (edges_num_active) {
799  /* Create a bvh-tree of the given target */
800  tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis);
801  if (tree) {
802  for (int i = 0; i < edge_num; i++) {
803  if (edges_mask && !BLI_BITMAP_TEST_BOOL(edges_mask, i)) {
804  continue;
805  }
806  float co[2][3];
807  copy_v3_v3(co[0], vert[edge[i].v1].co);
808  copy_v3_v3(co[1], vert[edge[i].v2].co);
809 
810  BLI_bvhtree_insert(tree, i, co[0], 2);
811  }
813  }
814  }
815 
816  return tree;
817 }
818 
820  BVHTree *tree,
821  const bool is_cached,
822  const MVert *vert,
823  const bool vert_allocated,
824  const MEdge *edge,
825  const bool edge_allocated)
826 {
827  memset(data, 0, sizeof(*data));
828 
829  data->tree = tree;
830 
831  data->cached = is_cached;
832 
833  data->nearest_callback = mesh_edges_nearest_point;
834  data->raycast_callback = mesh_edges_spherecast;
835 
836  data->vert = vert;
837  data->vert_allocated = vert_allocated;
838  data->edge = edge;
839  data->edge_allocated = edge_allocated;
840 }
841 
842 /* Builds a bvh tree where nodes are the edges of the given em */
844  BMEditMesh *em,
845  const BLI_bitmap *edges_mask,
846  int edges_num_active,
847  float epsilon,
848  int tree_type,
849  int axis,
850  const BVHCacheType bvh_cache_type,
851  BVHCache **bvh_cache_p,
852  ThreadMutex *mesh_eval_mutex)
853 {
854  BVHTree *tree = NULL;
855 
856  if (bvh_cache_p) {
857  bool lock_started = false;
858  data->cached = bvhcache_find(
859  bvh_cache_p, bvh_cache_type, &data->tree, &lock_started, mesh_eval_mutex);
860  BVHCache *bvh_cache = *bvh_cache_p;
861  if (data->cached == false) {
863  epsilon, tree_type, axis, em, edges_mask, edges_num_active);
864 
865  /* Save on cache for later use */
866  /* printf("BVHTree built and saved on cache\n"); */
867  bvhcache_insert(bvh_cache, tree, bvh_cache_type);
868  data->cached = true;
869  }
870  bvhcache_unlock(bvh_cache, lock_started);
871  }
872  else {
874  epsilon, tree_type, axis, em, edges_mask, edges_num_active);
875  }
876 
877  if (tree) {
878  memset(data, 0, sizeof(*data));
879  data->tree = tree;
880  data->em = em;
881  data->nearest_callback = NULL; /* TODO */
882  data->raycast_callback = NULL; /* TODO */
883  data->cached = bvh_cache_p != NULL;
884  }
885 
886  return tree;
887 }
888 
890  BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
891 {
893  data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL);
894 }
895 
905  const MVert *vert,
906  const bool vert_allocated,
907  const MEdge *edge,
908  const int edges_num,
909  const bool edge_allocated,
910  const BLI_bitmap *edges_mask,
911  int edges_num_active,
912  float epsilon,
913  int tree_type,
914  int axis,
915  const BVHCacheType bvh_cache_type,
916  BVHCache **bvh_cache_p,
917  ThreadMutex *mesh_eval_mutex)
918 {
919  bool in_cache = false;
920  bool lock_started = false;
921  BVHTree *tree = NULL;
922  if (bvh_cache_p) {
923  in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
924  }
925 
926  if (in_cache == false) {
928  vert, edge, edges_num, edges_mask, edges_num_active, epsilon, tree_type, axis);
929 
930  if (bvh_cache_p) {
931  BVHCache *bvh_cache = *bvh_cache_p;
932  /* Save on cache for later use */
933  /* printf("BVHTree built and saved on cache\n"); */
934  bvhcache_insert(bvh_cache, tree, bvh_cache_type);
935  in_cache = true;
936  }
937  }
938 
939  if (bvh_cache_p) {
940  bvhcache_unlock(*bvh_cache_p, lock_started);
941  }
942 
943  /* Setup BVHTreeFromMesh */
945  data, tree, in_cache, vert, vert_allocated, edge, edge_allocated);
946 
947  return tree;
948 }
949 
952 /* -------------------------------------------------------------------- */
957  int tree_type,
958  int axis,
959  const MVert *vert,
960  const MFace *face,
961  const int faces_num,
962  const BLI_bitmap *faces_mask,
963  int faces_num_active)
964 {
965  BVHTree *tree = NULL;
966 
967  if (faces_num) {
968  if (faces_mask) {
969  BLI_assert(IN_RANGE_INCL(faces_num_active, 0, faces_num));
970  }
971  else {
972  faces_num_active = faces_num;
973  }
974 
975  /* Create a bvh-tree of the given target */
976  /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */
977  tree = BLI_bvhtree_new(faces_num_active, epsilon, tree_type, axis);
978  if (tree) {
979  if (vert && face) {
980  for (int i = 0; i < faces_num; i++) {
981  float co[4][3];
982  if (faces_mask && !BLI_BITMAP_TEST_BOOL(faces_mask, i)) {
983  continue;
984  }
985 
986  copy_v3_v3(co[0], vert[face[i].v1].co);
987  copy_v3_v3(co[1], vert[face[i].v2].co);
988  copy_v3_v3(co[2], vert[face[i].v3].co);
989  if (face[i].v4) {
990  copy_v3_v3(co[3], vert[face[i].v4].co);
991  }
992 
993  BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
994  }
995  }
996  BLI_assert(BLI_bvhtree_get_len(tree) == faces_num_active);
998  }
999  }
1000 
1001  return tree;
1002 }
1003 
1005  BVHTree *tree,
1006  const bool is_cached,
1007  const MVert *vert,
1008  const bool vert_allocated,
1009  const MFace *face,
1010  const bool face_allocated)
1011 {
1012  memset(data, 0, sizeof(*data));
1013 
1014  data->tree = tree;
1015  data->cached = is_cached;
1016 
1017  data->nearest_callback = mesh_faces_nearest_point;
1018  data->raycast_callback = mesh_faces_spherecast;
1019 
1020  data->vert = vert;
1021  data->vert_allocated = vert_allocated;
1022  data->face = face;
1023  data->face_allocated = face_allocated;
1024 }
1025 
1036  const MVert *vert,
1037  const bool vert_allocated,
1038  const MFace *face,
1039  const int numFaces,
1040  const bool face_allocated,
1041  const BLI_bitmap *faces_mask,
1042  int faces_num_active,
1043  float epsilon,
1044  int tree_type,
1045  int axis,
1046  const BVHCacheType bvh_cache_type,
1047  BVHCache **bvh_cache_p,
1048  ThreadMutex *mesh_eval_mutex)
1049 {
1050  bool in_cache = false;
1051  bool lock_started = false;
1052  BVHTree *tree = NULL;
1053  if (bvh_cache_p) {
1054  in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
1055  }
1056 
1057  if (in_cache == false) {
1059  epsilon, tree_type, axis, vert, face, numFaces, faces_mask, faces_num_active);
1060 
1061  if (bvh_cache_p) {
1062  /* Save on cache for later use */
1063  /* printf("BVHTree built and saved on cache\n"); */
1064  BVHCache *bvh_cache = *bvh_cache_p;
1065  bvhcache_insert(bvh_cache, tree, bvh_cache_type);
1066  in_cache = true;
1067  }
1068  }
1069 
1070  if (bvh_cache_p) {
1071  bvhcache_unlock(*bvh_cache_p, lock_started);
1072  }
1073 
1074  /* Setup BVHTreeFromMesh */
1076  data, tree, in_cache, vert, vert_allocated, face, face_allocated);
1077 
1078  return tree;
1079 }
1080 
1083 /* -------------------------------------------------------------------- */
1088  int tree_type,
1089  int axis,
1090  BMEditMesh *em,
1091  const BLI_bitmap *looptri_mask,
1092  int looptri_num_active)
1093 {
1094  BVHTree *tree = NULL;
1095  const int looptri_num = em->tottri;
1096 
1097  if (looptri_num) {
1098  if (looptri_mask) {
1099  BLI_assert(IN_RANGE_INCL(looptri_num_active, 0, looptri_num));
1100  }
1101  else {
1102  looptri_num_active = looptri_num;
1103  }
1104 
1105  /* Create a bvh-tree of the given target */
1106  /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */
1107  tree = BLI_bvhtree_new(looptri_num_active, epsilon, tree_type, axis);
1108  if (tree) {
1109  const struct BMLoop *(*looptris)[3] = (void *)em->looptris;
1110 
1111  /* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden
1112  * and/or selected. Even if the faces themselves are not selected for the snapped
1113  * transform, having a vertex selected means the face (and thus it's tessellated
1114  * triangles) will be moving and will not be a good snap targets. */
1115  for (int i = 0; i < looptri_num; i++) {
1116  const BMLoop **ltri = looptris[i];
1117  bool insert = looptri_mask ? BLI_BITMAP_TEST_BOOL(looptri_mask, i) : true;
1118 
1119  if (insert) {
1120  /* No reason found to block hit-testing the triangle for snap, so insert it now.*/
1121  float co[3][3];
1122  copy_v3_v3(co[0], ltri[0]->v->co);
1123  copy_v3_v3(co[1], ltri[1]->v->co);
1124  copy_v3_v3(co[2], ltri[2]->v->co);
1125 
1126  BLI_bvhtree_insert(tree, i, co[0], 3);
1127  }
1128  }
1129  BLI_assert(BLI_bvhtree_get_len(tree) == looptri_num_active);
1131  }
1132  }
1133 
1134  return tree;
1135 }
1136 
1138  int tree_type,
1139  int axis,
1140  const MVert *vert,
1141  const MLoop *mloop,
1142  const MLoopTri *looptri,
1143  const int looptri_num,
1144  const BLI_bitmap *looptri_mask,
1145  int looptri_num_active)
1146 {
1147  BVHTree *tree = NULL;
1148 
1149  if (looptri_mask) {
1150  BLI_assert(IN_RANGE_INCL(looptri_num_active, 0, looptri_num));
1151  }
1152  else {
1153  looptri_num_active = looptri_num;
1154  }
1155 
1156  if (looptri_num_active) {
1157  /* Create a bvh-tree of the given target */
1158  /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */
1159  tree = BLI_bvhtree_new(looptri_num_active, epsilon, tree_type, axis);
1160  if (tree) {
1161  if (vert && looptri) {
1162  for (int i = 0; i < looptri_num; i++) {
1163  float co[3][3];
1164  if (looptri_mask && !BLI_BITMAP_TEST_BOOL(looptri_mask, i)) {
1165  continue;
1166  }
1167 
1168  copy_v3_v3(co[0], vert[mloop[looptri[i].tri[0]].v].co);
1169  copy_v3_v3(co[1], vert[mloop[looptri[i].tri[1]].v].co);
1170  copy_v3_v3(co[2], vert[mloop[looptri[i].tri[2]].v].co);
1171 
1172  BLI_bvhtree_insert(tree, i, co[0], 3);
1173  }
1174  }
1175  BLI_assert(BLI_bvhtree_get_len(tree) == looptri_num_active);
1177  }
1178  }
1179 
1180  return tree;
1181 }
1182 
1184  BVHTree *tree,
1185  const bool is_cached,
1186  const MVert *vert,
1187  const bool vert_allocated,
1188  const MLoop *mloop,
1189  const bool loop_allocated,
1190  const MLoopTri *looptri,
1191  const bool looptri_allocated)
1192 {
1193  memset(data, 0, sizeof(*data));
1194 
1195  data->tree = tree;
1196  data->cached = is_cached;
1197 
1198  data->nearest_callback = mesh_looptri_nearest_point;
1199  data->raycast_callback = mesh_looptri_spherecast;
1200 
1201  data->vert = vert;
1202  data->vert_allocated = vert_allocated;
1203  data->loop = mloop;
1204  data->loop_allocated = loop_allocated;
1205  data->looptri = looptri;
1206  data->looptri_allocated = looptri_allocated;
1207 }
1208 
1213  BMEditMesh *em,
1214  const BLI_bitmap *looptri_mask,
1215  int looptri_num_active,
1216  float epsilon,
1217  int tree_type,
1218  int axis,
1219  const BVHCacheType bvh_cache_type,
1220  BVHCache **bvh_cache_p,
1221  ThreadMutex *mesh_eval_mutex)
1222 {
1223  /* BMESH specific check that we have tessfaces,
1224  * we _could_ tessellate here but rather not - campbell */
1225 
1226  BVHTree *tree = NULL;
1227  if (bvh_cache_p) {
1228  bool lock_started = false;
1229  bool in_cache = bvhcache_find(
1230  bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
1231  BVHCache *bvh_cache = *bvh_cache_p;
1232 
1233  if (in_cache == false) {
1235  epsilon, tree_type, axis, em, looptri_mask, looptri_num_active);
1236 
1237  /* Save on cache for later use */
1238  /* printf("BVHTree built and saved on cache\n"); */
1239  bvhcache_insert(bvh_cache, tree, bvh_cache_type);
1240  }
1241  bvhcache_unlock(bvh_cache, lock_started);
1242  }
1243  else {
1245  epsilon, tree_type, axis, em, looptri_mask, looptri_num_active);
1246  }
1247 
1248  if (tree) {
1249  data->tree = tree;
1250  data->nearest_callback = editmesh_looptri_nearest_point;
1251  data->raycast_callback = editmesh_looptri_spherecast;
1252  data->em = em;
1253  data->cached = bvh_cache_p != NULL;
1254  }
1255  return tree;
1256 }
1257 
1259  BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
1260 {
1262  data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL);
1263 }
1264 
1271  const struct MVert *vert,
1272  const bool vert_allocated,
1273  const struct MLoop *mloop,
1274  const bool loop_allocated,
1275  const struct MLoopTri *looptri,
1276  const int looptri_num,
1277  const bool looptri_allocated,
1278  const BLI_bitmap *looptri_mask,
1279  int looptri_num_active,
1280  float epsilon,
1281  int tree_type,
1282  int axis,
1283  const BVHCacheType bvh_cache_type,
1284  BVHCache **bvh_cache_p,
1285  ThreadMutex *mesh_eval_mutex)
1286 {
1287  bool in_cache = false;
1288  bool lock_started = false;
1289  BVHTree *tree = NULL;
1290  if (bvh_cache_p) {
1291  in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
1292  }
1293 
1294  if (in_cache == false) {
1295  /* Setup BVHTreeFromMesh */
1297  tree_type,
1298  axis,
1299  vert,
1300  mloop,
1301  looptri,
1302  looptri_num,
1303  looptri_mask,
1304  looptri_num_active);
1305 
1306  if (bvh_cache_p) {
1307  BVHCache *bvh_cache = *bvh_cache_p;
1308  bvhcache_insert(bvh_cache, tree, bvh_cache_type);
1309  in_cache = true;
1310  }
1311  }
1312 
1313  if (bvh_cache_p) {
1314  bvhcache_unlock(*bvh_cache_p, lock_started);
1315  }
1316 
1317  /* Setup BVHTreeFromMesh */
1319  tree,
1320  in_cache,
1321  vert,
1322  vert_allocated,
1323  mloop,
1324  loop_allocated,
1325  looptri,
1326  looptri_allocated);
1327 
1328  return tree;
1329 }
1330 
1331 static BLI_bitmap *loose_verts_map_get(const MEdge *medge,
1332  int edges_num,
1333  const MVert *UNUSED(mvert),
1334  int verts_num,
1335  int *r_loose_vert_num)
1336 {
1337  BLI_bitmap *loose_verts_mask = BLI_BITMAP_NEW(verts_num, __func__);
1338  BLI_bitmap_set_all(loose_verts_mask, true, verts_num);
1339 
1340  const MEdge *e = medge;
1341  int num_linked_verts = 0;
1342  for (; edges_num--; e++) {
1343  if (BLI_BITMAP_TEST(loose_verts_mask, e->v1)) {
1344  BLI_BITMAP_DISABLE(loose_verts_mask, e->v1);
1345  num_linked_verts++;
1346  }
1347  if (BLI_BITMAP_TEST(loose_verts_mask, e->v2)) {
1348  BLI_BITMAP_DISABLE(loose_verts_mask, e->v2);
1349  num_linked_verts++;
1350  }
1351  }
1352 
1353  *r_loose_vert_num = verts_num - num_linked_verts;
1354 
1355  return loose_verts_mask;
1356 }
1357 
1358 static BLI_bitmap *loose_edges_map_get(const MEdge *medge,
1359  const int edges_len,
1360  int *r_loose_edge_len)
1361 {
1362  BLI_bitmap *loose_edges_mask = BLI_BITMAP_NEW(edges_len, __func__);
1363 
1364  int loose_edges_len = 0;
1365  const MEdge *e = medge;
1366  for (int i = 0; i < edges_len; i++, e++) {
1367  if (e->flag & ME_LOOSEEDGE) {
1368  BLI_BITMAP_ENABLE(loose_edges_mask, i);
1369  loose_edges_len++;
1370  }
1371  else {
1372  BLI_BITMAP_DISABLE(loose_edges_mask, i);
1373  }
1374  }
1375 
1376  *r_loose_edge_len = loose_edges_len;
1377 
1378  return loose_edges_mask;
1379 }
1380 
1382  const int looptri_len,
1383  int *r_looptri_active_len)
1384 {
1385  BLI_bitmap *looptri_mask = BLI_BITMAP_NEW(looptri_len, __func__);
1386 
1387  int looptri_no_hidden_len = 0;
1388  int looptri_iter = 0;
1389  const MPoly *mp = mpoly;
1390  while (looptri_iter != looptri_len) {
1391  int mp_totlooptri = mp->totloop - 2;
1392  if (mp->flag & ME_HIDE) {
1393  looptri_iter += mp_totlooptri;
1394  }
1395  else {
1396  while (mp_totlooptri--) {
1397  BLI_BITMAP_ENABLE(looptri_mask, looptri_iter);
1398  looptri_iter++;
1399  looptri_no_hidden_len++;
1400  }
1401  }
1402  mp++;
1403  }
1404 
1405  *r_looptri_active_len = looptri_no_hidden_len;
1406 
1407  return looptri_mask;
1408 }
1409 
1414  struct Mesh *mesh,
1415  const BVHCacheType bvh_cache_type,
1416  const int tree_type)
1417 {
1418  BVHTree *tree = NULL;
1419  BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime.bvh_cache;
1420  ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex;
1421 
1422  bool is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, NULL, NULL);
1423 
1424  if (is_cached && tree == NULL) {
1425  memset(data, 0, sizeof(*data));
1426  return tree;
1427  }
1428 
1429  switch (bvh_cache_type) {
1430  case BVHTREE_FROM_VERTS:
1432  if (is_cached == false) {
1433  BLI_bitmap *loose_verts_mask = NULL;
1434  int loose_vert_len = -1;
1435  int verts_len = mesh->totvert;
1436 
1437  if (bvh_cache_type == BVHTREE_FROM_LOOSEVERTS) {
1438  loose_verts_mask = loose_verts_map_get(
1439  mesh->medge, mesh->totedge, mesh->mvert, verts_len, &loose_vert_len);
1440  }
1441 
1443  mesh->mvert,
1444  verts_len,
1445  false,
1446  loose_verts_mask,
1447  loose_vert_len,
1448  0.0f,
1449  tree_type,
1450  6,
1451  bvh_cache_type,
1452  bvh_cache_p,
1453  mesh_eval_mutex);
1454 
1455  if (loose_verts_mask != NULL) {
1456  MEM_freeN(loose_verts_mask);
1457  }
1458  }
1459  else {
1460  /* Setup BVHTreeFromMesh */
1462  }
1463  break;
1464 
1465  case BVHTREE_FROM_EDGES:
1467  if (is_cached == false) {
1468  BLI_bitmap *loose_edges_mask = NULL;
1469  int loose_edges_len = -1;
1470  int edges_len = mesh->totedge;
1471 
1472  if (bvh_cache_type == BVHTREE_FROM_LOOSEEDGES) {
1473  loose_edges_mask = loose_edges_map_get(mesh->medge, edges_len, &loose_edges_len);
1474  }
1475 
1477  mesh->mvert,
1478  false,
1479  mesh->medge,
1480  edges_len,
1481  false,
1482  loose_edges_mask,
1483  loose_edges_len,
1484  0.0,
1485  tree_type,
1486  6,
1487  bvh_cache_type,
1488  bvh_cache_p,
1489  mesh_eval_mutex);
1490 
1491  if (loose_edges_mask != NULL) {
1492  MEM_freeN(loose_edges_mask);
1493  }
1494  }
1495  else {
1496  /* Setup BVHTreeFromMesh */
1498  data, tree, true, mesh->mvert, false, mesh->medge, false);
1499  }
1500  break;
1501 
1502  case BVHTREE_FROM_FACES:
1503  if (is_cached == false) {
1504  int num_faces = mesh->totface;
1505  BLI_assert(!(num_faces == 0 && mesh->totpoly != 0));
1506 
1508  mesh->mvert,
1509  false,
1510  mesh->mface,
1511  num_faces,
1512  false,
1513  NULL,
1514  -1,
1515  0.0,
1516  tree_type,
1517  6,
1518  bvh_cache_type,
1519  bvh_cache_p,
1520  mesh_eval_mutex);
1521  }
1522  else {
1523  /* Setup BVHTreeFromMesh */
1525  data, tree, true, mesh->mvert, false, mesh->mface, false);
1526  }
1527  break;
1528 
1529  case BVHTREE_FROM_LOOPTRI:
1531  if (is_cached == false) {
1532  const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
1533  int looptri_len = BKE_mesh_runtime_looptri_len(mesh);
1534 
1535  int looptri_mask_active_len = -1;
1536  BLI_bitmap *looptri_mask = NULL;
1537  if (bvh_cache_type == BVHTREE_FROM_LOOPTRI_NO_HIDDEN) {
1538  looptri_mask = looptri_no_hidden_map_get(
1539  mesh->mpoly, looptri_len, &looptri_mask_active_len);
1540  }
1541 
1543  mesh->mvert,
1544  false,
1545  mesh->mloop,
1546  false,
1547  mlooptri,
1548  looptri_len,
1549  false,
1550  looptri_mask,
1551  looptri_mask_active_len,
1552  0.0,
1553  tree_type,
1554  6,
1555  bvh_cache_type,
1556  bvh_cache_p,
1557  mesh_eval_mutex);
1558 
1559  if (looptri_mask != NULL) {
1560  MEM_freeN(looptri_mask);
1561  }
1562  }
1563  else {
1564  /* Setup BVHTreeFromMesh */
1565  const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
1567  data, tree, true, mesh->mvert, false, mesh->mloop, false, mlooptri, false);
1568  }
1569  break;
1570  case BVHTREE_FROM_EM_VERTS:
1571  case BVHTREE_FROM_EM_EDGES:
1573  case BVHTREE_MAX_ITEM:
1574  BLI_assert(false);
1575  break;
1576  }
1577 
1578  if (data->tree != NULL) {
1579 #ifdef DEBUG
1580  if (BLI_bvhtree_get_tree_type(data->tree) != tree_type) {
1581  printf("tree_type %d obtained instead of %d\n",
1583  tree_type);
1584  }
1585 #endif
1586  BLI_assert(data->cached);
1587  }
1588  else {
1590  memset(data, 0, sizeof(*data));
1591  }
1592 
1593  return tree;
1594 }
1595 
1600  struct BMEditMesh *em,
1601  const int tree_type,
1602  const BVHCacheType bvh_cache_type,
1603  BVHCache **bvh_cache_p,
1604  ThreadMutex *mesh_eval_mutex)
1605 {
1606  BVHTree *tree = NULL;
1607  bool is_cached = false;
1608 
1609  memset(data, 0, sizeof(*data));
1610 
1611  if (bvh_cache_p) {
1612  is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, NULL, NULL);
1613 
1614  if (is_cached && tree == NULL) {
1615  return tree;
1616  }
1617  }
1618  data->tree = tree;
1619  data->em = em;
1620  data->cached = is_cached;
1621 
1622  switch (bvh_cache_type) {
1623  case BVHTREE_FROM_EM_VERTS:
1624  if (is_cached == false) {
1626  data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex);
1627  }
1628  else {
1629  data->nearest_callback = NULL;
1630  data->raycast_callback = editmesh_verts_spherecast;
1631  }
1632  break;
1633 
1634  case BVHTREE_FROM_EM_EDGES:
1635  if (is_cached == false) {
1637  data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex);
1638  }
1639  else {
1640  /* Setup BVHTreeFromMesh */
1641  data->nearest_callback = NULL; /* TODO */
1642  data->raycast_callback = NULL; /* TODO */
1643  }
1644  break;
1645 
1647  if (is_cached == false) {
1649  data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex);
1650  }
1651  else {
1652  /* Setup BVHTreeFromMesh */
1653  data->nearest_callback = editmesh_looptri_nearest_point;
1654  data->raycast_callback = editmesh_looptri_spherecast;
1655  }
1656  break;
1657  case BVHTREE_FROM_VERTS:
1658  case BVHTREE_FROM_EDGES:
1659  case BVHTREE_FROM_FACES:
1660  case BVHTREE_FROM_LOOPTRI:
1664  case BVHTREE_MAX_ITEM:
1665  BLI_assert(false);
1666  break;
1667  }
1668 
1669  if (data->tree != NULL) {
1670 #ifdef DEBUG
1671  if (BLI_bvhtree_get_tree_type(data->tree) != tree_type) {
1672  printf("tree_type %d obtained instead of %d\n",
1674  tree_type);
1675  }
1676 #endif
1677  BLI_assert(data->cached);
1678  }
1679  else {
1681  memset(data, 0, sizeof(*data));
1682  }
1683 
1684  return tree;
1685 }
1686 
1689 /* Frees data allocated by a call to bvhtree_from_editmesh_*. */
1691 {
1692  if (data->tree) {
1693  if (!data->cached) {
1694  BLI_bvhtree_free(data->tree);
1695  }
1696  memset(data, 0, sizeof(*data));
1697  }
1698 }
1699 
1700 /* Frees data allocated by a call to bvhtree_from_mesh_*. */
1702 {
1703  if (data->tree && !data->cached) {
1704  BLI_bvhtree_free(data->tree);
1705  }
1706 
1707  if (data->vert_allocated) {
1708  MEM_freeN((void *)data->vert);
1709  }
1710  if (data->edge_allocated) {
1711  MEM_freeN((void *)data->edge);
1712  }
1713  if (data->face_allocated) {
1714  MEM_freeN((void *)data->face);
1715  }
1716  if (data->loop_allocated) {
1717  MEM_freeN((void *)data->loop);
1718  }
1719  if (data->looptri_allocated) {
1720  MEM_freeN((void *)data->looptri);
1721  }
1722 
1723  memset(data, 0, sizeof(*data));
1724 }
1725 
1728 /* -------------------------------------------------------------------- */
1733  const PointCloud *pointcloud,
1734  const int tree_type)
1735 {
1736  BVHTree *tree = BLI_bvhtree_new(pointcloud->totpoint, 0.0f, tree_type, 6);
1737  if (!tree) {
1738  return NULL;
1739  }
1740 
1741  for (int i = 0; i < pointcloud->totpoint; i++) {
1742  BLI_bvhtree_insert(tree, i, pointcloud->co[i], 1);
1743  }
1744  BLI_assert(BLI_bvhtree_get_len(tree) == pointcloud->totpoint);
1746 
1747  data->coords = pointcloud->co;
1748  data->tree = tree;
1749  data->nearest_callback = NULL;
1750 
1751  return tree;
1752 }
1753 
1755 {
1756  if (data->tree) {
1757  BLI_bvhtree_free(data->tree);
1758  }
1759  memset(data, 0, sizeof(*data));
1760 }
1761 
BVHCacheType
Definition: BKE_bvhutils.h:89
@ BVHTREE_FROM_EDGES
Definition: BKE_bvhutils.h:91
@ BVHTREE_FROM_EM_EDGES
Definition: BKE_bvhutils.h:100
@ BVHTREE_FROM_FACES
Definition: BKE_bvhutils.h:92
@ 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
@ BVHTREE_MAX_ITEM
Definition: BKE_bvhutils.h:104
@ BVHTREE_FROM_VERTS
Definition: BKE_bvhutils.h:90
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(struct Mesh *mesh)
Definition: mesh_runtime.c:155
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh)
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_BITMAP_TEST(_bitmap, _index)
Definition: BLI_bitmap.h:63
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:78
#define BLI_BITMAP_DISABLE(_bitmap, _index)
Definition: BLI_bitmap.h:83
#define BLI_BITMAP_TEST_BOOL(_bitmap, _index)
Definition: BLI_bitmap.h:73
#define BLI_BITMAP_NEW(_tot, _alloc_string)
Definition: BLI_bitmap.h:50
void BLI_bitmap_set_all(BLI_bitmap *bitmap, bool set, size_t bits)
Definition: bitmap.c:33
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
int BLI_bvhtree_get_tree_type(const BVHTree *tree)
Definition: BLI_kdopbvh.c:1069
void BLI_bvhtree_balance(BVHTree *tree)
Definition: BLI_kdopbvh.c:956
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
Definition: BLI_kdopbvh.c:873
void BLI_bvhtree_free(BVHTree *tree)
Definition: BLI_kdopbvh.c:945
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
Definition: BLI_kdopbvh.c:998
int BLI_bvhtree_get_len(const BVHTree *tree)
Definition: BLI_kdopbvh.c:1061
void BLI_kdtree_nd_() insert(KDTree *tree, int index, const float co[KD_DIMS]) ATTR_NONNULL(1
MINLINE float square_f(float a)
int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float r_i1[3], float r_i2[3])
Definition: math_geom.c:3103
bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius, const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float ipoint[3])
Definition: math_geom.c:2788
bool isect_ray_tri_watertight_v3(const float ray_origin[3], const struct IsectRayPrecalc *isect_precalc, const float v0[3], const float v1[3], const float v2[3], float *r_dist, float r_uv[2])
Definition: math_geom.c:1906
void closest_on_tri_to_point_v3(float r[3], const float p[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:1023
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3449
void closest_to_line_segment_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:375
bool isect_ray_tri_epsilon_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float epsilon)
Definition: math_geom.c:1830
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:51
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3(float r[3])
MINLINE float dot_v3v3v3(const float p[3], const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
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 copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
void BLI_mutex_end(ThreadMutex *mutex)
Definition: threads.cc:416
void BLI_mutex_init(ThreadMutex *mutex)
Definition: threads.cc:396
void BLI_mutex_lock(ThreadMutex *mutex)
Definition: threads.cc:401
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition: threads.cc:406
pthread_mutex_t ThreadMutex
Definition: BLI_threads.h:83
#define UNUSED(x)
#define UNPACK3(a)
#define IN_RANGE_INCL(a, b, c)
@ ME_HIDE
@ ME_LOOSEEDGE
_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 i1
_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_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_EDGES_OF_MESH
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2276
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 const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
BVHTree * bvhtree_from_editmesh_looptri(BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
Definition: bvhutils.c:1258
bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree)
Definition: bvhutils.c:113
static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition: bvhutils.c:308
static BLI_bitmap * loose_edges_map_get(const MEdge *medge, const int edges_len, int *r_loose_edge_len)
Definition: bvhutils.c:1358
static BVHTree * bvhtree_from_mesh_faces_create_tree(float epsilon, int tree_type, int axis, const MVert *vert, const MFace *face, const int faces_num, const BLI_bitmap *faces_mask, int faces_num_active)
Definition: bvhutils.c:956
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
BVHTree * bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, BMEditMesh *em, const BLI_bitmap *looptri_mask, int looptri_num_active, float epsilon, int tree_type, int axis, const BVHCacheType bvh_cache_type, BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex)
Definition: bvhutils.c:1212
static void mesh_looptri_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
Definition: bvhutils.c:251
static BVHTree * bvhtree_from_mesh_verts_create_tree(float epsilon, int tree_type, int axis, const MVert *vert, const int verts_num, const BLI_bitmap *verts_mask, int verts_num_active)
Definition: bvhutils.c:575
static BVHTree * bvhtree_from_mesh_looptri_create_tree(float epsilon, int tree_type, int axis, const MVert *vert, const MLoop *mloop, const MLoopTri *looptri, const int looptri_num, const BLI_bitmap *looptri_mask, int looptri_num_active)
Definition: bvhutils.c:1137
BVHTree * BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, struct BMEditMesh *em, const int tree_type, const BVHCacheType bvh_cache_type, BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex)
Definition: bvhutils.c:1599
BVHCache * bvhcache_init(void)
Definition: bvhutils.c:127
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
Definition: bvhutils.c:1701
void free_bvhtree_from_pointcloud(BVHTreeFromPointCloud *data)
Definition: bvhutils.c:1754
struct BVHCacheItem BVHCacheItem
static void mesh_looptri_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition: bvhutils.c:347
static void mesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
Definition: bvhutils.c:216
static BVHTree * bvhtree_from_editmesh_looptri_create_tree(float epsilon, int tree_type, int axis, BMEditMesh *em, const BLI_bitmap *looptri_mask, int looptri_num_active)
Definition: bvhutils.c:1087
static void bvhcache_insert(BVHCache *bvh_cache, BVHTree *tree, BVHCacheType type)
Definition: bvhutils.c:141
static void mesh_verts_spherecast_do(int index, const float v[3], const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition: bvhutils.c:440
BVHTree * bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data, const MVert *vert, const int verts_num, const bool vert_allocated, const BLI_bitmap *verts_mask, int verts_num_active, float epsilon, int tree_type, int axis, const BVHCacheType bvh_cache_type, BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex)
Definition: bvhutils.c:691
BVHTree * BKE_bvhtree_from_pointcloud_get(BVHTreeFromPointCloud *data, const PointCloud *pointcloud, const int tree_type)
Definition: bvhutils.c:1732
float bvhtree_ray_tri_intersection(const BVHTreeRay *ray, const float UNUSED(m_dist), const float v0[3], const float v1[3], const float v2[3])
Definition: bvhutils.c:170
static void bvhtree_from_mesh_verts_setup_data(BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, const MVert *vert, const bool vert_allocated)
Definition: bvhutils.c:610
static BLI_bitmap * looptri_no_hidden_map_get(const MPoly *mpoly, const int looptri_len, int *r_looptri_active_len)
Definition: bvhutils.c:1381
static BVHTree * bvhtree_from_editmesh_verts_create_tree(float epsilon, int tree_type, int axis, BMEditMesh *em, const BLI_bitmap *verts_mask, int verts_num_active)
Definition: bvhutils.c:542
static void bvhtree_from_mesh_faces_setup_data(BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, const MVert *vert, const bool vert_allocated, const MFace *face, const bool face_allocated)
Definition: bvhutils.c:1004
static void editmesh_looptri_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition: bvhutils.c:378
BVHTree * bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data, const struct MVert *vert, const bool vert_allocated, const struct MLoop *mloop, const bool loop_allocated, const struct MLoopTri *looptri, const int looptri_num, const bool looptri_allocated, const BLI_bitmap *looptri_mask, int looptri_num_active, float epsilon, int tree_type, int axis, const BVHCacheType bvh_cache_type, BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex)
Definition: bvhutils.c:1270
static BVHTree * bvhtree_from_editmesh_edges_create_tree(float epsilon, int tree_type, int axis, BMEditMesh *em, const BLI_bitmap *edges_mask, int edges_num_active)
Definition: bvhutils.c:740
static void bvhtree_from_mesh_looptri_setup_data(BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, const MVert *vert, const bool vert_allocated, const MLoop *mloop, const bool loop_allocated, const MLoopTri *looptri, const bool looptri_allocated)
Definition: bvhutils.c:1183
BVHTree * bvhtree_from_editmesh_edges(BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
Definition: bvhutils.c:889
BVHTree * bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data, BMEditMesh *em, const BLI_bitmap *verts_mask, int verts_num_active, float epsilon, int tree_type, int axis, const BVHCacheType bvh_cache_type, BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex)
Definition: bvhutils.c:631
static void bvhtree_from_mesh_edges_setup_data(BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, const MVert *vert, const bool vert_allocated, const MEdge *edge, const bool edge_allocated)
Definition: bvhutils.c:819
static void editmesh_verts_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition: bvhutils.c:461
BVHTree * bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data, BMEditMesh *em, const BLI_bitmap *edges_mask, int edges_num_active, float epsilon, int tree_type, int axis, const BVHCacheType bvh_cache_type, BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex)
Definition: bvhutils.c:843
BVHTree * bvhtree_from_editmesh_verts(BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
Definition: bvhutils.c:677
static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition: bvhutils.c:487
static bool bvhcache_find(BVHCache **bvh_cache_p, BVHCacheType type, BVHTree **r_tree, bool *r_locked, ThreadMutex *mesh_eval_mutex)
Definition: bvhutils.c:66
static BVHTree * bvhtree_from_mesh_edges_create_tree(const MVert *vert, const MEdge *edge, const int edge_num, const BLI_bitmap *edges_mask, int edges_num_active, float epsilon, int tree_type, int axis)
Definition: bvhutils.c:780
static void bvhcache_unlock(BVHCache *bvh_cache, bool lock_started)
Definition: bvhutils.c:106
BVHTree * bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data, const MVert *vert, const bool vert_allocated, const MEdge *edge, const int edges_num, const bool edge_allocated, const BLI_bitmap *edges_mask, int edges_num_active, float epsilon, int tree_type, int axis, const BVHCacheType bvh_cache_type, BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex)
Definition: bvhutils.c:904
void free_bvhtree_from_editmesh(struct BVHTreeFromEditMesh *data)
Definition: bvhutils.c:1690
static BLI_bitmap * loose_verts_map_get(const MEdge *medge, int edges_num, const MVert *UNUSED(mvert), int verts_num, int *r_loose_vert_num)
Definition: bvhutils.c:1331
static void mesh_edges_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
Definition: bvhutils.c:413
struct BVHCache BVHCache
void bvhcache_free(BVHCache *bvh_cache)
Definition: bvhutils.c:152
BVHTree * bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data, const MVert *vert, const bool vert_allocated, const MFace *face, const int numFaces, const bool face_allocated, const BLI_bitmap *faces_mask, int faces_num_active, float epsilon, int tree_type, int axis, const BVHCacheType bvh_cache_type, BVHCache **bvh_cache_p, ThreadMutex *mesh_eval_mutex)
Definition: bvhutils.c:1035
static void mesh_verts_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition: bvhutils.c:474
static void editmesh_looptri_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
Definition: bvhutils.c:277
float bvhtree_sphereray_tri_intersection(const BVHTreeRay *ray, float radius, const float m_dist, const float v0[3], const float v1[3], const float v2[3])
Definition: bvhutils.c:190
void * tree
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static double epsilon
BMVert * v1
Definition: bmesh_class.h:134
BMVert * v2
Definition: bmesh_class.h:134
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
float co[3]
Definition: bmesh_class.h:99
int totvert
Definition: bmesh_class.h:297
int totedge
Definition: bmesh_class.h:297
bool is_filled
Definition: bvhutils.c:49
BVHTree * tree
Definition: bvhutils.c:50
ThreadMutex mutex
Definition: bvhutils.c:55
BVHCacheItem items[BVHTREE_MAX_ITEM]
Definition: bvhutils.c:54
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
struct IsectRayPrecalc * isect_precalc
Definition: BLI_kdopbvh.h:76
float direction[3]
Definition: BLI_kdopbvh.h:72
float radius
Definition: BLI_kdopbvh.h:74
unsigned int v1
unsigned int v2
unsigned int v2
unsigned int v1
unsigned int v4
unsigned int v3
unsigned int tri[3]
float co[3]
struct BVHCache * bvh_cache
void * eval_mutex
struct MEdge * medge
struct MVert * mvert
int totedge
int totvert
struct MLoop * mloop
int totface
Mesh_Runtime runtime
int totpoly
struct MFace * mface
struct MPoly * mpoly
float(* co)[3]