use super::*;
impl Ray {
pub fn new(origin: Vector3D, direction: Vector3D) -> Ray {
Ray {
origin,
direction,
t_min: RAYTRACE_DEFAULT_T_MIN,
t_max: RAYTRACE_DEFAULT_T_MAX,
depth: 0,
}
}
pub fn at(&self, t: f64) -> Vector3D {
self.get_origin() + self.get_direction().scaled(t)
}
pub fn with_depth(&self, depth: u32) -> Ray {
Ray {
origin: self.get_origin(),
direction: self.get_direction(),
t_min: self.get_t_min(),
t_max: self.get_t_max(),
depth,
}
}
pub fn intersect_triangle(
&self,
v0: Vector3D,
v1: Vector3D,
v2: Vector3D,
) -> Option<(f64, Vector3D)> {
let (t, normal): (f64, Vector3D) =
intersect_triangle(self.get_origin(), self.get_direction(), v0, v1, v2)?;
if t < self.get_t_min() || t > self.get_t_max() {
return None;
}
Some((t, normal))
}
}
impl Occluder {
pub fn sphere(center: Vector3D, radius: f64, material: Material) -> Occluder {
Occluder {
kind: OccluderKind::Sphere,
center,
extent: Vector3D::new(radius, radius, radius),
vertices: [center; 3],
material,
}
}
pub fn aabb(min: Vector3D, max: Vector3D, material: Material) -> Occluder {
Occluder {
kind: OccluderKind::Aabb,
center: min,
extent: max,
vertices: [min; 3],
material,
}
}
pub fn triangle(v0: Vector3D, v1: Vector3D, v2: Vector3D, material: Material) -> Occluder {
Occluder {
kind: OccluderKind::Triangle,
center: Vector3D::zero(),
extent: Vector3D::zero(),
vertices: [v0, v1, v2],
material,
}
}
pub fn occluder_points(&self) -> Vec<(Vector3D, f64)> {
collect_occluder_points(std::slice::from_ref(self))
}
}
impl RayTraceScene {
pub fn new(occluders: Vec<Occluder>) -> RayTraceScene {
let shadow_points: Vec<(Vector3D, f64)> = collect_occluder_points(&occluders);
RayTraceScene {
occluders,
shadow_points,
}
}
pub fn trace(&self, ray: Ray, lights: &LightingUniforms) -> Vector3D {
self.trace_with_bounces(ray, lights, RAYTRACE_DEFAULT_MAX_BOUNCES)
}
pub fn trace_with_bounces(
&self,
ray: Ray,
lights: &LightingUniforms,
max_bounces: u32,
) -> Vector3D {
trace_bounces(
ray,
self.get_occluders(),
self.get_shadow_points(),
lights,
max_bounces,
)
}
pub fn closest_hit(&self, ray: &Ray) -> Option<Hit> {
let occluders: &[Occluder] = self.get_occluders();
closest_hit_indexed(ray, occluders).map(
|(index, t, position, normal): (usize, f64, Vector3D, Vector3D)| Hit {
t,
position,
normal,
material: occluders[index].get_material().clone(),
},
)
}
}