From 43cae9ac71f2d6933ba3ea25641585bb88ae60ad Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Sat, 15 Aug 2026 17:59:17 -0700 Subject: working, performance is bad --- src/camera.rs | 140 +++++++++++++++++----------------------------------------- 1 file changed, 40 insertions(+), 100 deletions(-) (limited to 'src/camera.rs') diff --git a/src/camera.rs b/src/camera.rs index 55a698c..0b69833 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,18 +1,25 @@ -use crate::{ - Input, - config::{CAMERA_MOVEMENT_SPEED, CHUNK_SIZE}, - sim::{chunk::Chunk, world::World}, -}; +use crate::{Input, config::CAMERA_MOVEMENT_SPEED}; + +#[repr(C)] +#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +pub struct CameraUniform { + pub scale: [f32; 2], + pub centre: [f32; 2], +} pub struct Camera { - // centre coords - pub x: f64, - pub y: f64, - // zoom scale factor, 1.0 = board <-> window - pub zoom: f64, + pub zoom: f32, + pub centre: (f32, f32), + screen_size: (i32, i32), } impl Camera { + fn scale(&self) -> (f32, f32) { + let half_w = self.zoom * self.screen_size.0 as f32 / 2.0; + let half_h = self.zoom * self.screen_size.1 as f32 / 2.0; + (1.0 / half_w, -1.0 / half_h) + } + pub fn handle_camera_input(&mut self, input: &Input, delta_time: f32) { // wasd movement let x: f32 = if input.is_left_pressed { @@ -38,105 +45,38 @@ impl Camera { let adjusted_x = x / magnitude * self.zoom as f32 * CAMERA_MOVEMENT_SPEED * delta_time; let adjusted_y = y / magnitude * self.zoom as f32 * CAMERA_MOVEMENT_SPEED * delta_time; - self.x += adjusted_x as f64; - self.y += adjusted_y as f64; + self.centre.0 += adjusted_x as f32; + self.centre.1 += adjusted_y as f32; } - pub fn screen_position_to_world(&self, screen_x: f64, screen_y: f64) -> (f64, f64) { - let camera_width = self.zoom * f64::from(1600); - let camera_height = self.zoom * f64::from(1200); - let camera_start_x = self.x - camera_width / 2.0; - let camera_start_y = self.y - camera_height / 2.0; - ( - (screen_x / 1600 as f64 * camera_width) + camera_start_x, - (screen_y / 1200 as f64 * camera_height) + camera_start_y, - ) - } - - pub fn write_frame_view(&self, frame: &mut [u8], world: &World) { - puffin::profile_function!(); + pub fn screen_position_to_world(&self, x: f32, y: f32) -> (f32, f32) { + let (scale_x, scale_y) = self.scale(); - // for i in 0..frame.len() / 4 { - // let idx = i * 4; - // frame[idx] = (i / 1000) as u8; - // frame[idx + 1] = 0x00; - // frame[idx + 2] = 0x00; - // frame[idx + 3] = 0xFF; - // } - // return; - - const BG: [u8; 4] = [0x00, 0x00, 0x00, 0xFF]; - for px in frame.chunks_exact_mut(4) { - px.copy_from_slice(&BG); - } + let ndc_x = x / self.screen_size.0 as f32 * 2.0 - 1.0; + let world_x = ndc_x / scale_x + self.centre.0; + let ndc_y = y / self.screen_size.1 as f32 * 2.0 - 1.0; + let world_y = ndc_y / -scale_y + self.centre.1; - // world-space rect covered by the screen - let (xl, yl) = self.screen_position_to_world(0.0, 0.0); - let (xu, yu) = self.screen_position_to_world(1600 as f64, 1200 as f64); - - let c = CHUNK_SIZE; - let cx0 = (xl.floor() as i32).div_euclid(c); - let cx1 = (xu.ceil() as i32).div_euclid(c); - let cy0 = (yl.floor() as i32).div_euclid(c); - let cy1 = (yu.ceil() as i32).div_euclid(c); - - let scale = 1.0 / self.zoom; // pixels per cell + (world_x, world_y) + } - for cy in cy0..=cy1 { - for cx in cx0..=cx1 { - let Some(&idx) = world.chunk_position_to_chunk_idx.get(&(cx, cy)) else { - continue; - }; - self.write_chunk(frame, &world.chunks[idx], cx, cy, xl, yl, scale); - } + pub fn to_uniform(&self) -> CameraUniform { + let (scale_x, scale_y) = self.scale(); + CameraUniform { + scale: [scale_x, scale_y], + centre: [self.centre.0, self.centre.1], } } - fn write_chunk( - &self, - frame: &mut [u8], - chunk: &Chunk, - cx: i32, - cy: i32, - xl: f64, - yl: f64, - scale: f64, - ) { - let c = CHUNK_SIZE; - let w = 1600 as i32; - let h = 1200 as i32; - - for ly in 0..c { - let wy = (cy * c + ly) as f64; - let sy0 = (((wy - yl) * scale).floor() as i32).max(0); - let sy1 = (((wy + 1.0 - yl) * scale).floor() as i32).min(h); - if sy0 >= sy1 { - continue; - } - - for lx in 0..c { - let wx = (cx * c + lx) as f64; - let sx0 = (((wx - xl) * scale).floor() as i32).max(0); - let sx1 = (((wx + 1.0 - xl) * scale).floor() as i32).min(w); - if sx0 >= sx1 { - continue; - } - - let color = chunk - .get_cell_at_local_position(lx as u8, ly as u8) - .material - .def() - .color; - let rgba = [color.0, color.1, color.2, color.3]; + pub fn resize(&mut self, screen_size: (i32, i32)) -> () { + self.screen_size = screen_size; + } - for sy in sy0..sy1 { - let start = (sy * w + sx0) as usize * 4; - let end = (sy * w + sx1) as usize * 4; - for px in frame[start..end].chunks_exact_mut(4) { - px.copy_from_slice(&rgba); - } - } - } + pub fn new(screen_size: (i32, i32)) -> Self { + Camera { + zoom: 0.2, + centre: (0.0, 0.0), + screen_size, } } } -- cgit v1.3.1