I am doing some basic ray tracing and currently wanted to have this basic code:
/// A ray-hittable or drawable object.
pub trait Hittable: Origin + TransformMatrix /*+ Hits<Self> ???*/ {}
/// Returns only hits, not all intersections.
pub trait Hits<'a, Object> {
/// Returns all the hits.
fn hits(&self, object: &'a Object) -> Vec<Intersection<'a, Object>>;
}
impl<'a, T, Object> Hits<'a, Object> for T
where
T: IntersectionsWith<'a, Object>,
{
fn hits(&self, object: &'a Object) -> Vec<Intersection<'a, Object>> {
self.intersections_with(object)
.into_iter()
.filter(|v| v.value >= 0.0)
.collect()
}
}
impl<'a> IntersectionsWith<'a, Sphere> for Ray {
fn intersections_with(&self, object: &'a Sphere) -> Vec<Intersection<'a, Sphere>> {
self.distance_to_intersections(object)
.into_iter()
.map(|value| Intersection { object, value })
.collect()
}
}
Here, in this basic code, there is a Ray
type which implements Hits<'a, T>
for T: Spherical + Origin + TransformMatrix
(eventually, through some other traits) because a ray requires knowing these properties of an object for intersecting (for now). Now, I want to create a world containing a vector of such objects and wanted to come up with some common marker trait like Hittable
or Drawable
which means that if this trait is implemented then a ray can actually be cast to this object and checked for intersections.
Is it possible for one trait A
to require that some other type (Ray
) implements trait B
with the type for type A
?
Ideally, it would look something like:
/// A ray-hittable or drawable object.
pub trait Hittable: Origin + TransformMatrix + Hits<Ray, Self> {}
where Hits<Ray, Self>
means there is an implementation of Hits<T>
for Ray where T
is Self
, where Self
implements Hittable
:
// Hits<Ray, Self> means there is
impl Hits<Sphere> for Ray { }
impl TransformMatrix for Sphere { }
impl Origin for Sphere { }
impl Hittable for Sphere { }