implement simple ecs systems

This commit is contained in:
SeanOMik 2023-06-29 01:17:30 -04:00
parent 6a30a17f5f
commit 1ef664165d
Signed by: SeanOMik
GPG Key ID: 568F326C7EB33ACB
6 changed files with 50 additions and 180 deletions

View File

@ -11,7 +11,7 @@ pub struct CameraComponent {
impl Default for CameraComponent { impl Default for CameraComponent {
fn default() -> Self { fn default() -> Self {
Self { Self {
transform: Transform::new(), transform: Transform::default(),
fov: Angle::Degrees(45.0), fov: Angle::Degrees(45.0),
mode: CameraProjectionMode::Perspective, mode: CameraProjectionMode::Perspective,
} }

View File

@ -69,19 +69,6 @@ impl TickCounter {
} }
} }
struct JiggleEntitiesSystem {
}
impl SimpleSystem for JiggleEntitiesSystem {
fn execute_mut(&mut self, world: &mut World) -> anyhow::Result<()> {
for (_eid, (transform, )) in world.query_mut::<(&mut TransformComponent,)>() {
transform.transform.translate_vec3(glam::Vec3::new(0.0, 0.001, 0.0));
}
Ok(())
}
}
struct GameLoop { struct GameLoop {
window: Arc<Window>, window: Arc<Window>,
@ -96,9 +83,6 @@ struct GameLoop {
impl GameLoop { impl GameLoop {
pub async fn new(window: Arc<Window>, world: Arc<Mutex<World>>, user_systems: Vec<Box<dyn SimpleSystem>>) -> GameLoop { pub async fn new(window: Arc<Window>, world: Arc<Mutex<World>>, user_systems: Vec<Box<dyn SimpleSystem>>) -> GameLoop {
/* let mut graph_exec = SystemGraphExecutor::new();
graph_exec.add_system("jiggle_entities".to_string(), Box::new(JiggleEntitiesSystem {}), &[]); */
Self { Self {
window: Arc::clone(&window), window: Arc::clone(&window),
renderer: Box::new(BasicRenderer::create_with_window(window).await), renderer: Box::new(BasicRenderer::create_with_window(window).await),

View File

@ -10,6 +10,7 @@ use ecs::components::mesh::MeshComponent;
use ecs::components::transform::TransformComponent; use ecs::components::transform::TransformComponent;
use game::Game; use game::Game;
use hecs::World; use hecs::World;
use tracing::debug;
use crate::ecs::SystemFnExecutor; use crate::ecs::SystemFnExecutor;
use crate::render::material::Material; use crate::render::material::Material;
@ -78,11 +79,11 @@ async fn main() {
shader_id: 0, shader_id: 0,
texture: diffuse_texture texture: diffuse_texture
}), }),
TransformComponent::from(Transform::from_translation(0.005, 0.0, 0.0)), TransformComponent::from(Transform::from_xyz(0.005, 0.0, 0.0)),
)); ));
let mut camera = CameraComponent::new(); let mut camera = CameraComponent::new();
camera.transform.translate_vec3(glam::Vec3::new(0.0, 0.0, 2.0)); camera.transform.translation += glam::Vec3::new(0.0, 0.0, 2.0);
//camera.transform.rotate_y(Angle::Degrees(-25.0)); //camera.transform.rotate_y(Angle::Degrees(-25.0));
camera.transform.rotate_z(Angle::Degrees(-90.0)); camera.transform.rotate_z(Angle::Degrees(-90.0));
world.spawn((camera,)); world.spawn((camera,));
@ -90,7 +91,11 @@ async fn main() {
let jiggle_system = |world: &mut World| -> anyhow::Result<()> { let jiggle_system = |world: &mut World| -> anyhow::Result<()> {
for (_eid, (transform, )) in world.query_mut::<(&mut TransformComponent,)>() { for (_eid, (transform, )) in world.query_mut::<(&mut TransformComponent,)>() {
let t = &mut transform.transform; let t = &mut transform.transform;
t.translate_vec3(glam::Vec3::new(t.x() * -1.0, 0.001, 0.0));
debug!("Translation: {}", t.translation);
t.translation += glam::Vec3::new(0.0, 0.001, 0.0);
t.translation.x *= -1.0
} }
Ok(()) Ok(())

View File

@ -3,186 +3,75 @@ use glam::{Vec3, Mat4, Quat};
use crate::math::angle::{self, Angle}; use crate::math::angle::{self, Angle};
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] #[derive(Debug, Copy, Clone)]
pub struct Transform { pub struct Transform {
matrix: glam::Mat4, pub translation: Vec3,
pub rotation: Quat,
pub scale: Vec3,
} }
impl Default for Transform { impl Default for Transform {
fn default() -> Self { fn default() -> Self {
Self { Self {
matrix: glam::Mat4::IDENTITY translation: Vec3::new(0.0, 0.0, 0.0),
rotation: Quat::IDENTITY,
scale: Vec3::new(1.0, 1.0, 1.0),
} }
} }
} }
impl Into<glam::Mat4> for Transform { /* impl Into<glam::Mat4> for Transform {
fn into(self) -> glam::Mat4 { fn into(self) -> glam::Mat4 {
self.matrix self.matrix
} }
} } */
// TODO: https://www.brainvoyager.com/bv/doc/UsersGuide/CoordsAndTransforms/SpatialTransformationMatrices.html
const ZERO_V3: Vec3 = Vec3::new(0.0, 0.0, 0.0);
const ONE_V3: Vec3 = Vec3::new(1.0, 1.0, 1.0);
#[allow(dead_code)] #[allow(dead_code)]
impl Transform { impl Transform {
pub fn new() -> Self { pub fn new(translation: Vec3, rotation: Quat, scale: Vec3) -> Self {
Self::default()
}
pub fn from_matrix(matrix: glam::Mat4) -> Self {
Self { Self {
matrix, translation,
rotation,
scale,
} }
} }
pub fn matrix(&self) -> glam::Mat4 { pub fn from_translation(translation: Vec3) -> Self {
self.matrix Self::new(translation, Quat::IDENTITY, ONE_V3)
} }
/// Create Transform from scale, rotation (in degrees), and translation pub fn from_xyz(x: f32, y: f32, z: f32) -> Self {
pub fn from_scale_rotation_deg_translation(scale: Vec3, mut rotation: Vec3, translation: Vec3) -> Self { Self::new(Vec3::new(x, y, z), Quat::IDENTITY, ONE_V3)
rotation.x = angle::degrees_to_radians(rotation.x);
rotation.y = angle::degrees_to_radians(rotation.y);
rotation.z = angle::degrees_to_radians(rotation.z);
let rotation_quat = glam::Quat::from_euler(glam::EulerRot::XYZ, rotation.x, rotation.y, rotation.z);
let matrix = glam::Mat4::from_scale_rotation_translation(scale, rotation_quat, translation);
Self::from_matrix(matrix)
} }
/// Create Transform from scale, rotation (in radians), and translation pub fn calculate_mat4(&self) -> Mat4 {
pub fn from_scale_rotation_rad_translation(scale: Vec3, rotation: Vec3, translation: Vec3) -> Self { Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
let rotation_quat = glam::Quat::from_euler(glam::EulerRot::XYZ, rotation.x, rotation.y, rotation.z);
let matrix = glam::Mat4::from_scale_rotation_translation(scale, rotation_quat, translation);
Self::from_matrix(matrix)
} }
/// Create Transform from scale, rotation (as a quaternion), and translation /// Get the forward vector of the Transform.
pub fn from_scale_rotation_quat_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self { pub fn forward(&self) -> Vec3 {
let matrix = glam::Mat4::from_scale_rotation_translation(scale, rotation, translation); self.rotation * ONE_V3
Self::from_matrix(matrix)
} }
pub fn from_translation_vec(translation: Vec3) -> Self { /// Rotate this transform using a Quaternion
let matrix = glam::Mat4::from_scale_rotation_translation(Vec3::new(1.0, 1.0, 1.0), Quat::IDENTITY, translation); pub fn rotate(&mut self, rotation: Quat) {
self.rotation = rotation * self.rotation;
Self::from_matrix(matrix)
} }
pub fn from_translation(x: f32, y: f32, z: f32) -> Self { pub fn rotate_x(&mut self, angle: Angle) {
Self::from_translation_vec(Vec3::new(x, y, z)) self.rotate(Quat::from_rotation_x(angle.to_radians()))
} }
pub fn translate_vec3(&mut self, vec: Vec3) -> &mut Self { pub fn rotate_y(&mut self, angle: Angle) {
let translation = glam::Mat4::from_translation(vec); self.rotate(Quat::from_rotation_y(angle.to_radians()))
self.matrix *= translation;
self
} }
/// Rotate around the given axis. pub fn rotate_z(&mut self, angle: Angle) {
pub fn rotate_axis(&mut self, axis: Vec3, angle: Angle) -> &mut Self { self.rotate(Quat::from_rotation_z(angle.to_radians()))
let radians = angle.to_radians();
let rotation = glam::Mat4::from_axis_angle(axis, radians);
self.matrix *= rotation;
self
}
// Rotate the transform with degrees
pub fn rotate_degrees(&mut self, mut x: f32, mut y: f32, mut z: f32) -> &mut Self {
// Convert degrees to radians
x = angle::degrees_to_radians(x);
y = angle::degrees_to_radians(y);
z = angle::degrees_to_radians(z);
let rotation = glam::Mat4::from_euler(glam::EulerRot::XYZ, x, y, z);
self.matrix *= rotation;
self
}
// Rotate the transform with degrees in a vec
pub fn rotate_degrees_vec(&mut self, mut rotation: Vec3) -> &mut Self {
self.rotate_degrees(rotation.x, rotation.y, rotation.z)
}
// Rotate the transform with radians
pub fn rotate_radians(&mut self, rotation: Vec3) -> &mut Self {
let rotation = glam::Mat4::from_euler(glam::EulerRot::XYZ, rotation.x, rotation.y, rotation.z);
self.matrix *= rotation;
self
}
/// Rotate the transform with a quaternion
pub fn rotate_quat(&mut self, quat: glam::Quat) -> &mut Self {
let rotation = glam::Mat4::from_quat(quat);
self.matrix *= rotation;
self
}
/// Rotate around the x axis.
pub fn rotate_x(&mut self, angle: Angle) -> &mut Self {
self.rotate_axis(Vec3::new(1.0, 0.0, 0.0), angle)
}
/// Rotate around the y axis.
pub fn rotate_y(&mut self, angle: Angle) -> &mut Self {
self.rotate_axis(Vec3::new(0.0, 1.0, 0.0), angle)
}
/// Rotate around the z axis.
pub fn rotate_z(&mut self, angle: Angle) -> &mut Self {
self.rotate_axis(Vec3::new(0.0, 0.0, 1.0), angle)
}
/// Get translation
pub fn get_translation(&self) -> glam::Vec3 {
let (_, _, t) = self.matrix.to_scale_rotation_translation();
t
}
/// Get rotation in radians
pub fn get_rotation_rad(&self) -> glam::Vec3 {
let (_, quat, _) = self.matrix.to_scale_rotation_translation();
let rot = quat.to_euler(glam::EulerRot::XYZ);
rot.into()
}
/// Get rotation in degrees
pub fn get_rotation_deg(&self) -> glam::Vec3 {
let mut rot = self.get_rotation_rad();
rot.x = angle::radians_to_degrees(rot.x);
rot.y = angle::radians_to_degrees(rot.y);
rot.z = angle::radians_to_degrees(rot.z);
rot
}
pub fn scale(&mut self, scale: Vec3) -> &mut Self {
let scale = Mat4::from_scale(scale);
self.matrix *= scale;
self
}
pub fn x(&self) -> f32 {
self.get_translation().x
}
pub fn y(&self) -> f32 {
self.get_translation().y
}
pub fn z(&self) -> f32 {
self.get_translation().z
} }
} }

View File

@ -61,17 +61,9 @@ impl RenderCamera {
} }
pub fn update_view_projection(&mut self, camera: &CameraComponent) -> &glam::Mat4 { pub fn update_view_projection(&mut self, camera: &CameraComponent) -> &glam::Mat4 {
let rotation = camera.transform.get_rotation_rad(); let position = camera.transform.translation;
let position = camera.transform.get_translation(); let target = camera.transform.rotation * glam::Vec3::new(0.0, 0.0, -1.0);
let target = target.normalize();
let (sin_y, cos_y) = rotation.y.sin_cos();
let (sin_z, cos_z) = rotation.z.sin_cos();
let target = glam::Vec3::new(
cos_y * cos_z,
sin_y,
cos_y * sin_z
).normalize();
/* debug!("Camera rotation: {:?}", rotation); /* debug!("Camera rotation: {:?}", rotation);
debug!("Camera position: {:?}", position); debug!("Camera position: {:?}", position);

View File

@ -162,7 +162,7 @@ impl BasicRenderer {
let transform_buffer = device.create_buffer_init( let transform_buffer = device.create_buffer_init(
&wgpu::util::BufferInitDescriptor { &wgpu::util::BufferInitDescriptor {
label: Some("Transform Buffer"), label: Some("Transform Buffer"),
contents: bytemuck::cast_slice(&[Transform::new()]), contents: bytemuck::cast_slice(&[glam::Mat4::IDENTITY]),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
} }
); );
@ -405,7 +405,7 @@ impl Renderer for BasicRenderer {
} }
// Update transform buffer, and bind to the bind group // Update transform buffer, and bind to the bind group
self.queue.write_buffer(&self.transform_buffer, 0, bytemuck::cast_slice(&[job.transform().matrix()])); self.queue.write_buffer(&self.transform_buffer, 0, bytemuck::cast_slice(&[job.transform().calculate_mat4()]));
render_pass.set_bind_group(1, &self.transform_bind_group, &[]); render_pass.set_bind_group(1, &self.transform_bind_group, &[]);
// There will always be a camera (hopefully) // There will always be a camera (hopefully)