1use super::BvhOptimizationHeapEntry;
2use crate::bounding_volume::{Aabb, BoundingVolume};
3use crate::math::{Point, Real, Vector};
4use crate::query::{Ray, RayCast};
5use crate::utils::VecMap;
6use alloc::collections::{BinaryHeap, VecDeque};
7use alloc::vec::Vec;
8use core::ops::{Deref, DerefMut, Index, IndexMut};
9
10#[derive(Default, Clone, Debug, Copy, PartialEq, Eq)]
15pub enum BvhBuildStrategy {
16 #[default]
21 Binned,
22 Ploc,
27}
28
29#[derive(Clone, Default)]
35pub struct BvhWorkspace {
36 pub(super) refit_tmp: BvhNodeVec,
37 pub(super) rebuild_leaves: Vec<BvhNode>,
38 pub(super) rebuild_frame_index: u32,
39 pub(super) rebuild_start_index: u32,
40 pub(super) optimization_roots: Vec<u32>,
41 pub(super) queue: BinaryHeap<BvhOptimizationHeapEntry>,
42 pub(super) dequeue: VecDeque<u32>,
43 pub(super) traversal_stack: Vec<u32>,
44}
45
46#[derive(Default, Copy, Clone, Debug)]
48#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
49#[cfg_attr(
50 feature = "rkyv",
51 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize),
52 archive(check_bytes)
53)]
54#[repr(transparent)]
55pub struct BvhNodeData(u32);
56const CHANGED: u32 = 0b01;
57const CHANGE_PENDING: u32 = 0b11;
58
59impl BvhNodeData {
60 #[inline(always)]
61 pub(super) fn with_leaf_count_and_pending_change(leaf_count: u32) -> Self {
62 Self(leaf_count | (CHANGE_PENDING << 30))
63 }
64
65 #[inline(always)]
66 pub(super) fn leaf_count(self) -> u32 {
67 self.0 & 0x3fff_ffff
68 }
69
70 #[inline(always)]
71 pub(super) fn is_changed(self) -> bool {
72 self.0 >> 30 == CHANGED
73 }
74
75 #[inline(always)]
76 pub(super) fn is_change_pending(self) -> bool {
77 self.0 >> 30 == CHANGE_PENDING
78 }
79
80 #[inline(always)]
81 pub(super) fn add_leaf_count(&mut self, added: u32) {
82 self.0 += added;
83 }
84
85 #[inline(always)]
86 pub(super) fn set_change_pending(&mut self) {
87 self.0 |= CHANGE_PENDING << 30;
88 }
89
90 #[inline(always)]
91 pub(super) fn resolve_pending_change(&mut self) {
92 if self.is_change_pending() {
93 *self = Self((self.0 & 0x3fff_ffff) | (CHANGED << 30));
94 } else {
95 *self = Self(self.0 & 0x3fff_ffff);
96 }
97 }
98
99 pub(super) fn merged(self, other: Self) -> Self {
100 let leaf_count = self.leaf_count() + other.leaf_count();
101 let changed = (self.0 >> 30) | (other.0 >> 30);
102 Self(leaf_count | changed << 30)
103 }
104}
105
106#[derive(Copy, Clone, Debug)]
113#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
114#[cfg_attr(
115 feature = "rkyv",
116 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize),
117 archive(check_bytes)
118)]
119#[repr(C)]
120#[cfg_attr(all(feature = "dim3", feature = "f32"), repr(align(64)))]
123pub struct BvhNodeWide {
124 pub(super) left: BvhNode,
125 pub(super) right: BvhNode,
126}
127
128#[cfg(all(feature = "dim3", feature = "f32"))]
130static_assertions::const_assert_eq!(align_of::<BvhNodeWide>(), 64);
131#[cfg(all(feature = "dim3", feature = "f32"))]
132static_assertions::assert_eq_size!(BvhNodeWide, [u8; 64]);
133
134impl BvhNodeWide {
135 #[inline(always)]
136 pub fn zeros() -> Self {
137 Self {
138 left: BvhNode::zeros(),
139 right: BvhNode::zeros(),
140 }
141 }
142
143 #[inline(always)]
147 pub fn as_array(&self) -> [&BvhNode; 2] {
148 [&self.left, &self.right]
149 }
150
151 #[inline(always)]
155 pub fn as_array_mut(&mut self) -> [&mut BvhNode; 2] {
156 [&mut self.left, &mut self.right]
157 }
158
159 pub fn merged(&self, my_id: u32) -> BvhNode {
161 self.left.merged(&self.right, my_id)
162 }
163
164 pub fn leaf_count(&self) -> u32 {
166 self.left.leaf_count() + self.right.leaf_count()
167 }
168}
169
170#[repr(C)] #[cfg(all(feature = "simd-is-enabled", feature = "dim3", feature = "f32"))]
172pub(super) struct BvhNodeSimd {
173 mins: glam::Vec3A,
174 maxs: glam::Vec3A,
175}
176
177#[cfg(all(feature = "simd-is-enabled", feature = "dim3", feature = "f32"))]
179static_assertions::assert_eq_align!(BvhNode, BvhNodeSimd);
180#[cfg(all(feature = "simd-is-enabled", feature = "dim3", feature = "f32"))]
181static_assertions::assert_eq_size!(BvhNode, BvhNodeSimd);
182
183#[derive(Copy, Clone, Debug)]
185#[repr(C)] #[cfg_attr(all(feature = "f32", feature = "dim3"), repr(align(16)))]
187#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
188#[cfg_attr(
189 feature = "rkyv",
190 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize),
191 archive(check_bytes)
192)]
193pub struct BvhNode {
194 pub(super) mins: Point<Real>,
196 pub(super) children: u32,
200 pub(super) maxs: Point<Real>,
202 pub(super) data: BvhNodeData,
204}
205
206impl BvhNode {
207 #[inline(always)]
208 pub(super) fn zeros() -> Self {
209 Self {
210 mins: Point::origin(),
211 children: 0,
212 maxs: Point::origin(),
213 data: BvhNodeData(0),
214 }
215 }
216
217 #[inline(always)]
219 pub fn leaf(aabb: Aabb, leaf_data: u32) -> BvhNode {
220 Self {
221 mins: aabb.mins,
222 maxs: aabb.maxs,
223 children: leaf_data,
224 data: BvhNodeData::with_leaf_count_and_pending_change(1),
225 }
226 }
227
228 #[inline(always)]
230 pub fn leaf_data(&self) -> Option<u32> {
231 self.is_leaf().then_some(self.children)
232 }
233
234 #[inline(always)]
236 pub fn is_leaf(&self) -> bool {
237 self.leaf_count() == 1
238 }
239
240 #[inline(always)]
241 pub(super) fn leaf_count(&self) -> u32 {
242 self.data.leaf_count()
243 }
244
245 #[inline(always)]
246 #[cfg(all(feature = "simd-is-enabled", feature = "dim3", feature = "f32"))]
247 pub(super) fn as_simd(&self) -> &BvhNodeSimd {
248 unsafe { core::mem::transmute(self) }
251 }
252
253 #[inline(always)]
254 pub(super) fn merged(&self, other: &Self, children: u32) -> Self {
255 Self {
257 mins: self.mins.inf(&other.mins),
258 children,
259 maxs: self.maxs.sup(&other.maxs),
260 data: self.data.merged(other.data),
261 }
262 }
263
264 #[inline]
266 pub fn mins(&self) -> Point<Real> {
267 self.mins
268 }
269
270 #[inline]
272 pub fn maxs(&self) -> Point<Real> {
273 self.maxs
274 }
275
276 #[inline]
278 pub fn aabb(&self) -> Aabb {
279 Aabb {
280 mins: self.mins,
281 maxs: self.maxs,
282 }
283 }
284
285 #[inline]
287 pub fn center(&self) -> Point<Real> {
288 na::center(&self.mins, &self.maxs)
289 }
290
291 #[inline(always)]
293 pub fn is_changed(&self) -> bool {
294 self.data.is_changed()
295 }
296
297 #[inline]
299 pub fn scale(&mut self, scale: &Vector<Real>) {
300 self.mins.coords.component_mul_assign(scale);
301 self.maxs.coords.component_mul_assign(scale);
302 }
303
304 #[inline]
306 pub fn volume(&self) -> Real {
307 let extents = self.maxs - self.mins;
309 #[cfg(feature = "dim2")]
310 return extents.x * extents.y;
311 #[cfg(feature = "dim3")]
312 return extents.x * extents.y * extents.z;
313 }
314
315 pub fn merged_volume(&self, other: &Self) -> Real {
317 let mins = self.mins.inf(&other.mins);
319 let maxs = self.maxs.sup(&other.maxs);
320 let extents = maxs - mins;
321
322 #[cfg(feature = "dim2")]
323 return extents.x * extents.y;
324 #[cfg(feature = "dim3")]
325 return extents.x * extents.y * extents.z;
326 }
327
328 #[cfg(not(all(feature = "simd-is-enabled", feature = "dim3", feature = "f32")))]
330 pub fn intersects(&self, other: &Self) -> bool {
331 na::partial_le(&self.mins, &other.maxs) && na::partial_ge(&self.maxs, &other.mins)
332 }
333
334 #[cfg(all(feature = "simd-is-enabled", feature = "dim3", feature = "f32"))]
336 pub fn intersects(&self, other: &Self) -> bool {
337 let simd_self = self.as_simd();
338 let simd_other = other.as_simd();
339 (simd_self.mins.cmple(simd_other.maxs) & simd_self.maxs.cmpge(simd_other.mins)).all()
340 }
341
342 #[cfg(not(all(feature = "simd-is-enabled", feature = "dim3", feature = "f32")))]
344 pub fn contains(&self, other: &Self) -> bool {
345 na::partial_le(&self.mins, &other.mins) && na::partial_ge(&self.maxs, &other.maxs)
346 }
347
348 #[cfg(all(feature = "simd-is-enabled", feature = "dim3", feature = "f32"))]
350 pub fn contains(&self, other: &Self) -> bool {
351 let simd_self = self.as_simd();
352 let simd_other = other.as_simd();
353 (simd_self.mins.cmple(simd_other.mins) & simd_self.maxs.cmpge(simd_other.maxs)).all()
354 }
355
356 pub fn contains_aabb(&self, other: &Aabb) -> bool {
358 na::partial_le(&self.mins, &other.mins) && na::partial_ge(&self.maxs, &other.maxs)
360 }
361
362 pub fn cast_ray(&self, ray: &Ray, max_toi: Real) -> Real {
366 self.aabb()
367 .cast_local_ray(ray, max_toi, true)
368 .unwrap_or(Real::MAX)
369 }
370
371 #[cfg(all(feature = "simd-is-enabled", feature = "dim3", feature = "f32"))]
375 pub(super) fn cast_inv_ray_simd(&self, ray: &super::bvh_queries::SimdInvRay) -> f32 {
376 let simd_self = self.as_simd();
377 let t1 = (simd_self.mins - ray.origin) * ray.inv_dir;
378 let t2 = (simd_self.maxs - ray.origin) * ray.inv_dir;
379
380 let tmin = t1.min(t2);
381 let tmax = t1.max(t2);
382 let tmin_n = tmin.max_element(); let tmax_n = tmax.min_element(); if tmax_n >= tmin_n && tmax_n >= 0.0 {
388 tmin_n
389 } else {
390 f32::MAX
391 }
392 }
393}
394
395#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
397#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
398#[cfg_attr(
399 feature = "rkyv",
400 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize),
401 archive(check_bytes)
402)]
403pub struct BvhNodeIndex(pub usize);
404
405impl BvhNodeIndex {
406 pub(super) const LEFT: bool = false;
407 pub(super) const RIGHT: bool = true;
408
409 #[inline]
412 pub fn decompose(self) -> (usize, bool) {
413 (self.0 >> 1, (self.0 & 0b01) != 0)
414 }
415
416 #[inline]
421 pub fn sibling(self) -> Self {
422 Self(self.0 ^ 0b01)
424 }
425
426 #[inline]
428 pub fn left(id: u32) -> Self {
429 Self::new(id, Self::LEFT)
430 }
431
432 #[inline]
434 pub fn right(id: u32) -> Self {
435 Self::new(id, Self::RIGHT)
436 }
437
438 #[inline]
441 pub fn new(id: u32, is_right: bool) -> Self {
442 Self(((id as usize) << 1) | (is_right as usize))
443 }
444}
445
446#[derive(Clone, Debug, Default)]
447#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
448#[cfg_attr(
449 feature = "rkyv",
450 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize),
451 archive(check_bytes)
452)]
453pub(crate) struct BvhNodeVec(pub(crate) Vec<BvhNodeWide>);
454
455impl Deref for BvhNodeVec {
456 type Target = Vec<BvhNodeWide>;
457 fn deref(&self) -> &Self::Target {
458 &self.0
459 }
460}
461
462impl DerefMut for BvhNodeVec {
463 fn deref_mut(&mut self) -> &mut Self::Target {
464 &mut self.0
465 }
466}
467
468impl Index<usize> for BvhNodeVec {
469 type Output = BvhNodeWide;
470
471 #[inline(always)]
472 fn index(&self, index: usize) -> &Self::Output {
473 &self.0[index]
474 }
475}
476
477impl IndexMut<usize> for BvhNodeVec {
478 #[inline(always)]
479 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
480 &mut self.0[index]
481 }
482}
483
484impl Index<BvhNodeIndex> for BvhNodeVec {
485 type Output = BvhNode;
486
487 #[inline(always)]
488 fn index(&self, index: BvhNodeIndex) -> &Self::Output {
489 self.0[index.0 >> 1].as_array()[index.0 & 1]
490 }
491}
492
493impl IndexMut<BvhNodeIndex> for BvhNodeVec {
494 #[inline(always)]
495 fn index_mut(&mut self, index: BvhNodeIndex) -> &mut Self::Output {
496 self.0[index.0 >> 1].as_array_mut()[index.0 & 1]
497 }
498}
499
500#[derive(Clone, Debug, Default)]
502#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
503#[cfg_attr(
504 feature = "rkyv",
505 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize),
506 archive(check_bytes)
507)]
508pub struct Bvh {
509 pub(super) nodes: BvhNodeVec,
510 pub(super) parents: Vec<BvhNodeIndex>,
513 pub(super) leaf_node_indices: VecMap<BvhNodeIndex>,
514}
515
516impl Bvh {
517 pub fn new() -> Self {
519 Self::default()
520 }
521
522 pub fn from_leaves(strategy: BvhBuildStrategy, leaves: &[Aabb]) -> Self {
527 Self::from_iter(strategy, leaves.iter().copied().enumerate())
528 }
529
530 pub fn from_iter<It>(strategy: BvhBuildStrategy, leaves: It) -> Self
539 where
540 It: IntoIterator<Item = (usize, Aabb)>,
541 {
542 let leaves = leaves.into_iter();
543 let (capacity_lo, capacity_up) = leaves.size_hint();
544 let capacity = capacity_up.unwrap_or(capacity_lo);
545
546 let mut result = Self::new();
547 let mut workspace = BvhWorkspace::default();
548 workspace.rebuild_leaves.reserve(capacity);
549 result.leaf_node_indices.reserve_len(capacity);
550
551 for (leaf_id, leaf_aabb) in leaves {
552 workspace
553 .rebuild_leaves
554 .push(BvhNode::leaf(leaf_aabb, leaf_id as u32));
555 let _ = result
556 .leaf_node_indices
557 .insert(leaf_id, BvhNodeIndex::default());
558 }
559
560 match workspace.rebuild_leaves.len() {
562 0 => {}
563 1 => {
564 result.nodes.push(BvhNodeWide {
565 left: workspace.rebuild_leaves[0],
566 right: BvhNode::zeros(),
567 });
568 result.parents.push(BvhNodeIndex::default());
569 result.leaf_node_indices[0] = BvhNodeIndex::left(0);
570 }
571 2 => {
572 result.nodes.push(BvhNodeWide {
573 left: workspace.rebuild_leaves[0],
574 right: workspace.rebuild_leaves[1],
575 });
576 result.parents.push(BvhNodeIndex::default());
577 result.leaf_node_indices[0] = BvhNodeIndex::left(0);
578 result.leaf_node_indices[1] = BvhNodeIndex::right(0);
579 }
580 _ => {
581 result.nodes.reserve(capacity);
582 result.parents.reserve(capacity);
583 result.parents.clear();
584 result.nodes.push(BvhNodeWide::zeros());
585 result.parents.push(BvhNodeIndex::default());
586
587 match strategy {
588 BvhBuildStrategy::Ploc => {
589 result.rebuild_range_ploc(0, &mut workspace.rebuild_leaves)
590 }
591 BvhBuildStrategy::Binned => {
592 result.rebuild_range_binned(0, &mut workspace.rebuild_leaves)
593 }
594 }
595
596 result.refit(&mut workspace);
598 }
599 }
600
601 result
602 }
603
604 pub fn root_aabb(&self) -> Aabb {
606 match self.leaf_count() {
607 0 => Aabb::new_invalid(),
608 1 => self.nodes[0].left.aabb(),
609 _ => self.nodes[0]
610 .left
611 .aabb()
612 .merged(&self.nodes[0].right.aabb()),
613 }
614 }
615
616 pub fn scale(&mut self, scale: &Vector<Real>) {
620 for node in self.nodes.0.iter_mut() {
621 node.left.scale(scale);
622 node.right.scale(scale);
623 }
624 }
625
626 pub fn is_empty(&self) -> bool {
628 self.nodes.is_empty()
629 }
630
631 pub fn leaf_node(&self, leaf_key: u32) -> Option<&BvhNode> {
633 let idx = self.leaf_node_indices.get(leaf_key as usize)?;
634 Some(&self.nodes[*idx])
635 }
636
637 pub fn total_memory_size(&self) -> usize {
640 size_of::<Self>() + self.heap_memory_size()
641 }
642
643 pub fn heap_memory_size(&self) -> usize {
645 let Self {
646 nodes,
647 parents,
648 leaf_node_indices,
649 } = self;
650 nodes.capacity() * size_of::<BvhNodeWide>()
651 + parents.capacity() * size_of::<BvhNodeIndex>()
652 + leaf_node_indices.capacity() * size_of::<BvhNodeIndex>()
653 }
654
655 pub fn subtree_depth(&self, node_id: u32) -> u32 {
659 if node_id == 0 && self.nodes.is_empty() {
660 return 0;
661 } else if node_id == 0 && self.nodes.len() == 1 {
662 return 1 + (self.nodes[0].right.leaf_count() != 0) as u32;
663 }
664
665 let node = &self.nodes[node_id as usize];
666
667 let left_depth = if node.left.is_leaf() {
668 1
669 } else {
670 self.subtree_depth(node.left.children)
671 };
672
673 let right_depth = if node.right.is_leaf() {
674 1
675 } else {
676 self.subtree_depth(node.right.children)
677 };
678
679 left_depth.max(right_depth) + 1
680 }
681
682 pub fn leaf_count(&self) -> u32 {
684 if self.nodes.is_empty() {
685 0
686 } else {
687 self.nodes[0].leaf_count()
688 }
689 }
690
691 pub fn remove(&mut self, leaf_index: u32) {
701 if let Some(node_index) = self.leaf_node_indices.remove(leaf_index as usize) {
702 if self.leaf_node_indices.is_empty() {
703 self.nodes.clear();
705 self.parents.clear();
706 return;
707 }
708
709 let sibling = node_index.sibling();
710 let (wide_node_index, is_right) = node_index.decompose();
711
712 if wide_node_index == 0 {
713 if self.nodes[sibling].is_leaf() {
714 if !is_right {
717 let moved_index = self.nodes[0].right.children;
719 self.nodes[0].left = self.nodes[0].right;
720 self.leaf_node_indices[moved_index as usize] = BvhNodeIndex::left(0);
721 }
722
723 self.nodes[0].right = BvhNode::zeros();
725 } else {
726 self.nodes[0] = self.nodes[self.nodes[sibling].children as usize];
728 let new_root = &mut self.nodes[0];
730 if new_root.left.is_leaf() {
731 self.leaf_node_indices[new_root.left.children as usize] =
732 BvhNodeIndex::left(0);
733 } else {
734 self.parents[new_root.left.children as usize] = BvhNodeIndex::left(0);
735 }
736 if new_root.right.is_leaf() {
737 self.leaf_node_indices[new_root.right.children as usize] =
738 BvhNodeIndex::right(0);
739 } else {
740 self.parents[new_root.right.children as usize] = BvhNodeIndex::right(0);
741 }
742 }
743 } else {
744 let parent = self.parents[wide_node_index];
747 let sibling = &self.nodes[sibling];
748
749 if sibling.is_leaf() {
750 self.leaf_node_indices[sibling.children as usize] = parent;
751 } else {
752 self.parents[sibling.children as usize] = parent;
753 }
754
755 self.nodes[parent] = *sibling;
756
757 let mut curr = parent.decompose().0;
760 while curr != 0 {
761 let parent = self.parents[curr];
762 self.nodes[parent] = self.nodes[curr].merged(curr as u32);
763 curr = parent.decompose().0;
764 }
765 }
766 }
767 }
768
769 }