diff --git a/Cargo.lock b/Cargo.lock index 05972c1..07be021 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,7 +1,3 @@ -[root] -name = "spectra_xyz" -version = "0.1.0" - [[package]] name = "ansi_term" version = "0.9.0" @@ -207,6 +203,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "sobol" version = "0.1.0" +[[package]] +name = "spectra_xyz" +version = "0.1.0" + [[package]] name = "strsim" version = "0.6.0" diff --git a/src/accel/bvh.rs b/src/accel/bvh.rs index ee5406b..65423f6 100644 --- a/src/accel/bvh.rs +++ b/src/accel/bvh.rs @@ -15,7 +15,6 @@ use super::bvh_base::{BVHBase, BVHBaseNode, BVH_MAX_DEPTH}; use super::ACCEL_TRAV_TIME; use super::ACCEL_NODE_RAY_TESTS; - #[derive(Copy, Clone, Debug)] pub struct BVH<'a> { root: Option<&'a BVHNode<'a>>, @@ -175,10 +174,8 @@ impl<'a> BVH<'a> { } => { let mut node = unsafe { arena.alloc_uninitialized_with_alignment::(32) }; - let bounds = arena.copy_slice_with_alignment( - &base.bounds[bounds_range.0..bounds_range.1], - 32, - ); + let bounds = arena + .copy_slice_with_alignment(&base.bounds[bounds_range.0..bounds_range.1], 32); let child1 = BVH::construct_from_base(arena, base, children_indices.0); let child2 = BVH::construct_from_base(arena, base, children_indices.1); @@ -219,20 +216,18 @@ impl<'a> Boundable for BVH<'a> { fn bounds(&self) -> &[BBox] { match self.root { None => &DEGENERATE_BOUNDS[..], - Some(root) => { - match *root { - BVHNode::Internal { - bounds_start, - bounds_len, - .. - } | - BVHNode::Leaf { - bounds_start, - bounds_len, - .. - } => unsafe { std::slice::from_raw_parts(bounds_start, bounds_len as usize) }, + Some(root) => match *root { + BVHNode::Internal { + bounds_start, + bounds_len, + .. } - } + | BVHNode::Leaf { + bounds_start, + bounds_len, + .. + } => unsafe { std::slice::from_raw_parts(bounds_start, bounds_len as usize) }, + }, } } } diff --git a/src/accel/bvh4.rs b/src/accel/bvh4.rs index d2e5012..f94e4dd 100644 --- a/src/accel/bvh4.rs +++ b/src/accel/bvh4.rs @@ -11,12 +11,11 @@ use lerp::lerp_slice; use ray::AccelRay; use timer::Timer; -use bvh_order::{TRAVERSAL_TABLE, SplitAxes, calc_traversal_code}; +use bvh_order::{calc_traversal_code, SplitAxes, TRAVERSAL_TABLE}; use super::bvh_base::{BVHBase, BVHBaseNode, BVH_MAX_DEPTH}; use super::ACCEL_TRAV_TIME; use super::ACCEL_NODE_RAY_TESTS; - #[derive(Copy, Clone, Debug)] pub struct BVH4<'a> { root: Option<&'a BVH4Node<'a>>, @@ -88,8 +87,8 @@ impl<'a> BVH4<'a> { rays[0].dir_inv.y() < 0.0, rays[0].dir_inv.z() < 0.0, ]; - let ray_code = ray_sign_is_neg[0] as usize + ((ray_sign_is_neg[1] as usize) << 1) + - ((ray_sign_is_neg[2] as usize) << 2); + let ray_code = ray_sign_is_neg[0] as usize + ((ray_sign_is_neg[1] as usize) << 1) + + ((ray_sign_is_neg[2] as usize) << 2); &TRAVERSAL_TABLE[ray_code] }; @@ -271,10 +270,8 @@ impl<'a> BVH4<'a> { } // Copy bounds - let bounds = arena.copy_slice_with_alignment( - &base.bounds[bounds_range.0..bounds_range.1], - 32, - ); + let bounds = arena + .copy_slice_with_alignment(&base.bounds[bounds_range.0..bounds_range.1], 32); // Build children let mut children_mem = unsafe { @@ -317,20 +314,18 @@ impl<'a> Boundable for BVH4<'a> { fn bounds(&self) -> &[BBox] { match self.root { None => &DEGENERATE_BOUNDS[..], - Some(root) => { - match *root { - BVH4Node::Inner { - bounds_start, - bounds_len, - .. - } | - BVH4Node::Leaf { - bounds_start, - bounds_len, - .. - } => unsafe { std::slice::from_raw_parts(bounds_start, bounds_len as usize) }, + Some(root) => match *root { + BVH4Node::Inner { + bounds_start, + bounds_len, + .. } - } + | BVH4Node::Leaf { + bounds_start, + bounds_len, + .. + } => unsafe { std::slice::from_raw_parts(bounds_start, bounds_len as usize) }, + }, } } } diff --git a/src/accel/bvh_base.rs b/src/accel/bvh_base.rs index acf2112..60593f5 100644 --- a/src/accel/bvh_base.rs +++ b/src/accel/bvh_base.rs @@ -5,8 +5,7 @@ use bbox::BBox; use lerp::lerp_slice; use math::log2_64; -use super::objects_split::{sah_split, median_split}; - +use super::objects_split::{median_split, sah_split}; pub const BVH_MAX_DEPTH: usize = 42; @@ -41,8 +40,9 @@ pub enum BVHBaseNode { impl BVHBaseNode { pub fn bounds_range(&self) -> (usize, usize) { match *self { - BVHBaseNode::Internal { bounds_range, .. } | - BVHBaseNode::Leaf { bounds_range, .. } => bounds_range, + BVHBaseNode::Internal { bounds_range, .. } | BVHBaseNode::Leaf { bounds_range, .. } => { + bounds_range + } } } } @@ -119,13 +119,13 @@ impl BVHBase { // We make sure that it's worth having multiple time samples, and if not // we reduce to the union of the time samples. self.acc_bounds(objects, bounder); - let union_bounds = self.bounds_cache.iter().fold( - BBox::new(), - |b1, b2| (b1 | *b2), - ); - let average_area = self.bounds_cache.iter().fold(0.0, |area, bb| { - area + bb.surface_area() - }) / self.bounds_cache.len() as f32; + let union_bounds = self.bounds_cache + .iter() + .fold(BBox::new(), |b1, b2| (b1 | *b2)); + let average_area = self.bounds_cache + .iter() + .fold(0.0, |area, bb| area + bb.surface_area()) + / self.bounds_cache.len() as f32; if union_bounds.surface_area() <= (average_area * USE_UNION_FACTOR) { self.bounds.push(union_bounds); } else { @@ -195,8 +195,8 @@ impl BVHBase { // We make sure that it's worth having multiple time samples, and if not // we reduce to the union of the time samples. let union_bounds = merged.iter().fold(BBox::new(), |b1, b2| (b1 | *b2)); - let average_area = merged.iter().fold(0.0, |area, bb| area + bb.surface_area()) / - merged.len() as f32; + let average_area = merged.iter().fold(0.0, |area, bb| area + bb.surface_area()) + / merged.len() as f32; if union_bounds.surface_area() <= (average_area * USE_UNION_FACTOR) { self.bounds.push(union_bounds); } else { @@ -204,7 +204,6 @@ impl BVHBase { } } - // Set node self.nodes[me] = BVHBaseNode::Internal { bounds_range: (bi, self.bounds.len()), diff --git a/src/accel/light_array.rs b/src/accel/light_array.rs index 307e4b7..7625820 100644 --- a/src/accel/light_array.rs +++ b/src/accel/light_array.rs @@ -1,7 +1,7 @@ use mem_arena::MemArena; use bbox::BBox; -use math::{Vector, Point, Normal}; +use math::{Normal, Point, Vector}; use shading::surface_closure::SurfaceClosure; use super::LightAccel; diff --git a/src/accel/light_tree.rs b/src/accel/light_tree.rs index 9c1a713..caa7471 100644 --- a/src/accel/light_tree.rs +++ b/src/accel/light_tree.rs @@ -3,18 +3,17 @@ use mem_arena::MemArena; use algorithm::merge_slices_append; use bbox::BBox; use lerp::lerp_slice; -use math::{Vector, Point, Normal}; +use math::{Normal, Point, Vector}; use shading::surface_closure::SurfaceClosure; use super::LightAccel; use super::objects_split::sah_split; const ARITY_LOG2: usize = 3; // Determines how much to collapse the binary tree, -// implicitly defining the light tree's arity. 1 = no collapsing, leave as binary -// tree. + // implicitly defining the light tree's arity. 1 = no collapsing, leave as binary + // tree. const ARITY: usize = 1 << ARITY_LOG2; // Arity of the final tree - #[derive(Copy, Clone, Debug)] pub struct LightTree<'a> { root: Option<&'a Node<'a>>, @@ -38,15 +37,13 @@ enum Node<'a> { impl<'a> Node<'a> { fn bounds(&self) -> &'a [BBox] { match *self { - Node::Inner { bounds, .. } | - Node::Leaf { bounds, .. } => bounds, + Node::Inner { bounds, .. } | Node::Leaf { bounds, .. } => bounds, } } fn energy(&self) -> f32 { match *self { - Node::Inner { energy, .. } | - Node::Leaf { energy, .. } => energy, + Node::Inner { energy, .. } | Node::Leaf { energy, .. } => energy, } } @@ -127,7 +124,6 @@ impl<'a> LightTree<'a> { } } - impl<'a> LightAccel for LightTree<'a> { fn select( &self, @@ -210,7 +206,6 @@ impl<'a> LightAccel for LightTree<'a> { } } - struct LightTreeBuilder { nodes: Vec, bounds: Vec, diff --git a/src/accel/mod.rs b/src/accel/mod.rs index f2dd5e0..8619543 100644 --- a/src/accel/mod.rs +++ b/src/accel/mod.rs @@ -7,10 +7,10 @@ mod objects_split; use std::cell::Cell; -use math::{Vector, Point, Normal}; +use math::{Normal, Point, Vector}; use shading::surface_closure::SurfaceClosure; -pub use self::bvh::{BVH, BVHNode}; +pub use self::bvh::{BVHNode, BVH}; pub use self::bvh4::{BVH4, BVH4Node}; pub use self::light_tree::LightTree; pub use self::light_array::LightArray; diff --git a/src/accel/objects_split.rs b/src/accel/objects_split.rs index 6e6895b..9c50506 100644 --- a/src/accel/objects_split.rs +++ b/src/accel/objects_split.rs @@ -8,14 +8,12 @@ use halton; use algorithm::{partition, quick_select}; use bbox::BBox; use lerp::lerp_slice; -use math::{Vector, dot}; +use math::{dot, Vector}; use sampling::uniform_sample_hemisphere; - const SAH_BIN_COUNT: usize = 13; // Prime numbers work best, for some reason const SPLIT_PLANE_COUNT: usize = 5; - /// Takes a slice of boundable objects and partitions them based on the Surface /// Area Heuristic, but using arbitrarily oriented planes. /// @@ -66,8 +64,8 @@ where // Build SAH bins let sah_bins = { - let mut sah_bins = [[(BBox::new(), BBox::new(), 0, 0); SAH_BIN_COUNT - 1]; - SPLIT_PLANE_COUNT]; + let mut sah_bins = + [[(BBox::new(), BBox::new(), 0, 0); SAH_BIN_COUNT - 1]; SPLIT_PLANE_COUNT]; for obj in objects.iter() { let tb = lerp_slice(bounder(obj), 0.5); let centroid = tb.center().into_vector(); @@ -148,7 +146,6 @@ where (split_i, approx_axis) } - /// Takes a slice of boundable objects and partitions them based on the Surface /// Area Heuristic. /// @@ -288,7 +285,6 @@ where (split_i, split_axis) } - /// Takes a slice of boundable objects and partitions them based on the median heuristic. /// /// Returns the index of the partition boundary and the axis that it split on @@ -321,7 +317,11 @@ where let place = { let place = objects.len() / 2; - if place > 0 { place } else { 1 } + if place > 0 { + place + } else { + 1 + } }; quick_select(objects, place, |a, b| { let tb_a = lerp_slice(bounder(a), 0.5); diff --git a/src/algorithm.rs b/src/algorithm.rs index 95495a8..7db1a75 100644 --- a/src/algorithm.rs +++ b/src/algorithm.rs @@ -5,8 +5,7 @@ use std::cmp; use std::cmp::Ordering; use hash::hash_u64; -use lerp::{Lerp, lerp_slice}; - +use lerp::{lerp_slice, Lerp}; /// Selects an item from a slice based on a weighting function and a /// number (n) between 0.0 and 1.0. Returns the index of the selected @@ -33,7 +32,6 @@ where unreachable!() } - /// Partitions a slice in-place with the given unary predicate, returning /// the index of the first element for which the predicate evaluates /// false. @@ -129,7 +127,6 @@ where } } - /// Partitions two slices in-place in concert based on the given unary /// predicate, returning the index of the first element for which the /// predicate evaluates false. @@ -167,8 +164,7 @@ where ((a1 as usize) - start) / std::mem::size_of::(), &mut *a1, &mut *a2, - ) - { + ) { break; } a1 = a1.offset(1); @@ -185,8 +181,7 @@ where ((b1 as usize) - start) / std::mem::size_of::(), &mut *b1, &mut *b2, - ) - { + ) { break; } } @@ -214,11 +209,10 @@ where let i = left + (hash_u64(right as u64, seed) as usize % (right - left)); slc.swap(i, right - 1); - let ii = left + - { - let (val, list) = (&mut slc[left..right]).split_last_mut().unwrap(); - partition(list, |n| order(n, val) == Ordering::Less) - }; + let ii = left + { + let (val, list) = (&mut slc[left..right]).split_last_mut().unwrap(); + partition(list, |n| order(n, val) == Ordering::Less) + }; slc.swap(ii, right - 1); if ii == n { @@ -276,12 +270,10 @@ where if slice1.is_empty() || slice2.is_empty() { return; } else if slice1.len() == slice2.len() { - for (xfo, (xf1, xf2)) in - Iterator::zip( - slice_out.iter_mut(), - Iterator::zip(slice1.iter(), slice2.iter()), - ) - { + for (xfo, (xf1, xf2)) in Iterator::zip( + slice_out.iter_mut(), + Iterator::zip(slice1.iter(), slice2.iter()), + ) { *xfo = merge(xf1, xf2); } } else if slice1.len() > slice2.len() { @@ -305,12 +297,14 @@ mod tests { use super::*; fn quick_select_ints(list: &mut [i32], i: usize) { - quick_select(list, i, |a, b| if a < b { - Ordering::Less - } else if a == b { - Ordering::Equal - } else { - Ordering::Greater + quick_select(list, i, |a, b| { + if a < b { + Ordering::Less + } else if a == b { + Ordering::Equal + } else { + Ordering::Greater + } }); } diff --git a/src/bbox.rs b/src/bbox.rs index 9b9c99f..2a677c8 100644 --- a/src/bbox.rs +++ b/src/bbox.rs @@ -5,10 +5,9 @@ use std::iter::Iterator; use std::ops::{BitOr, BitOrAssign}; use lerp::{lerp, lerp_slice, Lerp}; -use math::{Point, Matrix4x4, fast_minf32}; +use math::{Matrix4x4, Point, fast_minf32}; use ray::AccelRay; - const BBOX_MAXT_ADJUST: f32 = 1.00000024; /// A 3D axis-aligned bounding box. @@ -98,15 +97,18 @@ impl BBox { } } - /// Union of two `BBox`es. impl BitOr for BBox { type Output = BBox; fn bitor(self, rhs: BBox) -> BBox { BBox::from_points( - Point { co: self.min.co.v_min(rhs.min.co) }, - Point { co: self.max.co.v_max(rhs.max.co) }, + Point { + co: self.min.co.v_min(rhs.min.co), + }, + Point { + co: self.max.co.v_max(rhs.max.co), + }, ) } } @@ -123,8 +125,12 @@ impl BitOr for BBox { fn bitor(self, rhs: Point) -> BBox { BBox::from_points( - Point { co: self.min.co.v_min(rhs.co) }, - Point { co: self.max.co.v_max(rhs.co) }, + Point { + co: self.min.co.v_min(rhs.co), + }, + Point { + co: self.max.co.v_max(rhs.co), + }, ) } } @@ -135,7 +141,6 @@ impl BitOrAssign for BBox { } } - impl Lerp for BBox { fn lerp(self, other: BBox, alpha: f32) -> BBox { BBox { @@ -145,7 +150,6 @@ impl Lerp for BBox { } } - pub fn transform_bbox_slice_from(bbs_in: &[BBox], xforms: &[Matrix4x4], bbs_out: &mut Vec) { bbs_out.clear(); diff --git a/src/boundable.rs b/src/boundable.rs index 0dc0485..9be6859 100644 --- a/src/boundable.rs +++ b/src/boundable.rs @@ -2,7 +2,6 @@ use bbox::BBox; - pub trait Boundable { fn bounds(&self) -> &[BBox]; } diff --git a/src/camera.rs b/src/camera.rs index 1701674..f115b93 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -3,11 +3,10 @@ use mem_arena::MemArena; use lerp::lerp_slice; -use math::{Vector, Point, Matrix4x4}; +use math::{Matrix4x4, Point, Vector}; use ray::Ray; use sampling::square_to_circle; - #[derive(Copy, Clone, Debug)] pub struct Camera<'a> { transforms: &'a [Matrix4x4], @@ -36,12 +35,12 @@ impl<'a> Camera<'a> { if aperture_radii.is_empty() && !focus_distances.is_empty() { println!( "WARNING: camera has aperture radius but no focus distance. Disabling \ - focal blur." + focal blur." ); } else if !aperture_radii.is_empty() && focus_distances.is_empty() { println!( "WARNING: camera has focus distance but no aperture radius. Disabling \ - focal blur." + focal blur." ); } } diff --git a/src/color.rs b/src/color.rs index dbcd241..c2756f7 100644 --- a/src/color.rs +++ b/src/color.rs @@ -1,4 +1,4 @@ -use std::ops::{Add, AddAssign, Mul, MulAssign, Div, DivAssign}; +use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign}; use spectra_xyz::{spectrum_xyz_to_p, EQUAL_ENERGY_REFLECTANCE}; @@ -6,8 +6,7 @@ use float4::Float4; use lerp::Lerp; use math::fast_exp; -pub use color_util::{xyz_to_rec709, xyz_to_rec709_e, rec709_to_xyz, rec709_e_to_xyz}; - +pub use color_util::{rec709_e_to_xyz, rec709_to_xyz, xyz_to_rec709, xyz_to_rec709_e}; // Minimum and maximum wavelength of light we care about, in nanometers const WL_MIN: f32 = 380.0; @@ -38,7 +37,11 @@ pub trait Color { fn nth_wavelength(hero_wavelength: f32, n: usize) -> f32 { let wl = hero_wavelength + (WL_RANGE_Q * n as f32); - if wl > WL_MAX { wl - WL_RANGE } else { wl } + if wl > WL_MAX { + wl - WL_RANGE + } else { + wl + } } //---------------------------------------------------------------- @@ -78,7 +81,11 @@ impl SpectralSample { /// Returns the nth wavelength fn wl_n(&self, n: usize) -> f32 { let wl = self.hero_wavelength + (WL_RANGE_Q * n as f32); - if wl > WL_MAX { wl - WL_RANGE } else { wl } + if wl > WL_MAX { + wl - WL_RANGE + } else { + wl + } } } @@ -278,8 +285,8 @@ pub fn x_1931(wavelength: f32) -> f32 { let t1 = (wavelength - 442.0) * (if wavelength < 442.0 { 0.0624 } else { 0.0374 }); let t2 = (wavelength - 599.8) * (if wavelength < 599.8 { 0.0264 } else { 0.0323 }); let t3 = (wavelength - 501.1) * (if wavelength < 501.1 { 0.0490 } else { 0.0382 }); - (0.362 * fast_exp(-0.5 * t1 * t1)) + (1.056 * fast_exp(-0.5 * t2 * t2)) - - (0.065 * fast_exp(-0.5 * t3 * t3)) + (0.362 * fast_exp(-0.5 * t1 * t1)) + (1.056 * fast_exp(-0.5 * t2 * t2)) + - (0.065 * fast_exp(-0.5 * t3 * t3)) } pub fn y_1931(wavelength: f32) -> f32 { diff --git a/src/fp_utils.rs b/src/fp_utils.rs index c2ee8f9..0665e1d 100644 --- a/src/fp_utils.rs +++ b/src/fp_utils.rs @@ -3,7 +3,7 @@ //! This is based on the work in section 3.9 of "Physically Based Rendering: //! From Theory to Implementation" 3rd edition by Pharr et al. -use math::{Point, Vector, Normal, dot}; +use math::{dot, Normal, Point, Vector}; #[inline(always)] pub fn fp_gamma(n: u32) -> f32 { @@ -12,7 +12,6 @@ pub fn fp_gamma(n: u32) -> f32 { (e * n as f32) / (1.0 - (e * n as f32)) } - pub fn increment_ulp(v: f32) -> f32 { // Handle special cases if (v.is_infinite() && v > 0.0) || v.is_nan() { @@ -30,7 +29,6 @@ pub fn increment_ulp(v: f32) -> f32 { } } - pub fn decrement_ulp(v: f32) -> f32 { // Handle special cases if (v.is_infinite() && v < 0.0) || v.is_nan() { @@ -53,7 +51,11 @@ pub fn robust_ray_origin(pos: Point, pos_err: f32, nor: Normal, ray_dir: Vector) // direction as ray_dir. let nor = { let nor = nor.into_vector(); - if dot(nor, ray_dir) >= 0.0 { nor } else { -nor } + if dot(nor, ray_dir) >= 0.0 { + nor + } else { + -nor + } }; // Calculate offset point @@ -83,7 +85,6 @@ pub fn robust_ray_origin(pos: Point, pos_err: f32, nor: Normal, ray_dir: Vector) Point::new(x, y, z) } - #[inline(always)] fn f32_to_bits(v: f32) -> u32 { use std::mem::transmute_copy; @@ -96,7 +97,6 @@ fn bits_to_f32(bits: u32) -> f32 { unsafe { transmute_copy::(&bits) } } - #[cfg(test)] mod tests { use super::*; diff --git a/src/hilbert.rs b/src/hilbert.rs index 67932a7..c8b1bcd 100644 --- a/src/hilbert.rs +++ b/src/hilbert.rs @@ -39,7 +39,6 @@ pub fn xy2d(x: u32, y: u32) -> u32 { d } - /// Convert hilbert curve index to (x,y). /// /// d: The hilbert curve index. diff --git a/src/image.rs b/src/image.rs index d5241d5..7868301 100644 --- a/src/image.rs +++ b/src/image.rs @@ -14,8 +14,7 @@ use half::f16; use png_encode_mini; use openexr; -use color::{XYZ, xyz_to_rec709_e}; - +use color::{xyz_to_rec709_e, XYZ}; #[derive(Debug)] pub struct Image { @@ -260,8 +259,8 @@ impl<'a> Drop for Bucket<'a> { // Find matching bucket and remove it let i = bucket_list.iter().position(|bucket| { - (bucket.0).0 == self.min.0 && (bucket.0).1 == self.min.1 && - (bucket.1).0 == self.max.0 && (bucket.1).1 == self.max.1 + (bucket.0).0 == self.min.0 && (bucket.0).1 == self.min.1 && (bucket.1).0 == self.max.0 + && (bucket.1).1 == self.max.1 }); bucket_list.swap_remove(i.unwrap()); } diff --git a/src/lerp.rs b/src/lerp.rs index cfa0747..7d8cfd7 100644 --- a/src/lerp.rs +++ b/src/lerp.rs @@ -8,7 +8,6 @@ pub trait Lerp { fn lerp(self, other: Self, alpha: f32) -> Self; } - /// Interpolates between two instances of a Lerp types. pub fn lerp(a: T, b: T, alpha: f32) -> T { debug_assert!(alpha >= 0.0); @@ -17,7 +16,6 @@ pub fn lerp(a: T, b: T, alpha: f32) -> T { a.lerp(b, alpha) } - /// Interpolates a slice of data as if each adjecent pair of elements /// represent a linear segment. pub fn lerp_slice(s: &[T], alpha: f32) -> T { @@ -58,7 +56,6 @@ where } } - impl Lerp for f32 { fn lerp(self, other: f32, alpha: f32) -> f32 { (self * (1.0 - alpha)) + (other * alpha) @@ -103,23 +100,22 @@ impl Lerp for Normal { } } - impl Lerp for Point { fn lerp(self, other: Point, alpha: f32) -> Point { let s = self.norm(); let o = other.norm(); - Point { co: (s.co * (1.0 - alpha)) + (o.co * alpha) } + Point { + co: (s.co * (1.0 - alpha)) + (o.co * alpha), + } } } - impl Lerp for Vector { fn lerp(self, other: Vector, alpha: f32) -> Vector { (self * (1.0 - alpha)) + (other * alpha) } } - #[cfg(test)] mod tests { use super::*; diff --git a/src/light/distant_disk_light.rs b/src/light/distant_disk_light.rs index e42ff76..3ddec1d 100644 --- a/src/light/distant_disk_light.rs +++ b/src/light/distant_disk_light.rs @@ -2,9 +2,9 @@ use std::f64::consts::PI as PI_64; use mem_arena::MemArena; -use color::{XYZ, SpectralSample, Color}; +use color::{Color, SpectralSample, XYZ}; use lerp::lerp_slice; -use math::{Vector, coordinate_system_from_vector}; +use math::{coordinate_system_from_vector, Vector}; use sampling::{uniform_sample_cone, uniform_sample_cone_pdf}; use super::WorldLightSource; @@ -87,10 +87,10 @@ impl<'a> WorldLightSource for DistantDiskLight<'a> { } fn approximate_energy(&self) -> f32 { - let color: XYZ = self.colors.iter().fold( - XYZ::new(0.0, 0.0, 0.0), - |a, &b| a + b, - ) / self.colors.len() as f32; + let color: XYZ = self.colors + .iter() + .fold(XYZ::new(0.0, 0.0, 0.0), |a, &b| a + b) + / self.colors.len() as f32; color.y } } diff --git a/src/light/mod.rs b/src/light/mod.rs index 643dbce..dc199a0 100644 --- a/src/light/mod.rs +++ b/src/light/mod.rs @@ -5,14 +5,13 @@ mod sphere_light; use std::fmt::Debug; use color::SpectralSample; -use math::{Vector, Normal, Point, Matrix4x4}; +use math::{Matrix4x4, Normal, Point, Vector}; use surface::Surface; pub use self::distant_disk_light::DistantDiskLight; pub use self::rectangle_light::RectangleLight; pub use self::sphere_light::SphereLight; - /// A finite light source that can be bounded in space. pub trait SurfaceLight: Surface { /// Samples the surface given a point to be illuminated. @@ -40,7 +39,6 @@ pub trait SurfaceLight: Surface { time: f32, ) -> (SpectralSample, (Point, Normal, f32), f32); - /// Returns whether the light has a delta distribution. /// /// If a light has no chance of a ray hitting it through random process @@ -48,7 +46,6 @@ pub trait SurfaceLight: Surface { /// lights that only emit in a single direction, etc. fn is_delta(&self) -> bool; - /// Returns an approximation of the total energy emitted by the surface. /// /// Note: this does not need to be exact, but it does need to be non-zero @@ -57,7 +54,6 @@ pub trait SurfaceLight: Surface { fn approximate_energy(&self) -> f32; } - /// An infinite light source that cannot be bounded in space. E.g. /// a sun light source. pub trait WorldLightSource: Debug + Sync { @@ -78,7 +74,6 @@ pub trait WorldLightSource: Debug + Sync { time: f32, ) -> (SpectralSample, Vector, f32); - /// Returns whether the light has a delta distribution. /// /// If a light has no chance of a ray hitting it through random process @@ -86,7 +81,6 @@ pub trait WorldLightSource: Debug + Sync { /// lights that only emit in a single direction, etc. fn is_delta(&self) -> bool; - /// Returns an approximation of the total energy emitted by the light /// source. /// diff --git a/src/light/rectangle_light.rs b/src/light/rectangle_light.rs index 33f8a3f..343b187 100644 --- a/src/light/rectangle_light.rs +++ b/src/light/rectangle_light.rs @@ -2,22 +2,20 @@ use mem_arena::MemArena; use bbox::BBox; use boundable::Boundable; -use color::{XYZ, SpectralSample, Color}; +use color::{Color, SpectralSample, XYZ}; use lerp::lerp_slice; -use math::{Vector, Normal, Point, Matrix4x4, cross, dot}; -use ray::{Ray, AccelRay}; -use sampling::{spherical_triangle_solid_angle, uniform_sample_spherical_triangle, - triangle_surface_area, uniform_sample_triangle}; -use shading::surface_closure::{SurfaceClosureUnion, EmitClosure}; +use math::{cross, dot, Matrix4x4, Normal, Point, Vector}; +use ray::{AccelRay, Ray}; +use sampling::{spherical_triangle_solid_angle, triangle_surface_area, + uniform_sample_spherical_triangle, uniform_sample_triangle}; +use shading::surface_closure::{EmitClosure, SurfaceClosureUnion}; use shading::SurfaceShader; -use surface::{Surface, SurfaceIntersection, SurfaceIntersectionData, triangle}; +use surface::{triangle, Surface, SurfaceIntersection, SurfaceIntersectionData}; use super::SurfaceLight; - const SIMPLE_SAMPLING_THRESHOLD: f32 = 0.01; - #[derive(Copy, Clone, Debug)] pub struct RectangleLight<'a> { dimensions: &'a [(f32, f32)], @@ -33,11 +31,9 @@ impl<'a> RectangleLight<'a> { ) -> RectangleLight<'b> { let bbs: Vec<_> = dimensions .iter() - .map(|d| { - BBox { - min: Point::new(d.0 * -0.5, d.1 * -0.5, 0.0), - max: Point::new(d.0 * 0.5, d.1 * 0.5, 0.0), - } + .map(|d| BBox { + min: Point::new(d.0 * -0.5, d.1 * -0.5, 0.0), + max: Point::new(d.0 * 0.5, d.1 * 0.5, 0.0), }) .collect(); RectangleLight { @@ -87,9 +83,9 @@ impl<'a> RectangleLight<'a> { // PDF if (area_1 + area_2) < SIMPLE_SAMPLING_THRESHOLD { let area = triangle_surface_area(p2, p1, p3) + triangle_surface_area(p4, p1, p3); - (hit_point - arr).length2() / - dot(sample_dir.normalized(), normal.into_vector().normalized()).abs() / - area + (hit_point - arr).length2() + / dot(sample_dir.normalized(), normal.into_vector().normalized()).abs() + / area } else { 1.0 / (area_1 + area_2) } @@ -188,9 +184,9 @@ impl<'a> SurfaceLight for RectangleLight<'a> { let shadow_vec = sample_point - arr; let spectral_sample = (col * surface_area_inv as f32 * 0.5).to_spectral_sample(wavelength); - let pdf = (sample_point - arr).length2() / - dot(shadow_vec.normalized(), normal.into_vector().normalized()).abs() / - (surface_area_1 + surface_area_2); + let pdf = (sample_point - arr).length2() + / dot(shadow_vec.normalized(), normal.into_vector().normalized()).abs() + / (surface_area_1 + surface_area_2); let point_err = 0.0001; // TODO: this is a hack, do properly. (spectral_sample, (sample_point, normal, point_err), pdf) } else { @@ -246,15 +242,14 @@ impl<'a> SurfaceLight for RectangleLight<'a> { } fn approximate_energy(&self) -> f32 { - let color: XYZ = self.colors.iter().fold( - XYZ::new(0.0, 0.0, 0.0), - |a, &b| a + b, - ) / self.colors.len() as f32; + let color: XYZ = self.colors + .iter() + .fold(XYZ::new(0.0, 0.0, 0.0), |a, &b| a + b) + / self.colors.len() as f32; color.y } } - impl<'a> Surface for RectangleLight<'a> { fn intersect_rays( &self, @@ -313,9 +308,9 @@ impl<'a> Surface for RectangleLight<'a> { let closure = { let inv_surface_area = (1.0 / (dim.0 as f64 * dim.1 as f64)) as f32; - let color = lerp_slice(self.colors, r.time).to_spectral_sample( - wr.wavelength, - ) * inv_surface_area; + let color = lerp_slice(self.colors, r.time) + .to_spectral_sample(wr.wavelength) + * inv_surface_area; SurfaceClosureUnion::EmitClosure(EmitClosure::new(color)) }; diff --git a/src/light/sphere_light.rs b/src/light/sphere_light.rs index afeea9a..93fbcb5 100644 --- a/src/light/sphere_light.rs +++ b/src/light/sphere_light.rs @@ -4,12 +4,12 @@ use mem_arena::MemArena; use bbox::BBox; use boundable::Boundable; -use color::{XYZ, SpectralSample, Color}; +use color::{Color, SpectralSample, XYZ}; use lerp::lerp_slice; -use math::{Vector, Normal, Point, Matrix4x4, dot, coordinate_system_from_vector}; -use ray::{Ray, AccelRay}; +use math::{coordinate_system_from_vector, dot, Matrix4x4, Normal, Point, Vector}; +use ray::{AccelRay, Ray}; use sampling::{uniform_sample_cone, uniform_sample_cone_pdf, uniform_sample_sphere}; -use shading::surface_closure::{SurfaceClosureUnion, EmitClosure}; +use shading::surface_closure::{EmitClosure, SurfaceClosureUnion}; use shading::SurfaceShader; use surface::{Surface, SurfaceIntersection, SurfaceIntersectionData}; @@ -32,11 +32,9 @@ impl<'a> SphereLight<'a> { pub fn new<'b>(arena: &'b MemArena, radii: Vec, colors: Vec) -> SphereLight<'b> { let bbs: Vec<_> = radii .iter() - .map(|r| { - BBox { - min: Point::new(-*r, -*r, -*r), - max: Point::new(*r, *r, *r), - } + .map(|r| BBox { + min: Point::new(-*r, -*r, -*r), + max: Point::new(*r, *r, *r), }) .collect(); SphereLight { @@ -81,7 +79,6 @@ impl<'a> SphereLight<'a> { } } - impl<'a> SurfaceLight for SphereLight<'a> { fn sample_from_point( &self, @@ -197,15 +194,14 @@ impl<'a> SurfaceLight for SphereLight<'a> { } fn approximate_energy(&self) -> f32 { - let color: XYZ = self.colors.iter().fold( - XYZ::new(0.0, 0.0, 0.0), - |a, &b| a + b, - ) / self.colors.len() as f32; + let color: XYZ = self.colors + .iter() + .fold(XYZ::new(0.0, 0.0, 0.0), |a, &b| a + b) + / self.colors.len() as f32; color.y } } - impl<'a> Surface for SphereLight<'a> { fn intersect_rays( &self, @@ -260,7 +256,8 @@ impl<'a> Surface for SphereLight<'a> { // Get our final parametric values let mut t0 = q / a; - let mut t1 = if q != 0.0 { c / q } else { r.max_t }; + let mut t1 = + if q != 0.0 { c / q } else { r.max_t }; // Swap them so they are ordered right if t0 > t1 { @@ -323,11 +320,10 @@ impl<'a> Surface for SphereLight<'a> { }; let closure = { - let inv_surface_area = (1.0 / (4.0 * PI_64 * radius as f64 * radius as f64)) as - f32; - let color = lerp_slice(self.colors, r.time).to_spectral_sample( - wr.wavelength, - ) * inv_surface_area; + let inv_surface_area = + (1.0 / (4.0 * PI_64 * radius as f64 * radius as f64)) as f32; + let color = lerp_slice(self.colors, r.time).to_spectral_sample(wr.wavelength) + * inv_surface_area; SurfaceClosureUnion::EmitClosure(EmitClosure::new(color)) }; @@ -344,7 +340,6 @@ impl<'a> Surface for SphereLight<'a> { } } - impl<'a> Boundable for SphereLight<'a> { fn bounds(&self) -> &[BBox] { self.bounds_ diff --git a/src/main.rs b/src/main.rs index f74c6e5..303dfc2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -68,16 +68,13 @@ use clap::{App, Arg}; use mem_arena::MemArena; use parse::{parse_scene, DataTree}; -use ray::{Ray, AccelRay}; +use ray::{AccelRay, Ray}; use surface::SurfaceIntersection; use renderer::LightPath; use bbox::BBox; -use accel::{BVHNode, BVH4Node}; +use accel::{BVH4Node, BVHNode}; use timer::Timer; - - - const VERSION: &'static str = env!("CARGO_PKG_VERSION"); fn main() { @@ -104,10 +101,9 @@ fn main() { .help("Number of samples per pixel") .takes_value(true) .validator(|s| { - usize::from_str(&s).and(Ok(())).or(Err( - "must be an integer" - .to_string(), - )) + usize::from_str(&s) + .and(Ok(())) + .or(Err("must be an integer".to_string())) }), ) .arg( @@ -115,15 +111,12 @@ fn main() { .short("b") .long("spb") .value_name("N") - .help( - "Target number of samples per bucket (determines bucket size)", - ) + .help("Target number of samples per bucket (determines bucket size)") .takes_value(true) .validator(|s| { - usize::from_str(&s).and(Ok(())).or(Err( - "must be an integer" - .to_string(), - )) + usize::from_str(&s) + .and(Ok(())) + .or(Err("must be an integer".to_string())) }), ) .arg( @@ -132,15 +125,14 @@ fn main() { .value_name("X1 Y1 X2 Y2") .help( "Only render the image between pixel coordinates (X1, Y1) \ - and (X2, Y2). Coordinates are zero-indexed and inclusive.", + and (X2, Y2). Coordinates are zero-indexed and inclusive.", ) .takes_value(true) .number_of_values(4) .validator(|s| { - usize::from_str(&s).and(Ok(())).or(Err( - "must be four integers" - .to_string(), - )) + usize::from_str(&s) + .and(Ok(())) + .or(Err("must be four integers".to_string())) }), ) .arg( @@ -150,22 +142,25 @@ fn main() { .value_name("N") .help( "Number of threads to render with. Defaults to the number of logical \ - cores on the system.", + cores on the system.", ) .takes_value(true) .validator(|s| { - usize::from_str(&s).and(Ok(())).or(Err( - "must be an integer" - .to_string(), - )) + usize::from_str(&s) + .and(Ok(())) + .or(Err("must be an integer".to_string())) }), ) - .arg(Arg::with_name("stats").long("stats").help( - "Print additional statistics about rendering", - )) - .arg(Arg::with_name("dev").long("dev").help( - "Show useful dev/debug info.", - )) + .arg( + Arg::with_name("stats") + .long("stats") + .help("Print additional statistics about rendering"), + ) + .arg( + Arg::with_name("dev") + .long("dev") + .help("Show useful dev/debug info."), + ) .arg( Arg::with_name("serialized_output") .long("serialized_output") @@ -213,9 +208,7 @@ fn main() { // Parse data tree of scene file if !args.is_present("serialized_output") { - println!( - "Parsing scene file...", - ); + println!("Parsing scene file...",); } t.tick(); let psy_contents = if args.is_present("use_stdin") { @@ -225,9 +218,9 @@ fn main() { let mut stdin = tmp.lock(); let mut buf = vec![0u8; 4096]; loop { - let count = stdin.read(&mut buf).expect( - "Unexpected end of scene input.", - ); + let count = stdin + .read(&mut buf) + .expect("Unexpected end of scene input."); let start = if input.len() < 11 { 0 } else { @@ -238,8 +231,7 @@ fn main() { let mut done = false; let mut trunc_len = 0; - if let nom::IResult::Done(remaining, _) = - take_until!(&input[start..end], "__PSY_EOF__") + if let nom::IResult::Done(remaining, _) = take_until!(&input[start..end], "__PSY_EOF__") { done = true; trunc_len = input.len() - remaining.len(); @@ -344,9 +336,9 @@ fn main() { if !args.is_present("serialized_output") { println!("Writing image to disk into '{}'...", r.output_file); if r.output_file.ends_with(".png") { - image.write_png(Path::new(&r.output_file)).expect( - "Failed to write png...", - ); + image + .write_png(Path::new(&r.output_file)) + .expect("Failed to write png..."); } else if r.output_file.ends_with(".exr") { image.write_exr(Path::new(&r.output_file)); } else { diff --git a/src/math.rs b/src/math.rs index 0b2bfd0..dea460d 100644 --- a/src/math.rs +++ b/src/math.rs @@ -2,8 +2,7 @@ use std::f32; -pub use math3d::{Matrix4x4, Normal, Point, Vector, DotProduct, dot, CrossProduct, cross}; - +pub use math3d::{cross, dot, CrossProduct, DotProduct, Matrix4x4, Normal, Point, Vector}; /// Clamps a value between a min and max. pub fn clamp(v: T, lower: T, upper: T) -> T { @@ -18,12 +17,20 @@ pub fn clamp(v: T, lower: T, upper: T) -> T { // The stdlib min function is slower than a simple if statement for some reason. pub fn fast_minf32(a: f32, b: f32) -> f32 { - if a < b { a } else { b } + if a < b { + a + } else { + b + } } // The stdlib max function is slower than a simple if statement for some reason. pub fn fast_maxf32(a: f32, b: f32) -> f32 { - if a > b { a } else { b } + if a > b { + a + } else { + b + } } /// Rounds an integer up to the next power of two. @@ -119,7 +126,6 @@ pub fn fast_logit(p: f32, width: f32) -> f32 { fast_ln(n / (1.0 - n)) * width * (0.6266 / 4.0) } - //---------------------------------------------------------------- // Adapted to Rust from https://code.google.com/archive/p/fastapprox/ @@ -139,9 +145,9 @@ pub fn fast_pow2(p: f32) -> f32 { let w: i32 = clipp as i32; let z: f32 = clipp - w as f32 + offset; - let i: u32 = ((1 << 23) as f32 * - (clipp + 121.2740575 + 27.7280233 / (4.84252568 - z) - 1.49012907 * z)) as - u32; + let i: u32 = ((1 << 23) as f32 + * (clipp + 121.2740575 + 27.7280233 / (4.84252568 - z) - 1.49012907 * z)) + as u32; unsafe { transmute_copy::(&i) } } @@ -177,11 +183,9 @@ pub fn faster_exp(p: f32) -> f32 { faster_pow2(f32::consts::LOG2_E * p) } - // End of adapted code //---------------------------------------------------------------- - #[cfg(test)] mod tests { use super::*; diff --git a/src/parse/basics.rs b/src/parse/basics.rs index 2722348..00a13b9 100644 --- a/src/parse/basics.rs +++ b/src/parse/basics.rs @@ -3,10 +3,9 @@ use std::str; -use nom::{IResult, Needed, digit, multispace}; +use nom::{digit, multispace, IResult, Needed}; use nom::IResult::*; - // Parsers for numbers surrounded by whitespace named!(pub ws_u32, delimited!(opt!(multispace), u32_utf8, opt!(multispace))); named!(pub ws_u64, delimited!(opt!(multispace), u64_utf8, opt!(multispace))); @@ -17,9 +16,6 @@ named!(pub ws_isize, delimited!(opt!(multispace), isize_utf8, opt!(multis named!(pub ws_f32, delimited!(opt!(multispace), f32_utf8, opt!(multispace))); named!(pub ws_f64, delimited!(opt!(multispace), f64_utf8, opt!(multispace))); - - - // ======================================================== named!(pub u32_utf8, chain!( @@ -131,9 +127,6 @@ fn take_decimal_real(i: &[u8]) -> IResult<&[u8], &[u8]> { } } - - - // ======================================================== #[cfg(test)] diff --git a/src/parse/data_tree.rs b/src/parse/data_tree.rs index 5bc73e8..0a1ba00 100644 --- a/src/parse/data_tree.rs +++ b/src/parse/data_tree.rs @@ -4,7 +4,6 @@ use std::iter::Iterator; use std::result::Result; use std::slice; - #[derive(Debug, Eq, PartialEq)] pub enum DataTree<'a> { Internal { @@ -21,7 +20,6 @@ pub enum DataTree<'a> { }, } - impl<'a> DataTree<'a> { pub fn from_str(source_text: &'a str) -> Result, ParseError> { let mut items = Vec::new(); @@ -49,15 +47,15 @@ impl<'a> DataTree<'a> { pub fn type_name(&'a self) -> &'a str { match *self { - DataTree::Internal { type_name, .. } | - DataTree::Leaf { type_name, .. } => type_name, + DataTree::Internal { type_name, .. } | DataTree::Leaf { type_name, .. } => type_name, } } pub fn byte_offset(&'a self) -> usize { match *self { - DataTree::Internal { byte_offset, .. } | - DataTree::Leaf { byte_offset, .. } => byte_offset, + DataTree::Internal { byte_offset, .. } | DataTree::Leaf { byte_offset, .. } => { + byte_offset + } } } @@ -166,7 +164,6 @@ impl<'a> DataTree<'a> { } } - /// An iterator over the children of a `DataTree` node that filters out the /// children not matching a specified type name. pub struct DataTreeFilterIter<'a> { @@ -192,7 +189,6 @@ impl<'a> Iterator for DataTreeFilterIter<'a> { } } - /// An iterator over the children of a `DataTree` node that filters out the /// children that aren't internal nodes and that don't match a specified /// type name. @@ -208,11 +204,11 @@ impl<'a> Iterator for DataTreeFilterInternalIter<'a> { loop { match self.iter.next() { Some(&DataTree::Internal { - type_name, - ident, - ref children, - byte_offset, - }) => { + type_name, + ident, + ref children, + byte_offset, + }) => { if type_name == self.type_name { return Some((type_name, ident, children, byte_offset)); } else { @@ -232,7 +228,6 @@ impl<'a> Iterator for DataTreeFilterInternalIter<'a> { } } - /// An iterator over the children of a `DataTree` node that filters out the /// children that aren't internal nodes and that don't match a specified /// type name. @@ -252,10 +247,10 @@ impl<'a> Iterator for DataTreeFilterLeafIter<'a> { } Some(&DataTree::Leaf { - type_name, - contents, - byte_offset, - }) => { + type_name, + contents, + byte_offset, + }) => { if type_name == self.type_name { return Some((type_name, contents, byte_offset)); } else { @@ -271,7 +266,6 @@ impl<'a> Iterator for DataTreeFilterLeafIter<'a> { } } - #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub enum ParseError { MissingOpener(usize), @@ -285,9 +279,6 @@ pub enum ParseError { Other((usize, &'static str)), } - - - // ================================================================ #[derive(Debug, PartialEq, Eq)] @@ -386,7 +377,6 @@ fn parse_node<'a>(source_text: (usize, &'a str)) -> ParseResult<'a> { } } - fn parse_leaf_content(source_text: (usize, &str)) -> (&str, (usize, &str)) { let mut si = 1; let mut escaped = false; @@ -407,13 +397,12 @@ fn parse_leaf_content(source_text: (usize, &str)) -> (&str, (usize, &str)) { si = source_text.1.len(); } - return (&source_text.1[0..si], ( - source_text.0 + si, - &source_text.1[si..], - )); + return ( + &source_text.1[0..si], + (source_text.0 + si, &source_text.1[si..]), + ); } - fn next_token<'a>(source_text: (usize, &'a str)) -> (Token<'a>, (usize, &'a str)) { let text1 = skip_ws_and_comments(source_text); @@ -480,13 +469,12 @@ fn next_token<'a>(source_text: (usize, &'a str)) -> (Token<'a>, (usize, &'a str) si = text1.1.len(); } - return (Token::TypeName(&text1.1[0..si]), ( - text1.0 + si, - &text1.1[si..], - )); + return ( + Token::TypeName(&text1.1[0..si]), + (text1.0 + si, &text1.1[si..]), + ); } } - } } else { return (Token::End, text1); @@ -576,9 +564,6 @@ fn skip_ws_and_comments(text: (usize, &str)) -> (usize, &str) { return (offset, remaining_text); } - - - // ================================================================ #[cfg(test)] @@ -623,10 +608,10 @@ mod tests { fn tokenize_5() { let input = (0, " $hi\\ t\\#he\\[re "); - assert_eq!(next_token(input), ( - Token::Ident("$hi\\ t\\#he\\[re"), - (15, " "), - )); + assert_eq!( + next_token(input), + (Token::Ident("$hi\\ t\\#he\\[re"), (15, " "),) + ); } #[test] @@ -657,18 +642,24 @@ mod tests { let (token7, input8) = next_token(input7); let (token8, input9) = next_token(input8); - assert_eq!((token1, input2), (Token::TypeName("Thing"), ( - 5, - " $yar { # A comment\n\tThing2 []\n}", - ))); - assert_eq!((token2, input3), (Token::Ident("$yar"), ( - 10, - " { # A comment\n\tThing2 []\n}", - ))); - assert_eq!((token3, input4), (Token::OpenInner, ( - 12, - " # A comment\n\tThing2 []\n}", - ))); + assert_eq!( + (token1, input2), + ( + Token::TypeName("Thing"), + (5, " $yar { # A comment\n\tThing2 []\n}",) + ) + ); + assert_eq!( + (token2, input3), + ( + Token::Ident("$yar"), + (10, " { # A comment\n\tThing2 []\n}",) + ) + ); + assert_eq!( + (token3, input4), + (Token::OpenInner, (12, " # A comment\n\tThing2 []\n}",)) + ); assert_eq!( (token4, input5), (Token::TypeName("Thing2"), (32, " []\n}")) diff --git a/src/parse/psy.rs b/src/parse/psy.rs index dcb3312..663198e 100644 --- a/src/parse/psy.rs +++ b/src/parse/psy.rs @@ -9,29 +9,28 @@ use nom::IResult; use mem_arena::MemArena; use camera::Camera; -use color::{XYZ, rec709_e_to_xyz}; +use color::{rec709_e_to_xyz, XYZ}; use light::WorldLightSource; use math::Matrix4x4; use renderer::Renderer; use scene::Scene; use scene::World; -use super::basics::{ws_u32, ws_f32}; +use super::basics::{ws_f32, ws_u32}; use super::DataTree; use super::psy_assembly::parse_assembly; use super::psy_light::parse_distant_disk_light; - #[derive(Debug)] pub enum PsyParseError { // The first usize for all errors is their byte offset // into the psy content where they occured. UnknownError(usize), - UnknownVariant(usize, &'static str), // Error message - ExpectedInternalNode(usize, &'static str), // Error message - ExpectedLeafNode(usize, &'static str), // Error message - MissingNode(usize, &'static str), // Error message - IncorrectLeafData(usize, &'static str), // Error message + UnknownVariant(usize, &'static str), // Error message + ExpectedInternalNode(usize, &'static str), // Error message + ExpectedLeafNode(usize, &'static str), // Error message + MissingNode(usize, &'static str), // Error message + IncorrectLeafData(usize, &'static str), // Error message WrongNodeCount(usize, &'static str, usize), // Error message, sections found InstancedMissingData(usize, &'static str, String), // Error message, data name } @@ -43,7 +42,7 @@ impl PsyParseError { let line = line_count_to_byte_offset(psy_content, offset); println!( "Line {}: Unknown parse error. If you get this message, please report \ - it to the developers so they can improve the error messages.", + it to the developers so they can improve the error messages.", line ); } @@ -90,7 +89,6 @@ fn line_count_to_byte_offset(text: &str, offset: usize) -> usize { text[..offset].matches('\n').count() + 1 } - /// Takes in a `DataTree` representing a Scene node and returns pub fn parse_scene<'a>( arena: &'a MemArena, @@ -102,7 +100,7 @@ pub fn parse_scene<'a>( return Err(PsyParseError::WrongNodeCount( tree.byte_offset(), "Scene should have precisely one Output \ - section.", + section.", count, )); } @@ -111,7 +109,7 @@ pub fn parse_scene<'a>( return Err(PsyParseError::WrongNodeCount( tree.byte_offset(), "Scene should have precisely one \ - RenderSettings section.", + RenderSettings section.", count, )); } @@ -120,7 +118,7 @@ pub fn parse_scene<'a>( return Err(PsyParseError::WrongNodeCount( tree.byte_offset(), "Scene should have precisely one Camera \ - section.", + section.", count, )); } @@ -137,7 +135,7 @@ pub fn parse_scene<'a>( return Err(PsyParseError::WrongNodeCount( tree.byte_offset(), "Scene should have precisely one Root Assembly \ - section.", + section.", count, )); } @@ -199,9 +197,6 @@ pub fn parse_scene<'a>( return Ok(renderer); } - - - fn parse_output_info(tree: &DataTree) -> Result { if let DataTree::Internal { ref children, .. } = *tree { let mut found_path = false; @@ -213,21 +208,22 @@ fn parse_output_info(tree: &DataTree) -> Result { type_name, contents, byte_offset, - } if type_name == "Path" => { + } if type_name == "Path" => + { // Trim and validate let tc = contents.trim(); if tc.chars().count() < 2 { return Err(PsyParseError::IncorrectLeafData( byte_offset, "File path format is \ - incorrect.", + incorrect.", )); } if tc.chars().nth(0).unwrap() != '"' || tc.chars().last().unwrap() != '"' { return Err(PsyParseError::IncorrectLeafData( byte_offset, "File paths must be \ - surrounded by quotes.", + surrounded by quotes.", )); } let len = tc.len(); @@ -255,14 +251,11 @@ fn parse_output_info(tree: &DataTree) -> Result { return Err(PsyParseError::ExpectedInternalNode( tree.byte_offset(), "Output section should be an internal \ - node, containing at least a Path.", + node, containing at least a Path.", )); }; } - - - fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyParseError> { if let DataTree::Internal { ref children, .. } = *tree { let mut found_res = false; @@ -278,7 +271,8 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyP type_name, contents, byte_offset, - } if type_name == "Resolution" => { + } if type_name == "Resolution" => + { if let IResult::Done(_, (w, h)) = closure!(terminated!(tuple!(ws_u32, ws_u32), nom::eof))(contents.as_bytes()) { @@ -299,7 +293,8 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyP type_name, contents, byte_offset, - } if type_name == "SamplesPerPixel" => { + } if type_name == "SamplesPerPixel" => + { if let IResult::Done(_, n) = ws_u32(contents.as_bytes()) { found_spp = true; spp = n; @@ -308,8 +303,8 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyP return Err(PsyParseError::IncorrectLeafData( byte_offset, "SamplesPerPixel should be \ - an integer specified in \ - the form '[samples]'.", + an integer specified in \ + the form '[samples]'.", )); } } @@ -319,7 +314,8 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyP type_name, contents, byte_offset, - } if type_name == "Seed" => { + } if type_name == "Seed" => + { if let IResult::Done(_, n) = ws_u32(contents.as_bytes()) { seed = n; } else { @@ -327,8 +323,8 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyP return Err(PsyParseError::IncorrectLeafData( byte_offset, "Seed should be an integer \ - specified in the form \ - '[samples]'.", + specified in the form \ + '[samples]'.", )); } } @@ -343,22 +339,19 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyP return Err(PsyParseError::MissingNode( tree.byte_offset(), "RenderSettings must have both Resolution and \ - SamplesPerPixel specified.", + SamplesPerPixel specified.", )); } } else { return Err(PsyParseError::ExpectedInternalNode( tree.byte_offset(), "RenderSettings section should be an \ - internal node, containing at least \ - Resolution and SamplesPerPixel.", + internal node, containing at least \ + Resolution and SamplesPerPixel.", )); }; } - - - fn parse_camera<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result, PsyParseError> { if let DataTree::Internal { ref children, .. } = *tree { let mut mats = Vec::new(); @@ -374,7 +367,8 @@ fn parse_camera<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result { + } if type_name == "Fov" => + { if let IResult::Done(_, fov) = ws_f32(contents.as_bytes()) { fovs.push(fov * (f32::consts::PI / 180.0)); } else { @@ -382,8 +376,8 @@ fn parse_camera<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result(arena: &'a MemArena, tree: &'a DataTree) -> Result { + } if type_name == "FocalDistance" => + { if let IResult::Done(_, fd) = ws_f32(contents.as_bytes()) { focus_distances.push(fd); } else { @@ -401,8 +396,8 @@ fn parse_camera<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result(arena: &'a MemArena, tree: &'a DataTree) -> Result { + } if type_name == "ApertureRadius" => + { if let IResult::Done(_, ar) = ws_f32(contents.as_bytes()) { aperture_radii.push(ar); } else { @@ -420,8 +416,8 @@ fn parse_camera<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result(arena: &'a MemArena, tree: &'a DataTree) -> Result { + } if type_name == "Transform" => + { if let Ok(mat) = parse_matrix(contents) { mats.push(mat); } else { @@ -455,15 +452,12 @@ fn parse_camera<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result(arena: &'a MemArena, tree: &'a DataTree) -> Result, PsyParseError> { if tree.is_internal() { let background_color; @@ -487,7 +481,7 @@ fn parse_world<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result, return Err(PsyParseError::WrongNodeCount( bgs.byte_offset(), "BackgroundShader should have \ - precisely one Type specified.", + precisely one Type specified.", bgs.iter_children_with_type("Type").count(), )); } @@ -499,17 +493,17 @@ fn parse_world<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result, return Err(PsyParseError::ExpectedLeafNode( bgs.byte_offset(), "BackgroundShader's Type should be a \ - leaf node.", + leaf node.", )); } }; match bgs_type { "Color" => { if let Some(&DataTree::Leaf { - contents, - byte_offset, - .. - }) = bgs.iter_children_with_type("Color").nth(0) + contents, + byte_offset, + .. + }) = bgs.iter_children_with_type("Color").nth(0) { if let IResult::Done(_, color) = closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.trim().as_bytes()) @@ -521,15 +515,15 @@ fn parse_world<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result, return Err(PsyParseError::IncorrectLeafData( byte_offset, "Color should be specified \ - with three decimal numbers \ - in the form '[R G B]'.", + with three decimal numbers \ + in the form '[R G B]'.", )); } } else { return Err(PsyParseError::MissingNode( bgs.byte_offset(), "BackgroundShader's Type is Color, \ - but no Color is specified.", + but no Color is specified.", )); } } @@ -538,7 +532,7 @@ fn parse_world<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result, return Err(PsyParseError::UnknownVariant( bgs.byte_offset(), "The specified BackgroundShader Type \ - isn't a recognized type.", + isn't a recognized type.", )) } } @@ -563,38 +557,34 @@ fn parse_world<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result, return Err(PsyParseError::ExpectedInternalNode( tree.byte_offset(), "World section should be an internal \ - node, containing at least a \ - BackgroundShader.", + node, containing at least a \ + BackgroundShader.", )); } } - - - pub fn parse_matrix(contents: &str) -> Result { - if let IResult::Done(_, ns) = - closure!(terminated!( - tuple!( - ws_f32, - ws_f32, - ws_f32, - ws_f32, - ws_f32, - ws_f32, - ws_f32, - ws_f32, - ws_f32, - ws_f32, - ws_f32, - ws_f32, - ws_f32, - ws_f32, - ws_f32, - ws_f32 - ), - nom::eof - ))(contents.as_bytes()) + if let IResult::Done(_, ns) = closure!(terminated!( + tuple!( + ws_f32, + ws_f32, + ws_f32, + ws_f32, + ws_f32, + ws_f32, + ws_f32, + ws_f32, + ws_f32, + ws_f32, + ws_f32, + ws_f32, + ws_f32, + ws_f32, + ws_f32, + ws_f32 + ), + nom::eof + ))(contents.as_bytes()) { return Ok(Matrix4x4::new_from_values( ns.0, @@ -623,6 +613,6 @@ pub fn make_transform_format_error(byte_offset: usize) -> PsyParseError { PsyParseError::IncorrectLeafData( byte_offset, "Transform should be sixteen integers specified in \ - the form '[# # # # # # # # # # # # # # # #]'.", + the form '[# # # # # # # # # # # # # # # #]'.", ) } diff --git a/src/parse/psy_assembly.rs b/src/parse/psy_assembly.rs index 86cb659..4ea3207 100644 --- a/src/parse/psy_assembly.rs +++ b/src/parse/psy_assembly.rs @@ -7,12 +7,11 @@ use mem_arena::MemArena; use scene::{Assembly, AssemblyBuilder, Object}; use super::DataTree; -use super::psy_light::{parse_sphere_light, parse_rectangle_light}; +use super::psy_light::{parse_rectangle_light, parse_sphere_light}; use super::psy_mesh_surface::parse_mesh_surface; use super::psy_surface_shader::parse_surface_shader; use super::psy::{parse_matrix, PsyParseError}; - pub fn parse_assembly<'a>( arena: &'a MemArena, tree: &'a DataTree, @@ -24,7 +23,10 @@ pub fn parse_assembly<'a>( match child.type_name() { // Sub-Assembly "Assembly" => { - if let DataTree::Internal { ident: Some(ident), .. } = *child { + if let DataTree::Internal { + ident: Some(ident), .. + } = *child + { builder.add_assembly(ident, parse_assembly(arena, child)?); } else { return Err(PsyParseError::UnknownError(child.byte_offset())); @@ -75,9 +77,9 @@ pub fn parse_assembly<'a>( return Err(PsyParseError::InstancedMissingData( child.iter_leaf_children_with_type("Data").nth(0).unwrap().2, "Attempted to add \ - instance for data with \ - a name that doesn't \ - exist.", + instance for data with \ + a name that doesn't \ + exist.", name.to_string(), )); } @@ -85,13 +87,16 @@ pub fn parse_assembly<'a>( // SurfaceShader "SurfaceShader" => { - if let DataTree::Internal { ident: Some(ident), .. } = *child { + if let DataTree::Internal { + ident: Some(ident), .. + } = *child + { builder.add_surface_shader(ident, parse_surface_shader(arena, child)?); } else { // TODO: error condition of some kind, because no ident panic!( "SurfaceShader encountered that was a leaf, but SurfaceShaders cannot \ - be a leaf: {}", + be a leaf: {}", child.byte_offset() ); } @@ -99,7 +104,10 @@ pub fn parse_assembly<'a>( // MeshSurface "MeshSurface" => { - if let DataTree::Internal { ident: Some(ident), .. } = *child { + if let DataTree::Internal { + ident: Some(ident), .. + } = *child + { builder.add_object( ident, Object::Surface(arena.alloc(parse_mesh_surface(arena, child)?)), @@ -108,7 +116,7 @@ pub fn parse_assembly<'a>( // TODO: error condition of some kind, because no ident panic!( "MeshSurface encountered that was a leaf, but MeshSurfaces cannot \ - be a leaf: {}", + be a leaf: {}", child.byte_offset() ); } @@ -116,7 +124,10 @@ pub fn parse_assembly<'a>( // Sphere Light "SphereLight" => { - if let DataTree::Internal { ident: Some(ident), .. } = *child { + if let DataTree::Internal { + ident: Some(ident), .. + } = *child + { builder.add_object( ident, Object::SurfaceLight(arena.alloc(parse_sphere_light(arena, child)?)), @@ -129,12 +140,13 @@ pub fn parse_assembly<'a>( // Rectangle Light "RectangleLight" => { - if let DataTree::Internal { ident: Some(ident), .. } = *child { + if let DataTree::Internal { + ident: Some(ident), .. + } = *child + { builder.add_object( ident, - Object::SurfaceLight( - arena.alloc(parse_rectangle_light(arena, child)?), - ), + Object::SurfaceLight(arena.alloc(parse_rectangle_light(arena, child)?)), ); } else { // No ident @@ -144,27 +156,25 @@ pub fn parse_assembly<'a>( _ => { // TODO: some kind of error, because not a known type name - } - - // // Bilinear Patch - // "BilinearPatch" => { - // assembly->add_object(child.name, parse_bilinear_patch(child)); - // } - // - // // Bicubic Patch - // else if (child.type == "BicubicPatch") { - // assembly->add_object(child.name, parse_bicubic_patch(child)); - // } - // - // // Subdivision surface - // else if (child.type == "SubdivisionSurface") { - // assembly->add_object(child.name, parse_subdivision_surface(child)); - // } - // - // // Sphere - // else if (child.type == "Sphere") { - // assembly->add_object(child.name, parse_sphere(child)); - // } + } // // Bilinear Patch + // "BilinearPatch" => { + // assembly->add_object(child.name, parse_bilinear_patch(child)); + // } + // + // // Bicubic Patch + // else if (child.type == "BicubicPatch") { + // assembly->add_object(child.name, parse_bicubic_patch(child)); + // } + // + // // Subdivision surface + // else if (child.type == "SubdivisionSurface") { + // assembly->add_object(child.name, parse_subdivision_surface(child)); + // } + // + // // Sphere + // else if (child.type == "Sphere") { + // assembly->add_object(child.name, parse_sphere(child)); + // } } } } else { diff --git a/src/parse/psy_light.rs b/src/parse/psy_light.rs index 3acc377..a16d8dc 100644 --- a/src/parse/psy_light.rs +++ b/src/parse/psy_light.rs @@ -7,14 +7,13 @@ use nom::IResult; use mem_arena::MemArena; use math::Vector; -use color::{XYZ, rec709_e_to_xyz}; -use light::{DistantDiskLight, SphereLight, RectangleLight}; +use color::{rec709_e_to_xyz, XYZ}; +use light::{DistantDiskLight, RectangleLight, SphereLight}; use super::basics::ws_f32; use super::DataTree; use super::psy::PsyParseError; - pub fn parse_distant_disk_light<'a>( arena: &'a MemArena, tree: &'a DataTree, @@ -32,7 +31,8 @@ pub fn parse_distant_disk_light<'a>( type_name, contents, byte_offset, - } if type_name == "Radius" => { + } if type_name == "Radius" => + { if let IResult::Done(_, radius) = ws_f32(contents.as_bytes()) { radii.push(radius); } else { @@ -46,7 +46,8 @@ pub fn parse_distant_disk_light<'a>( type_name, contents, byte_offset, - } if type_name == "Direction" => { + } if type_name == "Direction" => + { if let IResult::Done(_, direction) = closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) { @@ -62,7 +63,8 @@ pub fn parse_distant_disk_light<'a>( type_name, contents, byte_offset, - } if type_name == "Color" => { + } if type_name == "Color" => + { if let IResult::Done(_, color) = closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) { @@ -86,7 +88,6 @@ pub fn parse_distant_disk_light<'a>( } } - pub fn parse_sphere_light<'a>( arena: &'a MemArena, tree: &'a DataTree, @@ -103,7 +104,8 @@ pub fn parse_sphere_light<'a>( type_name, contents, byte_offset, - } if type_name == "Radius" => { + } if type_name == "Radius" => + { if let IResult::Done(_, radius) = ws_f32(contents.as_bytes()) { radii.push(radius); } else { @@ -117,7 +119,8 @@ pub fn parse_sphere_light<'a>( type_name, contents, byte_offset, - } if type_name == "Color" => { + } if type_name == "Color" => + { if let IResult::Done(_, color) = closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) { @@ -157,7 +160,8 @@ pub fn parse_rectangle_light<'a>( type_name, contents, byte_offset, - } if type_name == "Dimensions" => { + } if type_name == "Dimensions" => + { if let IResult::Done(_, radius) = closure!(tuple!(ws_f32, ws_f32))(contents.as_bytes()) { @@ -173,7 +177,8 @@ pub fn parse_rectangle_light<'a>( type_name, contents, byte_offset, - } if type_name == "Color" => { + } if type_name == "Color" => + { if let IResult::Done(_, color) = closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes()) { diff --git a/src/parse/psy_mesh_surface.rs b/src/parse/psy_mesh_surface.rs index 06ee27d..aa61fca 100644 --- a/src/parse/psy_mesh_surface.rs +++ b/src/parse/psy_mesh_surface.rs @@ -6,14 +6,13 @@ use nom::IResult; use mem_arena::MemArena; -use math::{Point, Normal}; +use math::{Normal, Point}; use surface::triangle_mesh::TriangleMesh; use super::basics::{ws_usize, ws_f32}; use super::DataTree; use super::psy::PsyParseError; - // pub struct TriangleMesh { // time_samples: usize, // geo: Vec<(Point, Point, Point)>, @@ -61,8 +60,7 @@ pub fn parse_mesh_surface<'a>( // Collect verts for this time sample let mut tnormals = Vec::new(); - while let IResult::Done(remaining, nor) = - closure!(tuple!(ws_f32, ws_f32, ws_f32))(raw_text) + while let IResult::Done(remaining, nor) = closure!(tuple!(ws_f32, ws_f32, ws_f32))(raw_text) { raw_text = remaining; diff --git a/src/parse/psy_surface_shader.rs b/src/parse/psy_surface_shader.rs index 33c4fe7..a687940 100644 --- a/src/parse/psy_surface_shader.rs +++ b/src/parse/psy_surface_shader.rs @@ -6,14 +6,13 @@ use nom::IResult; use mem_arena::MemArena; -use color::{XYZ, rec709_e_to_xyz}; -use shading::{SurfaceShader, SimpleSurfaceShader}; +use color::{rec709_e_to_xyz, XYZ}; +use shading::{SimpleSurfaceShader, SurfaceShader}; use super::basics::ws_f32; use super::DataTree; use super::psy::PsyParseError; - // pub struct TriangleMesh { // time_samples: usize, // geo: Vec<(Point, Point, Point)>, diff --git a/src/ray.rs b/src/ray.rs index 16abe46..2f7b8d1 100644 --- a/src/ray.rs +++ b/src/ray.rs @@ -3,8 +3,7 @@ use std; use float4::Float4; -use math::{Vector, Point, Matrix4x4}; - +use math::{Matrix4x4, Point, Vector}; const OCCLUSION_FLAG: u32 = 1; const DONE_FLAG: u32 = 1 << 1; @@ -52,7 +51,6 @@ impl Ray { } } - #[derive(Debug, Copy, Clone)] pub struct AccelRay { pub orig: Point, @@ -67,7 +65,9 @@ impl AccelRay { pub fn new(ray: &Ray, id: u32) -> AccelRay { AccelRay { orig: ray.orig, - dir_inv: Vector { co: Float4::new(1.0, 1.0, 1.0, 1.0) / ray.dir.co }, + dir_inv: Vector { + co: Float4::new(1.0, 1.0, 1.0, 1.0) / ray.dir.co, + }, max_t: ray.max_t, time: ray.time, flags: ray.flags, @@ -77,12 +77,16 @@ impl AccelRay { pub fn update_from_world_ray(&mut self, wr: &Ray) { self.orig = wr.orig; - self.dir_inv = Vector { co: Float4::new(1.0, 1.0, 1.0, 1.0) / wr.dir.co }; + self.dir_inv = Vector { + co: Float4::new(1.0, 1.0, 1.0, 1.0) / wr.dir.co, + }; } pub fn update_from_xformed_world_ray(&mut self, wr: &Ray, mat: &Matrix4x4) { self.orig = wr.orig * *mat; - self.dir_inv = Vector { co: Float4::new(1.0, 1.0, 1.0, 1.0) / (wr.dir * *mat).co }; + self.dir_inv = Vector { + co: Float4::new(1.0, 1.0, 1.0, 1.0) / (wr.dir * *mat).co, + }; } pub fn is_occlusion(&self) -> bool { diff --git a/src/renderer.rs b/src/renderer.rs index 8e0bad6..e595790 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -3,16 +3,16 @@ use std::cell::Cell; use std::cmp; use std::cmp::min; use std::io::{self, Write}; -use std::sync::{RwLock, Mutex}; +use std::sync::{Mutex, RwLock}; use crossbeam::sync::MsQueue; use scoped_threadpool::Pool; use halton; -use accel::{ACCEL_TRAV_TIME, ACCEL_NODE_RAY_TESTS}; +use accel::{ACCEL_NODE_RAY_TESTS, ACCEL_TRAV_TIME}; use algorithm::partition_pair; -use color::{Color, XYZ, SpectralSample, map_0_1_to_wavelength}; +use color::{Color, SpectralSample, map_0_1_to_wavelength, XYZ}; use float4::Float4; use fp_utils::robust_ray_origin; use hash::hash_u32; @@ -27,7 +27,6 @@ use timer::Timer; use tracer::Tracer; use transform_stack::TransformStack; - #[derive(Debug)] pub struct Renderer<'a> { pub output_file: String, @@ -184,9 +183,7 @@ impl<'a> Renderer<'a> { }); // Clear percentage progress print - print!( - "\r \r", - ); + print!("\r \r",); // Return the rendered image and stats return (image, *collective_stats.read().unwrap()); @@ -353,7 +350,6 @@ impl<'a> Renderer<'a> { } } - #[derive(Debug)] enum LightPathEvent { CameraRay, @@ -410,7 +406,6 @@ impl LightPath { pending_color_addition: Float4::splat(0.0), color: Float4::splat(0.0), }, - scene.camera.generate_ray( image_plane_co.0, image_plane_co.1, @@ -438,8 +433,7 @@ impl LightPath { match self.event { //-------------------------------------------------------------------- // Result of Camera or bounce ray, prepare next bounce and light rays - LightPathEvent::CameraRay | - LightPathEvent::BounceRay => { + LightPathEvent::CameraRay | LightPathEvent::BounceRay => { if let surface::SurfaceIntersection::Hit { intersection_data: ref idata, ref closure, @@ -482,8 +476,8 @@ impl LightPath { self.time, isect, ); - let found_light = if light_info.is_none() || light_info.pdf() <= 0.0 || - light_info.selection_pdf() <= 0.0 + let found_light = if light_info.is_none() || light_info.pdf() <= 0.0 + || light_info.selection_pdf() <= 0.0 { false } else { @@ -564,9 +558,9 @@ impl LightPath { // Calculate and store the light that will be contributed // to the film plane if the light is not in shadow. let light_mis_pdf = power_heuristic(light_pdf, closure_pdf); - self.pending_color_addition = light_info.color().e * attenuation.e * - self.light_attenuation / - (light_mis_pdf * light_sel_pdf); + self.pending_color_addition = light_info.color().e * attenuation.e + * self.light_attenuation + / (light_mis_pdf * light_sel_pdf); *ray = shadow_ray; @@ -630,8 +624,8 @@ impl LightPath { .world .background_color .to_spectral_sample(self.wavelength) - .e * self.light_attenuation / - self.closure_sample_pdf; + .e * self.light_attenuation + / self.closure_sample_pdf; return false; } } @@ -672,7 +666,6 @@ fn get_sample(dimension: u32, i: u32) -> f32 { } } - #[derive(Debug)] struct BucketJob { x: u32, diff --git a/src/sampling/mod.rs b/src/sampling/mod.rs index bc518e0..ced027a 100644 --- a/src/sampling/mod.rs +++ b/src/sampling/mod.rs @@ -1,6 +1,7 @@ mod monte_carlo; -pub use self::monte_carlo::{square_to_circle, cosine_sample_hemisphere, uniform_sample_hemisphere, - uniform_sample_sphere, uniform_sample_cone, uniform_sample_cone_pdf, - uniform_sample_triangle, triangle_surface_area, - spherical_triangle_solid_angle, uniform_sample_spherical_triangle}; +pub use self::monte_carlo::{cosine_sample_hemisphere, spherical_triangle_solid_angle, + square_to_circle, triangle_surface_area, uniform_sample_cone, + uniform_sample_cone_pdf, uniform_sample_hemisphere, + uniform_sample_sphere, uniform_sample_spherical_triangle, + uniform_sample_triangle}; diff --git a/src/sampling/monte_carlo.rs b/src/sampling/monte_carlo.rs index 22c76d2..f19acee 100644 --- a/src/sampling/monte_carlo.rs +++ b/src/sampling/monte_carlo.rs @@ -4,8 +4,7 @@ use std::f32::consts::FRAC_PI_4 as QPI_32; use std::f32::consts::PI as PI_32; use std::f64::consts::PI as PI_64; -use math::{Vector, Point, cross, dot}; - +use math::{cross, dot, Point, Vector}; /// Maps the unit square to the unit circle. /// NOTE: x and y should be distributed within [-1, 1], @@ -194,8 +193,8 @@ pub fn uniform_sample_spherical_triangle( let q_bottom = ((v * s) + (u * t)) * sin_va; let q = q_top / q_bottom; - let vc_2 = (va * q as f32) + - ((vc - (va * dot(vc, va))).normalized() * (1.0 - (q * q)).sqrt() as f32); + let vc_2 = + (va * q as f32) + ((vc - (va * dot(vc, va))).normalized() * (1.0 - (q * q)).sqrt() as f32); let z = 1.0 - (j * (1.0 - dot(vc_2, vb))); diff --git a/src/scene/assembly.rs b/src/scene/assembly.rs index 9fe3fee..de5cd18 100644 --- a/src/scene/assembly.rs +++ b/src/scene/assembly.rs @@ -4,7 +4,7 @@ use mem_arena::MemArena; use accel::{LightAccel, LightTree}; use accel::BVH4; -use bbox::{BBox, transform_bbox_slice_from}; +use bbox::{transform_bbox_slice_from, BBox}; use boundable::Boundable; use color::SpectralSample; use lerp::lerp_slice; @@ -14,7 +14,6 @@ use surface::{Surface, SurfaceIntersection}; use shading::SurfaceShader; use transform_stack::TransformStack; - #[derive(Copy, Clone, Debug)] pub struct Assembly<'a> { // Instance list @@ -59,20 +58,17 @@ impl<'a> Assembly<'a> { } else { Matrix4x4::new() }; - if let Some((light_i, sel_pdf, whittled_n)) = - self.light_accel.select( - idata.incoming * sel_xform, - idata.pos * sel_xform, - idata.nor * sel_xform, - idata.nor_g * sel_xform, - closure.as_surface_closure(), - time, - n, - ) - { + if let Some((light_i, sel_pdf, whittled_n)) = self.light_accel.select( + idata.incoming * sel_xform, + idata.pos * sel_xform, + idata.nor * sel_xform, + idata.nor_g * sel_xform, + closure.as_surface_closure(), + time, + n, + ) { let inst = self.light_instances[light_i]; match inst.instance_type { - InstanceType::Object => { match self.objects[inst.data_index] { Object::SurfaceLight(light) => { @@ -151,7 +147,6 @@ impl<'a> Boundable for Assembly<'a> { } } - #[derive(Debug)] pub struct AssemblyBuilder<'a> { arena: &'a MemArena, @@ -173,7 +168,6 @@ pub struct AssemblyBuilder<'a> { assembly_map: HashMap, // map Name -> Index } - impl<'a> AssemblyBuilder<'a> { pub fn new(arena: &'a MemArena) -> AssemblyBuilder<'a> { AssemblyBuilder { @@ -196,10 +190,8 @@ impl<'a> AssemblyBuilder<'a> { } // Add shader - self.surface_shader_map.insert( - name.to_string(), - self.surface_shaders.len(), - ); + self.surface_shader_map + .insert(name.to_string(), self.surface_shaders.len()); self.surface_shaders.push(shader); } @@ -219,15 +211,13 @@ impl<'a> AssemblyBuilder<'a> { if self.name_exists(name) { panic!( "Attempted to add assembly to another assembly with a name that already \ - exists." + exists." ); } // Add assembly - self.assembly_map.insert( - name.to_string(), - self.assemblies.len(), - ); + self.assembly_map + .insert(name.to_string(), self.assemblies.len()); self.assemblies.push(asmb); } @@ -244,7 +234,11 @@ impl<'a> AssemblyBuilder<'a> { // Map zero-length transforms to None let xforms = if let Some(xf) = xforms { - if !xf.is_empty() { Some(xf) } else { None } + if !xf.is_empty() { + Some(xf) + } else { + None + } } else { None }; @@ -255,30 +249,26 @@ impl<'a> AssemblyBuilder<'a> { instance_type: InstanceType::Object, data_index: self.object_map[name], surface_shader_index: surface_shader_name.map(|name| { - *self.surface_shader_map.get(name).expect(&format!( - "Unknown surface shader '{}'.", - name - )) + *self.surface_shader_map + .get(name) + .expect(&format!("Unknown surface shader '{}'.", name)) }), id: self.instances.len(), - transform_indices: xforms.map( - |xf| (self.xforms.len(), self.xforms.len() + xf.len()), - ), + transform_indices: xforms + .map(|xf| (self.xforms.len(), self.xforms.len() + xf.len())), } } else { Instance { instance_type: InstanceType::Assembly, data_index: self.assembly_map[name], surface_shader_index: surface_shader_name.map(|name| { - *self.surface_shader_map.get(name).expect(&format!( - "Unknown surface shader '{}'.", - name - )) + *self.surface_shader_map + .get(name) + .expect(&format!("Unknown surface shader '{}'.", name)) }), id: self.instances.len(), - transform_indices: xforms.map( - |xf| (self.xforms.len(), self.xforms.len() + xf.len()), - ), + transform_indices: xforms + .map(|xf| (self.xforms.len(), self.xforms.len() + xf.len())), } }; @@ -337,11 +327,9 @@ impl<'a> AssemblyBuilder<'a> { } } - InstanceType::Assembly => { - self.assemblies[inst.data_index] - .light_accel - .approximate_energy() - } + InstanceType::Assembly => self.assemblies[inst.data_index] + .light_accel + .approximate_energy(), }; (bounds, energy) }); @@ -358,7 +346,6 @@ impl<'a> AssemblyBuilder<'a> { } } - /// Returns a pair of vectors with the bounds of all instances. /// This is used for building the assembly's BVH4. fn instance_bounds(&self) -> (Vec, Vec) { @@ -405,15 +392,12 @@ impl<'a> AssemblyBuilder<'a> { } } - - #[derive(Copy, Clone, Debug)] pub enum Object<'a> { Surface(&'a Surface), SurfaceLight(&'a SurfaceLight), } - #[derive(Debug, Copy, Clone)] pub struct Instance { pub instance_type: InstanceType, diff --git a/src/scene/mod.rs b/src/scene/mod.rs index a48bb69..4ca8ed8 100644 --- a/src/scene/mod.rs +++ b/src/scene/mod.rs @@ -2,6 +2,6 @@ mod assembly; mod scene; mod world; -pub use self::assembly::{Assembly, AssemblyBuilder, Object, InstanceType}; +pub use self::assembly::{Assembly, AssemblyBuilder, InstanceType, Object}; pub use self::scene::{Scene, SceneLightSample}; pub use self::world::World; diff --git a/src/scene/scene.rs b/src/scene/scene.rs index 054ad60..2516626 100644 --- a/src/scene/scene.rs +++ b/src/scene/scene.rs @@ -2,14 +2,13 @@ use accel::LightAccel; use algorithm::weighted_choice; use camera::Camera; use color::SpectralSample; -use math::{Vector, Normal, Point}; +use math::{Normal, Point, Vector}; use surface::SurfaceIntersection; use transform_stack::TransformStack; use super::Assembly; use super::World; - #[derive(Debug)] pub struct Scene<'a> { pub name: Option, @@ -35,9 +34,11 @@ impl<'a> Scene<'a> { // Calculate relative probabilities of traversing into world lights // or local lights. - let wl_energy = if self.world.lights.iter().fold(0.0, |energy, light| { - energy + light.approximate_energy() - }) <= 0.0 + let wl_energy = if self.world + .lights + .iter() + .fold(0.0, |energy, light| energy + light.approximate_energy()) + <= 0.0 { 0.0 } else { @@ -73,14 +74,8 @@ impl<'a> Scene<'a> { let n = (n - wl_prob) / (1.0 - wl_prob); if let Some((ss, sgeo, pdf, spdf)) = - self.root.sample_lights( - xform_stack, - n, - uvw, - wavelength, - time, - intr, - ) + self.root + .sample_lights(xform_stack, n, uvw, wavelength, time, intr) { return SceneLightSample::Surface { color: ss, @@ -96,7 +91,6 @@ impl<'a> Scene<'a> { } } - #[derive(Debug, Copy, Clone)] pub enum SceneLightSample { None, diff --git a/src/shading/mod.rs b/src/shading/mod.rs index 7f6f00d..b7e9d60 100644 --- a/src/shading/mod.rs +++ b/src/shading/mod.rs @@ -2,8 +2,8 @@ pub mod surface_closure; use std::fmt::Debug; -use color::{XYZ, Color}; -use self::surface_closure::{SurfaceClosureUnion, EmitClosure, LambertClosure, GTRClosure}; +use color::{Color, XYZ}; +use self::surface_closure::{EmitClosure, GTRClosure, LambertClosure, SurfaceClosureUnion}; use surface::SurfaceIntersectionData; /// Trait for surface shaders. @@ -31,8 +31,12 @@ pub trait SurfaceShader: Debug + Sync { /// building. #[derive(Debug, Copy, Clone)] pub enum SimpleSurfaceShader { - Emit { color: XYZ }, - Lambert { color: XYZ }, + Emit { + color: XYZ, + }, + Lambert { + color: XYZ, + }, GTR { color: XYZ, roughness: f32, @@ -51,29 +55,23 @@ impl SurfaceShader for SimpleSurfaceShader { let _ = (data, time); // Silence "unused" compiler warning match *self { - SimpleSurfaceShader::Emit { color } => { - SurfaceClosureUnion::EmitClosure( - EmitClosure::new(color.to_spectral_sample(wavelength)), - ) - } - SimpleSurfaceShader::Lambert { color } => { - SurfaceClosureUnion::LambertClosure( - LambertClosure::new(color.to_spectral_sample(wavelength)), - ) - } + SimpleSurfaceShader::Emit { color } => SurfaceClosureUnion::EmitClosure( + EmitClosure::new(color.to_spectral_sample(wavelength)), + ), + SimpleSurfaceShader::Lambert { color } => SurfaceClosureUnion::LambertClosure( + LambertClosure::new(color.to_spectral_sample(wavelength)), + ), SimpleSurfaceShader::GTR { color, roughness, tail_shape, fresnel, - } => { - SurfaceClosureUnion::GTRClosure(GTRClosure::new( - color.to_spectral_sample(wavelength), - roughness, - tail_shape, - fresnel, - )) - } + } => SurfaceClosureUnion::GTRClosure(GTRClosure::new( + color.to_spectral_sample(wavelength), + roughness, + tail_shape, + fresnel, + )), } } } diff --git a/src/shading/surface_closure.rs b/src/shading/surface_closure.rs index bac3cc2..54b2f37 100644 --- a/src/shading/surface_closure.rs +++ b/src/shading/surface_closure.rs @@ -3,11 +3,10 @@ use std::f32::consts::PI as PI_32; use color::SpectralSample; -use math::{Vector, Normal, dot, clamp, zup_to_vec}; +use math::{clamp, dot, zup_to_vec, Normal, Vector}; use sampling::cosine_sample_hemisphere; use lerp::lerp; - const INV_PI: f32 = 1.0 / PI_32; const H_PI: f32 = PI_32 / 2.0; @@ -90,7 +89,6 @@ pub trait SurfaceClosure { ) -> f32; } - /// Utility function that calculates the fresnel reflection factor of a given /// incoming ray against a surface with the given ior outside/inside ratio. /// @@ -114,7 +112,6 @@ fn dielectric_fresnel(ior_ratio: f32, c: f32) -> f32 { 0.5 * f3 * f6 } - /// Schlick's approximation of the fresnel reflection factor. /// /// Same interface as `dielectric_fresnel()`, above. @@ -128,7 +125,6 @@ fn schlick_fresnel(ior_ratio: f32, c: f32) -> f32 { f2 + ((1.0 - f2) * c1 * c2 * c2) } - /// Utility function that calculates the fresnel reflection factor of a given /// incoming ray against a surface with the given normal-reflectance factor. /// @@ -154,7 +150,6 @@ fn dielectric_fresnel_from_fac(fresnel_fac: f32, c: f32) -> f32 { dielectric_fresnel(ior_ratio, c) } - /// Schlick's approximation version of `dielectric_fresnel_from_fac()` above. #[allow(dead_code)] fn schlick_fresnel_from_fac(frensel_fac: f32, c: f32) -> f32 { @@ -163,7 +158,6 @@ fn schlick_fresnel_from_fac(frensel_fac: f32, c: f32) -> f32 { frensel_fac + ((1.0 - frensel_fac) * c1 * c2 * c2) } - /// Emit closure. /// /// NOTE: this needs to be handled specially by the integrator! It does not @@ -228,7 +222,6 @@ impl SurfaceClosure for EmitClosure { } } - /// Lambertian surface closure #[derive(Debug, Copy, Clone)] pub struct LambertClosure { @@ -368,7 +361,6 @@ impl SurfaceClosure for LambertClosure { } } - /// The GTR microfacet BRDF from the Disney Principled BRDF paper. #[derive(Debug, Copy, Clone)] pub struct GTRClosure { @@ -438,8 +430,8 @@ impl GTRClosure { let roughness2 = self.roughness * self.roughness; // Calculate top half of equation - let top = 1.0 - - ((roughness2.powf(1.0 - self.tail_shape) * (1.0 - u)) + u) + let top = 1.0 + - ((roughness2.powf(1.0 - self.tail_shape) * (1.0 - u)) + u) .powf(1.0 / (1.0 - self.tail_shape)); // Calculate bottom half of equation @@ -470,7 +462,6 @@ impl SurfaceClosure for GTRClosure { self.roughness == 0.0 } - fn sample( &self, inc: Vector, @@ -505,7 +496,6 @@ impl SurfaceClosure for GTRClosure { } } - fn evaluate(&self, inc: Vector, out: Vector, nor: Normal, nor_g: Normal) -> SpectralSample { // Calculate needed vectors, normalized let aa = -inc.normalized(); // Vector pointing to where "in" came from @@ -605,7 +595,6 @@ impl SurfaceClosure for GTRClosure { } } - fn sample_pdf(&self, inc: Vector, out: Vector, nor: Normal, nor_g: Normal) -> f32 { // Calculate needed vectors, normalized let aa = -inc.normalized(); // Vector pointing to where "in" came from @@ -630,7 +619,6 @@ impl SurfaceClosure for GTRClosure { self.dist(nh, self.roughness) * INV_PI } - fn estimate_eval_over_sphere_light( &self, inc: Vector, diff --git a/src/surface/mod.rs b/src/surface/mod.rs index 5389618..453a1eb 100644 --- a/src/surface/mod.rs +++ b/src/surface/mod.rs @@ -6,12 +6,11 @@ pub mod triangle_mesh; use std::fmt::Debug; use boundable::Boundable; -use math::{Point, Vector, Normal, Matrix4x4}; -use ray::{Ray, AccelRay}; +use math::{Matrix4x4, Normal, Point, Vector}; +use ray::{AccelRay, Ray}; use shading::surface_closure::SurfaceClosureUnion; use shading::SurfaceShader; - pub trait Surface: Boundable + Debug + Sync { fn intersect_rays( &self, @@ -23,7 +22,6 @@ pub trait Surface: Boundable + Debug + Sync { ); } - #[derive(Debug, Copy, Clone)] pub enum SurfaceIntersection { Miss, @@ -34,17 +32,16 @@ pub enum SurfaceIntersection { }, } - #[derive(Debug, Copy, Clone)] pub struct SurfaceIntersectionData { pub incoming: Vector, // Direction of the incoming ray - pub pos: Point, // Position of the intersection - pub pos_err: f32, // Error magnitude of the intersection position. Imagine + pub pos: Point, // Position of the intersection + pub pos_err: f32, // Error magnitude of the intersection position. Imagine // a cube centered around `pos` with dimensions of `2 * pos_err`. - pub nor: Normal, // Shading normal - pub nor_g: Normal, // True geometric normal + pub nor: Normal, // Shading normal + pub nor_g: Normal, // True geometric normal pub local_space: Matrix4x4, // Matrix from global space to local space - pub t: f32, // Ray t-value at the intersection point - pub uv: (f32, f32), // 2d surface parameters - pub sample_pdf: f32, // The PDF of getting this point by explicitly sampling the surface + pub t: f32, // Ray t-value at the intersection point + pub uv: (f32, f32), // 2d surface parameters + pub sample_pdf: f32, // The PDF of getting this point by explicitly sampling the surface } diff --git a/src/surface/triangle.rs b/src/surface/triangle.rs index 1f785a4..b58c28a 100644 --- a/src/surface/triangle.rs +++ b/src/surface/triangle.rs @@ -4,7 +4,6 @@ use fp_utils::fp_gamma; use math::Point; use ray::Ray; - /// Intersects `ray` with `tri`, returning `Some((t, b0, b1, b2))`, or `None` /// if no intersection. /// @@ -83,8 +82,8 @@ pub fn intersect_ray(ray: &Ray, tri: (Point, Point, Point)) -> Option<(f32, f32, let t_scaled = (e0 * p0z) + (e1 * p1z) + (e2 * p2z); // Check if the hitpoint t is within ray min/max t. - if (det > 0.0 && (t_scaled <= 0.0 || t_scaled > (ray.max_t * det))) || - (det < 0.0 && (t_scaled >= 0.0 || t_scaled < (ray.max_t * det))) + if (det > 0.0 && (t_scaled <= 0.0 || t_scaled > (ray.max_t * det))) + || (det < 0.0 && (t_scaled >= 0.0 || t_scaled < (ray.max_t * det))) { return None; } @@ -115,8 +114,8 @@ pub fn intersect_ray(ray: &Ray, tri: (Point, Point, Point)) -> Option<(f32, f32, // Calculate delta t let max_e = max_abs_3(e0, e1, e2); - let dt = 3.0 * ((fp_gamma(3) * max_e * max_zt) + (de * max_zt + dz * max_e)) * - inv_det.abs(); + let dt = + 3.0 * ((fp_gamma(3) * max_e * max_zt) + (de * max_zt + dz * max_e)) * inv_det.abs(); // Finally, do the check if t <= dt { @@ -133,12 +132,13 @@ pub fn intersect_ray(ray: &Ray, tri: (Point, Point, Point)) -> Option<(f32, f32, /// /// Returns the point and the error magnitude of the point. pub fn surface_point(tri: (Point, Point, Point), bary: (f32, f32, f32)) -> (Point, f32) { - let pos = ((tri.0.into_vector() * bary.0) + (tri.1.into_vector() * bary.1) + - (tri.2.into_vector() * bary.2)) + let pos = ((tri.0.into_vector() * bary.0) + (tri.1.into_vector() * bary.1) + + (tri.2.into_vector() * bary.2)) .into_point(); - let pos_err = (((tri.0.into_vector().abs() * bary.0) + (tri.1.into_vector().abs() * bary.1) + - (tri.2.into_vector().abs() * bary.2)) * fp_gamma(7)).co + let pos_err = (((tri.0.into_vector().abs() * bary.0) + (tri.1.into_vector().abs() * bary.1) + + (tri.2.into_vector().abs() * bary.2)) * fp_gamma(7)) + .co .h_max(); (pos, pos_err) diff --git a/src/surface/triangle_mesh.rs b/src/surface/triangle_mesh.rs index 29c8ca5..b06ed34 100644 --- a/src/surface/triangle_mesh.rs +++ b/src/surface/triangle_mesh.rs @@ -6,14 +6,13 @@ use accel::BVH4; use bbox::BBox; use boundable::Boundable; use lerp::lerp_slice; -use math::{Point, Normal, Matrix4x4, dot, cross}; -use ray::{Ray, AccelRay}; +use math::{cross, dot, Matrix4x4, Normal, Point}; +use ray::{AccelRay, Ray}; use shading::SurfaceShader; use super::{Surface, SurfaceIntersection, SurfaceIntersectionData}; use super::triangle; - #[derive(Copy, Clone, Debug)] pub struct TriangleMesh<'a> { time_sample_count: usize, @@ -94,8 +93,8 @@ impl<'a> TriangleMesh<'a> { // Build BVH let accel = BVH4::from_objects(arena, &mut indices[..], 3, |tri| { - &bounds[(tri.3 as usize * time_sample_count).. - ((tri.3 as usize + 1) * time_sample_count)] + &bounds + [(tri.3 as usize * time_sample_count)..((tri.3 as usize + 1) * time_sample_count)] }); TriangleMesh { @@ -114,7 +113,6 @@ impl<'a> Boundable for TriangleMesh<'a> { } } - impl<'a> Surface for TriangleMesh<'a> { fn intersect_rays( &self, @@ -131,27 +129,25 @@ impl<'a> Surface for TriangleMesh<'a> { Matrix4x4::new() }; - self.accel.traverse( - &mut accel_rays[..], - self.indices, - |tri_indices, rs| { + self.accel + .traverse(&mut accel_rays[..], self.indices, |tri_indices, rs| { for r in rs { let wr = &wrays[r.id as usize]; // Get triangle let tri = { - let p0_slice = &self.vertices[(tri_indices.0 as usize * - self.time_sample_count).. - ((tri_indices.0 as usize + 1) * - self.time_sample_count)]; - let p1_slice = &self.vertices[(tri_indices.1 as usize * - self.time_sample_count).. - ((tri_indices.1 as usize + 1) * - self.time_sample_count)]; - let p2_slice = &self.vertices[(tri_indices.2 as usize * - self.time_sample_count).. - ((tri_indices.2 as usize + 1) * - self.time_sample_count)]; + let p0_slice = &self.vertices[(tri_indices.0 as usize + * self.time_sample_count) + ..((tri_indices.0 as usize + 1) + * self.time_sample_count)]; + let p1_slice = &self.vertices[(tri_indices.1 as usize + * self.time_sample_count) + ..((tri_indices.1 as usize + 1) + * self.time_sample_count)]; + let p2_slice = &self.vertices[(tri_indices.2 as usize + * self.time_sample_count) + ..((tri_indices.2 as usize + 1) + * self.time_sample_count)]; let p0 = lerp_slice(p0_slice, wr.time); let p1 = lerp_slice(p1_slice, wr.time); @@ -166,18 +162,20 @@ impl<'a> Surface for TriangleMesh<'a> { if space.len() > 1 { // Per-ray transform, for motion blur let mat_space = lerp_slice(space, wr.time).inverse(); - (mat_space, ( - tri.0 * mat_space, - tri.1 * mat_space, - tri.2 * mat_space, - )) + ( + mat_space, + (tri.0 * mat_space, tri.1 * mat_space, tri.2 * mat_space), + ) } else { // Same transform for all rays - (static_mat_space, ( - tri.0 * static_mat_space, - tri.1 * static_mat_space, - tri.2 * static_mat_space, - )) + ( + static_mat_space, + ( + tri.0 * static_mat_space, + tri.1 * static_mat_space, + tri.2 * static_mat_space, + ), + ) } } else { // No transforms @@ -199,18 +197,18 @@ impl<'a> Surface for TriangleMesh<'a> { // Calculate interpolated surface normal, if any let shading_normal = if let Some(normals) = self.normals { - let n0_slice = &normals[(tri_indices.0 as usize * - self.time_sample_count).. - ((tri_indices.0 as usize + 1) * - self.time_sample_count)]; - let n1_slice = &normals[(tri_indices.1 as usize * - self.time_sample_count).. - ((tri_indices.1 as usize + 1) * - self.time_sample_count)]; - let n2_slice = &normals[(tri_indices.2 as usize * - self.time_sample_count).. - ((tri_indices.2 as usize + 1) * - self.time_sample_count)]; + let n0_slice = &normals[(tri_indices.0 as usize + * self.time_sample_count) + ..((tri_indices.0 as usize + 1) + * self.time_sample_count)]; + let n1_slice = &normals[(tri_indices.1 as usize + * self.time_sample_count) + ..((tri_indices.1 as usize + 1) + * self.time_sample_count)]; + let n2_slice = &normals[(tri_indices.2 as usize + * self.time_sample_count) + ..((tri_indices.2 as usize + 1) + * self.time_sample_count)]; let n0 = lerp_slice(n0_slice, wr.time).normalized(); let n1 = lerp_slice(n1_slice, wr.time).normalized(); @@ -252,7 +250,6 @@ impl<'a> Surface for TriangleMesh<'a> { } } } - }, - ); + }); } } diff --git a/src/timer.rs b/src/timer.rs index d838dea..352df15 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -5,7 +5,6 @@ use std::time::Duration; use time; - #[derive(Copy, Clone)] pub struct Timer { last_time: u64, @@ -13,7 +12,9 @@ pub struct Timer { impl Timer { pub fn new() -> Timer { - Timer { last_time: time::precise_time_ns() } + Timer { + last_time: time::precise_time_ns(), + } } /// Marks a new tick time and returns the time elapsed in seconds since diff --git a/src/tracer.rs b/src/tracer.rs index 07a5513..e855dc4 100644 --- a/src/tracer.rs +++ b/src/tracer.rs @@ -2,13 +2,12 @@ use std::iter; use algorithm::partition; use lerp::lerp_slice; -use ray::{Ray, AccelRay}; -use scene::{Assembly, Object, InstanceType}; +use ray::{AccelRay, Ray}; +use scene::{Assembly, InstanceType, Object}; use surface::SurfaceIntersection; use transform_stack::TransformStack; -use shading::{SurfaceShader, SimpleSurfaceShader}; -use color::{XYZ, rec709_to_xyz}; - +use shading::{SimpleSurfaceShader, SurfaceShader}; +use color::{rec709_to_xyz, XYZ}; pub struct Tracer<'a> { rays: Vec, @@ -31,9 +30,11 @@ impl<'a> Tracer<'a> { self.rays.clear(); self.rays.reserve(wrays.len()); let mut ids = 0..(wrays.len() as u32); - self.rays.extend(wrays.iter().map( - |wr| AccelRay::new(wr, ids.next().unwrap()), - )); + self.rays.extend( + wrays + .iter() + .map(|wr| AccelRay::new(wr, ids.next().unwrap())), + ); self.inner.trace(wrays, &mut self.rays[..]) } @@ -50,12 +51,8 @@ impl<'a> TracerInner<'a> { // Ready the isects self.isects.clear(); self.isects.reserve(wrays.len()); - self.isects.extend( - iter::repeat(SurfaceIntersection::Miss).take( - wrays - .len(), - ), - ); + self.isects + .extend(iter::repeat(SurfaceIntersection::Miss).take(wrays.len())); let mut ray_sets = split_rays_by_direction(&mut rays[..]); for ray_set in ray_sets.iter_mut().filter(|ray_set| !ray_set.is_empty()) { @@ -71,10 +68,9 @@ impl<'a> TracerInner<'a> { wrays: &[Ray], accel_rays: &mut [AccelRay], ) { - assembly.object_accel.traverse( - &mut accel_rays[..], - &assembly.instances[..], - |inst, rs| { + assembly + .object_accel + .traverse(&mut accel_rays[..], &assembly.instances[..], |inst, rs| { // Transform rays if needed if let Some((xstart, xend)) = inst.transform_indices { // Push transforms to stack @@ -130,9 +126,8 @@ impl<'a> TracerInner<'a> { InstanceType::Object => { self.trace_object( &assembly.objects[inst.data_index], - inst.surface_shader_index.map( - |i| assembly.surface_shaders[i], - ), + inst.surface_shader_index + .map(|i| assembly.surface_shaders[i]), wrays, ray_set, ); @@ -172,8 +167,7 @@ impl<'a> TracerInner<'a> { } } } - }, - ); + }); } fn trace_object<'b>( @@ -217,7 +211,6 @@ impl<'a> TracerInner<'a> { } } - fn split_rays_by_direction(rays: &mut [AccelRay]) -> [&mut [AccelRay]; 8] { // | | | | | | | | | // s1 s2 s3 s4 s5 s6 s7 diff --git a/src/transform_stack.rs b/src/transform_stack.rs index ac9347f..3041e4a 100644 --- a/src/transform_stack.rs +++ b/src/transform_stack.rs @@ -3,7 +3,6 @@ use std::cmp; use algorithm::merge_slices_to; use math::Matrix4x4; - pub struct TransformStack { stack: Vec, stack_indices: Vec, diff --git a/sub_crates/bvh_order/build.rs b/sub_crates/bvh_order/build.rs index 0f46941..0b1d99e 100644 --- a/sub_crates/bvh_order/build.rs +++ b/sub_crates/bvh_order/build.rs @@ -34,10 +34,8 @@ fn main() { perm.swap(0, 2); perm.swap(1, 3); } - traversal_table[raydir].push( - perm[0] + (perm[1] << 2) + (perm[2] << 4) + - (perm[3] << 6), - ); + traversal_table[raydir] + .push(perm[0] + (perm[1] << 2) + (perm[2] << 4) + (perm[3] << 6)); } } } diff --git a/sub_crates/bvh_order/src/lib.rs b/sub_crates/bvh_order/src/lib.rs index b1b66e6..f9717aa 100644 --- a/sub_crates/bvh_order/src/lib.rs +++ b/sub_crates/bvh_order/src/lib.rs @@ -19,9 +19,9 @@ include!(concat!(env!("OUT_DIR"), "/table_inc.rs")); #[derive(Debug, Copy, Clone)] pub enum SplitAxes { Full((u8, u8, u8)), // top, left, right - Left((u8, u8)), // top, left - Right((u8, u8)), // top, right - TopOnly(u8), // top + Left((u8, u8)), // top, left + Right((u8, u8)), // top, right + TopOnly(u8), // top } /// Calculates the traversal code for a BVH4 node based on the splits and diff --git a/sub_crates/color/build.rs b/sub_crates/color/build.rs index 91de910..e61b616 100644 --- a/sub_crates/color/build.rs +++ b/sub_crates/color/build.rs @@ -3,7 +3,6 @@ use std::fs::File; use std::io::Write; use std::path::Path; - #[derive(Copy, Clone)] struct Chromaticities { r: (f64, f64), @@ -12,7 +11,6 @@ struct Chromaticities { w: (f64, f64), } - fn main() { let out_dir = env::var("OUT_DIR").unwrap(); @@ -77,10 +75,8 @@ fn main() { } } - /// Generates conversion functions for the given rgb to xyz transform matrix. fn write_conversion_functions(space_name: &str, to_xyz: [[f64; 3]; 3], f: &mut File) { - f.write_all( format!( r#" @@ -185,7 +181,6 @@ pub fn xyz_to_{}_e(xyz: (f32, f32, f32)) -> (f32, f32, f32) {{ ).unwrap(); } - /// Port of the RGBtoXYZ function from the ACES CTL reference implementation. /// See lib/IlmCtlMath/CtlColorSpace.cpp in the CTL reference implementation. /// @@ -200,20 +195,20 @@ fn rgb_to_xyz(chroma: Chromaticities, y: f64) -> [[f64; 3]; 3] { let z = (1.0 - chroma.w.0 - chroma.w.1) * y / chroma.w.1; // Scale factors for matrix rows - let d = chroma.r.0 * (chroma.b.1 - chroma.g.1) + chroma.b.0 * (chroma.g.1 - chroma.r.1) + - chroma.g.0 * (chroma.r.1 - chroma.b.1); + let d = chroma.r.0 * (chroma.b.1 - chroma.g.1) + chroma.b.0 * (chroma.g.1 - chroma.r.1) + + chroma.g.0 * (chroma.r.1 - chroma.b.1); - let sr = (x * (chroma.b.1 - chroma.g.1) - - chroma.g.0 * (y * (chroma.b.1 - 1.0) + chroma.b.1 * (x + z)) + - chroma.b.0 * (y * (chroma.g.1 - 1.0) + chroma.g.1 * (x + z))) / d; + let sr = (x * (chroma.b.1 - chroma.g.1) + - chroma.g.0 * (y * (chroma.b.1 - 1.0) + chroma.b.1 * (x + z)) + + chroma.b.0 * (y * (chroma.g.1 - 1.0) + chroma.g.1 * (x + z))) / d; - let sg = (x * (chroma.r.1 - chroma.b.1) + - chroma.r.0 * (y * (chroma.b.1 - 1.0) + chroma.b.1 * (x + z)) - - chroma.b.0 * (y * (chroma.r.1 - 1.0) + chroma.r.1 * (x + z))) / d; + let sg = (x * (chroma.r.1 - chroma.b.1) + + chroma.r.0 * (y * (chroma.b.1 - 1.0) + chroma.b.1 * (x + z)) + - chroma.b.0 * (y * (chroma.r.1 - 1.0) + chroma.r.1 * (x + z))) / d; - let sb = (x * (chroma.g.1 - chroma.r.1) - - chroma.r.0 * (y * (chroma.g.1 - 1.0) + chroma.g.1 * (x + z)) + - chroma.g.0 * (y * (chroma.r.1 - 1.0) + chroma.r.1 * (x + z))) / d; + let sb = (x * (chroma.g.1 - chroma.r.1) + - chroma.r.0 * (y * (chroma.g.1 - 1.0) + chroma.g.1 * (x + z)) + + chroma.g.0 * (y * (chroma.r.1 - 1.0) + chroma.r.1 * (x + z))) / d; // Assemble the matrix let mut mat = [[0.0; 3]; 3]; @@ -233,7 +228,6 @@ fn rgb_to_xyz(chroma: Chromaticities, y: f64) -> [[f64; 3]; 3] { mat } - /// Chromatically adapts a matrix from `rgb_to_xyz` to a whitepoint of E. /// /// In other words, makes it so that RGB (1,1,1) maps to XYZ (1,1,1). @@ -259,7 +253,6 @@ fn adapt_to_e(mat: [[f64; 3]; 3], y: f64) -> [[f64; 3]; 3] { mat2 } - /// Calculates the inverse of the given 3x3 matrix. /// /// Ported to Rust from `gjInverse()` in IlmBase's Imath/ImathMatrix.h diff --git a/sub_crates/halton/build.rs b/sub_crates/halton/build.rs index 8a871e3..dfbc2c1 100644 --- a/sub_crates/halton/build.rs +++ b/sub_crates/halton/build.rs @@ -27,7 +27,6 @@ use std::fs::File; use std::io::Write; use std::path::Path; - /// How many components to generate. const NUM_DIMENSIONS: usize = 128; @@ -111,8 +110,7 @@ pub fn sample(dimension: u32, index: u32) -> f32 {{ format!( r#" {} => halton{}(index),"#, - i, - primes[i] + i, primes[i] ).as_bytes(), ).unwrap(); } @@ -127,7 +125,6 @@ pub fn sample(dimension: u32, index: u32) -> f32 {{ ).as_bytes(), ).unwrap(); - // Write the special-cased first dimension f.write_all( format!( @@ -196,9 +193,7 @@ fn halton{}(index: u32) -> f32 {{ format!( r#" return (unsafe{{*PERM{}.get_unchecked((index % {}) as usize)}} as u32 * {} +"#, - base, - pow_base, - power + base, pow_base, power ).as_bytes(), ).unwrap();; @@ -211,10 +206,7 @@ fn halton{}(index: u32) -> f32 {{ format!( r#" unsafe{{*PERM{}.get_unchecked(((index / {}) % {}) as usize)}} as u32 * {} +"#, - base, - div, - pow_base, - power + base, div, pow_base, power ).as_bytes(), ).unwrap();; } @@ -235,7 +227,6 @@ fn halton{}(index: u32) -> f32 {{ } } - /// Check primality. Not optimized, since it's not performance-critical. fn is_prime(p: usize) -> bool { for i in 2..p { @@ -271,10 +262,12 @@ fn get_faure_permutation(faure: &Vec>, b: usize) -> Vec { let c = b / 2; return (0..b) - .map(|i| if i < c { - 2 * faure[c][i] - } else { - 2 * faure[c][i - c] + 1 + .map(|i| { + if i < c { + 2 * faure[c][i] + } else { + 2 * faure[c][i - c] + 1 + } }) .collect(); } diff --git a/sub_crates/math3d/src/lib.rs b/sub_crates/math3d/src/lib.rs index 9757cc8..26cfe15 100644 --- a/sub_crates/math3d/src/lib.rs +++ b/sub_crates/math3d/src/lib.rs @@ -23,7 +23,6 @@ pub fn dot(a: T, b: T) -> f32 { a.dot(b) } - /// Trait for calculating cross products. pub trait CrossProduct { #[inline] diff --git a/sub_crates/math3d/src/matrix.rs b/sub_crates/math3d/src/matrix.rs index 9199250..f28fb4c 100644 --- a/sub_crates/math3d/src/matrix.rs +++ b/sub_crates/math3d/src/matrix.rs @@ -7,14 +7,12 @@ use float4::Float4; use super::Point; - /// A 4x4 matrix, used for transforms #[derive(Debug, Copy, Clone)] pub struct Matrix4x4 { pub values: [Float4; 4], } - impl Matrix4x4 { /// Creates a new identity matrix #[inline] @@ -143,7 +141,6 @@ impl Matrix4x4 { } } - /// Returns the inverse of the Matrix #[inline] pub fn inverse(&self) -> Matrix4x4 { @@ -169,31 +166,44 @@ impl Matrix4x4 { values: { [ Float4::new( - ((self[1].get_1() * c5) - (self[1].get_2() * c4) + (self[1].get_3() * c3)) * invdet, - ((-self[0].get_1() * c5) + (self[0].get_2() * c4) - (self[0].get_3() * c3)) * invdet, - ((self[3].get_1() * s5) - (self[3].get_2() * s4) + (self[3].get_3() * s3)) * invdet, - ((-self[2].get_1() * s5) + (self[2].get_2() * s4) - (self[2].get_3() * s3)) * invdet, + ((self[1].get_1() * c5) - (self[1].get_2() * c4) + (self[1].get_3() * c3)) + * invdet, + ((-self[0].get_1() * c5) + (self[0].get_2() * c4) - (self[0].get_3() * c3)) + * invdet, + ((self[3].get_1() * s5) - (self[3].get_2() * s4) + (self[3].get_3() * s3)) + * invdet, + ((-self[2].get_1() * s5) + (self[2].get_2() * s4) - (self[2].get_3() * s3)) + * invdet, ), - Float4::new( - ((-self[1].get_0() * c5) + (self[1].get_2() * c2) - (self[1].get_3() * c1)) * invdet, - ((self[0].get_0() * c5) - (self[0].get_2() * c2) + (self[0].get_3() * c1)) * invdet, - ((-self[3].get_0() * s5) + (self[3].get_2() * s2) - (self[3].get_3() * s1)) * invdet, - ((self[2].get_0() * s5) - (self[2].get_2() * s2) + (self[2].get_3() * s1)) * invdet, + ((-self[1].get_0() * c5) + (self[1].get_2() * c2) - (self[1].get_3() * c1)) + * invdet, + ((self[0].get_0() * c5) - (self[0].get_2() * c2) + (self[0].get_3() * c1)) + * invdet, + ((-self[3].get_0() * s5) + (self[3].get_2() * s2) - (self[3].get_3() * s1)) + * invdet, + ((self[2].get_0() * s5) - (self[2].get_2() * s2) + (self[2].get_3() * s1)) + * invdet, ), - Float4::new( - ((self[1].get_0() * c4) - (self[1].get_1() * c2) + (self[1].get_3() * c0)) * invdet, - ((-self[0].get_0() * c4) + (self[0].get_1() * c2) - (self[0].get_3() * c0)) * invdet, - ((self[3].get_0() * s4) - (self[3].get_1() * s2) + (self[3].get_3() * s0)) * invdet, - ((-self[2].get_0() * s4) + (self[2].get_1() * s2) - (self[2].get_3() * s0)) * invdet, + ((self[1].get_0() * c4) - (self[1].get_1() * c2) + (self[1].get_3() * c0)) + * invdet, + ((-self[0].get_0() * c4) + (self[0].get_1() * c2) - (self[0].get_3() * c0)) + * invdet, + ((self[3].get_0() * s4) - (self[3].get_1() * s2) + (self[3].get_3() * s0)) + * invdet, + ((-self[2].get_0() * s4) + (self[2].get_1() * s2) - (self[2].get_3() * s0)) + * invdet, ), - Float4::new( - ((-self[1].get_0() * c3) + (self[1].get_1() * c1) - (self[1].get_2() * c0)) * invdet, - ((self[0].get_0() * c3) - (self[0].get_1() * c1) + (self[0].get_2() * c0)) * invdet, - ((-self[3].get_0() * s3) + (self[3].get_1() * s1) - (self[3].get_2() * s0)) * invdet, - ((self[2].get_0() * s3) - (self[2].get_1() * s1) + (self[2].get_2() * s0)) * invdet, + ((-self[1].get_0() * c3) + (self[1].get_1() * c1) - (self[1].get_2() * c0)) + * invdet, + ((self[0].get_0() * c3) - (self[0].get_1() * c1) + (self[0].get_2() * c0)) + * invdet, + ((-self[3].get_0() * s3) + (self[3].get_1() * s1) - (self[3].get_2() * s0)) + * invdet, + ((self[2].get_0() * s3) - (self[2].get_1() * s1) + (self[2].get_2() * s0)) + * invdet, ), ] }, @@ -201,7 +211,6 @@ impl Matrix4x4 { } } - impl Index for Matrix4x4 { type Output = Float4; @@ -211,7 +220,6 @@ impl Index for Matrix4x4 { } } - impl IndexMut for Matrix4x4 { #[inline(always)] fn index_mut<'a>(&'a mut self, _index: usize) -> &'a mut Float4 { @@ -219,7 +227,6 @@ impl IndexMut for Matrix4x4 { } } - impl PartialEq for Matrix4x4 { #[inline] fn eq(&self, other: &Matrix4x4) -> bool { @@ -235,7 +242,6 @@ impl PartialEq for Matrix4x4 { } } - /// Multiply two matrices together impl Mul for Matrix4x4 { type Output = Matrix4x4; @@ -251,21 +257,18 @@ impl Mul for Matrix4x4 { (m[2] * other[0]).h_sum(), (m[3] * other[0]).h_sum(), ), - Float4::new( (m[0] * other[1]).h_sum(), (m[1] * other[1]).h_sum(), (m[2] * other[1]).h_sum(), (m[3] * other[1]).h_sum(), ), - Float4::new( (m[0] * other[2]).h_sum(), (m[1] * other[2]).h_sum(), (m[2] * other[2]).h_sum(), (m[3] * other[2]).h_sum(), ), - Float4::new( (m[0] * other[3]).h_sum(), (m[1] * other[3]).h_sum(), @@ -277,10 +280,6 @@ impl Mul for Matrix4x4 { } } - - - - #[cfg(test)] mod tests { use super::*; diff --git a/sub_crates/math3d/src/normal.rs b/sub_crates/math3d/src/normal.rs index 410181a..116f411 100644 --- a/sub_crates/math3d/src/normal.rs +++ b/sub_crates/math3d/src/normal.rs @@ -1,14 +1,13 @@ #![allow(dead_code)] use std::cmp::PartialEq; -use std::ops::{Add, Sub, Mul, Div, Neg}; +use std::ops::{Add, Div, Mul, Neg, Sub}; use float4::Float4; -use super::{DotProduct, CrossProduct}; +use super::{CrossProduct, DotProduct}; use super::{Matrix4x4, Vector}; - /// A surface normal in 3d homogeneous space. #[derive(Debug, Copy, Clone)] pub struct Normal { @@ -18,7 +17,9 @@ pub struct Normal { impl Normal { #[inline(always)] pub fn new(x: f32, y: f32, z: f32) -> Normal { - Normal { co: Float4::new(x, y, z, 0.0) } + Normal { + co: Float4::new(x, y, z, 0.0), + } } #[inline(always)] @@ -82,7 +83,6 @@ impl Normal { } } - impl PartialEq for Normal { #[inline(always)] fn eq(&self, other: &Normal) -> bool { @@ -90,33 +90,36 @@ impl PartialEq for Normal { } } - impl Add for Normal { type Output = Normal; #[inline(always)] fn add(self, other: Normal) -> Normal { - Normal { co: self.co + other.co } + Normal { + co: self.co + other.co, + } } } - impl Sub for Normal { type Output = Normal; #[inline(always)] fn sub(self, other: Normal) -> Normal { - Normal { co: self.co - other.co } + Normal { + co: self.co - other.co, + } } } - impl Mul for Normal { type Output = Normal; #[inline(always)] fn mul(self, other: f32) -> Normal { - Normal { co: self.co * other } + Normal { + co: self.co * other, + } } } @@ -137,17 +140,17 @@ impl Mul for Normal { } } - impl Div for Normal { type Output = Normal; #[inline(always)] fn div(self, other: f32) -> Normal { - Normal { co: self.co / other } + Normal { + co: self.co / other, + } } } - impl Neg for Normal { type Output = Normal; @@ -157,7 +160,6 @@ impl Neg for Normal { } } - impl DotProduct for Normal { #[inline(always)] fn dot(self, other: Normal) -> f32 { @@ -165,7 +167,6 @@ impl DotProduct for Normal { } } - impl CrossProduct for Normal { #[inline] fn cross(self, other: Normal) -> Normal { @@ -180,11 +181,10 @@ impl CrossProduct for Normal { } } - #[cfg(test)] mod tests { use super::*; - use super::super::{Matrix4x4, CrossProduct, DotProduct}; + use super::super::{CrossProduct, DotProduct, Matrix4x4}; #[test] fn add() { diff --git a/sub_crates/math3d/src/point.rs b/sub_crates/math3d/src/point.rs index ef36321..25ea710 100644 --- a/sub_crates/math3d/src/point.rs +++ b/sub_crates/math3d/src/point.rs @@ -1,14 +1,13 @@ #![allow(dead_code)] use std::cmp::PartialEq; -use std::ops::{Add, Sub, Mul}; +use std::ops::{Add, Mul, Sub}; use float4::Float4; use super::Matrix4x4; use super::Vector; - /// A position in 3d homogeneous space. #[derive(Debug, Copy, Clone)] pub struct Point { @@ -18,14 +17,18 @@ pub struct Point { impl Point { #[inline(always)] pub fn new(x: f32, y: f32, z: f32) -> Point { - Point { co: Float4::new(x, y, z, 1.0) } + Point { + co: Float4::new(x, y, z, 1.0), + } } /// Returns the point in standardized coordinates, where the /// fourth homogeneous component has been normalized to 1.0. #[inline(always)] pub fn norm(&self) -> Point { - Point { co: self.co / self.co.get_3() } + Point { + co: self.co / self.co.get_3(), + } } #[inline(always)] @@ -33,7 +36,9 @@ impl Point { let n1 = self.norm(); let n2 = other.norm(); - Point { co: n1.co.v_min(n2.co) } + Point { + co: n1.co.v_min(n2.co), + } } #[inline(always)] @@ -41,7 +46,9 @@ impl Point { let n1 = self.norm(); let n2 = other.norm(); - Point { co: n1.co.v_max(n2.co) } + Point { + co: n1.co.v_max(n2.co), + } } #[inline(always)] @@ -90,7 +97,6 @@ impl Point { } } - impl PartialEq for Point { #[inline(always)] fn eq(&self, other: &Point) -> bool { @@ -98,23 +104,25 @@ impl PartialEq for Point { } } - impl Add for Point { type Output = Point; #[inline(always)] fn add(self, other: Vector) -> Point { - Point { co: self.co + other.co } + Point { + co: self.co + other.co, + } } } - impl Sub for Point { type Output = Vector; #[inline(always)] fn sub(self, other: Point) -> Vector { - Vector { co: self.norm().co - other.norm().co } + Vector { + co: self.norm().co - other.norm().co, + } } } @@ -123,7 +131,9 @@ impl Sub for Point { #[inline(always)] fn sub(self, other: Vector) -> Point { - Point { co: self.co - other.co } + Point { + co: self.co - other.co, + } } } @@ -143,11 +153,10 @@ impl Mul for Point { } } - #[cfg(test)] mod tests { use super::*; - use super::super::{Vector, Matrix4x4}; + use super::super::{Matrix4x4, Vector}; #[test] fn norm() { diff --git a/sub_crates/math3d/src/vector.rs b/sub_crates/math3d/src/vector.rs index 2e52980..2e440dd 100644 --- a/sub_crates/math3d/src/vector.rs +++ b/sub_crates/math3d/src/vector.rs @@ -1,13 +1,12 @@ #![allow(dead_code)] use std::cmp::PartialEq; -use std::ops::{Add, Sub, Mul, Div, Neg}; +use std::ops::{Add, Div, Mul, Neg, Sub}; use float4::Float4; -use super::{DotProduct, CrossProduct}; -use super::{Matrix4x4, Point, Normal}; - +use super::{CrossProduct, DotProduct}; +use super::{Matrix4x4, Normal, Point}; /// A direction vector in 3d homogeneous space. #[derive(Debug, Copy, Clone)] @@ -18,7 +17,9 @@ pub struct Vector { impl Vector { #[inline(always)] pub fn new(x: f32, y: f32, z: f32) -> Vector { - Vector { co: Float4::new(x, y, z, 0.0) } + Vector { + co: Float4::new(x, y, z, 0.0), + } } #[inline(always)] @@ -92,7 +93,6 @@ impl Vector { } } - impl PartialEq for Vector { #[inline(always)] fn eq(&self, other: &Vector) -> bool { @@ -100,37 +100,39 @@ impl PartialEq for Vector { } } - impl Add for Vector { type Output = Vector; #[inline(always)] fn add(self, other: Vector) -> Vector { - Vector { co: self.co + other.co } + Vector { + co: self.co + other.co, + } } } - impl Sub for Vector { type Output = Vector; #[inline(always)] fn sub(self, other: Vector) -> Vector { - Vector { co: self.co - other.co } + Vector { + co: self.co - other.co, + } } } - impl Mul for Vector { type Output = Vector; #[inline(always)] fn mul(self, other: f32) -> Vector { - Vector { co: self.co * other } + Vector { + co: self.co * other, + } } } - impl Mul for Vector { type Output = Vector; @@ -147,17 +149,17 @@ impl Mul for Vector { } } - impl Div for Vector { type Output = Vector; #[inline(always)] fn div(self, other: f32) -> Vector { - Vector { co: self.co / other } + Vector { + co: self.co / other, + } } } - impl Neg for Vector { type Output = Vector; @@ -167,7 +169,6 @@ impl Neg for Vector { } } - impl DotProduct for Vector { #[inline(always)] fn dot(self, other: Vector) -> f32 { @@ -175,7 +176,6 @@ impl DotProduct for Vector { } } - impl CrossProduct for Vector { #[inline] fn cross(self, other: Vector) -> Vector { @@ -190,11 +190,10 @@ impl CrossProduct for Vector { } } - #[cfg(test)] mod tests { use super::*; - use super::super::{Matrix4x4, CrossProduct, DotProduct}; + use super::super::{CrossProduct, DotProduct, Matrix4x4}; #[test] fn add() { diff --git a/sub_crates/mem_arena/src/lib.rs b/sub_crates/mem_arena/src/lib.rs index 7889c92..5f5921d 100644 --- a/sub_crates/mem_arena/src/lib.rs +++ b/sub_crates/mem_arena/src/lib.rs @@ -1,6 +1,6 @@ use std::slice; use std::cell::{Cell, RefCell}; -use std::mem::{size_of, align_of}; +use std::mem::{align_of, size_of}; use std::cmp::max; const GROWTH_FRACTION: usize = 8; // 1/N (smaller number leads to bigger allocations) @@ -261,10 +261,8 @@ impl MemArena { unsafe fn alloc_raw(&self, size: usize, alignment: usize) -> *mut u8 { assert!(alignment > 0); - self.stat_space_allocated.set( - self.stat_space_allocated.get() + - size, - ); // Update stats + self.stat_space_allocated + .set(self.stat_space_allocated.get() + size); // Update stats let mut blocks = self.blocks.borrow_mut(); @@ -302,21 +300,22 @@ impl MemArena { }; let waste_percentage = { - let w1 = ((blocks[0].capacity() - blocks[0].len()) * 100) / - blocks[0].capacity(); - let w2 = ((self.stat_space_occupied.get() - self.stat_space_allocated.get()) * - 100) / - self.stat_space_occupied.get(); - if w1 < w2 { w1 } else { w2 } + let w1 = + ((blocks[0].capacity() - blocks[0].len()) * 100) / blocks[0].capacity(); + let w2 = ((self.stat_space_occupied.get() - self.stat_space_allocated.get()) + * 100) / self.stat_space_occupied.get(); + if w1 < w2 { + w1 + } else { + w2 + } }; // If it's a "large allocation", give it its own memory block. if (size + alignment) > next_size || waste_percentage > self.max_waste_percentage { // Update stats - self.stat_space_occupied.set( - self.stat_space_occupied.get() + size + alignment - - 1, - ); + self.stat_space_occupied + .set(self.stat_space_occupied.get() + size + alignment - 1); blocks.push(Vec::with_capacity(size + alignment - 1)); blocks.last_mut().unwrap().set_len(size + alignment - 1); @@ -330,10 +329,8 @@ impl MemArena { // Otherwise create a new shared block. else { // Update stats - self.stat_space_occupied.set( - self.stat_space_occupied.get() + - next_size, - ); + self.stat_space_occupied + .set(self.stat_space_occupied.get() + next_size); blocks.push(Vec::with_capacity(next_size)); let block_count = blocks.len(); diff --git a/sub_crates/sobol/src/lib.rs b/sub_crates/sobol/src/lib.rs index f968cd0..47b5a8b 100644 --- a/sub_crates/sobol/src/lib.rs +++ b/sub_crates/sobol/src/lib.rs @@ -23,7 +23,7 @@ mod matrices; pub use matrices::NUM_DIMENSIONS; -use matrices::{SIZE, MATRICES}; +use matrices::{MATRICES, SIZE}; /// Compute one component of the Sobol'-sequence, where the component /// corresponds to the dimension parameter, and the index specifies