Add motion blur and MovingSphere type to exercise it.
Also changes Ray implementation to use public struct members instead of accessor functions.
This commit is contained in:
parent
919fa5f8d5
commit
896ae20196
@ -17,13 +17,12 @@ use rtiow::hitable_list::HitableList;
|
|||||||
use rtiow::material::Dielectric;
|
use rtiow::material::Dielectric;
|
||||||
use rtiow::material::Lambertian;
|
use rtiow::material::Lambertian;
|
||||||
use rtiow::material::Metal;
|
use rtiow::material::Metal;
|
||||||
|
use rtiow::moving_sphere::MovingSphere;
|
||||||
use rtiow::renderer::render;
|
use rtiow::renderer::render;
|
||||||
use rtiow::renderer::Scene;
|
use rtiow::renderer::Scene;
|
||||||
use rtiow::sphere::Sphere;
|
use rtiow::sphere::Sphere;
|
||||||
use rtiow::vec3::Vec3;
|
use rtiow::vec3::Vec3;
|
||||||
|
|
||||||
const BOOK_COVER: bool = true;
|
|
||||||
|
|
||||||
fn random_scene() -> Vec<Box<Hit>> {
|
fn random_scene() -> Vec<Box<Hit>> {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let mut objects: Vec<Box<Hit>> = vec![Box::new(Sphere::new(
|
let mut objects: Vec<Box<Hit>> = vec![Box::new(Sphere::new(
|
||||||
@ -98,6 +97,8 @@ fn build_scene_book(opt: &Opt) -> Scene {
|
|||||||
let lookat = Vec3::new(0., 0., 0.);
|
let lookat = Vec3::new(0., 0., 0.);
|
||||||
let dist_to_focus = 10.;
|
let dist_to_focus = 10.;
|
||||||
let aperture = 0.1;
|
let aperture = 0.1;
|
||||||
|
let time_min = 0.;
|
||||||
|
let time_max = 1.;
|
||||||
let camera = Camera::new(
|
let camera = Camera::new(
|
||||||
lookfrom,
|
lookfrom,
|
||||||
lookat,
|
lookat,
|
||||||
@ -106,6 +107,8 @@ fn build_scene_book(opt: &Opt) -> Scene {
|
|||||||
opt.width as f32 / opt.height as f32,
|
opt.width as f32 / opt.height as f32,
|
||||||
aperture,
|
aperture,
|
||||||
dist_to_focus,
|
dist_to_focus,
|
||||||
|
time_min,
|
||||||
|
time_max,
|
||||||
);
|
);
|
||||||
let world = HitableList::new(random_scene());
|
let world = HitableList::new(random_scene());
|
||||||
Scene {
|
Scene {
|
||||||
@ -122,6 +125,8 @@ fn build_scene_tutorial(opt: &Opt) -> Scene {
|
|||||||
let lookat = Vec3::new(0., 0., -1.);
|
let lookat = Vec3::new(0., 0., -1.);
|
||||||
let dist_to_focus = (lookfrom - lookat).length();
|
let dist_to_focus = (lookfrom - lookat).length();
|
||||||
let aperture = 0.1;
|
let aperture = 0.1;
|
||||||
|
let time_min = 0.;
|
||||||
|
let time_max = 1.;
|
||||||
let camera = Camera::new(
|
let camera = Camera::new(
|
||||||
lookfrom,
|
lookfrom,
|
||||||
lookat,
|
lookat,
|
||||||
@ -130,6 +135,8 @@ fn build_scene_tutorial(opt: &Opt) -> Scene {
|
|||||||
opt.width as f32 / opt.height as f32,
|
opt.width as f32 / opt.height as f32,
|
||||||
aperture,
|
aperture,
|
||||||
dist_to_focus,
|
dist_to_focus,
|
||||||
|
time_min,
|
||||||
|
time_max,
|
||||||
);
|
);
|
||||||
let world = HitableList::new(vec![
|
let world = HitableList::new(vec![
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
@ -140,22 +147,20 @@ fn build_scene_tutorial(opt: &Opt) -> Scene {
|
|||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
Vec3::new(0., -100.5, -1.),
|
Vec3::new(0., -100.5, -1.),
|
||||||
100.,
|
100.,
|
||||||
Box::new(Lambertian::new(Vec3::new(0.8, 0.8, 0.))),
|
Box::new(Lambertian::new(Vec3::new(0.8, 0.8, 0.8))),
|
||||||
)),
|
)),
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
Vec3::new(1., 0., -1.),
|
Vec3::new(1., 0., -1.),
|
||||||
0.5,
|
0.5,
|
||||||
Box::new(Metal::new(Vec3::new(0.8, 0.6, 0.2), 0.2)),
|
Box::new(Metal::new(Vec3::new(0.8, 0.6, 0.2), 0.2)),
|
||||||
)),
|
)),
|
||||||
Box::new(Sphere::new(
|
Box::new(MovingSphere::new(
|
||||||
Vec3::new(-1., 0., -1.),
|
Vec3::new(-1., 0., -1.25),
|
||||||
|
Vec3::new(-1., 0., -0.75),
|
||||||
0.5,
|
0.5,
|
||||||
Box::new(Dielectric::new(1.5)),
|
0.,
|
||||||
)),
|
1.,
|
||||||
Box::new(Sphere::new(
|
Box::new(Lambertian::new(Vec3::new(0.2, 0.8, 0.2))),
|
||||||
Vec3::new(-1., 0., -1.),
|
|
||||||
-0.45,
|
|
||||||
Box::new(Dielectric::new(1.5)),
|
|
||||||
)),
|
)),
|
||||||
]);
|
]);
|
||||||
Scene {
|
Scene {
|
||||||
|
|||||||
@ -1,46 +0,0 @@
|
|||||||
extern crate rtiow;
|
|
||||||
|
|
||||||
use rtiow::ray::Ray;
|
|
||||||
use rtiow::vec3::dot;
|
|
||||||
use rtiow::vec3::Vec3;
|
|
||||||
|
|
||||||
fn hit_sphere(center: Vec3, radius: f32, r: Ray) -> bool {
|
|
||||||
let oc = r.origin() - center;
|
|
||||||
let a = dot(r.direction(), r.direction());
|
|
||||||
let b = 2. * dot(oc, r.direction());
|
|
||||||
let c = dot(oc, oc) - radius * radius;
|
|
||||||
let discriminant = b * b - 4. * a * c;
|
|
||||||
discriminant > 0.
|
|
||||||
}
|
|
||||||
|
|
||||||
fn color(r: Ray) -> Vec3 {
|
|
||||||
if hit_sphere(Vec3::new(0., 0., -1.), 0.5, r) {
|
|
||||||
return Vec3::new(1., 0., 0.);
|
|
||||||
}
|
|
||||||
let unit_direction = r.direction().unit_vector();
|
|
||||||
let t = 0.5 * (unit_direction.y + 1.);
|
|
||||||
Vec3::new(1., 1., 1.) * (1. - t) + Vec3::new(0.5, 0.7, 1.) * t
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), std::io::Error> {
|
|
||||||
let nx = 200;
|
|
||||||
let ny = 100;
|
|
||||||
println!("P3\n{} {}\n255", nx, ny);
|
|
||||||
let lower_left_corner = Vec3::new(-2., -1., -1.);
|
|
||||||
let horizontal = Vec3::new(4., 0., 0.);
|
|
||||||
let vertical = Vec3::new(0., 2., 0.);
|
|
||||||
let origin: Vec3 = Default::default();
|
|
||||||
for j in (0..ny).rev() {
|
|
||||||
for i in 0..nx {
|
|
||||||
let u = i as f32 / nx as f32;
|
|
||||||
let v = j as f32 / ny as f32;
|
|
||||||
let r = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
|
|
||||||
let col = color(r);
|
|
||||||
let ir = (255.99 * col[0]) as u32;
|
|
||||||
let ig = (255.99 * col[1]) as u32;
|
|
||||||
let ib = (255.99 * col[2]) as u32;
|
|
||||||
println!("{} {} {}", ir, ig, ib);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
extern crate rtiow;
|
|
||||||
|
|
||||||
use rtiow::ray::Ray;
|
|
||||||
use rtiow::vec3::dot;
|
|
||||||
use rtiow::vec3::Vec3;
|
|
||||||
|
|
||||||
fn hit_sphere(center: Vec3, radius: f32, r: Ray) -> f32 {
|
|
||||||
let oc = r.origin() - center;
|
|
||||||
let a = dot(r.direction(), r.direction());
|
|
||||||
let b = 2. * dot(oc, r.direction());
|
|
||||||
let c = dot(oc, oc) - radius * radius;
|
|
||||||
let discriminant = b * b - 4. * a * c;
|
|
||||||
if discriminant < 0. {
|
|
||||||
return -1.;
|
|
||||||
}
|
|
||||||
(-b - discriminant.sqrt()) / (2. * a)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn color(r: Ray) -> Vec3 {
|
|
||||||
let t = hit_sphere(Vec3::new(0., 0., -1.), 0.5, r);
|
|
||||||
if t > 0. {
|
|
||||||
let n = (r.point_at_parameter(t) - Vec3::new(0., 0., -1.)).unit_vector();
|
|
||||||
return (n + 1.) * 0.5;
|
|
||||||
}
|
|
||||||
let unit_direction = r.direction().unit_vector();
|
|
||||||
let t = 0.5 * (unit_direction.y + 1.);
|
|
||||||
Vec3::new(1., 1., 1.) * (1. - t) + Vec3::new(0.5, 0.7, 1.) * t
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), std::io::Error> {
|
|
||||||
let nx = 200;
|
|
||||||
let ny = 100;
|
|
||||||
println!("P3\n{} {}\n255", nx, ny);
|
|
||||||
let lower_left_corner = Vec3::new(-2., -1., -1.);
|
|
||||||
let horizontal = Vec3::new(4., 0., 0.);
|
|
||||||
let vertical = Vec3::new(0., 2., 0.);
|
|
||||||
let origin: Vec3 = Default::default();
|
|
||||||
for j in (0..ny).rev() {
|
|
||||||
for i in 0..nx {
|
|
||||||
let u = i as f32 / nx as f32;
|
|
||||||
let v = j as f32 / ny as f32;
|
|
||||||
let r = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
|
|
||||||
let col = color(r);
|
|
||||||
let ir = (255.99 * col[0]) as u32;
|
|
||||||
let ig = (255.99 * col[1]) as u32;
|
|
||||||
let ib = (255.99 * col[2]) as u32;
|
|
||||||
println!("{} {} {}", ir, ig, ib);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
extern crate rtiow;
|
|
||||||
|
|
||||||
use rtiow::ray::Ray;
|
|
||||||
use rtiow::vec3::dot;
|
|
||||||
use rtiow::vec3::Vec3;
|
|
||||||
|
|
||||||
fn hit_sphere(center: Vec3, radius: f32, r: Ray) -> bool {
|
|
||||||
let oc = r.origin() - center;
|
|
||||||
let a = dot(r.direction(), r.direction());
|
|
||||||
let b = 2. * dot(oc, r.direction());
|
|
||||||
let c = dot(oc, oc) - radius * radius;
|
|
||||||
let discriminant = b * b - 4. * a * c;
|
|
||||||
discriminant > 0.
|
|
||||||
}
|
|
||||||
|
|
||||||
fn color(r: Ray) -> Vec3 {
|
|
||||||
if hit_sphere(Vec3::new(0., 0., -1.), 0.5, r) {
|
|
||||||
return Vec3::new(1., 0., 0.);
|
|
||||||
}
|
|
||||||
let unit_direction = r.direction().unit_vector();
|
|
||||||
let t = 0.5 * (unit_direction.y + 1.);
|
|
||||||
Vec3::new(1., 1., 1.) * (1. - t) + Vec3::new(0.5, 0.7, 1.) * t
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), std::io::Error> {
|
|
||||||
let nx = 200;
|
|
||||||
let ny = 100;
|
|
||||||
println!("P3\n{} {}\n255", nx, ny);
|
|
||||||
let lower_left_corner = Vec3::new(-2., -1., -1.);
|
|
||||||
let horizontal = Vec3::new(4., 0., 0.);
|
|
||||||
let vertical = Vec3::new(0., 2., 0.);
|
|
||||||
let origin: Vec3 = Default::default();
|
|
||||||
for j in (0..ny).rev() {
|
|
||||||
for i in 0..nx {
|
|
||||||
let u = i as f32 / nx as f32;
|
|
||||||
let v = j as f32 / ny as f32;
|
|
||||||
let r = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
|
|
||||||
let col = color(r);
|
|
||||||
let ir = (255.99 * col[0]) as u32;
|
|
||||||
let ig = (255.99 * col[1]) as u32;
|
|
||||||
let ib = (255.99 * col[2]) as u32;
|
|
||||||
println!("{} {} {}", ir, ig, ib);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
@ -30,6 +30,8 @@ pub struct Camera {
|
|||||||
u: Vec3,
|
u: Vec3,
|
||||||
v: Vec3,
|
v: Vec3,
|
||||||
lens_radius: f32,
|
lens_radius: f32,
|
||||||
|
time_min: f32,
|
||||||
|
time_max: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Camera {
|
impl Camera {
|
||||||
@ -42,6 +44,8 @@ impl Camera {
|
|||||||
aspect: f32,
|
aspect: f32,
|
||||||
aperture: f32,
|
aperture: f32,
|
||||||
focus_dist: f32,
|
focus_dist: f32,
|
||||||
|
time_min: f32,
|
||||||
|
time_max: f32,
|
||||||
) -> Camera {
|
) -> Camera {
|
||||||
let theta = vfov * PI / 180.;
|
let theta = vfov * PI / 180.;
|
||||||
let half_height = (theta / 2.).tan();
|
let half_height = (theta / 2.).tan();
|
||||||
@ -61,15 +65,20 @@ impl Camera {
|
|||||||
u: cross(vup, w).unit_vector(),
|
u: cross(vup, w).unit_vector(),
|
||||||
v: cross(w, u),
|
v: cross(w, u),
|
||||||
lens_radius: aperture / 2.,
|
lens_radius: aperture / 2.,
|
||||||
|
time_min,
|
||||||
|
time_max,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ray(&self, u: f32, v: f32) -> Ray {
|
pub fn get_ray(&self, u: f32, v: f32) -> Ray {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
let rd = self.lens_radius * random_in_unit_disk();
|
let rd = self.lens_radius * random_in_unit_disk();
|
||||||
let offset = self.u * rd.x + self.v * rd.y;
|
let offset = self.u * rd.x + self.v * rd.y;
|
||||||
|
let time = self.time_min + rng.gen_range::<f32>(0., 1.) * (self.time_max - self.time_min);
|
||||||
Ray::new(
|
Ray::new(
|
||||||
self.origin + offset,
|
self.origin + offset,
|
||||||
self.lower_left_corner + self.horizontal * u + self.vertical * v - self.origin - offset,
|
self.lower_left_corner + self.horizontal * u + self.vertical * v - self.origin - offset,
|
||||||
|
time,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ pub mod camera;
|
|||||||
pub mod hitable;
|
pub mod hitable;
|
||||||
pub mod hitable_list;
|
pub mod hitable_list;
|
||||||
pub mod material;
|
pub mod material;
|
||||||
|
pub mod moving_sphere;
|
||||||
pub mod ray;
|
pub mod ray;
|
||||||
pub mod renderer;
|
pub mod renderer;
|
||||||
pub mod sphere;
|
pub mod sphere;
|
||||||
|
|||||||
@ -43,11 +43,11 @@ impl Lambertian {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Material for Lambertian {
|
impl Material for Lambertian {
|
||||||
fn scatter(&self, _r_in: &Ray, rec: &HitRecord) -> ScatterResponse {
|
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse {
|
||||||
let target = rec.p + rec.normal + random_in_unit_sphere();
|
let target = rec.p + rec.normal + random_in_unit_sphere();
|
||||||
ScatterResponse {
|
ScatterResponse {
|
||||||
attenutation: self.albedo,
|
attenutation: self.albedo,
|
||||||
scattered: Ray::new(rec.p, target - rec.p),
|
scattered: Ray::new(rec.p, target - rec.p, r_in.time),
|
||||||
reflected: true,
|
reflected: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,12 +71,16 @@ impl Metal {
|
|||||||
|
|
||||||
impl Material for Metal {
|
impl Material for Metal {
|
||||||
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse {
|
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse {
|
||||||
let reflected = reflect(r_in.direction().unit_vector(), rec.normal);
|
let reflected = reflect(r_in.direction.unit_vector(), rec.normal);
|
||||||
let scattered = Ray::new(rec.p, reflected + self.fuzzy * random_in_unit_sphere());
|
let scattered = Ray::new(
|
||||||
|
rec.p,
|
||||||
|
reflected + self.fuzzy * random_in_unit_sphere(),
|
||||||
|
r_in.time,
|
||||||
|
);
|
||||||
ScatterResponse {
|
ScatterResponse {
|
||||||
scattered,
|
scattered,
|
||||||
attenutation: self.albedo,
|
attenutation: self.albedo,
|
||||||
reflected: dot(scattered.direction(), rec.normal) > 0.,
|
reflected: dot(scattered.direction, rec.normal) > 0.,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,30 +113,30 @@ impl Dielectric {
|
|||||||
|
|
||||||
impl Material for Dielectric {
|
impl Material for Dielectric {
|
||||||
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse {
|
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> ScatterResponse {
|
||||||
let reflected = reflect(r_in.direction(), rec.normal);
|
let reflected = reflect(r_in.direction, rec.normal);
|
||||||
let (outward_normal, ni_over_nt, cosine) = if dot(r_in.direction(), rec.normal) > 0. {
|
let (outward_normal, ni_over_nt, cosine) = if dot(r_in.direction, rec.normal) > 0. {
|
||||||
(
|
(
|
||||||
-rec.normal,
|
-rec.normal,
|
||||||
self.ref_idx,
|
self.ref_idx,
|
||||||
self.ref_idx * dot(r_in.direction(), rec.normal) / r_in.direction().length(),
|
self.ref_idx * dot(r_in.direction, rec.normal) / r_in.direction.length(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
rec.normal,
|
rec.normal,
|
||||||
1. / self.ref_idx,
|
1. / self.ref_idx,
|
||||||
-dot(r_in.direction(), rec.normal) / r_in.direction().length(),
|
-dot(r_in.direction, rec.normal) / r_in.direction.length(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let scattered =
|
let scattered = if let Some(refracted) = refract(r_in.direction, outward_normal, ni_over_nt)
|
||||||
if let Some(refracted) = refract(r_in.direction(), outward_normal, ni_over_nt) {
|
{
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
if rng.gen_range::<f32>(0., 1.) < schlick(cosine, self.ref_idx) {
|
if rng.gen_range::<f32>(0., 1.) < schlick(cosine, self.ref_idx) {
|
||||||
Ray::new(rec.p, reflected)
|
Ray::new(rec.p, reflected, r_in.time)
|
||||||
} else {
|
} else {
|
||||||
Ray::new(rec.p, refracted)
|
Ray::new(rec.p, refracted, r_in.time)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ray::new(rec.p, reflected)
|
Ray::new(rec.p, reflected, r_in.time)
|
||||||
};
|
};
|
||||||
|
|
||||||
ScatterResponse {
|
ScatterResponse {
|
||||||
|
|||||||
72
rtiow/src/moving_sphere.rs
Normal file
72
rtiow/src/moving_sphere.rs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
use hitable::Hit;
|
||||||
|
use hitable::HitRecord;
|
||||||
|
use material::Material;
|
||||||
|
use ray::Ray;
|
||||||
|
use vec3::dot;
|
||||||
|
use vec3::Vec3;
|
||||||
|
|
||||||
|
pub struct MovingSphere {
|
||||||
|
center0: Vec3,
|
||||||
|
center1: Vec3,
|
||||||
|
radius: f32,
|
||||||
|
material: Box<Material>,
|
||||||
|
time0: f32,
|
||||||
|
time1: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MovingSphere {
|
||||||
|
pub fn new(
|
||||||
|
center0: Vec3,
|
||||||
|
center1: Vec3,
|
||||||
|
radius: f32,
|
||||||
|
time0: f32,
|
||||||
|
time1: f32,
|
||||||
|
material: Box<Material>,
|
||||||
|
) -> MovingSphere {
|
||||||
|
MovingSphere {
|
||||||
|
center0,
|
||||||
|
center1,
|
||||||
|
radius,
|
||||||
|
material,
|
||||||
|
time0,
|
||||||
|
time1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn center(&self, time: f32) -> Vec3 {
|
||||||
|
self.center0
|
||||||
|
+ ((time - self.time0) / (self.time1 - self.time0)) * (self.center1 - self.center0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hit for MovingSphere {
|
||||||
|
fn hit(&self, r: Ray, t0: f32, t1: f32) -> Option<HitRecord> {
|
||||||
|
let oc = r.origin - self.center(r.time);
|
||||||
|
let a = dot(r.direction, r.direction);
|
||||||
|
let b = dot(oc, r.direction);
|
||||||
|
let c = dot(oc, oc) - self.radius * self.radius;
|
||||||
|
let discriminant = b * b - a * c;
|
||||||
|
if discriminant > 0. {
|
||||||
|
let temp = (-b - (b * b - a * c).sqrt()) / a;
|
||||||
|
if temp < t1 && temp > t0 {
|
||||||
|
let point = r.point_at_parameter(temp);
|
||||||
|
return Some(HitRecord {
|
||||||
|
t: temp,
|
||||||
|
p: point,
|
||||||
|
normal: (point - self.center(r.time)) / self.radius,
|
||||||
|
material: &*self.material,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let temp = (-b + (b * b - a * c).sqrt()) / a;
|
||||||
|
if temp < t1 && temp > t0 {
|
||||||
|
let point = r.point_at_parameter(temp);
|
||||||
|
return Some(HitRecord {
|
||||||
|
t: temp,
|
||||||
|
p: point,
|
||||||
|
normal: (point - self.center(r.time)) / self.radius,
|
||||||
|
material: &*self.material,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,21 +2,20 @@ use vec3::Vec3;
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Default)]
|
#[derive(Copy, Clone, Default)]
|
||||||
pub struct Ray {
|
pub struct Ray {
|
||||||
a: Vec3,
|
pub origin: Vec3,
|
||||||
b: Vec3,
|
pub direction: Vec3,
|
||||||
|
pub time: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ray {
|
impl Ray {
|
||||||
pub fn new(a: Vec3, b: Vec3) -> Ray {
|
pub fn new(origin: Vec3, direction: Vec3, time: f32) -> Ray {
|
||||||
Ray { a, b }
|
Ray {
|
||||||
|
origin,
|
||||||
|
direction,
|
||||||
|
time,
|
||||||
}
|
}
|
||||||
pub fn origin(self) -> Vec3 {
|
|
||||||
self.a
|
|
||||||
}
|
|
||||||
pub fn direction(self) -> Vec3 {
|
|
||||||
self.b
|
|
||||||
}
|
}
|
||||||
pub fn point_at_parameter(self, t: f32) -> Vec3 {
|
pub fn point_at_parameter(self, t: f32) -> Vec3 {
|
||||||
self.a + self.b * t
|
self.origin + self.direction * t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,7 +34,7 @@ fn color(r: Ray, world: &Hit, depth: usize) -> Vec3 {
|
|||||||
return Default::default();
|
return Default::default();
|
||||||
}
|
}
|
||||||
// No hit, choose color from background.
|
// No hit, choose color from background.
|
||||||
let unit_direction = r.direction().unit_vector();
|
let unit_direction = r.direction.unit_vector();
|
||||||
let t = 0.5 * (unit_direction.y + 1.);
|
let t = 0.5 * (unit_direction.y + 1.);
|
||||||
Vec3::new(1., 1., 1.) * (1. - t) + Vec3::new(0.5, 0.7, 1.) * t
|
Vec3::new(1., 1., 1.) * (1. - t) + Vec3::new(0.5, 0.7, 1.) * t
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,9 +23,9 @@ impl Sphere {
|
|||||||
|
|
||||||
impl Hit for Sphere {
|
impl Hit for Sphere {
|
||||||
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
||||||
let oc = r.origin() - self.center;
|
let oc = r.origin - self.center;
|
||||||
let a = dot(r.direction(), r.direction());
|
let a = dot(r.direction, r.direction);
|
||||||
let b = dot(oc, r.direction());
|
let b = dot(oc, r.direction);
|
||||||
let c = dot(oc, oc) - self.radius * self.radius;
|
let c = dot(oc, oc) - self.radius * self.radius;
|
||||||
let discriminant = b * b - a * c;
|
let discriminant = b * b - a * c;
|
||||||
if discriminant > 0. {
|
if discriminant > 0. {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user