Bunch of code quality improvements based on running clippy.

None of them change behavior, just make the code cleaner.
This commit is contained in:
Nathan Vegdahl 2017-07-22 17:21:11 -07:00
parent 3cb684514a
commit c0a26819c6
35 changed files with 354 additions and 353 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
target target
*.rs.bk *.rs.bk
clippy.toml
# Python Byte-compiled / optimized / DLL files # Python Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/

View File

@ -48,7 +48,7 @@ impl<'a> BVH<'a> {
where where
F: 'b + Fn(&T) -> &'b [BBox], F: 'b + Fn(&T) -> &'b [BBox],
{ {
if objects.len() == 0 { if objects.is_empty() {
BVH { BVH {
root: None, root: None,
depth: 0, depth: 0,
@ -96,8 +96,8 @@ impl<'a> BVH<'a> {
while stack_ptr > 0 { while stack_ptr > 0 {
node_tests += ray_i_stack[stack_ptr] as u64; node_tests += ray_i_stack[stack_ptr] as u64;
match node_stack[stack_ptr] { match *node_stack[stack_ptr] {
&BVHNode::Internal { BVHNode::Internal {
children, children,
bounds_start, bounds_start,
bounds_len, bounds_len,
@ -124,7 +124,7 @@ impl<'a> BVH<'a> {
} }
} }
&BVHNode::Leaf { BVHNode::Leaf {
object_range, object_range,
bounds_start, bounds_start,
bounds_len, bounds_len,
@ -161,13 +161,14 @@ impl<'a> BVH<'a> {
}); });
} }
#[cfg_attr(feature = "cargo-clippy", allow(mut_from_ref))]
fn construct_from_base( fn construct_from_base(
arena: &'a MemArena, arena: &'a MemArena,
base: &BVHBase, base: &BVHBase,
node_index: usize, node_index: usize,
) -> &'a mut BVHNode<'a> { ) -> &'a mut BVHNode<'a> {
match &base.nodes[node_index] { match base.nodes[node_index] {
&BVHBaseNode::Internal { BVHBaseNode::Internal {
bounds_range, bounds_range,
children_indices, children_indices,
split_axis, split_axis,
@ -188,10 +189,10 @@ impl<'a> BVH<'a> {
children: (child1, child2), children: (child1, child2),
}; };
return node; node
} }
&BVHBaseNode::Leaf { BVHBaseNode::Leaf {
bounds_range, bounds_range,
object_range, object_range,
} => { } => {
@ -204,7 +205,7 @@ impl<'a> BVH<'a> {
object_range: object_range, object_range: object_range,
}; };
return node; node
} }
} }
} }
@ -215,18 +216,17 @@ lazy_static! {
} }
impl<'a> Boundable for BVH<'a> { impl<'a> Boundable for BVH<'a> {
fn bounds<'b>(&'b self) -> &'b [BBox] { fn bounds(&self) -> &[BBox] {
match self.root { match self.root {
None => &DEGENERATE_BOUNDS[..], None => &DEGENERATE_BOUNDS[..],
Some(root) => { Some(root) => {
match root { match *root {
&BVHNode::Internal { BVHNode::Internal {
bounds_start, bounds_start,
bounds_len, bounds_len,
.. ..
} => unsafe { std::slice::from_raw_parts(bounds_start, bounds_len as usize) }, } |
BVHNode::Leaf {
&BVHNode::Leaf {
bounds_start, bounds_start,
bounds_len, bounds_len,
.. ..

View File

@ -49,7 +49,7 @@ impl<'a> BVH4<'a> {
where where
F: 'b + Fn(&T) -> &'b [BBox], F: 'b + Fn(&T) -> &'b [BBox],
{ {
if objects.len() == 0 { if objects.is_empty() {
BVH4 { BVH4 {
root: None, root: None,
depth: 0, depth: 0,
@ -100,8 +100,8 @@ impl<'a> BVH4<'a> {
while stack_ptr > 0 { while stack_ptr > 0 {
node_tests += ray_i_stack[stack_ptr] as u64; node_tests += ray_i_stack[stack_ptr] as u64;
match node_stack[stack_ptr] { match *node_stack[stack_ptr] {
&BVH4Node::Inner { BVH4Node::Inner {
traversal_code, traversal_code,
bounds_start, bounds_start,
bounds_len, bounds_len,
@ -167,7 +167,7 @@ impl<'a> BVH4<'a> {
} }
} }
&BVH4Node::Leaf { BVH4Node::Leaf {
object_range, object_range,
bounds_start, bounds_start,
bounds_len, bounds_len,
@ -210,8 +210,8 @@ impl<'a> BVH4<'a> {
node_index: usize, node_index: usize,
node_mem: &mut BVH4Node<'a>, node_mem: &mut BVH4Node<'a>,
) { ) {
match &base.nodes[node_index] { match base.nodes[node_index] {
&BVHBaseNode::Internal { BVHBaseNode::Internal {
bounds_range, bounds_range,
children_indices, children_indices,
split_axis, split_axis,
@ -223,14 +223,14 @@ impl<'a> BVH4<'a> {
let child_count: usize; let child_count: usize;
let child_indices: [usize; 4]; let child_indices: [usize; 4];
let split_info: SplitAxes; let split_info: SplitAxes;
match child_l { match *child_l {
&BVHBaseNode::Internal { BVHBaseNode::Internal {
children_indices: i_l, children_indices: i_l,
split_axis: s_l, split_axis: s_l,
.. ..
} => { } => {
match child_r { match *child_r {
&BVHBaseNode::Internal { BVHBaseNode::Internal {
children_indices: i_r, children_indices: i_r,
split_axis: s_r, split_axis: s_r,
.. ..
@ -240,7 +240,7 @@ impl<'a> BVH4<'a> {
child_indices = [i_l.0, i_l.1, i_r.0, i_r.1]; child_indices = [i_l.0, i_l.1, i_r.0, i_r.1];
split_info = SplitAxes::Full((split_axis, s_l, s_r)); split_info = SplitAxes::Full((split_axis, s_l, s_r));
} }
&BVHBaseNode::Leaf { .. } => { BVHBaseNode::Leaf { .. } => {
// Three nodes with left split // Three nodes with left split
child_count = 3; child_count = 3;
child_indices = [i_l.0, i_l.1, children_indices.1, 0]; child_indices = [i_l.0, i_l.1, children_indices.1, 0];
@ -248,9 +248,9 @@ impl<'a> BVH4<'a> {
} }
} }
} }
&BVHBaseNode::Leaf { .. } => { BVHBaseNode::Leaf { .. } => {
match child_r { match *child_r {
&BVHBaseNode::Internal { BVHBaseNode::Internal {
children_indices: i_r, children_indices: i_r,
split_axis: s_r, split_axis: s_r,
.. ..
@ -260,7 +260,7 @@ impl<'a> BVH4<'a> {
child_indices = [children_indices.0, i_r.0, i_r.1, 0]; child_indices = [children_indices.0, i_r.0, i_r.1, 0];
split_info = SplitAxes::Right((split_axis, s_r)); split_info = SplitAxes::Right((split_axis, s_r));
} }
&BVHBaseNode::Leaf { .. } => { BVHBaseNode::Leaf { .. } => {
// Two nodes // Two nodes
child_count = 2; child_count = 2;
child_indices = [children_indices.0, children_indices.1, 0, 0]; child_indices = [children_indices.0, children_indices.1, 0, 0];
@ -293,7 +293,7 @@ impl<'a> BVH4<'a> {
}; };
} }
&BVHBaseNode::Leaf { BVHBaseNode::Leaf {
bounds_range, bounds_range,
object_range, object_range,
} => { } => {
@ -314,18 +314,17 @@ lazy_static! {
} }
impl<'a> Boundable for BVH4<'a> { impl<'a> Boundable for BVH4<'a> {
fn bounds<'b>(&'b self) -> &'b [BBox] { fn bounds(&self) -> &[BBox] {
match self.root { match self.root {
None => &DEGENERATE_BOUNDS[..], None => &DEGENERATE_BOUNDS[..],
Some(root) => { Some(root) => {
match root { match *root {
&BVH4Node::Inner { BVH4Node::Inner {
bounds_start, bounds_start,
bounds_len, bounds_len,
.. ..
} => unsafe { std::slice::from_raw_parts(bounds_start, bounds_len as usize) }, } |
BVH4Node::Leaf {
&BVH4Node::Leaf {
bounds_start, bounds_start,
bounds_len, bounds_len,
.. ..

View File

@ -40,9 +40,9 @@ pub enum BVHBaseNode {
impl BVHBaseNode { impl BVHBaseNode {
pub fn bounds_range(&self) -> (usize, usize) { pub fn bounds_range(&self) -> (usize, usize) {
match self { match *self {
&BVHBaseNode::Internal { bounds_range, .. } => bounds_range, BVHBaseNode::Internal { bounds_range, .. } |
&BVHBaseNode::Leaf { bounds_range, .. } => bounds_range, BVHBaseNode::Leaf { bounds_range, .. } => bounds_range,
} }
} }
} }
@ -82,7 +82,7 @@ impl BVHBase {
for obj in objects.iter() { for obj in objects.iter() {
let bounds = bounder(obj); let bounds = bounder(obj);
debug_assert!(bounds.len() > 0); debug_assert!(!bounds.is_empty());
if bounds.len() == max_len { if bounds.len() == max_len {
for i in 0..bounds.len() { for i in 0..bounds.len() {
self.bounds_cache[i] |= bounds[i]; self.bounds_cache[i] |= bounds[i];
@ -109,7 +109,7 @@ impl BVHBase {
{ {
let me = self.nodes.len(); let me = self.nodes.len();
if objects.len() == 0 { if objects.is_empty() {
return (0, (0, 0)); return (0, (0, 0));
} else if objects.len() <= objects_per_leaf { } else if objects.len() <= objects_per_leaf {
// Leaf node // Leaf node

View File

@ -53,7 +53,7 @@ impl<'a> LightAccel for LightArray<'a> {
assert!(n >= 0.0 && n <= 1.0); assert!(n >= 0.0 && n <= 1.0);
if self.indices.len() == 0 { if self.indices.is_empty() {
return None; return None;
} }

View File

@ -37,23 +37,23 @@ enum Node<'a> {
impl<'a> Node<'a> { impl<'a> Node<'a> {
fn bounds(&self) -> &'a [BBox] { fn bounds(&self) -> &'a [BBox] {
match self { match *self {
&Node::Inner { ref bounds, .. } => bounds, Node::Inner { bounds, .. } |
&Node::Leaf { ref bounds, .. } => bounds, Node::Leaf { bounds, .. } => bounds,
} }
} }
fn energy(&self) -> f32 { fn energy(&self) -> f32 {
match self { match *self {
&Node::Inner { energy, .. } => energy, Node::Inner { energy, .. } |
&Node::Leaf { energy, .. } => energy, Node::Leaf { energy, .. } => energy,
} }
} }
fn light_index(&self) -> usize { fn light_index(&self) -> usize {
match self { match *self {
&Node::Inner { .. } => panic!(), Node::Inner { .. } => panic!(),
&Node::Leaf { light_index, .. } => light_index, Node::Leaf { light_index, .. } => light_index,
} }
} }
} }
@ -67,7 +67,7 @@ impl<'a> LightTree<'a> {
where where
F: 'b + Fn(&T) -> (&'b [BBox], f32), F: 'b + Fn(&T) -> (&'b [BBox], f32),
{ {
if objects.len() == 0 { if objects.is_empty() {
LightTree { LightTree {
root: None, root: None,
depth: 0, depth: 0,
@ -170,44 +170,40 @@ impl<'a> LightAccel for LightTree<'a> {
let mut node = self.root.unwrap(); let mut node = self.root.unwrap();
let mut tot_prob = 1.0; let mut tot_prob = 1.0;
let mut n = n; let mut n = n;
loop { while let Node::Inner { children, .. } = *node {
if let Node::Inner { children, .. } = *node { // Calculate the relative probabilities of the children
// Calculate the relative probabilities of the children let ps = {
let ps = { let mut ps = [0.0; ARITY];
let mut ps = [0.0; ARITY]; let mut total = 0.0;
let mut total = 0.0; for (i, child) in children.iter().enumerate() {
for (i, child) in children.iter().enumerate() { let p = node_prob(child);
let p = node_prob(child); ps[i] = p;
ps[i] = p; total += p;
total += p; }
if total <= 0.0 {
let p = 1.0 / children.len() as f32;
for prob in &mut ps[..] {
*prob = p;
} }
if total <= 0.0 { } else {
let p = 1.0 / children.len() as f32; for prob in &mut ps[..] {
for prob in &mut ps[..] { *prob /= total;
*prob = p;
}
} else {
for prob in &mut ps[..] {
*prob = *prob / total;
}
}
ps
};
// Pick child and update probabilities
let mut base = 0.0;
for (i, &p) in ps.iter().enumerate() {
if (n <= base + p) || (i == children.len() - 1) {
tot_prob *= p;
node = &children[i];
n = (n - base) / p;
break;
} else {
base += p;
} }
} }
} else { ps
break; };
// Pick child and update probabilities
let mut base = 0.0;
for (i, &p) in ps.iter().enumerate() {
if (n <= base + p) || (i == children.len() - 1) {
tot_prob *= p;
node = &children[i];
n = (n - base) / p;
break;
} else {
base += p;
}
} }
} }
@ -216,7 +212,7 @@ impl<'a> LightAccel for LightTree<'a> {
} }
fn approximate_energy(&self) -> f32 { fn approximate_energy(&self) -> f32 {
if let Some(ref node) = self.root { if let Some(node) = self.root {
node.energy() node.energy()
} else { } else {
0.0 0.0
@ -270,17 +266,18 @@ impl LightTreeBuilder {
pub fn node_child_count_recurse(&self, level_collapse: usize, node_index: usize) -> usize { pub fn node_child_count_recurse(&self, level_collapse: usize, node_index: usize) -> usize {
if level_collapse > 0 { if level_collapse > 0 {
if self.nodes[node_index].is_leaf { if self.nodes[node_index].is_leaf {
return 1; 1
} else { } else {
let a = self.node_child_count_recurse(level_collapse - 1, node_index + 1); let a = self.node_child_count_recurse(level_collapse - 1, node_index + 1);
let b = self.node_child_count_recurse( let b = self.node_child_count_recurse(
level_collapse - 1, level_collapse - 1,
self.nodes[node_index].child_index, self.nodes[node_index].child_index,
); );
return a + b;
a + b
} }
} else { } else {
return 1; 1
} }
} }
@ -320,7 +317,7 @@ impl LightTreeBuilder {
{ {
let me_index = self.nodes.len(); let me_index = self.nodes.len();
if objects.len() == 0 { if objects.is_empty() {
return (0, (0, 0)); return (0, (0, 0));
} else if objects.len() == 1 { } else if objects.len() == 1 {
// Leaf node // Leaf node

View File

@ -170,7 +170,7 @@ where
// Pre-calc SAH div points // Pre-calc SAH div points
let sah_divs = { let sah_divs = {
let mut sah_divs = [[0.0f32; SAH_BIN_COUNT - 1]; 3]; let mut sah_divs = [[0.0f32; SAH_BIN_COUNT - 1]; 3];
for d in 0..3 { for d in 0..sah_divs.len() {
let extent = bounds.max.get_n(d) - bounds.min.get_n(d); let extent = bounds.max.get_n(d) - bounds.min.get_n(d);
for div in 0..(SAH_BIN_COUNT - 1) { for div in 0..(SAH_BIN_COUNT - 1) {
let part = extent * ((div + 1) as f32 / SAH_BIN_COUNT as f32); let part = extent * ((div + 1) as f32 / SAH_BIN_COUNT as f32);

View File

@ -16,7 +16,7 @@ pub fn weighted_choice<T, F>(slc: &[T], n: f32, weight: F) -> (usize, f32)
where where
F: Fn(&T) -> f32, F: Fn(&T) -> f32,
{ {
assert!(slc.len() > 0); assert!(!slc.is_empty());
let total_weight = slc.iter().fold(0.0, |sum, v| sum + weight(v)); let total_weight = slc.iter().fold(0.0, |sum, v| sum + weight(v));
let n = n * total_weight; let n = n * total_weight;
@ -147,7 +147,7 @@ pub fn partition_pair<A, B, F>(slc1: &mut [A], slc2: &mut [B], mut pred: F) -> u
where where
F: FnMut(usize, &mut A, &mut B) -> bool, F: FnMut(usize, &mut A, &mut B) -> bool,
{ {
assert!(slc1.len() == slc2.len()); assert_eq!(slc1.len(), slc2.len());
// This version uses raw pointers and pointer arithmetic to squeeze more // This version uses raw pointers and pointer arithmetic to squeeze more
// performance out of the code. // performance out of the code.
@ -233,7 +233,7 @@ where
} }
} }
/// Merges two slices of things, appending the result to vec_out /// Merges two slices of things, appending the result to `vec_out`
pub fn merge_slices_append<T: Lerp + Copy, F>( pub fn merge_slices_append<T: Lerp + Copy, F>(
slice1: &[T], slice1: &[T],
slice2: &[T], slice2: &[T],
@ -243,7 +243,7 @@ pub fn merge_slices_append<T: Lerp + Copy, F>(
F: Fn(&T, &T) -> T, F: Fn(&T, &T) -> T,
{ {
// Transform the bounding boxes // Transform the bounding boxes
if slice1.len() == 0 || slice2.len() == 0 { if slice1.is_empty() || slice2.is_empty() {
return; return;
} else if slice1.len() == slice2.len() { } else if slice1.len() == slice2.len() {
for (xf1, xf2) in Iterator::zip(slice1.iter(), slice2.iter()) { for (xf1, xf2) in Iterator::zip(slice1.iter(), slice2.iter()) {
@ -264,16 +264,16 @@ pub fn merge_slices_append<T: Lerp + Copy, F>(
} }
} }
/// Merges two slices of things, storing the result in slice_out. /// Merges two slices of things, storing the result in `slice_out`.
/// Panics if slice_out is not the right size. /// Panics if `slice_out` is not the right size.
pub fn merge_slices_to<T: Lerp + Copy, F>(slice1: &[T], slice2: &[T], slice_out: &mut [T], merge: F) pub fn merge_slices_to<T: Lerp + Copy, F>(slice1: &[T], slice2: &[T], slice_out: &mut [T], merge: F)
where where
F: Fn(&T, &T) -> T, F: Fn(&T, &T) -> T,
{ {
assert!(slice_out.len() == cmp::max(slice1.len(), slice2.len())); assert_eq!(slice_out.len(), cmp::max(slice1.len(), slice2.len()));
// Transform the bounding boxes // Transform the bounding boxes
if slice1.len() == 0 || slice2.len() == 0 { if slice1.is_empty() || slice2.is_empty() {
return; return;
} else if slice1.len() == slice2.len() { } else if slice1.len() == slice2.len() {
for (xfo, (xf1, xf2)) in for (xfo, (xf1, xf2)) in

View File

@ -52,7 +52,7 @@ impl BBox {
let near_hit_t = near_t.h_max(); let near_hit_t = near_t.h_max();
// Did we hit? // Did we hit?
return near_hit_t <= far_hit_t; near_hit_t <= far_hit_t
} }
// Creates a new BBox transformed into a different space. // Creates a new BBox transformed into a different space.
@ -71,13 +71,13 @@ impl BBox {
// Transform BBox corners and make new bbox // Transform BBox corners and make new bbox
let mut b = BBox::new(); let mut b = BBox::new();
for v in vs.iter() { for v in &vs {
let v = *v * xform; let v = *v * xform;
b.min = v.min(b.min); b.min = v.min(b.min);
b.max = v.max(b.max); b.max = v.max(b.max);
} }
return b; b
} }
pub fn surface_area(&self) -> f32 { pub fn surface_area(&self) -> f32 {
@ -95,7 +95,7 @@ impl BBox {
} }
/// Union of two BBoxes. /// Union of two `BBox`es.
impl BitOr for BBox { impl BitOr for BBox {
type Output = BBox; type Output = BBox;
@ -113,7 +113,7 @@ impl BitOrAssign for BBox {
} }
} }
/// Expand BBox by a point. /// Expand `BBox` by a point.
impl BitOr<Point> for BBox { impl BitOr<Point> for BBox {
type Output = BBox; type Output = BBox;
@ -146,8 +146,8 @@ pub fn transform_bbox_slice_from(bbs_in: &[BBox], xforms: &[Matrix4x4], bbs_out:
bbs_out.clear(); bbs_out.clear();
// Transform the bounding boxes // Transform the bounding boxes
if xforms.len() == 0 { if xforms.is_empty() {
return; bbs_out.extend_from_slice(bbs_in);
} else if bbs_in.len() == xforms.len() { } else if bbs_in.len() == xforms.len() {
for (bb, xf) in Iterator::zip(bbs_in.iter(), xforms.iter()) { for (bb, xf) in Iterator::zip(bbs_in.iter(), xforms.iter()) {
bbs_out.push(bb.transformed(xf.inverse())); bbs_out.push(bb.transformed(xf.inverse()));

View File

@ -4,5 +4,5 @@ use bbox::BBox;
pub trait Boundable { pub trait Boundable {
fn bounds<'a>(&'a self) -> &'a [BBox]; fn bounds(&self) -> &[BBox];
} }

View File

@ -25,20 +25,20 @@ impl<'a> Camera<'a> {
mut aperture_radii: Vec<f32>, mut aperture_radii: Vec<f32>,
mut focus_distances: Vec<f32>, mut focus_distances: Vec<f32>,
) -> Camera<'a> { ) -> Camera<'a> {
assert!(transforms.len() != 0, "Camera has no transform(s)!"); assert!(!transforms.is_empty(), "Camera has no transform(s)!");
assert!(fovs.len() != 0, "Camera has no fov(s)!"); assert!(!fovs.is_empty(), "Camera has no fov(s)!");
// Aperture needs focus distance and vice-versa. // Aperture needs focus distance and vice-versa.
if aperture_radii.len() == 0 || focus_distances.len() == 0 { if aperture_radii.is_empty() || focus_distances.is_empty() {
aperture_radii = vec![0.0]; aperture_radii = vec![0.0];
focus_distances = vec![1.0]; focus_distances = vec![1.0];
if aperture_radii.len() == 0 && focus_distances.len() != 0 { if aperture_radii.is_empty() && !focus_distances.is_empty() {
println!( println!(
"WARNING: camera has aperture radius but no focus distance. Disabling \ "WARNING: camera has aperture radius but no focus distance. Disabling \
focal blur." focal blur."
); );
} else if aperture_radii.len() != 0 && focus_distances.len() == 0 { } else if !aperture_radii.is_empty() && focus_distances.is_empty() {
println!( println!(
"WARNING: camera has focus distance but no aperture radius. Disabling \ "WARNING: camera has focus distance but no aperture radius. Disabling \
focal blur." focal blur."
@ -71,10 +71,10 @@ impl<'a> Camera<'a> {
pub fn generate_ray(&self, x: f32, y: f32, time: f32, u: f32, v: f32) -> Ray { pub fn generate_ray(&self, x: f32, y: f32, time: f32, u: f32, v: f32) -> Ray {
// Get time-interpolated camera settings // Get time-interpolated camera settings
let transform = lerp_slice(&self.transforms, time); let transform = lerp_slice(self.transforms, time);
let tfov = lerp_slice(&self.tfovs, time); let tfov = lerp_slice(self.tfovs, time);
let aperture_radius = lerp_slice(&self.aperture_radii, time); let aperture_radius = lerp_slice(self.aperture_radii, time);
let focus_distance = lerp_slice(&self.focus_distances, time); let focus_distance = lerp_slice(self.focus_distances, time);
// Ray origin // Ray origin
let orig = { let orig = {

View File

@ -85,7 +85,7 @@ impl SpectralSample {
impl Add for SpectralSample { impl Add for SpectralSample {
type Output = SpectralSample; type Output = SpectralSample;
fn add(self, rhs: SpectralSample) -> Self::Output { fn add(self, rhs: SpectralSample) -> Self::Output {
assert!(self.hero_wavelength == rhs.hero_wavelength); assert_eq!(self.hero_wavelength, rhs.hero_wavelength);
SpectralSample { SpectralSample {
e: self.e + rhs.e, e: self.e + rhs.e,
hero_wavelength: self.hero_wavelength, hero_wavelength: self.hero_wavelength,
@ -95,7 +95,7 @@ impl Add for SpectralSample {
impl AddAssign for SpectralSample { impl AddAssign for SpectralSample {
fn add_assign(&mut self, rhs: SpectralSample) { fn add_assign(&mut self, rhs: SpectralSample) {
assert!(self.hero_wavelength == rhs.hero_wavelength); assert_eq!(self.hero_wavelength, rhs.hero_wavelength);
self.e = self.e + rhs.e; self.e = self.e + rhs.e;
} }
} }
@ -103,7 +103,7 @@ impl AddAssign for SpectralSample {
impl Mul for SpectralSample { impl Mul for SpectralSample {
type Output = SpectralSample; type Output = SpectralSample;
fn mul(self, rhs: SpectralSample) -> Self::Output { fn mul(self, rhs: SpectralSample) -> Self::Output {
assert!(self.hero_wavelength == rhs.hero_wavelength); assert_eq!(self.hero_wavelength, rhs.hero_wavelength);
SpectralSample { SpectralSample {
e: self.e * rhs.e, e: self.e * rhs.e,
hero_wavelength: self.hero_wavelength, hero_wavelength: self.hero_wavelength,
@ -113,7 +113,7 @@ impl Mul for SpectralSample {
impl MulAssign for SpectralSample { impl MulAssign for SpectralSample {
fn mul_assign(&mut self, rhs: SpectralSample) { fn mul_assign(&mut self, rhs: SpectralSample) {
assert!(self.hero_wavelength == rhs.hero_wavelength); assert_eq!(self.hero_wavelength, rhs.hero_wavelength);
self.e = self.e * rhs.e; self.e = self.e * rhs.e;
} }
} }

View File

@ -2,26 +2,24 @@ use std;
pub fn hash_u32(n: u32, seed: u32) -> u32 { pub fn hash_u32(n: u32, seed: u32) -> u32 {
let mut hash = n; let mut hash = n;
for _ in 0..3 { for _ in 0..3 {
hash = hash.wrapping_mul(1936502639); hash = hash.wrapping_mul(1936502639);
hash ^= hash.wrapping_shr(16); hash ^= hash.wrapping_shr(16);
hash = hash.wrapping_add(seed); hash = hash.wrapping_add(seed);
} }
return hash; hash
} }
pub fn hash_u64(n: u64, seed: u64) -> u64 { pub fn hash_u64(n: u64, seed: u64) -> u64 {
let mut hash = n; let mut hash = n;
for _ in 0..4 { for _ in 0..4 {
hash = hash.wrapping_mul(32416190071 * 314604959); hash = hash.wrapping_mul(32416190071 * 314604959);
hash ^= hash.wrapping_shr(32); hash ^= hash.wrapping_shr(32);
hash = hash.wrapping_add(seed); hash = hash.wrapping_add(seed);
} }
return hash; hash
} }
/// Returns a random float in [0, 1] based on 'n' and a seed. /// Returns a random float in [0, 1] based on 'n' and a seed.
@ -29,13 +27,12 @@ pub fn hash_u64(n: u64, seed: u64) -> u64 {
/// numbers, and use seed to vary between runs. /// numbers, and use seed to vary between runs.
pub fn hash_u32_to_f32(n: u32, seed: u32) -> f32 { pub fn hash_u32_to_f32(n: u32, seed: u32) -> f32 {
let mut hash = n; let mut hash = n;
for _ in 0..3 { for _ in 0..3 {
hash = hash.wrapping_mul(1936502639); hash = hash.wrapping_mul(1936502639);
hash ^= hash.wrapping_shr(16); hash ^= hash.wrapping_shr(16);
hash = hash.wrapping_add(seed); hash = hash.wrapping_add(seed);
} }
const INV_MAX: f32 = 1.0 / std::u32::MAX as f32; const INV_MAX: f32 = 1.0 / std::u32::MAX as f32;
return hash as f32 * INV_MAX;
hash as f32 * INV_MAX
} }

View File

@ -4,14 +4,13 @@ const N: u32 = 1 << 16;
// Utility function used by the functions below. // Utility function used by the functions below.
fn hil_rot(n: u32, rx: u32, ry: u32, x: &mut u32, y: &mut u32) { fn hil_rot(n: u32, rx: u32, ry: u32, x: &mut u32, y: &mut u32) {
use std::mem;
if ry == 0 { if ry == 0 {
if rx == 1 { if rx == 1 {
*x = (n - 1).wrapping_sub(*x); *x = (n - 1).wrapping_sub(*x);
*y = (n - 1).wrapping_sub(*y); *y = (n - 1).wrapping_sub(*y);
} }
let t = *x; mem::swap(x, y);
*x = *y;
*y = t;
} }
} }

View File

@ -47,7 +47,7 @@ impl Image {
assert!(x < self.res.0); assert!(x < self.res.0);
assert!(y < self.res.1); assert!(y < self.res.1);
let data: &Vec<XYZ> = unsafe { mem::transmute(self.data.get()) }; let data: &Vec<XYZ> = unsafe { &*self.data.get() };
data[self.res.0 * y + x] data[self.res.0 * y + x]
} }
@ -55,7 +55,7 @@ impl Image {
assert!(x < self.res.0); assert!(x < self.res.0);
assert!(y < self.res.1); assert!(y < self.res.1);
let data: &mut Vec<XYZ> = unsafe { mem::transmute(self.data.get()) }; let data: &mut Vec<XYZ> = unsafe { &mut *self.data.get() };
data[self.res.0 * y + x] = value; data[self.res.0 * y + x] = value;
} }
@ -187,11 +187,11 @@ impl Image {
let mut fb = { let mut fb = {
// Create the frame buffer // Create the frame buffer
let mut fb = openexr::FrameBuffer::new(self.res.0, self.res.1); let mut fb = openexr::FrameBuffer::new(self.res.0, self.res.1);
fb.insert_channels(&["R", "G", "B"], &mut image); fb.insert_channels(&["R", "G", "B"], &image);
fb fb
}; };
wr.write_pixels(&mut fb).unwrap(); wr.write_pixels(&fb).unwrap();
} }
} }
@ -208,8 +208,8 @@ impl<'a> Bucket<'a> {
assert!(x >= self.min.0 && x < self.max.0); assert!(x >= self.min.0 && x < self.max.0);
assert!(y >= self.min.1 && y < self.max.1); assert!(y >= self.min.1 && y < self.max.1);
let img: &mut Image = unsafe { mem::transmute(self.img) }; let img: &mut Image = unsafe { &mut *self.img };
let data: &Vec<XYZ> = unsafe { mem::transmute(img.data.get()) }; let data: &Vec<XYZ> = unsafe { &mut *img.data.get() };
data[img.res.0 * y as usize + x as usize] data[img.res.0 * y as usize + x as usize]
} }
@ -218,8 +218,8 @@ impl<'a> Bucket<'a> {
assert!(x >= self.min.0 && x < self.max.0); assert!(x >= self.min.0 && x < self.max.0);
assert!(y >= self.min.1 && y < self.max.1); assert!(y >= self.min.1 && y < self.max.1);
let img: &mut Image = unsafe { mem::transmute(self.img) }; let img: &mut Image = unsafe { &mut *self.img };
let data: &mut Vec<XYZ> = unsafe { mem::transmute(img.data.get()) }; let data: &mut Vec<XYZ> = unsafe { &mut *img.data.get() };
data[img.res.0 * y as usize + x as usize] = value; data[img.res.0 * y as usize + x as usize] = value;
} }
@ -258,7 +258,7 @@ impl<'a> Bucket<'a> {
impl<'a> Drop for Bucket<'a> { impl<'a> Drop for Bucket<'a> {
fn drop(&mut self) { fn drop(&mut self) {
let img: &mut Image = unsafe { mem::transmute(self.img) }; let img: &mut Image = unsafe { &mut *self.img };
let tmp = img.checked_out_blocks.lock().unwrap(); let tmp = img.checked_out_blocks.lock().unwrap();
let mut bucket_list = tmp.borrow_mut(); let mut bucket_list = tmp.borrow_mut();

View File

@ -21,19 +21,19 @@ pub fn lerp<T: Lerp>(a: T, b: T, alpha: f32) -> T {
/// Interpolates a slice of data as if each adjecent pair of elements /// Interpolates a slice of data as if each adjecent pair of elements
/// represent a linear segment. /// represent a linear segment.
pub fn lerp_slice<T: Lerp + Copy>(s: &[T], alpha: f32) -> T { pub fn lerp_slice<T: Lerp + Copy>(s: &[T], alpha: f32) -> T {
debug_assert!(s.len() > 0); debug_assert!(!s.is_empty());
debug_assert!(alpha >= 0.0); debug_assert!(alpha >= 0.0);
debug_assert!(alpha <= 1.0); debug_assert!(alpha <= 1.0);
if s.len() == 1 || alpha == 1.0 { if s.len() == 1 || alpha == 1.0 {
return *s.last().unwrap(); *s.last().unwrap()
} else { } else {
let tmp = alpha * ((s.len() - 1) as f32); let tmp = alpha * ((s.len() - 1) as f32);
let i1 = tmp as usize; let i1 = tmp as usize;
let i2 = i1 + 1; let i2 = i1 + 1;
let alpha2 = tmp - (i1 as f32); let alpha2 = tmp - (i1 as f32);
return lerp(s[i1], s[i2], alpha2); lerp(s[i1], s[i2], alpha2)
} }
} }
@ -42,19 +42,19 @@ where
T: Copy, T: Copy,
F: Fn(T, T, f32) -> T, F: Fn(T, T, f32) -> T,
{ {
debug_assert!(s.len() > 0); debug_assert!(!s.is_empty());
debug_assert!(alpha >= 0.0); debug_assert!(alpha >= 0.0);
debug_assert!(alpha <= 1.0); debug_assert!(alpha <= 1.0);
if s.len() == 1 || alpha == 1.0 { if s.len() == 1 || alpha == 1.0 {
return *s.last().unwrap(); *s.last().unwrap()
} else { } else {
let tmp = alpha * ((s.len() - 1) as f32); let tmp = alpha * ((s.len() - 1) as f32);
let i1 = tmp as usize; let i1 = tmp as usize;
let i2 = i1 + 1; let i2 = i1 + 1;
let alpha2 = tmp - (i1 as f32); let alpha2 = tmp - (i1 as f32);
return f(s[i1], s[i2], alpha2); f(s[i1], s[i2], alpha2)
} }
} }

View File

@ -36,9 +36,9 @@ impl<'a> DistantDiskLight<'a> {
impl<'a> WorldLightSource for DistantDiskLight<'a> { impl<'a> WorldLightSource for DistantDiskLight<'a> {
fn sample(&self, u: f32, v: f32, wavelength: f32, time: f32) -> (SpectralSample, Vector, f32) { fn sample(&self, u: f32, v: f32, wavelength: f32, time: f32) -> (SpectralSample, Vector, f32) {
// Calculate time interpolated values // Calculate time interpolated values
let radius: f64 = lerp_slice(&self.radii, time) as f64; let radius: f64 = lerp_slice(self.radii, time) as f64;
let direction = lerp_slice(&self.directions, time); let direction = lerp_slice(self.directions, time);
let col = lerp_slice(&self.colors, time); let col = lerp_slice(self.colors, time);
let solid_angle_inv = 1.0 / (2.0 * PI_64 * (1.0 - radius.cos())); let solid_angle_inv = 1.0 / (2.0 * PI_64 * (1.0 - radius.cos()));
// Create a coordinate system from the vector pointing at the center of // Create a coordinate system from the vector pointing at the center of
@ -53,25 +53,26 @@ impl<'a> WorldLightSource for DistantDiskLight<'a> {
let spectral_sample = (col * solid_angle_inv as f32).to_spectral_sample(wavelength); let spectral_sample = (col * solid_angle_inv as f32).to_spectral_sample(wavelength);
let shadow_vec = (x * sample.x()) + (y * sample.y()) + (z * sample.z()); let shadow_vec = (x * sample.x()) + (y * sample.y()) + (z * sample.z());
let pdf = uniform_sample_cone_pdf(cos_theta_max); let pdf = uniform_sample_cone_pdf(cos_theta_max);
(spectral_sample, shadow_vec, pdf as f32)
return (spectral_sample, shadow_vec, pdf as f32);
} }
fn sample_pdf(&self, sample_dir: Vector, wavelength: f32, time: f32) -> f32 { fn sample_pdf(&self, sample_dir: Vector, wavelength: f32, time: f32) -> f32 {
// We're not using these, silence warnings // We're not using these, silence warnings
let _ = (sample_dir, wavelength); let _ = (sample_dir, wavelength);
let radius: f64 = lerp_slice(&self.radii, time) as f64; let radius: f64 = lerp_slice(self.radii, time) as f64;
return uniform_sample_cone_pdf(radius.cos()) as f32;
uniform_sample_cone_pdf(radius.cos()) as f32
} }
fn outgoing(&self, dir: Vector, wavelength: f32, time: f32) -> SpectralSample { fn outgoing(&self, dir: Vector, wavelength: f32, time: f32) -> SpectralSample {
// We're not using this, silence warning // We're not using this, silence warning
let _ = dir; let _ = dir;
let radius = lerp_slice(&self.radii, time) as f64; let radius = lerp_slice(self.radii, time) as f64;
let col = lerp_slice(&self.colors, time); let col = lerp_slice(self.colors, time);
let solid_angle = 2.0 * PI_64 * (1.0 - radius.cos()); let solid_angle = 2.0 * PI_64 * (1.0 - radius.cos());
(col / solid_angle as f32).to_spectral_sample(wavelength) (col / solid_angle as f32).to_spectral_sample(wavelength)
} }

View File

@ -51,8 +51,8 @@ impl<'a> LightSource for RectangleLight<'a> {
time: f32, time: f32,
) -> (SpectralSample, Vector, f32) { ) -> (SpectralSample, Vector, f32) {
// Calculate time interpolated values // Calculate time interpolated values
let dim = lerp_slice(&self.dimensions, time); let dim = lerp_slice(self.dimensions, time);
let col = lerp_slice(&self.colors, time); let col = lerp_slice(self.colors, time);
// TODO: Is this right? Do we need to get the surface area post-transform? // TODO: Is this right? Do we need to get the surface area post-transform?
let surface_area_inv: f64 = 1.0 / (dim.0 as f64 * dim.1 as f64); let surface_area_inv: f64 = 1.0 / (dim.0 as f64 * dim.1 as f64);
@ -105,7 +105,7 @@ impl<'a> LightSource for RectangleLight<'a> {
let pdf = 1.0 / (area_1 + area_2); // PDF of the ray direction being sampled let pdf = 1.0 / (area_1 + area_2); // PDF of the ray direction being sampled
let spectral_sample = (col * surface_area_inv as f32 * 0.5).to_spectral_sample(wavelength); let spectral_sample = (col * surface_area_inv as f32 * 0.5).to_spectral_sample(wavelength);
return (spectral_sample, shadow_vec, pdf as f32); (spectral_sample, shadow_vec, pdf as f32)
} }
fn sample_pdf( fn sample_pdf(
@ -121,7 +121,7 @@ impl<'a> LightSource for RectangleLight<'a> {
// We're not using these, silence warnings // We're not using these, silence warnings
let _ = (sample_dir, sample_u, sample_v, wavelength); let _ = (sample_dir, sample_u, sample_v, wavelength);
let dim = lerp_slice(&self.dimensions, time); let dim = lerp_slice(self.dimensions, time);
// Get the four corners of the rectangle, transformed into world space // Get the four corners of the rectangle, transformed into world space
let space_inv = space.inverse(); let space_inv = space.inverse();
@ -156,8 +156,8 @@ impl<'a> LightSource for RectangleLight<'a> {
// We're not using these, silence warnings // We're not using these, silence warnings
let _ = (space, dir, u, v); let _ = (space, dir, u, v);
let dim = lerp_slice(&self.dimensions, time); let dim = lerp_slice(self.dimensions, time);
let col = lerp_slice(&self.colors, time); let col = lerp_slice(self.colors, time);
// TODO: Is this right? Do we need to get the surface area post-transform? // TODO: Is this right? Do we need to get the surface area post-transform?
let surface_area_inv: f64 = 1.0 / (dim.0 as f64 * dim.1 as f64); let surface_area_inv: f64 = 1.0 / (dim.0 as f64 * dim.1 as f64);
@ -179,7 +179,7 @@ impl<'a> LightSource for RectangleLight<'a> {
} }
impl<'a> Boundable for RectangleLight<'a> { impl<'a> Boundable for RectangleLight<'a> {
fn bounds<'b>(&'b self) -> &'b [BBox] { fn bounds(&self) -> &[BBox] {
&self.bounds_ self.bounds_
} }
} }

View File

@ -54,8 +54,8 @@ impl<'a> LightSource for SphereLight<'a> {
let pos = Point::new(0.0, 0.0, 0.0); let pos = Point::new(0.0, 0.0, 0.0);
// Calculate time interpolated values // Calculate time interpolated values
let radius: f64 = lerp_slice(&self.radii, time) as f64; let radius: f64 = lerp_slice(self.radii, time) as f64;
let col = lerp_slice(&self.colors, time); let col = lerp_slice(self.colors, time);
let surface_area_inv: f64 = 1.0 / (4.0 * PI_64 * radius * radius); let surface_area_inv: f64 = 1.0 / (4.0 * PI_64 * radius * radius);
@ -131,7 +131,7 @@ impl<'a> LightSource for SphereLight<'a> {
let arr = arr * *space; let arr = arr * *space;
let pos = Point::new(0.0, 0.0, 0.0); let pos = Point::new(0.0, 0.0, 0.0);
let radius: f64 = lerp_slice(&self.radii, time) as f64; let radius: f64 = lerp_slice(self.radii, time) as f64;
let d2: f64 = (pos - arr).length2() as f64; // Distance from center of sphere squared let d2: f64 = (pos - arr).length2() as f64; // Distance from center of sphere squared
let d: f64 = d2.sqrt(); // Distance from center of sphere let d: f64 = d2.sqrt(); // Distance from center of sphere
@ -142,9 +142,9 @@ impl<'a> LightSource for SphereLight<'a> {
let cos_theta_max2: f64 = 1.0 - sin_theta_max2; let cos_theta_max2: f64 = 1.0 - sin_theta_max2;
let cos_theta_max: f64 = cos_theta_max2.sqrt(); let cos_theta_max: f64 = cos_theta_max2.sqrt();
return uniform_sample_cone_pdf(cos_theta_max) as f32; uniform_sample_cone_pdf(cos_theta_max) as f32
} else { } else {
return (1.0 / (4.0 * PI_64)) as f32; (1.0 / (4.0 * PI_64)) as f32
} }
} }
@ -161,8 +161,8 @@ impl<'a> LightSource for SphereLight<'a> {
let _ = (space, dir, u, v); let _ = (space, dir, u, v);
// TODO: use transform space correctly // TODO: use transform space correctly
let radius = lerp_slice(&self.radii, time) as f64; let radius = lerp_slice(self.radii, time) as f64;
let col = lerp_slice(&self.colors, time); let col = lerp_slice(self.colors, time);
let surface_area = 4.0 * PI_64 * radius * radius; let surface_area = 4.0 * PI_64 * radius * radius;
(col / surface_area as f32).to_spectral_sample(wavelength) (col / surface_area as f32).to_spectral_sample(wavelength)
} }
@ -181,7 +181,7 @@ impl<'a> LightSource for SphereLight<'a> {
} }
impl<'a> Boundable for SphereLight<'a> { impl<'a> Boundable for SphereLight<'a> {
fn bounds<'b>(&'b self) -> &'b [BBox] { fn bounds(&self) -> &[BBox] {
&self.bounds_ self.bounds_
} }
} }

View File

@ -1,3 +1,11 @@
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp))]
#![cfg_attr(feature = "cargo-clippy", allow(inline_always))]
#![cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))]
#![cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))]
#![cfg_attr(feature = "cargo-clippy", allow(needless_return))]
#![cfg_attr(feature = "cargo-clippy", allow(or_fun_call))]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
extern crate bvh_order; extern crate bvh_order;
extern crate color as color_util; extern crate color as color_util;
extern crate float4; extern crate float4;
@ -274,18 +282,18 @@ fn main() {
if !args.is_present("serialized_output") { if !args.is_present("serialized_output") {
println!("\tOverriding scene spp: {}", spp); println!("\tOverriding scene spp: {}", spp);
} }
r.spp = usize::from_str(&spp).unwrap(); r.spp = usize::from_str(spp).unwrap();
} }
let max_samples_per_bucket = let max_samples_per_bucket =
if let Some(max_samples_per_bucket) = args.value_of("max_bucket_samples") { if let Some(max_samples_per_bucket) = args.value_of("max_bucket_samples") {
u32::from_str(&max_samples_per_bucket).unwrap() u32::from_str(max_samples_per_bucket).unwrap()
} else { } else {
4096 4096
}; };
let thread_count = if let Some(threads) = args.value_of("threads") { let thread_count = if let Some(threads) = args.value_of("threads") {
u32::from_str(&threads).unwrap() u32::from_str(threads).unwrap()
} else { } else {
num_cpus::get() as u32 num_cpus::get() as u32
}; };

View File

@ -1,6 +1,10 @@
#![allow(dead_code)] #![allow(dead_code)]
use std::f32;
pub use math3d::{Matrix4x4, Normal, Point, Vector, DotProduct, dot, CrossProduct, cross}; pub use math3d::{Matrix4x4, Normal, Point, Vector, DotProduct, dot, CrossProduct, cross};
/// Clamps a value between a min and max. /// Clamps a value between a min and max.
pub fn clamp<T: PartialOrd>(v: T, lower: T, upper: T) -> T { pub fn clamp<T: PartialOrd>(v: T, lower: T, upper: T) -> T {
if v < lower { if v < lower {
@ -49,7 +53,7 @@ pub fn log2_64(mut value: u64) -> u64 {
(1, (1 << 1) - 1), (1, (1 << 1) - 1),
]; ];
for &(i, j) in POWERS.iter() { for &(i, j) in &POWERS {
let tmp = value >> i; let tmp = value >> i;
if tmp != 0 { if tmp != 0 {
log += i; log += i;
@ -112,7 +116,7 @@ pub fn logit(p: f32, width: f32) -> f32 {
pub fn fast_logit(p: f32, width: f32) -> f32 { pub fn fast_logit(p: f32, width: f32) -> f32 {
let n = 0.001 + (p * 0.998); let n = 0.001 + (p * 0.998);
fast_ln((n / (1.0 - n))) * width * (0.6266 / 4.0) fast_ln(n / (1.0 - n)) * width * (0.6266 / 4.0)
} }
@ -124,7 +128,7 @@ pub fn fast_ln(x: f32) -> f32 {
let mut y = unsafe { transmute_copy::<f32, u32>(&x) as f32 }; let mut y = unsafe { transmute_copy::<f32, u32>(&x) as f32 };
y *= 8.2629582881927490e-8; y *= 8.2629582881927490e-8;
return y - 87.989971088; y - 87.989971088
} }
pub fn fast_pow2(p: f32) -> f32 { pub fn fast_pow2(p: f32) -> f32 {
@ -149,11 +153,11 @@ pub fn fast_log2(x: f32) -> f32 {
let y = xi as f32 * 1.1920928955078125e-7; let y = xi as f32 * 1.1920928955078125e-7;
let mx = unsafe { transmute_copy::<u32, f32>(&((xi & 0x007FFFFF) | 0x3f000000)) }; let mx = unsafe { transmute_copy::<u32, f32>(&((xi & 0x007FFFFF) | 0x3f000000)) };
return y - 124.22551499 - 1.498030302 * mx - 1.72587999 / (0.3520887068 + mx); y - 124.22551499 - 1.498030302 * mx - 1.72587999 / (0.3520887068 + mx)
} }
pub fn fast_exp(p: f32) -> f32 { pub fn fast_exp(p: f32) -> f32 {
fast_pow2(1.442695040 * p) fast_pow2(f32::consts::LOG2_E * p)
} }
pub fn fast_pow(x: f32, p: f32) -> f32 { pub fn fast_pow(x: f32, p: f32) -> f32 {
@ -170,7 +174,7 @@ pub fn faster_pow2(p: f32) -> f32 {
} }
pub fn faster_exp(p: f32) -> f32 { pub fn faster_exp(p: f32) -> f32 {
faster_pow2(1.442695040 * p) faster_pow2(f32::consts::LOG2_E * p)
} }

View File

@ -34,7 +34,7 @@ impl<'a> DataTree<'a> {
remaining_text = skip_ws_and_comments(remaining_text); remaining_text = skip_ws_and_comments(remaining_text);
if remaining_text.1.len() == 0 { if remaining_text.1.is_empty() {
return Ok(DataTree::Internal { return Ok(DataTree::Internal {
type_name: "ROOT", type_name: "ROOT",
ident: None, ident: None,
@ -48,42 +48,42 @@ impl<'a> DataTree<'a> {
} }
pub fn type_name(&'a self) -> &'a str { pub fn type_name(&'a self) -> &'a str {
match self { match *self {
&DataTree::Internal { type_name, .. } => type_name, DataTree::Internal { type_name, .. } |
&DataTree::Leaf { type_name, .. } => type_name, DataTree::Leaf { type_name, .. } => type_name,
} }
} }
pub fn byte_offset(&'a self) -> usize { pub fn byte_offset(&'a self) -> usize {
match self { match *self {
&DataTree::Internal { byte_offset, .. } => byte_offset, DataTree::Internal { byte_offset, .. } |
&DataTree::Leaf { byte_offset, .. } => byte_offset, DataTree::Leaf { byte_offset, .. } => byte_offset,
} }
} }
pub fn is_internal(&self) -> bool { pub fn is_internal(&self) -> bool {
match self { match *self {
&DataTree::Internal { .. } => true, DataTree::Internal { .. } => true,
&DataTree::Leaf { .. } => false, DataTree::Leaf { .. } => false,
} }
} }
pub fn is_leaf(&self) -> bool { pub fn is_leaf(&self) -> bool {
match self { match *self {
&DataTree::Internal { .. } => false, DataTree::Internal { .. } => false,
&DataTree::Leaf { .. } => true, DataTree::Leaf { .. } => true,
} }
} }
pub fn leaf_contents(&'a self) -> Option<&'a str> { pub fn leaf_contents(&'a self) -> Option<&'a str> {
match self { match *self {
&DataTree::Internal { .. } => None, DataTree::Internal { .. } => None,
&DataTree::Leaf { contents, .. } => Some(contents), DataTree::Leaf { contents, .. } => Some(contents),
} }
} }
pub fn iter_children(&'a self) -> slice::Iter<'a, DataTree<'a>> { pub fn iter_children(&'a self) -> slice::Iter<'a, DataTree<'a>> {
if let &DataTree::Internal { ref children, .. } = self { if let DataTree::Internal { ref children, .. } = *self {
children.iter() children.iter()
} else { } else {
[].iter() [].iter()
@ -91,7 +91,7 @@ impl<'a> DataTree<'a> {
} }
pub fn iter_children_with_type(&'a self, type_name: &'static str) -> DataTreeFilterIter<'a> { pub fn iter_children_with_type(&'a self, type_name: &'static str) -> DataTreeFilterIter<'a> {
if let &DataTree::Internal { ref children, .. } = self { if let DataTree::Internal { ref children, .. } = *self {
DataTreeFilterIter { DataTreeFilterIter {
type_name: type_name, type_name: type_name,
iter: children.iter(), iter: children.iter(),
@ -108,7 +108,7 @@ impl<'a> DataTree<'a> {
&'a self, &'a self,
type_name: &'static str, type_name: &'static str,
) -> DataTreeFilterInternalIter<'a> { ) -> DataTreeFilterInternalIter<'a> {
if let &DataTree::Internal { ref children, .. } = self { if let DataTree::Internal { ref children, .. } = *self {
DataTreeFilterInternalIter { DataTreeFilterInternalIter {
type_name: type_name, type_name: type_name,
iter: children.iter(), iter: children.iter(),
@ -125,7 +125,7 @@ impl<'a> DataTree<'a> {
&'a self, &'a self,
type_name: &'static str, type_name: &'static str,
) -> DataTreeFilterLeafIter<'a> { ) -> DataTreeFilterLeafIter<'a> {
if let &DataTree::Internal { ref children, .. } = self { if let DataTree::Internal { ref children, .. } = *self {
DataTreeFilterLeafIter { DataTreeFilterLeafIter {
type_name: type_name, type_name: type_name,
iter: children.iter(), iter: children.iter(),
@ -167,7 +167,7 @@ impl<'a> DataTree<'a> {
} }
/// An iterator over the children of a DataTree node that filters out the /// An iterator over the children of a `DataTree` node that filters out the
/// children not matching a specified type name. /// children not matching a specified type name.
pub struct DataTreeFilterIter<'a> { pub struct DataTreeFilterIter<'a> {
type_name: &'a str, type_name: &'a str,
@ -193,7 +193,7 @@ impl<'a> Iterator for DataTreeFilterIter<'a> {
} }
/// An iterator over the children of a DataTree node that filters out the /// 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 /// children that aren't internal nodes and that don't match a specified
/// type name. /// type name.
pub struct DataTreeFilterInternalIter<'a> { pub struct DataTreeFilterInternalIter<'a> {
@ -233,7 +233,7 @@ impl<'a> Iterator for DataTreeFilterInternalIter<'a> {
} }
/// An iterator over the children of a DataTree node that filters out the /// 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 /// children that aren't internal nodes and that don't match a specified
/// type name. /// type name.
pub struct DataTreeFilterLeafIter<'a> { pub struct DataTreeFilterLeafIter<'a> {
@ -387,7 +387,7 @@ fn parse_node<'a>(source_text: (usize, &'a str)) -> ParseResult<'a> {
} }
fn parse_leaf_content<'a>(source_text: (usize, &'a str)) -> (&'a str, (usize, &'a str)) { fn parse_leaf_content(source_text: (usize, &str)) -> (&str, (usize, &str)) {
let mut si = 1; let mut si = 1;
let mut escaped = false; let mut escaped = false;
let mut reached_end = true; let mut reached_end = true;
@ -521,7 +521,7 @@ fn is_ident_char(c: char) -> bool {
!is_ws(c) && !is_reserved_char(c) !is_ws(c) && !is_reserved_char(c)
} }
fn skip_ws<'a>(text: &'a str) -> &'a str { fn skip_ws(text: &str) -> &str {
let mut si = 0; let mut si = 0;
let mut reached_end = true; let mut reached_end = true;
for (i, c) in text.char_indices() { for (i, c) in text.char_indices() {
@ -539,7 +539,7 @@ fn skip_ws<'a>(text: &'a str) -> &'a str {
return &text[si..]; return &text[si..];
} }
fn skip_comment<'a>(text: &'a str) -> &'a str { fn skip_comment(text: &str) -> &str {
let mut si = 0; let mut si = 0;
if Some('#') == text.chars().nth(0) { if Some('#') == text.chars().nth(0) {
let mut reached_end = true; let mut reached_end = true;
@ -559,7 +559,7 @@ fn skip_comment<'a>(text: &'a str) -> &'a str {
return &text[si..]; return &text[si..];
} }
fn skip_ws_and_comments<'a>(text: (usize, &'a str)) -> (usize, &'a str) { fn skip_ws_and_comments(text: (usize, &str)) -> (usize, &str) {
let mut remaining_text = text.1; let mut remaining_text = text.1;
loop { loop {

View File

@ -1,6 +1,7 @@
#![allow(dead_code)] #![allow(dead_code)]
use std::result::Result; use std::result::Result;
use std::f32;
use nom; use nom;
use nom::IResult; use nom::IResult;
@ -37,8 +38,8 @@ pub enum PsyParseError {
impl PsyParseError { impl PsyParseError {
pub fn print(&self, psy_content: &str) { pub fn print(&self, psy_content: &str) {
match self { match *self {
&PsyParseError::UnknownError(offset) => { PsyParseError::UnknownError(offset) => {
let line = line_count_to_byte_offset(psy_content, offset); let line = line_count_to_byte_offset(psy_content, offset);
println!( println!(
"Line {}: Unknown parse error. If you get this message, please report \ "Line {}: Unknown parse error. If you get this message, please report \
@ -47,37 +48,37 @@ impl PsyParseError {
); );
} }
&PsyParseError::UnknownVariant(offset, error) => { PsyParseError::UnknownVariant(offset, error) => {
let line = line_count_to_byte_offset(psy_content, offset); let line = line_count_to_byte_offset(psy_content, offset);
println!("Line {}: {}", line, error); println!("Line {}: {}", line, error);
} }
&PsyParseError::ExpectedInternalNode(offset, error) => { PsyParseError::ExpectedInternalNode(offset, error) => {
let line = line_count_to_byte_offset(psy_content, offset); let line = line_count_to_byte_offset(psy_content, offset);
println!("Line {}: {}", line, error); println!("Line {}: {}", line, error);
} }
&PsyParseError::ExpectedLeafNode(offset, error) => { PsyParseError::ExpectedLeafNode(offset, error) => {
let line = line_count_to_byte_offset(psy_content, offset); let line = line_count_to_byte_offset(psy_content, offset);
println!("Line {}: {}", line, error); println!("Line {}: {}", line, error);
} }
&PsyParseError::MissingNode(offset, error) => { PsyParseError::MissingNode(offset, error) => {
let line = line_count_to_byte_offset(psy_content, offset); let line = line_count_to_byte_offset(psy_content, offset);
println!("Line {}: {}", line, error); println!("Line {}: {}", line, error);
} }
&PsyParseError::IncorrectLeafData(offset, error) => { PsyParseError::IncorrectLeafData(offset, error) => {
let line = line_count_to_byte_offset(psy_content, offset); let line = line_count_to_byte_offset(psy_content, offset);
println!("Line {}: {}", line, error); println!("Line {}: {}", line, error);
} }
&PsyParseError::WrongNodeCount(offset, error, count) => { PsyParseError::WrongNodeCount(offset, error, count) => {
let line = line_count_to_byte_offset(psy_content, offset); let line = line_count_to_byte_offset(psy_content, offset);
println!("Line {}: {} Found: {}", line, error, count); println!("Line {}: {} Found: {}", line, error, count);
} }
&PsyParseError::InstancedMissingData(offset, error, ref data_name) => { PsyParseError::InstancedMissingData(offset, error, ref data_name) => {
let line = line_count_to_byte_offset(psy_content, offset); let line = line_count_to_byte_offset(psy_content, offset);
println!("Line {}: {} Data name: '{}'", line, error, data_name); println!("Line {}: {} Data name: '{}'", line, error, data_name);
} }
@ -86,11 +87,11 @@ impl PsyParseError {
} }
fn line_count_to_byte_offset(text: &str, offset: usize) -> usize { fn line_count_to_byte_offset(text: &str, offset: usize) -> usize {
text[..offset].matches("\n").count() + 1 text[..offset].matches('\n').count() + 1
} }
/// Takes in a DataTree representing a Scene node and returns /// Takes in a `DataTree` representing a Scene node and returns
pub fn parse_scene<'a>( pub fn parse_scene<'a>(
arena: &'a MemArena, arena: &'a MemArena,
tree: &'a DataTree, tree: &'a DataTree,
@ -167,7 +168,7 @@ pub fn parse_scene<'a>(
)?; )?;
// Put scene together // Put scene together
let scene_name = if let &DataTree::Internal { ident, .. } = tree { let scene_name = if let DataTree::Internal { ident, .. } = *tree {
if let Some(name) = ident { if let Some(name) = ident {
Some(name.to_string()) Some(name.to_string())
} else { } else {
@ -202,13 +203,13 @@ pub fn parse_scene<'a>(
fn parse_output_info(tree: &DataTree) -> Result<String, PsyParseError> { fn parse_output_info(tree: &DataTree) -> Result<String, PsyParseError> {
if let &DataTree::Internal { ref children, .. } = tree { if let DataTree::Internal { ref children, .. } = *tree {
let mut found_path = false; let mut found_path = false;
let mut path = String::new(); let mut path = String::new();
for child in children { for child in children {
match child { match *child {
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,
@ -243,7 +244,7 @@ fn parse_output_info(tree: &DataTree) -> Result<String, PsyParseError> {
} }
if found_path { if found_path {
return Ok((path)); return Ok(path);
} else { } else {
return Err(PsyParseError::MissingNode( return Err(PsyParseError::MissingNode(
tree.byte_offset(), tree.byte_offset(),
@ -263,7 +264,7 @@ fn parse_output_info(tree: &DataTree) -> Result<String, PsyParseError> {
fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyParseError> { fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyParseError> {
if let &DataTree::Internal { ref children, .. } = tree { if let DataTree::Internal { ref children, .. } = *tree {
let mut found_res = false; let mut found_res = false;
let mut found_spp = false; let mut found_spp = false;
let mut res = (0, 0); let mut res = (0, 0);
@ -271,9 +272,9 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyP
let mut seed = 0; let mut seed = 0;
for child in children { for child in children {
match child { match *child {
// Resolution // Resolution
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,
@ -294,7 +295,7 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyP
} }
// SamplesPerPixel // SamplesPerPixel
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,
@ -314,7 +315,7 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyP
} }
// Seed // Seed
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,
@ -359,7 +360,7 @@ fn parse_render_settings(tree: &DataTree) -> Result<((u32, u32), u32, u32), PsyP
fn parse_camera<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result<Camera<'a>, PsyParseError> { fn parse_camera<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result<Camera<'a>, PsyParseError> {
if let &DataTree::Internal { ref children, .. } = tree { if let DataTree::Internal { ref children, .. } = *tree {
let mut mats = Vec::new(); let mut mats = Vec::new();
let mut fovs = Vec::new(); let mut fovs = Vec::new();
let mut focus_distances = Vec::new(); let mut focus_distances = Vec::new();
@ -367,15 +368,15 @@ fn parse_camera<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result<Camera<'a
// Parse // Parse
for child in children.iter() { for child in children.iter() {
match child { match *child {
// Fov // Fov
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,
} if type_name == "Fov" => { } if type_name == "Fov" => {
if let IResult::Done(_, fov) = ws_f32(contents.as_bytes()) { if let IResult::Done(_, fov) = ws_f32(contents.as_bytes()) {
fovs.push(fov * (3.1415926536 / 180.0)); fovs.push(fov * (f32::consts::PI / 180.0));
} else { } else {
// Found Fov, but its contents is not in the right format // Found Fov, but its contents is not in the right format
return Err(PsyParseError::IncorrectLeafData( return Err(PsyParseError::IncorrectLeafData(
@ -388,7 +389,7 @@ fn parse_camera<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result<Camera<'a
} }
// FocalDistance // FocalDistance
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,
@ -407,7 +408,7 @@ fn parse_camera<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result<Camera<'a
} }
// ApertureRadius // ApertureRadius
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,
@ -426,7 +427,7 @@ fn parse_camera<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result<Camera<'a
} }
// Transform // Transform
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,
@ -490,8 +491,8 @@ fn parse_world<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result<World<'a>,
bgs.iter_children_with_type("Type").count(), bgs.iter_children_with_type("Type").count(),
)); ));
} }
if let &DataTree::Leaf { contents, .. } = if let DataTree::Leaf { contents, .. } =
bgs.iter_children_with_type("Type").nth(0).unwrap() *bgs.iter_children_with_type("Type").nth(0).unwrap()
{ {
contents.trim() contents.trim()
} else { } else {
@ -544,9 +545,9 @@ fn parse_world<'a>(arena: &'a MemArena, tree: &'a DataTree) -> Result<World<'a>,
// Parse light sources // Parse light sources
for child in tree.iter_children() { for child in tree.iter_children() {
match child { match *child {
&DataTree::Internal { type_name, .. } if type_name == "DistantDiskLight" => { DataTree::Internal { type_name, .. } if type_name == "DistantDiskLight" => {
lights.push(arena.alloc(parse_distant_disk_light(arena, &child)?)); lights.push(arena.alloc(parse_distant_disk_light(arena, child)?));
} }
_ => {} _ => {}
@ -619,9 +620,9 @@ pub fn parse_matrix(contents: &str) -> Result<Matrix4x4, PsyParseError> {
} }
pub fn make_transform_format_error(byte_offset: usize) -> PsyParseError { pub fn make_transform_format_error(byte_offset: usize) -> PsyParseError {
return PsyParseError::IncorrectLeafData( PsyParseError::IncorrectLeafData(
byte_offset, byte_offset,
"Transform should be sixteen integers specified in \ "Transform should be sixteen integers specified in \
the form '[# # # # # # # # # # # # # # # #]'.", the form '[# # # # # # # # # # # # # # # #]'.",
); )
} }

View File

@ -23,8 +23,8 @@ pub fn parse_assembly<'a>(
match child.type_name() { match child.type_name() {
// Sub-Assembly // Sub-Assembly
"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)?); builder.add_assembly(ident, parse_assembly(arena, child)?);
} else { } else {
return Err(PsyParseError::UnknownError(child.byte_offset())); return Err(PsyParseError::UnknownError(child.byte_offset()));
} }
@ -68,10 +68,10 @@ pub fn parse_assembly<'a>(
// MeshSurface // MeshSurface
"MeshSurface" => { "MeshSurface" => {
if let &DataTree::Internal { ident: Some(ident), .. } = child { if let DataTree::Internal { ident: Some(ident), .. } = *child {
builder.add_object( builder.add_object(
ident, ident,
Object::Surface(arena.alloc(parse_mesh_surface(arena, &child)?)), Object::Surface(arena.alloc(parse_mesh_surface(arena, child)?)),
); );
} else { } else {
// TODO: error condition of some kind, because no ident // TODO: error condition of some kind, because no ident
@ -85,10 +85,10 @@ pub fn parse_assembly<'a>(
// Sphere Light // Sphere Light
"SphereLight" => { "SphereLight" => {
if let &DataTree::Internal { ident: Some(ident), .. } = child { if let DataTree::Internal { ident: Some(ident), .. } = *child {
builder.add_object( builder.add_object(
ident, ident,
Object::Light(arena.alloc(parse_sphere_light(arena, &child)?)), Object::Light(arena.alloc(parse_sphere_light(arena, child)?)),
); );
} else { } else {
// No ident // No ident
@ -98,10 +98,10 @@ pub fn parse_assembly<'a>(
// Rectangle Light // Rectangle Light
"RectangleLight" => { "RectangleLight" => {
if let &DataTree::Internal { ident: Some(ident), .. } = child { if let DataTree::Internal { ident: Some(ident), .. } = *child {
builder.add_object( builder.add_object(
ident, ident,
Object::Light(arena.alloc(parse_rectangle_light(arena, &child)?)), Object::Light(arena.alloc(parse_rectangle_light(arena, child)?)),
); );
} else { } else {
// No ident // No ident
@ -111,7 +111,7 @@ pub fn parse_assembly<'a>(
// Surface shader // Surface shader
"SurfaceShader" => { "SurfaceShader" => {
if let &DataTree::Internal { ident: Some(_), .. } = child { if let DataTree::Internal { ident: Some(_), .. } = *child {
// TODO // TODO
//unimplemented!() //unimplemented!()
} else { } else {

View File

@ -19,16 +19,16 @@ pub fn parse_distant_disk_light<'a>(
arena: &'a MemArena, arena: &'a MemArena,
tree: &'a DataTree, tree: &'a DataTree,
) -> Result<DistantDiskLight<'a>, PsyParseError> { ) -> Result<DistantDiskLight<'a>, PsyParseError> {
if let &DataTree::Internal { ref children, .. } = tree { if let DataTree::Internal { ref children, .. } = *tree {
let mut radii = Vec::new(); let mut radii = Vec::new();
let mut directions = Vec::new(); let mut directions = Vec::new();
let mut colors = Vec::new(); let mut colors = Vec::new();
// Parse // Parse
for child in children.iter() { for child in children.iter() {
match child { match *child {
// Radius // Radius
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,
@ -42,7 +42,7 @@ pub fn parse_distant_disk_light<'a>(
} }
// Direction // Direction
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,
@ -58,7 +58,7 @@ pub fn parse_distant_disk_light<'a>(
} }
// Color // Color
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,
@ -91,15 +91,15 @@ pub fn parse_sphere_light<'a>(
arena: &'a MemArena, arena: &'a MemArena,
tree: &'a DataTree, tree: &'a DataTree,
) -> Result<SphereLight<'a>, PsyParseError> { ) -> Result<SphereLight<'a>, PsyParseError> {
if let &DataTree::Internal { ref children, .. } = tree { if let DataTree::Internal { ref children, .. } = *tree {
let mut radii = Vec::new(); let mut radii = Vec::new();
let mut colors = Vec::new(); let mut colors = Vec::new();
// Parse // Parse
for child in children.iter() { for child in children.iter() {
match child { match *child {
// Radius // Radius
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,
@ -113,7 +113,7 @@ pub fn parse_sphere_light<'a>(
} }
// Color // Color
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,
@ -145,15 +145,15 @@ pub fn parse_rectangle_light<'a>(
arena: &'a MemArena, arena: &'a MemArena,
tree: &'a DataTree, tree: &'a DataTree,
) -> Result<RectangleLight<'a>, PsyParseError> { ) -> Result<RectangleLight<'a>, PsyParseError> {
if let &DataTree::Internal { ref children, .. } = tree { if let DataTree::Internal { ref children, .. } = *tree {
let mut dimensions = Vec::new(); let mut dimensions = Vec::new();
let mut colors = Vec::new(); let mut colors = Vec::new();
// Parse // Parse
for child in children.iter() { for child in children.iter() {
match child { match *child {
// Dimensions // Dimensions
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,
@ -169,7 +169,7 @@ pub fn parse_rectangle_light<'a>(
} }
// Color // Color
&DataTree::Leaf { DataTree::Leaf {
type_name, type_name,
contents, contents,
byte_offset, byte_offset,

View File

@ -51,7 +51,7 @@ pub fn parse_mesh_surface<'a>(
// Make sure all time samples have same vert count // Make sure all time samples have same vert count
if let Some(fvc) = first_vert_count { if let Some(fvc) = first_vert_count {
assert!(vert_count == fvc); assert_eq!(vert_count, fvc);
} else { } else {
first_vert_count = Some(vert_count); first_vert_count = Some(vert_count);
} }
@ -85,7 +85,7 @@ pub fn parse_mesh_surface<'a>(
let mut triangles = Vec::new(); let mut triangles = Vec::new();
let vert_count = first_vert_count.unwrap(); let vert_count = first_vert_count.unwrap();
let mut ii = 0; let mut ii = 0;
for fvc in face_vert_counts.iter() { for fvc in &face_vert_counts {
if *fvc >= 3 { if *fvc >= 3 {
// Store the polygon, split up into triangles if >3 verts // Store the polygon, split up into triangles if >3 verts
let v1 = ii; let v1 = ii;

View File

@ -232,10 +232,8 @@ impl<'a> Renderer<'a> {
if let Some(b) = job_queue.try_pop() { if let Some(b) = job_queue.try_pop() {
bucket = b; bucket = b;
break; break;
} else { } else if *all_jobs_queued.read().unwrap() {
if *all_jobs_queued.read().unwrap() == true { break 'render_loop;
break 'render_loop;
}
} }
} }
@ -293,7 +291,7 @@ impl<'a> Renderer<'a> {
let min = (bucket.x, bucket.y); let min = (bucket.x, bucket.y);
let max = (bucket.x + bucket.w, bucket.y + bucket.h); let max = (bucket.x + bucket.w, bucket.y + bucket.h);
let mut img_bucket = image.get_bucket(min, max); let mut img_bucket = image.get_bucket(min, max);
for path in paths.iter() { for path in &paths {
let path_col = SpectralSample::from_parts(path.color, path.wavelength); let path_col = SpectralSample::from_parts(path.color, path.wavelength);
let mut col = img_bucket.get(path.pixel_co.0, path.pixel_co.1); let mut col = img_bucket.get(path.pixel_co.0, path.pixel_co.1);
col += XYZ::from_spectral_sample(&path_col) / self.spp as f32; col += XYZ::from_spectral_sample(&path_col) / self.spp as f32;
@ -438,10 +436,10 @@ impl LightPath {
// Result of Camera or bounce ray, prepare next bounce and light rays // Result of Camera or bounce ray, prepare next bounce and light rays
LightPathEvent::CameraRay | LightPathEvent::CameraRay |
LightPathEvent::BounceRay => { LightPathEvent::BounceRay => {
if let &surface::SurfaceIntersection::Hit { if let surface::SurfaceIntersection::Hit {
intersection_data: ref idata, intersection_data: ref idata,
ref closure, ref closure,
} = isect } = *isect
{ {
// Hit something! Do the stuff // Hit something! Do the stuff
@ -544,10 +542,7 @@ impl LightPath {
}; };
// Book keeping for next event // Book keeping for next event
if found_light && do_bounce { if found_light {
self.event = LightPathEvent::ShadowRay;
return true;
} else if found_light {
self.event = LightPathEvent::ShadowRay; self.event = LightPathEvent::ShadowRay;
return true; return true;
} else if do_bounce { } else if do_bounce {
@ -574,7 +569,7 @@ impl LightPath {
LightPathEvent::ShadowRay => { LightPathEvent::ShadowRay => {
// If the light was not in shadow, add it's light to the film // If the light was not in shadow, add it's light to the film
// plane. // plane.
if let &surface::SurfaceIntersection::Miss = isect { if let surface::SurfaceIntersection::Miss = *isect {
self.color += self.pending_color_addition; self.color += self.pending_color_addition;
} }

View File

@ -37,7 +37,7 @@ pub fn square_to_circle(x: f32, y: f32) -> (f32, f32) {
pub fn cosine_sample_hemisphere(u: f32, v: f32) -> Vector { pub fn cosine_sample_hemisphere(u: f32, v: f32) -> Vector {
let (u, v) = square_to_circle((u * 2.0) - 1.0, (v * 2.0) - 1.0); let (u, v) = square_to_circle((u * 2.0) - 1.0, (v * 2.0) - 1.0);
let z = (1.0 - ((u * u) + (v * v))).max(0.0).sqrt(); let z = (1.0 - ((u * u) + (v * v))).max(0.0).sqrt();
return Vector::new(u, v, z); Vector::new(u, v, z)
} }
pub fn uniform_sample_hemisphere(u: f32, v: f32) -> Vector { pub fn uniform_sample_hemisphere(u: f32, v: f32) -> Vector {
@ -61,9 +61,9 @@ pub fn uniform_sample_sphere(u: f32, v: f32) -> Vector {
/// Samples a solid angle defined by a cone originating from (0,0,0) /// Samples a solid angle defined by a cone originating from (0,0,0)
/// and pointing down the positive z-axis. /// and pointing down the positive z-axis.
/// ///
/// u, v: sampling variables, should each be in the interval [0,1] /// `u`, `v`: sampling variables, should each be in the interval [0,1]
/// cos_theta_max: cosine of the max angle from the z-axis, defining /// `cos_theta_max`: cosine of the max angle from the z-axis, defining
/// the outer extent of the cone. /// the outer extent of the cone.
pub fn uniform_sample_cone(u: f32, v: f32, cos_theta_max: f64) -> Vector { pub fn uniform_sample_cone(u: f32, v: f32, cos_theta_max: f64) -> Vector {
let cos_theta = (1.0 - u as f64) + (u as f64 * cos_theta_max); let cos_theta = (1.0 - u as f64) + (u as f64 * cos_theta_max);
let sin_theta = (1.0 - (cos_theta * cos_theta)).sqrt(); let sin_theta = (1.0 - (cos_theta * cos_theta)).sqrt();

View File

@ -45,12 +45,12 @@ impl<'a> Assembly<'a> {
time: f32, time: f32,
intr: &SurfaceIntersection, intr: &SurfaceIntersection,
) -> Option<(SpectralSample, Vector, f32, f32)> { ) -> Option<(SpectralSample, Vector, f32, f32)> {
if let &SurfaceIntersection::Hit { if let SurfaceIntersection::Hit {
intersection_data: idata, intersection_data: idata,
closure, closure,
} = intr } = *intr
{ {
let sel_xform = if xform_stack.top().len() > 0 { let sel_xform = if !xform_stack.top().is_empty() {
lerp_slice(xform_stack.top(), time) lerp_slice(xform_stack.top(), time)
} else { } else {
Matrix4x4::new() Matrix4x4::new()
@ -69,20 +69,20 @@ impl<'a> Assembly<'a> {
match inst.instance_type { match inst.instance_type {
InstanceType::Object => { InstanceType::Object => {
match &self.objects[inst.data_index] { match self.objects[inst.data_index] {
&Object::Light(ref light) => { Object::Light(light) => {
// Get the world-to-object space transform of the light // Get the world-to-object space transform of the light
let xform = if let Some((a, b)) = inst.transform_indices { let xform = if let Some((a, b)) = inst.transform_indices {
let pxforms = xform_stack.top(); let pxforms = xform_stack.top();
let xform = lerp_slice(&self.xforms[a..b], time); let xform = lerp_slice(&self.xforms[a..b], time);
if pxforms.len() > 0 { if !pxforms.is_empty() {
lerp_slice(pxforms, time) * xform lerp_slice(pxforms, time) * xform
} else { } else {
xform xform
} }
} else { } else {
let pxforms = xform_stack.top(); let pxforms = xform_stack.top();
if pxforms.len() > 0 { if !pxforms.is_empty() {
lerp_slice(pxforms, time) lerp_slice(pxforms, time)
} else { } else {
Matrix4x4::new() Matrix4x4::new()
@ -117,7 +117,7 @@ impl<'a> Assembly<'a> {
); );
// Pop the assembly's transforms off the transform stack. // Pop the assembly's transforms off the transform stack.
if let Some(_) = inst.transform_indices { if inst.transform_indices.is_some() {
xform_stack.pop(); xform_stack.pop();
} }
@ -135,7 +135,7 @@ impl<'a> Assembly<'a> {
} }
impl<'a> Boundable for Assembly<'a> { impl<'a> Boundable for Assembly<'a> {
fn bounds<'b>(&'b self) -> &'b [BBox] { fn bounds(&self) -> &[BBox] {
self.object_accel.bounds() self.object_accel.bounds()
} }
} }
@ -208,7 +208,7 @@ impl<'a> AssemblyBuilder<'a> {
// Map zero-length transforms to None // Map zero-length transforms to None
let xforms = if let Some(xf) = xforms { let xforms = if let Some(xf) = xforms {
if xf.len() > 0 { Some(xf) } else { None } if !xf.is_empty() { Some(xf) } else { None }
} else { } else {
None None
}; };
@ -274,7 +274,7 @@ impl<'a> AssemblyBuilder<'a> {
.approximate_energy() > 0.0 .approximate_energy() > 0.0
} }
}) })
.map(|&a| a) .cloned()
.collect(); .collect();
// Build light accel // Build light accel
@ -282,7 +282,7 @@ impl<'a> AssemblyBuilder<'a> {
let bounds = &bbs[bis[inst.id]..bis[inst.id + 1]]; let bounds = &bbs[bis[inst.id]..bis[inst.id + 1]];
let energy = match inst.instance_type { let energy = match inst.instance_type {
InstanceType::Object => { InstanceType::Object => {
if let Object::Light(ref light) = self.objects[inst.data_index] { if let Object::Light(light) = self.objects[inst.data_index] {
light.approximate_energy() light.approximate_energy()
} else { } else {
0.0 0.0
@ -316,7 +316,7 @@ impl<'a> AssemblyBuilder<'a> {
let mut indices = vec![0]; let mut indices = vec![0];
let mut bounds = Vec::new(); let mut bounds = Vec::new();
for inst in self.instances.iter() { for inst in &self.instances {
let mut bbs = Vec::new(); let mut bbs = Vec::new();
let mut bbs2 = Vec::new(); let mut bbs2 = Vec::new();
@ -325,9 +325,9 @@ impl<'a> AssemblyBuilder<'a> {
InstanceType::Object => { InstanceType::Object => {
// Push bounds onto bbs // Push bounds onto bbs
let obj = &self.objects[inst.data_index]; let obj = &self.objects[inst.data_index];
match obj { match *obj {
&Object::Surface(ref s) => bbs.extend(s.bounds()), Object::Surface(s) => bbs.extend(s.bounds()),
&Object::Light(ref l) => bbs.extend(l.bounds()), Object::Light(l) => bbs.extend(l.bounds()),
} }
} }
@ -341,7 +341,7 @@ impl<'a> AssemblyBuilder<'a> {
// Transform the bounding boxes, if necessary // Transform the bounding boxes, if necessary
if let Some((xstart, xend)) = inst.transform_indices { if let Some((xstart, xend)) = inst.transform_indices {
let xf = &self.xforms[xstart..xend]; let xf = &self.xforms[xstart..xend];
transform_bbox_slice_from(&bbs, &xf, &mut bbs2); transform_bbox_slice_from(&bbs, xf, &mut bbs2);
} else { } else {
bbs2.clear(); bbs2.clear();
bbs2.extend(bbs); bbs2.extend(bbs);
@ -352,7 +352,7 @@ impl<'a> AssemblyBuilder<'a> {
indices.push(bounds.len()); indices.push(bounds.len());
} }
return (indices, bounds); (indices, bounds)
} }
} }

View File

@ -59,7 +59,7 @@ impl<'a> Scene<'a> {
if n < wl_prob { if n < wl_prob {
// World lights // World lights
let n = n / wl_prob; let n = n / wl_prob;
let (i, p) = weighted_choice(&self.world.lights, n, |l| l.approximate_energy()); let (i, p) = weighted_choice(self.world.lights, n, |l| l.approximate_energy());
let (ss, sv, pdf) = self.world.lights[i].sample(uvw.0, uvw.1, wavelength, time); let (ss, sv, pdf) = self.world.lights[i].sample(uvw.0, uvw.1, wavelength, time);
return Some((ss, sv, pdf, p * wl_prob, true)); return Some((ss, sv, pdf, p * wl_prob, true));
} else { } else {

View File

@ -20,10 +20,10 @@ pub enum SurfaceClosureUnion {
impl SurfaceClosureUnion { impl SurfaceClosureUnion {
pub fn as_surface_closure(&self) -> &SurfaceClosure { pub fn as_surface_closure(&self) -> &SurfaceClosure {
match self { match *self {
&SurfaceClosureUnion::EmitClosure(ref closure) => closure as &SurfaceClosure, SurfaceClosureUnion::EmitClosure(ref closure) => closure as &SurfaceClosure,
&SurfaceClosureUnion::LambertClosure(ref closure) => closure as &SurfaceClosure, SurfaceClosureUnion::LambertClosure(ref closure) => closure as &SurfaceClosure,
&SurfaceClosureUnion::GTRClosure(ref closure) => closure as &SurfaceClosure, SurfaceClosureUnion::GTRClosure(ref closure) => closure as &SurfaceClosure,
} }
} }
} }
@ -86,11 +86,11 @@ pub trait SurfaceClosure {
/// Utility function that calculates the fresnel reflection factor of a given /// Utility function that calculates the fresnel reflection factor of a given
/// incoming ray against a surface with the given ior outside/inside ratio. /// incoming ray against a surface with the given ior outside/inside ratio.
/// ///
/// ior_ratio: The ratio of the outside material ior (probably 1.0 for air) /// `ior_ratio`: The ratio of the outside material ior (probably 1.0 for air)
/// over the inside ior. /// over the inside ior.
/// c: The cosine of the angle between the incoming light and the /// `c`: The cosine of the angle between the incoming light and the
/// surface's normal. Probably calculated e.g. with a normalized /// surface's normal. Probably calculated e.g. with a normalized
/// dot product. /// dot product.
#[allow(dead_code)] #[allow(dead_code)]
fn dielectric_fresnel(ior_ratio: f32, c: f32) -> f32 { fn dielectric_fresnel(ior_ratio: f32, c: f32) -> f32 {
let g = (ior_ratio - 1.0 + (c * c)).sqrt(); let g = (ior_ratio - 1.0 + (c * c)).sqrt();
@ -103,31 +103,32 @@ fn dielectric_fresnel(ior_ratio: f32, c: f32) -> f32 {
let f5 = (c * f1) + 1.0; let f5 = (c * f1) + 1.0;
let f6 = 1.0 + ((f4 * f4) / (f5 * f5)); let f6 = 1.0 + ((f4 * f4) / (f5 * f5));
return 0.5 * f3 * f6; 0.5 * f3 * f6
} }
/// Schlick's approximation of the fresnel reflection factor. /// Schlick's approximation of the fresnel reflection factor.
/// ///
/// Same interface as dielectric_fresnel(), above. /// Same interface as `dielectric_fresnel()`, above.
#[allow(dead_code)] #[allow(dead_code)]
fn schlick_fresnel(ior_ratio: f32, c: f32) -> f32 { fn schlick_fresnel(ior_ratio: f32, c: f32) -> f32 {
let f1 = (1.0 - ior_ratio) / (1.0 + ior_ratio); let f1 = (1.0 - ior_ratio) / (1.0 + ior_ratio);
let f2 = f1 * f1; let f2 = f1 * f1;
let c1 = 1.0 - c; let c1 = 1.0 - c;
let c2 = c1 * c1; let c2 = c1 * c1;
return f2 + ((1.0 - f2) * c1 * c2 * c2);
f2 + ((1.0 - f2) * c1 * c2 * c2)
} }
/// Utility function that calculates the fresnel reflection factor of a given /// Utility function that calculates the fresnel reflection factor of a given
/// incoming ray against a surface with the given normal-reflectance factor. /// incoming ray against a surface with the given normal-reflectance factor.
/// ///
/// frensel_fac: The ratio of light reflected back if the ray were to /// `frensel_fac`: The ratio of light reflected back if the ray were to
/// hit the surface head-on (perpendicular to the surface). /// hit the surface head-on (perpendicular to the surface).
/// c The cosine of the angle between the incoming light and the /// `c`: The cosine of the angle between the incoming light and the
/// surface's normal. Probably calculated e.g. with a normalized /// surface's normal. Probably calculated e.g. with a normalized
/// dot product. /// dot product.
#[allow(dead_code)] #[allow(dead_code)]
fn dielectric_fresnel_from_fac(fresnel_fac: f32, c: f32) -> f32 { fn dielectric_fresnel_from_fac(fresnel_fac: f32, c: f32) -> f32 {
let tmp1 = fresnel_fac.sqrt() - 1.0; let tmp1 = fresnel_fac.sqrt() - 1.0;
@ -142,16 +143,16 @@ fn dielectric_fresnel_from_fac(fresnel_fac: f32, c: f32) -> f32 {
let ior_ratio = tmp2 * tmp2; let ior_ratio = tmp2 * tmp2;
// Calculate fresnel factor // Calculate fresnel factor
return dielectric_fresnel(ior_ratio, c); dielectric_fresnel(ior_ratio, c)
} }
/// Schlick's approximation version of dielectric_fresnel_from_fac() above. /// Schlick's approximation version of `dielectric_fresnel_from_fac()` above.
#[allow(dead_code)] #[allow(dead_code)]
fn schlick_fresnel_from_fac(frensel_fac: f32, c: f32) -> f32 { fn schlick_fresnel_from_fac(frensel_fac: f32, c: f32) -> f32 {
let c1 = 1.0 - c; let c1 = 1.0 - c;
let c2 = c1 * c1; let c2 = c1 * c1;
return frensel_fac + ((1.0 - frensel_fac) * c1 * c2 * c2); frensel_fac + ((1.0 - frensel_fac) * c1 * c2 * c2)
} }
@ -429,14 +430,12 @@ impl GTRClosure {
let roughness2 = rough * rough; let roughness2 = rough * rough;
// Calculate D - Distribution // Calculate D - Distribution
let dist = if nh <= 0.0 { if nh <= 0.0 {
0.0 0.0
} else { } else {
let nh2 = nh * nh; let nh2 = nh * nh;
self.normalization_factor / (1.0 + ((roughness2 - 1.0) * nh2)).powf(self.tail_shape) self.normalization_factor / (1.0 + ((roughness2 - 1.0) * nh2)).powf(self.tail_shape)
}; }
dist
} }
} }
@ -567,7 +566,7 @@ impl SurfaceClosure for GTRClosure {
}; };
// Final result // Final result
return col_f * (dist * g1 * g2) * INV_PI; col_f * (dist * g1 * g2) * INV_PI
} }
} }
@ -588,7 +587,7 @@ impl SurfaceClosure for GTRClosure {
// Calculate needed dot products // Calculate needed dot products
let nh = clamp(dot(nn, hh), -1.0, 1.0); let nh = clamp(dot(nn, hh), -1.0, 1.0);
return self.dist(nh, self.roughness) * INV_PI; self.dist(nh, self.roughness) * INV_PI
} }
@ -639,6 +638,6 @@ impl SurfaceClosure for GTRClosure {
(1.0f32).min(self.roughness.sqrt() + (2.0 * theta / PI_32)), (1.0f32).min(self.roughness.sqrt() + (2.0 * theta / PI_32)),
); );
return fac * (1.0f32).min(1.0 - cos_theta) * INV_PI; fac * (1.0f32).min(1.0 - cos_theta) * INV_PI
} }
} }

View File

@ -83,9 +83,9 @@ pub fn intersect_ray(ray: &Ray, tri: (Point, Point, Point)) -> Option<(f32, f32,
let t_scaled = (e0 * p0z) + (e1 * p1z) + (e2 * p2z); let t_scaled = (e0 * p0z) + (e1 * p1z) + (e2 * p2z);
// Check if the hitpoint t is within ray min/max t. // 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)) { if (det > 0.0 && (t_scaled <= 0.0 || t_scaled > (ray.max_t * det))) ||
return None; (det < 0.0 && (t_scaled >= 0.0 || t_scaled < (ray.max_t * det)))
} else if det < 0.0 && (t_scaled >= 0.0 || t_scaled < (ray.max_t * det)) { {
return None; return None;
} }

View File

@ -30,7 +30,7 @@ impl<'a> TriangleMesh<'a> {
time_samples: usize, time_samples: usize,
triangles: Vec<(Point, Point, Point)>, triangles: Vec<(Point, Point, Point)>,
) -> TriangleMesh<'b> { ) -> TriangleMesh<'b> {
assert!(triangles.len() % time_samples == 0); assert_eq!(triangles.len() % time_samples, 0);
let mut indices: Vec<usize> = (0..(triangles.len() / time_samples)) let mut indices: Vec<usize> = (0..(triangles.len() / time_samples))
.map(|n| n * time_samples) .map(|n| n * time_samples)
@ -38,7 +38,7 @@ impl<'a> TriangleMesh<'a> {
let bounds = { let bounds = {
let mut bounds = Vec::new(); let mut bounds = Vec::new();
for tri in triangles.iter() { for tri in &triangles {
let minimum = tri.0.min(tri.1.min(tri.2)); let minimum = tri.0.min(tri.1.min(tri.2));
let maximum = tri.0.max(tri.1.max(tri.2)); let maximum = tri.0.max(tri.1.max(tri.2));
bounds.push(BBox::from_points(minimum, maximum)); bounds.push(BBox::from_points(minimum, maximum));
@ -60,7 +60,7 @@ impl<'a> TriangleMesh<'a> {
} }
impl<'a> Boundable for TriangleMesh<'a> { impl<'a> Boundable for TriangleMesh<'a> {
fn bounds<'b>(&'b self) -> &'b [BBox] { fn bounds(&self) -> &[BBox] {
self.accel.bounds() self.accel.bounds()
} }
} }
@ -83,7 +83,7 @@ impl<'a> Surface for TriangleMesh<'a> {
self.accel self.accel
.traverse( .traverse(
&mut accel_rays[..], &self.indices, |tri_i, rs| { &mut accel_rays[..], self.indices, |tri_i, rs| {
for r in rs { for r in rs {
let wr = &wrays[r.id as usize]; let wr = &wrays[r.id as usize];
@ -96,7 +96,7 @@ impl<'a> Surface for TriangleMesh<'a> {
// Transform triangle as necessary, and get transform // Transform triangle as necessary, and get transform
// space. // space.
let (mat_space, tri) = if space.len() > 0 { let (mat_space, tri) = if !space.is_empty() {
if space.len() > 1 { if space.len() > 1 {
// Per-ray transform, for motion blur // Per-ray transform, for motion blur
let mat_space = lerp_slice(space, wr.time).inverse(); let mat_space = lerp_slice(space, wr.time).inverse();

View File

@ -33,7 +33,7 @@ impl<'a> Tracer<'a> {
|wr| AccelRay::new(wr, ids.next().unwrap()), |wr| AccelRay::new(wr, ids.next().unwrap()),
)); ));
return self.inner.trace(wrays, &mut self.rays[..]); self.inner.trace(wrays, &mut self.rays[..])
} }
} }
@ -56,11 +56,11 @@ impl<'a> TracerInner<'a> {
); );
let mut ray_sets = split_rays_by_direction(&mut rays[..]); let mut ray_sets = split_rays_by_direction(&mut rays[..]);
for ray_set in ray_sets.iter_mut().filter(|ray_set| ray_set.len() > 0) { for ray_set in ray_sets.iter_mut().filter(|ray_set| !ray_set.is_empty()) {
self.trace_assembly(self.root, wrays, ray_set); self.trace_assembly(self.root, wrays, ray_set);
} }
return &self.isects; &self.isects
} }
fn trace_assembly<'b>( fn trace_assembly<'b>(
@ -102,7 +102,7 @@ impl<'a> TracerInner<'a> {
// TODO: do this in a way that's less confusing. Probably split // TODO: do this in a way that's less confusing. Probably split
// the tracing code out into a trace_instance() method or // the tracing code out into a trace_instance() method or
// something. // something.
let mut tmp = if let Some(_) = inst.transform_indices { let mut tmp = if inst.transform_indices.is_some() {
split_rays_by_direction(rs) split_rays_by_direction(rs)
} else { } else {
[ [
@ -116,14 +116,14 @@ impl<'a> TracerInner<'a> {
&mut [], &mut [],
] ]
}; };
let mut ray_sets = if let Some(_) = inst.transform_indices { let mut ray_sets = if inst.transform_indices.is_some() {
&mut tmp[..] &mut tmp[..]
} else { } else {
&mut tmp[..1] &mut tmp[..1]
}; };
// Loop through the split ray slices and trace them // Loop through the split ray slices and trace them
for ray_set in ray_sets.iter_mut().filter(|ray_set| ray_set.len() > 0) { for ray_set in ray_sets.iter_mut().filter(|ray_set| !ray_set.is_empty()) {
match inst.instance_type { match inst.instance_type {
InstanceType::Object => { InstanceType::Object => {
self.trace_object( self.trace_object(
@ -145,13 +145,13 @@ impl<'a> TracerInner<'a> {
} }
// Un-transform rays if needed // Un-transform rays if needed
if let Some(_) = inst.transform_indices { if inst.transform_indices.is_some() {
// Pop transforms off stack // Pop transforms off stack
self.xform_stack.pop(); self.xform_stack.pop();
// Undo transforms // Undo transforms
let xforms = self.xform_stack.top(); let xforms = self.xform_stack.top();
if xforms.len() > 0 { if !xforms.is_empty() {
for ray in &mut rs[..] { for ray in &mut rs[..] {
let id = ray.id; let id = ray.id;
let t = ray.time; let t = ray.time;
@ -172,12 +172,12 @@ impl<'a> TracerInner<'a> {
} }
fn trace_object<'b>(&'b mut self, obj: &Object, wrays: &[Ray], rays: &mut [AccelRay]) { fn trace_object<'b>(&'b mut self, obj: &Object, wrays: &[Ray], rays: &mut [AccelRay]) {
match obj { match *obj {
&Object::Surface(ref surface) => { Object::Surface(surface) => {
surface.intersect_rays(rays, wrays, &mut self.isects, self.xform_stack.top()); surface.intersect_rays(rays, wrays, &mut self.isects, self.xform_stack.top());
} }
&Object::Light(_) => { Object::Light(_) => {
// TODO // TODO
} }
} }

View File

@ -30,9 +30,9 @@ impl TransformStack {
} }
pub fn push(&mut self, xforms: &[Matrix4x4]) { pub fn push(&mut self, xforms: &[Matrix4x4]) {
assert!(xforms.len() > 0); assert!(!xforms.is_empty());
if self.stack.len() == 0 { if self.stack.is_empty() {
self.stack.extend(xforms); self.stack.extend(xforms);
} else { } else {
let sil = self.stack_indices.len(); let sil = self.stack_indices.len();
@ -66,7 +66,7 @@ impl TransformStack {
self.stack_indices.pop(); self.stack_indices.pop();
} }
pub fn top<'a>(&'a self) -> &'a [Matrix4x4] { pub fn top(&self) -> &[Matrix4x4] {
let sil = self.stack_indices.len(); let sil = self.stack_indices.len();
let i1 = self.stack_indices[sil - 2]; let i1 = self.stack_indices[sil - 2];
let i2 = self.stack_indices[sil - 1]; let i2 = self.stack_indices[sil - 1];