diff --git a/geometry/src/aabb.rs b/geometry/src/aabb.rs index bb2328f1..d6d56e49 100644 --- a/geometry/src/aabb.rs +++ b/geometry/src/aabb.rs @@ -54,6 +54,7 @@ impl Aabb { 8. * self.half_size.x * self.half_size.y * self.half_size.z } + #[must_use] pub fn translate(&self, delta: &Vector3) -> Aabb { Aabb { center: self.center + delta, @@ -61,6 +62,7 @@ impl Aabb { } } + #[must_use] pub fn enlarge(&self, delta: &Vector3) -> Aabb { Aabb { center: self.center, @@ -73,13 +75,11 @@ impl Aabb { let snd_half_axis = (self.max()[plane.axis] - plane.distance) / 2.; debug_assert!( fst_half_axis >= 0.0, - "fst_half_axis is negative {}", - fst_half_axis + "fst_half_axis is negative {fst_half_axis}", ); debug_assert!( snd_half_axis >= 0.0, - "snd_half_axis is negative {}", - snd_half_axis + "snd_half_axis is negative {snd_half_axis}", ); let mut fst_center = self.center; diff --git a/geometry/src/algorithms.rs b/geometry/src/algorithms.rs index ab4e6a3f..4bedd351 100644 --- a/geometry/src/algorithms.rs +++ b/geometry/src/algorithms.rs @@ -252,6 +252,10 @@ mod tests_intersect_triangle_ray { } pub fn intersect_triangle_aabb(triangle: &Triangle, aabb: &Aabb) -> bool { + const U0: Vector3 = Vector3::new(1., 0., 0.); + const U1: Vector3 = Vector3::new(0., 1., 0.); + const U2: Vector3 = Vector3::new(0., 0., 1.); + let v0 = triangle.v0 - aabb.center; let v1 = triangle.v1 - aabb.center; let v2 = triangle.v2 - aabb.center; @@ -260,10 +264,6 @@ pub fn intersect_triangle_aabb(triangle: &Triangle, aabb: &Aabb) -> bool { let f1 = v2 - v1; let f2 = v0 - v2; - const U0: Vector3 = Vector3::new(1., 0., 0.); - const U1: Vector3 = Vector3::new(0., 1., 0.); - const U2: Vector3 = Vector3::new(0., 0., 1.); - let test_axis = |axis: Vector3| { let p0 = v0.dot(&axis); let p1 = v1.dot(&axis); diff --git a/geometry/src/ray.rs b/geometry/src/ray.rs index 5693186e..4bb40d47 100644 --- a/geometry/src/ray.rs +++ b/geometry/src/ray.rs @@ -14,6 +14,7 @@ impl Ray { } } + #[must_use] pub fn extend(&self, t: f32) -> Ray { Ray { origin: self.origin, @@ -25,6 +26,7 @@ impl Ray { self.origin + t * self.direction } + #[must_use] pub fn reverse(&self) -> Ray { Ray { origin: self.origin + self.direction, diff --git a/kdtree/src/build_median.rs b/kdtree/src/build_median.rs index 5608fbd7..cd902d26 100644 --- a/kdtree/src/build_median.rs +++ b/kdtree/src/build_median.rs @@ -7,6 +7,8 @@ use geometry::{ triangle::Triangle, }; +use crate::split::ClippedTriangle; + use super::{ build::{KdBox, KdSplit, KdTreeBuilder}, split::{clip_triangle, split_and_partition}, @@ -47,7 +49,7 @@ impl KdTreeBuilder for MedianKdTreeBuilder { .collect::>(); let planes = clipped_triangles .iter() - .flat_map(|clipped| clipped.perfect_splits()) + .flat_map(ClippedTriangle::perfect_splits) .filter_map(|s| { (s.axis == axis && s.distance > min && s.distance < max).then_some(Aap { axis: s.axis, diff --git a/kdtree/src/build_sah.rs b/kdtree/src/build_sah.rs index 33b22213..2a5fcce5 100644 --- a/kdtree/src/build_sah.rs +++ b/kdtree/src/build_sah.rs @@ -89,7 +89,7 @@ impl KdTreeBuilder for SahKdTreeBuilder { .collect::>(); let mut splits = clipped_triangles .iter() - .flat_map(|clipped| clipped.perfect_splits()) + .flat_map(ClippedTriangle::perfect_splits) .collect::>(); splits.sort_unstable_by(PerfectSplit::total_cmp); splits.dedup(); diff --git a/kdtree/src/lib.rs b/kdtree/src/lib.rs index 638df3a5..c82c49c0 100644 --- a/kdtree/src/lib.rs +++ b/kdtree/src/lib.rs @@ -47,7 +47,7 @@ impl KdNode { impl Display for KdNode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - KdNode::Leaf(triangle_indices) => write!(f, "{:?}", triangle_indices), + KdNode::Leaf(triangle_indices) => write!(f, "{triangle_indices:?}"), KdNode::Node { plane, left, right } => { write!( f, diff --git a/pathtracer-cli/src/main.rs b/pathtracer-cli/src/main.rs index 007c10d1..7999da45 100644 --- a/pathtracer-cli/src/main.rs +++ b/pathtracer-cli/src/main.rs @@ -129,7 +129,7 @@ fn main() { .into_par_iter() .map(|i| worker_thread(i, &work, iterations_per_thread, &tx)); let printer = std::thread::spawn(move || printer_thread(args.threads, args.iterations, rx)); - let buffer = buffers.reduce_with(|a, b| a.add(b)).unwrap(); + let buffer = buffers.reduce_with(|a, b| a.add(&b)).unwrap(); tx.send(time::Duration::ZERO).unwrap(); printer.join().unwrap(); diff --git a/src/image_buffer.rs b/src/image_buffer.rs index 3690b7c1..5974bde9 100644 --- a/src/image_buffer.rs +++ b/src/image_buffer.rs @@ -2,12 +2,13 @@ use std::path::Path; pub struct ImageBuffer(image::ImageBuffer, Vec>); -fn gamma_correct(x: &f32) -> f32 { +fn gamma_correct(x: f32) -> f32 { const GAMMA_POWER: f32 = 1.0 / 2.2; 1.0f32.min(x.powf(GAMMA_POWER)) } impl ImageBuffer { + #[must_use] pub fn new(width: u32, height: u32) -> Self { ImageBuffer(image::ImageBuffer::new(width, height)) } @@ -23,6 +24,7 @@ impl ImageBuffer { self.0.height() } + #[must_use] pub fn div(&self, value: f32) -> Self { ImageBuffer( image::ImageBuffer::from_vec( @@ -34,7 +36,8 @@ impl ImageBuffer { ) } - pub fn add(&self, rhs: Self) -> Self { + #[must_use] + pub fn add(&self, rhs: &Self) -> Self { ImageBuffer( image::ImageBuffer::from_vec( self.0.width(), @@ -49,11 +52,11 @@ impl ImageBuffer { ) } - pub fn add_mut(&mut self, rhs: Self) { + pub fn add_mut(&mut self, rhs: &Self) { self.0 .iter_mut() .zip(rhs.0.iter()) - .for_each(|(a, b)| *a += *b) + .for_each(|(a, b)| *a += *b); } pub fn add_pixel_mut(&mut self, x: u32, y: u32, value: [f32; 3]) { @@ -62,12 +65,13 @@ impl ImageBuffer { self.0[(x, y)][2] += value[2]; } + #[must_use] pub fn gamma_correct(&self) -> Self { ImageBuffer( image::ImageBuffer::from_vec( self.0.width(), self.0.height(), - self.0.iter().map(gamma_correct).collect(), + self.0.iter().map(|x| gamma_correct(*x)).collect(), ) .unwrap(), ) diff --git a/src/light.rs b/src/light.rs index a0933f9c..e1625d15 100644 --- a/src/light.rs +++ b/src/light.rs @@ -1,7 +1,8 @@ -use crate::sampling::*; use nalgebra::Vector3; use rand::rngs::SmallRng; +use crate::sampling::uniform_sample_unit_sphere; + #[derive(Clone, Debug)] pub struct SphericalLight { pub center: Vector3, diff --git a/src/material.rs b/src/material.rs index 0de45d57..c6fcf324 100644 --- a/src/material.rs +++ b/src/material.rs @@ -1,7 +1,7 @@ -use crate::sampling::*; use nalgebra::{RealField, UnitVector3, Vector3}; -use rand::rngs::SmallRng; -use rand::Rng; +use rand::{rngs::SmallRng, Rng}; + +use crate::sampling::cosine_sample_hemisphere; fn perpendicular(v: &Vector3) -> Vector3 { if v.x.abs() < v.y.abs() { diff --git a/src/pathtracer.rs b/src/pathtracer.rs index 478a8b54..b281364f 100644 --- a/src/pathtracer.rs +++ b/src/pathtracer.rs @@ -1,8 +1,7 @@ -use crate::camera::*; -use crate::image_buffer::ImageBuffer; -use crate::raylogger::RayLoggerWithMeta; -use crate::sampling::*; -use crate::scene::*; +use crate::{ + camera::Pinhole, image_buffer::ImageBuffer, raylogger::RayLoggerWithMeta, + sampling::uniform_sample_unit_square, scene::Scene, +}; use geometry::ray::Ray; use nalgebra::{Vector2, Vector3}; use rand::rngs::SmallRng; @@ -15,7 +14,7 @@ fn trace_ray( _ray_logger: &mut RayLoggerWithMeta, max_bounces: u32, scene: &Scene, - ray: Ray, + ray: &Ray, accumulated_radiance: Vector3, accumulated_transport: Vector3, accumulated_bounces: u32, @@ -25,11 +24,11 @@ fn trace_ray( return accumulated_radiance; } - let intersection = scene.intersect(&ray, 0.0, std::f32::MAX); + let intersection = scene.intersect(ray, 0.0, std::f32::MAX); if intersection.is_none() { //_ray_logger.log(&ray.extend(10.0)).unwrap(); return accumulated_radiance - + accumulated_transport.component_mul(&environment_contribution(&ray)); + + accumulated_transport.component_mul(&environment_contribution(ray)); } let (triangle_index, intersection) = intersection.unwrap(); @@ -94,7 +93,7 @@ fn trace_ray( _ray_logger, max_bounces, scene, - next_ray, + &next_ray, accumulated_radiance, accumulated_transport, accumulated_bounces + 1, @@ -121,7 +120,7 @@ pub fn render( &mut logger, max_bounces, scene, - ray, + &ray, Vector3::zeros(), Vector3::new(1.0, 1.0, 1.0), 0, diff --git a/src/raytracer.rs b/src/raytracer.rs index cea41bda..ab0e5bbb 100644 --- a/src/raytracer.rs +++ b/src/raytracer.rs @@ -1,8 +1,7 @@ -use crate::camera::*; -use crate::image_buffer::ImageBuffer; -use crate::light::*; -use crate::material::*; -use crate::scene::*; +use crate::{ + camera::Pinhole, image_buffer::ImageBuffer, light::SphericalLight, material::Material, + scene::Scene, +}; use geometry::ray::Ray; use nalgebra::{UnitVector3, Vector2, Vector3}; diff --git a/src/scene.rs b/src/scene.rs index d5fcd4b5..e73d2369 100644 --- a/src/scene.rs +++ b/src/scene.rs @@ -1,10 +1,18 @@ -use crate::{camera::*, light::*, material::*}; use geometry::{algorithms::TriangleRayIntersection, ray::Ray, triangle::Triangle}; use kdtree::{build::build_kdtree, build_sah::SahKdTreeBuilder, KdTree}; use nalgebra::{UnitVector3, Vector2, Vector3}; use std::{collections::BTreeMap, sync::Arc}; use wavefront::{mtl, obj}; +use crate::{ + camera::Camera, + light::SphericalLight, + material::{ + BlendMaterial, DiffuseReflectiveMaterial, FresnelBlendMaterial, Material, + SpecularReflectiveMaterial, SpecularRefractiveMaterial, + }, +}; + #[derive(Clone, Debug, PartialEq)] pub struct TriangleNormals { pub n0: Vector3, @@ -104,11 +112,11 @@ fn triangle_materials_from_obj_and_mtl( obj: &obj::Obj, mtl: &mtl::Mtl, ) -> Vec> { - let materials = BTreeMap::from_iter( - mtl.materials - .iter() - .map(|m| (m.name.as_str(), blend_from_mtl(m))), - ); + let materials = mtl + .materials + .iter() + .map(|m| (m.name.as_str(), blend_from_mtl(m))) + .collect::>(); obj.chunks .iter() .flat_map(|chunk| { diff --git a/wavefront/src/mtl.rs b/wavefront/src/mtl.rs index 0a18ba61..69d7e4f8 100644 --- a/wavefront/src/mtl.rs +++ b/wavefront/src/mtl.rs @@ -84,45 +84,45 @@ pub fn mtl(input: &str) -> Mtl { } if let Ok((_, _)) = tagged("newlight", rest, line) { - lights.push(Default::default()) + lights.push(Light::default()); } else if let Ok((_, x)) = tagged("lightposition", vec3, line) { - lights.last_mut().unwrap().position = x + lights.last_mut().unwrap().position = x; } else if let Ok((_, x)) = tagged("lightcolor", vec3, line) { - lights.last_mut().unwrap().color = x + lights.last_mut().unwrap().color = x; } else if let Ok((_, x)) = tagged("lightradius", float, line) { - lights.last_mut().unwrap().radius = x + lights.last_mut().unwrap().radius = x; } else if let Ok((_, x)) = tagged("lightintensity", float, line) { - lights.last_mut().unwrap().intensity = x + lights.last_mut().unwrap().intensity = x; } else if let Ok((_, _)) = tagged("newcamera", rest, line) { - cameras.push(Default::default()) + cameras.push(Camera::default()); } else if let Ok((_, x)) = tagged("cameraposition", vec3, line) { - cameras.last_mut().unwrap().position = x + cameras.last_mut().unwrap().position = x; } else if let Ok((_, x)) = tagged("cameratarget", vec3, line) { - cameras.last_mut().unwrap().target = x + cameras.last_mut().unwrap().target = x; } else if let Ok((_, x)) = tagged("cameraup", vec3, line) { - cameras.last_mut().unwrap().up = x + cameras.last_mut().unwrap().up = x; } else if let Ok((_, x)) = tagged("camerafov", float, line) { - cameras.last_mut().unwrap().fov = x + cameras.last_mut().unwrap().fov = x; } else if let Ok((_, name)) = tagged("newmtl", rest, line) { materials.push(Material::new(name.to_string())); } else if let Ok((_, x)) = tagged("kd", vec3, line) { - materials.last_mut().unwrap().diffuse_reflection = x + materials.last_mut().unwrap().diffuse_reflection = x; } else if let Ok((_, x)) = tagged("ks", vec3, line) { - materials.last_mut().unwrap().specular_reflection = x + materials.last_mut().unwrap().specular_reflection = x; } else if let Ok((_, x)) = tagged("reflat0deg", float, line) { - materials.last_mut().unwrap().reflection_0_degrees = x + materials.last_mut().unwrap().reflection_0_degrees = x; } else if let Ok((_, x)) = tagged("reflat90deg", float, line) { - materials.last_mut().unwrap().reflection_90_degrees = x + materials.last_mut().unwrap().reflection_90_degrees = x; } else if let Ok((_, x)) = tagged("indexofrefraction", float, line) { - materials.last_mut().unwrap().index_of_refraction = x + materials.last_mut().unwrap().index_of_refraction = x; } else if let Ok((_, x)) = tagged("transparency", float, line) { - materials.last_mut().unwrap().transparency = x + materials.last_mut().unwrap().transparency = x; } else if let Ok((_, _)) = tagged("specularroughness", float, line) { // TODO: not supported } else if let Ok((_, _)) = tagged("map_kd", rest, line) { // TODO: not supported } else { - panic!("Unexpected line: \"{}\"", line) + panic!("Unexpected line: \"{line}\""); } } diff --git a/wavefront/src/obj.rs b/wavefront/src/obj.rs index 79e129bf..4d783236 100644 --- a/wavefront/src/obj.rs +++ b/wavefront/src/obj.rs @@ -119,23 +119,23 @@ pub fn obj(input: &str) -> Obj { } if let Ok((_, x)) = tagged("mtllib", rest, line) { - mtl_lib = Path::new(x) + mtl_lib = Path::new(x); } else if let Ok((_, x)) = tagged("usemtl", rest, line) { - chunks.push(Chunk::new(x.to_string())) + chunks.push(Chunk::new(x.to_string())); } else if let Ok((_, x)) = tagged("v", vec3, line) { - vertices.push(x) + vertices.push(x); } else if let Ok((_, x)) = tagged("vn", vec3, line) { - normals.push(x) + normals.push(x); } else if let Ok((_, x)) = tagged("vt", vec2, line) { - texcoords.push(x) + texcoords.push(x); } else if let Ok((_, x)) = tagged("f", triangle, line) { - chunks.last_mut().unwrap().faces.push(x) + chunks.last_mut().unwrap().faces.push(x); } else if let Ok((_, _)) = tagged("o", rest, line) { // TODO: not supported } else if let Ok((_, _)) = tagged("s", rest, line) { // TODO: not supported } else { - panic!("Unexpected line: \"{}\"", line) + panic!("Unexpected line: \"{line}\""); } }