camera & spheres: add feature tag disable_inverse_cache

This commit is contained in:
Bill Thiede 2021-07-18 08:51:51 -07:00
parent 538b8ad364
commit 2eeeb2013b
3 changed files with 56 additions and 3 deletions

View File

@ -6,6 +6,9 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
disable_inverse_cache = []
[dependencies]
anyhow = "1.0.41"
criterion = "0.3.4"

View File

@ -112,6 +112,7 @@ impl Camera {
/// Tuple::vector(2_f32.sqrt() / 2., 0., -2_f32.sqrt() / 2.)
/// );
/// ```
#[cfg(not(feature = "disable_inverse_cache"))]
pub fn ray_for_pixel(&self, px: usize, py: usize) -> Ray {
// The offset from the edge of the canvas to the pixel's corner.
let xoffset = (px as f32 + 0.5) * self.pixel_size;
@ -124,16 +125,35 @@ impl Camera {
// Using the camera matrix, transofmrm the canvas point and the origin,
// and then compute the ray's direction vector.
// (Remember that the canves is at z>=-1).
// (Remember that the canvas is at z>=-1).
let pixel = self.inverse_transform * Tuple::point(world_x, world_y, -1.);
let origin = self.inverse_transform * Tuple::point(0., 0., 0.);
let direction = (pixel - origin).normalize();
Ray::new(origin, direction)
}
#[cfg(feature = "disable_inverse_cache")]
pub fn ray_for_pixel(&self, px: usize, py: usize) -> Ray {
// The offset from the edge of the canvas to the pixel's corner.
let xoffset = (px as f32 + 0.5) * self.pixel_size;
let yoffset = (py as f32 + 0.5) * self.pixel_size;
// The untransformed coordinates of the pixle in world space.
// (Remember that the camera looks toward -z, so +x is to the left.)
let world_x = self.half_width - xoffset;
let world_y = self.half_height - yoffset;
// Using the camera matrix, transofmrm the canvas point and the origin,
// and then compute the ray's direction vector.
// (Remember that the canvas is at z>=-1).
let pixel = self.transform.inverse() * Tuple::point(world_x, world_y, -1.);
let origin = self.transform.inverse() * Tuple::point(0., 0., 0.);
let direction = (pixel - origin).normalize();
Ray::new(origin, direction)
}
/// Use camera to render an image of the given world.
///
/// # Examples
/// ```
/// use std::f32::consts::PI;
@ -160,7 +180,28 @@ impl Camera {
}
#[allow(dead_code)]
fn render_parallel(&self, w: &World) -> Canvas {
fn render_parallel_one_tread_per_core(&self, w: &World) -> Canvas {
let image_mu = Mutex::new(Canvas::new(self.hsize, self.vsize, BLACK));
(0..self.vsize).into_par_iter().for_each(|y| {
let mut row_image = Canvas::new(self.hsize, 1, BLACK);
for x in 0..self.hsize {
let ray = self.ray_for_pixel(x, y);
let color = w.color_at(&ray);
row_image.set(x, 0, color);
}
// TODO(wathiede): create a row based setter for memcpying the row as a whole.
let mut image = image_mu.lock().expect("failed to lock image mutex");
for x in 0..self.hsize {
image.set(x, y, row_image.get(x, 0));
}
});
image_mu
.into_inner()
.expect("failed to get image out of mutex")
}
#[allow(dead_code)]
fn render_parallel_rayon(&self, w: &World) -> Canvas {
let image_mu = Mutex::new(Canvas::new(self.hsize, self.vsize, BLACK));
(0..self.vsize).into_par_iter().for_each(|y| {

View File

@ -105,6 +105,7 @@ impl Sphere {
/// let n = s.normal_at(Tuple::point(0., 2_f32.sqrt()/2., -2_f32.sqrt()/2.));
/// assert_eq!(n, Tuple::vector(0., 0.97014, -0.24254));
/// ```
#[cfg(not(feature = "disable_inverse_cache"))]
pub fn normal_at(&self, world_point: Tuple) -> Tuple {
let object_point = self.inverse_transform * world_point;
let object_normal = object_point - Tuple::point(0., 0., 0.);
@ -112,6 +113,14 @@ impl Sphere {
world_normal.w = 0.;
world_normal.normalize()
}
#[cfg(feature = "disable_inverse_cache")]
pub fn normal_at(&self, world_point: Tuple) -> Tuple {
let object_point = self.transform.inverse() * world_point;
let object_normal = object_point - Tuple::point(0., 0., 0.);
let mut world_normal = self.transform.inverse().transpose() * object_normal;
world_normal.w = 0.;
world_normal.normalize()
}
pub fn transform(&self) -> Matrix4x4 {
self.transform