From 351d9132c0b2c54dfa9f50bfe328d25ccf059cea Mon Sep 17 00:00:00 2001 From: Julian T Date: Mon, 2 Aug 2021 15:21:59 +0200 Subject: Move back to dynamic dispatch for object.shape This will allow more general nesting, with the performance penalty of dynamic dispatching. This is implemented with the DynHittable for convenience. --- src/world/hittable.rs | 18 ++++++++++++++++++ src/world/mod.rs | 12 ++++++------ src/world/scene.rs | 9 +++++++-- src/world/shapes/sphere.rs | 8 +++++++- 4 files changed, 38 insertions(+), 9 deletions(-) (limited to 'src/world') diff --git a/src/world/hittable.rs b/src/world/hittable.rs index e11a3bc..4fbd3d0 100644 --- a/src/world/hittable.rs +++ b/src/world/hittable.rs @@ -2,6 +2,8 @@ use crate::core::{Vector3f, Bound3f, Ray}; use crate::Float; use crate::material::Material; +use std::ops::Deref; + /// Returns the context of a intersection pub struct Intersection<'a> { /// Normal vector at intersection @@ -39,3 +41,19 @@ pub trait Hittable: Sync + Send { /// Returns the axis alligned bounding box containing self fn bounding_box(&self) -> Bound3f; } + +pub struct DynHittable(Box); + +impl DynHittable { + pub fn new(hit: Box) -> Self { + Self (hit) + } +} + +impl Deref for DynHittable { + type Target = dyn Hittable; + + fn deref(&self) -> &Self::Target { + self.0.as_ref() + } +} diff --git a/src/world/mod.rs b/src/world/mod.rs index cba6ddc..0779551 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -5,7 +5,7 @@ mod scene; pub mod container; mod hittable; pub use scene::*; -pub use hittable::{Intersection, Hittable}; +pub use hittable::{Intersection, Hittable, DynHittable}; pub use shapes::Shape; use std::sync::Arc; @@ -13,22 +13,22 @@ use crate::material::Material; use crate::core::{Bound3f, Ray}; pub struct Object { - pub shape: Shape, + pub inner: DynHittable, pub mat: Arc, } impl Object { - pub fn new>(mat: Arc, shape: T) -> Self { + pub fn new>(mat: Arc, inner: T) -> Self { Object { mat, - shape: shape.into(), + inner: inner.into(), } } } impl Hittable for Object { fn intersect(&self, ray: &Ray) -> Option { - if let Some(mut inter) = self.shape.intersect(ray) { + if let Some(mut inter) = self.inner.intersect(ray) { inter.add_material_if_none(self.mat.as_ref()); Some(inter) } else { @@ -37,6 +37,6 @@ impl Hittable for Object { } fn bounding_box(&self) -> Bound3f { - self.shape.bounding_box() + self.inner.bounding_box() } } diff --git a/src/world/scene.rs b/src/world/scene.rs index 87bec1f..8954050 100644 --- a/src/world/scene.rs +++ b/src/world/scene.rs @@ -1,5 +1,7 @@ use crate::core::{Bound3f, Ray}; +use std::iter::IntoIterator; + use super::{Object, container, Hittable, Intersection}; type Container = container::HittableList; @@ -17,8 +19,11 @@ impl Scene { self.content.add(obj); } - pub fn add_objects(&mut self, objs: Vec) { - for obj in objs { + pub fn add_objects(&mut self, objs: T) + where + T: IntoIterator, + { + for obj in objs.into_iter() { self.add_object(obj); } } diff --git a/src/world/shapes/sphere.rs b/src/world/shapes/sphere.rs index 1df9c35..fc2cfe2 100644 --- a/src/world/shapes/sphere.rs +++ b/src/world/shapes/sphere.rs @@ -3,7 +3,7 @@ //! Spheres are relatively easy to calculate intersections between use crate::{Float, NEAR_ZERO}; use crate::core::{Ray, Vector3f, Bound3f}; -use crate::world::{Hittable, Intersection}; +use crate::world::{Hittable, DynHittable, Intersection}; pub struct Sphere { radius: Float, @@ -79,6 +79,12 @@ impl Hittable for Sphere { } } +impl Into for Sphere { + fn into(self) -> DynHittable { + DynHittable::new(Box::new(self)) + } +} + #[cfg(test)] mod tests { use super::*; -- cgit v1.2.3