use nalgebra::RealField;
use num_traits::ToPrimitive;
use std::borrow::Cow;
use crate::{
error::Result,
geometry::{Aabb, Mesh, Plane, Sphere, Triangle},
rt::{Hit, Ray},
scene::Instance,
traits::{Bounded, Traceable},
};
#[derive(Debug)]
pub enum SceneObject<'a, T: RealField + Copy> {
Sphere(Sphere<T>),
Plane(Plane<T>),
Triangle(Triangle<T>),
Mesh(Mesh<T>),
Instance(Instance<'a, T>),
}
impl<T: RealField + Copy + ToPrimitive> Bounded<T> for SceneObject<'_, T> {
fn aabb(&self) -> Result<Cow<Aabb<T>>> {
match self {
SceneObject::Sphere(sphere) => sphere.aabb(),
SceneObject::Plane(plane) => plane.aabb(),
SceneObject::Triangle(triangle) => triangle.aabb(),
SceneObject::Mesh(mesh) => mesh.aabb(),
SceneObject::Instance(instance) => Ok(Cow::Borrowed(instance.world_aabb())),
}
}
}
impl<T: RealField + Copy + ToPrimitive> Traceable<T> for SceneObject<'_, T> {
fn intersect(&self, ray: &Ray<T>) -> Result<Option<Hit<T>>> {
match self {
SceneObject::Sphere(sphere) => sphere.intersect(ray),
SceneObject::Plane(plane) => plane.intersect(ray),
SceneObject::Triangle(triangle) => triangle.intersect(ray),
SceneObject::Mesh(mesh) => mesh.intersect(ray),
SceneObject::Instance(instance) => instance.intersect(ray),
}
}
fn intersect_any(&self, ray: &Ray<T>, max_distance: T) -> Result<bool> {
match self {
SceneObject::Sphere(sphere) => sphere.intersect_any(ray, max_distance),
SceneObject::Plane(plane) => plane.intersect_any(ray, max_distance),
SceneObject::Triangle(triangle) => triangle.intersect_any(ray, max_distance),
SceneObject::Mesh(mesh) => mesh.intersect_any(ray, max_distance),
SceneObject::Instance(instance) => instance.intersect_any(ray, max_distance),
}
}
}