1use super::{Bvh, BvhNode, BvhWorkspace};
2use alloc::vec::Vec;
3use smallvec::SmallVec;
4
5const TRAVERSAL_STACK_SIZE: usize = 32;
6
7impl Bvh {
8 pub fn traverse_bvtt_single_tree<const CHANGE_DETECTION: bool>(
21 &self,
22 workspace: &mut BvhWorkspace,
23 f: &mut impl FnMut(u32, u32),
24 ) {
25 if self.nodes.is_empty() || self.nodes[0].right.leaf_count() == 0 {
26 return;
28 }
29
30 workspace.traversal_stack.clear();
31 self.self_intersect_node::<CHANGE_DETECTION>(&mut workspace.traversal_stack, 0, f)
32 }
33
34 fn self_intersect_node<const CHANGE_DETECTION: bool>(
40 &self,
41 stack: &mut Vec<u32>,
42 id: u32,
43 f: &mut impl FnMut(u32, u32),
44 ) {
45 let node = &self.nodes[id as usize];
46
47 if CHANGE_DETECTION && !node.right.is_changed() && !node.left.is_changed() {
48 return;
49 }
50
51 let left_right_intersect = node.left.intersects(&node.right);
52 let left_child = node.left.children;
53 let right_child = node.right.children;
54 let left_is_leaf = node.left.is_leaf();
55 let right_is_leaf = node.right.is_leaf();
56
57 if (!CHANGE_DETECTION || node.left.is_changed()) && !left_is_leaf {
58 self.self_intersect_node::<CHANGE_DETECTION>(stack, left_child, f);
59 }
60
61 if (!CHANGE_DETECTION || node.right.is_changed()) && !right_is_leaf {
62 self.self_intersect_node::<CHANGE_DETECTION>(stack, right_child, f);
63 }
64
65 if left_right_intersect {
66 match (left_is_leaf, right_is_leaf) {
67 (true, true) => f(left_child, right_child),
68 (true, false) => self.traverse_single_subtree::<CHANGE_DETECTION>(
69 stack,
70 &node.left,
71 right_child,
72 f,
73 ),
74 (false, true) => self.traverse_single_subtree::<CHANGE_DETECTION>(
75 stack,
76 &node.right,
77 left_child,
78 f,
79 ),
80 (false, false) => self.traverse_two_branches::<CHANGE_DETECTION>(
81 stack,
82 left_child,
83 right_child,
84 f,
85 ),
86 }
87 }
88 }
89
90 fn traverse_two_branches<const CHANGE_DETECTION: bool>(
91 &self,
92 stack: &mut Vec<u32>,
93 a: u32,
94 b: u32,
95 f: &mut impl FnMut(u32, u32),
96 ) {
97 let node1 = &self.nodes[a as usize];
98 let node2 = &self.nodes[b as usize];
99
100 let left1 = &node1.left;
101 let right1 = &node1.right;
102 let left2 = &node2.left;
103 let right2 = &node2.right;
104
105 let left_left = (!CHANGE_DETECTION || left1.is_changed() || left2.is_changed())
106 && left1.intersects(left2);
107 let left_right = (!CHANGE_DETECTION || left1.is_changed() || right2.is_changed())
108 && left1.intersects(right2);
109 let right_left = (!CHANGE_DETECTION || right1.is_changed() || left2.is_changed())
110 && right1.intersects(left2);
111 let right_right = (!CHANGE_DETECTION || right1.is_changed() || right2.is_changed())
112 && right1.intersects(right2);
113
114 macro_rules! dispatch(
115 ($check: ident, $child_a: ident, $child_b: ident) => {
116 if $check {
117 match ($child_a.is_leaf(), $child_b.is_leaf()) {
118 (true, true) => f($child_a.children, $child_b.children),
119 (true, false) => {
120 self.traverse_single_subtree::<CHANGE_DETECTION>(stack, $child_a, $child_b.children, f)
121 }
122 (false, true) => self.traverse_single_subtree::<CHANGE_DETECTION>(
123 stack,
124 $child_b,
125 $child_a.children,
126 f,
127 ),
128 (false, false) => self.traverse_two_branches::<CHANGE_DETECTION>(
129 stack,
130 $child_a.children,
131 $child_b.children,
132 f,
133 ),
134 }
135 }
136 }
137 );
138
139 dispatch!(left_left, left1, left2);
140 dispatch!(left_right, left1, right2);
141 dispatch!(right_left, right1, left2);
142 dispatch!(right_right, right1, right2);
143 }
144
145 fn traverse_single_subtree<const CHANGE_DETECTION: bool>(
147 &self,
148 stack: &mut Vec<u32>,
149 node: &BvhNode,
150 subtree: u32,
151 f: &mut impl FnMut(u32, u32),
152 ) {
153 debug_assert!(stack.is_empty());
154
155 let mut curr_id = subtree;
159 let node_changed = node.is_changed();
160
161 loop {
162 let curr = &self.nodes[curr_id as usize];
163 let left = &curr.left;
164 let right = &curr.right;
165 let left_check =
166 (!CHANGE_DETECTION || node_changed || left.is_changed()) && node.intersects(left);
167 let right_check =
168 (!CHANGE_DETECTION || node_changed || right.is_changed()) && node.intersects(right);
169 let left_is_leaf = left.is_leaf();
170 let right_is_leaf = right.is_leaf();
171 let mut found_next = false;
172
173 if left_check {
174 if left_is_leaf {
175 f(node.children, left.children)
176 } else {
177 curr_id = left.children;
178 found_next = true;
179 }
180 }
181
182 if right_check {
183 if right_is_leaf {
184 f(node.children, right.children)
185 } else if !found_next {
186 curr_id = right.children;
187 found_next = true;
188 } else {
189 stack.push(right.children);
192 }
193 }
194
195 if !found_next {
196 if let Some(next_id) = stack.pop() {
198 curr_id = next_id;
199 } else {
200 return;
202 }
203 }
204 }
205 }
206
207 #[cfg(feature = "parallel")]
214 pub fn traverse_bvtt_single_tree_parallel<const CHANGE_DETECTION: bool>(
215 &self,
216 ) -> Vec<(u32, u32)> {
217 if self.nodes.is_empty() || self.nodes[0].right.leaf_count() == 0 {
218 return Vec::new();
220 }
221
222 const MAX_SPLIT_DEPTH: u32 = 6;
223 self.self_intersect_node_parallel::<CHANGE_DETECTION>(0, MAX_SPLIT_DEPTH)
224 }
225
226 #[cfg(feature = "parallel")]
229 fn self_intersect_node_parallel<const CHANGE_DETECTION: bool>(
230 &self,
231 id: u32,
232 depth: u32,
233 ) -> Vec<(u32, u32)> {
234 const SEQ_LEAF_THRESHOLD: u32 = 512;
236
237 let node = &self.nodes[id as usize];
238
239 if CHANGE_DETECTION && !node.right.is_changed() && !node.left.is_changed() {
240 return Vec::new();
241 }
242
243 if depth == 0 || node.left.leaf_count() + node.right.leaf_count() <= SEQ_LEAF_THRESHOLD {
244 let mut out = Vec::new();
245 let mut stack = Vec::new();
246 self.self_intersect_node::<CHANGE_DETECTION>(&mut stack, id, &mut |a, b| {
247 out.push((a, b))
248 });
249 return out;
250 }
251
252 let left_right_intersect = node.left.intersects(&node.right);
253 let left_child = node.left.children;
254 let right_child = node.right.children;
255 let left_is_leaf = node.left.is_leaf();
256 let right_is_leaf = node.right.is_leaf();
257
258 let (mut left_pairs, (mut right_pairs, mut cross_pairs)) = rayon::join(
259 || {
260 if (!CHANGE_DETECTION || node.left.is_changed()) && !left_is_leaf {
261 self.self_intersect_node_parallel::<CHANGE_DETECTION>(left_child, depth - 1)
262 } else {
263 Vec::new()
264 }
265 },
266 || {
267 rayon::join(
268 || {
269 if (!CHANGE_DETECTION || node.right.is_changed()) && !right_is_leaf {
270 self.self_intersect_node_parallel::<CHANGE_DETECTION>(
271 right_child,
272 depth - 1,
273 )
274 } else {
275 Vec::new()
276 }
277 },
278 || {
279 let mut out = Vec::new();
280 if left_right_intersect {
281 match (left_is_leaf, right_is_leaf) {
282 (true, true) => out.push((left_child, right_child)),
283 (true, false) => {
284 let mut stack = Vec::new();
285 self.traverse_single_subtree::<CHANGE_DETECTION>(
286 &mut stack,
287 &node.left,
288 right_child,
289 &mut |a, b| out.push((a, b)),
290 );
291 }
292 (false, true) => {
293 let mut stack = Vec::new();
294 self.traverse_single_subtree::<CHANGE_DETECTION>(
295 &mut stack,
296 &node.right,
297 left_child,
298 &mut |a, b| out.push((a, b)),
299 );
300 }
301 (false, false) => {
302 out = self.traverse_two_branches_parallel::<CHANGE_DETECTION>(
303 left_child,
304 right_child,
305 depth - 1,
306 );
307 }
308 }
309 }
310 out
311 },
312 )
313 },
314 );
315
316 left_pairs.append(&mut right_pairs);
317 left_pairs.append(&mut cross_pairs);
318 left_pairs
319 }
320
321 #[cfg(feature = "parallel")]
324 fn traverse_two_branches_parallel<const CHANGE_DETECTION: bool>(
325 &self,
326 a: u32,
327 b: u32,
328 depth: u32,
329 ) -> Vec<(u32, u32)> {
330 const SEQ_LEAF_THRESHOLD: u32 = 512;
331
332 let node1 = &self.nodes[a as usize];
333 let node2 = &self.nodes[b as usize];
334 let leaf_count = node1.left.leaf_count()
335 + node1.right.leaf_count()
336 + node2.left.leaf_count()
337 + node2.right.leaf_count();
338
339 if depth == 0 || leaf_count <= SEQ_LEAF_THRESHOLD {
340 let mut out = Vec::new();
341 let mut stack = Vec::new();
342 self.traverse_two_branches::<CHANGE_DETECTION>(&mut stack, a, b, &mut |a, b| {
343 out.push((a, b))
344 });
345 return out;
346 }
347
348 let dispatch = |child_a: &BvhNode, child_b: &BvhNode, check: bool| -> Vec<(u32, u32)> {
349 let mut out = Vec::new();
350 if check {
351 match (child_a.is_leaf(), child_b.is_leaf()) {
352 (true, true) => out.push((child_a.children, child_b.children)),
353 (true, false) => {
354 let mut stack = Vec::new();
355 self.traverse_single_subtree::<CHANGE_DETECTION>(
356 &mut stack,
357 child_a,
358 child_b.children,
359 &mut |a, b| out.push((a, b)),
360 );
361 }
362 (false, true) => {
363 let mut stack = Vec::new();
364 self.traverse_single_subtree::<CHANGE_DETECTION>(
365 &mut stack,
366 child_b,
367 child_a.children,
368 &mut |a, b| out.push((a, b)),
369 );
370 }
371 (false, false) => {
372 out = self.traverse_two_branches_parallel::<CHANGE_DETECTION>(
373 child_a.children,
374 child_b.children,
375 depth - 1,
376 );
377 }
378 }
379 }
380 out
381 };
382
383 let left1 = &node1.left;
384 let right1 = &node1.right;
385 let left2 = &node2.left;
386 let right2 = &node2.right;
387
388 let left_left = (!CHANGE_DETECTION || left1.is_changed() || left2.is_changed())
389 && left1.intersects(left2);
390 let left_right = (!CHANGE_DETECTION || left1.is_changed() || right2.is_changed())
391 && left1.intersects(right2);
392 let right_left = (!CHANGE_DETECTION || right1.is_changed() || left2.is_changed())
393 && right1.intersects(left2);
394 let right_right = (!CHANGE_DETECTION || right1.is_changed() || right2.is_changed())
395 && right1.intersects(right2);
396
397 let ((mut ll, mut lr), (mut rl, mut rr)) = rayon::join(
398 || {
399 rayon::join(
400 || dispatch(left1, left2, left_left),
401 || dispatch(left1, right2, left_right),
402 )
403 },
404 || {
405 rayon::join(
406 || dispatch(right1, left2, right_left),
407 || dispatch(right1, right2, right_right),
408 )
409 },
410 );
411
412 ll.append(&mut lr);
413 ll.append(&mut rl);
414 ll.append(&mut rr);
415 ll
416 }
417
418 pub fn leaf_pairs<'a, F: Fn(&BvhNode, &BvhNode) -> bool>(
423 &'a self,
424 other: &'a Self,
425 check: F,
426 ) -> LeafPairs<'a, F> {
427 if let (Some(root1), Some(root2)) = (self.nodes.first(), other.nodes.first()) {
428 let mut stack = SmallVec::default();
429
430 if root1.left.leaf_count() > 0 && root2.right.leaf_count() > 0 {
431 stack.push((&root1.left, &root2.right));
432 }
436
437 if root1.right.leaf_count() > 0 {
438 if root2.right.leaf_count() > 0 {
439 stack.push((&root1.right, &root2.right));
440 }
441 stack.push((&root1.right, &root2.left))
442 }
443
444 LeafPairs {
445 tree1: self,
446 tree2: other,
447 next: Some((&root1.left, &root2.left)),
448 stack,
449 check,
450 }
451 } else {
452 LeafPairs {
453 tree1: self,
454 tree2: other,
455 next: None,
456 stack: Default::default(),
457 check,
458 }
459 }
460 }
461}
462
463pub struct LeafPairs<'a, Check: Fn(&BvhNode, &BvhNode) -> bool> {
464 tree1: &'a Bvh,
465 tree2: &'a Bvh,
466 next: Option<(&'a BvhNode, &'a BvhNode)>,
467 stack: SmallVec<[(&'a BvhNode, &'a BvhNode); TRAVERSAL_STACK_SIZE]>,
468 check: Check,
469}
470
471impl<'a, Check: Fn(&BvhNode, &BvhNode) -> bool> Iterator for LeafPairs<'a, Check> {
472 type Item = (u32, u32);
473 fn next(&mut self) -> Option<Self::Item> {
474 loop {
475 if self.next.is_none() {
476 self.next = self.stack.pop();
477 }
478
479 let (node1, node2) = self.next.take()?;
480
481 match (node1.is_leaf(), node2.is_leaf()) {
482 (true, true) => return Some((node1.children, node2.children)),
483 (true, false) => {
484 let child2 = &self.tree2.nodes[node2.children as usize];
485 if (self.check)(node1, &child2.left) {
486 self.next = Some((node1, &child2.left));
487 }
488 if (self.check)(node1, &child2.right) {
489 if self.next.is_none() {
490 self.next = Some((node1, &child2.right));
491 } else {
492 self.stack.push((node1, &child2.right));
493 }
494 }
495 }
496 (false, true) => {
497 let child1 = &self.tree1.nodes[node1.children as usize];
498 if (self.check)(&child1.left, node2) {
499 self.next = Some((&child1.left, node2));
500 }
501 if (self.check)(&child1.right, node2) {
502 if self.next.is_none() {
503 self.next = Some((&child1.right, node2));
504 } else {
505 self.stack.push((&child1.right, node2));
506 }
507 }
508 }
509 (false, false) => {
510 let child1 = &self.tree1.nodes[node1.children as usize];
511 let child2 = &self.tree2.nodes[node2.children as usize];
512 if (self.check)(&child1.left, &child2.left) {
513 self.stack.push((&child1.left, &child2.left));
514 }
515 if (self.check)(&child1.right, &child2.left) {
516 self.stack.push((&child1.right, &child2.left));
517 }
518 if (self.check)(&child1.left, &child2.right) {
519 self.stack.push((&child1.left, &child2.right));
520 }
521 if (self.check)(&child1.right, &child2.right) {
522 self.stack.push((&child1.right, &child2.right));
523 }
524 }
525 }
526 }
527 }
528}