diff --git a/src/ecs/components/camera.rs b/src/ecs/components/camera.rs index f677882..f1762ed 100755 --- a/src/ecs/components/camera.rs +++ b/src/ecs/components/camera.rs @@ -11,7 +11,7 @@ pub struct CameraComponent { impl Default for CameraComponent { fn default() -> Self { Self { - transform: Transform::new(), + transform: Transform::default(), fov: Angle::Degrees(45.0), mode: CameraProjectionMode::Perspective, } diff --git a/src/game.rs b/src/game.rs index bac87b9..323e077 100755 --- a/src/game.rs +++ b/src/game.rs @@ -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 { window: Arc, @@ -96,9 +83,6 @@ struct GameLoop { impl GameLoop { pub async fn new(window: Arc, world: Arc>, user_systems: Vec>) -> GameLoop { - /* let mut graph_exec = SystemGraphExecutor::new(); - graph_exec.add_system("jiggle_entities".to_string(), Box::new(JiggleEntitiesSystem {}), &[]); */ - Self { window: Arc::clone(&window), renderer: Box::new(BasicRenderer::create_with_window(window).await), diff --git a/src/main.rs b/src/main.rs index add3211..3ffceb4 100755 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ use ecs::components::mesh::MeshComponent; use ecs::components::transform::TransformComponent; use game::Game; use hecs::World; +use tracing::debug; use crate::ecs::SystemFnExecutor; use crate::render::material::Material; @@ -78,11 +79,11 @@ async fn main() { shader_id: 0, 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(); - 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_z(Angle::Degrees(-90.0)); world.spawn((camera,)); @@ -90,7 +91,11 @@ async fn main() { let jiggle_system = |world: &mut World| -> anyhow::Result<()> { for (_eid, (transform, )) in world.query_mut::<(&mut TransformComponent,)>() { 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(()) diff --git a/src/math/transform.rs b/src/math/transform.rs index 3e97a14..00df98a 100755 --- a/src/math/transform.rs +++ b/src/math/transform.rs @@ -3,186 +3,75 @@ use glam::{Vec3, Mat4, Quat}; use crate::math::angle::{self, Angle}; #[repr(C)] -#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +#[derive(Debug, Copy, Clone)] pub struct Transform { - matrix: glam::Mat4, + pub translation: Vec3, + pub rotation: Quat, + pub scale: Vec3, } impl Default for Transform { fn default() -> 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 for Transform { +/* impl Into for Transform { fn into(self) -> glam::Mat4 { 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)] impl Transform { - pub fn new() -> Self { - Self::default() - } - - pub fn from_matrix(matrix: glam::Mat4) -> Self { + pub fn new(translation: Vec3, rotation: Quat, scale: Vec3) -> Self { Self { - matrix, + translation, + rotation, + scale, } } - pub fn matrix(&self) -> glam::Mat4 { - self.matrix + pub fn from_translation(translation: Vec3) -> Self { + Self::new(translation, Quat::IDENTITY, ONE_V3) } - /// Create Transform from scale, rotation (in degrees), and translation - pub fn from_scale_rotation_deg_translation(scale: Vec3, mut rotation: Vec3, translation: Vec3) -> Self { - 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) + pub fn from_xyz(x: f32, y: f32, z: f32) -> Self { + Self::new(Vec3::new(x, y, z), Quat::IDENTITY, ONE_V3) } - /// Create Transform from scale, rotation (in radians), and translation - pub fn from_scale_rotation_rad_translation(scale: Vec3, rotation: Vec3, translation: Vec3) -> Self { - 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) + pub fn calculate_mat4(&self) -> Mat4 { + Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation) } - /// Create Transform from scale, rotation (as a quaternion), and translation - pub fn from_scale_rotation_quat_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self { - let matrix = glam::Mat4::from_scale_rotation_translation(scale, rotation, translation); - - Self::from_matrix(matrix) + /// Get the forward vector of the Transform. + pub fn forward(&self) -> Vec3 { + self.rotation * ONE_V3 } - pub fn from_translation_vec(translation: Vec3) -> Self { - let matrix = glam::Mat4::from_scale_rotation_translation(Vec3::new(1.0, 1.0, 1.0), Quat::IDENTITY, translation); - - Self::from_matrix(matrix) + /// Rotate this transform using a Quaternion + pub fn rotate(&mut self, rotation: Quat) { + self.rotation = rotation * self.rotation; } - pub fn from_translation(x: f32, y: f32, z: f32) -> Self { - Self::from_translation_vec(Vec3::new(x, y, z)) + pub fn rotate_x(&mut self, angle: Angle) { + self.rotate(Quat::from_rotation_x(angle.to_radians())) } - pub fn translate_vec3(&mut self, vec: Vec3) -> &mut Self { - let translation = glam::Mat4::from_translation(vec); - self.matrix *= translation; - - self + pub fn rotate_y(&mut self, angle: Angle) { + self.rotate(Quat::from_rotation_y(angle.to_radians())) } - /// Rotate around the given axis. - pub fn rotate_axis(&mut self, axis: Vec3, angle: Angle) -> &mut Self { - 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 + pub fn rotate_z(&mut self, angle: Angle) { + self.rotate(Quat::from_rotation_z(angle.to_radians())) } } \ No newline at end of file diff --git a/src/render/camera.rs b/src/render/camera.rs index 50fc38e..a4542fd 100755 --- a/src/render/camera.rs +++ b/src/render/camera.rs @@ -61,17 +61,9 @@ impl RenderCamera { } pub fn update_view_projection(&mut self, camera: &CameraComponent) -> &glam::Mat4 { - let rotation = camera.transform.get_rotation_rad(); - let position = camera.transform.get_translation(); - - 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(); + let position = camera.transform.translation; + let target = camera.transform.rotation * glam::Vec3::new(0.0, 0.0, -1.0); + let target = target.normalize(); /* debug!("Camera rotation: {:?}", rotation); debug!("Camera position: {:?}", position); diff --git a/src/render/renderer.rs b/src/render/renderer.rs index 99ea17a..e109547 100755 --- a/src/render/renderer.rs +++ b/src/render/renderer.rs @@ -162,7 +162,7 @@ impl BasicRenderer { let transform_buffer = device.create_buffer_init( &wgpu::util::BufferInitDescriptor { 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, } ); @@ -405,7 +405,7 @@ impl Renderer for BasicRenderer { } // 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, &[]); // There will always be a camera (hopefully)