use std::fmt; use ray::Ray; use vec3::Vec3; #[derive(Debug, Clone, PartialEq)] pub struct AABB { bounds: [Vec3; 2], } impl fmt::Display for AABB { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({})-({})", self.bounds[0], self.bounds[1]) } } fn min(x: f32, y: f32) -> f32 { if x < y { x } else { y } } fn max(x: f32, y: f32) -> f32 { if x > y { x } else { y } } impl AABB { pub fn new(min: Vec3, max: Vec3) -> AABB { AABB { bounds: [min, max] } } pub fn min(&self) -> Vec3 { self.bounds[0] } pub fn max(&self) -> Vec3 { self.bounds[1] } pub fn hit2(&self, r: Ray, t_min: f32, t_max: f32) -> bool { let mut t_min = t_min; let mut t_max = t_max; for axis in 0..3 { let d_inv = 1.0 / r.direction[axis]; let t0 = min( (self.min()[axis] - r.origin[axis]) * d_inv, (self.max()[axis] - r.origin[axis]) * d_inv, ); let t1 = max( (self.min()[axis] - r.origin[axis]) * d_inv, (self.max()[axis] - r.origin[axis]) * d_inv, ); t_min = max(t0, t_min); t_max = min(t1, t_max); if t_max <= t_min { return false; } } true } pub fn hit(&self, r: Ray, t0: f32, t1: f32) -> bool { let mut t_min = (self.bounds[r.sign[0]].x - r.origin.x) * r.inv_direction.x; let mut t_max = (self.bounds[1 - r.sign[0]].x - r.origin.x) * r.inv_direction.x; let t_y_min = (self.bounds[r.sign[0]].y - r.origin.y) * r.inv_direction.y; let t_y_max = (self.bounds[1 - r.sign[0]].y - r.origin.y) * r.inv_direction.y; if t_min > t_y_max || t_y_min > t_max { return false; } if t_y_min > t_min { t_min = t_y_min; } if t_y_max < t_max { t_max = t_y_max; } let t_z_min = (self.bounds[r.sign[2]].z - r.origin.z) * r.inv_direction.z; let t_z_max = (self.bounds[1 - r.sign[2]].z - r.origin.z) * r.inv_direction.z; if t_min > t_z_max || t_z_min > t_max { return false; } if t_z_min > t_min { t_min = t_z_min; } if t_z_max < t_max { t_max = t_z_max; } t_min < t1 && t_max > t0 } pub fn hit_original(&self, r: Ray, t_min: f32, t_max: f32) -> bool { let mut t_min = t_min; let mut t_max = t_max; for axis in 0..3 { let t0 = ((self.min()[axis] - r.origin[axis]) * r.inv_direction[axis]) .min((self.max()[axis] - r.origin[axis]) * r.inv_direction[axis]); let t1 = ((self.min()[axis] - r.origin[axis]) * r.inv_direction[axis]) .max((self.max()[axis] - r.origin[axis]) * r.inv_direction[axis]); t_min = t0.max(t_min); t_max = t1.min(t_max); if t_max <= t_min { return false; } } true } pub fn hit_fast(&self, r: Ray, _t_min: f32, _t_max: f32) -> bool { let b = self; let mut t1 = (b.min()[0] - r.origin[0]) * 1. / r.direction[0]; let mut t2 = (b.max()[0] - r.origin[0]) * 1. / r.direction[0]; let mut tmin = t1.min(t2); let mut tmax = t1.max(t2); for i in 1..3 { t1 = (b.min()[i] - r.origin[i]) * 1. / r.direction[i]; t2 = (b.max()[i] - r.origin[i]) * 1. / r.direction[i]; tmin = tmin.max(t1.min(t2)); tmax = tmax.min(t1.max(t2)); } return tmax > tmin.max(0.0); } } pub fn surrounding_box(box0: &AABB, box1: &AABB) -> AABB { let min = Vec3::new( box0.min().x.min(box1.min().x), box0.min().y.min(box1.min().y), box0.min().z.min(box1.min().z), ); let max = Vec3::new( box0.max().x.max(box1.max().x), box0.max().y.max(box1.max().y), box0.max().z.max(box1.max().z), ); AABB::new(min, max) }