68 lines
2.0 KiB
Rust
68 lines
2.0 KiB
Rust
use crate::{Color, Vec3};
|
|
use crate::hittable::{HitRecord, HittableList};
|
|
use crate::material::Scatterable;
|
|
use crate::vec3::Point3;
|
|
|
|
#[derive(Debug)]
|
|
pub struct Ray {
|
|
origin: Point3,
|
|
direction: Vec3,
|
|
time: f64
|
|
}
|
|
impl Default for Ray {
|
|
fn default() -> Self {
|
|
Ray::new(Vec3::default(), Vec3::default(), 0.0)
|
|
}
|
|
}
|
|
|
|
impl Ray {
|
|
pub fn new(origin: Point3, direction: Point3, time: f64) -> Ray {
|
|
Ray { origin, direction, time }
|
|
}
|
|
pub fn at(&self, t: f64) -> Point3 {
|
|
self.origin + self.direction * t
|
|
}
|
|
pub fn direction(&self) -> Vec3 { self.direction }
|
|
pub fn origin(&self) -> Point3 { self.origin }
|
|
pub fn time(&self) -> f64 { self.time }
|
|
pub fn pixel_color(&self, background: Color, world: &HittableList, depth: i32) -> Color {
|
|
if depth <= 0 {
|
|
return Color::default();
|
|
}
|
|
match self.hit_world(world, 0.001, f64::INFINITY) {
|
|
Some(rect) => {
|
|
let scattered = rect.material.scatter(self, &rect);
|
|
let emitted = rect.material.emitted(rect.u, rect.v, &rect.point);
|
|
match scattered {
|
|
Some((scattered, albedo)) => {
|
|
match scattered {
|
|
Some(scattered) => {
|
|
emitted + albedo * scattered.pixel_color(background, world, depth-1)
|
|
},
|
|
None => albedo
|
|
}
|
|
},
|
|
_ => emitted
|
|
}
|
|
},
|
|
None => background
|
|
}
|
|
}
|
|
pub fn hit_world<'material>(
|
|
&self,
|
|
world: &'material HittableList,
|
|
t_min: f64,
|
|
t_max: f64,
|
|
) -> Option<HitRecord<'material>> {
|
|
let mut closest_so_far = t_max;
|
|
let mut hit_record = None;
|
|
for sphere in world {
|
|
if let Some(hit) = sphere.hit(self, t_min, closest_so_far) {
|
|
closest_so_far = hit.t;
|
|
hit_record = Some(hit);
|
|
}
|
|
}
|
|
hit_record
|
|
}
|
|
}
|