70 lines
2.1 KiB
Rust
70 lines
2.1 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, world: &HittableList, depth: i32) -> Color {
|
|
if depth <= 0 {
|
|
return Color::default();
|
|
}
|
|
if let Some(rect) = self.hit_world(world, 0.001, f64::INFINITY) {
|
|
let scattered = rect.material.scatter(self, &rect);
|
|
return match scattered {
|
|
Some((scattered_ray, albedo)) => {
|
|
match scattered_ray {
|
|
Some(sr) => {
|
|
albedo * sr.pixel_color(world, depth-1)
|
|
},
|
|
None => albedo
|
|
}
|
|
},
|
|
None => { return Color::default() }
|
|
};
|
|
|
|
}
|
|
|
|
//Hot nothing, display sky color
|
|
let unit_direction = self.direction().unit_vector();
|
|
let t = 0.5 * (unit_direction.y() + 1.0);
|
|
(1.0 - t) * Color::new(1.0, 1.0, 1.0) + t * Color::new(0.5, 0.7, 1.0)
|
|
}
|
|
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
|
|
}
|
|
}
|