use std::{fs::File, io::Write, path::PathBuf}; use nalgebra::Point2; use crate::algebra::{Scalar, N}; use crate::renderer::Camera; use crate::particle_system::Particle; pub struct PPM { pub prefix: PathBuf, buffer: [[bool; WIDTH]; HEIGHT], // pixels_per_unit: usize, } impl PPM { pub fn new(prefix: PathBuf) -> Self { Self { prefix, buffer: [[false; WIDTH]; HEIGHT], } } pub fn clear_buffer(&mut self) { self.buffer = [[false; WIDTH]; HEIGHT] } pub fn draw_circle(&mut self, center: Point2, radius: Scalar) { let screen_center = Point2::new((WIDTH / 2) as Scalar, (HEIGHT / 2) as Scalar); for pixel_row in 0..HEIGHT { for pixel_col in 0..WIDTH { let point = Point2::new(pixel_col as Scalar, pixel_row as Scalar); if (point - center - screen_center.coords).norm() <= radius { self.buffer[HEIGHT - pixel_row - 1][pixel_col] = true } } } } pub fn render_particles(&mut self, particles: &Vec, camera: &Camera) { for p in particles { let point = camera.world_to_screen_space(p.position); self.draw_circle(point, p.mass.powf(1.0 / N as Scalar)); } } pub fn save_frame(&self, time: Scalar) { let file_name = format!("frame-{:08.3}", time); let path = self.prefix.join(file_name); let mut file = File::create(path).unwrap(); let mut s = format!("P3\n{} {}\n255\n", WIDTH, HEIGHT); let white = "255 255 255 "; let black = "0 0 0 "; for row in self.buffer { for pixel in row { let color = if pixel { black } else { white }; s += color } s += "\n"; } file.write(s.as_bytes()).unwrap(); } }