diff options
Diffstat (limited to 'engine')
| -rw-r--r-- | engine/src/camera/fly.rs | 16 | ||||
| -rw-r--r-- | engine/src/data_types/matrix.rs | 9 | ||||
| -rw-r--r-- | engine/src/rendering/main_render_pass.rs | 8 | ||||
| -rw-r--r-- | engine/src/rendering/shader/default.rs | 32 | ||||
| -rw-r--r-- | engine/src/transform.rs | 82 | ||||
| -rw-r--r-- | engine/src/util.rs | 117 | ||||
| -rw-r--r-- | engine/src/windowing.rs | 35 |
7 files changed, 182 insertions, 117 deletions
diff --git a/engine/src/camera/fly.rs b/engine/src/camera/fly.rs index 80355fa..0651e58 100644 --- a/engine/src/camera/fly.rs +++ b/engine/src/camera/fly.rs @@ -13,7 +13,7 @@ use crate::ecs::{Component, Query}; use crate::input::keyboard::{Key, Keyboard}; use crate::input::mouse::Mouse; use crate::reflection::Reflection; -use crate::transform::WorldPosition; +use crate::transform::Transform; use crate::vector::{Vec2, Vec3}; builder! { @@ -77,7 +77,7 @@ pub struct Options fn update( camera_query: Query<( &mut Camera, - &mut WorldPosition, + &mut Transform, &mut Fly, Option<&ControllableCamera>, With<ActiveCamera>, @@ -94,7 +94,7 @@ fn update( for ( camera_ent_id, - (mut camera, mut camera_world_pos, mut fly_camera, controllable_camera), + (mut camera, mut camera_transform, mut fly_camera, controllable_camera), ) in camera_query.iter_with_euids() { if let Some(controllable_camera) = controllable_camera { @@ -134,30 +134,30 @@ fn update( camera.global_up = cam_right.cross(&direction).normalize(); if keyboard.pressed(Key::W) { - camera_world_pos.position += + camera_transform.position += direction * fly_camera.speed * time.delta_time.as_secs_f32(); } if keyboard.pressed(Key::S) { - camera_world_pos.position -= + camera_transform.position -= direction * fly_camera.speed * time.delta_time.as_secs_f32(); } if keyboard.pressed(Key::A) { let cam_left = -direction.cross(&Vec3::UP).normalize(); - camera_world_pos.position += + camera_transform.position += cam_left * fly_camera.speed * time.delta_time.as_secs_f32(); } if keyboard.pressed(Key::D) { let cam_right = direction.cross(&Vec3::UP).normalize(); - camera_world_pos.position += + camera_transform.position += cam_right * fly_camera.speed * time.delta_time.as_secs_f32(); } - camera.target = camera_world_pos.position + direction; + camera.target = camera_transform.position + direction; } Ok(()) diff --git a/engine/src/data_types/matrix.rs b/engine/src/data_types/matrix.rs index 48796bf..3c54bb1 100644 --- a/engine/src/data_types/matrix.rs +++ b/engine/src/data_types/matrix.rs @@ -1,5 +1,6 @@ use std::ops::{Index, IndexMut, Mul}; +use crate::data_types::dimens::Dimens3; use crate::vector::{Vec3, Vec4}; #[derive(Debug, Clone)] @@ -90,11 +91,11 @@ impl Matrix<f32, 4, 4> self[CellPos { row: 3, col: 3 }] = 1.0; } - pub fn scale(&mut self, scaling: &Vec3<f32>) + pub fn scale(&mut self, scaling: &Dimens3<f32>) { - self[CellPos { row: 0, col: 0 }] = scaling.x; - self[CellPos { row: 1, col: 1 }] = scaling.y; - self[CellPos { row: 2, col: 2 }] = scaling.z; + self[CellPos { row: 0, col: 0 }] = scaling.width; + self[CellPos { row: 1, col: 1 }] = scaling.height; + self[CellPos { row: 2, col: 2 }] = scaling.depth; self[CellPos { row: 3, col: 3 }] = 1.0; } diff --git a/engine/src/rendering/main_render_pass.rs b/engine/src/rendering/main_render_pass.rs index 622a087..c3278fa 100644 --- a/engine/src/rendering/main_render_pass.rs +++ b/engine/src/rendering/main_render_pass.rs @@ -56,7 +56,7 @@ use crate::texture::{ Wrapping as TextureWrapping, WHITE_1X1_ASSET_LABEL as TEXTURE_WHITE_1X1_ASSET_LABEL, }; -use crate::transform::WorldPosition; +use crate::transform::Transform; use crate::vector::Vec3; use crate::windowing::window::Window; @@ -88,7 +88,7 @@ pub fn add_main_render_pass( renderable_query: Query<RenderableEntity<'_>>, camera_query: Query<( &Camera, - &WorldPosition, + &Transform, &ActiveCamera, Traverse<(With<Scene>, With<ActiveScene>), TraverseUp, ChildOf>, )>, @@ -117,7 +117,7 @@ pub fn add_main_render_pass( return Ok(()); }; - let Some((camera, camera_world_pos, _)) = camera_query.iter().next() else { + let Some((camera, camera_transform, _)) = camera_query.iter().next() else { tracing::trace!("No active camera"); return Ok(()); }; @@ -350,7 +350,7 @@ pub fn add_main_render_pass( .unwrap(), ); - let mut view = camera.to_view_matrix(camera_world_pos.position); + let mut view = camera.to_view_matrix(camera_transform.position); view.translate(&Vec3 { x: 0.0, y: 0.0, z: 0.0 }); diff --git a/engine/src/rendering/shader/default.rs b/engine/src/rendering/shader/default.rs index 4c59a1b..59d0c9e 100644 --- a/engine/src/rendering/shader/default.rs +++ b/engine/src/rendering/shader/default.rs @@ -35,7 +35,7 @@ use crate::rendering::{ }; use crate::scene::{Active as ActiveScene, Scene}; use crate::texture::WHITE_1X1_ASSET_LABEL as TEXTURE_WHITE_1X1_ASSET_LABEL; -use crate::transform::{Scale, Transform, WorldPosition}; +use crate::transform::Transform; use crate::windowing::window::Window; pub static ASSET_LABEL: LazyLock<AssetLabel> = LazyLock::new(|| AssetLabel { @@ -63,14 +63,14 @@ pub fn enqueue_set_shader_bindings( renderable_query: Query<RenderableEntity<'_>>, camera_query: Query<( &Camera, - &WorldPosition, + &Transform, &ActiveCamera, Traverse<(With<Scene>, With<ActiveScene>), TraverseUp, ChildOf>, )>, window_query: Query<(&Window, &SurfaceSpec, With<RenderingTargetWindow>)>, point_light_query: Query<( &PointLight, - &WorldPosition, + &Transform, Traverse<(With<Scene>, With<ActiveScene>), TraverseUp, ChildOf>, )>, directional_light_query: Query<( @@ -85,7 +85,7 @@ pub fn enqueue_set_shader_bindings( let assets = assets.get()?; let shader_context = shader_context.get()?; - let Some((camera, camera_world_pos, _)) = camera_query.iter().next() else { + let Some((camera, camera_transform, _)) = camera_query.iter().next() else { tracing::trace!("No active camera"); return Ok(()); }; @@ -100,8 +100,7 @@ pub fn enqueue_set_shader_bindings( model, environmental_lighting, material_flags, - world_pos, - scale, + transform, shader, mut pending_shader_bindings, ), @@ -143,12 +142,12 @@ pub fn enqueue_set_shader_bindings( .unwrap(), ); - let model_matrix = Transform { - position: world_pos.as_deref().cloned().unwrap_or_default().position, - scale: scale.as_deref().cloned().unwrap_or_default().scale, - } - .to_matrix(); + let transform = match transform.as_deref() { + Some(transform) => transform, + None => &Transform::default(), + }; + let model_matrix = transform.to_matrix(); let inverted_model_matrix = model_matrix.inverse(); let model_material = match model_spec.find_first_material(&assets) { @@ -190,7 +189,7 @@ pub fn enqueue_set_shader_bindings( let lighting_shader_cursor = shader_cursor.field("Uniforms").field("lighting"); let material_shader_cursor = lighting_shader_cursor.field("material"); - let view = camera.to_view_matrix(camera_world_pos.position); + let view = camera.to_view_matrix(camera_transform.position); shader_bindings.bindings.extend([ model_3d_shader_cursor @@ -202,7 +201,7 @@ pub fn enqueue_set_shader_bindings( model_3d_shader_cursor.field("view").binding(view.into())?, lighting_shader_cursor .field("view_pos") - .binding(camera_world_pos.position.into())?, + .binding(camera_transform.position.into())?, material_shader_cursor.field("ambient").binding( (if material_flags.use_ambient_color { &model_material.ambient @@ -256,7 +255,7 @@ pub fn enqueue_set_shader_bindings( .bindings .reserve(point_light_query.iter().count() * 6); - for (point_light_index, (point_light, point_light_world_pos)) in + for (point_light_index, (point_light, point_light_transform)) in point_light_query.iter().enumerate() { let point_light_shader_cursor = lighting_shader_cursor @@ -276,7 +275,7 @@ pub fn enqueue_set_shader_bindings( .field("specular") .binding(point_light.specular.clone().into())?, point_light_shader_cursor.field("position").binding( - (point_light_world_pos.position + point_light.local_position).into(), + (point_light_transform.position + point_light.local_position).into(), )?, attenuation_props_shader_cursor .field("constant") @@ -399,8 +398,7 @@ type RenderableEntity<'a> = ( ChildOf, >, Option<&'a MaterialFlags>, - Option<&'a WorldPosition>, - Option<&'a Scale>, + Option<&'a Transform>, Option<&'a Shader>, Option<&'a mut PendingShaderBindings>, Without<NoDraw>, diff --git a/engine/src/transform.rs b/engine/src/transform.rs index 3b1c041..8e768a6 100644 --- a/engine/src/transform.rs +++ b/engine/src/transform.rs @@ -1,25 +1,29 @@ -use crate::builder; +use crate::data_types::dimens::Dimens3; use crate::ecs::Component; use crate::matrix::Matrix; use crate::reflection::Reflection; use crate::vector::Vec3; -builder!( - #[builder(name = Builder, derives=(Debug))] - #[derive(Debug)] - #[non_exhaustive] - pub struct Transform - { - pub position: Vec3<f32>, - pub scale: Vec3<f32>, - } -); +#[derive(Debug, Clone, Component, Reflection)] +#[non_exhaustive] +pub struct Transform +{ + pub position: Vec3<f32>, + pub scale: Dimens3<f32>, +} impl Transform { - pub fn builder() -> Builder + pub fn position(mut self, position: Vec3<f32>) -> Self { - Builder::default() + self.position = position; + self + } + + pub fn scale(mut self, scale: Dimens3<f32>) -> Self + { + self.scale = scale; + self } pub fn to_matrix(&self) -> Matrix<f32, 4, 4> @@ -37,57 +41,9 @@ impl Default for Transform { fn default() -> Self { - Self::builder().build() - } -} - -impl Default for Builder -{ - fn default() -> Self - { - Self { - position: Vec3::from(0.0), - scale: Vec3::from(1.0), - } - } -} - -/// A position in world space. -#[derive(Debug, Default, Clone, Copy, Component, Reflection)] -pub struct WorldPosition -{ - pub position: Vec3<f32>, -} - -impl From<Vec3<f32>> for WorldPosition -{ - fn from(position: Vec3<f32>) -> Self - { - Self { position } - } -} - -/// Scaling of a 3D object. -#[derive(Debug, Clone, Copy, Component, Reflection)] -pub struct Scale -{ - pub scale: Vec3<f32>, -} - -impl From<Vec3<f32>> for Scale -{ - fn from(scale: Vec3<f32>) -> Self - { - Self { scale } - } -} - -impl Default for Scale -{ - fn default() -> Self - { Self { - scale: Vec3 { x: 1.0, y: 1.0, z: 1.0 }, + position: Vec3 { x: 0.0, y: 0.0, z: 0.0 }, + scale: Dimens3 { width: 1.0, height: 1.0, depth: 1.0 }, } } } diff --git a/engine/src/util.rs b/engine/src/util.rs index 9d1c887..84ce726 100644 --- a/engine/src/util.rs +++ b/engine/src/util.rs @@ -1,6 +1,6 @@ use std::fmt::{Debug, Display}; -use crate::ecs::util::VecExt; +use crate::ecs::util::{StreamingIterator, VecExt}; #[derive(Debug, Clone)] pub struct MapVec<Key: Ord, Value> @@ -259,16 +259,18 @@ impl<const SIZE: usize, const BITS_PER_ITEM: usize> BitArray<SIZE, BITS_PER_ITEM self.inner[byte_index] |= item_bits << bit_index_in_byte; } - pub fn clear(&mut self) + pub fn iter_occupied(&self) -> BitArrayOccupiedIter<'_, BITS_PER_ITEM> { - self.inner.fill(0); + BitArrayOccupiedIter { + inner: self.inner.iter().enumerate().peekable(), + mask: u8::MAX, + } } - pub fn iter_occupied(&self) -> BitArrayOccupiedIter<'_, BITS_PER_ITEM> + pub fn iter_occupied_mut(&mut self) -> BitArrayOccupiedMutIter<'_, BITS_PER_ITEM> { - BitArrayOccupiedIter { - inner: self.inner.iter().copied().enumerate(), - byte: None, + BitArrayOccupiedMutIter { + inner: self.inner.iter_mut().enumerate().peekable(), mask: u8::MAX, } } @@ -290,8 +292,7 @@ impl<const SIZE: usize, const BITS_PER_ITEM: usize> Default pub struct BitArrayOccupiedIter<'a, const BITS_PER_ITEM: usize> { - inner: std::iter::Enumerate<std::iter::Copied<std::slice::Iter<'a, u8>>>, - byte: Option<(u8, usize)>, + inner: std::iter::Peekable<std::iter::Enumerate<std::slice::Iter<'a, u8>>>, mask: u8, } @@ -307,8 +308,8 @@ impl<const BITS_PER_ITEM: usize> Iterator for BitArrayOccupiedIter<'_, BITS_PER_ fn next(&mut self) -> Option<Self::Item> { let (byte_masked, byte_index, item_bit_index_in_byte) = loop { - let current = self.byte.and_then(|(byte, byte_index)| { - let byte_masked = byte & self.mask; + let current = self.inner.peek().and_then(|(byte_index, byte)| { + let byte_masked = **byte & self.mask; let lowest_one = byte_masked.lowest_one()?; @@ -321,9 +322,8 @@ impl<const BITS_PER_ITEM: usize> Iterator for BitArrayOccupiedIter<'_, BITS_PER_ }); let Some((byte_masked, byte_index, item_bit_index_in_byte)) = current else { - let (next_byte_index, next_byte) = self.inner.next()?; + let _ = self.inner.next()?; - self.byte = Some((next_byte, next_byte_index)); self.mask = u8::MAX; continue; @@ -346,6 +346,97 @@ impl<const BITS_PER_ITEM: usize> Iterator for BitArrayOccupiedIter<'_, BITS_PER_ } } +pub struct BitArrayOccupiedMutIter<'a, const BITS_PER_ITEM: usize> +{ + inner: std::iter::Peekable<std::iter::Enumerate<std::slice::IterMut<'a, u8>>>, + mask: u8, +} + +impl<const BITS_PER_ITEM: usize> BitArrayOccupiedMutIter<'_, BITS_PER_ITEM> +{ + const ITEM_MASK: u8 = !(u8::MAX << BITS_PER_ITEM); +} + +impl<const BITS_PER_ITEM: usize> StreamingIterator + for BitArrayOccupiedMutIter<'_, BITS_PER_ITEM> +{ + type Item<'a> + = BitArrayItemMut<'a, BITS_PER_ITEM> + where + Self: 'a; + + fn streaming_next(&mut self) -> Option<Self::Item<'_>> + { + let (byte_masked, byte_index, item_bit_index_in_byte) = loop { + let current = self.inner.peek().and_then(|(byte_index, byte)| { + let byte_masked = **byte & self.mask; + + let lowest_one = byte_masked.lowest_one()?; + + let item_bit_index_in_byte = match lowest_one as usize % BITS_PER_ITEM { + 0 => lowest_one as usize, + remainder => lowest_one as usize - remainder, + }; + + Some((byte_masked, byte_index, item_bit_index_in_byte)) + }); + + let Some((byte_masked, byte_index, item_bit_index_in_byte)) = current else { + let _ = self.inner.next()?; + + self.mask = u8::MAX; + + continue; + }; + + break (byte_masked, byte_index, item_bit_index_in_byte); + }; + + let item_bits = (byte_masked >> (item_bit_index_in_byte)) & Self::ITEM_MASK; + + self.mask &= (!Self::ITEM_MASK) << item_bit_index_in_byte; + + let item_index_in_byte = item_bit_index_in_byte as usize / BITS_PER_ITEM; + + let prev_bytes_item_cnt = (byte_index * 8) / BITS_PER_ITEM; + + let index = prev_bytes_item_cnt + item_index_in_byte; + + Some(BitArrayItemMut { + index, + bits: item_bits, + byte: self.inner.peek_mut().unwrap().1, + bit_index_in_byte: item_bit_index_in_byte, + }) + } +} + +pub struct BitArrayItemMut<'a, const BITS_PER_ITEM: usize> +{ + pub index: usize, + pub bits: u8, + byte: &'a mut u8, + bit_index_in_byte: usize, +} + +impl<'a, const BITS_PER_ITEM: usize> BitArrayItemMut<'a, BITS_PER_ITEM> +{ + const ITEM_MASK: u8 = !(u8::MAX << BITS_PER_ITEM); + + pub fn clear_and_set(&mut self, new_bits: u8, clear_mask: u8) + { + let new_bits = new_bits & Self::ITEM_MASK; + + let clear_mask = clear_mask & Self::ITEM_MASK; + + *self.byte &= !(clear_mask << self.bit_index_in_byte); + + *self.byte |= new_bits << self.bit_index_in_byte; + + self.bits = new_bits; + } +} + macro_rules! try_option { ($expr: expr) => { match $expr { diff --git a/engine/src/windowing.rs b/engine/src/windowing.rs index 4279148..aa86f01 100644 --- a/engine/src/windowing.rs +++ b/engine/src/windowing.rs @@ -31,6 +31,7 @@ use crate::ecs::phase::{Phase, PRE_UPDATE as PRE_UPDATE_PHASE}; use crate::ecs::sole::Single; use crate::ecs::system::observer::Observe; use crate::ecs::uid::Uid; +use crate::ecs::util::StreamingIterator; use crate::ecs::{declare_entity, pair, Query, Sole}; use crate::util::{BitArray, MapVec}; use crate::vector::Vec2; @@ -207,21 +208,41 @@ fn update_stuff( mouse_button_input.flags.clear(); } - for (key_index, key_state_bits) in input.keys.iter_occupied() { - let key = Key::KEYS[key_index]; + let mut key_updates = input.keys.iter_occupied_mut(); - let key_state = match key_state_bits { + while let Some(mut key_item) = key_updates.streaming_next() { + let key = Key::KEYS[key_item.index]; + + if key_item.bits == KEY_PRESSED_BITS | KEY_RELEASED_BITS { + match keyboard.get_key_state(key) { + KeyState::Pressed => { + keyboard.set_key_state(key, KeyState::Released); + + key_item.clear_and_set(KEY_PRESSED_BITS, u8::MAX); + } + KeyState::Released => { + keyboard.set_key_state(key, KeyState::Pressed); + + key_item.clear_and_set(KEY_RELEASED_BITS, u8::MAX); + } + } + + continue; + } + + let key_state = match key_item.bits { KEY_PRESSED_BITS => KeyState::Pressed, KEY_RELEASED_BITS => KeyState::Released, _ => unreachable!(), }; keyboard.set_key_state(key, key_state); + + key_item.clear_and_set(0, u8::MAX); } input.relative_mouse_pos_delta = Vec2 { x: 0.0, y: 0.0 }; input.mouse_scroll_delta = MouseScrollDelta { vert_lines: 0.0, hor_lines: 0.0 }; - input.keys.clear(); }; keyboard.set_text_keys(iter_array_queue(&context.shared_state.text_keys)); @@ -776,7 +797,7 @@ struct MouseButtonFlags: u8 const BITS_PER_KEY: usize = 2; -const KEY_PRESSED_BITS: u8 = 0b11; +const KEY_PRESSED_BITS: u8 = 0b10; const KEY_RELEASED_BITS: u8 = 0b01; #[derive(Debug)] @@ -1005,9 +1026,7 @@ impl ApplicationHandler for App KeyState::Released => KEY_RELEASED_BITS, }; - input - .keys - .clear_and_set(key as usize, key_state_bits, u8::MAX); + input.keys.clear_and_set(key as usize, key_state_bits, 0); } WindowEvent::CursorMoved { device_id: _, position } => { { |
