Blender V4.3
bvhutils.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11
12#include "BLI_math_geom.h"
13#include "BLI_task.h"
14
15#include "BKE_attribute.hh"
16#include "BKE_bvhutils.hh"
17#include "BKE_editmesh.hh"
18#include "BKE_mesh.hh"
19
22using blender::float3;
24using blender::int3;
25using blender::Span;
26using blender::VArray;
27
28/* -------------------------------------------------------------------- */
36
41
50static bool bvhcache_find(BVHCache **bvh_cache_p,
51 BVHCacheType type,
52 BVHTree **r_tree,
53 bool *r_locked,
54 std::mutex *mesh_eval_mutex)
55{
56 bool do_lock = r_locked;
57 if (r_locked) {
58 *r_locked = false;
59 }
60 if (*bvh_cache_p == nullptr) {
61 if (!do_lock) {
62 /* Cache does not exist and no lock is requested. */
63 return false;
64 }
65 /* Lazy initialization of the bvh_cache using the `mesh_eval_mutex`. */
66 std::lock_guard lock{*mesh_eval_mutex};
67 if (*bvh_cache_p == nullptr) {
68 *bvh_cache_p = bvhcache_init();
69 }
70 }
71 BVHCache *bvh_cache = *bvh_cache_p;
72
73 if (bvh_cache->items[type].is_filled) {
74 *r_tree = bvh_cache->items[type].tree;
75 return true;
76 }
77 if (do_lock) {
78 BLI_mutex_lock(&bvh_cache->mutex);
79 bool in_cache = bvhcache_find(bvh_cache_p, type, r_tree, nullptr, nullptr);
80 if (in_cache) {
81 BLI_mutex_unlock(&bvh_cache->mutex);
82 return in_cache;
83 }
84 *r_locked = true;
85 }
86 return false;
87}
88
89static void bvhcache_unlock(BVHCache *bvh_cache, bool lock_started)
90{
91 if (lock_started) {
92 BLI_mutex_unlock(&bvh_cache->mutex);
93 }
94}
95
96bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree)
97{
98 if (bvh_cache == nullptr) {
99 return false;
100 }
101
102 for (int i = 0; i < BVHTREE_MAX_ITEM; i++) {
103 if (bvh_cache->items[i].tree == tree) {
104 return true;
105 }
106 }
107 return false;
108}
109
111{
112 BVHCache *cache = MEM_cnew<BVHCache>(__func__);
113 BLI_mutex_init(&cache->mutex);
114 return cache;
115}
124static void bvhcache_insert(BVHCache *bvh_cache, BVHTree *tree, BVHCacheType type)
125{
126 BVHCacheItem *item = &bvh_cache->items[type];
127 BLI_assert(!item->is_filled);
128 item->tree = tree;
129 item->is_filled = true;
130}
131
132void bvhcache_free(BVHCache *bvh_cache)
133{
134 for (int index = 0; index < BVHTREE_MAX_ITEM; index++) {
135 BVHCacheItem *item = &bvh_cache->items[index];
136 BLI_bvhtree_free(item->tree);
137 item->tree = nullptr;
138 }
139 BLI_mutex_end(&bvh_cache->mutex);
140 MEM_freeN(bvh_cache);
141}
142
148static void bvhtree_balance_isolated(void *userdata)
149{
150 BLI_bvhtree_balance((BVHTree *)userdata);
151}
152
153static void bvhtree_balance(BVHTree *tree, const bool isolate)
154{
155 if (tree) {
156 if (isolate) {
158 }
159 else {
161 }
162 }
163}
164
167/* -------------------------------------------------------------------- */
171/* Math stuff for ray casting on mesh faces and for nearest surface */
172
174 const float /*m_dist*/,
175 const float v0[3],
176 const float v1[3],
177 const float v2[3])
178{
179 float dist;
180
181#ifdef USE_KDOPBVH_WATERTIGHT
182 if (isect_ray_tri_watertight_v3(ray->origin, ray->isect_precalc, v0, v1, v2, &dist, nullptr))
183#else
185 ray->origin, ray->direction, v0, v1, v2, &dist, nullptr, FLT_EPSILON))
186#endif
187 {
188 return dist;
189 }
190
191 return FLT_MAX;
192}
193
195 float radius,
196 const float m_dist,
197 const float v0[3],
198 const float v1[3],
199 const float v2[3])
200{
201
202 float idist;
203 float p1[3];
204 float hit_point[3];
205
206 madd_v3_v3v3fl(p1, ray->origin, ray->direction, m_dist);
207 if (isect_sweeping_sphere_tri_v3(ray->origin, p1, radius, v0, v1, v2, &idist, hit_point)) {
208 return idist * m_dist;
209 }
210
211 return FLT_MAX;
212}
213
214/*
215 * BVH from meshes callbacks
216 */
217
224static void mesh_faces_nearest_point(void *userdata,
225 int index,
226 const float co[3],
227 BVHTreeNearest *nearest)
228{
229 const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
230 const MFace *face = data->face + index;
231
232 const float *t0, *t1, *t2, *t3;
233 t0 = data->vert_positions[face->v1];
234 t1 = data->vert_positions[face->v2];
235 t2 = data->vert_positions[face->v3];
236 t3 = face->v4 ? &data->vert_positions[face->v4].x : nullptr;
237
238 do {
239 float nearest_tmp[3], dist_sq;
240
241 closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
242 dist_sq = len_squared_v3v3(co, nearest_tmp);
243
244 if (dist_sq < nearest->dist_sq) {
245 nearest->index = index;
246 nearest->dist_sq = dist_sq;
247 copy_v3_v3(nearest->co, nearest_tmp);
248 normal_tri_v3(nearest->no, t0, t1, t2);
249 }
250
251 t1 = t2;
252 t2 = t3;
253 t3 = nullptr;
254
255 } while (t2);
256}
257/* copy of function above */
258static void mesh_corner_tris_nearest_point(void *userdata,
259 int index,
260 const float co[3],
261 BVHTreeNearest *nearest)
262{
263 const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
264 const int3 &tri = data->corner_tris[index];
265 const float *vtri_co[3] = {
266 data->vert_positions[data->corner_verts[tri[0]]],
267 data->vert_positions[data->corner_verts[tri[1]]],
268 data->vert_positions[data->corner_verts[tri[2]]],
269 };
270 float nearest_tmp[3], dist_sq;
271
272 closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(vtri_co));
273 dist_sq = len_squared_v3v3(co, nearest_tmp);
274
275 if (dist_sq < nearest->dist_sq) {
276 nearest->index = index;
277 nearest->dist_sq = dist_sq;
278 copy_v3_v3(nearest->co, nearest_tmp);
279 normal_tri_v3(nearest->no, UNPACK3(vtri_co));
280 }
281}
282
289static void mesh_faces_spherecast(void *userdata,
290 int index,
291 const BVHTreeRay *ray,
292 BVHTreeRayHit *hit)
293{
294 const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
295 const MFace *face = &data->face[index];
296
297 const float *t0, *t1, *t2, *t3;
298 t0 = data->vert_positions[face->v1];
299 t1 = data->vert_positions[face->v2];
300 t2 = data->vert_positions[face->v3];
301 t3 = face->v4 ? &data->vert_positions[face->v4].x : nullptr;
302
303 do {
304 float dist;
305 if (ray->radius == 0.0f) {
306 dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
307 }
308 else {
309 dist = bvhtree_sphereray_tri_intersection(ray, ray->radius, hit->dist, t0, t1, t2);
310 }
311
312 if (dist >= 0 && dist < hit->dist) {
313 hit->index = index;
314 hit->dist = dist;
315 madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
316
317 normal_tri_v3(hit->no, t0, t1, t2);
318 }
319
320 t1 = t2;
321 t2 = t3;
322 t3 = nullptr;
323
324 } while (t2);
325}
326/* copy of function above */
327static void mesh_corner_tris_spherecast(void *userdata,
328 int index,
329 const BVHTreeRay *ray,
330 BVHTreeRayHit *hit)
331{
332 const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
333 const Span<float3> positions = data->vert_positions;
334 const int3 &tri = data->corner_tris[index];
335 const float *vtri_co[3] = {
336 positions[data->corner_verts[tri[0]]],
337 positions[data->corner_verts[tri[1]]],
338 positions[data->corner_verts[tri[2]]],
339 };
340 float dist;
341
342 if (ray->radius == 0.0f) {
343 dist = bvhtree_ray_tri_intersection(ray, hit->dist, UNPACK3(vtri_co));
344 }
345 else {
346 dist = bvhtree_sphereray_tri_intersection(ray, ray->radius, hit->dist, UNPACK3(vtri_co));
347 }
348
349 if (dist >= 0 && dist < hit->dist) {
350 hit->index = index;
351 hit->dist = dist;
352 madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
353
354 normal_tri_v3(hit->no, UNPACK3(vtri_co));
355 }
356}
357
364static void mesh_edges_nearest_point(void *userdata,
365 int index,
366 const float co[3],
367 BVHTreeNearest *nearest)
368{
369 const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
370 const Span<float3> positions = data->vert_positions;
371 const blender::int2 edge = data->edges[index];
372 float nearest_tmp[3], dist_sq;
373
374 const float *t0, *t1;
375 t0 = positions[edge[0]];
376 t1 = positions[edge[1]];
377
378 closest_to_line_segment_v3(nearest_tmp, co, t0, t1);
379 dist_sq = len_squared_v3v3(nearest_tmp, co);
380
381 if (dist_sq < nearest->dist_sq) {
382 nearest->index = index;
383 nearest->dist_sq = dist_sq;
384 copy_v3_v3(nearest->co, nearest_tmp);
385 sub_v3_v3v3(nearest->no, t0, t1);
386 normalize_v3(nearest->no);
387 }
388}
389
390/* Helper, does all the point-sphere-cast work actually. */
391static void mesh_verts_spherecast_do(int index,
392 const float v[3],
393 const BVHTreeRay *ray,
394 BVHTreeRayHit *hit)
395{
396 float dist;
397 const float *r1;
398 float r2[3], i1[3];
399 r1 = ray->origin;
400 add_v3_v3v3(r2, r1, ray->direction);
401
402 closest_to_line_segment_v3(i1, v, r1, r2);
403
404 /* No hit if closest point is 'behind' the origin of the ray, or too far away from it. */
405 if ((dot_v3v3v3(r1, i1, r2) >= 0.0f) && ((dist = len_v3v3(r1, i1)) < hit->dist)) {
406 hit->index = index;
407 hit->dist = dist;
408 copy_v3_v3(hit->co, i1);
409 }
410}
411
418static void mesh_verts_spherecast(void *userdata,
419 int index,
420 const BVHTreeRay *ray,
421 BVHTreeRayHit *hit)
422{
423 const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
424 const float *v = data->vert_positions[index];
425
426 mesh_verts_spherecast_do(index, v, ray, hit);
427}
428
435static void mesh_edges_spherecast(void *userdata,
436 int index,
437 const BVHTreeRay *ray,
438 BVHTreeRayHit *hit)
439{
440 const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
441 const Span<float3> positions = data->vert_positions;
442 const blender::int2 edge = data->edges[index];
443
444 const float radius_sq = square_f(ray->radius);
445 float dist;
446 const float *v1, *v2, *r1;
447 float r2[3], i1[3], i2[3];
448 v1 = positions[edge[0]];
449 v2 = positions[edge[1]];
450
451 /* In case we get a zero-length edge, handle it as a point! */
452 if (equals_v3v3(v1, v2)) {
453 mesh_verts_spherecast_do(index, v1, ray, hit);
454 return;
455 }
456
457 r1 = ray->origin;
458 add_v3_v3v3(r2, r1, ray->direction);
459
460 if (isect_line_line_v3(v1, v2, r1, r2, i1, i2)) {
461 /* No hit if intersection point is 'behind' the origin of the ray, or too far away from it. */
462 if ((dot_v3v3v3(r1, i2, r2) >= 0.0f) && ((dist = len_v3v3(r1, i2)) < hit->dist)) {
463 const float e_fac = line_point_factor_v3(i1, v1, v2);
464 if (e_fac < 0.0f) {
465 copy_v3_v3(i1, v1);
466 }
467 else if (e_fac > 1.0f) {
468 copy_v3_v3(i1, v2);
469 }
470 /* Ensure ray is really close enough from edge! */
471 if (len_squared_v3v3(i1, i2) <= radius_sq) {
472 hit->index = index;
473 hit->dist = dist;
474 copy_v3_v3(hit->co, i2);
475 }
476 }
477 }
478}
479
482/*
483 * BVH builders
484 */
485
486/* -------------------------------------------------------------------- */
491 const BVHCacheType bvh_cache_type,
492 const Span<float3> positions,
493 const Span<blender::int2> edges,
494 const Span<int> corner_verts,
495 const Span<int3> corner_tris,
496 const MFace *face,
497 BVHTreeFromMesh *r_data)
498{
499 *r_data = {};
500
501 r_data->tree = tree;
502
503 r_data->vert_positions = positions;
504 r_data->edges = edges;
505 r_data->face = face;
506 r_data->corner_verts = corner_verts;
507 r_data->corner_tris = corner_tris;
508
509 switch (bvh_cache_type) {
513 /* a nullptr nearest callback works fine
514 * remember the min distance to point is the same as the min distance to BV of point */
515 r_data->nearest_callback = nullptr;
517 break;
523 break;
527 break;
532 break;
533 case BVHTREE_MAX_ITEM:
534 BLI_assert(false);
535 break;
536 }
537}
538
540 float epsilon, int tree_type, int axis, int elems_num, int &elems_num_active)
541{
542 if (elems_num_active != -1) {
543 BLI_assert(IN_RANGE_INCL(elems_num_active, 0, elems_num));
544 }
545 else {
546 elems_num_active = elems_num;
547 }
548
549 if (elems_num_active == 0) {
550 return nullptr;
551 }
552
553 return BLI_bvhtree_new(elems_num_active, epsilon, tree_type, axis);
554}
555
558/* -------------------------------------------------------------------- */
563 int tree_type,
564 int axis,
565 const Span<float3> positions,
566 const BitSpan verts_mask,
567 int verts_num_active)
568{
569 BVHTree *tree = bvhtree_new_common(epsilon, tree_type, axis, positions.size(), verts_num_active);
570 if (!tree) {
571 return nullptr;
572 }
573
574 for (const int i : positions.index_range()) {
575 if (!verts_mask.is_empty() && !verts_mask[i]) {
576 continue;
577 }
578 BLI_bvhtree_insert(tree, i, positions[i], 1);
579 }
580 BLI_assert(BLI_bvhtree_get_len(tree) == verts_num_active);
581
582 return tree;
583}
584
586 const Span<float3> vert_positions,
587 const BitSpan verts_mask,
588 int verts_num_active,
589 float epsilon,
590 int tree_type,
591 int axis)
592{
594 epsilon, tree_type, axis, vert_positions, verts_mask, verts_num_active);
595
596 bvhtree_balance(tree, false);
597
598 if (data) {
599 /* Setup BVHTreeFromMesh */
600 bvhtree_from_mesh_setup_data(tree, BVHTREE_FROM_VERTS, vert_positions, {}, {}, {}, {}, data);
601 }
602
603 return tree;
604}
605
608/* -------------------------------------------------------------------- */
614 const BitSpan edges_mask,
615 int edges_num_active,
616 float epsilon,
617 int tree_type,
618 int axis)
619{
620 BVHTree *tree = bvhtree_new_common(epsilon, tree_type, axis, edges.size(), edges_num_active);
621 if (!tree) {
622 return nullptr;
623 }
624
625 for (const int i : edges.index_range()) {
626 if (!edges_mask.is_empty() && !edges_mask[i]) {
627 continue;
628 }
629 float co[2][3];
630 copy_v3_v3(co[0], positions[edges[i][0]]);
631 copy_v3_v3(co[1], positions[edges[i][1]]);
632
633 BLI_bvhtree_insert(tree, i, co[0], 2);
634 }
635
636 return tree;
637}
638
640 const Span<float3> vert_positions,
641 const Span<blender::int2> edges,
642 const BitSpan edges_mask,
643 int edges_num_active,
644 float epsilon,
645 int tree_type,
646 int axis)
647{
649 vert_positions, edges, edges_mask, edges_num_active, epsilon, tree_type, axis);
650
651 bvhtree_balance(tree, false);
652
653 if (data) {
654 /* Setup BVHTreeFromMesh */
656 tree, BVHTREE_FROM_EDGES, vert_positions, edges, {}, {}, {}, data);
657 }
658
659 return tree;
660}
661
664/* -------------------------------------------------------------------- */
669 int tree_type,
670 int axis,
671 const Span<float3> positions,
672 const MFace *face,
673 const int faces_num,
674 const BitSpan faces_mask,
675 int faces_num_active)
676{
677 BVHTree *tree = bvhtree_new_common(epsilon, tree_type, axis, faces_num, faces_num_active);
678 if (!tree) {
679 return nullptr;
680 }
681
682 if (!positions.is_empty() && face) {
683 for (int i = 0; i < faces_num; i++) {
684 float co[4][3];
685 if (!faces_mask.is_empty() && !faces_mask[i]) {
686 continue;
687 }
688
689 copy_v3_v3(co[0], positions[face[i].v1]);
690 copy_v3_v3(co[1], positions[face[i].v2]);
691 copy_v3_v3(co[2], positions[face[i].v3]);
692 if (face[i].v4) {
693 copy_v3_v3(co[3], positions[face[i].v4]);
694 }
695
696 BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
697 }
698 }
699 BLI_assert(BLI_bvhtree_get_len(tree) == faces_num_active);
700
701 return tree;
702}
703
706/* -------------------------------------------------------------------- */
711 int tree_type,
712 int axis,
713 const Span<float3> positions,
714 const Span<int> corner_verts,
715 const Span<int3> corner_tris,
716 const BitSpan corner_tris_mask,
717 int corner_tris_num_active)
718{
719 if (positions.is_empty()) {
720 return nullptr;
721 }
722
724 epsilon, tree_type, axis, corner_tris.size(), corner_tris_num_active);
725
726 if (!tree) {
727 return nullptr;
728 }
729
730 for (const int i : corner_tris.index_range()) {
731 float co[3][3];
732 if (!corner_tris_mask.is_empty() && !corner_tris_mask[i]) {
733 continue;
734 }
735
736 copy_v3_v3(co[0], positions[corner_verts[corner_tris[i][0]]]);
737 copy_v3_v3(co[1], positions[corner_verts[corner_tris[i][1]]]);
738 copy_v3_v3(co[2], positions[corner_verts[corner_tris[i][2]]]);
739
740 BLI_bvhtree_insert(tree, i, co[0], 3);
741 }
742
743 BLI_assert(BLI_bvhtree_get_len(tree) == corner_tris_num_active);
744
745 return tree;
746}
747
749 const Span<float3> vert_positions,
750 const Span<int> corner_verts,
751 const Span<int3> corner_tris,
752 const BitSpan corner_tris_mask,
753 int corner_tris_num_active,
754 float epsilon,
755 int tree_type,
756 int axis)
757{
759 tree_type,
760 axis,
761 vert_positions,
762 corner_verts,
763 corner_tris,
764 corner_tris_mask,
765 corner_tris_num_active);
766
767 bvhtree_balance(tree, false);
768
769 if (data) {
770 /* Setup BVHTreeFromMesh */
773 vert_positions,
774 {},
775 corner_verts,
776 corner_tris,
777 nullptr,
778 data);
779 }
780
781 return tree;
782}
783
784static BitVector<> loose_verts_no_hidden_mask_get(const Mesh &mesh, int *r_elem_active_len)
785{
786 using namespace blender;
787 using namespace blender::bke;
788
789 int count = mesh.verts_num;
790 BitVector<> verts_mask(count, true);
791
792 const AttributeAccessor attributes = mesh.attributes();
793 const Span<int2> edges = mesh.edges();
794 const VArray<bool> hide_edge = *attributes.lookup_or_default(
795 ".hide_edge", AttrDomain::Edge, false);
796 const VArray<bool> hide_vert = *attributes.lookup_or_default(
797 ".hide_vert", AttrDomain::Point, false);
798
799 for (const int i : edges.index_range()) {
800 if (hide_edge[i]) {
801 continue;
802 }
803 for (const int vert : {edges[i][0], edges[i][1]}) {
804 if (verts_mask[vert]) {
805 verts_mask[vert].reset();
806 count--;
807 }
808 }
809 }
810
811 if (count) {
812 for (const int vert : verts_mask.index_range()) {
813 if (verts_mask[vert] && hide_vert[vert]) {
814 verts_mask[vert].reset();
815 count--;
816 }
817 }
818 }
819
820 *r_elem_active_len = count;
821
822 return verts_mask;
823}
824
825static BitVector<> loose_edges_no_hidden_mask_get(const Mesh &mesh, int *r_elem_active_len)
826{
827 using namespace blender;
828 using namespace blender::bke;
829
830 int count = mesh.edges_num;
831 BitVector<> edge_mask(count, true);
832
833 const AttributeAccessor attributes = mesh.attributes();
834 const OffsetIndices faces = mesh.faces();
835 const Span<int> corner_edges = mesh.corner_edges();
836 const VArray<bool> hide_poly = *attributes.lookup_or_default(
837 ".hide_poly", AttrDomain::Face, false);
838 const VArray<bool> hide_edge = *attributes.lookup_or_default(
839 ".hide_edge", AttrDomain::Edge, false);
840
841 for (const int i : faces.index_range()) {
842 if (hide_poly[i]) {
843 continue;
844 }
845 for (const int edge : corner_edges.slice(faces[i])) {
846 if (edge_mask[edge]) {
847 edge_mask[edge].reset();
848 count--;
849 }
850 }
851 }
852
853 if (count) {
854 for (const int edge : edge_mask.index_range()) {
855 if (edge_mask[edge] && hide_edge[edge]) {
856 edge_mask[edge].reset();
857 count--;
858 }
859 }
860 }
861
862 *r_elem_active_len = count;
863
864 return edge_mask;
865}
866
868 const VArray<bool> &hide_poly,
869 const int corner_tris_len,
870 int *r_corner_tris_active_len)
871{
872 if (hide_poly.is_single() && !hide_poly.get_internal_single()) {
873 return {};
874 }
875 BitVector<> corner_tris_mask(corner_tris_len);
876
877 int corner_tris_no_hidden_len = 0;
878 int tri_index = 0;
879 for (const int64_t i : faces.index_range()) {
880 const int triangles_num = blender::bke::mesh::face_triangles_num(faces[i].size());
881 if (hide_poly[i]) {
882 tri_index += triangles_num;
883 }
884 else {
885 for (const int i : IndexRange(triangles_num)) {
886 UNUSED_VARS(i);
887 corner_tris_mask[tri_index].set();
888 tri_index++;
889 corner_tris_no_hidden_len++;
890 }
891 }
892 }
893
894 *r_corner_tris_active_len = corner_tris_no_hidden_len;
895
896 return corner_tris_mask;
897}
898
900 const Mesh *mesh,
901 const BVHCacheType bvh_cache_type,
902 const int tree_type)
903{
904 using namespace blender;
905 using namespace blender::bke;
906 BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime->bvh_cache;
907
908 Span<int3> corner_tris;
910 corner_tris = mesh->corner_tris();
911 }
912
913 const Span<float3> positions = mesh->vert_positions();
914 const Span<int2> edges = mesh->edges();
915 const Span<int> corner_verts = mesh->corner_verts();
916
917 /* Setup BVHTreeFromMesh */
919 bvh_cache_type,
920 positions,
921 edges,
922 corner_verts,
923 corner_tris,
924 (const MFace *)CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE),
925 data);
926
927 bool lock_started = false;
928 data->cached = bvhcache_find(
929 bvh_cache_p, bvh_cache_type, &data->tree, &lock_started, &mesh->runtime->eval_mutex);
930
931 if (data->cached) {
932 BLI_assert(lock_started == false);
933
934 /* NOTE: #data->tree can be nullptr. */
935 return data->tree;
936 }
937
938 /* Create BVHTree. */
939
940 switch (bvh_cache_type) {
942 const LooseVertCache &loose_verts = mesh->loose_verts();
944 0.0f, tree_type, 6, positions, loose_verts.is_loose_bits, loose_verts.count);
945 break;
946 }
948 int mask_bits_act_len = -1;
949 const BitVector<> mask = loose_verts_no_hidden_mask_get(*mesh, &mask_bits_act_len);
951 0.0f, tree_type, 6, positions, mask, mask_bits_act_len);
952 break;
953 }
954 case BVHTREE_FROM_VERTS: {
955 data->tree = bvhtree_from_mesh_verts_create_tree(0.0f, tree_type, 6, positions, {}, -1);
956 break;
957 }
959 const LooseEdgeCache &loose_edges = mesh->loose_edges();
961 positions, edges, loose_edges.is_loose_bits, loose_edges.count, 0.0f, tree_type, 6);
962 break;
963 }
965 int mask_bits_act_len = -1;
966 const BitVector<> mask = loose_edges_no_hidden_mask_get(*mesh, &mask_bits_act_len);
968 positions, edges, mask, mask_bits_act_len, 0.0f, tree_type, 6);
969 break;
970 }
971 case BVHTREE_FROM_EDGES: {
973 positions, edges, {}, -1, 0.0f, tree_type, 6);
974 break;
975 }
976 case BVHTREE_FROM_FACES: {
977 BLI_assert(!(mesh->totface_legacy == 0 && mesh->faces_num != 0));
979 0.0f,
980 tree_type,
981 6,
982 positions,
983 (const MFace *)CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE),
984 mesh->totface_legacy,
985 {},
986 -1);
987 break;
988 }
990 AttributeAccessor attributes = mesh->attributes();
991 int mask_bits_act_len = -1;
992 const BitVector<> mask = corner_tris_no_hidden_map_get(
993 mesh->faces(),
994 *attributes.lookup_or_default(".hide_poly", AttrDomain::Face, false),
995 corner_tris.size(),
996 &mask_bits_act_len);
998 0.0f, tree_type, 6, positions, corner_verts, corner_tris, mask, mask_bits_act_len);
999 break;
1000 }
1003 0.0f, tree_type, 6, positions, corner_verts, corner_tris, {}, -1);
1004 break;
1005 }
1006 case BVHTREE_MAX_ITEM:
1008 break;
1009 }
1010
1011 bvhtree_balance(data->tree, lock_started);
1012
1013 /* Save on cache for later use */
1014 // printf("BVHTree built and saved on cache\n");
1015 BLI_assert(data->cached == false);
1016 data->cached = true;
1017 bvhcache_insert(*bvh_cache_p, data->tree, bvh_cache_type);
1018 bvhcache_unlock(*bvh_cache_p, lock_started);
1019
1020#ifndef NDEBUG
1021 if (data->tree != nullptr) {
1022 if (BLI_bvhtree_get_tree_type(data->tree) != tree_type) {
1023 printf("tree_type %d obtained instead of %d\n",
1024 BLI_bvhtree_get_tree_type(data->tree),
1025 tree_type);
1026 }
1027 }
1028#endif
1029
1030 return data->tree;
1031}
1032
1034 const blender::IndexMask &faces_mask,
1035 BVHTreeFromMesh &r_data)
1036{
1037 using namespace blender;
1038 using namespace blender::bke;
1039
1040 if (faces_mask.size() == mesh.faces_num) {
1041 /* Can use cache if all faces are in the bvh tree. */
1043 return;
1044 }
1045
1046 const Span<float3> positions = mesh.vert_positions();
1047 const Span<int2> edges = mesh.edges();
1048 const Span<int> corner_verts = mesh.corner_verts();
1049 const OffsetIndices faces = mesh.faces();
1050 const Span<int3> corner_tris = mesh.corner_tris();
1053 positions,
1054 edges,
1055 corner_verts,
1056 corner_tris,
1057 nullptr,
1058 &r_data);
1059
1060 int tris_num = 0;
1061 faces_mask.foreach_index(
1062 [&](const int i) { tris_num += mesh::face_triangles_num(faces[i].size()); });
1063
1064 int active_num = -1;
1065 BVHTree *tree = bvhtree_new_common(0.0f, 2, 6, tris_num, active_num);
1066 r_data.tree = tree;
1067 if (tree == nullptr) {
1068 return;
1069 }
1070
1071 faces_mask.foreach_index([&](const int face_i) {
1072 const IndexRange triangles_range = mesh::face_triangles_range(faces, face_i);
1073 for (const int tri_i : triangles_range) {
1074 float co[3][3];
1075 copy_v3_v3(co[0], positions[corner_verts[corner_tris[tri_i][0]]]);
1076 copy_v3_v3(co[1], positions[corner_verts[corner_tris[tri_i][1]]]);
1077 copy_v3_v3(co[2], positions[corner_verts[corner_tris[tri_i][2]]]);
1078
1079 BLI_bvhtree_insert(tree, tri_i, co[0], 3);
1080 }
1081 });
1082
1084}
1085
1087 const blender::IndexMask &edges_mask,
1088 BVHTreeFromMesh &r_data)
1089{
1090 using namespace blender;
1091 using namespace blender::bke;
1092
1093 if (edges_mask.size() == mesh.edges_num) {
1094 /* Can use cache if all edges are in the bvh tree. */
1096 return;
1097 }
1098
1099 const Span<float3> positions = mesh.vert_positions();
1100 const Span<int2> edges = mesh.edges();
1102 nullptr, BVHTREE_FROM_EDGES, positions, edges, {}, {}, nullptr, &r_data);
1103
1104 int active_num = -1;
1105 BVHTree *tree = bvhtree_new_common(0.0f, 2, 6, edges_mask.size(), active_num);
1106 r_data.tree = tree;
1107 if (tree == nullptr) {
1108 return;
1109 }
1110
1111 edges_mask.foreach_index([&](const int edge_i) {
1112 const int2 &edge = edges[edge_i];
1113 float co[2][3];
1114 copy_v3_v3(co[0], positions[edge[0]]);
1115 copy_v3_v3(co[1], positions[edge[1]]);
1116 BLI_bvhtree_insert(tree, edge_i, co[0], 2);
1117 });
1118
1120}
1121
1123 const blender::IndexMask &verts_mask,
1124 BVHTreeFromMesh &r_data)
1125{
1126 using namespace blender;
1127 using namespace blender::bke;
1128
1129 if (verts_mask.size() == mesh.verts_num) {
1130 /* Can use cache if all vertices are in the bvh tree. */
1132 return;
1133 }
1134
1135 const Span<float3> positions = mesh.vert_positions();
1137 nullptr, BVHTREE_FROM_VERTS, positions, {}, {}, {}, nullptr, &r_data);
1138
1139 int active_num = -1;
1140 BVHTree *tree = bvhtree_new_common(0.0f, 2, 6, verts_mask.size(), active_num);
1141 r_data.tree = tree;
1142 if (tree == nullptr) {
1143 return;
1144 }
1145
1146 verts_mask.foreach_index([&](const int vert_i) {
1147 const float3 &position = positions[vert_i];
1148 BLI_bvhtree_insert(tree, vert_i, position, 1);
1149 });
1150
1152}
1153
1156/* -------------------------------------------------------------------- */
1161{
1162 if (data->tree && !data->cached) {
1163 BLI_bvhtree_free(data->tree);
1164 }
1165
1166 *data = {};
1167}
1168
1171/* -------------------------------------------------------------------- */
1176 const blender::IndexMask &points_mask,
1177 BVHTreeFromPointCloud &r_data)
1178{
1179 int active_num = -1;
1180 BVHTree *tree = bvhtree_new_common(0.0f, 2, 6, points_mask.size(), active_num);
1181 r_data.tree = tree;
1182 if (!tree) {
1183 return;
1184 }
1185
1186 const Span<float3> positions = pointcloud.positions();
1187 points_mask.foreach_index([&](const int i) { BLI_bvhtree_insert(tree, i, positions[i], 1); });
1188
1190
1191 r_data.coords = (const float(*)[3])positions.data();
1192 r_data.tree = tree;
1193 r_data.nearest_callback = nullptr;
1194}
1195
1197{
1198 if (data->tree) {
1199 BLI_bvhtree_free(data->tree);
1200 }
1201 memset(data, 0, sizeof(*data));
1202}
1203
BVHCacheType
@ BVHTREE_FROM_CORNER_TRIS
@ BVHTREE_FROM_EDGES
@ BVHTREE_FROM_CORNER_TRIS_NO_HIDDEN
@ BVHTREE_FROM_FACES
@ BVHTREE_FROM_LOOSEEDGES
@ BVHTREE_FROM_LOOSEVERTS
@ BVHTREE_FROM_LOOSEEDGES_NO_HIDDEN
@ BVHTREE_FROM_LOOSEVERTS_NO_HIDDEN
@ BVHTREE_MAX_ITEM
@ BVHTREE_FROM_VERTS
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
int BLI_bvhtree_get_tree_type(const BVHTree *tree)
void BLI_bvhtree_balance(BVHTree *tree)
void BLI_bvhtree_free(BVHTree *tree)
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
int BLI_bvhtree_get_len(const BVHTree *tree)
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])
float closest_to_line_segment_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3])
Definition math_geom.cc:385
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])
bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], float radius, const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float ipoint[3])
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_lambda, float r_uv[2])
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition math_geom.cc:39
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], float epsilon)
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE bool equals_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
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 void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE float normalize_v3(float n[3])
void BLI_task_isolate(void(*func)(void *userdata), void *userdata)
void BLI_mutex_end(ThreadMutex *mutex)
Definition threads.cc:360
void BLI_mutex_init(ThreadMutex *mutex)
Definition threads.cc:340
void BLI_mutex_lock(ThreadMutex *mutex)
Definition threads.cc:345
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition threads.cc:350
pthread_mutex_t ThreadMutex
Definition BLI_threads.h:83
#define UNUSED_VARS(...)
#define UNPACK3(a)
#define ELEM(...)
#define IN_RANGE_INCL(a, b, c)
volatile int lock
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree)
Definition bvhutils.cc:96
static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition bvhutils.cc:289
void free_bvhtree_from_mesh(BVHTreeFromMesh *data)
Definition bvhutils.cc:1160
static BVHTree * bvhtree_from_mesh_faces_create_tree(float epsilon, int tree_type, int axis, const Span< float3 > positions, const MFace *face, const int faces_num, const BitSpan faces_mask, int faces_num_active)
Definition bvhutils.cc:668
static BVHTree * bvhtree_from_mesh_corner_tris_create_tree(float epsilon, int tree_type, int axis, const Span< float3 > positions, const Span< int > corner_verts, const Span< int3 > corner_tris, const BitSpan corner_tris_mask, int corner_tris_num_active)
Definition bvhutils.cc:710
BVHCache * bvhcache_init()
Definition bvhutils.cc:110
static BitVector corner_tris_no_hidden_map_get(const blender::OffsetIndices< int > faces, const VArray< bool > &hide_poly, const int corner_tris_len, int *r_corner_tris_active_len)
Definition bvhutils.cc:867
void BKE_bvhtree_from_pointcloud_get(const PointCloud &pointcloud, const blender::IndexMask &points_mask, BVHTreeFromPointCloud &r_data)
Definition bvhutils.cc:1175
void free_bvhtree_from_pointcloud(BVHTreeFromPointCloud *data)
Definition bvhutils.cc:1196
static BVHTree * bvhtree_from_mesh_verts_create_tree(float epsilon, int tree_type, int axis, const Span< float3 > positions, const BitSpan verts_mask, int verts_num_active)
Definition bvhutils.cc:562
static void mesh_corner_tris_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
Definition bvhutils.cc:258
static void mesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
Definition bvhutils.cc:224
static void bvhtree_balance_isolated(void *userdata)
Definition bvhutils.cc:148
static void bvhcache_insert(BVHCache *bvh_cache, BVHTree *tree, BVHCacheType type)
Definition bvhutils.cc:124
static void mesh_verts_spherecast_do(int index, const float v[3], const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition bvhutils.cc:391
BVHTree * bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data, const Span< float3 > vert_positions, const Span< blender::int2 > edges, const BitSpan edges_mask, int edges_num_active, float epsilon, int tree_type, int axis)
Definition bvhutils.cc:639
static void bvhtree_balance(BVHTree *tree, const bool isolate)
Definition bvhutils.cc:153
static void mesh_corner_tris_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition bvhutils.cc:327
static BVHTree * bvhtree_from_mesh_edges_create_tree(const Span< float3 > positions, const blender::Span< blender::int2 > edges, const BitSpan edges_mask, int edges_num_active, float epsilon, int tree_type, int axis)
Definition bvhutils.cc:612
float bvhtree_ray_tri_intersection(const BVHTreeRay *ray, const float, const float v0[3], const float v1[3], const float v2[3])
Definition bvhutils.cc:173
static BitVector loose_verts_no_hidden_mask_get(const Mesh &mesh, int *r_elem_active_len)
Definition bvhutils.cc:784
static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition bvhutils.cc:435
void BKE_bvhtree_from_mesh_verts_init(const Mesh &mesh, const blender::IndexMask &verts_mask, BVHTreeFromMesh &r_data)
Definition bvhutils.cc:1122
static bool bvhcache_find(BVHCache **bvh_cache_p, BVHCacheType type, BVHTree **r_tree, bool *r_locked, std::mutex *mesh_eval_mutex)
Definition bvhutils.cc:50
static BitVector loose_edges_no_hidden_mask_get(const Mesh &mesh, int *r_elem_active_len)
Definition bvhutils.cc:825
BVHTree * BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data, const Mesh *mesh, const BVHCacheType bvh_cache_type, const int tree_type)
Definition bvhutils.cc:899
static BVHTree * bvhtree_new_common(float epsilon, int tree_type, int axis, int elems_num, int &elems_num_active)
Definition bvhutils.cc:539
BVHTree * bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data, const Span< float3 > vert_positions, const BitSpan verts_mask, int verts_num_active, float epsilon, int tree_type, int axis)
Definition bvhutils.cc:585
static void bvhcache_unlock(BVHCache *bvh_cache, bool lock_started)
Definition bvhutils.cc:89
BVHTree * bvhtree_from_mesh_corner_tris_ex(BVHTreeFromMesh *data, const Span< float3 > vert_positions, const Span< int > corner_verts, const Span< int3 > corner_tris, const BitSpan corner_tris_mask, int corner_tris_num_active, float epsilon, int tree_type, int axis)
Definition bvhutils.cc:748
static void mesh_edges_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
Definition bvhutils.cc:364
void BKE_bvhtree_from_mesh_edges_init(const Mesh &mesh, const blender::IndexMask &edges_mask, BVHTreeFromMesh &r_data)
Definition bvhutils.cc:1086
static void bvhtree_from_mesh_setup_data(BVHTree *tree, const BVHCacheType bvh_cache_type, const Span< float3 > positions, const Span< blender::int2 > edges, const Span< int > corner_verts, const Span< int3 > corner_tris, const MFace *face, BVHTreeFromMesh *r_data)
Definition bvhutils.cc:490
void bvhcache_free(BVHCache *bvh_cache)
Definition bvhutils.cc:132
static void mesh_verts_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition bvhutils.cc:418
void BKE_bvhtree_from_mesh_tris_init(const Mesh &mesh, const blender::IndexMask &faces_mask, BVHTreeFromMesh &r_data)
Definition bvhutils.cc:1033
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.cc:194
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:138
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
void foreach_index(Fn &&fn) const
#define printf
KDTree_3d * tree
draw_view in_light_buf[] float
int count
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
int face_triangles_num(const int face_size)
Definition BKE_mesh.hh:287
#define FLT_MAX
Definition stdcycles.h:14
__int64 int64_t
Definition stdint.h:89
bool is_filled
Definition bvhutils.cc:33
BVHTree * tree
Definition bvhutils.cc:34
ThreadMutex mutex
Definition bvhutils.cc:39
BVHCacheItem items[BVHTREE_MAX_ITEM]
Definition bvhutils.cc:38
blender::Span< blender::int3 > corner_tris
BVHTree_RayCastCallback raycast_callback
blender::Span< blender::float3 > vert_positions
blender::Span< blender::int2 > edges
blender::Span< int > corner_verts
const MFace * face
BVHTree_NearestPointCallback nearest_callback
BVHTree_NearestPointCallback nearest_callback
const float(* coords)[3]
unsigned int v4
blender::BitVector is_loose_bits