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