diff --git a/src/bbox.rs b/src/bbox.rs index 68e0c4a..fa5e8ea 100644 --- a/src/bbox.rs +++ b/src/bbox.rs @@ -7,7 +7,7 @@ use std::{ use crate::{ lerp::{lerp, lerp_slice, Lerp}, - math::{fast_minf32, Point, Vector, Xform, XformFull}, + math::{fast_minf32, Point, Vector, Xform}, }; const BBOX_MAXT_ADJUST: f32 = 1.000_000_24; @@ -57,7 +57,7 @@ impl BBox { // Creates a new BBox transformed from its local space to the // given space. #[must_use] - pub fn xform(&self, xform: &XformFull) -> BBox { + pub fn xform(&self, xform: &Xform) -> BBox { // BBox corners let vs = [ Point::new(self.min.x(), self.min.y(), self.min.z()), @@ -73,7 +73,7 @@ impl BBox { // Transform BBox corners and make new bbox let mut b = BBox::new(); for v in &vs { - let v = v.xform(&xform); + let v = v.xform(xform); b.min = v.min(b.min); b.max = v.max(b.max); } @@ -141,11 +141,7 @@ impl Lerp for BBox { } } -pub fn transform_bbox_slice_from( - bbs_in: &[BBox], - xforms: &[Xform], - bbs_out: &mut Vec, -) -> Result<(), ()> { +pub fn transform_bbox_slice_from(bbs_in: &[BBox], xforms: &[Xform], bbs_out: &mut Vec) { bbs_out.clear(); // Transform the bounding boxes @@ -153,19 +149,17 @@ pub fn transform_bbox_slice_from( bbs_out.extend_from_slice(bbs_in); } else if bbs_in.len() == xforms.len() { for (bb, xf) in Iterator::zip(bbs_in.iter(), xforms.iter()) { - bbs_out.push(bb.xform(&xf.into_full().ok_or(())?)); + bbs_out.push(bb.xform(&xf)); } } else if bbs_in.len() > xforms.len() { let s = (bbs_in.len() - 1) as f32; for (i, bb) in bbs_in.iter().enumerate() { - bbs_out.push(bb.xform(&lerp_slice(xforms, i as f32 / s).into_full().ok_or(())?)); + bbs_out.push(bb.xform(&lerp_slice(xforms, i as f32 / s))); } } else if bbs_in.len() < xforms.len() { let s = (xforms.len() - 1) as f32; for (i, xf) in xforms.iter().enumerate() { - bbs_out.push(lerp_slice(bbs_in, i as f32 / s).xform(&xf.into_full().ok_or(())?)); + bbs_out.push(lerp_slice(bbs_in, i as f32 / s).xform(&xf)); } } - - Ok(()) } diff --git a/src/camera.rs b/src/camera.rs index 4f65a7f..7dbd3b9 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -73,7 +73,7 @@ impl<'a> Camera<'a> { pub fn generate_ray(&self, x: f32, y: f32, time: f32, wavelength: f32, u: f32, v: f32) -> Ray { // Get time-interpolated camera settings - let transform = lerp_slice(self.transforms, time).into_full_fast().unwrap(); + let transform = lerp_slice(self.transforms, time).to_full_fast().unwrap(); let tfov = lerp_slice(self.tfovs, time); let aperture_radius = lerp_slice(self.aperture_radii, time); let focus_distance = lerp_slice(self.focus_distances, time); diff --git a/src/light/rectangle_light.rs b/src/light/rectangle_light.rs index 231e687..73c3b14 100644 --- a/src/light/rectangle_light.rs +++ b/src/light/rectangle_light.rs @@ -271,7 +271,7 @@ impl<'a> Surface for RectangleLight<'a> { let dim = lerp_slice(self.dimensions, time); let xform = lerp_slice(space, time); - let space = if let Some(xform) = xform.into_full() { + let space = if let Some(xform) = xform.to_full() { xform } else { return; diff --git a/src/light/sphere_light.rs b/src/light/sphere_light.rs index 9ff1664..8da8515 100644 --- a/src/light/sphere_light.rs +++ b/src/light/sphere_light.rs @@ -215,7 +215,7 @@ impl<'a> Surface for SphereLight<'a> { let time = rays.time(ray_idx); // Get the transform space - let xform = if let Some(xform) = lerp_slice(space, time).into_full() { + let xform = if let Some(xform) = lerp_slice(space, time).to_full() { xform } else { return; diff --git a/src/math.rs b/src/math.rs index 2fd40da..705f8ee 100644 --- a/src/math.rs +++ b/src/math.rs @@ -3,8 +3,8 @@ use std::f32; pub use rmath::{ - cross, cross_fast, dot, dot_fast, wide4::Float4, CrossProduct, DotProduct, Normal, Point, - Vector, Xform, XformFull, + cross, cross_fast, dot, dot_fast, wide4::Float4, AsXform, CrossProduct, DotProduct, Normal, + Point, Vector, Xform, XformFull, }; /// Clamps a value between a min and max. diff --git a/src/scene/assembly.rs b/src/scene/assembly.rs index 2f47cfe..1e6e98c 100644 --- a/src/scene/assembly.rs +++ b/src/scene/assembly.rs @@ -58,7 +58,7 @@ impl<'a> Assembly<'a> { } = *intr { let sel_xform = if !xform_stack.top().is_empty() { - if let Some(xform) = lerp_slice(xform_stack.top(), time).into_full() { + if let Some(xform) = lerp_slice(xform_stack.top(), time).to_full() { xform } else { return None; @@ -98,7 +98,7 @@ impl<'a> Assembly<'a> { Xform::identity() } } - .into_full(); + .to_full(); // Sample the light if let Some(xform) = xform { @@ -390,7 +390,7 @@ impl<'a> AssemblyBuilder<'a> { // Transform the bounding boxes, if necessary if let Some((xstart, xend)) = inst.transform_indices { let xf = &self.xforms[xstart..xend]; - transform_bbox_slice_from(&bbs, xf, &mut bbs2).unwrap(); + transform_bbox_slice_from(&bbs, xf, &mut bbs2); } else { bbs2.clear(); bbs2.extend(bbs); diff --git a/src/surface/micropoly_batch.rs b/src/surface/micropoly_batch.rs index 9a95e31..cb7e6c4 100644 --- a/src/surface/micropoly_batch.rs +++ b/src/surface/micropoly_batch.rs @@ -9,7 +9,7 @@ use crate::{ bbox::BBox, boundable::Boundable, lerp::lerp_slice, - math::{cross, dot, Normal, Point, Xform, XformFull}, + math::{cross, dot, Normal, Point, Xform}, ray::{RayBatch, RayStack}, shading::SurfaceClosure, }; @@ -154,13 +154,9 @@ impl<'a> MicropolyBatch<'a> { ) { // Precalculate transform for non-motion blur cases let static_mat_space = if space.len() == 1 { - if let Some(xform) = space[0].into_full() { - xform - } else { - return; - } + space[0] } else { - XformFull::identity() + Xform::identity() }; self.accel @@ -209,11 +205,7 @@ impl<'a> MicropolyBatch<'a> { // Calculate the ray space, if necessary. let mat_space = if space.len() > 1 { // Per-ray transform, for motion blur - if let Some(xform) = lerp_slice(space, ray_time).into_full() { - xform - } else { - return; - } + lerp_slice(space, ray_time) } else { static_mat_space }; @@ -292,6 +284,13 @@ impl<'a> MicropolyBatch<'a> { // Calculate intersection data if necessary. if non_shadow_hit { + // Get the full space data. + let mat_space = if let Some(space) = mat_space.to_full() { + space + } else { + return; + }; + let hit_tri = unsafe { hit_tri.assume_init() }; let hit_tri_indices = unsafe { hit_tri_indices.assume_init() }; let (t, b0, b1, b2) = unsafe { hit_tri_data.assume_init() }; diff --git a/src/surface/triangle_mesh.rs b/src/surface/triangle_mesh.rs index f41ca6f..6e3546a 100644 --- a/src/surface/triangle_mesh.rs +++ b/src/surface/triangle_mesh.rs @@ -7,7 +7,7 @@ use crate::{ bbox::BBox, boundable::Boundable, lerp::lerp_slice, - math::{cross, dot, Normal, Point, Xform, XformFull}, + math::{cross, dot, Normal, Point, Xform}, ray::{RayBatch, RayStack}, shading::SurfaceShader, }; @@ -132,13 +132,9 @@ impl<'a> Surface for TriangleMesh<'a> { ) { // Precalculate transform for non-motion blur cases let static_mat_space = if space.len() == 1 { - if let Some(xform) = lerp_slice(space, 0.0).into_full() { - xform - } else { - return; - } + space[0] } else { - XformFull::identity() + Xform::identity() }; self.accel @@ -187,11 +183,7 @@ impl<'a> Surface for TriangleMesh<'a> { // Calculate the ray space, if necessary. let mat_space = if space.len() > 1 { // Per-ray transform, for motion blur - if let Some(xform) = lerp_slice(space, ray_time).into_full() { - xform - } else { - return; - } + lerp_slice(space, ray_time) } else { static_mat_space }; @@ -270,6 +262,13 @@ impl<'a> Surface for TriangleMesh<'a> { // Calculate intersection data if necessary. if non_shadow_hit { + // Get the full space data. + let mat_space = if let Some(space) = mat_space.to_full() { + space + } else { + return; + }; + let hit_tri = unsafe { hit_tri.assume_init() }; let (t, b0, b1, b2) = unsafe { hit_tri_data.assume_init() }; diff --git a/src/tracer.rs b/src/tracer.rs index 88833d3..5a3d834 100644 --- a/src/tracer.rs +++ b/src/tracer.rs @@ -103,16 +103,27 @@ impl<'a> TracerInner<'a> { // Do transforms // TODO: re-divide rays based on direction (maybe?). let xforms = self.xform_stack.top(); + let static_xform = if xforms.len() == 1 { + if let Some(xform) = xforms[0].to_full() { + Some(xform) + } else { + return; + } + } else if xforms.len() == 0 { + Some(XformFull::identity()) + } else { + None + }; ray_stack.do_next_task(|ray_idx| { let t = rays.time(ray_idx); rays.update_local( ray_idx, - &if let Some(xform) = lerp_slice(xforms, t).into_full() { - xform - } else { - // TODO: filter out ray instead. - XformFull::identity() - }, + &static_xform.unwrap_or_else(|| { + lerp_slice(xforms, t).to_full().unwrap_or( + // TODO: filter out ray instead. + XformFull::identity(), + ) + }), ); }); ray_stack.duplicate_next_task(); @@ -142,17 +153,28 @@ impl<'a> TracerInner<'a> { // Undo transforms let xforms = self.xform_stack.top(); + let static_xform = if xforms.len() == 1 { + if let Some(xform) = xforms[0].to_full() { + Some(xform) + } else { + return; + } + } else if xforms.len() == 0 { + Some(XformFull::identity()) + } else { + None + }; if !xforms.is_empty() { ray_stack.pop_do_next_task(|ray_idx| { let t = rays.time(ray_idx); rays.update_local( ray_idx, - &if let Some(xform) = lerp_slice(xforms, t).into_full() { - xform - } else { - // TODO: filter out ray instead. - XformFull::identity() - }, + &static_xform.unwrap_or_else(|| { + lerp_slice(xforms, t).to_full().unwrap_or( + // TODO: filter out ray instead. + XformFull::identity(), + ) + }), ); }); } else {