///|
/// Axis-Aligned Bounding Box for ray intersection acceleration.
pub(all) struct AABB {
min : Vec3
max : Vec3
} derive(Debug)
pub fn AABB::new(min~ : Vec3, max~ : Vec3) -> AABB {
{ min, max }
}
pub fn empty_aabb() -> AABB {
{
min: { x: 1.0e30, y: 1.0e30, z: 1.0e30 },
max: { x: -1.0e30, y: -1.0e30, z: -1.0e30 },
}
}
pub fn AABB::hit(self : AABB, r : Ray, t_min~ : Double, t_max~ : Double) -> Bool {
let mut t0 = t_min
let mut t1 = t_max
let inv_d = 1.0 / r.dir.x
let mut t0x = (self.min.x - r.orig.x) * inv_d
let mut t1x = (self.max.x - r.orig.x) * inv_d
if inv_d < 0.0 {
let tmp = t0x
t0x = t1x
t1x = tmp
}
if t0x > t0 { t0 = t0x }
if t1x < t1 { t1 = t1x }
if t0 >= t1 { return false }
let inv_d_y = 1.0 / r.dir.y
let mut t0y = (self.min.y - r.orig.y) * inv_d_y
let mut t1y = (self.max.y - r.orig.y) * inv_d_y
if inv_d_y < 0.0 {
let tmp = t0y
t0y = t1y
t1y = tmp
}
if t0y > t0 { t0 = t0y }
if t1y < t1 { t1 = t1y }
if t0 >= t1 { return false }
let inv_d_z = 1.0 / r.dir.z
let mut t0z = (self.min.z - r.orig.z) * inv_d_z
let mut t1z = (self.max.z - r.orig.z) * inv_d_z
if inv_d_z < 0.0 {
let tmp = t0z
t0z = t1z
t1z = tmp
}
if t0z > t0 { t0 = t0z }
if t1z < t1 { t1 = t1z }
if t0 >= t1 { return false }
true
}
pub fn surrounding_box(box0 : AABB, box1 : AABB) -> AABB {
let small = box0.min.min(box1.min)
let big = box0.max.max(box1.max)
{ min: small, max: big }
}
pub fn Hitable::bounding_box(self : Hitable) -> AABB {
match self {
Sphere(s) => {
let r = { x: s.radius, y: s.radius, z: s.radius }
{ min: s.center - r, max: s.center + r }
}
Plane(_) => {
let inf = 1.0e30
{ min: { x: -inf, y: -inf, z: -inf }, max: { x: inf, y: inf, z: inf } }
}
Triangle(tri) => {
let v0 = tri.v0
let v1 = tri.v1
let v2 = tri.v2
let min_p = v0.min(v1).min(v2) - { x: 0.001, y: 0.001, z: 0.001 }
let max_p = v0.max(v1).max(v2) + { x: 0.001, y: 0.001, z: 0.001 }
{ min: min_p, max: max_p }
}
BoxShape(bx) => {
let r = { x: bx.size.x / 2.0, y: bx.size.y / 2.0, z: bx.size.z / 2.0 }
{ min: bx.center - r, max: bx.center + r }
}
Cylinder(cyl) => {
let r = { x: cyl.radius, y: cyl.height / 2.0, z: cyl.radius }
{ min: cyl.center - r, max: cyl.center + r }
}
Disk(dk) => {
let r = { x: dk.radius, y: 0.001, z: dk.radius }
{ min: dk.center - r, max: dk.center + r }
}
Cone(cn) => {
let r = cn.base_radius
let min_y = cn.base_center.y.min(cn.apex.y)
let max_y = cn.base_center.y.max(cn.apex.y)
{ min: { x: cn.base_center.x - r, y: min_y, z: cn.base_center.z - r },
max: { x: cn.base_center.x + r, y: max_y, z: cn.base_center.z + r } }
}
Torus(tor) => {
let big_r = tor.major_radius + tor.minor_radius
let rv = { x: big_r, y: tor.minor_radius, z: big_r }
{ min: tor.center - rv, max: tor.center + rv }
}
}
}