From 3b36990d32d9870ef3e2621c97858006ddf501d5 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sat, 28 Jan 2023 04:20:51 +0100 Subject: [PATCH] raycasts, refactor --- src/input.rs | 9 +++- src/main.rs | 19 ++++++- src/player.rs | 42 +++++----------- src/rendering.rs | 3 ++ src/rendering/selection_box.rs | 18 +++++++ src/{world/render.rs => rendering/world.rs} | 2 +- src/world.rs | 28 ++++++++++- src/world/chunk.rs | 3 +- src/world/loading.rs | 4 +- src/world/mesh.rs | 3 +- src/world/raycast.rs | 55 +++++++++++++++++++++ src/world/tasks.rs | 2 +- 12 files changed, 147 insertions(+), 41 deletions(-) create mode 100644 src/rendering/selection_box.rs rename src/{world/render.rs => rendering/world.rs} (99%) create mode 100644 src/world/raycast.rs diff --git a/src/input.rs b/src/input.rs index cff8084..522b569 100644 --- a/src/input.rs +++ b/src/input.rs @@ -16,6 +16,7 @@ pub struct Inputs { #[derive(Unique, Clone, Default, Debug)] pub struct RawInputState { pub keyboard_state: HashSet>, + pub button_state: [bool; 32], pub mouse_delta: DVec2 } @@ -37,8 +38,10 @@ pub fn process_events( }; } }, - DeviceEvent::Button { button: _, state: _ } => { - //log::debug!("Button {button} {state:?}"); + DeviceEvent::Button { button, state } => { + if button < 32 { + input_state.button_state[button as usize] = matches!(state, ElementState::Pressed); + } }, _ => () } @@ -56,6 +59,8 @@ pub fn update_input_states ( raw_inputs.keyboard_state.contains(&VirtualKeyCode::S) as u32 as f32 ).normalize_or_zero(); inputs.look = raw_inputs.mouse_delta.as_vec2(); + inputs.action_a = raw_inputs.button_state[1]; + inputs.action_b = raw_inputs.button_state[3]; } pub fn init_input ( diff --git a/src/main.rs b/src/main.rs index e4cec44..aa72591 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ use glam::vec3; use std::time::{Instant, Duration}; mod logging; + pub(crate) mod rendering; pub(crate) mod world; pub(crate) mod player; @@ -24,8 +25,17 @@ pub(crate) mod events; pub(crate) mod input; pub(crate) mod fly_controller; -use rendering::{Renderer, RenderTarget, BackgroundColor, clear_background}; -use world::{loading::update_loaded_world_around_player, render::draw_world, init_game_world}; +use rendering::{ + Renderer, + RenderTarget, + BackgroundColor, + clear_background +}; +use world::{ + init_game_world, + loading::update_loaded_world_around_player, + raycast::update_player_raycast +}; use player::spawn_player; use prefabs::load_prefabs; use settings::GameSettings; @@ -33,6 +43,10 @@ use camera::compute_cameras; use events::{clear_events, process_glutin_events}; use input::{init_input, process_inputs}; use fly_controller::update_controllers; +use rendering::{ + selection_box::render_selection_box, + world::draw_world, +}; #[derive(Unique)] pub(crate) struct DeltaTime(Duration); @@ -50,6 +64,7 @@ fn update() -> Workload { process_inputs, update_controllers, update_loaded_world_around_player, + update_player_raycast, compute_cameras ).into_workload() } diff --git a/src/player.rs b/src/player.rs index 88ce652..4a2fbc1 100644 --- a/src/player.rs +++ b/src/player.rs @@ -1,14 +1,12 @@ use glam::Mat4; -use shipyard::{Component, EntitiesViewMut, ViewMut}; +use shipyard::{Component, AllStoragesViewMut}; use crate::{ transform::Transform, camera::Camera, - fly_controller::FlyController, + fly_controller::FlyController, + world::raycast::LookingAtBlock, }; -#[derive(Component)] -pub struct LocalPlayer; - #[derive(Component)] pub struct Player; @@ -16,31 +14,15 @@ pub struct Player; pub struct MainPlayer; pub fn spawn_player ( - mut entities: EntitiesViewMut, - mut vm_player: ViewMut, - mut vm_main_player: ViewMut, - mut vm_local_player: ViewMut, - mut vm_transform: ViewMut, - mut vm_camera: ViewMut, - mut vm_controls: ViewMut, + mut storages: AllStoragesViewMut ) { log::info!("spawning player"); - entities.add_entity( - ( - &mut vm_player, - &mut vm_main_player, - &mut vm_local_player, - &mut vm_transform, - &mut vm_camera, - &mut vm_controls - ), - ( - Player, - MainPlayer, - LocalPlayer, - Transform(Mat4::default()), - Camera::default(), - FlyController - ) - ); + storages.add_entity(( + Player, + MainPlayer, + Transform::default(), + Camera::default(), + FlyController, + LookingAtBlock::default(), + )); } diff --git a/src/rendering.rs b/src/rendering.rs index 2bf0517..7a42932 100644 --- a/src/rendering.rs +++ b/src/rendering.rs @@ -9,6 +9,9 @@ use glium::{ }; use glam::Vec3; +pub mod world; +pub mod selection_box; + #[derive(Unique)] pub struct RenderTarget(pub glium::Frame); diff --git a/src/rendering/selection_box.rs b/src/rendering/selection_box.rs new file mode 100644 index 0000000..4871bf2 --- /dev/null +++ b/src/rendering/selection_box.rs @@ -0,0 +1,18 @@ +use shipyard::{View, IntoIter, NonSendSync, UniqueViewMut}; +use crate::{ + player::MainPlayer, + world::raycast::LookingAtBlock, + camera::Camera +}; +use super::RenderTarget; + +//wip +pub fn render_selection_box( + lookat: View, + camera: View, + mut target: NonSendSync>, +) { + for lookat in lookat.iter() { + + } +} diff --git a/src/world/render.rs b/src/rendering/world.rs similarity index 99% rename from src/world/render.rs rename to src/rendering/world.rs index 3cda8fc..26f8822 100644 --- a/src/world/render.rs +++ b/src/rendering/world.rs @@ -19,7 +19,6 @@ use glium::{ }; use crate::{ camera::Camera, - rendering::RenderTarget, prefabs::{ ChunkShaderPrefab, BlockTexturesPrefab, @@ -30,6 +29,7 @@ use crate::{ chunk::CHUNK_SIZE, }, }; +use super::RenderTarget; #[derive(Clone, Copy)] pub struct ChunkVertex { diff --git a/src/world.rs b/src/world.rs index 2f3ace1..a52c55a 100644 --- a/src/world.rs +++ b/src/world.rs @@ -6,16 +6,18 @@ use anyhow::{Result, Context}; pub mod chunk; pub mod block; -pub mod render; pub mod tasks; pub mod loading; pub mod mesh; pub mod neighbors; pub mod worldgen; +pub mod raycast; use chunk::{Chunk, ChunkMesh}; use tasks::ChunkTaskManager; +use self::{chunk::CHUNK_SIZE, block::Block}; + //TODO separate world struct for render data // because this is not send-sync @@ -25,6 +27,30 @@ pub struct ChunkStorage { pub chunks: HashMap } impl ChunkStorage { + pub const fn to_chunk_coords(position: IVec3) -> (IVec3, IVec3) { + ( + IVec3::new( + position.x.div_euclid(CHUNK_SIZE as i32), + position.y.div_euclid(CHUNK_SIZE as i32), + position.z.div_euclid(CHUNK_SIZE as i32), + ), + IVec3::new( + position.x.rem_euclid(CHUNK_SIZE as i32), + position.y.rem_euclid(CHUNK_SIZE as i32), + position.z.rem_euclid(CHUNK_SIZE as i32), + ) + ) + } + pub fn get_block(&self, position: IVec3) -> Option { + let (chunk, block) = Self::to_chunk_coords(position); + let block = self.chunks + .get(&chunk)? + .block_data.as_ref()? + .blocks.get(block.x as usize)? + .get(block.y as usize)? + .get(block.z as usize)?; + Some(*block) + } pub fn new() -> Self { Self::default() } diff --git a/src/world/chunk.rs b/src/world/chunk.rs index 20e91e5..ba46819 100644 --- a/src/world/chunk.rs +++ b/src/world/chunk.rs @@ -1,6 +1,7 @@ use glam::IVec3; use glium::{VertexBuffer, IndexBuffer}; -use super::{block::Block, render::ChunkVertex}; +use super::block::Block; +use crate::rendering::world::ChunkVertex; pub const CHUNK_SIZE: usize = 32; diff --git a/src/world/loading.rs b/src/world/loading.rs index 226b6e3..498c3af 100644 --- a/src/world/loading.rs +++ b/src/world/loading.rs @@ -2,7 +2,7 @@ use glam::{IVec3, ivec3}; use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType}; use shipyard::{View, UniqueView, UniqueViewMut, IntoIter, Workload, IntoWorkload, NonSendSync}; use crate::{ - player::LocalPlayer, + player::MainPlayer, transform::Transform, settings::GameSettings, rendering::Renderer @@ -27,7 +27,7 @@ pub fn update_loaded_world_around_player() -> Workload { pub fn update_chunks_if_player_moved( v_settings: UniqueView, - v_local_player: View, + v_local_player: View, v_transform: View, mut vm_world: UniqueViewMut, ) { diff --git a/src/world/mesh.rs b/src/world/mesh.rs index 6d6b6f2..69018dc 100644 --- a/src/world/mesh.rs +++ b/src/world/mesh.rs @@ -1,6 +1,7 @@ use strum::{EnumIter, IntoEnumIterator}; use glam::{Vec3A, vec3a, IVec3, ivec3}; -use super::{render::ChunkVertex, chunk::CHUNK_SIZE, block::{Block, RenderType}}; +use super::{chunk::CHUNK_SIZE, block::{Block, RenderType}}; +use crate::rendering::world::ChunkVertex; pub mod data; use data::MeshGenData; diff --git a/src/world/raycast.rs b/src/world/raycast.rs new file mode 100644 index 0000000..303df3e --- /dev/null +++ b/src/world/raycast.rs @@ -0,0 +1,55 @@ +use glam::{Vec3, IVec3}; +use shipyard::{View, Component, ViewMut, IntoIter, UniqueView}; +use crate::{player::MainPlayer, transform::Transform}; + +use super::{ChunkStorage, block::Block}; + +const RAYCAST_STEP: f32 = 0.25; + +#[derive(Clone, Copy, Debug)] +pub struct RaycastReport { + pub length: f32, + pub position: Vec3, + pub block_position: IVec3, + pub block: Block, +} + +impl ChunkStorage { + //this is probably pretty slow... + pub fn raycast(&self, origin: Vec3, direction: Vec3, limit: Option) -> Option { + debug_assert!(direction.is_normalized(), "Ray direction not normalized"); + let mut position = origin; + let mut length = 0.; + loop { + let block_position = position.floor().as_ivec3(); + if let Some(block) = self.get_block(block_position) { + if block.descriptor().raycast_collision { + return Some(RaycastReport { length, position, block_position, block }); + } + } + length += RAYCAST_STEP; + position += direction * RAYCAST_STEP; + if let Some(limit) = limit { + if length > limit { + return None; + } + } + } + } +} + +#[derive(Component, Clone, Copy, Debug, Default)] +pub struct LookingAtBlock(pub Option); + +pub fn update_player_raycast( + main_player: View, + transform: View, + mut raycast: ViewMut, + world: UniqueView, +) { + for (_, transform, report) in (&main_player, transform.inserted_or_modified(), &mut raycast).iter() { + let (_, rotation, position) = transform.0.to_scale_rotation_translation(); + let direction = rotation * Vec3::NEG_Z; + *report = LookingAtBlock(world.raycast(position, direction, Some(10.))); + } +} diff --git a/src/world/tasks.rs b/src/world/tasks.rs index 61a1c8d..2c73c16 100644 --- a/src/world/tasks.rs +++ b/src/world/tasks.rs @@ -4,10 +4,10 @@ use shipyard::Unique; use rayon::{ThreadPool, ThreadPoolBuilder}; use super::{ chunk::BlockData, - render::ChunkVertex, mesh::{generate_mesh, data::MeshGenData}, worldgen::generate_world, }; +use crate::rendering::world::ChunkVertex; pub enum ChunkTask { LoadChunk {