diff --git a/src/core/render/primitives/transform.rs b/src/core/render/primitives/transform.rs index c5a6fae..85bd01b 100644 --- a/src/core/render/primitives/transform.rs +++ b/src/core/render/primitives/transform.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use bevy_ecs::resource::Resource; +use bevy_ecs::prelude::*; use glam::{Mat4, Quat, Vec3}; use vulkano::{ Validated, @@ -13,7 +13,7 @@ use crate::core::render::primitives::{AsBindableBuffer, AsVertexBuffer}; use super::command::AsRenderableMeshInstance; -#[derive(Resource, Debug, Clone)] +#[derive(Component, Debug, Clone)] pub struct Transform { pub position: Vec3, pub rotation: Quat, diff --git a/src/core/render/primitives/velocity.rs b/src/core/render/primitives/velocity.rs index 7663f3e..6e16db4 100644 --- a/src/core/render/primitives/velocity.rs +++ b/src/core/render/primitives/velocity.rs @@ -1,7 +1,7 @@ -use bevy_ecs::resource::Resource; +use bevy_ecs::prelude::*; use glam::Vec3; -#[derive(Resource, Debug, Clone)] +#[derive(Component, Debug, Clone)] pub struct Velocity { pub linear: Vec3, pub angular: Vec3, diff --git a/src/core/scene/manager.rs b/src/core/scene/manager.rs index 652e83b..47aa2e9 100644 --- a/src/core/scene/manager.rs +++ b/src/core/scene/manager.rs @@ -33,60 +33,29 @@ impl SceneManager { fn create_world_with_resources(window_context: &WindowContext) -> World { let mut world = World::new(); - // Add Vulkan resources - world.insert_resource(VulkanInstance( - window_context - .vulkan_context() - .vulkano_context() - .instance() - .clone(), - )); - world.insert_resource(VulkanDevice( - window_context - .vulkan_context() - .vulkano_context() - .device() - .clone(), - )); - world.insert_resource(VulkanGraphicsQueue( - window_context - .vulkan_context() - .vulkano_context() - .graphics_queue() - .clone(), - )); - world.insert_resource(VulkanComputeQueue( - window_context - .vulkan_context() - .vulkano_context() - .compute_queue() - .clone(), - )); - world.insert_resource(VulkanTransferQueue( - window_context - .vulkan_context() - .vulkano_context() - .transfer_queue() - .cloned(), - )); - world.insert_resource(VulkanMemoryAllocator( - window_context - .vulkan_context() - .vulkano_context() - .memory_allocator() - .clone(), - )); + let vulkan_context = window_context.vulkan_context(); + let vulkano_context = vulkan_context.vulkano_context(); + + let vulkan_instance = vulkano_context.instance(); + let vulkan_device = vulkano_context.device(); + let vulkan_graphics_queue = vulkano_context.graphics_queue(); + let vulkan_compute_queue = vulkano_context.compute_queue(); + let vulkan_transfer_queue = vulkano_context.transfer_queue(); + let vulkan_memory_allocator = vulkano_context.memory_allocator(); + let vulkan_command_buffer_allocator = vulkan_context.command_buffer_allocator(); + let vulkan_descriptor_set_allocator = vulkan_context.descriptor_set_allocator(); + + world.insert_resource(VulkanInstance(vulkan_instance.clone())); + world.insert_resource(VulkanDevice(vulkan_device.clone())); + world.insert_resource(VulkanGraphicsQueue(vulkan_graphics_queue.clone())); + world.insert_resource(VulkanComputeQueue(vulkan_compute_queue.clone())); + world.insert_resource(VulkanTransferQueue(vulkan_transfer_queue.cloned())); + world.insert_resource(VulkanMemoryAllocator(vulkan_memory_allocator.clone())); world.insert_resource(VulkanCommandBufferAllocator( - window_context - .vulkan_context() - .command_buffer_allocator() - .clone(), + vulkan_command_buffer_allocator.clone(), )); world.insert_resource(VulkanDescriptorSetAllocator( - window_context - .vulkan_context() - .descriptor_set_allocator() - .clone(), + vulkan_descriptor_set_allocator.clone(), )); world diff --git a/src/core/timer.rs b/src/core/timer.rs index 3245a4c..1efb5ad 100644 --- a/src/core/timer.rs +++ b/src/core/timer.rs @@ -1,3 +1,6 @@ +use bevy_ecs::resource::Resource; + +#[derive(Resource)] pub struct Timer { start_time: std::time::Instant, last_time: std::time::Instant, diff --git a/src/game/scenes/main_scene.rs b/src/game/scenes/main_scene.rs index 0079a5a..0ad4d61 100644 --- a/src/game/scenes/main_scene.rs +++ b/src/game/scenes/main_scene.rs @@ -7,6 +7,7 @@ use crate::core::app::context::WindowContext; use crate::core::app::user_event::UserEvent; use crate::core::render::primitives::camera::Camera3D; use crate::core::render::primitives::transform::Transform; +use crate::core::render::primitives::velocity::Velocity; use crate::core::render::primitives::vulkan_resource::{ VulkanCommandBufferAllocator, VulkanDescriptorSetAllocator, VulkanDevice, VulkanGraphicsQueue, VulkanMemoryAllocator, @@ -17,7 +18,10 @@ use crate::core::render::resources::meshes::{ObjMesh, SquareMesh}; use crate::core::render::resources::pipeline::PipelineLoader; use crate::core::render::resources::texture::{TextureLoadInfo, TextureLoader, TextureSourceKind}; use crate::core::scene::AsScene; +use crate::core::timer::Timer; use crate::game::assets::pipelines::simple::SimplePipeline; +use bevy_ecs::prelude::*; +use bevy_ecs::schedule::Schedule; use bevy_ecs::world::World; use egui_winit_vulkano::egui; use glam::EulerRot; @@ -31,15 +35,20 @@ use vulkano::{ }; use winit::window::CursorGrabMode; +#[derive(Component)] +pub struct Square; + +#[derive(Component)] +pub struct Cube; + pub struct MainSceneState { texture_loader: TextureLoader, pipeline_loader: PipelineLoader, square: SquareMesh, obj: ObjMesh, - square_instances: Vec, - obj_instances: Vec, camera: Camera3D, speed: f32, + scheduler: Schedule, } #[derive(Default)] @@ -111,45 +120,6 @@ impl AsScene for MainScene { obj.into_iter().next().unwrap() }; - let num_instances = 100; - let instance_size = 10.0; - let instance_spacing = 10.0; - let num_instances_per_row = (num_instances as f32 / instance_spacing).ceil() as u32; - let square_instances: Vec = (0..num_instances) - .map(|i| { - Transform::new( - Vec3::new( - (i % num_instances_per_row) as f32 * (instance_spacing + instance_size), - 0.0, - (i / num_instances_per_row) as f32 * (instance_spacing + instance_size), - ), - Quat::from_euler(EulerRot::XYZ, 0.0, rand::random_range(0.0..=360.0), 0.0), - Vec3::new(instance_size, instance_size, instance_size), - ) - }) - .collect(); - - let obj_instances: Vec = (0..num_instances) - .map(|i| { - Transform::new( - Vec3::new( - (i % num_instances_per_row) as f32 * (instance_spacing + instance_size), - 0.0, - (i / num_instances_per_row) as f32 - * (instance_spacing + instance_size) - * -1.0 - - instance_spacing * 2.0, - ), - Quat::from_euler(EulerRot::XYZ, 0.0, rand::random_range(0.0..=360.0), 0.0), - Vec3::new( - instance_size * 0.5, - instance_size * 0.5, - instance_size * 0.5, - ), - ) - }) - .collect(); - let camera = window_context.with_renderer(|renderer| { Camera3D::new( renderer.aspect_ratio(), @@ -159,14 +129,20 @@ impl AsScene for MainScene { ) }); + let mut scheduler = Schedule::default(); + scheduler.add_systems(update_velocity_system); + scheduler.add_systems(update_timer_system); + + world.insert_resource(Timer::new()); + Self::create_entities(world, 100, 10.0, 10.0); + self.state = Some(MainSceneState { square, obj, pipeline_loader, - square_instances, - obj_instances, camera, speed: 50.0, + scheduler, texture_loader, }); @@ -175,7 +151,7 @@ impl AsScene for MainScene { fn update( &mut self, - _world: &mut World, + world: &mut World, window_context: &WindowContext, ) -> Result<(), Box> { let state = self.state.as_mut().unwrap(); @@ -192,20 +168,7 @@ impl AsScene for MainScene { }); }); - let delta_time = window_context.get_delta_time(); - for (i, instance) in state.square_instances.iter_mut().enumerate() { - let rotation_speed = (i % 10) as f32; - let rotation_delta = Quat::from_rotation_y(rotation_speed * delta_time); - - instance.rotate(rotation_delta); - } - - for (i, instance) in state.obj_instances.iter_mut().enumerate() { - let rotation_speed = (i % 10) as f32; - let rotation_delta = Quat::from_rotation_y(rotation_speed * delta_time); - - instance.rotate(rotation_delta); - } + state.scheduler.run(world); if window_context .with_input_manager(|input_manager| input_manager.get_virtual_input_state("mouse_left")) @@ -276,13 +239,23 @@ impl AsScene for MainScene { .camera .create_buffer(VulkanMemoryAllocator::get_from_world(world))?, ); + let square_transforms = world + .query_filtered::<&Transform, With>() + .iter(&world) + .cloned() + .collect::>(); let square_transform_uniform = Transform::create_buffer( VulkanMemoryAllocator::get_from_world(world), - &state.square_instances, + &square_transforms, )?; - let obj_transform_uniform = Transform::create_buffer( + let cube_transforms = world + .query_filtered::<&Transform, With>() + .iter(&world) + .cloned() + .collect::>(); + let cube_transform_uniform = Transform::create_buffer( VulkanMemoryAllocator::get_from_world(world), - &state.obj_instances, + &cube_transforms, )?; state @@ -309,7 +282,7 @@ impl AsScene for MainScene { &VulkanDescriptorSetAllocator::get_from_world(world), pipeline, &state.obj, - &obj_transform_uniform, + &cube_transform_uniform, vec![ camera_uniform.clone() as Arc, state @@ -400,3 +373,89 @@ impl AsScene for MainScene { self.state = None; } } + +impl MainScene { + // Function to create entities in the ECS world + fn create_entities( + world: &mut World, + num_instances: u32, + instance_size: f32, + instance_spacing: f32, + ) { + let num_instances_per_row = (num_instances as f32 / instance_spacing).ceil() as u32; + + let square_instances = (0..num_instances) + .map(|i| { + let x_index = i % num_instances_per_row; + let z_index = i / num_instances_per_row; + + let transform = Transform::new( + Vec3::new( + x_index as f32 * (instance_spacing + instance_size), + 0.0, + z_index as f32 * (instance_spacing + instance_size), + ), + Quat::from_euler(EulerRot::XYZ, 0.0, rand::random_range(0.0..=360.0), 0.0), + Vec3::new(instance_size, instance_size, instance_size), + ); + + let velocity = Velocity::new(Vec3::ZERO, Vec3::new(0.0, x_index as f32, 0.0)); + + (Square, transform, velocity) + }) + .collect::>(); + + world.spawn_batch(square_instances); + + let cube_instances = (0..num_instances) + .map(|i| { + let x_index = i % num_instances_per_row; + let z_index = i / num_instances_per_row; + + let transform = Transform::new( + Vec3::new( + x_index as f32 * (instance_spacing + instance_size), + 0.0, + z_index as f32 * (instance_spacing + instance_size) * -1.0 + - instance_spacing * 2.0, + ), + Quat::from_euler(EulerRot::XYZ, 0.0, rand::random_range(0.0..=360.0), 0.0), + Vec3::new( + instance_size * 0.5, + instance_size * 0.5, + instance_size * 0.5, + ), + ); + + let velocity = Velocity::new(Vec3::ZERO, Vec3::new(0.0, x_index as f32, 0.0)); + + (Cube, transform, velocity) + }) + .collect::>(); + + world.spawn_batch(cube_instances); + } +} + +fn update_velocity_system(mut query: Query<(&mut Transform, &Velocity)>, time: Res) { + for (mut transform, velocity) in query.iter_mut() { + let delta_time = time.delta_time(); + + // Update linear position + transform.translate(velocity.linear * delta_time); + + // Update angular rotation + let angular_delta = velocity.angular * delta_time; + let rotation_delta = Quat::from_euler( + EulerRot::XYZ, + angular_delta.x, + angular_delta.y, + angular_delta.z, + ); + transform.rotate(rotation_delta); + } +} + +fn update_timer_system(mut timer: ResMut) { + timer.update(); +}