use super::prelude::*;
use crate::image::prelude::*;
use crate::linalg::ray::Ray;
use crate::trace::sampling::SamplingStrategy;
use crate::trace::world::World;
use rand::RngCore;
use std::sync::mpsc::Receiver;
use std::sync::{mpsc, Arc, Mutex};
use std::thread;
use std::thread::JoinHandle;
pub struct Camera<const W: usize, const H: usize> {
aspect_ratio: f64,
origin: Vec3,
right: Vec3,
up: Vec3,
forward: Vec3,
viewport_top_left: Vec3,
pub gamma: f64,
}
impl<const W: usize, const H: usize> Camera<W, H> {
pub unsafe fn new_unchecked(
origin: Vec3,
right: Vec3,
up: Vec3,
focal_length: f64,
gamma: f64,
) -> Self {
let aspect_ratio = W as f64 / H as f64;
let forward = right.cross(up);
let viewport_middle = origin + forward * focal_length;
let viewport_top_left = viewport_middle - right * 0.5 + up * 0.5 / aspect_ratio;
Self {
aspect_ratio,
origin,
right,
up,
forward,
viewport_top_left,
gamma,
}
}
pub fn sampling_rays_for_pixel(
&self,
rng: &mut Box<dyn RngCore>,
sampling_strategy: Arc<dyn SamplingStrategy>,
x: usize,
y: usize,
) -> Vec<Ray<f64, 3>> {
sampling_strategy
.get_sample_positions(rng, x, y)
.into_iter()
.map(|(x, y)| {
let direction =
self.viewport_top_left + self.right * x - self.up * y / self.aspect_ratio;
Ray::new(self.origin, direction)
})
.collect()
}
fn trace_sample(&self, rng: &mut Box<dyn RngCore>, world: &World, x: f64, y: f64) -> Colour {
let direction = self.viewport_top_left + self.right * x - self.up * y / self.aspect_ratio;
let ray = Ray::new(self.origin, direction);
world.trace(rng, &ray)
}
fn spawn_threads<S: SamplingStrategy + Clone + 'static>(
&'static self,
sampling_strategy: S,
world: Arc<World>,
num_threads: usize,
) -> (Vec<JoinHandle<()>>, Receiver<Vec<Colour>>) {
let (tx, rx) = mpsc::channel::<Vec<Colour>>();
let lines_numbers = Arc::new(Mutex::new(0..H));
let join_handles = (0..num_threads).map(|_| {
let line_nums = lines_numbers.clone();
let tx = tx.clone();
let sampling_strategy = sampling_strategy.clone();
});
thread::spawn(move || {
let mut rng: Box<dyn RngCore> = Box::new(rand::thread_rng());
world.trace(&mut rng, &Ray::new(self.origin, self.forward));
});
todo!()
}
}