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)]
pub struct RawInputState {
pub keyboard_state: HashSet<VirtualKeyCode, BuildNoHashHasher<u32>>,
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 (

View file

@ -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()
}

View file

@ -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,
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<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>,
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(),
));
}

View file

@ -9,6 +9,9 @@ use glium::{
};
use glam::Vec3;
pub mod world;
pub mod selection_box;
#[derive(Unique)]
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::{
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 {

View file

@ -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<IVec3, Chunk>
}
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 {
Self::default()
}

View file

@ -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;

View file

@ -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<GameSettings>,
v_local_player: View<LocalPlayer>,
v_local_player: View<MainPlayer>,
v_transform: View<Transform>,
mut vm_world: UniqueViewMut<ChunkStorage>,
) {

View file

@ -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;

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 super::{
chunk::BlockData,
render::ChunkVertex,
mesh::{generate_mesh, data::MeshGenData},
worldgen::generate_world,
};
use crate::rendering::world::ChunkVertex;
pub enum ChunkTask {
LoadChunk {