77 lines
2.2 KiB
Rust
77 lines
2.2 KiB
Rust
use ray_tracing_core::light::AreaLight;
|
|
use ray_tracing_core::prelude::*;
|
|
use ray_tracing_core::scene::{Intersection, Scene};
|
|
use ray_tracing_material::default::DefaultMaterial;
|
|
|
|
#[derive(Clone)]
|
|
pub struct BasicScene<M> {
|
|
pub(crate) spheres: Vec<(Pos3, Float)>,
|
|
area_light: AreaLight,
|
|
material: M,
|
|
}
|
|
|
|
impl<M> BasicScene<M> {
|
|
pub fn new(material: M) -> Self {
|
|
Self {
|
|
spheres: vec![(Pos3::zero(), 1.0), (Pos3::new(0.0, -4.5, 0.0), 4.0)],
|
|
area_light: AreaLight::new(Color::white()),
|
|
material,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for BasicScene<DefaultMaterial> {
|
|
fn default() -> Self {
|
|
Self::new(DefaultMaterial {})
|
|
}
|
|
}
|
|
|
|
impl<R: Rng, M: Material<R>> Scene<R> for BasicScene<M> {
|
|
fn intersect(&self, ray: Ray, min: Float, max: Float) -> Option<Intersection<'_, R>> {
|
|
let mut intersection: Option<Intersection<'_, R>> = None;
|
|
|
|
for &(c, r) in &self.spheres {
|
|
let offset = ray.start() - c;
|
|
let p = Dir3::dot(ray.dir(), offset);
|
|
let delta = p * p - (offset.length_squared() - r * r);
|
|
|
|
if delta >= 0.0 {
|
|
let d = -p - Float::sqrt(delta);
|
|
|
|
let int = Intersection::new(
|
|
d,
|
|
((ray.start() + d * ray.dir()) - c).normalize(),
|
|
Some(&self.material),
|
|
None,
|
|
0.0,
|
|
);
|
|
if d >= min && d <= max {
|
|
if let Some(i) = intersection.as_ref() {
|
|
if i.t() > d {
|
|
intersection.replace(int);
|
|
}
|
|
} else {
|
|
intersection = Some(int)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Some(intersection.unwrap_or(Intersection::new(
|
|
Float::INFINITY,
|
|
-ray.dir(),
|
|
None,
|
|
Some(&self.area_light),
|
|
0.0,
|
|
)))
|
|
}
|
|
|
|
fn sample_light(
|
|
&self,
|
|
_w_in: Dir3,
|
|
_intersection: &Intersection<'_, R>,
|
|
_rng: &mut R,
|
|
) -> Option<ray_tracing_core::scene::LightSample<'_, R>> {
|
|
None
|
|
}
|
|
}
|