M src/camera.rs => src/camera.rs +14 -12
@@ 1,4 1,4 @@
-use crate::{Point3, Ray, Vec3};
+use crate::{cross, degrees_to_radians, unit_vector, Point3, Ray, Vec3};
pub struct Camera {
origin: Point3,
@@ 8,17 8,19 @@ pub struct Camera {
}
impl Camera {
- pub fn new() -> Self {
- let aspect_ratio = 16.0 / 9.0;
- let viewport_height = 2.0;
+ pub fn new(lookfrom: Point3, lookat: Point3, vup: Vec3, vfov: f64, aspect_ratio: f64) -> Self {
+ let theta = degrees_to_radians(vfov);
+ let h = (theta / 2.0).tan();
+ let viewport_height = 2.0 * h;
let viewport_width = aspect_ratio * viewport_height;
- let focal_length = 1.0;
- let origin = Point3::new(0., 0., 0.);
- let horizontal = Vec3::new(viewport_width, 0.0, 0.0);
- let vertical = Vec3::new(0.0, viewport_height, 0.0);
- let lower_left_corner =
- origin - horizontal / 2. - vertical / 2. - Vec3::new(0., 0., focal_length);
+ let w = unit_vector(lookfrom - lookat);
+ let u = unit_vector(cross(&vup, &w));
+ let v = cross(&w, &u);
+ let origin = lookfrom;
+ let horizontal = viewport_width * u;
+ let vertical = viewport_height * v;
+ let lower_left_corner = origin - horizontal / 2. - vertical / 2. - w;
Self {
origin,
lower_left_corner,
@@ 27,10 29,10 @@ impl Camera {
}
}
- pub fn get_ray(&self, u: f64, v: f64) -> Ray {
+ pub fn get_ray(&self, s: f64, t: f64) -> Ray {
return Ray::new(
&self.origin,
- &(self.lower_left_corner + u * self.horizontal + v * self.vertical - self.origin),
+ &(self.lower_left_corner + s * &self.horizontal + t * self.vertical - self.origin),
);
}
}
M src/hittable_list.rs => src/hittable_list.rs +0 -4
@@ 12,10 12,6 @@ impl HittableList {
HittableList { objects: vec![] }
}
- pub fn clear(&mut self) {
- self.objects.clear();
- }
-
pub fn add(&mut self, object: Arc<dyn Hittable>) {
self.objects.push(object);
}
M src/main.rs => src/main.rs +10 -15
@@ 24,19 24,7 @@ use camera::*;
mod material;
use material::*;
-fn hit_sphere(center: &Point3, radius: f64, r: &Ray) -> f64 {
- let oc = r.origin() - *center;
- let a = r.direction().length_squared();
- let half_b = dot(&oc, &r.direction());
- let c = oc.length_squared() - radius * radius;
- let discriminant = half_b * half_b - a * c;
-
- if discriminant < 0.0 {
- -1.0
- } else {
- (-half_b - discriminant.sqrt()) / a
- }
-}
+pub use std::f64::consts::PI;
fn ray_color(r: &Ray, world: &dyn Hittable, depth: isize) -> Color {
// If we've exceeded the ray bounce limit, no more light is gathered.
@@ 60,7 48,7 @@ fn main() {
// Image
let aspect_ratio = 16.0 / 9.0;
- let image_width = 400;
+ // let image_width = 400;
let image_width = 1000;
// let image_width = 1600;
let image_height = (image_width as f64 / aspect_ratio) as i32;
@@ 69,6 57,7 @@ fn main() {
// World
let mut world = HittableList::empty();
+
let material_ground: MaterialPtr = Arc::new(Lambertian::new(Color::new(0.8, 0.8, 0.0)));
let material_center: MaterialPtr = Arc::new(Lambertian::new(Color::new(0.1, 0.2, 0.5)));
let material_left: MaterialPtr = Arc::new(Dielectric::new(1.5));
@@ 101,7 90,13 @@ fn main() {
)));
// Camera
- let cam = Camera::new();
+ let cam = Camera::new(
+ Point3::new(-2., 2., 1.),
+ Point3::new(0., 0., -1.),
+ Point3::new(0., 1., 0.),
+ 20.0,
+ aspect_ratio,
+ );
// Render
M src/material.rs => src/material.rs +2 -2
@@ 22,7 22,7 @@ impl Lambertian {
}
impl Material for Lambertian {
- fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> Option<(Color, Ray)> {
+ fn scatter(&self, _r_in: &Ray, rec: &HitRecord) -> Option<(Color, Ray)> {
let mut scatter_direction = rec.normal + random_unit_vector();
// Catch degenerate scatter direction
if scatter_direction.near_zero() {
@@ 84,7 84,7 @@ impl Material for Dielectric {
fn scatter(&self, r_in: &Ray, rec: &HitRecord) -> Option<(Color, Ray)> {
let attenuation = Color::new(1.0, 1.0, 1.0);
let refraction_ratio = if rec.front_face {
- (1.0 / self.ir)
+ 1.0 / self.ir
} else {
self.ir
};