First entities render with ecs
This commit is contained in:
parent
9fabacffc9
commit
37467d5066
5 changed files with 148 additions and 117 deletions
|
@ -1,6 +1,6 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use bevy_ecs::resource::Resource;
|
use bevy_ecs::prelude::*;
|
||||||
use glam::{Mat4, Quat, Vec3};
|
use glam::{Mat4, Quat, Vec3};
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
Validated,
|
Validated,
|
||||||
|
@ -13,7 +13,7 @@ use crate::core::render::primitives::{AsBindableBuffer, AsVertexBuffer};
|
||||||
|
|
||||||
use super::command::AsRenderableMeshInstance;
|
use super::command::AsRenderableMeshInstance;
|
||||||
|
|
||||||
#[derive(Resource, Debug, Clone)]
|
#[derive(Component, Debug, Clone)]
|
||||||
pub struct Transform {
|
pub struct Transform {
|
||||||
pub position: Vec3,
|
pub position: Vec3,
|
||||||
pub rotation: Quat,
|
pub rotation: Quat,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use bevy_ecs::resource::Resource;
|
use bevy_ecs::prelude::*;
|
||||||
use glam::Vec3;
|
use glam::Vec3;
|
||||||
|
|
||||||
#[derive(Resource, Debug, Clone)]
|
#[derive(Component, Debug, Clone)]
|
||||||
pub struct Velocity {
|
pub struct Velocity {
|
||||||
pub linear: Vec3,
|
pub linear: Vec3,
|
||||||
pub angular: Vec3,
|
pub angular: Vec3,
|
||||||
|
|
|
@ -33,60 +33,29 @@ impl SceneManager {
|
||||||
fn create_world_with_resources(window_context: &WindowContext) -> World {
|
fn create_world_with_resources(window_context: &WindowContext) -> World {
|
||||||
let mut world = World::new();
|
let mut world = World::new();
|
||||||
|
|
||||||
// Add Vulkan resources
|
let vulkan_context = window_context.vulkan_context();
|
||||||
world.insert_resource(VulkanInstance(
|
let vulkano_context = vulkan_context.vulkano_context();
|
||||||
window_context
|
|
||||||
.vulkan_context()
|
let vulkan_instance = vulkano_context.instance();
|
||||||
.vulkano_context()
|
let vulkan_device = vulkano_context.device();
|
||||||
.instance()
|
let vulkan_graphics_queue = vulkano_context.graphics_queue();
|
||||||
.clone(),
|
let vulkan_compute_queue = vulkano_context.compute_queue();
|
||||||
));
|
let vulkan_transfer_queue = vulkano_context.transfer_queue();
|
||||||
world.insert_resource(VulkanDevice(
|
let vulkan_memory_allocator = vulkano_context.memory_allocator();
|
||||||
window_context
|
let vulkan_command_buffer_allocator = vulkan_context.command_buffer_allocator();
|
||||||
.vulkan_context()
|
let vulkan_descriptor_set_allocator = vulkan_context.descriptor_set_allocator();
|
||||||
.vulkano_context()
|
|
||||||
.device()
|
world.insert_resource(VulkanInstance(vulkan_instance.clone()));
|
||||||
.clone(),
|
world.insert_resource(VulkanDevice(vulkan_device.clone()));
|
||||||
));
|
world.insert_resource(VulkanGraphicsQueue(vulkan_graphics_queue.clone()));
|
||||||
world.insert_resource(VulkanGraphicsQueue(
|
world.insert_resource(VulkanComputeQueue(vulkan_compute_queue.clone()));
|
||||||
window_context
|
world.insert_resource(VulkanTransferQueue(vulkan_transfer_queue.cloned()));
|
||||||
.vulkan_context()
|
world.insert_resource(VulkanMemoryAllocator(vulkan_memory_allocator.clone()));
|
||||||
.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(),
|
|
||||||
));
|
|
||||||
world.insert_resource(VulkanCommandBufferAllocator(
|
world.insert_resource(VulkanCommandBufferAllocator(
|
||||||
window_context
|
vulkan_command_buffer_allocator.clone(),
|
||||||
.vulkan_context()
|
|
||||||
.command_buffer_allocator()
|
|
||||||
.clone(),
|
|
||||||
));
|
));
|
||||||
world.insert_resource(VulkanDescriptorSetAllocator(
|
world.insert_resource(VulkanDescriptorSetAllocator(
|
||||||
window_context
|
vulkan_descriptor_set_allocator.clone(),
|
||||||
.vulkan_context()
|
|
||||||
.descriptor_set_allocator()
|
|
||||||
.clone(),
|
|
||||||
));
|
));
|
||||||
|
|
||||||
world
|
world
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
use bevy_ecs::resource::Resource;
|
||||||
|
|
||||||
|
#[derive(Resource)]
|
||||||
pub struct Timer {
|
pub struct Timer {
|
||||||
start_time: std::time::Instant,
|
start_time: std::time::Instant,
|
||||||
last_time: std::time::Instant,
|
last_time: std::time::Instant,
|
||||||
|
|
|
@ -7,6 +7,7 @@ use crate::core::app::context::WindowContext;
|
||||||
use crate::core::app::user_event::UserEvent;
|
use crate::core::app::user_event::UserEvent;
|
||||||
use crate::core::render::primitives::camera::Camera3D;
|
use crate::core::render::primitives::camera::Camera3D;
|
||||||
use crate::core::render::primitives::transform::Transform;
|
use crate::core::render::primitives::transform::Transform;
|
||||||
|
use crate::core::render::primitives::velocity::Velocity;
|
||||||
use crate::core::render::primitives::vulkan_resource::{
|
use crate::core::render::primitives::vulkan_resource::{
|
||||||
VulkanCommandBufferAllocator, VulkanDescriptorSetAllocator, VulkanDevice, VulkanGraphicsQueue,
|
VulkanCommandBufferAllocator, VulkanDescriptorSetAllocator, VulkanDevice, VulkanGraphicsQueue,
|
||||||
VulkanMemoryAllocator,
|
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::pipeline::PipelineLoader;
|
||||||
use crate::core::render::resources::texture::{TextureLoadInfo, TextureLoader, TextureSourceKind};
|
use crate::core::render::resources::texture::{TextureLoadInfo, TextureLoader, TextureSourceKind};
|
||||||
use crate::core::scene::AsScene;
|
use crate::core::scene::AsScene;
|
||||||
|
use crate::core::timer::Timer;
|
||||||
use crate::game::assets::pipelines::simple::SimplePipeline;
|
use crate::game::assets::pipelines::simple::SimplePipeline;
|
||||||
|
use bevy_ecs::prelude::*;
|
||||||
|
use bevy_ecs::schedule::Schedule;
|
||||||
use bevy_ecs::world::World;
|
use bevy_ecs::world::World;
|
||||||
use egui_winit_vulkano::egui;
|
use egui_winit_vulkano::egui;
|
||||||
use glam::EulerRot;
|
use glam::EulerRot;
|
||||||
|
@ -31,15 +35,20 @@ use vulkano::{
|
||||||
};
|
};
|
||||||
use winit::window::CursorGrabMode;
|
use winit::window::CursorGrabMode;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct Square;
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct Cube;
|
||||||
|
|
||||||
pub struct MainSceneState {
|
pub struct MainSceneState {
|
||||||
texture_loader: TextureLoader,
|
texture_loader: TextureLoader,
|
||||||
pipeline_loader: PipelineLoader,
|
pipeline_loader: PipelineLoader,
|
||||||
square: SquareMesh,
|
square: SquareMesh,
|
||||||
obj: ObjMesh,
|
obj: ObjMesh,
|
||||||
square_instances: Vec<Transform>,
|
|
||||||
obj_instances: Vec<Transform>,
|
|
||||||
camera: Camera3D,
|
camera: Camera3D,
|
||||||
speed: f32,
|
speed: f32,
|
||||||
|
scheduler: Schedule,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -111,45 +120,6 @@ impl AsScene for MainScene {
|
||||||
obj.into_iter().next().unwrap()
|
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<Transform> = (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<Transform> = (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| {
|
let camera = window_context.with_renderer(|renderer| {
|
||||||
Camera3D::new(
|
Camera3D::new(
|
||||||
renderer.aspect_ratio(),
|
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 {
|
self.state = Some(MainSceneState {
|
||||||
square,
|
square,
|
||||||
obj,
|
obj,
|
||||||
pipeline_loader,
|
pipeline_loader,
|
||||||
square_instances,
|
|
||||||
obj_instances,
|
|
||||||
camera,
|
camera,
|
||||||
speed: 50.0,
|
speed: 50.0,
|
||||||
|
scheduler,
|
||||||
texture_loader,
|
texture_loader,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -175,7 +151,7 @@ impl AsScene for MainScene {
|
||||||
|
|
||||||
fn update(
|
fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
_world: &mut World,
|
world: &mut World,
|
||||||
window_context: &WindowContext,
|
window_context: &WindowContext,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
let state = self.state.as_mut().unwrap();
|
let state = self.state.as_mut().unwrap();
|
||||||
|
@ -192,20 +168,7 @@ impl AsScene for MainScene {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let delta_time = window_context.get_delta_time();
|
state.scheduler.run(world);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if window_context
|
if window_context
|
||||||
.with_input_manager(|input_manager| input_manager.get_virtual_input_state("mouse_left"))
|
.with_input_manager(|input_manager| input_manager.get_virtual_input_state("mouse_left"))
|
||||||
|
@ -276,13 +239,23 @@ impl AsScene for MainScene {
|
||||||
.camera
|
.camera
|
||||||
.create_buffer(VulkanMemoryAllocator::get_from_world(world))?,
|
.create_buffer(VulkanMemoryAllocator::get_from_world(world))?,
|
||||||
);
|
);
|
||||||
|
let square_transforms = world
|
||||||
|
.query_filtered::<&Transform, With<Square>>()
|
||||||
|
.iter(&world)
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<Transform>>();
|
||||||
let square_transform_uniform = Transform::create_buffer(
|
let square_transform_uniform = Transform::create_buffer(
|
||||||
VulkanMemoryAllocator::get_from_world(world),
|
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<Cube>>()
|
||||||
|
.iter(&world)
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<Transform>>();
|
||||||
|
let cube_transform_uniform = Transform::create_buffer(
|
||||||
VulkanMemoryAllocator::get_from_world(world),
|
VulkanMemoryAllocator::get_from_world(world),
|
||||||
&state.obj_instances,
|
&cube_transforms,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
state
|
state
|
||||||
|
@ -309,7 +282,7 @@ impl AsScene for MainScene {
|
||||||
&VulkanDescriptorSetAllocator::get_from_world(world),
|
&VulkanDescriptorSetAllocator::get_from_world(world),
|
||||||
pipeline,
|
pipeline,
|
||||||
&state.obj,
|
&state.obj,
|
||||||
&obj_transform_uniform,
|
&cube_transform_uniform,
|
||||||
vec![
|
vec![
|
||||||
camera_uniform.clone() as Arc<dyn AsDescriptorSet>,
|
camera_uniform.clone() as Arc<dyn AsDescriptorSet>,
|
||||||
state
|
state
|
||||||
|
@ -400,3 +373,89 @@ impl AsScene for MainScene {
|
||||||
self.state = None;
|
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::<Vec<_>>();
|
||||||
|
|
||||||
|
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::<Vec<_>>();
|
||||||
|
|
||||||
|
world.spawn_batch(cube_instances);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_velocity_system(mut query: Query<(&mut Transform, &Velocity)>, time: Res<Timer>) {
|
||||||
|
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>) {
|
||||||
|
timer.update();
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue