summaryrefslogtreecommitdiff
path: root/src/camera.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/camera.rs')
-rw-r--r--src/camera.rs140
1 files changed, 40 insertions, 100 deletions
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,
}
}
}