Blender V5.0
bvhutils.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
11
12#include "BLI_math_geom.h"
13
14#include "BKE_attribute.hh"
15#include "BKE_bvhutils.hh"
16#include "BKE_editmesh.hh"
17#include "BKE_mesh.hh"
18#include "BKE_pointcloud.hh"
19
20namespace blender::bke {
21
22/* -------------------------------------------------------------------- */
25
26/* Math stuff for ray casting on mesh faces and for nearest surface */
27
29 const float /*m_dist*/,
30 const float v0[3],
31 const float v1[3],
32 const float v2[3])
33{
34 float dist;
35
36#ifdef USE_KDOPBVH_WATERTIGHT
37 if (isect_ray_tri_watertight_v3(ray->origin, ray->isect_precalc, v0, v1, v2, &dist, nullptr))
38#else
40 ray->origin, ray->direction, v0, v1, v2, &dist, nullptr, FLT_EPSILON))
41#endif
42 {
43 return dist;
44 }
45
46 return FLT_MAX;
47}
48
50 float radius,
51 const float m_dist,
52 const float v0[3],
53 const float v1[3],
54 const float v2[3])
55{
56
57 float idist;
58 float p1[3];
59 float hit_point[3];
60
61 madd_v3_v3v3fl(p1, ray->origin, ray->direction, m_dist);
62 if (isect_sweeping_sphere_tri_v3(ray->origin, p1, radius, v0, v1, v2, &idist, hit_point)) {
63 return idist * m_dist;
64 }
65
66 return FLT_MAX;
67}
68
69/*
70 * BVH from meshes callbacks
71 */
72
79static void mesh_faces_nearest_point(void *userdata,
80 int index,
81 const float co[3],
82 BVHTreeNearest *nearest)
83{
84 const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
85 const MFace *face = data->face + index;
86
87 const float *t0, *t1, *t2, *t3;
88 t0 = data->vert_positions[face->v1];
89 t1 = data->vert_positions[face->v2];
90 t2 = data->vert_positions[face->v3];
91 t3 = face->v4 ? &data->vert_positions[face->v4].x : nullptr;
92
93 do {
94 float nearest_tmp[3], dist_sq;
95
96 closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
97 dist_sq = len_squared_v3v3(co, nearest_tmp);
98
99 if (dist_sq < nearest->dist_sq) {
100 nearest->index = index;
101 nearest->dist_sq = dist_sq;
102 copy_v3_v3(nearest->co, nearest_tmp);
103 normal_tri_v3(nearest->no, t0, t1, t2);
104 }
105
106 t1 = t2;
107 t2 = t3;
108 t3 = nullptr;
109
110 } while (t2);
111}
112/* copy of function above */
113static void mesh_corner_tris_nearest_point(void *userdata,
114 int index,
115 const float co[3],
116 BVHTreeNearest *nearest)
117{
118 const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
119 const int3 &tri = data->corner_tris[index];
120 const float *vtri_co[3] = {
121 data->vert_positions[data->corner_verts[tri[0]]],
122 data->vert_positions[data->corner_verts[tri[1]]],
123 data->vert_positions[data->corner_verts[tri[2]]],
124 };
125 float nearest_tmp[3], dist_sq;
126
127 closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(vtri_co));
128 dist_sq = len_squared_v3v3(co, nearest_tmp);
129
130 if (dist_sq < nearest->dist_sq) {
131 nearest->index = index;
132 nearest->dist_sq = dist_sq;
133 copy_v3_v3(nearest->co, nearest_tmp);
134 normal_tri_v3(nearest->no, UNPACK3(vtri_co));
135 }
136}
137
144static void mesh_faces_spherecast(void *userdata,
145 int index,
146 const BVHTreeRay *ray,
147 BVHTreeRayHit *hit)
148{
149 const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
150 const MFace *face = &data->face[index];
151
152 const float *t0, *t1, *t2, *t3;
153 t0 = data->vert_positions[face->v1];
154 t1 = data->vert_positions[face->v2];
155 t2 = data->vert_positions[face->v3];
156 t3 = face->v4 ? &data->vert_positions[face->v4].x : nullptr;
157
158 do {
159 float dist;
160 if (ray->radius == 0.0f) {
161 dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
162 }
163 else {
164 dist = bvhtree_sphereray_tri_intersection(ray, ray->radius, hit->dist, t0, t1, t2);
165 }
166
167 if (dist >= 0 && dist < hit->dist) {
168 hit->index = index;
169 hit->dist = dist;
170 madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
171
172 normal_tri_v3(hit->no, t0, t1, t2);
173 }
174
175 t1 = t2;
176 t2 = t3;
177 t3 = nullptr;
178
179 } while (t2);
180}
181/* copy of function above */
182static void mesh_corner_tris_spherecast(void *userdata,
183 int index,
184 const BVHTreeRay *ray,
185 BVHTreeRayHit *hit)
186{
187 const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
188 const Span<float3> positions = data->vert_positions;
189 const int3 &tri = data->corner_tris[index];
190 const float *vtri_co[3] = {
191 positions[data->corner_verts[tri[0]]],
192 positions[data->corner_verts[tri[1]]],
193 positions[data->corner_verts[tri[2]]],
194 };
195 float dist;
196
197 if (ray->radius == 0.0f) {
198 dist = bvhtree_ray_tri_intersection(ray, hit->dist, UNPACK3(vtri_co));
199 }
200 else {
201 dist = bvhtree_sphereray_tri_intersection(ray, ray->radius, hit->dist, UNPACK3(vtri_co));
202 }
203
204 if (dist >= 0 && dist < hit->dist) {
205 hit->index = index;
206 hit->dist = dist;
207 madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
208
209 normal_tri_v3(hit->no, UNPACK3(vtri_co));
210 }
211}
212
219static void mesh_edges_nearest_point(void *userdata,
220 int index,
221 const float co[3],
222 BVHTreeNearest *nearest)
223{
224 const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
225 const Span<float3> positions = data->vert_positions;
226 const int2 edge = data->edges[index];
227 float nearest_tmp[3], dist_sq;
228
229 const float *t0, *t1;
230 t0 = positions[edge[0]];
231 t1 = positions[edge[1]];
232
233 closest_to_line_segment_v3(nearest_tmp, co, t0, t1);
234 dist_sq = len_squared_v3v3(nearest_tmp, co);
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 sub_v3_v3v3(nearest->no, t0, t1);
241 normalize_v3(nearest->no);
242 }
243}
244
245/* Helper, does all the point-sphere-cast work actually. */
246static void mesh_verts_spherecast_do(int index,
247 const float v[3],
248 const BVHTreeRay *ray,
249 BVHTreeRayHit *hit)
250{
251 const float *r1;
252 float r2[3], i1[3];
253 r1 = ray->origin;
254 add_v3_v3v3(r2, r1, ray->direction);
255
256 closest_to_line_segment_v3(i1, v, r1, r2);
257
258 /* No hit if closest point is 'behind' the origin of the ray, or too far away from it. */
259 if (dot_v3v3v3(r1, i1, r2) >= 0.0f) {
260 const float dist = len_v3v3(r1, i1);
261 if (dist < hit->dist) {
262 hit->index = index;
263 hit->dist = dist;
264 copy_v3_v3(hit->co, i1);
265 }
266 }
267}
268
275static void mesh_verts_spherecast(void *userdata,
276 int index,
277 const BVHTreeRay *ray,
278 BVHTreeRayHit *hit)
279{
280 const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
281 const float *v = data->vert_positions[index];
282
283 mesh_verts_spherecast_do(index, v, ray, hit);
284}
285
292static void mesh_edges_spherecast(void *userdata,
293 int index,
294 const BVHTreeRay *ray,
295 BVHTreeRayHit *hit)
296{
297 const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
298 const Span<float3> positions = data->vert_positions;
299 const int2 edge = data->edges[index];
300
301 const float radius_sq = square_f(ray->radius);
302 const float *v1, *v2, *r1;
303 float r2[3], i1[3], i2[3];
304 v1 = positions[edge[0]];
305 v2 = positions[edge[1]];
306
307 /* In case we get a zero-length edge, handle it as a point! */
308 if (equals_v3v3(v1, v2)) {
309 mesh_verts_spherecast_do(index, v1, ray, hit);
310 return;
311 }
312
313 r1 = ray->origin;
314 add_v3_v3v3(r2, r1, ray->direction);
315
316 if (isect_line_line_v3(v1, v2, r1, r2, i1, i2)) {
317 /* No hit if intersection point is 'behind' the origin of the ray, or too far away from it. */
318 if (dot_v3v3v3(r1, i2, r2) >= 0.0f) {
319 const float dist = len_v3v3(r1, i2);
320 if (dist < hit->dist) {
321 const float e_fac = line_point_factor_v3(i1, v1, v2);
322 if (e_fac < 0.0f) {
323 copy_v3_v3(i1, v1);
324 }
325 else if (e_fac > 1.0f) {
326 copy_v3_v3(i1, v2);
327 }
328 /* Ensure ray is really close enough from edge! */
329 if (len_squared_v3v3(i1, i2) <= radius_sq) {
330 hit->index = index;
331 hit->dist = dist;
332 copy_v3_v3(hit->co, i2);
333 }
334 }
335 }
336 }
337}
338
340
341/*
342 * BVH builders
343 */
344
345/* -------------------------------------------------------------------- */
348
350{
352 data.tree = tree;
353 data.vert_positions = positions;
354 /* a nullptr nearest callback works fine
355 * remember the min distance to point is the same as the min distance to BV of point */
356 data.nearest_callback = nullptr;
357 data.raycast_callback = mesh_verts_spherecast;
358 return data;
359}
360
361static BVHTreeFromMesh create_verts_tree_data(std::unique_ptr<BVHTree, BVHTreeDeleter> tree,
362 const Span<float3> positions)
363{
365 data.owned_tree = std::move(tree);
366 return data;
367}
368
370 const Span<float3> positions,
371 const Span<int2> edges)
372{
374 data.tree = tree;
375 data.vert_positions = positions;
376 data.edges = edges;
377 data.nearest_callback = mesh_edges_nearest_point;
378 data.raycast_callback = mesh_edges_spherecast;
379 return data;
380}
381
382static BVHTreeFromMesh create_edges_tree_data(std::unique_ptr<BVHTree, BVHTreeDeleter> tree,
383 const Span<float3> positions,
384 const Span<int2> edges)
385{
386 BVHTreeFromMesh data = create_edges_tree_data(tree.get(), positions, edges);
387 data.owned_tree = std::move(tree);
388 return data;
389}
390
392 const Span<float3> positions,
393 const MFace *face)
394{
396 data.tree = tree;
397 data.vert_positions = positions;
398 data.face = face;
399 data.nearest_callback = mesh_faces_nearest_point;
400 data.raycast_callback = mesh_faces_spherecast;
401 return data;
402}
403
405 const Span<float3> positions,
406 const Span<int> corner_verts,
407 const Span<int3> corner_tris)
408{
410 data.tree = tree;
411 data.vert_positions = positions;
412 data.corner_verts = corner_verts;
413 data.corner_tris = corner_tris;
414 data.nearest_callback = mesh_corner_tris_nearest_point;
415 data.raycast_callback = mesh_corner_tris_spherecast;
416 return data;
417}
418
419static BVHTreeFromMesh create_tris_tree_data(std::unique_ptr<BVHTree, BVHTreeDeleter> tree,
420 const Span<float3> positions,
421 const Span<int> corner_verts,
422 const Span<int3> corner_tris)
423{
424 BVHTreeFromMesh data = create_tris_tree_data(tree.get(), positions, corner_verts, corner_tris);
425 data.owned_tree = std::move(tree);
426 return data;
427}
428
429static std::unique_ptr<BVHTree, BVHTreeDeleter> bvhtree_new_common(int elems_num)
430{
431 if (elems_num == 0) {
432 return nullptr;
433 }
434 return std::unique_ptr<BVHTree, BVHTreeDeleter>(BLI_bvhtree_new(elems_num, 0.0f, 2, 6));
435}
436
437static std::unique_ptr<BVHTree, BVHTreeDeleter> create_tree_from_verts(
438 const Span<float3> positions, const IndexMask &verts_mask)
439{
440 std::unique_ptr<BVHTree, BVHTreeDeleter> tree = bvhtree_new_common(verts_mask.size());
441 if (!tree) {
442 return nullptr;
443 }
444 verts_mask.foreach_index(
445 [&](const int i) { BLI_bvhtree_insert(tree.get(), i, positions[i], 1); });
447 return tree;
448}
449
451 const IndexMask &verts_mask)
452{
453 return create_verts_tree_data(create_tree_from_verts(vert_positions, verts_mask),
454 vert_positions);
455}
456
457static std::unique_ptr<BVHTree, BVHTreeDeleter> create_tree_from_edges(
458 const Span<float3> positions, const Span<int2> edges, const IndexMask &edges_mask)
459{
460 std::unique_ptr<BVHTree, BVHTreeDeleter> tree = bvhtree_new_common(edges_mask.size());
461 if (!tree) {
462 return nullptr;
463 }
464 edges_mask.foreach_index([&](const int edge_i) {
465 const int2 &edge = edges[edge_i];
466 float co[2][3];
467 copy_v3_v3(co[0], positions[edge[0]]);
468 copy_v3_v3(co[1], positions[edge[1]]);
469 BLI_bvhtree_insert(tree.get(), edge_i, co[0], 2);
470 });
472 return tree;
473}
474
476 const Span<int2> edges,
477 const IndexMask &edges_mask)
478{
480 create_tree_from_edges(vert_positions, edges, edges_mask), vert_positions, edges);
481}
482
483static std::unique_ptr<BVHTree, BVHTreeDeleter> create_tree_from_legacy_faces(
484 const Span<float3> positions, const Span<MFace> faces)
485{
486 std::unique_ptr<BVHTree, BVHTreeDeleter> tree = bvhtree_new_common(faces.size());
487 if (!tree) {
488 return nullptr;
489 }
490 for (const int i : faces.index_range()) {
491 float co[4][3];
492 copy_v3_v3(co[0], positions[faces[i].v1]);
493 copy_v3_v3(co[1], positions[faces[i].v2]);
494 copy_v3_v3(co[2], positions[faces[i].v3]);
495 if (faces[i].v4) {
496 copy_v3_v3(co[3], positions[faces[i].v4]);
497 }
498 BLI_bvhtree_insert(tree.get(), i, co[0], faces[i].v4 ? 4 : 3);
499 }
501 return tree;
502}
503
504static std::unique_ptr<BVHTree, BVHTreeDeleter> create_tree_from_tris(const Span<float3> positions,
505 const Span<int> corner_verts,
506 const Span<int3> corner_tris)
507{
508 std::unique_ptr<BVHTree, BVHTreeDeleter> tree = bvhtree_new_common(corner_tris.size());
509 if (!tree) {
510 return {};
511 }
512 for (const int tri : corner_tris.index_range()) {
513 float co[3][3];
514 copy_v3_v3(co[0], positions[corner_verts[corner_tris[tri][0]]]);
515 copy_v3_v3(co[1], positions[corner_verts[corner_tris[tri][1]]]);
516 copy_v3_v3(co[2], positions[corner_verts[corner_tris[tri][2]]]);
517 BLI_bvhtree_insert(tree.get(), tri, co[0], 3);
518 }
520 return tree;
521}
522
523static std::unique_ptr<BVHTree, BVHTreeDeleter> create_tree_from_tris(
524 const Span<float3> positions,
526 const Span<int> corner_verts,
527 const Span<int3> corner_tris,
528 const IndexMask &faces_mask)
529{
530 if (faces_mask.size() == faces.size()) {
531 /* Avoid accessing face offsets if the selection is full. */
532 return create_tree_from_tris(positions, corner_verts, corner_tris);
533 }
534
535 int tris_num = 0;
536 faces_mask.foreach_index_optimized<int>(
537 [&](const int i) { tris_num += mesh::face_triangles_num(faces[i].size()); });
538
539 std::unique_ptr<BVHTree, BVHTreeDeleter> tree = bvhtree_new_common(tris_num);
540 if (!tree) {
541 return {};
542 }
543 faces_mask.foreach_index([&](const int face) {
544 for (const int tri : mesh::face_triangles_range(faces, face)) {
545 float co[3][3];
546 copy_v3_v3(co[0], positions[corner_verts[corner_tris[tri][0]]]);
547 copy_v3_v3(co[1], positions[corner_verts[corner_tris[tri][1]]]);
548 copy_v3_v3(co[2], positions[corner_verts[corner_tris[tri][2]]]);
549 BLI_bvhtree_insert(tree.get(), tri, co[0], 3);
550 }
551 });
553 return tree;
554}
555
558 const Span<int> corner_verts,
559 const Span<int3> corner_tris,
560 const IndexMask &faces_mask)
561{
563 create_tree_from_tris(vert_positions, faces, corner_verts, corner_tris, faces_mask),
564 vert_positions,
565 corner_verts,
566 corner_tris);
567}
568
570{
571 int count = mesh.verts_num;
572 BitVector<> verts_mask(count, true);
573
574 const AttributeAccessor attributes = mesh.attributes();
575 const Span<int2> edges = mesh.edges();
576 const VArray<bool> hide_edge = *attributes.lookup_or_default(
577 ".hide_edge", AttrDomain::Edge, false);
578 const VArray<bool> hide_vert = *attributes.lookup_or_default(
579 ".hide_vert", AttrDomain::Point, false);
580
581 for (const int i : edges.index_range()) {
582 if (hide_edge[i]) {
583 continue;
584 }
585 for (const int vert : {edges[i][0], edges[i][1]}) {
586 if (verts_mask[vert]) {
587 verts_mask[vert].reset();
588 count--;
589 }
590 }
591 }
592
593 if (count) {
594 for (const int vert : verts_mask.index_range()) {
595 if (verts_mask[vert] && hide_vert[vert]) {
596 verts_mask[vert].reset();
597 }
598 }
599 }
600
601 return verts_mask;
602}
603
605{
606 int count = mesh.edges_num;
607 BitVector<> edge_mask(count, true);
608
609 const AttributeAccessor attributes = mesh.attributes();
610 const OffsetIndices faces = mesh.faces();
611 const Span<int> corner_edges = mesh.corner_edges();
612 const VArray<bool> hide_poly = *attributes.lookup_or_default(
613 ".hide_poly", AttrDomain::Face, false);
614 const VArray<bool> hide_edge = *attributes.lookup_or_default(
615 ".hide_edge", AttrDomain::Edge, false);
616
617 for (const int i : faces.index_range()) {
618 if (hide_poly[i]) {
619 continue;
620 }
621 for (const int edge : corner_edges.slice(faces[i])) {
622 if (edge_mask[edge]) {
623 edge_mask[edge].reset();
624 count--;
625 }
626 }
627 }
628
629 if (count) {
630 for (const int edge : edge_mask.index_range()) {
631 if (edge_mask[edge] && hide_edge[edge]) {
632 edge_mask[edge].reset();
633 }
634 }
635 }
636
637 return edge_mask;
638}
639
640} // namespace blender::bke
641
642blender::bke::BVHTreeFromMesh Mesh::bvh_loose_verts() const
643{
644 using namespace blender;
645 using namespace blender::bke;
646 const Span<float3> positions = this->vert_positions();
647 this->runtime->bvh_cache_loose_verts.ensure([&](std::unique_ptr<BVHTree, BVHTreeDeleter> &data) {
648 const LooseVertCache &loose_verts = this->loose_verts();
649 IndexMaskMemory memory;
650 const IndexMask mask = IndexMask::from_bits(loose_verts.is_loose_bits, memory);
651 data = create_tree_from_verts(positions, mask);
652 });
653 return create_verts_tree_data(this->runtime->bvh_cache_loose_verts.data().get(), positions);
654}
655
656blender::bke::BVHTreeFromMesh Mesh::bvh_loose_no_hidden_verts() const
657{
658 using namespace blender;
659 using namespace blender::bke;
660 const Span<float3> positions = this->vert_positions();
661 this->runtime->bvh_cache_loose_verts_no_hidden.ensure(
662 [&](std::unique_ptr<BVHTree, BVHTreeDeleter> &data) {
663 const BitVector<> mask = loose_verts_no_hidden_mask_get(*this);
664 IndexMaskMemory memory;
666 });
667 return create_verts_tree_data(this->runtime->bvh_cache_loose_verts_no_hidden.data().get(),
668 positions);
669}
670
671blender::bke::BVHTreeFromMesh Mesh::bvh_verts() const
672{
673 using namespace blender;
674 using namespace blender::bke;
675 const Span<float3> positions = this->vert_positions();
676 this->runtime->bvh_cache_verts.ensure([&](std::unique_ptr<BVHTree, BVHTreeDeleter> &data) {
677 data = create_tree_from_verts(positions, positions.index_range());
678 });
679 return create_verts_tree_data(this->runtime->bvh_cache_verts.data().get(), positions);
680}
681
682blender::bke::BVHTreeFromMesh Mesh::bvh_loose_edges() const
683{
684 using namespace blender;
685 using namespace blender::bke;
686 const Span<float3> positions = this->vert_positions();
687 const Span<int2> edges = this->edges();
688 this->runtime->bvh_cache_loose_edges.ensure([&](std::unique_ptr<BVHTree, BVHTreeDeleter> &data) {
689 const LooseEdgeCache &loose_edges = this->loose_edges();
690 IndexMaskMemory memory;
691 const IndexMask mask = IndexMask::from_bits(loose_edges.is_loose_bits, memory);
692 data = create_tree_from_edges(positions, edges, mask);
693 });
695 this->runtime->bvh_cache_loose_edges.data().get(), positions, edges);
696}
697
698blender::bke::BVHTreeFromMesh Mesh::bvh_loose_no_hidden_edges() const
699{
700 using namespace blender;
701 using namespace blender::bke;
702 const Span<float3> positions = this->vert_positions();
703 const Span<int2> edges = this->edges();
704 this->runtime->bvh_cache_loose_edges_no_hidden.ensure(
705 [&](std::unique_ptr<BVHTree, BVHTreeDeleter> &data) {
706 const BitVector<> mask = loose_edges_no_hidden_mask_get(*this);
707 IndexMaskMemory memory;
708 data = create_tree_from_edges(positions, edges, IndexMask::from_bits(mask, memory));
709 });
711 this->runtime->bvh_cache_loose_edges_no_hidden.data().get(), positions, edges);
712}
713
714blender::bke::BVHTreeFromMesh Mesh::bvh_edges() const
715{
716 using namespace blender;
717 using namespace blender::bke;
718 const Span<float3> positions = this->vert_positions();
719 const Span<int2> edges = this->edges();
720 this->runtime->bvh_cache_edges.ensure([&](std::unique_ptr<BVHTree, BVHTreeDeleter> &data) {
721 data = create_tree_from_edges(positions, edges, edges.index_range());
722 });
723 return create_edges_tree_data(this->runtime->bvh_cache_edges.data().get(), positions, edges);
724}
725
726blender::bke::BVHTreeFromMesh Mesh::bvh_legacy_faces() const
727{
728 using namespace blender;
729 using namespace blender::bke;
730 BLI_assert(!(this->totface_legacy == 0 && this->faces_num != 0));
731 Span legacy_faces{
732 static_cast<const MFace *>(CustomData_get_layer(&this->fdata_legacy, CD_MFACE)),
733 this->totface_legacy};
734 const Span<float3> positions = this->vert_positions();
735 this->runtime->bvh_cache_faces.ensure([&](std::unique_ptr<BVHTree, BVHTreeDeleter> &data) {
736 data = create_tree_from_legacy_faces(positions, legacy_faces);
737 });
739 this->runtime->bvh_cache_faces.data().get(), positions, legacy_faces.data());
740}
741
742blender::bke::BVHTreeFromMesh Mesh::bvh_corner_tris_no_hidden() const
743{
744 using namespace blender;
745 using namespace blender::bke;
746 const Span<float3> positions = this->vert_positions();
747 const Span<int> corner_verts = this->corner_verts();
748 const Span<int3> corner_tris = this->corner_tris();
749 const AttributeAccessor attributes = this->attributes();
750 const VArray hide_poly = *attributes.lookup<bool>(".hide_poly", AttrDomain::Face);
751 if (!hide_poly) {
752 return this->bvh_corner_tris();
753 }
754 this->runtime->bvh_cache_corner_tris_no_hidden.ensure(
755 [&](std::unique_ptr<BVHTree, BVHTreeDeleter> &data) {
756 const OffsetIndices<int> faces = this->faces();
757 IndexMaskMemory memory;
758 const IndexMask visible_faces = IndexMask::from_bools_inverse(
759 faces.index_range(), VArraySpan(hide_poly), memory);
760 data = create_tree_from_tris(positions, faces, corner_verts, corner_tris, visible_faces);
761 });
762 return create_tris_tree_data(this->runtime->bvh_cache_corner_tris_no_hidden.data().get(),
763 positions,
764 corner_verts,
765 corner_tris);
766}
767
768blender::bke::BVHTreeFromMesh Mesh::bvh_corner_tris() const
769{
770 using namespace blender;
771 using namespace blender::bke;
772 const Span<float3> positions = this->vert_positions();
773 const Span<int> corner_verts = this->corner_verts();
774 const Span<int3> corner_tris = this->corner_tris();
775 this->runtime->bvh_cache_corner_tris.ensure([&](std::unique_ptr<BVHTree, BVHTreeDeleter> &data) {
776 data = create_tree_from_tris(positions, corner_verts, corner_tris);
777 });
779 this->runtime->bvh_cache_corner_tris.data().get(), positions, corner_verts, corner_tris);
780}
781
782namespace blender::bke {
783
785{
786 if (faces_mask.size() == mesh.faces_num) {
787 return mesh.bvh_corner_tris();
788 }
790 mesh.vert_positions(), mesh.faces(), mesh.corner_verts(), mesh.corner_tris(), faces_mask);
791}
792
794{
795 if (edges_mask.size() == mesh.edges_num) {
796 return mesh.bvh_edges();
797 }
798 return bvhtree_from_mesh_edges_ex(mesh.vert_positions(), mesh.edges(), edges_mask);
799}
800
802{
803 if (verts_mask.size() == mesh.verts_num) {
804 return mesh.bvh_verts();
805 }
806 return bvhtree_from_mesh_verts_ex(mesh.vert_positions(), verts_mask);
807}
808
810
811/* -------------------------------------------------------------------- */
814
816 const Span<float3> positions)
817{
819 data.tree = tree;
820 data.positions = positions;
821 data.nearest_callback = nullptr;
822 return data;
823}
824
826 const Span<float3> positions)
827{
829 data.tree = tree;
830 data.positions = positions;
831 return data;
832}
833
835 std::unique_ptr<BVHTree, BVHTreeDeleter> tree, const Span<float3> positions)
836{
838 data.owned_tree = std::move(tree);
839 return data;
840}
841
843 const IndexMask &points_mask)
844{
845 if (points_mask.size() == pointcloud.totpoint) {
846 return pointcloud.bvh_tree();
847 }
848 const Span<float3> positions = pointcloud.positions();
849 return create_pointcloud_tree_data(create_tree_from_verts(positions, points_mask), positions);
850}
851
852} // namespace blender::bke
853
854blender::bke::BVHTreeFromPointCloud PointCloud::bvh_tree() const
855{
856 using namespace blender;
857 using namespace blender::bke;
858 const Span<float3> positions = this->positions();
859 this->runtime->bvh_cache.ensure([&](std::unique_ptr<BVHTree, BVHTreeDeleter> &data) {
860 data = create_tree_from_verts(positions, positions.index_range());
861 });
862 return create_pointcloud_tree_data(this->runtime->bvh_cache.data().get(), positions);
863}
864
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
General operations for point clouds.
#define BLI_assert(a)
Definition BLI_assert.h:46
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
void BLI_bvhtree_balance(BVHTree *tree)
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
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:387
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:41
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])
#define UNPACK3(a)
struct MFace MFace
BMesh const char void * data
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
AttributeSet attributes
static IndexMask from_bits(BitSpan bits, IndexMaskMemory &memory)
static IndexMask from_bools_inverse(const VArray< bool > &bools, IndexMaskMemory &memory)
constexpr const T * data() const
Definition BLI_span.hh:215
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:137
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
IndexRange index_range() const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, AttrType data_type, const void *default_value=nullptr) const
void foreach_index_optimized(Fn &&fn) const
void foreach_index(Fn &&fn) const
KDTree_3d * tree
int count
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static char faces[256]
int face_triangles_num(const int face_size)
Definition BKE_mesh.hh:350
IndexRange face_triangles_range(OffsetIndices< int > faces, int face_i)
Definition BKE_mesh.hh:359
static BVHTreeFromPointCloud create_pointcloud_tree_data(const BVHTree *tree, const Span< float3 > positions)
Definition bvhutils.cc:825
static std::unique_ptr< BVHTree, BVHTreeDeleter > create_tree_from_legacy_faces(const Span< float3 > positions, const Span< MFace > faces)
Definition bvhutils.cc:483
BVHTreeFromMesh bvhtree_from_mesh_corner_tris_ex(Span< float3 > vert_positions, OffsetIndices< int > faces, Span< int > corner_verts, Span< int3 > corner_tris, const IndexMask &faces_mask)
Definition bvhutils.cc:556
static void mesh_verts_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition bvhutils.cc:275
static std::unique_ptr< BVHTree, BVHTreeDeleter > create_tree_from_verts(const Span< float3 > positions, const IndexMask &verts_mask)
Definition bvhutils.cc:437
static BitVector loose_verts_no_hidden_mask_get(const Mesh &mesh)
Definition bvhutils.cc:569
float bvhtree_sphereray_tri_intersection(const BVHTreeRay *ray, float radius, float m_dist, const float v0[3], const float v1[3], const float v2[3])
Definition bvhutils.cc:49
static BVHTreeFromMesh create_tris_tree_data(const BVHTree *tree, const Span< float3 > positions, const Span< int > corner_verts, const Span< int3 > corner_tris)
Definition bvhutils.cc:404
static std::unique_ptr< BVHTree, BVHTreeDeleter > bvhtree_new_common(int elems_num)
Definition bvhutils.cc:429
static void mesh_corner_tris_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition bvhutils.cc:182
static BVHTreeFromMesh create_edges_tree_data(const BVHTree *tree, const Span< float3 > positions, const Span< int2 > edges)
Definition bvhutils.cc:369
static BVHTreeFromMesh create_legacy_faces_tree_data(const BVHTree *tree, const Span< float3 > positions, const MFace *face)
Definition bvhutils.cc:391
BVHTreeFromMesh bvhtree_from_mesh_edges_init(const Mesh &mesh, const IndexMask &edges_mask)
Definition bvhutils.cc:793
static std::unique_ptr< BVHTree, BVHTreeDeleter > create_tree_from_tris(const Span< float3 > positions, const Span< int > corner_verts, const Span< int3 > corner_tris)
Definition bvhutils.cc:504
float bvhtree_ray_tri_intersection(const BVHTreeRay *ray, float m_dist, const float v0[3], const float v1[3], const float v2[3])
Definition bvhutils.cc:28
BVHTreeFromMesh bvhtree_from_mesh_tris_init(const Mesh &mesh, const IndexMask &faces_mask)
Definition bvhutils.cc:784
static BVHTreeFromMesh create_verts_tree_data(const BVHTree *tree, const Span< float3 > positions)
Definition bvhutils.cc:349
static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition bvhutils.cc:292
static BVHTreeFromPointCloud create_points_tree_data(const BVHTree *tree, const Span< float3 > positions)
Definition bvhutils.cc:815
static std::unique_ptr< BVHTree, BVHTreeDeleter > create_tree_from_edges(const Span< float3 > positions, const Span< int2 > edges, const IndexMask &edges_mask)
Definition bvhutils.cc:457
BVHTreeFromMesh bvhtree_from_mesh_edges_ex(Span< float3 > vert_positions, Span< int2 > edges, const IndexMask &edges_mask)
Definition bvhutils.cc:475
static void mesh_corner_tris_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
Definition bvhutils.cc:113
BVHTreeFromMesh bvhtree_from_mesh_verts_init(const Mesh &mesh, const IndexMask &verts_mask)
Definition bvhutils.cc:801
BVHTreeFromMesh bvhtree_from_mesh_verts_ex(Span< float3 > vert_positions, const IndexMask &verts_mask)
Definition bvhutils.cc:450
static void mesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
Definition bvhutils.cc:79
static void mesh_verts_spherecast_do(int index, const float v[3], const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition bvhutils.cc:246
static BitVector loose_edges_no_hidden_mask_get(const Mesh &mesh)
Definition bvhutils.cc:604
static void mesh_edges_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
Definition bvhutils.cc:219
BVHTreeFromPointCloud bvhtree_from_pointcloud_get(const PointCloud &pointcloud, const IndexMask &points_mask)
Definition bvhutils.cc:842
static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
Definition bvhutils.cc:144
VecBase< int32_t, 2 > int2
VecBase< int32_t, 3 > int3
#define FLT_MAX
Definition stdcycles.h:14
float origin[3]
struct IsectRayPrecalc * isect_precalc
float direction[3]
unsigned int v2
unsigned int v1
unsigned int v4
unsigned int v3
MeshRuntimeHandle * runtime
CustomData fdata_legacy
int totface_legacy
int faces_num
PointCloudRuntimeHandle * runtime
blender::BitVector is_loose_bits
i
Definition text_draw.cc:230