///|
/// Axis-aligned box geometry (cuboid).
pub(all) struct BoxShape {
center : Vec3
size : Vec3
material : Material
} derive(Debug)
pub fn BoxShape::new(center~ : Vec3, size~ : Vec3, material~ : Material) -> BoxShape {
{ center, size, material }
}
pub fn BoxShape::hit_box(self : BoxShape, r : Ray, t_min~ : Double, t_max~ : Double) -> HitRecord? {
let half = { x: self.size.x / 2.0, y: self.size.y / 2.0, z: self.size.z / 2.0 }
let box_min = self.center - half
let box_max = self.center + half
let inv_dir = { x: 1.0 / r.dir.x, y: 1.0 / r.dir.y, z: 1.0 / r.dir.z }
let mut tmin = (box_min.x - r.orig.x) * inv_dir.x
let mut tmax = (box_max.x - r.orig.x) * inv_dir.x
if inv_dir.x < 0.0 {
let tmp = tmin
tmin = tmax
tmax = tmp
}
let tymin = (box_min.y - r.orig.y) * inv_dir.y
let tymax = (box_max.y - r.orig.y) * inv_dir.y
if inv_dir.y < 0.0 {
let tmp = tymin
let tmp2 = tymax
tmin = if tmp > tmin { tmp } else { tmin }
tmax = if tmp2 < tmax { tmp2 } else { tmax }
} else {
tmin = if tymin > tmin { tymin } else { tmin }
tmax = if tymax < tmax { tymax } else { tmax }
}
if tmin >= tmax || tmax < t_min || tmin > t_max {
return None
}
let tzmin = (box_min.z - r.orig.z) * inv_dir.z
let tzmax = (box_max.z - r.orig.z) * inv_dir.z
if inv_dir.z < 0.0 {
let tmp = tzmin
let tmp2 = tzmax
tmin = if tmp > tmin { tmp } else { tmin }
tmax = if tmp2 < tmax { tmp2 } else { tmax }
} else {
tmin = if tzmin > tmin { tzmin } else { tmin }
tmax = if tzmax < tmax { tzmax } else { tmax }
}
if tmin >= tmax || tmax < t_min || tmin > t_max {
return None
}
let t = if tmin > t_min { tmin } else { tmax }
if t < t_min || t > t_max {
return None
}
let p = r.at(t)
let outward_normal = box_normal_at(p, box_min, box_max)
let rec = { p, normal: outward_normal, t, front_face: false, material: self.material }
Some(rec.set_face_normal(r, outward_normal))
}
fn box_normal_at(p : Vec3, box_min : Vec3, box_max : Vec3) -> Vec3 {
let eps = 1.0e-4
if (p.x - box_min.x).abs() < eps {
{ x: -1.0, y: 0.0, z: 0.0 }
} else if (p.x - box_max.x).abs() < eps {
{ x: 1.0, y: 0.0, z: 0.0 }
} else if (p.y - box_min.y).abs() < eps {
{ x: 0.0, y: -1.0, z: 0.0 }
} else if (p.y - box_max.y).abs() < eps {
{ x: 0.0, y: 1.0, z: 0.0 }
} else if (p.z - box_min.z).abs() < eps {
{ x: 0.0, y: 0.0, z: -1.0 }
} else {
{ x: 0.0, y: 0.0, z: 1.0 }
}
}