more project structure cleanup, removing spaghetti code, using traits

This commit is contained in:
Piotrek
2021-04-26 21:39:20 +02:00
parent 3a444d6e3a
commit ad62a29263
14 changed files with 224 additions and 179 deletions
+23 -22
View File
@@ -1,7 +1,7 @@
use winit::event::Event; use winit::event::Event;
use winit::event::{WindowEvent, DeviceEvent, KeyboardInput, ElementState, VirtualKeyCode}; use winit::event::{WindowEvent, DeviceEvent, KeyboardInput, ElementState, VirtualKeyCode};
use cgmath::{InnerSpace, Matrix4, Rad, Deg, Transform, Vector3}; use cgmath::{InnerSpace, Matrix4, Rad, Deg, Transform, Vector3, Point3};
use crate::renderer::camera::Camera; use crate::renderer::camera::CameraTransform;
#[derive(Default)] #[derive(Default)]
struct CameraMovement { struct CameraMovement {
@@ -33,22 +33,22 @@ pub struct CameraController {
enabled: bool, enabled: bool,
movement: CameraMovement, movement: CameraMovement,
rotation: CameraRotation, rotation: CameraRotation,
cam_position: Point3<f32>,
} }
impl CameraController { impl CameraController {
pub fn new() -> Self { pub fn new() -> Self {
let mut movement = CameraMovement::default(); Self {
movement.speed = 2.0; enabled: false,
let mut rotation = CameraRotation::default(); movement: CameraMovement { speed: 2.0, .. CameraMovement::default()},
rotation.yaw = 45.0; rotation: CameraRotation { yaw: 45.0, sensitivity: 0.2, .. CameraRotation::default() },
rotation.sensitivity = 0.2; cam_position: (0.0, 0.0, 0.0).into(),
Self { enabled: false, movement, rotation } }
} }
pub fn set_enabled(&mut self, enabled: bool) { pub fn set_enabled(&mut self, enabled: bool) { self.enabled = enabled; }
self.enabled = enabled;
}
pub fn handle_input(&mut self, event: &Event<()>) -> bool { pub fn handle_input(&mut self, event: &Event<()>) -> bool {
// Abort if not enabled // Abort if not enabled
@@ -93,33 +93,34 @@ impl CameraController {
} }
} }
pub fn update_camera(&mut self, camera: &mut Camera, delta_time: f32) { pub fn update(&mut self, delta_time: f32, camera: &mut dyn CameraTransform) {
// Abort if not enabled // Abort if not enabled
if !self.enabled { return; } if !self.enabled { return; }
// Rotation // Rotation
let yaw_rot = self.rotation.yaw_rot(); let yaw_rot = self.rotation.yaw_rot();
let pitch_rot = self.rotation.pitch_rot(); let pitch_rot = self.rotation.pitch_rot();
camera.forward = yaw_rot.transform_vector(pitch_rot.transform_vector(Vector3::unit_z())); let cam_forward = yaw_rot.transform_vector(pitch_rot.transform_vector(Vector3::unit_z()));
camera.up = yaw_rot.transform_vector(pitch_rot.transform_vector(Vector3::unit_y())); let cam_up = yaw_rot.transform_vector(pitch_rot.transform_vector(Vector3::unit_y()));
// Movement amount // Movement amount
let mut amount = delta_time * self.movement.speed; let mut amount = delta_time * self.movement.speed;
if self.movement.shift { amount *= 2.0; } if self.movement.shift { amount *= 2.0; }
// Forward and backwards // Forward and backwards
if self.movement.fwd && camera.forward.magnitude() > amount { camera.position += camera.forward.normalize() * amount; } if self.movement.fwd && cam_forward.magnitude() > amount { self.cam_position += cam_forward.normalize() * amount; }
if self.movement.back { camera.position -= camera.forward.normalize() * amount; } if self.movement.back { self.cam_position -= cam_forward.normalize() * amount; }
// Up and down // Up and down
if self.movement.up { camera.position += camera.up.normalize() * amount; } if self.movement.up { self.cam_position += cam_up.normalize() * amount; }
if self.movement.down { camera.position -= camera.up.normalize() * amount; } if self.movement.down { self.cam_position -= cam_up.normalize() * amount; }
// Left and right // Left and right
let right = camera.forward.cross(camera.up); let right = cam_forward.cross(cam_up);
if self.movement.right { camera.position += right * amount; } if self.movement.right { self.cam_position += right * amount; }
if self.movement.left { camera.position -= right * amount; } if self.movement.left { self.cam_position -= right * amount; }
// Update camerea
camera.update(self.cam_position, cam_forward, cam_up);
} }
} }
+36 -53
View File
@@ -1,74 +1,57 @@
use winit::{ use winit::event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, MouseButton};
event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, MouseButton},
window::Window
};
use cgmath::Point3;
use noise::Perlin; use noise::Perlin;
use std::sync::Arc; use std::sync::Arc;
use noise::NoiseFn;
mod camera_controller; use camera_controller::CameraController; use crate::renderer::{camera::CameraTransform, Level};
mod world_gen; use world_gen::WorldGen;
use crate::renderer::Renderer;
//use crate::renderer::BrickData;
mod camera_controller;
use camera_controller::CameraController;
mod world_gen;
use world_gen::WorldGen;
pub enum GameState {
Paused,
Running
}
pub struct App { pub struct App {
pub window: Window,
pub renderer: Renderer,
world_gen: WorldGen, world_gen: WorldGen,
camera_controller: CameraController, camera_controller: CameraController
} }
impl App { impl App {
pub fn new(window: Window) -> Self { pub fn new(level: &mut dyn Level) -> Self {
let mut renderer = futures::executor::block_on(Renderer::new(&window)); let mut instance = Self {
let camera_controller = CameraController::new(); camera_controller: CameraController::new(),
let mut world_gen = WorldGen::new(); world_gen: WorldGen::new()
};
let start = std::time::Instant::now(); instance.world_gen.generate(level, &Perlin::new());
let noise = Perlin::new(); instance
world_gen.generate(&mut renderer, &noise);
println!("Generated in {}ms", start.elapsed().as_millis());
Self { window, renderer, camera_controller, world_gen }
} }
pub fn input(&mut self, event: Arc<Event<()>>) { pub fn input(&mut self, event: &Event<()>) {
// Update camera controller
self.camera_controller.handle_input(event);
}
match event.as_ref() { pub fn update_state(&mut self, requested_state: GameState) -> GameState {
Event::WindowEvent { ref event, .. } => { match requested_state {
match event { GameState::Paused => {
// Escape key self.camera_controller.set_enabled(false);
WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, virtual_keycode: Some(VirtualKeyCode::Escape), .. }, .. } => { }
self.window.set_cursor_grab(false).unwrap(); GameState::Running => {
self.window.set_cursor_visible(true); self.camera_controller.set_enabled(true);
self.camera_controller.set_enabled(false);
}
// Window clicked
WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Left, .. } => {
self.window.set_cursor_grab(true).unwrap();
self.window.set_cursor_visible(false);
self.camera_controller.set_enabled(true);
}
// Window resized
WindowEvent::Resized(physical_size) => {
self.renderer.resize(Some(*physical_size));
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
self.renderer.resize(Some(**new_inner_size));
}
_ => ()
}
} }
_ => () _ => ()
} };
// Update camera controller // Currently we are not preventing any state changes, just return requested state
self.camera_controller.handle_input(event.as_ref()); requested_state
} }
pub fn update(&mut self, delta: f32) { pub fn update_camera(&mut self, delta: f32, camera_transform: &mut dyn CameraTransform) {
self.camera_controller.update_camera(&mut self.renderer.camera, delta); self.camera_controller.update(delta, camera_transform);
} }
} }
+8
View File
@@ -0,0 +1,8 @@
struct Player {
camera_controller: CameraController
}
impl Player {
}
+12
View File
@@ -0,0 +1,12 @@
struct World {
}
impl World {
pub fn new() -> Self {
Self {}
}
}
+4 -4
View File
@@ -2,7 +2,7 @@ use cgmath::{Point3, InnerSpace};
use noise::{Perlin, NoiseFn}; use noise::{Perlin, NoiseFn};
use rand::Rng; use rand::Rng;
use crate::renderer::Renderer; use crate::renderer::Level;
use crate::renderer::buffers::{BLOCK_SIZE, NODE_TEX_SIZE}; use crate::renderer::buffers::{BLOCK_SIZE, NODE_TEX_SIZE};
@@ -20,7 +20,7 @@ impl WorldGen {
/* /*
* Generate world * Generate world
*/ */
pub fn generate(&mut self, renderer: &mut Renderer, noise: &Perlin) { pub fn generate(&mut self, level: &mut dyn Level, noise: &Perlin) {
const SCALE: f64 = 150.0; const SCALE: f64 = 150.0;
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
@@ -31,7 +31,7 @@ impl WorldGen {
let mut block_ids = [0_usize; 16]; let mut block_ids = [0_usize; 16];
for by in 0..2 { for by in 0..2 {
//TODO consume only nonempty blocks //TODO consume only nonempty blocks
block_ids[by] = renderer.block_get_id(Point3{x:bx, y:by, z:bz}, true); block_ids[by] = level.block_get_id(Point3{x:bx, y:by, z:bz}, true);
} }
for x in 0..BLOCK_SIZE { for x in 0..BLOCK_SIZE {
@@ -53,7 +53,7 @@ impl WorldGen {
let by = wy / BLOCK_SIZE; let by = wy / BLOCK_SIZE;
let val = if wy == wh-1 { 2 } else { 1 }; let val = if wy == wh-1 { 2 } else { 1 };
renderer.block_set_voxel(block_ids[by], x, y, z, val); level.block_set_voxel(block_ids[by], x, y, z, val);
} }
} }
} }
+40 -12
View File
@@ -1,26 +1,31 @@
use std::sync::Arc; use std::sync::Arc;
use winit::{ use winit::{
event::{Event, WindowEvent}, event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, MouseButton},
event_loop::{ControlFlow, EventLoop}, event_loop::{ControlFlow, EventLoop},
window::WindowBuilder, window::WindowBuilder,
dpi::LogicalSize dpi::LogicalSize
}; };
mod renderer;
use renderer::Renderer;
mod app;
use app::{App, GameState};
mod renderer; use renderer::Renderer;
mod app; use app::App;
fn main() { fn main() {
// Create event loop // Create event loop
let events = EventLoop::new(); let events = EventLoop::new();
// Create app // Create app
let _window = WindowBuilder::new() let window = WindowBuilder::new()
.with_title("Test") .with_title("Test")
.with_inner_size(LogicalSize::new(1280.0, 720.0)) .with_inner_size(LogicalSize::new(1280.0, 720.0))
.build(&events) .build(&events)
.expect("Failed to create window"); .expect("Failed to create window");
let mut app = App::new(_window);
let mut renderer = futures::executor::block_on(Renderer::new(&window));
let mut app = App::new(&mut renderer);
// Stats // Stats
let mut fps_timer = std::time::Instant::now(); let mut fps_timer = std::time::Instant::now();
@@ -30,27 +35,50 @@ fn main() {
// Run event loop // Run event loop
events.run(move |ev, _, c| { events.run(move |ev, _, c| {
// App input // App input
let event = Arc::new(ev); app.input(&ev);
app.input(event.clone());
// Other // Other
match event.as_ref() { match ev {
// Window event // Window event
Event::WindowEvent { ref event, .. } => { Event::WindowEvent { ref event, .. } => {
match event { match event {
// Window closed (ALT+F4,) // Window closed (ALT+F4,)
WindowEvent::CloseRequested => { *c = ControlFlow::Exit; } WindowEvent::CloseRequested => { *c = ControlFlow::Exit; }
// Escape key
WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, virtual_keycode: Some(VirtualKeyCode::Escape), .. }, .. } => {
// Request pause
if let GameState::Paused = app.update_state(GameState::Paused) {
window.set_cursor_grab(false).unwrap();
window.set_cursor_visible(true);
}
}
// Window clicked
WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Left, .. } => {
// Request unpause
if let GameState::Running = app.update_state(GameState::Running) {
window.set_cursor_grab(true).unwrap();
window.set_cursor_visible(false);
}
}
// Window resized
WindowEvent::Resized(physical_size) => {
renderer.resize(Some(*physical_size));
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
renderer.resize(Some(**new_inner_size));
}
_ => () _ => ()
} }
} }
// Loop // Loop
Event::MainEventsCleared => { Event::MainEventsCleared => {
// Update // Update
app.update(delta_timer.elapsed().as_secs_f32()); let delta = delta_timer.elapsed().as_secs_f32();
app.update_camera(delta, &mut renderer.camera);
delta_timer = std::time::Instant::now(); delta_timer = std::time::Instant::now();
// Redraw // Redraw
app.window.request_redraw(); window.request_redraw();
} }
// Draw // Draw
Event::RedrawRequested(_) => { Event::RedrawRequested(_) => {
@@ -66,10 +94,10 @@ fn main() {
fps_counter += 1; fps_counter += 1;
// Render // Render
match app.renderer.render() { match renderer.render() {
Ok(_) => { } Ok(_) => { }
// Recreate the swap_chain if lost // Recreate the swap_chain if lost
Err(wgpu::SwapChainError::Lost) => app.renderer.resize(None), Err(wgpu::SwapChainError::Lost) => renderer.resize(None),
// The system is out of memory, we should probably quit // The system is out of memory, we should probably quit
Err(wgpu::SwapChainError::OutOfMemory) => *c = ControlFlow::Exit, Err(wgpu::SwapChainError::OutOfMemory) => *c = ControlFlow::Exit,
// All other errors (Outdated, Timeout) should be resolved by the next frame // All other errors (Outdated, Timeout) should be resolved by the next frame
+3 -3
View File
@@ -24,9 +24,9 @@ impl UniformValues {
} }
pub fn update(&mut self, camera: &Camera, time: f32) { pub fn update(&mut self, camera: &Camera, time: f32) {
self.view_inv = camera.view_matrix().invert().unwrap().into(); self.view_inv = camera.get_view().invert().unwrap().into();
self.proj_inv = camera.proj_matrix().invert().unwrap().into(); self.proj_inv = camera.get_projection().invert().unwrap().into();
self.cam_pos = camera.position.into(); self.cam_pos = camera.get_position().into();
self.time = time; self.time = time;
} }
} }
+29 -26
View File
@@ -1,38 +1,41 @@
use cgmath::{Point3, Vector3, Matrix4, Deg, InnerSpace}; use cgmath::{Point3, Vector3, Matrix4, Deg, InnerSpace, Zero};
pub struct Camera { pub struct Camera {
pub position: Point3<f32>, position: Point3<f32>,
pub forward: Vector3<f32>, proj_matrix: Matrix4<f32>,
pub up: Vector3<f32>, view_matrix: Matrix4<f32>
aspect: f32,
fovy: f32,
znear: f32,
zfar: f32,
} }
impl Camera { impl Camera {
pub fn new(aspect: f32, fov: f32) -> Self { pub fn new(aspect: f32) -> Self {
Self { let mut instance = Self {
position: (1.0, 2.0, 1.0).into(), position: (2.0,1.0,2.0).into(),
forward: (0.66, -0.25, 0.66).into(), view_matrix: Matrix4::look_to_rh(
up: Vector3::unit_y(), (0.0,0.0,0.0).into(),
aspect, Vector3{ x:0.66, y:0.0, z:0.66}.normalize(),
fovy: fov, Vector3::unit_y()
znear: 0.1, ),
zfar: 100.0 proj_matrix: Matrix4::zero()
} };
instance.set_aspect(aspect);
instance
} }
pub fn set_aspect(&mut self, aspect: f32) { pub fn set_aspect(&mut self, aspect: f32) { self.proj_matrix = cgmath::perspective(Deg(60.0), aspect, 0.1, 100.0); }
self.aspect = aspect; pub fn get_projection(&self) -> Matrix4<f32> { return self.proj_matrix; }
} pub fn get_view(&self) -> Matrix4<f32> { return self.view_matrix; }
pub fn get_position(&self) -> Point3<f32> { return self.position; }
}
pub fn proj_matrix(&self) -> Matrix4<f32> { pub trait CameraTransform {
return cgmath::perspective(Deg(self.fovy), self.aspect, self.znear, self.zfar); fn update(&mut self, position: Point3<f32>, forward: Vector3<f32>, up: Vector3<f32>);
} }
pub fn view_matrix(&self) -> Matrix4<f32> { impl CameraTransform for Camera {
return Matrix4::look_to_rh((0.0,0.0,0.0).into(), self.forward.normalize(), self.up); fn update(&mut self, position: Point3<f32>, forward: Vector3<f32>, up: Vector3<f32>) {
self.position = position;
self.view_matrix = Matrix4::look_to_rh((0.0,0.0,0.0).into(), forward, up);
} }
} }
+59
View File
@@ -0,0 +1,59 @@
use cgmath::Point3;
use crate::renderer::{Renderer, buffers};
pub trait Level {
fn set_voxel(&mut self, x: usize, y: usize, z:usize, value: u8);
fn block_set_voxel(&mut self, brick_id:usize, x: usize, y: usize, z:usize, value: u8);
fn block_get_id(&mut self, pos: Point3<usize>, apply: bool) -> usize;
fn block_mark_changed(&mut self, brick_id:usize);
}
impl Level for Renderer {
/*
* Create or update brick at given location
*/
#[allow(dead_code)]
fn set_voxel(&mut self, x: usize, y: usize, z:usize, value: u8) {
let brick_id = self.block_get_id(Point3{x:x/32, y:y/32, z:z/32}, true);
self.block_set_voxel(brick_id, x%32, y%32, z%32, value);
}
/*
* Create or update brick at given location
*/
fn block_set_voxel(&mut self, brick_id:usize, x: usize, y: usize, z:usize, value: u8) {
let voxel_id = x + buffers::BLOCK_SIZE * (y + buffers::BLOCK_SIZE * z);
let brick_offset = brick_id * buffers::BLOCK_LEN;
self.buffers.brick_buffer.blocks[brick_offset + voxel_id] = value;
}
/*
* Gets brick id
*/
fn block_get_id(&mut self, pos: Point3<usize>, apply: bool) -> usize {
// Get node
let node_idx = pos.x + buffers::NODE_TEX_SIZE * (pos.y + buffers::NODE_TEX_SIZE * pos.z);
let mut node_value = self.buffers.node_buffer.nodes[node_idx];
// Use new brick if neccesary
if node_value == 0 {
node_value = self.buffers.brick_buffer.next_block(apply) as u32;
if apply { self.buffers.node_buffer.nodes[node_idx] = node_value; }
}
// Get brick id from node value
let brick_id = (node_value - 1) as usize;
if apply { self.block_mark_changed(brick_id); }
brick_id
}
/*
* Marks brick as changed
*/
fn block_mark_changed(&mut self, brick_id:usize) {
if !self.changed_bricks.contains(&brick_id) {
self.changed_bricks.push(brick_id);
}
}
}
+4 -51
View File
@@ -10,6 +10,8 @@ use passes::{RaytracePass, PostprocessPass};
pub mod camera; pub mod camera;
use camera::Camera; use camera::Camera;
pub mod level;
pub use level::Level;
pub struct Renderer { pub struct Renderer {
surface: wgpu::Surface, surface: wgpu::Surface,
@@ -59,10 +61,10 @@ impl Renderer {
// Camera // Camera
let aspect = swapchain_desc.width as f32 / swapchain_desc.height as f32; let aspect = swapchain_desc.width as f32 / swapchain_desc.height as f32;
let camera = Camera::new(aspect, 60.0); let camera = Camera::new(aspect);
// Middleman texture // Middleman texture
let mut texture_descriptor = wgpu::TextureDescriptor { let texture_descriptor = wgpu::TextureDescriptor {
label: Some("glow_post_process_texture1"), label: Some("glow_post_process_texture1"),
size: wgpu::Extent3d { width: swapchain_desc.width, size: wgpu::Extent3d { width: swapchain_desc.width,
height: swapchain_desc.height, height: swapchain_desc.height,
@@ -145,53 +147,4 @@ impl Renderer {
// Return ok // Return ok
Ok(()) Ok(())
} }
//TODO: Move things below to a separate struct, maybe trait?
/*
* Create or update brick at given location
*/
#[allow(dead_code)]
pub fn set_voxel(&mut self, x: usize, y: usize, z:usize, value: u8) {
let brick_id = self.block_get_id(Point3{x:x/32, y:y/32, z:z/32}, true);
self.block_set_voxel(brick_id, x%32, y%32, z%32, value);
}
/*
* Create or update brick at given location
*/
pub fn block_set_voxel(&mut self, brick_id:usize, x: usize, y: usize, z:usize, value: u8) {
let voxel_id = x + buffers::BLOCK_SIZE * (y + buffers::BLOCK_SIZE * z);
let brick_offset = brick_id * buffers::BLOCK_LEN;
self.buffers.brick_buffer.blocks[brick_offset + voxel_id] = value;
}
/*
* Gets brick id
*/
pub fn block_get_id(&mut self, pos: Point3<usize>, apply: bool) -> usize {
// Get node
let node_idx = pos.x + buffers::NODE_TEX_SIZE * (pos.y + buffers::NODE_TEX_SIZE * pos.z);
let mut node_value = self.buffers.node_buffer.nodes[node_idx];
// Use new brick if neccesary
if node_value == 0 {
node_value = self.buffers.brick_buffer.next_block(apply) as u32;
if apply { self.buffers.node_buffer.nodes[node_idx] = node_value; }
}
// Get brick id from node value
let brick_id = (node_value - 1) as usize;
if apply { self.block_mark_changed(brick_id); }
brick_id
}
/*
* Marks brick as changed
*/
pub fn block_mark_changed(&mut self, brick_id:usize) {
if !self.changed_bricks.contains(&brick_id) {
self.changed_bricks.push(brick_id);
}
}
} }
Binary file not shown.
+1 -3
View File
@@ -13,9 +13,7 @@ void main()
vec3 color = texture(sampler2D(_InTexture, _InTextureSampler), uv).rgb; vec3 color = texture(sampler2D(_InTexture, _InTextureSampler), uv).rgb;
// Viniette // Viniette
color = vec3(1,1,1); //color = vec3(1,1,1);
color *= smoothstep(0.0, 0.2, pow(1.0-length(_InUV), 1.5)) + 0.5;
// Return // Return
_OutColor = vec4(color, 1.0); _OutColor = vec4(color, 1.0);
Binary file not shown.
+2 -2
View File
@@ -96,8 +96,8 @@ HitResult castNodes(Ray ray, uint maxSteps)
pos += incAxis * raySign; pos += incAxis * raySign;
// Outside bounds // Outside bounds
if(pos.x < 0 || pos.y < 0 || pos.z < 0) { break; } // if(pos.x < 0 || pos.y < 0 || pos.z < 0) { break; }
if(pos.x >= BLOCK_TEX_SIZE || pos.y > BLOCK_TEX_SIZE || pos.z >= NODE_TEX_SIZE) { break; } // if(pos.x >= BLOCK_TEX_SIZE || pos.y > BLOCK_TEX_SIZE || pos.z >= NODE_TEX_SIZE) { break; }
} }
// Not found // Not found