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::{WindowEvent, DeviceEvent, KeyboardInput, ElementState, VirtualKeyCode};
use cgmath::{InnerSpace, Matrix4, Rad, Deg, Transform, Vector3};
use crate::renderer::camera::Camera;
use cgmath::{InnerSpace, Matrix4, Rad, Deg, Transform, Vector3, Point3};
use crate::renderer::camera::CameraTransform;
#[derive(Default)]
struct CameraMovement {
@@ -33,22 +33,22 @@ pub struct CameraController {
enabled: bool,
movement: CameraMovement,
rotation: CameraRotation,
cam_position: Point3<f32>,
}
impl CameraController {
pub fn new() -> Self {
let mut movement = CameraMovement::default();
movement.speed = 2.0;
let mut rotation = CameraRotation::default();
rotation.yaw = 45.0;
rotation.sensitivity = 0.2;
Self { enabled: false, movement, rotation }
Self {
enabled: false,
movement: CameraMovement { speed: 2.0, .. CameraMovement::default()},
rotation: CameraRotation { yaw: 45.0, sensitivity: 0.2, .. CameraRotation::default() },
cam_position: (0.0, 0.0, 0.0).into(),
}
}
pub fn set_enabled(&mut self, enabled: bool) {
self.enabled = enabled;
}
pub fn set_enabled(&mut self, enabled: bool) { self.enabled = enabled; }
pub fn handle_input(&mut self, event: &Event<()>) -> bool {
// 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
if !self.enabled { return; }
// Rotation
let yaw_rot = self.rotation.yaw_rot();
let pitch_rot = self.rotation.pitch_rot();
camera.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_forward = yaw_rot.transform_vector(pitch_rot.transform_vector(Vector3::unit_z()));
let cam_up = yaw_rot.transform_vector(pitch_rot.transform_vector(Vector3::unit_y()));
// Movement amount
let mut amount = delta_time * self.movement.speed;
if self.movement.shift { amount *= 2.0; }
// Forward and backwards
if self.movement.fwd && camera.forward.magnitude() > amount { camera.position += camera.forward.normalize() * amount; }
if self.movement.back { 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 { self.cam_position -= cam_forward.normalize() * amount; }
// Up and down
if self.movement.up { camera.position += camera.up.normalize() * amount; }
if self.movement.down { camera.position -= camera.up.normalize() * amount; }
if self.movement.up { self.cam_position += cam_up.normalize() * amount; }
if self.movement.down { self.cam_position -= cam_up.normalize() * amount; }
// Left and right
let right = camera.forward.cross(camera.up);
if self.movement.right { camera.position += right * amount; }
if self.movement.left { camera.position -= right * amount; }
let right = cam_forward.cross(cam_up);
if self.movement.right { self.cam_position += right * amount; }
if self.movement.left { self.cam_position -= right * amount; }
// Update camerea
camera.update(self.cam_position, cam_forward, cam_up);
}
}
+34 -51
View File
@@ -1,74 +1,57 @@
use winit::{
event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, MouseButton},
window::Window
};
use cgmath::Point3;
use winit::event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, MouseButton};
use noise::Perlin;
use std::sync::Arc;
use noise::NoiseFn;
mod camera_controller; use camera_controller::CameraController;
mod world_gen; use world_gen::WorldGen;
use crate::renderer::Renderer;
//use crate::renderer::BrickData;
use crate::renderer::{camera::CameraTransform, Level};
mod camera_controller;
use camera_controller::CameraController;
mod world_gen;
use world_gen::WorldGen;
pub enum GameState {
Paused,
Running
}
pub struct App {
pub window: Window,
pub renderer: Renderer,
world_gen: WorldGen,
camera_controller: CameraController,
camera_controller: CameraController
}
impl App {
pub fn new(window: Window) -> Self {
let mut renderer = futures::executor::block_on(Renderer::new(&window));
let camera_controller = CameraController::new();
let mut world_gen = WorldGen::new();
pub fn new(level: &mut dyn Level) -> Self {
let mut instance = Self {
camera_controller: CameraController::new(),
world_gen: WorldGen::new()
};
let start = std::time::Instant::now();
let noise = Perlin::new();
world_gen.generate(&mut renderer, &noise);
println!("Generated in {}ms", start.elapsed().as_millis());
Self { window, renderer, camera_controller, world_gen }
instance.world_gen.generate(level, &Perlin::new());
instance
}
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() {
Event::WindowEvent { ref event, .. } => {
match event {
// Escape key
WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, virtual_keycode: Some(VirtualKeyCode::Escape), .. }, .. } => {
self.window.set_cursor_grab(false).unwrap();
self.window.set_cursor_visible(true);
pub fn update_state(&mut self, requested_state: GameState) -> GameState {
match requested_state {
GameState::Paused => {
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);
GameState::Running => {
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));
}
_ => ()
}
}
_ => ()
};
// Currently we are not preventing any state changes, just return requested state
requested_state
}
// Update camera controller
self.camera_controller.handle_input(event.as_ref());
}
pub fn update(&mut self, delta: f32) {
self.camera_controller.update_camera(&mut self.renderer.camera, delta);
pub fn update_camera(&mut self, delta: f32, camera_transform: &mut dyn CameraTransform) {
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 rand::Rng;
use crate::renderer::Renderer;
use crate::renderer::Level;
use crate::renderer::buffers::{BLOCK_SIZE, NODE_TEX_SIZE};
@@ -20,7 +20,7 @@ impl WorldGen {
/*
* 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;
let mut rng = rand::thread_rng();
@@ -31,7 +31,7 @@ impl WorldGen {
let mut block_ids = [0_usize; 16];
for by in 0..2 {
//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 {
@@ -53,7 +53,7 @@ impl WorldGen {
let by = wy / BLOCK_SIZE;
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 winit::{
event::{Event, WindowEvent},
event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, MouseButton},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
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() {
// Create event loop
let events = EventLoop::new();
// Create app
let _window = WindowBuilder::new()
let window = WindowBuilder::new()
.with_title("Test")
.with_inner_size(LogicalSize::new(1280.0, 720.0))
.build(&events)
.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
let mut fps_timer = std::time::Instant::now();
@@ -30,27 +35,50 @@ fn main() {
// Run event loop
events.run(move |ev, _, c| {
// App input
let event = Arc::new(ev);
app.input(event.clone());
app.input(&ev);
// Other
match event.as_ref() {
match ev {
// Window event
Event::WindowEvent { ref event, .. } => {
match event {
// Window closed (ALT+F4,)
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
Event::MainEventsCleared => {
// 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();
// Redraw
app.window.request_redraw();
window.request_redraw();
}
// Draw
Event::RedrawRequested(_) => {
@@ -66,10 +94,10 @@ fn main() {
fps_counter += 1;
// Render
match app.renderer.render() {
match renderer.render() {
Ok(_) => { }
// 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
Err(wgpu::SwapChainError::OutOfMemory) => *c = ControlFlow::Exit,
// 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) {
self.view_inv = camera.view_matrix().invert().unwrap().into();
self.proj_inv = camera.proj_matrix().invert().unwrap().into();
self.cam_pos = camera.position.into();
self.view_inv = camera.get_view().invert().unwrap().into();
self.proj_inv = camera.get_projection().invert().unwrap().into();
self.cam_pos = camera.get_position().into();
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 position: Point3<f32>,
pub forward: Vector3<f32>,
pub up: Vector3<f32>,
aspect: f32,
fovy: f32,
znear: f32,
zfar: f32,
position: Point3<f32>,
proj_matrix: Matrix4<f32>,
view_matrix: Matrix4<f32>
}
impl Camera {
pub fn new(aspect: f32, fov: f32) -> Self {
Self {
position: (1.0, 2.0, 1.0).into(),
forward: (0.66, -0.25, 0.66).into(),
up: Vector3::unit_y(),
aspect,
fovy: fov,
znear: 0.1,
zfar: 100.0
}
pub fn new(aspect: f32) -> Self {
let mut instance = Self {
position: (2.0,1.0,2.0).into(),
view_matrix: Matrix4::look_to_rh(
(0.0,0.0,0.0).into(),
Vector3{ x:0.66, y:0.0, z:0.66}.normalize(),
Vector3::unit_y()
),
proj_matrix: Matrix4::zero()
};
instance.set_aspect(aspect);
instance
}
pub fn set_aspect(&mut self, aspect: f32) {
self.aspect = aspect;
}
pub fn set_aspect(&mut self, aspect: f32) { self.proj_matrix = cgmath::perspective(Deg(60.0), aspect, 0.1, 100.0); }
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> {
return cgmath::perspective(Deg(self.fovy), self.aspect, self.znear, self.zfar);
}
pub trait CameraTransform {
fn update(&mut self, position: Point3<f32>, forward: Vector3<f32>, up: Vector3<f32>);
}
pub fn view_matrix(&self) -> Matrix4<f32> {
return Matrix4::look_to_rh((0.0,0.0,0.0).into(), self.forward.normalize(), self.up);
impl CameraTransform for Camera {
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;
use camera::Camera;
pub mod level;
pub use level::Level;
pub struct Renderer {
surface: wgpu::Surface,
@@ -59,10 +61,10 @@ impl Renderer {
// Camera
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
let mut texture_descriptor = wgpu::TextureDescriptor {
let texture_descriptor = wgpu::TextureDescriptor {
label: Some("glow_post_process_texture1"),
size: wgpu::Extent3d { width: swapchain_desc.width,
height: swapchain_desc.height,
@@ -145,53 +147,4 @@ impl Renderer {
// Return 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;
// Viniette
color = vec3(1,1,1);
color *= smoothstep(0.0, 0.2, pow(1.0-length(_InUV), 1.5)) + 0.5;
//color = vec3(1,1,1);
// Return
_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;
// Outside bounds
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 < 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; }
}
// Not found