use super::*;
#[derive(Copy, Clone)]
pub struct AaBoundingBox {
pub ax_min: Point,
pub ax_max: Point,
}
impl Default for AaBoundingBox {
fn default() -> Self {
Self {
ax_min: Point::splat(crate::INF),
ax_max: Point::splat(-crate::INF),
}
}
}
impl AaBoundingBox {
pub fn new(ax_min: Point, ax_max: Point) -> Self {
Self { ax_min, ax_max }
}
pub fn intersect(&self, r: &Ray) -> (Float, Float) {
let ro_min = (self.ax_min - r.origin) / r.dir;
let ro_max = (self.ax_max - r.origin) / r.dir;
let t_start = ro_min.min(ro_max);
let t_end = ro_max.max(ro_min);
let t_start = t_start.max_element();
let t_end = t_end.min_element();
(t_start, t_end * (1.0 + 2.0 * efloat::gamma(3)))
}
pub fn merge(&self, other: &Self) -> Self {
Self::new(self.ax_min.min(other.ax_min), self.ax_max.max(other.ax_max))
}
pub fn area(&self) -> Float {
let bb_dim = self.ax_max - self.ax_min;
2.0 * (bb_dim.x * bb_dim.y + bb_dim.x * bb_dim.z + bb_dim.y * bb_dim.z)
}
pub fn cuts(&self, axis: Axis, point: Float) -> bool {
match axis {
Axis::X => self.ax_min.x < point && point < self.ax_max.x,
Axis::Y => self.ax_min.y < point && point < self.ax_max.y,
Axis::Z => self.ax_min.z < point && point < self.ax_max.z,
}
}
pub fn max(&self, axis: Axis) -> Float {
match axis {
Axis::X => self.ax_max.x,
Axis::Y => self.ax_max.y,
Axis::Z => self.ax_max.z,
}
}
pub fn min(&self, axis: Axis) -> Float {
match axis {
Axis::X => self.ax_min.x,
Axis::Y => self.ax_min.y,
Axis::Z => self.ax_min.z,
}
}
pub fn split(&self, axis: Axis, value: Float) -> (Self, Self) {
let mut ax_mid_max = self.ax_max;
let mut ax_mid_min = self.ax_min;
match axis {
Axis::X => {
ax_mid_max.x = value;
ax_mid_min.x = value;
}
Axis::Y => {
ax_mid_max.y = value;
ax_mid_min.y = value;
}
Axis::Z => {
ax_mid_max.z = value;
ax_mid_min.z = value;
}
}
(
Self::new(self.ax_min, ax_mid_max),
Self::new(ax_mid_min, self.ax_max),
)
}
}