Quick-and-dirty multithreading
Not the best multithreading scheme and needs error handling, but it works.
This commit is contained in:
parent
3618636c42
commit
e1de889d3a
|
|
@ -7,6 +7,8 @@ use super::raycasting::Ray;
|
||||||
use super::sampler::Sampler;
|
use super::sampler::Sampler;
|
||||||
use super::scene::Scene;
|
use super::scene::Scene;
|
||||||
|
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
struct ImageSampler<T: RealField> {
|
struct ImageSampler<T: RealField> {
|
||||||
image_height_pixels: u32,
|
image_height_pixels: u32,
|
||||||
image_width_pixels: u32,
|
image_width_pixels: u32,
|
||||||
|
|
@ -62,30 +64,23 @@ impl<T: RealField> ImageSampler<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_scene<T: RealField>(output_image: &mut ImageRgbF<T>, scene: &Scene<T>) {
|
pub fn render_scene<T: RealField>(output_image: Arc<Mutex<ImageRgbF<T>>>, scene: Arc<Scene<T>>) {
|
||||||
partial_render_scene(
|
let height = output_image.lock().unwrap().get_height();
|
||||||
output_image,
|
let width = output_image.lock().unwrap().get_width();
|
||||||
scene,
|
partial_render_scene(output_image, scene, 0, height, 0, width, height, width)
|
||||||
0,
|
|
||||||
output_image.get_height(),
|
|
||||||
0,
|
|
||||||
output_image.get_width(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn partial_render_scene<T: RealField>(
|
pub fn partial_render_scene<T: RealField>(
|
||||||
output_image: &mut ImageRgbF<T>,
|
output_image: Arc<Mutex<ImageRgbF<T>>>,
|
||||||
scene: &Scene<T>,
|
scene: Arc<Scene<T>>,
|
||||||
row_start: u32,
|
row_start: u32,
|
||||||
row_end: u32,
|
row_end: u32,
|
||||||
column_start: u32,
|
column_start: u32,
|
||||||
column_end: u32,
|
column_end: u32,
|
||||||
|
height: u32,
|
||||||
|
width: u32,
|
||||||
) {
|
) {
|
||||||
let image_sampler = ImageSampler::new(
|
let image_sampler = ImageSampler::new(width, height, scene.camera_location);
|
||||||
output_image.get_width(),
|
|
||||||
output_image.get_height(),
|
|
||||||
scene.camera_location,
|
|
||||||
);
|
|
||||||
let ambient_intensity: T = convert(0.0);
|
let ambient_intensity: T = convert(0.0);
|
||||||
let directional_intensity1: T = convert(7.0);
|
let directional_intensity1: T = convert(7.0);
|
||||||
let directional_intensity2: T = convert(3.0);
|
let directional_intensity2: T = convert(3.0);
|
||||||
|
|
@ -107,7 +102,7 @@ pub fn partial_render_scene<T: RealField>(
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
let sampler = Sampler { scene };
|
let sampler = Sampler { scene: &scene };
|
||||||
for column in column_start..column_end {
|
for column in column_start..column_end {
|
||||||
for row in row_start..row_end {
|
for row in row_start..row_end {
|
||||||
let ray = image_sampler.ray_for_pixel(row, column);
|
let ray = image_sampler.ray_for_pixel(row, column);
|
||||||
|
|
@ -116,7 +111,8 @@ pub fn partial_render_scene<T: RealField>(
|
||||||
None => ColourRgbF::from_named(NamedColour::Black),
|
None => ColourRgbF::from_named(NamedColour::Black),
|
||||||
Some(intersection_info) => integrator.integrate(&sampler, &intersection_info),
|
Some(intersection_info) => integrator.integrate(&sampler, &intersection_info),
|
||||||
};
|
};
|
||||||
output_image.set_colour(row, column, colour);
|
let mut locked_image = output_image.lock().unwrap();
|
||||||
|
locked_image.set_colour(row, column, colour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -126,7 +122,7 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::materials::LambertianMaterial;
|
use crate::materials::LambertianMaterial;
|
||||||
use crate::raycasting::{Intersect, IntersectionInfo, Plane};
|
use crate::raycasting::{Intersect, IntersectionInfo, Plane};
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod imagesampler {
|
mod imagesampler {
|
||||||
|
|
@ -151,7 +147,7 @@ mod tests {
|
||||||
let film_plane = Plane::new(
|
let film_plane = Plane::new(
|
||||||
Vector3::new(0.0, 0.0, 1.0),
|
Vector3::new(0.0, 0.0, 1.0),
|
||||||
target.film_distance,
|
target.film_distance,
|
||||||
Rc::new(LambertianMaterial::<f64>::new_dummy()),
|
Arc::new(LambertianMaterial::<f64>::new_dummy()),
|
||||||
);
|
);
|
||||||
let point_on_film_plane = match film_plane.intersect(&ray) {
|
let point_on_film_plane = match film_plane.intersect(&ray) {
|
||||||
Some(IntersectionInfo {
|
Some(IntersectionInfo {
|
||||||
|
|
|
||||||
75
src/main.rs
75
src/main.rs
|
|
@ -7,16 +7,18 @@ use std::time::Duration;
|
||||||
|
|
||||||
use nalgebra::{Point3, Vector3};
|
use nalgebra::{Point3, Vector3};
|
||||||
|
|
||||||
|
use itertools::iproduct;
|
||||||
|
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
use vanrijn::camera::partial_render_scene;
|
use vanrijn::camera::partial_render_scene;
|
||||||
use vanrijn::colour::{ColourRgbF, NamedColour};
|
use vanrijn::colour::{ColourRgbF, NamedColour};
|
||||||
use vanrijn::image::{ClampingToneMapper, ImageRgbF, ImageRgbU8, ToneMapper};
|
use vanrijn::image::{ClampingToneMapper, ImageRgbF, ImageRgbU8, ToneMapper};
|
||||||
use vanrijn::materials::{LambertianMaterial, PhongMaterial, ReflectiveMaterial};
|
use vanrijn::materials::{LambertianMaterial, PhongMaterial, ReflectiveMaterial};
|
||||||
use vanrijn::mesh::{load_obj, Triangle};
|
use vanrijn::mesh::load_obj;
|
||||||
use vanrijn::raycasting::{Intersect, Plane, Sphere};
|
use vanrijn::raycasting::{Intersect, Plane, Sphere};
|
||||||
use vanrijn::scene::Scene;
|
use vanrijn::scene::Scene;
|
||||||
|
|
||||||
|
|
@ -59,7 +61,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
image_width as u32,
|
image_width as u32,
|
||||||
image_height as u32,
|
image_height as u32,
|
||||||
)?;
|
)?;
|
||||||
let mut output_image = ImageRgbF::<f64>::new(image_width, image_height);
|
let output_image = Arc::new(Mutex::new(ImageRgbF::<f64>::new(image_width, image_height)));
|
||||||
|
|
||||||
let scene = Arc::new(Scene {
|
let scene = Arc::new(Scene {
|
||||||
camera_location: Point3::new(-2.0, 1.0, -5.0),
|
camera_location: Point3::new(-2.0, 1.0, -5.0),
|
||||||
|
|
@ -78,7 +80,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
Box::new(Plane::new(
|
Box::new(Plane::new(
|
||||||
Vector3::new(0.0, 1.0, 0.0),
|
Vector3::new(0.0, 1.0, 0.0),
|
||||||
-2.0,
|
-2.0,
|
||||||
Rc::new(LambertianMaterial {
|
Arc::new(LambertianMaterial {
|
||||||
colour: ColourRgbF::new(0.55, 0.27, 0.04),
|
colour: ColourRgbF::new(0.55, 0.27, 0.04),
|
||||||
diffuse_strength: 0.1,
|
diffuse_strength: 0.1,
|
||||||
}),
|
}),
|
||||||
|
|
@ -94,7 +96,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
Point3::new(-4.25, -0.5, 2.0),
|
Point3::new(-4.25, -0.5, 2.0),
|
||||||
1.0,
|
1.0,
|
||||||
Rc::new(ReflectiveMaterial {
|
Arc::new(ReflectiveMaterial {
|
||||||
colour: ColourRgbF::from_named(NamedColour::Blue),
|
colour: ColourRgbF::from_named(NamedColour::Blue),
|
||||||
diffuse_strength: 0.01,
|
diffuse_strength: 0.01,
|
||||||
reflection_strength: 0.99,
|
reflection_strength: 0.99,
|
||||||
|
|
@ -103,7 +105,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
Box::new(Sphere::new(
|
Box::new(Sphere::new(
|
||||||
Point3::new(-5.0, 1.5, 1.0),
|
Point3::new(-5.0, 1.5, 1.0),
|
||||||
1.0,
|
1.0,
|
||||||
Rc::new(PhongMaterial {
|
Arc::new(PhongMaterial {
|
||||||
colour: ColourRgbF::from_named(NamedColour::Red),
|
colour: ColourRgbF::from_named(NamedColour::Red),
|
||||||
diffuse_strength: 0.05,
|
diffuse_strength: 0.05,
|
||||||
smoothness: 100.0,
|
smoothness: 100.0,
|
||||||
|
|
@ -117,26 +119,49 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut event_pump = sdl_context.event_pump()?;
|
let mut event_pump = sdl_context.event_pump()?;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
'running: loop {
|
'running: loop {
|
||||||
let tile_size = 256;
|
let subtile_size = 16;
|
||||||
for tile_row in 0..=(output_image.get_height() + 1) / tile_size {
|
let tile_divisions = 4;
|
||||||
for tile_column in 0..=(output_image.get_width() + 1) / tile_size {
|
let tile_size = subtile_size * tile_divisions;
|
||||||
let row_start = tile_row * tile_size;
|
for tile_row in 0..=(image_height + 1) / tile_size {
|
||||||
let row_end = min(tile_row * tile_size + tile_size, output_image.get_height());
|
for tile_column in 0..=(image_width + 1) / tile_size {
|
||||||
let column_start = tile_column * tile_size;
|
//let row_start = tile_row * tile_size;
|
||||||
let column_end = min(
|
//let row_end = min(tile_row * tile_size + tile_size, image_height);
|
||||||
tile_column * tile_size + tile_size,
|
//let column_start = tile_column * tile_size;
|
||||||
output_image.get_width(),
|
//let column_end = min(tile_column * tile_size + tile_size, image_width);
|
||||||
);
|
let join_handles: Vec<_> = iproduct!(0..tile_divisions, 0..tile_divisions)
|
||||||
partial_render_scene(
|
.map(|(tile_i, tile_j)| {
|
||||||
&mut output_image,
|
let start_i = tile_row * tile_size + tile_i * subtile_size;
|
||||||
&scene,
|
let start_j = tile_column * tile_size + tile_j * subtile_size;
|
||||||
row_start,
|
(
|
||||||
row_end,
|
start_i,
|
||||||
column_start,
|
min(start_i + subtile_size, image_height),
|
||||||
column_end,
|
start_j,
|
||||||
);
|
min(start_j + subtile_size, image_width),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.map(|(i_min, i_max, j_min, j_max)| {
|
||||||
|
let image_ptr = output_image.clone();
|
||||||
|
let scene_ptr = scene.clone();
|
||||||
|
thread::spawn(move || {
|
||||||
|
partial_render_scene(
|
||||||
|
image_ptr,
|
||||||
|
scene_ptr,
|
||||||
|
i_min,
|
||||||
|
i_max,
|
||||||
|
j_min,
|
||||||
|
j_max,
|
||||||
|
image_height,
|
||||||
|
image_width,
|
||||||
|
);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
for h in join_handles {
|
||||||
|
h.join();
|
||||||
|
}
|
||||||
|
let locked_image = output_image.lock().unwrap();
|
||||||
let mut output_image_rgbu8 = ImageRgbU8::new(image_width, image_height);
|
let mut output_image_rgbu8 = ImageRgbU8::new(image_width, image_height);
|
||||||
ClampingToneMapper {}.apply_tone_mapping(&output_image, &mut output_image_rgbu8);
|
ClampingToneMapper {}.apply_tone_mapping(&locked_image, &mut output_image_rgbu8);
|
||||||
update_texture(&output_image_rgbu8, &mut rendered_image_texture);
|
update_texture(&output_image_rgbu8, &mut rendered_image_texture);
|
||||||
canvas.copy(&rendered_image_texture, None, None)?;
|
canvas.copy(&rendered_image_texture, None, None)?;
|
||||||
canvas.present();
|
canvas.present();
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,9 @@ use super::colour::{ColourRgbF, NamedColour};
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
type Bsdf<'a, T> =
|
type Bsdf<'a, T> = Box<dyn Fn(Vector3<T>, Vector3<T>, ColourRgbF<T>) -> ColourRgbF<T> + 'a>;
|
||||||
Box<dyn Fn(Vector3<T>, Vector3<T>, ColourRgbF<T>) -> ColourRgbF<T> + 'a>;
|
|
||||||
|
|
||||||
pub trait Material<T: RealField>: Debug {
|
pub trait Material<T: RealField>: Debug + Sync + Send {
|
||||||
fn bsdf<'a>(&'a self) -> Bsdf<'a, T>;
|
fn bsdf<'a>(&'a self) -> Bsdf<'a, T>;
|
||||||
|
|
||||||
fn sample(&self, _w_o: &Vector3<T>) -> Vec<Vector3<T>> {
|
fn sample(&self, _w_o: &Vector3<T>) -> Vec<Vector3<T>> {
|
||||||
|
|
|
||||||
32
src/mesh.rs
32
src/mesh.rs
|
|
@ -4,16 +4,16 @@ use obj::{IndexTuple, Obj, SimplePolygon};
|
||||||
use super::materials::Material;
|
use super::materials::Material;
|
||||||
use super::raycasting::{Intersect, IntersectionInfo, Ray};
|
use super::raycasting::{Intersect, IntersectionInfo, Ray};
|
||||||
|
|
||||||
use std::rc::Rc;
|
|
||||||
use alga::general::SupersetOf;
|
use alga::general::SupersetOf;
|
||||||
use std::io::Result;
|
use std::io::Result;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Triangle<T: RealField> {
|
pub struct Triangle<T: RealField> {
|
||||||
pub vertices: [Point3<T>; 3],
|
pub vertices: [Point3<T>; 3],
|
||||||
pub normals: [Vector3<T>; 3],
|
pub normals: [Vector3<T>; 3],
|
||||||
pub material: Rc<dyn Material<T>>,
|
pub material: Arc<dyn Material<T> >,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RealField> Intersect<T> for Triangle<T> {
|
impl<T: RealField> Intersect<T> for Triangle<T> {
|
||||||
|
|
@ -65,7 +65,7 @@ impl<T: RealField> Intersect<T> for Triangle<T> {
|
||||||
.normalize();
|
.normalize();
|
||||||
let tangent = cotangent.cross(&normal).normalize();
|
let tangent = cotangent.cross(&normal).normalize();
|
||||||
let retro = (ray.origin - location).normalize();
|
let retro = (ray.origin - location).normalize();
|
||||||
let material = Rc::clone(&self.material);
|
let material = Arc::clone(&self.material);
|
||||||
Some(IntersectionInfo {
|
Some(IntersectionInfo {
|
||||||
distance,
|
distance,
|
||||||
location,
|
location,
|
||||||
|
|
@ -373,7 +373,7 @@ mod tests {
|
||||||
Point3::new(-1.0, -1.0, 1.0),
|
Point3::new(-1.0, -1.0, 1.0),
|
||||||
],
|
],
|
||||||
normals: [Vector3::zeros(); 3],
|
normals: [Vector3::zeros(); 3],
|
||||||
material: Rc::new(LambertianMaterial::new_dummy()),
|
material: Arc::new(LambertianMaterial::new_dummy()),
|
||||||
};
|
};
|
||||||
let target_ray = Ray::new(Point3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 1.0));
|
let target_ray = Ray::new(Point3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 1.0));
|
||||||
if let None = target_triangle.intersect(&target_ray) {
|
if let None = target_triangle.intersect(&target_ray) {
|
||||||
|
|
@ -390,7 +390,7 @@ mod tests {
|
||||||
Point3::new(1.0, -1.0, 1.0),
|
Point3::new(1.0, -1.0, 1.0),
|
||||||
],
|
],
|
||||||
normals: [Vector3::zeros(); 3],
|
normals: [Vector3::zeros(); 3],
|
||||||
material: Rc::new(LambertianMaterial::new_dummy()),
|
material: Arc::new(LambertianMaterial::new_dummy()),
|
||||||
};
|
};
|
||||||
let target_ray = Ray::new(Point3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 1.0));
|
let target_ray = Ray::new(Point3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 1.0));
|
||||||
if let None = target_triangle.intersect(&target_ray) {
|
if let None = target_triangle.intersect(&target_ray) {
|
||||||
|
|
@ -407,7 +407,7 @@ mod tests {
|
||||||
Point3::new(-1.0, -1.0, -1.0),
|
Point3::new(-1.0, -1.0, -1.0),
|
||||||
],
|
],
|
||||||
normals: [Vector3::zeros(); 3],
|
normals: [Vector3::zeros(); 3],
|
||||||
material: Rc::new(LambertianMaterial::new_dummy()),
|
material: Arc::new(LambertianMaterial::new_dummy()),
|
||||||
};
|
};
|
||||||
let target_ray = Ray::new(Point3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, -1.0));
|
let target_ray = Ray::new(Point3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, -1.0));
|
||||||
if let None = target_triangle.intersect(&target_ray) {
|
if let None = target_triangle.intersect(&target_ray) {
|
||||||
|
|
@ -424,7 +424,7 @@ mod tests {
|
||||||
Point3::new(1.0, -1.0, -1.0),
|
Point3::new(1.0, -1.0, -1.0),
|
||||||
],
|
],
|
||||||
normals: [Vector3::zeros(); 3],
|
normals: [Vector3::zeros(); 3],
|
||||||
material: Rc::new(LambertianMaterial::new_dummy()),
|
material: Arc::new(LambertianMaterial::new_dummy()),
|
||||||
};
|
};
|
||||||
let target_ray = Ray::new(Point3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, -1.0));
|
let target_ray = Ray::new(Point3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, -1.0));
|
||||||
if let None = target_triangle.intersect(&target_ray) {
|
if let None = target_triangle.intersect(&target_ray) {
|
||||||
|
|
@ -441,7 +441,7 @@ mod tests {
|
||||||
Point3::new(4.0, 4.0, 6.0),
|
Point3::new(4.0, 4.0, 6.0),
|
||||||
],
|
],
|
||||||
normals: [Vector3::zeros(); 3],
|
normals: [Vector3::zeros(); 3],
|
||||||
material: Rc::new(LambertianMaterial::new_dummy()),
|
material: Arc::new(LambertianMaterial::new_dummy()),
|
||||||
};
|
};
|
||||||
let target_ray = Ray::new(Point3::new(5.0, 5.0, 5.0), Vector3::new(0.0, 0.0, 1.0));
|
let target_ray = Ray::new(Point3::new(5.0, 5.0, 5.0), Vector3::new(0.0, 0.0, 1.0));
|
||||||
if let None = target_triangle.intersect(&target_ray) {
|
if let None = target_triangle.intersect(&target_ray) {
|
||||||
|
|
@ -458,7 +458,7 @@ mod tests {
|
||||||
Point3::new(5.0, 4.5, 6.0),
|
Point3::new(5.0, 4.5, 6.0),
|
||||||
],
|
],
|
||||||
normals: [Vector3::zeros(); 3],
|
normals: [Vector3::zeros(); 3],
|
||||||
material: Rc::new(LambertianMaterial::new_dummy()),
|
material: Arc::new(LambertianMaterial::new_dummy()),
|
||||||
};
|
};
|
||||||
let target_ray = Ray::new(Point3::new(5.0, 5.0, 5.0), Vector3::new(1.0, 0.5, 1.0));
|
let target_ray = Ray::new(Point3::new(5.0, 5.0, 5.0), Vector3::new(1.0, 0.5, 1.0));
|
||||||
if let None = target_triangle.intersect(&target_ray) {
|
if let None = target_triangle.intersect(&target_ray) {
|
||||||
|
|
@ -492,7 +492,7 @@ mod tests {
|
||||||
Point3::from(vertex2),
|
Point3::from(vertex2),
|
||||||
],
|
],
|
||||||
normals: [normal; 3],
|
normals: [normal; 3],
|
||||||
material: Rc::new(LambertianMaterial::new_dummy()),
|
material: Arc::new(LambertianMaterial::new_dummy()),
|
||||||
};
|
};
|
||||||
let ray = Ray::new(ray_origin, ray_direction);
|
let ray = Ray::new(ray_origin, ray_direction);
|
||||||
|
|
||||||
|
|
@ -523,7 +523,7 @@ mod tests {
|
||||||
Point3::from(vertex2),
|
Point3::from(vertex2),
|
||||||
],
|
],
|
||||||
normals: [normal; 3],
|
normals: [normal; 3],
|
||||||
material: Rc::new(LambertianMaterial::new_dummy()),
|
material: Arc::new(LambertianMaterial::new_dummy()),
|
||||||
};
|
};
|
||||||
let ray = Ray::new(ray_origin, ray_direction);
|
let ray = Ray::new(ray_origin, ray_direction);
|
||||||
|
|
||||||
|
|
@ -668,7 +668,7 @@ mod tests {
|
||||||
Point3::from(vertex2),
|
Point3::from(vertex2),
|
||||||
],
|
],
|
||||||
normals: [normal; 3],
|
normals: [normal; 3],
|
||||||
material: Rc::new(LambertianMaterial::new_dummy()),
|
material: Arc::new(LambertianMaterial::new_dummy()),
|
||||||
};
|
};
|
||||||
let ray = Ray::new(ray_origin, ray_direction);
|
let ray = Ray::new(ray_origin, ray_direction);
|
||||||
|
|
||||||
|
|
@ -795,7 +795,7 @@ mod tests {
|
||||||
let triangle = Triangle {
|
let triangle = Triangle {
|
||||||
vertices: [vertex0, vertex1, vertex2],
|
vertices: [vertex0, vertex1, vertex2],
|
||||||
normals: [Vector3::zeros(); 3],
|
normals: [Vector3::zeros(); 3],
|
||||||
material: Rc::new(LambertianMaterial::new_dummy()),
|
material: Arc::new(LambertianMaterial::new_dummy()),
|
||||||
};
|
};
|
||||||
match triangle.intersect(&ray) {
|
match triangle.intersect(&ray) {
|
||||||
Some(_) => false,
|
Some(_) => false,
|
||||||
|
|
@ -823,7 +823,7 @@ mod tests {
|
||||||
let triangle = Triangle {
|
let triangle = Triangle {
|
||||||
vertices: [vertex0, vertex1, vertex2],
|
vertices: [vertex0, vertex1, vertex2],
|
||||||
normals: [Vector3::zeros(); 3],
|
normals: [Vector3::zeros(); 3],
|
||||||
material: Rc::new(LambertianMaterial::new_dummy()),
|
material: Arc::new(LambertianMaterial::new_dummy()),
|
||||||
};
|
};
|
||||||
match triangle.intersect(&ray) {
|
match triangle.intersect(&ray) {
|
||||||
Some(_) => false,
|
Some(_) => false,
|
||||||
|
|
@ -851,7 +851,7 @@ mod tests {
|
||||||
let triangle = Triangle {
|
let triangle = Triangle {
|
||||||
vertices: [vertex0, vertex1, vertex2],
|
vertices: [vertex0, vertex1, vertex2],
|
||||||
normals: [Vector3::zeros(); 3],
|
normals: [Vector3::zeros(); 3],
|
||||||
material: Rc::new(LambertianMaterial::new_dummy()),
|
material: Arc::new(LambertianMaterial::new_dummy()),
|
||||||
};
|
};
|
||||||
match triangle.intersect(&ray) {
|
match triangle.intersect(&ray) {
|
||||||
Some(_) => false,
|
Some(_) => false,
|
||||||
|
|
@ -877,7 +877,7 @@ mod tests {
|
||||||
let triangle = Triangle {
|
let triangle = Triangle {
|
||||||
vertices: [vertex0, vertex1, vertex2],
|
vertices: [vertex0, vertex1, vertex2],
|
||||||
normals: [Vector3::zeros(); 3],
|
normals: [Vector3::zeros(); 3],
|
||||||
material: Rc::new(LambertianMaterial::new_dummy()),
|
material: Arc::new(LambertianMaterial::new_dummy()),
|
||||||
};
|
};
|
||||||
match triangle.intersect(&ray) {
|
match triangle.intersect(&ray) {
|
||||||
Some(_) => false,
|
Some(_) => false,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use nalgebra::{convert, Point3, RealField, Vector3};
|
||||||
|
|
||||||
use super::materials::Material;
|
use super::materials::Material;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Ray<T: RealField> {
|
pub struct Ray<T: RealField> {
|
||||||
|
|
@ -35,21 +35,21 @@ pub struct IntersectionInfo<T: RealField> {
|
||||||
pub tangent: Vector3<T>,
|
pub tangent: Vector3<T>,
|
||||||
pub cotangent: Vector3<T>,
|
pub cotangent: Vector3<T>,
|
||||||
pub retro: Vector3<T>,
|
pub retro: Vector3<T>,
|
||||||
pub material: Rc<dyn Material<T>>,
|
pub material: Arc<dyn Material<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Intersect<T: RealField> {
|
pub trait Intersect<T: RealField>: Send + Sync {
|
||||||
fn intersect<'a>(&'a self, ray: &Ray<T>) -> Option<IntersectionInfo<T>>;
|
fn intersect<'a>(&'a self, ray: &Ray<T>) -> Option<IntersectionInfo<T>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Sphere<T: RealField> {
|
pub struct Sphere<T: RealField> {
|
||||||
centre: Point3<T>,
|
centre: Point3<T>,
|
||||||
radius: T,
|
radius: T,
|
||||||
material: Rc<dyn Material<T>>,
|
material: Arc<dyn Material<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RealField> Sphere<T> {
|
impl<T: RealField> Sphere<T> {
|
||||||
pub fn new(centre: Point3<T>, radius: T, material: Rc<dyn Material<T>>) -> Sphere<T> {
|
pub fn new(centre: Point3<T>, radius: T, material: Arc<dyn Material<T>>) -> Sphere<T> {
|
||||||
Sphere {
|
Sphere {
|
||||||
centre,
|
centre,
|
||||||
radius,
|
radius,
|
||||||
|
|
@ -142,7 +142,7 @@ impl<T: RealField> Intersect<T> for Sphere<T> {
|
||||||
tangent,
|
tangent,
|
||||||
cotangent,
|
cotangent,
|
||||||
retro,
|
retro,
|
||||||
material: Rc::clone(&self.material),
|
material: Arc::clone(&self.material),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -154,14 +154,14 @@ pub struct Plane<T: RealField> {
|
||||||
tangent: Vector3<T>,
|
tangent: Vector3<T>,
|
||||||
cotangent: Vector3<T>,
|
cotangent: Vector3<T>,
|
||||||
distance_from_origin: T,
|
distance_from_origin: T,
|
||||||
material: Rc<dyn Material<T>>,
|
material: Arc<dyn Material<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RealField> Plane<T> {
|
impl<T: RealField> Plane<T> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
normal: Vector3<T>,
|
normal: Vector3<T>,
|
||||||
distance_from_origin: T,
|
distance_from_origin: T,
|
||||||
material: Rc<dyn Material<T>>,
|
material: Arc<dyn Material<T>>,
|
||||||
) -> Plane<T> {
|
) -> Plane<T> {
|
||||||
normal.normalize();
|
normal.normalize();
|
||||||
let mut axis_closest_to_tangent = Vector3::zeros();
|
let mut axis_closest_to_tangent = Vector3::zeros();
|
||||||
|
|
@ -202,7 +202,7 @@ impl<T: RealField> Intersect<T> for Plane<T> {
|
||||||
tangent: self.tangent,
|
tangent: self.tangent,
|
||||||
cotangent: self.cotangent,
|
cotangent: self.cotangent,
|
||||||
retro: -ray.direction,
|
retro: -ray.direction,
|
||||||
material: Rc::clone(&self.material),
|
material: Arc::clone(&self.material),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -266,7 +266,7 @@ mod tests {
|
||||||
let s = Sphere::new(
|
let s = Sphere::new(
|
||||||
Point3::new(1.5, 1.5, 15.0),
|
Point3::new(1.5, 1.5, 15.0),
|
||||||
5.0,
|
5.0,
|
||||||
Rc::new(LambertianMaterial::new_dummy()),
|
Arc::new(LambertianMaterial::new_dummy()),
|
||||||
);
|
);
|
||||||
assert_matches!(s.intersect(&r), Some(_));
|
assert_matches!(s.intersect(&r), Some(_));
|
||||||
}
|
}
|
||||||
|
|
@ -277,7 +277,7 @@ mod tests {
|
||||||
let s = Sphere::new(
|
let s = Sphere::new(
|
||||||
Point3::new(-5.0, 1.5, 15.0),
|
Point3::new(-5.0, 1.5, 15.0),
|
||||||
5.0,
|
5.0,
|
||||||
Rc::new(LambertianMaterial::new_dummy()),
|
Arc::new(LambertianMaterial::new_dummy()),
|
||||||
);
|
);
|
||||||
assert_matches!(s.intersect(&r), None);
|
assert_matches!(s.intersect(&r), None);
|
||||||
}
|
}
|
||||||
|
|
@ -288,7 +288,7 @@ mod tests {
|
||||||
let s = Sphere::new(
|
let s = Sphere::new(
|
||||||
Point3::new(1.5, 1.5, -15.0),
|
Point3::new(1.5, 1.5, -15.0),
|
||||||
5.0,
|
5.0,
|
||||||
Rc::new(LambertianMaterial::new_dummy()),
|
Arc::new(LambertianMaterial::new_dummy()),
|
||||||
);
|
);
|
||||||
assert_matches!(s.intersect(&r), None);
|
assert_matches!(s.intersect(&r), None);
|
||||||
}
|
}
|
||||||
|
|
@ -299,7 +299,7 @@ mod tests {
|
||||||
let s = Sphere::new(
|
let s = Sphere::new(
|
||||||
Point3::new(1.5, 1.5, 2.0),
|
Point3::new(1.5, 1.5, 2.0),
|
||||||
5.0,
|
5.0,
|
||||||
Rc::new(LambertianMaterial::new_dummy()),
|
Arc::new(LambertianMaterial::new_dummy()),
|
||||||
);
|
);
|
||||||
assert_matches!(s.intersect(&r), Some(_));
|
assert_matches!(s.intersect(&r), Some(_));
|
||||||
}
|
}
|
||||||
|
|
@ -316,7 +316,7 @@ mod tests {
|
||||||
let sphere = Sphere::new(
|
let sphere = Sphere::new(
|
||||||
sphere_centre,
|
sphere_centre,
|
||||||
radius,
|
radius,
|
||||||
Rc::new(LambertianMaterial::new_dummy()),
|
Arc::new(LambertianMaterial::new_dummy()),
|
||||||
);
|
);
|
||||||
let ray = Ray::new(ray_origin, sphere_centre - ray_origin);
|
let ray = Ray::new(ray_origin, sphere_centre - ray_origin);
|
||||||
let info = sphere.intersect(&ray).unwrap();
|
let info = sphere.intersect(&ray).unwrap();
|
||||||
|
|
@ -332,7 +332,7 @@ mod tests {
|
||||||
let p = Plane::new(
|
let p = Plane::new(
|
||||||
Vector3::new(1.0, 0.0, 0.0),
|
Vector3::new(1.0, 0.0, 0.0),
|
||||||
-5.0,
|
-5.0,
|
||||||
Rc::new(LambertianMaterial::new_dummy()),
|
Arc::new(LambertianMaterial::new_dummy()),
|
||||||
);
|
);
|
||||||
assert_matches!(p.intersect(&r), Some(_));
|
assert_matches!(p.intersect(&r), Some(_));
|
||||||
}
|
}
|
||||||
|
|
@ -343,7 +343,7 @@ mod tests {
|
||||||
let p = Plane::new(
|
let p = Plane::new(
|
||||||
Vector3::new(1.0, 0.0, 0.0),
|
Vector3::new(1.0, 0.0, 0.0),
|
||||||
-5.0,
|
-5.0,
|
||||||
Rc::new(LambertianMaterial::new_dummy()),
|
Arc::new(LambertianMaterial::new_dummy()),
|
||||||
);
|
);
|
||||||
assert_matches!(p.intersect(&r), None);
|
assert_matches!(p.intersect(&r), None);
|
||||||
}
|
}
|
||||||
|
|
@ -354,7 +354,7 @@ mod tests {
|
||||||
let p = Plane::new(
|
let p = Plane::new(
|
||||||
Vector3::new(1.0, 0.0, 0.0),
|
Vector3::new(1.0, 0.0, 0.0),
|
||||||
-5.0,
|
-5.0,
|
||||||
Rc::new(LambertianMaterial::new_dummy()),
|
Arc::new(LambertianMaterial::new_dummy()),
|
||||||
);
|
);
|
||||||
match p.intersect(&r) {
|
match p.intersect(&r) {
|
||||||
Some(IntersectionInfo {
|
Some(IntersectionInfo {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue