From feefeecec6c6050635b2c016452dfa1529575987 Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Thu, 13 Aug 2026 01:56:09 -0700 Subject: big refactor for board --- src/camera.rs | 110 ++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 77 insertions(+), 33 deletions(-) (limited to 'src/camera.rs') diff --git a/src/camera.rs b/src/camera.rs index 604cb0d..9310cac 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,7 +1,7 @@ use crate::{ Input, - config::{CAMERA_MOVEMENT_SPEED, PIXEL_BUFFER_HEIGHT, PIXEL_BUFFER_WIDTH}, - sim::board::Board, + config::{CAMERA_MOVEMENT_SPEED, CHUNK_SIZE, PIXEL_BUFFER_HEIGHT, PIXEL_BUFFER_WIDTH}, + sim::{chunk::Chunk, world::World}, }; pub struct Camera { @@ -42,14 +42,9 @@ impl Camera { self.y += adjusted_y as f64; } - pub fn screen_position_to_board( - &self, - board: &Board, - screen_x: f64, - screen_y: f64, - ) -> (f64, f64) { - let camera_width = self.zoom * f64::from(board.size_x); - let camera_height = self.zoom * f64::from(board.size_y); + pub fn screen_position_to_world(&self, screen_x: f64, screen_y: f64) -> (f64, f64) { + let camera_width = self.zoom * f64::from(PIXEL_BUFFER_WIDTH); + let camera_height = self.zoom * f64::from(PIXEL_BUFFER_HEIGHT); let camera_start_x = self.x - camera_width / 2.0; let camera_start_y = self.y - camera_height / 2.0; ( @@ -58,32 +53,81 @@ impl Camera { ) } - pub fn write_frame_view( + pub fn write_frame_view(&self, frame: &mut [u8], world: &World) { + puffin::profile_function!(); + + const BG: [u8; 4] = [0x00, 0x00, 0x00, 0xFF]; + for px in frame.chunks_exact_mut(4) { + px.copy_from_slice(&BG); + } + + // 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(PIXEL_BUFFER_WIDTH as f64, PIXEL_BUFFER_HEIGHT as f64); + + let c = CHUNK_SIZE as i32; + 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 + + 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); + } + } + } + + fn write_chunk( &self, frame: &mut [u8], - board: &Board, - get_overlay: impl Fn(i32, i32) -> (u8, u8, u8, u8), + chunk: &Chunk, + cx: i32, + cy: i32, + xl: f64, + yl: f64, + scale: f64, ) { - for frame_y in 0..PIXEL_BUFFER_HEIGHT { - for frame_x in 0..PIXEL_BUFFER_WIDTH { - let (x_coord, y_coord) = - self.screen_position_to_board(board, frame_x as f64, frame_y as f64); - - let cell = board.cell_at_position(x_coord as i32, y_coord as i32); - let cell_color: Option<(u8, u8, u8, u8)> = cell.map(|c| { - let m = c.material.def(); - (m.color[0], m.color[1], m.color[2], 0xFF) - }); - let off_grid_color: (u8, u8, u8, u8) = (0x00, 0x00, 0x00, 0xFF); - - let target_color: (u8, u8, u8, u8) = cell_color.unwrap_or(off_grid_color); - let overlay = get_overlay(x_coord as i32, y_coord as i32); - - let frame_idx = ((frame_y * PIXEL_BUFFER_WIDTH + frame_x) * 4) as usize; - frame[frame_idx] = target_color.0.saturating_add(overlay.0); - frame[frame_idx + 1] = target_color.1.saturating_add(overlay.1); - frame[frame_idx + 2] = target_color.2.saturating_add(overlay.2); - frame[frame_idx + 3] = target_color.3.saturating_add(overlay.3); + let c = CHUNK_SIZE as i32; + let w = PIXEL_BUFFER_WIDTH as i32; + let h = PIXEL_BUFFER_HEIGHT 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]; + + 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); + } + } } } } -- cgit v1.3.1