raycasts, refactor

This commit is contained in:
griffi-gh 2023-01-28 04:20:51 +01:00
parent a9666062ec
commit 3b36990d32
12 changed files with 147 additions and 41 deletions

View file

@ -16,6 +16,7 @@ pub struct Inputs {
#[derive(Unique, Clone, Default, Debug)] #[derive(Unique, Clone, Default, Debug)]
pub struct RawInputState { pub struct RawInputState {
pub keyboard_state: HashSet<VirtualKeyCode, BuildNoHashHasher<u32>>, pub keyboard_state: HashSet<VirtualKeyCode, BuildNoHashHasher<u32>>,
pub button_state: [bool; 32],
pub mouse_delta: DVec2 pub mouse_delta: DVec2
} }
@ -37,8 +38,10 @@ pub fn process_events(
}; };
} }
}, },
DeviceEvent::Button { button: _, state: _ } => { DeviceEvent::Button { button, state } => {
//log::debug!("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 raw_inputs.keyboard_state.contains(&VirtualKeyCode::S) as u32 as f32
).normalize_or_zero(); ).normalize_or_zero();
inputs.look = raw_inputs.mouse_delta.as_vec2(); 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 ( pub fn init_input (

View file

@ -13,6 +13,7 @@ use glam::vec3;
use std::time::{Instant, Duration}; use std::time::{Instant, Duration};
mod logging; mod logging;
pub(crate) mod rendering; pub(crate) mod rendering;
pub(crate) mod world; pub(crate) mod world;
pub(crate) mod player; pub(crate) mod player;
@ -24,8 +25,17 @@ pub(crate) mod events;
pub(crate) mod input; pub(crate) mod input;
pub(crate) mod fly_controller; pub(crate) mod fly_controller;
use rendering::{Renderer, RenderTarget, BackgroundColor, clear_background}; use rendering::{
use world::{loading::update_loaded_world_around_player, render::draw_world, init_game_world}; 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 player::spawn_player;
use prefabs::load_prefabs; use prefabs::load_prefabs;
use settings::GameSettings; use settings::GameSettings;
@ -33,6 +43,10 @@ use camera::compute_cameras;
use events::{clear_events, process_glutin_events}; use events::{clear_events, process_glutin_events};
use input::{init_input, process_inputs}; use input::{init_input, process_inputs};
use fly_controller::update_controllers; use fly_controller::update_controllers;
use rendering::{
selection_box::render_selection_box,
world::draw_world,
};
#[derive(Unique)] #[derive(Unique)]
pub(crate) struct DeltaTime(Duration); pub(crate) struct DeltaTime(Duration);
@ -50,6 +64,7 @@ fn update() -> Workload {
process_inputs, process_inputs,
update_controllers, update_controllers,
update_loaded_world_around_player, update_loaded_world_around_player,
update_player_raycast,
compute_cameras compute_cameras
).into_workload() ).into_workload()
} }

View file

@ -1,14 +1,12 @@
use glam::Mat4; use glam::Mat4;
use shipyard::{Component, EntitiesViewMut, ViewMut}; use shipyard::{Component, AllStoragesViewMut};
use crate::{ use crate::{
transform::Transform, transform::Transform,
camera::Camera, camera::Camera,
fly_controller::FlyController, fly_controller::FlyController,
world::raycast::LookingAtBlock,
}; };
#[derive(Component)]
pub struct LocalPlayer;
#[derive(Component)] #[derive(Component)]
pub struct Player; pub struct Player;
@ -16,31 +14,15 @@ pub struct Player;
pub struct MainPlayer; pub struct MainPlayer;
pub fn spawn_player ( pub fn spawn_player (
mut entities: EntitiesViewMut, mut storages: AllStoragesViewMut
mut vm_player: ViewMut<Player>,
mut vm_main_player: ViewMut<MainPlayer>,
mut vm_local_player: ViewMut<LocalPlayer>,
mut vm_transform: ViewMut<Transform>,
mut vm_camera: ViewMut<Camera>,
mut vm_controls: ViewMut<FlyController>,
) { ) {
log::info!("spawning player"); log::info!("spawning player");
entities.add_entity( storages.add_entity((
( Player,
&mut vm_player, MainPlayer,
&mut vm_main_player, Transform::default(),
&mut vm_local_player, Camera::default(),
&mut vm_transform, FlyController,
&mut vm_camera, LookingAtBlock::default(),
&mut vm_controls ));
),
(
Player,
MainPlayer,
LocalPlayer,
Transform(Mat4::default()),
Camera::default(),
FlyController
)
);
} }

View file

@ -9,6 +9,9 @@ use glium::{
}; };
use glam::Vec3; use glam::Vec3;
pub mod world;
pub mod selection_box;
#[derive(Unique)] #[derive(Unique)]
pub struct RenderTarget(pub glium::Frame); pub struct RenderTarget(pub glium::Frame);

View file

@ -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<LookingAtBlock>,
camera: View<Camera>,
mut target: NonSendSync<UniqueViewMut<RenderTarget>>,
) {
for lookat in lookat.iter() {
}
}

View file

@ -19,7 +19,6 @@ use glium::{
}; };
use crate::{ use crate::{
camera::Camera, camera::Camera,
rendering::RenderTarget,
prefabs::{ prefabs::{
ChunkShaderPrefab, ChunkShaderPrefab,
BlockTexturesPrefab, BlockTexturesPrefab,
@ -30,6 +29,7 @@ use crate::{
chunk::CHUNK_SIZE, chunk::CHUNK_SIZE,
}, },
}; };
use super::RenderTarget;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct ChunkVertex { pub struct ChunkVertex {

View file

@ -6,16 +6,18 @@ use anyhow::{Result, Context};
pub mod chunk; pub mod chunk;
pub mod block; pub mod block;
pub mod render;
pub mod tasks; pub mod tasks;
pub mod loading; pub mod loading;
pub mod mesh; pub mod mesh;
pub mod neighbors; pub mod neighbors;
pub mod worldgen; pub mod worldgen;
pub mod raycast;
use chunk::{Chunk, ChunkMesh}; use chunk::{Chunk, ChunkMesh};
use tasks::ChunkTaskManager; use tasks::ChunkTaskManager;
use self::{chunk::CHUNK_SIZE, block::Block};
//TODO separate world struct for render data //TODO separate world struct for render data
// because this is not send-sync // because this is not send-sync
@ -25,6 +27,30 @@ pub struct ChunkStorage {
pub chunks: HashMap<IVec3, Chunk> pub chunks: HashMap<IVec3, Chunk>
} }
impl ChunkStorage { 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<Block> {
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 { pub fn new() -> Self {
Self::default() Self::default()
} }

View file

@ -1,6 +1,7 @@
use glam::IVec3; use glam::IVec3;
use glium::{VertexBuffer, IndexBuffer}; 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; pub const CHUNK_SIZE: usize = 32;

View file

@ -2,7 +2,7 @@ use glam::{IVec3, ivec3};
use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType}; use glium::{VertexBuffer, IndexBuffer, index::PrimitiveType};
use shipyard::{View, UniqueView, UniqueViewMut, IntoIter, Workload, IntoWorkload, NonSendSync}; use shipyard::{View, UniqueView, UniqueViewMut, IntoIter, Workload, IntoWorkload, NonSendSync};
use crate::{ use crate::{
player::LocalPlayer, player::MainPlayer,
transform::Transform, transform::Transform,
settings::GameSettings, settings::GameSettings,
rendering::Renderer rendering::Renderer
@ -27,7 +27,7 @@ pub fn update_loaded_world_around_player() -> Workload {
pub fn update_chunks_if_player_moved( pub fn update_chunks_if_player_moved(
v_settings: UniqueView<GameSettings>, v_settings: UniqueView<GameSettings>,
v_local_player: View<LocalPlayer>, v_local_player: View<MainPlayer>,
v_transform: View<Transform>, v_transform: View<Transform>,
mut vm_world: UniqueViewMut<ChunkStorage>, mut vm_world: UniqueViewMut<ChunkStorage>,
) { ) {

View file

@ -1,6 +1,7 @@
use strum::{EnumIter, IntoEnumIterator}; use strum::{EnumIter, IntoEnumIterator};
use glam::{Vec3A, vec3a, IVec3, ivec3}; 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; pub mod data;
use data::MeshGenData; use data::MeshGenData;

55
src/world/raycast.rs Normal file
View file

@ -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<f32>) -> Option<RaycastReport> {
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<RaycastReport>);
pub fn update_player_raycast(
main_player: View<MainPlayer>,
transform: View<Transform>,
mut raycast: ViewMut<LookingAtBlock>,
world: UniqueView<ChunkStorage>,
) {
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.)));
}
}

View file

@ -4,10 +4,10 @@ use shipyard::Unique;
use rayon::{ThreadPool, ThreadPoolBuilder}; use rayon::{ThreadPool, ThreadPoolBuilder};
use super::{ use super::{
chunk::BlockData, chunk::BlockData,
render::ChunkVertex,
mesh::{generate_mesh, data::MeshGenData}, mesh::{generate_mesh, data::MeshGenData},
worldgen::generate_world, worldgen::generate_world,
}; };
use crate::rendering::world::ChunkVertex;
pub enum ChunkTask { pub enum ChunkTask {
LoadChunk { LoadChunk {