summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/camera.rs22
-rw-r--r--src/config.rs2
-rw-r--r--src/main.rs149
-rw-r--r--src/sim/chunk.rs2
-rw-r--r--src/sim/materials/mod.rs2
-rw-r--r--src/sim/sim.rs25
-rw-r--r--src/sim/world.rs10
7 files changed, 142 insertions, 70 deletions
diff --git a/src/camera.rs b/src/camera.rs
index 3713b98..55a698c 100644
--- a/src/camera.rs
+++ b/src/camera.rs
@@ -8,7 +8,7 @@ pub struct Camera {
// centre coords
pub x: f64,
pub y: f64,
- // zoom scale factor, 1.0 = board <-> frame
+ // zoom scale factor, 1.0 = board <-> window
pub zoom: f64,
}
@@ -56,14 +56,14 @@ impl Camera {
pub fn write_frame_view(&self, frame: &mut [u8], world: &World) {
puffin::profile_function!();
- 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;
+ // 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) {
@@ -74,7 +74,7 @@ impl Camera {
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 as i32;
+ 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);
@@ -102,7 +102,7 @@ impl Camera {
yl: f64,
scale: f64,
) {
- let c = CHUNK_SIZE as i32;
+ let c = CHUNK_SIZE;
let w = 1600 as i32;
let h = 1200 as i32;
diff --git a/src/config.rs b/src/config.rs
index 2e656d4..8e8f7a1 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,6 +1,6 @@
pub const WINDOW_TITLE: &str = "pxs";
-pub const CHUNK_SIZE: u32 = 32;
+pub const CHUNK_SIZE: i32 = 32;
pub const CELLS_IN_CHUNK: usize = (CHUNK_SIZE * CHUNK_SIZE) as usize;
pub const CAMERA_MOVEMENT_SPEED: f32 = 10.0;
diff --git a/src/main.rs b/src/main.rs
index 483bfb2..d248a75 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -7,6 +7,7 @@ use egui::Id;
use egui_wgpu::{RendererOptions, ScreenDescriptor};
use egui_winit::egui::{self, Context};
use futures::executor;
+use rand::random_range;
use std::{
sync::Arc,
time::{Duration, Instant},
@@ -26,7 +27,7 @@ use winit::{
use crate::{
camera::Camera,
config::WINDOW_TITLE,
- sim::{materials::MaterialId, sim::sim_tick, world::World},
+ sim::{cell::Cell, materials::MaterialId, sim::sim_tick, world::World},
ui::draw_egui,
};
@@ -56,6 +57,11 @@ struct Diagnostics {
fps: f32,
}
+struct RendererChunk {
+ texture: wgpu::Texture,
+ bind_group: wgpu::BindGroup,
+}
+
struct RendererState {
window: Arc<Window>,
surface: wgpu::Surface<'static>,
@@ -69,6 +75,8 @@ struct RendererState {
egui_state: egui_winit::State,
egui_renderer: egui_wgpu::Renderer,
+ // world pixels
+ renderer_chunks: Vec<RendererChunk>,
pixels_pipeline: wgpu::RenderPipeline,
pixels_bind_group: wgpu::BindGroup,
texture: wgpu::Texture,
@@ -168,13 +176,6 @@ impl RendererState {
}],
});
- let pixels_pipeline_layout =
- device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
- label: None,
- immediate_size: 0,
- bind_group_layouts: &[Some(&pixels_bind_group_layout)],
- });
-
let pixels_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &pixels_bind_group_layout,
@@ -197,6 +198,13 @@ impl RendererState {
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
+ let pixels_pipeline_layout =
+ device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
+ label: None,
+ immediate_size: 0,
+ bind_group_layouts: &[Some(&pixels_bind_group_layout)],
+ });
+
let pixels_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
layout: Some(&pixels_pipeline_layout),
@@ -231,6 +239,67 @@ impl RendererState {
cache: None,
});
+ let mut renderer_chunks: Vec<RendererChunk> = Vec::new();
+
+ // match number of world chunks
+ // TODO refactor so that this implicit
+ for _ in -10..10 {
+ for _ in -10..10 {
+ let texture = device.create_texture(&wgpu::TextureDescriptor {
+ label: None,
+ mip_level_count: 1,
+ sample_count: 1,
+ usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
+ format: wgpu_types::TextureFormat::Rgba8UnormSrgb,
+ size: wgpu::Extent3d {
+ width: size.width,
+ height: size.height,
+ depth_or_array_layers: 1,
+ },
+ dimension: wgpu::TextureDimension::D2,
+ view_formats: &[],
+ });
+
+ let bind_group_layout =
+ device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
+ label: None,
+ entries: &[wgpu::BindGroupLayoutEntry {
+ ty: wgpu::BindingType::Texture {
+ sample_type: wgpu::TextureSampleType::Float { filterable: true },
+ view_dimension: wgpu::TextureViewDimension::D2,
+ multisampled: false,
+ },
+ binding: 0,
+ count: None,
+ visibility: wgpu::ShaderStages::FRAGMENT,
+ }],
+ });
+
+ let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
+ label: None,
+ layout: &bind_group_layout,
+ entries: &[wgpu::BindGroupEntry {
+ binding: 0,
+ resource: wgpu::BindingResource::TextureView(&texture.create_view(
+ &wgpu::TextureViewDescriptor {
+ dimension: Some(wgpu::TextureViewDimension::D2),
+ usage: Some(
+ wgpu::TextureUsages::TEXTURE_BINDING
+ | wgpu::TextureUsages::COPY_DST,
+ ),
+ ..wgpu::TextureViewDescriptor::default()
+ },
+ )),
+ }],
+ });
+
+ renderer_chunks.push(RendererChunk {
+ texture,
+ bind_group,
+ })
+ }
+ }
+
RendererState {
window,
surface,
@@ -243,6 +312,7 @@ impl RendererState {
egui_state,
egui_renderer,
+ renderer_chunks: Vec::new(),
texture,
frame_view: vec![0; size.width as usize * size.height as usize * 4],
pixels_pipeline,
@@ -576,11 +646,9 @@ impl ApplicationHandler for App {
}
WindowEvent::CursorMoved { position, .. } => {
self.input.last_mouse_pos_on_screen = Some((position.x, position.y));
- // self.input.last_mouse_pos_on_board = pixels
- // .window_pos_to_pixel((position.x as f32, position.y as f32))
- // .map(|v| camera.screen_position_to_world(v.0 as f64, v.1 as f64))
- // .map(|v| (v.0 as i32, v.1 as i32))
- // .ok();
+ let world_pos = camera.screen_position_to_world(position.x, position.y);
+ self.input.last_mouse_pos_on_board =
+ Some((world_pos.0 as i32, world_pos.1 as i32))
}
WindowEvent::MouseInput { state, button, .. } => {
if button == MouseButton::Left {
@@ -611,35 +679,34 @@ impl ApplicationHandler for App {
camera.handle_camera_input(&self.input, delta_time);
// // --TEST DRAWING--
- // if self.input.is_lmb_pressed
- // && let Some(lm) = self.input.last_mouse_pos_on_board
- // {
- // // start with the bounding box of the drawing brush circle + some margin
- // // clamp the bounding box to the board sie
- // // TODO better way to do this without unwrap?
- // let bb_xl = lm.0 - self.config.brush_radius as i32;
- // let bb_xu = lm.0 + self.config.brush_radius as i32;
- // let bb_yl = lm.1 - self.config.brush_radius as i32;
- // let bb_yu = lm.1 + self.config.brush_radius as i32;
+ if self.input.is_lmb_pressed
+ && let Some(lm) = self.input.last_mouse_pos_on_board
+ {
+ // start with the bounding box of the drawing brush circle + some margin
+ // clamp the bounding box to the board sie
+ let bb_xl = lm.0 - self.config.brush_radius as i32;
+ let bb_xu = lm.0 + self.config.brush_radius as i32;
+ let bb_yl = lm.1 - self.config.brush_radius as i32;
+ let bb_yu = lm.1 + self.config.brush_radius as i32;
- // // for each point, check if the distance is less than the brush size and write the pixel
- // for x in bb_xl..bb_xu {
- // for y in bb_yl..bb_yu {
- // let r = random_range(0.0..1.0);
- // if ((x - lm.0).pow(2) + (y - lm.1).pow(2))
- // < (self.config.brush_radius as i32).pow(2)
- // && r > 0.9
- // {
- // let mut cell = Cell::from_material(self.config.brush_material);
- // cell.flags = (self.sim_seqno as u8) & 0b1;
- // world.set_cell_from_game_position(
- // x, y, cell, // wake the chunk
- // false,
- // );
- // }
- // }
- // }
- // }
+ // for each point, check if the distance is less than the brush size and write the pixel
+ for x in bb_xl..bb_xu {
+ for y in bb_yl..bb_yu {
+ let r = random_range(0.0..1.0);
+ if ((x - lm.0).pow(2) + (y - lm.1).pow(2))
+ < (self.config.brush_radius as i32).pow(2)
+ && r > 0.9
+ {
+ let mut cell = Cell::from_material(self.config.brush_material);
+ cell.flags = (self.sim_seqno as u8) & 0b1;
+ world.set_cell_from_game_position(
+ x, y, cell, // wake the chunk
+ false,
+ );
+ }
+ }
+ }
+ }
// TODO check if we need to run another sim tick given the sim speed + delta_time
// SIM logic
diff --git a/src/sim/chunk.rs b/src/sim/chunk.rs
index cf4179a..1980932 100644
--- a/src/sim/chunk.rs
+++ b/src/sim/chunk.rs
@@ -6,6 +6,7 @@ use crate::{
pub struct Chunk {
pub cells: Box<[Cell; CELLS_IN_CHUNK as usize]>,
pub sleeping: bool,
+ pub needs_texture_update: bool,
}
impl Chunk {
@@ -22,6 +23,7 @@ impl Chunk {
Chunk {
cells: Box::new([Cell::void(); CELLS_IN_CHUNK]),
sleeping: true,
+ needs_texture_update: true,
}
}
}
diff --git a/src/sim/materials/mod.rs b/src/sim/materials/mod.rs
index 581ce31..d2d0e0e 100644
--- a/src/sim/materials/mod.rs
+++ b/src/sim/materials/mod.rs
@@ -24,7 +24,7 @@ pub struct MaterialDef {
static MATERIALS: [MaterialDef; 5] = [
MaterialDef {
name: "Void",
- color: (0xFF, 0xFF, 0x00, 0xFF),
+ color: (0x00, 0x00, 0x00, 0x00),
density: 0,
sim_update: None,
},
diff --git a/src/sim/sim.rs b/src/sim/sim.rs
index 6e0029e..ef2fc80 100644
--- a/src/sim/sim.rs
+++ b/src/sim/sim.rs
@@ -41,12 +41,12 @@ pub struct UpdateCtx<'a, 'b, 'c> {
}
fn get_cell(chunks: &[Option<&mut Chunk>; 9], x: i32, y: i32) -> Option<Cell> {
- let dcx = x.div_euclid(CHUNK_SIZE as i32);
- let dcy = y.div_euclid(CHUNK_SIZE as i32);
+ let dcx = x.div_euclid(CHUNK_SIZE);
+ let dcy = y.div_euclid(CHUNK_SIZE);
if dcx != 0 || dcy != 0 {
// in a different chunk
- let nc_x = x.rem_euclid(CHUNK_SIZE as i32) as u8;
- let nc_y = y.rem_euclid(CHUNK_SIZE as i32) as u8;
+ let nc_x = x.rem_euclid(CHUNK_SIZE) as u8;
+ let nc_y = y.rem_euclid(CHUNK_SIZE) as u8;
return if let Some(chunk) = &chunks[(dcx + 1 + (dcy + 1) * 3) as usize] {
Some(chunk.get_cell_at_local_position(nc_x, nc_y))
@@ -63,19 +63,21 @@ fn get_cell(chunks: &[Option<&mut Chunk>; 9], x: i32, y: i32) -> Option<Cell> {
}
pub fn set_cell(chunks: &mut [Option<&mut Chunk>; 9], x: i32, y: i32, cell: Cell) {
- let dcx = x.div_euclid(CHUNK_SIZE as i32);
- let dcy = y.div_euclid(CHUNK_SIZE as i32);
+ let dcx = x.div_euclid(CHUNK_SIZE);
+ let dcy = y.div_euclid(CHUNK_SIZE);
if dcx != 0 || dcy != 0 {
// in a different chunk
- let nc_x = x.rem_euclid(CHUNK_SIZE as i32) as u8;
- let nc_y = y.rem_euclid(CHUNK_SIZE as i32) as u8;
+ let nc_x = x.rem_euclid(CHUNK_SIZE) as u8;
+ let nc_y = y.rem_euclid(CHUNK_SIZE) as u8;
if let Some(chunk) = &mut chunks[(dcx + 1 + (dcy + 1) * 3) as usize] {
chunk.set_cell_at_local_position(nc_x, nc_y, cell);
+ chunk.needs_texture_update = true;
}
} else {
if let Some(target) = &mut chunks[4] {
target.set_cell_at_local_position(x as u8, y as u8, cell);
+ target.needs_texture_update = true;
}
}
}
@@ -118,12 +120,12 @@ pub fn sim_tick_chunk(chunks: &mut [Option<&mut Chunk>; 9], seqno: u64) {
let seqno_parity = (seqno as u8) & 0b1;
if chunks[4].is_some() {
- for y in (0..CHUNK_SIZE as i32).rev() {
- for i in 0..CHUNK_SIZE as i32 {
+ for y in (0..CHUNK_SIZE).rev() {
+ for i in 0..CHUNK_SIZE {
let x = if seqno_parity == 0 {
i
} else {
- (CHUNK_SIZE as i32) - i - 1
+ (CHUNK_SIZE) - i - 1
};
let mut cell = get_cell(chunks, x, y).unwrap();
@@ -213,6 +215,7 @@ pub fn sim_tick(world: &mut World, seqno: u64, use_threading: bool) {
};
if use_threading {
+ // TODO use forte
color.par_iter().for_each(chunk_closure);
} else {
color.iter().for_each(chunk_closure);
diff --git a/src/sim/world.rs b/src/sim/world.rs
index 7775744..bdb1286 100644
--- a/src/sim/world.rs
+++ b/src/sim/world.rs
@@ -17,12 +17,12 @@ impl World {
(
(
// TODO is this cast expensive?
- x.div_euclid(CHUNK_SIZE as i32),
- y.div_euclid(CHUNK_SIZE as i32),
+ x.div_euclid(CHUNK_SIZE),
+ y.div_euclid(CHUNK_SIZE),
),
(
- x.rem_euclid(CHUNK_SIZE as i32) as u8,
- y.rem_euclid(CHUNK_SIZE as i32) as u8,
+ x.rem_euclid(CHUNK_SIZE) as u8,
+ y.rem_euclid(CHUNK_SIZE) as u8,
),
)
}
@@ -64,7 +64,7 @@ impl World {
};
for y in -10..10 {
- for x in -50..50 {
+ for x in -10..10 {
world.insert(x, y, Chunk::void());
}
}