diff options
author | Julian T <julian@jtle.dk> | 2021-08-02 15:21:59 +0200 |
---|---|---|
committer | Julian T <julian@jtle.dk> | 2021-08-02 15:21:59 +0200 |
commit | 351d9132c0b2c54dfa9f50bfe328d25ccf059cea (patch) | |
tree | c2b9401c6484f1ba5354de4ea5dc6f58b2a214cd /src/world | |
parent | 13e018067631a7401df5b232f95f3d1f7a0cd75c (diff) |
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.
Diffstat (limited to 'src/world')
-rw-r--r-- | src/world/hittable.rs | 18 | ||||
-rw-r--r-- | src/world/mod.rs | 12 | ||||
-rw-r--r-- | src/world/scene.rs | 9 | ||||
-rw-r--r-- | src/world/shapes/sphere.rs | 8 |
4 files changed, 38 insertions, 9 deletions
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<dyn Hittable>); + +impl DynHittable { + pub fn new(hit: Box<dyn Hittable>) -> 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<dyn Material>, } impl Object { - pub fn new<T: Into<Shape>>(mat: Arc<dyn Material>, shape: T) -> Self { + pub fn new<T: Into<DynHittable>>(mat: Arc<dyn Material>, inner: T) -> Self { Object { mat, - shape: shape.into(), + inner: inner.into(), } } } impl Hittable for Object { fn intersect(&self, ray: &Ray) -> Option<Intersection> { - 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<Object>) { - for obj in objs { + pub fn add_objects<T>(&mut self, objs: T) + where + T: IntoIterator<Item = Object>, + { + 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<DynHittable> for Sphere { + fn into(self) -> DynHittable { + DynHittable::new(Box::new(self)) + } +} + #[cfg(test)] mod tests { use super::*; |