Implement positional camera.

Bug fix for cross()
This commit is contained in:
Bill Thiede 2018-09-09 21:27:34 -07:00
parent b342e00d4c
commit 196a4b76bc
4 changed files with 136 additions and 2 deletions

View File

@ -58,7 +58,13 @@ fn main() -> Result<(), std::io::Error> {
Box::new(Dielectric::new(1.5)),
),
];
let cam = Camera::new2x1();
let cam = Camera::new_lookfrom_vfov(
Vec3::new(-2., 2., 1.),
Vec3::new(0., 0., -1.),
Vec3::new(0., 1., 0.),
90.,
nx as f32 / ny as f32,
);
let world = HitableList::new(objects.iter().map(|o| o).collect());
for j in (0..ny).rev() {
for i in 0..nx {

View File

@ -0,0 +1,89 @@
extern crate rand;
extern crate rtiow;
use rand::Rng;
use rtiow::camera::Camera;
use rtiow::hitable::Hit;
use rtiow::hitable_list::HitableList;
use rtiow::material::Dielectric;
use rtiow::material::Lambertian;
use rtiow::material::Metal;
use rtiow::ray::Ray;
use rtiow::sphere::Sphere;
use rtiow::vec3::Vec3;
fn color(r: Ray, world: &Hit, depth: usize) -> Vec3 {
if let Some(rec) = world.hit(r, 0.001, std::f32::MAX) {
let scatter_response = rec.material.scatter(&r, &rec);
if depth < 50 && scatter_response.reflected {
return scatter_response.attenutation
* color(scatter_response.scattered, world, depth + 1);
}
return Default::default();
}
// No hit, choose color from background.
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 mut rng = rand::thread_rng();
let nx = 200;
let ny = 100;
let ns = 100;
println!("P3\n{} {}\n255", nx, ny);
let objects = vec![
Sphere::new(
Vec3::new(0., 0., -1.),
0.5,
Box::new(Lambertian::new(Vec3::new(0.1, 0.2, 0.5))),
),
Sphere::new(
Vec3::new(0., -100.5, -1.),
100.,
Box::new(Lambertian::new(Vec3::new(0.8, 0.8, 0.))),
),
Sphere::new(
Vec3::new(1., 0., -1.),
0.5,
Box::new(Metal::new(Vec3::new(0.8, 0.6, 0.2), 0.2)),
),
Sphere::new(Vec3::new(-1., 0., -1.), 0.5, Box::new(Dielectric::new(1.5))),
Sphere::new(
Vec3::new(-1., 0., -1.),
-0.45,
Box::new(Dielectric::new(1.5)),
),
];
let cam = Camera::new_lookfrom_vfov(
Vec3::new(-2., 2., 1.),
Vec3::new(0., 0., -1.),
Vec3::new(0., 1., 0.),
90.,
nx as f32 / ny as f32,
);
let world = HitableList::new(objects.iter().map(|o| o).collect());
for j in (0..ny).rev() {
for i in 0..nx {
let mut col: Vec3 = Default::default();
for _ in 0..ns {
let u = (rng.gen_range::<f32>(0., 1.) + i as f32) / nx as f32;
let v = (rng.gen_range::<f32>(0., 1.) + j as f32) / ny as f32;
let r = cam.get_ray(u, v);
col = col + color(r, &world, 0);
}
col = col / ns as f32;
// Gamma correct, use gamma 2 correction, which is 1/gamma where gamma=2 which is 1/2
// or sqrt.
col = Vec3::new(col[0].sqrt(), col[1].sqrt(), col[2].sqrt());
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(())
}

View File

@ -1,4 +1,7 @@
use std::f32::consts::PI;
use ray::Ray;
use vec3::cross;
use vec3::Vec3;
pub struct Camera {
@ -18,6 +21,42 @@ impl Camera {
}
}
// vfov is top to bottom in degrees
pub fn new_lookfrom_vfov(
lookfrom: Vec3,
lookat: Vec3,
vup: Vec3,
vfov: f32,
aspect: f32,
) -> Camera {
let theta = vfov * PI / 180.;
let half_height = (theta / 2.).tan();
let half_width = aspect * half_height;
let origin = lookfrom;
let w = (lookfrom - lookat).unit_vector();
let u = cross(vup, w).unit_vector();
let v = cross(w, u);
Camera {
lower_left_corner: origin - half_width * u - half_height * v - w,
horizontal: 2. * half_width * u,
vertical: 2. * half_height * v,
origin,
}
}
// vfov is top to bottom in degrees
pub fn new_vfov(vfov: f32, aspect: f32) -> Camera {
let theta = vfov * PI / 180.;
let half_height = (theta / 2.).tan();
let half_width = aspect * half_height;
Camera {
lower_left_corner: Vec3::new(-half_width, -half_height, -1.),
horizontal: Vec3::new(2. * half_width, 0., 0.),
vertical: Vec3::new(0., 2. * half_height, 0.),
origin: Default::default(),
}
}
pub fn get_ray(&self, u: f32, v: f32) -> Ray {
Ray::new(
self.origin,

View File

@ -18,7 +18,7 @@ pub struct Vec3 {
pub fn cross(v1: Vec3, v2: Vec3) -> Vec3 {
Vec3 {
x: v1.y * v2.z - v1.z * v2.y,
y: v1.x * v2.z - v1.z * v2.x,
y: v1.z * v2.x - v1.x * v2.z,
z: v1.x * v2.y - v1.y * v2.x,
}
}