MUDA
Loading...
Searching...
No Matches
query.h
1#pragma once
2#include <muda/ext/geo/lbvh/bvh.h>
3#include <muda/ext/geo/lbvh/predicator.h>
4
5namespace muda::lbvh
6{
7template <typename Real, typename Objects, typename AABBGetter, typename MortonCodeCalculator, typename OutputBackInserter>
8MUDA_HOST uint32_t query(const BVH<Real, Objects, AABBGetter, MortonCodeCalculator>& tree,
9 const query_overlap<Real> q,
10 OutputBackInserter outiter) noexcept
11{
12 using bvh_type = BVH<Real, Objects, AABBGetter, MortonCodeCalculator>;
13 using index_type = typename bvh_type::index_type;
14 using aabb_type = typename bvh_type::aabb_type;
15 using node_type = typename bvh_type::node_type;
16
17 std::vector<std::size_t> stack;
18 stack.reserve(64);
19 stack.push_back(0);
20
21 uint32_t num_found = 0;
22 do
23 {
24 const index_type node = stack.back();
25 stack.pop_back();
26 const index_type L_idx = tree.host_nodes()[node].left_idx;
27 const index_type R_idx = tree.host_nodes()[node].right_idx;
28
29 if(intersects(q.target, tree.host_aabbs()[L_idx]))
30 {
31 const auto obj_idx = tree.host_nodes()[L_idx].object_idx;
32 if(obj_idx != 0xFFFFFFFF)
33 {
34 *outiter++ = obj_idx;
35 ++num_found;
36 }
37 else // the node is not a leaf.
38 {
39 stack.push_back(L_idx);
40 }
41 }
42 if(intersects(q.target, tree.host_aabbs()[R_idx]))
43 {
44 const auto obj_idx = tree.host_nodes()[R_idx].object_idx;
45 if(obj_idx != 0xFFFFFFFF)
46 {
47 *outiter++ = obj_idx;
48 ++num_found;
49 }
50 else // the node is not a leaf.
51 {
52 stack.push_back(R_idx);
53 }
54 }
55 } while(!stack.empty());
56 return num_found;
57}
58
59template <typename Real, typename Objects, typename AABBGetter, typename MortonCodeCalculator, typename DistanceCalculator>
60MUDA_HOST std::pair<uint32_t, Real> query(const BVH<Real, Objects, AABBGetter, MortonCodeCalculator>& tree,
61 const query_nearest<Real>& q,
62 DistanceCalculator calc_dist) noexcept
63{
64 using bvh_type = BVH<Real, Objects, AABBGetter, MortonCodeCalculator>;
65 using real_type = typename bvh_type::real_type;
66 using index_type = typename bvh_type::index_type;
67 using aabb_type = typename bvh_type::aabb_type;
68 using node_type = typename bvh_type::node_type;
69
70 //if(!tree.query_host_enabled())
71 //{
72 // throw std::runtime_error("lbvh::bvh query_host is not enabled");
73 //}
74
75 // pair of {node_idx, mindist}
76 std::vector<std::pair<index_type, real_type>> stack = {
77 {0, mindist(tree.host_aabbs()[0], q.target)}};
78 stack.reserve(64);
79
80 uint32_t nearest = 0xFFFFFFFF;
81 real_type current_nearest_dist = infinity<real_type>();
82 do
83 {
84 const auto node = stack.back();
85 stack.pop_back();
86 if(node.second > current_nearest_dist)
87 {
88 // if aabb mindist > already_found_mindist, it cannot have a nearest
89 continue;
90 }
91
92 const index_type L_idx = tree.host_nodes()[node.first].left_idx;
93 const index_type R_idx = tree.host_nodes()[node.first].right_idx;
94
95 const aabb_type& L_box = tree.host_aabbs()[L_idx];
96 const aabb_type& R_box = tree.host_aabbs()[R_idx];
97
98 const real_type L_mindist = mindist(L_box, q.target);
99 const real_type R_mindist = mindist(R_box, q.target);
100
101 const real_type L_minmaxdist = minmaxdist(L_box, q.target);
102 const real_type R_minmaxdist = minmaxdist(R_box, q.target);
103
104 // there should be an object that locates within minmaxdist.
105
106 if(L_mindist <= R_minmaxdist) // L is worth considering
107 {
108 const auto obj_idx = tree.host_nodes()[L_idx].object_idx;
109 if(obj_idx != 0xFFFFFFFF) // leaf node
110 {
111 const real_type dist = calc_dist(q.target, tree.objects_host()[obj_idx]);
112 if(dist <= current_nearest_dist)
113 {
114 current_nearest_dist = dist;
115 nearest = obj_idx;
116 }
117 }
118 else
119 {
120 stack.emplace_back(L_idx, L_mindist);
121 }
122 }
123 if(R_mindist <= L_minmaxdist) // R is worth considering
124 {
125 const auto obj_idx = tree.host_nodes()[R_idx].object_idx;
126 if(obj_idx != 0xFFFFFFFF) // leaf node
127 {
128 const real_type dist = calc_dist(q.target, tree.objects_host()[obj_idx]);
129 if(dist <= current_nearest_dist)
130 {
131 current_nearest_dist = dist;
132 nearest = obj_idx;
133 }
134 }
135 else
136 {
137 stack.emplace_back(R_idx, R_mindist);
138 }
139 }
140 } while(!stack.empty());
141 return std::make_pair(nearest, current_nearest_dist);
142}
143} // namespace muda::lbvh