34 using Tscal = shambase::VecComponent<Tvec>;
37 return shamtree::details::mac(a, b, theta_crit);
40 template<
bool allow_leaf_lowering>
42 sham::DeviceScheduler_ptr dev_sched,
44 shambase::VecComponent<Tvec> theta_crit,
45 bool ordered_result) {
53 using ObjItAcc =
typename ObjectIterator::acc;
55 u32 total_cell_count = bvh.
structure.get_total_cell_count();
59 count_m2l.set_val_at_idx(total_cell_count, 0);
60 count_p2p.set_val_at_idx(total_cell_count, 0);
72 u32 *__restrict__ count_m2l,
73 u32 *__restrict__ count_p2p) {
75 = {obj_it.tree_traverser.aabb_min[i], obj_it.tree_traverser.aabb_max[i]};
77 auto is_kdnode_within_node = [&](
u32 node_id) ->
bool {
79 = {obj_it.tree_traverser.aabb_min[node_id],
80 obj_it.tree_traverser.aabb_max[node_id]};
87 auto &ttrav = obj_it.tree_traverser.tree_traverser;
93 if (i == 0 && ttrav.is_id_leaf(0)) {
106 bool is_a_i_same = a == i;
109 obj_it.tree_traverser.aabb_min[a], obj_it.tree_traverser.aabb_max[a]};
111 obj_it.tree_traverser.aabb_min[b], obj_it.tree_traverser.aabb_max[b]};
113 bool crit = mac(aabb_a, aabb_b, theta_crit) ==
false;
117 if constexpr (allow_leaf_lowering) {
119 bool is_a_leaf = ttrav.is_id_leaf(a);
120 bool is_b_leaf = ttrav.is_id_leaf(b);
122 if (is_a_leaf && is_b_leaf) {
129 u32 child_a_1 = (is_a_leaf) ? a : ttrav.get_left_child(a);
130 u32 child_a_2 = (is_a_leaf) ? a : ttrav.get_right_child(a);
131 u32 child_b_1 = (is_b_leaf) ? b : ttrav.get_left_child(b);
132 u32 child_b_2 = (is_b_leaf) ? b : ttrav.get_right_child(b);
135 bool run_a_2 = !is_a_leaf;
137 bool run_b_2 = !is_b_leaf;
142 if (is_a_i_same && (child_a_1 != a)) {
146 bool is_node_i_in_left_a = is_kdnode_within_node(child_a_1);
147 bool is_node_i_in_right_a = is_kdnode_within_node(child_a_2);
149 run_a_1 = run_a_1 && is_node_i_in_left_a;
150 run_a_2 = run_a_2 && is_node_i_in_right_a;
152 if (run_a_1 && run_b_1)
153 stack.
push({child_a_1, child_b_1});
154 if (run_a_2 && run_b_1)
155 stack.
push({child_a_2, child_b_1});
156 if (run_a_1 && run_b_2)
157 stack.
push({child_a_1, child_b_2});
158 if (run_a_2 && run_b_2)
159 stack.
push({child_a_2, child_b_2});
163 u32 child_a_1 = ttrav.get_left_child(a);
164 u32 child_a_2 = ttrav.get_right_child(a);
165 u32 child_b_1 = ttrav.get_left_child(b);
166 u32 child_b_2 = ttrav.get_right_child(b);
168 bool child_a_1_leaf = ttrav.is_id_leaf(child_a_1);
169 bool child_a_2_leaf = ttrav.is_id_leaf(child_a_2);
170 bool child_b_1_leaf = ttrav.is_id_leaf(child_b_1);
171 bool child_b_2_leaf = ttrav.is_id_leaf(child_b_2);
173 if ((child_a_1_leaf || child_a_2_leaf || child_b_1_leaf
174 || child_b_2_leaf)) {
182 bool is_node_i_in_left_a = is_kdnode_within_node(child_a_1);
183 bool is_node_i_in_right_a = is_kdnode_within_node(child_a_2);
189 if (is_node_i_in_left_a) {
190 stack.
push({child_a_1, child_b_1});
191 stack.
push({child_a_1, child_b_2});
193 if (is_node_i_in_right_a) {
194 stack.
push({child_a_2, child_b_1});
195 stack.
push({child_a_2, child_b_2});
206 count_m2l[i] = count_m2l_i;
207 count_p2p[i] = count_p2p_i;
219 u32 total_count_m2l = scan_m2l.get_val_at_idx(total_cell_count);
235 const u32 *__restrict__ scan_m2l,
236 const u32 *__restrict__ scan_p2p,
237 u32_2 *__restrict__ idx_m2l,
238 u32_2 *__restrict__ idx_p2p) {
239 u32 offset_m2l = scan_m2l[i];
240 u32 offset_p2p = scan_p2p[i];
243 = {obj_it.tree_traverser.aabb_min[i], obj_it.tree_traverser.aabb_max[i]};
245 auto is_kdnode_within_node = [&](
u32 node_id) ->
bool {
247 = {obj_it.tree_traverser.aabb_min[node_id],
248 obj_it.tree_traverser.aabb_max[node_id]};
255 auto &ttrav = obj_it.tree_traverser.tree_traverser;
258 if (i == 0 && ttrav.is_id_leaf(0)) {
259 idx_p2p[offset_p2p] = {0, 0};
272 bool is_a_i_same = a == i;
275 obj_it.tree_traverser.aabb_min[a], obj_it.tree_traverser.aabb_max[a]};
277 obj_it.tree_traverser.aabb_min[b], obj_it.tree_traverser.aabb_max[b]};
279 bool crit = mac(aabb_a, aabb_b, theta_crit) ==
false;
283 if constexpr (allow_leaf_lowering) {
285 bool is_a_leaf = ttrav.is_id_leaf(a);
286 bool is_b_leaf = ttrav.is_id_leaf(b);
288 if (is_a_leaf && is_b_leaf) {
290 idx_p2p[offset_p2p] = {a, b};
296 u32 child_a_1 = (is_a_leaf) ? a : ttrav.get_left_child(a);
297 u32 child_a_2 = (is_a_leaf) ? a : ttrav.get_right_child(a);
298 u32 child_b_1 = (is_b_leaf) ? b : ttrav.get_left_child(b);
299 u32 child_b_2 = (is_b_leaf) ? b : ttrav.get_right_child(b);
302 bool run_a_2 = !is_a_leaf;
304 bool run_b_2 = !is_b_leaf;
309 if (is_a_i_same && (child_a_1 != a)) {
313 bool is_node_i_in_left_a = is_kdnode_within_node(child_a_1);
314 bool is_node_i_in_right_a = is_kdnode_within_node(child_a_2);
316 run_a_1 = run_a_1 && is_node_i_in_left_a;
317 run_a_2 = run_a_2 && is_node_i_in_right_a;
319 if (run_a_1 && run_b_1)
320 stack.
push({child_a_1, child_b_1});
321 if (run_a_2 && run_b_1)
322 stack.
push({child_a_2, child_b_1});
323 if (run_a_1 && run_b_2)
324 stack.
push({child_a_1, child_b_2});
325 if (run_a_2 && run_b_2)
326 stack.
push({child_a_2, child_b_2});
329 u32 child_a_1 = ttrav.get_left_child(a);
330 u32 child_a_2 = ttrav.get_right_child(a);
331 u32 child_b_1 = ttrav.get_left_child(b);
332 u32 child_b_2 = ttrav.get_right_child(b);
334 bool child_a_1_leaf = ttrav.is_id_leaf(child_a_1);
335 bool child_a_2_leaf = ttrav.is_id_leaf(child_a_2);
336 bool child_b_1_leaf = ttrav.is_id_leaf(child_b_1);
337 bool child_b_2_leaf = ttrav.is_id_leaf(child_b_2);
339 if ((child_a_1_leaf || child_a_2_leaf || child_b_1_leaf
340 || child_b_2_leaf)) {
342 idx_p2p[offset_p2p] = {a, b};
348 bool is_node_i_in_left_a = is_kdnode_within_node(child_a_1);
349 bool is_node_i_in_right_a = is_kdnode_within_node(child_a_2);
355 if (is_node_i_in_left_a) {
356 stack.
push({child_a_1, child_b_1});
357 stack.
push({child_a_1, child_b_2});
359 if (is_node_i_in_right_a) {
360 stack.
push({child_a_2, child_b_1});
361 stack.
push({child_a_2, child_b_2});
367 idx_m2l[offset_m2l] = {a, b};
374 DTTResult ret{std::move(idx_m2l), std::move(idx_p2p)};
376 if (ordered_result) {
378 ret.ordered_result = std::move(ordering);
385 sham::DeviceScheduler_ptr dev_sched,
387 shambase::VecComponent<Tvec> theta_crit,
389 bool allow_leaf_lowering) {
390 if (allow_leaf_lowering) {
391 return dtt_internal<true>(dev_sched, bvh, theta_crit, ordered_result);
393 return dtt_internal<false>(dev_sched, bvh, theta_crit, ordered_result);