summaryrefslogtreecommitdiff
path: root/src/camera.rs
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2026-08-13 01:56:09 -0700
committerKai Stevenson <kai@kaistevenson.com>2026-08-13 01:56:09 -0700
commitfeefeecec6c6050635b2c016452dfa1529575987 (patch)
tree024cc36c2c75e10b6bfd68f29c1494830bec37df /src/camera.rs
parent7ce9781f86c56f932dabc3bc84b8d21d7be8fecc (diff)
big refactor for board
Diffstat (limited to 'src/camera.rs')
-rw-r--r--src/camera.rs104
1 files changed, 74 insertions, 30 deletions
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 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;
+ }
- 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);
+ 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 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 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];
- 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);
+ 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);
+ }
+ }
}
}
}