summaryrefslogtreecommitdiff
path: root/engine
diff options
context:
space:
mode:
Diffstat (limited to 'engine')
-rw-r--r--engine/src/camera/fly.rs16
-rw-r--r--engine/src/data_types/matrix.rs9
-rw-r--r--engine/src/rendering/main_render_pass.rs8
-rw-r--r--engine/src/rendering/shader/default.rs32
-rw-r--r--engine/src/transform.rs82
-rw-r--r--engine/src/util.rs117
-rw-r--r--engine/src/windowing.rs35
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 } => {
{