molgfx_math/bounds/
source.rs1use crate::{Aabb, Vec3};
14
15pub trait BvhSource: Sync {
17 fn len(&self) -> usize;
19
20 fn bound(&self, index: u32) -> Aabb;
23
24 fn is_empty(&self) -> bool {
26 self.len() == 0
27 }
28}
29
30impl BvhSource for [Aabb] {
31 #[inline]
32 fn len(&self) -> usize {
33 <[Aabb]>::len(self)
34 }
35
36 #[inline]
37 fn bound(&self, index: u32) -> Aabb {
38 match self.get(index as usize) {
39 Some(bound) => *bound,
40 None => Aabb::EMPTY,
41 }
42 }
43}
44
45impl BvhSource for Vec<Aabb> {
46 #[inline]
47 fn len(&self) -> usize {
48 self.as_slice().len()
49 }
50
51 #[inline]
52 fn bound(&self, index: u32) -> Aabb {
53 self.as_slice().bound(index)
54 }
55}
56
57impl<const N: usize> BvhSource for [Aabb; N] {
58 #[inline]
59 fn len(&self) -> usize {
60 N
61 }
62
63 #[inline]
64 fn bound(&self, index: u32) -> Aabb {
65 self.as_slice().bound(index)
66 }
67}
68
69impl<T: BvhSource + ?Sized> BvhSource for &T {
70 #[inline]
71 fn len(&self) -> usize {
72 (**self).len()
73 }
74
75 #[inline]
76 fn bound(&self, index: u32) -> Aabb {
77 (**self).bound(index)
78 }
79}
80
81#[derive(Clone, Copy, Debug)]
87pub struct SphereBounds<'a> {
88 centers: &'a [[f32; 3]],
89 radii: &'a [f32],
90}
91
92impl<'a> SphereBounds<'a> {
93 #[must_use]
95 pub fn new(centers: &'a [[f32; 3]], radii: &'a [f32]) -> Self {
96 Self { centers, radii }
97 }
98}
99
100impl BvhSource for SphereBounds<'_> {
101 #[inline]
102 fn len(&self) -> usize {
103 self.centers.len().min(self.radii.len())
104 }
105
106 #[inline]
107 fn bound(&self, index: u32) -> Aabb {
108 let index = index as usize;
109 let (Some(center), Some(radius)) = (self.centers.get(index), self.radii.get(index)) else {
110 return Aabb::EMPTY;
111 };
112 let center = Vec3::from_array(*center);
113 let extent = Vec3::splat(radius.abs());
114 Aabb::new(center - extent, center + extent)
115 }
116}
117
118#[derive(Clone, Copy, Debug)]
124pub struct SweptSphereBounds<'a> {
125 start: &'a [[f32; 3]],
126 end: &'a [[f32; 3]],
127 radii: &'a [f32],
128}
129
130impl<'a> SweptSphereBounds<'a> {
131 #[must_use]
133 pub fn new(start: &'a [[f32; 3]], end: &'a [[f32; 3]], radii: &'a [f32]) -> Self {
134 Self { start, end, radii }
135 }
136}
137
138impl BvhSource for SweptSphereBounds<'_> {
139 #[inline]
140 fn len(&self) -> usize {
141 self.start.len().min(self.end.len()).min(self.radii.len())
142 }
143
144 #[inline]
145 fn bound(&self, index: u32) -> Aabb {
146 let index = index as usize;
147 let (Some(start), Some(end), Some(radius)) = (
148 self.start.get(index),
149 self.end.get(index),
150 self.radii.get(index),
151 ) else {
152 return Aabb::EMPTY;
153 };
154 let start = Vec3::from_array(*start);
155 let end = Vec3::from_array(*end);
156 let extent = Vec3::splat(radius.abs());
157 Aabb::new(start.min(end) - extent, start.max(end) + extent)
158 }
159}
160
161#[cfg(test)]
162#[path = "source_tests.rs"]
163mod tests;