From ba172ea3325caef0d1f8e34d1ed583f8a3d21d0d Mon Sep 17 00:00:00 2001 From: Asuro Date: Thu, 14 Oct 2021 05:30:55 +0200 Subject: [PATCH] remove game object handles --- src/game/level.rs | 11 ++-- src/game/mod.rs | 59 ++++++++++-------- src/game/player.rs | 4 +- src/vulkan/gameobject.rs | 21 ++----- src/vulkan/mod.rs | 129 ++++++++++++++++++++------------------- 5 files changed, 110 insertions(+), 114 deletions(-) diff --git a/src/game/level.rs b/src/game/level.rs index 3b9948b..5596ae8 100644 --- a/src/game/level.rs +++ b/src/game/level.rs @@ -3,7 +3,7 @@ use std::fs::File; use serde_derive::{Deserialize, Serialize}; -use crate::{vulkan::{MeshHandle, VulkanRenderer, gameobject::GameObjectHandle}}; +use crate::vulkan::{MeshHandle, VulkanRenderer, gameobject::GameObjectHandle}; use crate::game::TestGame; #[derive(Debug, Serialize, Deserialize)] @@ -38,8 +38,8 @@ pub fn load_level(path: &str, game: &mut TestGame, renderer: &mut VulkanRenderer let objects: Vec = level_json.objects.iter().filter_map(|json_obj| { // TODO: Parenting if let Some(mesh_index) = json_obj.mesh_index { - let mut handle = game.add_game_object(renderer, meshes[mesh_index].clone()); - let game_object = handle.get_game_object_mut(renderer).unwrap(); + let handle = game.add_game_object(renderer, meshes[mesh_index].clone()); + let game_object = &mut game.game_objects[handle]; game_object.position = json_obj.position.into(); game_object.rotation = json_obj.rotation.into(); game_object.scale = json_obj.scale.into(); @@ -60,11 +60,10 @@ pub fn save_level(path: &str, game: &mut TestGame, renderer: &mut VulkanRenderer } }).collect(); - let objects = game.game_objects.iter().filter_map(|game_object_handle| { - let game_object = game_object_handle.get_game_object(renderer).unwrap(); + let objects = game.game_objects.iter().enumerate().filter_map(|(i, game_object)| { if game_object.pipeline_index != 0 { return None; } Some(ObjectJson { - mesh_index: Some(game_object_handle.object_index), + mesh_index: Some(i), position: game_object.position.into(), rotation: game_object.rotation.into(), scale: game_object.scale.into() diff --git a/src/game/mod.rs b/src/game/mod.rs index 1c8bf63..d0a7b81 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -3,6 +3,7 @@ use cgmath::{Deg, Euler, Quaternion, vec3}; use glyph_brush::{BrushAction, BrushError, GlyphBrush, GlyphBrushBuilder, GlyphVertex, Rectangle, Section, Text}; use glyph_brush::ab_glyph::FontArc; use vulkano::format::Format; +use vulkano::image::Dimensions; use vulkano::sampler::{Filter, SamplerAddressMode}; use winit::event::Event; @@ -11,7 +12,7 @@ use player::Player; use crate::{config::LogConfig, vulkan}; use crate::input::InputState; -use crate::vulkan::{Game, Mesh, MeshHandle, TextVertex, Texture, Vertex, VulkanRenderer}; +use crate::vulkan::{Game, MeshHandle, TextVertex, Texture, Vertex, VulkanRenderer}; use crate::vulkan::gameobject::{GameObject, GameObjectHandle, Updatable}; use crate::vulkan::mesh::{self, CPUMesh, CPUVertex}; use crate::vulkan::pipelines::vs::ty::ObjectUniformData; @@ -22,7 +23,7 @@ mod level; pub struct TestGame { pub input: InputState, pub player: Player, - pub game_objects: Vec, + pub game_objects: Vec, pub text_objects: Vec, pub log_config: LogConfig, pub texture_index_counter: usize, @@ -33,6 +34,10 @@ pub struct TestGame { } impl Game for TestGame { + fn get_game_objects(&self) -> &Vec { + &self.game_objects + } + fn on_window_event(self: &mut Self, event: &Event<()>) { self.input.on_window_event(event); } @@ -45,9 +50,11 @@ impl Game for TestGame { // Component update let input = &self.input; + let objs = &mut self.game_objects; let components = &mut self.components; + components.iter_mut().for_each(|component| { - component.update(frame_time, &input, renderer); + component.update(frame_time, &input, renderer, objs); }); // User interaction @@ -76,13 +83,13 @@ impl Game for TestGame { if self.input.button_just_pressed("test") { // self.paused = !self.paused; - self.text_objects[0].update_text("yeet", 100.0, renderer); + self.text_objects[0].update_text(":)", 200.0, renderer, &mut self.game_objects); } // Custom game object stuff let light_pos = vec3(2.0, 0.5, 2.0); if !self.paused { - self.player.update(frame_time, &self.input, renderer); + self.player.update(frame_time, &self.input, renderer, &mut self.game_objects); } // End frame @@ -173,14 +180,13 @@ impl TestGame { } pub fn add_game_object(&mut self, renderer: &mut VulkanRenderer, mesh: MeshHandle) -> GameObjectHandle { - let obj = GameObject::new(mesh); - let obj_handle = renderer.add_game_object(obj); - self.game_objects.push(obj_handle); - self.game_objects.last().unwrap().clone() + let mut obj = GameObject::new(mesh); + obj.init_descriptor_sets(renderer); + self.game_objects.push(obj); + self.game_objects.len() - 1 } fn convert_vertices(vertex_data: GlyphVertex) -> Vec { - // println!("VD: {:?}", vertex_data); let result = vec![ TextVertex { position: [vertex_data.pixel_coords.min.x, vertex_data.pixel_coords.min.y, 0.], uv: [vertex_data.tex_coords.min.x, vertex_data.tex_coords.min.y] }, TextVertex { position: [vertex_data.pixel_coords.min.x, vertex_data.pixel_coords.max.y, 0.], uv: [vertex_data.tex_coords.min.x, vertex_data.tex_coords.max.y] }, @@ -208,9 +214,11 @@ impl TestGame { self.texture_index_counter += 1; }, Self::convert_vertices), self.texture_index_counter - 1, + uploaded_texture.as_mut(), + None, None, renderer); - + TextObject { brush: glyph_brush, texture: uploaded_texture.unwrap(), @@ -233,28 +241,20 @@ pub fn print_quat_as_euler(quat: Quaternion) { pub fn update_text_texture(old_texture: Option<&mut Texture>, renderer: &mut VulkanRenderer, rect: Rectangle, text_data: &[u8]) -> (Option, u32) { let size = u32::max(rect.width(), rect.height()); - let final_texture; + let mut final_texture = None; if let Some(old_tex) = old_texture { - println!("rect: {:?}", rect); - final_texture = renderer.update_texture(old_tex, text_data, [rect.width(), rect.height(), 1], [rect.min[0], rect.min[1], 0], renderer.device.clone()); - if let Some(_tex) = final_texture.clone() { - println!("Updating texture size. TODO!"); - // renderer.game_data.textures.push(tex.clone()); - // go_handle.get_game_object_mut(renderer).unwrap().textures.texture_index = renderer.game_data.textures.len() - 1; - // renderer.update_descriptor_set(&mut go_handle); - } + renderer.update_texture(old_tex, text_data, [rect.width(), rect.height(), 1], [rect.min[0], rect.min[1], 0], renderer.device.clone()); } else { - println!("Init size: {:?}", rect); let tex = renderer.upload_texture(text_data, size, size, Format::R8Unorm, Filter::Nearest, SamplerAddressMode::ClampToEdge, renderer.device.clone()); renderer.game_data.textures.push(tex.clone()); - final_texture = Some(tex) + final_texture = Some(tex); } (final_texture, size) } -pub fn process_text_brush_data(result: Result>, BrushError>, texture_index: usize, mesh_index: Option, renderer: &mut VulkanRenderer) -> Option { +pub fn process_text_brush_data(result: Result>, BrushError>, texture_index: usize, texture: Option<&mut Texture>, mesh_index: Option, game_object: Option<&mut GameObject>, renderer: &mut VulkanRenderer) -> Option { match result { Ok(BrushAction::Draw(quads)) => { let mut final_vertices = vec![]; @@ -289,7 +289,11 @@ pub fn process_text_brush_data(result: Result>, Brus } }, Ok(BrushAction::ReDraw) => None, - Err(BrushError::TextureTooSmall { suggested }) => { println!("texture too small, suggested: {:?}!", suggested); None }, + Err(BrushError::TextureTooSmall { suggested }) => { + let size = Dimensions::Dim2d { width: suggested.0, height: suggested.1 }; + renderer.resize_texture(game_object.unwrap(), texture.unwrap(), size, renderer.device.clone()); + None + }, } } @@ -301,19 +305,20 @@ pub struct TextObject { } impl TextObject { - pub fn update_text(&mut self, new_text: &str, new_size: f32, renderer: &mut VulkanRenderer) { + pub fn update_text(&mut self, new_text: &str, new_size: f32, renderer: &mut VulkanRenderer, game_objects: &mut Vec) { self.brush.queue(Section::default().add_text(Text::new(new_text).with_scale(new_size))); let mut old_texture = self.texture.clone(); let mut new_texture = None; let mut new_size = None; - let mesh_index = self.game_object.get_game_object_mut(renderer).unwrap().mesh_index; + let go = &mut game_objects[self.game_object]; + let mesh_index = go.mesh_index; process_text_brush_data(self.brush.process_queued(|rect, text_data| { let (t, s) = update_text_texture(Some(&mut old_texture), renderer, rect, text_data); new_texture = t; new_size = Some(s); - }, TestGame::convert_vertices), 420, Some(mesh_index), renderer); + }, TestGame::convert_vertices), 420, Some(&mut self.texture), Some(mesh_index), Some(go), renderer); if let Some(tex) = new_texture { self.texture = tex; } diff --git a/src/game/player.rs b/src/game/player.rs index d733765..de61bda 100644 --- a/src/game/player.rs +++ b/src/game/player.rs @@ -178,7 +178,7 @@ pub fn intersect_triangle(ray_origin: Vector3, ray_direction: Vector3, } impl Updatable for Player { - fn update(&mut self, delta_time: f32, input: &InputState, renderer: &mut VulkanRenderer) { + fn update(&mut self, delta_time: f32, input: &InputState, renderer: &mut VulkanRenderer, game_objects: &mut Vec) { // Edit mode if input.button_just_pressed("toggle_edit") { if self.movement_mode == FirstPerson { @@ -190,7 +190,7 @@ impl Updatable for Player { if input.button_just_pressed("select") { let ray_direction = self.camera.viewport_pos_to_ray_direction(input.mouse_position, renderer.game_data.dimensions).unwrap(); - for game_object in &mut renderer.game_data.game_objects { + for game_object in game_objects { let mesh = &renderer.game_data.meshes[game_object.mesh_index]; if let Some(_) = intersection_distance(self.camera.position, ray_direction, mesh, game_object) { game_object.is_selected = !game_object.is_selected; diff --git a/src/vulkan/gameobject.rs b/src/vulkan/gameobject.rs index 541a880..52b03d9 100644 --- a/src/vulkan/gameobject.rs +++ b/src/vulkan/gameobject.rs @@ -39,6 +39,10 @@ impl GameObject { descriptor_sets: vec![], is_selected: false, pipeline_index: mesh.pipeline_index } } + pub fn init_descriptor_sets(&mut self, renderer: &mut VulkanRenderer) { + self.descriptor_sets = renderer.pipelines[self.pipeline_index].create_descriptor_set(&self.textures, renderer); + } + pub fn _set_position(&mut self, x: f32, y: f32, z: f32) { self.position.x = x; self.position.y = y; @@ -80,21 +84,8 @@ impl GameObject { } } -#[derive(Debug, Clone, Copy)] -pub struct GameObjectHandle { - pub object_index: usize -} - -impl GameObjectHandle { - pub fn get_game_object<'a>(&self, renderer: &'a VulkanRenderer) -> Option<&'a GameObject> { - renderer.game_data.game_objects.get(self.object_index) - } - - pub fn get_game_object_mut<'a>(&mut self, renderer: &'a mut VulkanRenderer) -> Option<&'a mut GameObject> { - renderer.game_data.game_objects.get_mut(self.object_index) - } -} +pub type GameObjectHandle = usize; pub trait Updatable { - fn update(&mut self, delta_time: f32, input: &InputState, renderer: &mut VulkanRenderer); + fn update(&mut self, delta_time: f32, input: &InputState, renderer: &mut VulkanRenderer, game_objects: &mut Vec); } diff --git a/src/vulkan/mod.rs b/src/vulkan/mod.rs index 0b95e1c..4f48436 100644 --- a/src/vulkan/mod.rs +++ b/src/vulkan/mod.rs @@ -29,7 +29,7 @@ use pipelines::{DefaultShader, TextShader}; use pipelines::vs; use crate::config::RenderConfig; -use crate::vulkan::gameobject::{GameObject, GameObjectHandle}; +use crate::vulkan::gameobject::GameObject; use self::mesh::CPUVertex; @@ -77,6 +77,8 @@ pub trait Game { fn on_window_event(self: &mut Self, event: &Event<()>); fn update(self: &mut Self, renderer: &mut VulkanRenderer) -> vs::ty::ObjectUniformData; + + fn get_game_objects(&self) -> &Vec; } pub struct Mesh { @@ -108,7 +110,6 @@ pub struct GameData { pub recreate_pipeline: bool, pub dimensions: [u32; 2], pub shutdown: bool, - pub game_objects: Vec, pub meshes: Vec>, pub meshes_text: Vec>, pub textures: Vec, @@ -149,7 +150,6 @@ impl VulkanRenderer { dimensions: [0, 0], meshes: vec![], meshes_text: vec![], - game_objects: vec![], textures: vec![], }; @@ -310,7 +310,7 @@ impl VulkanRenderer { }, events_loop) } - fn create_command_buffer(self: &mut Self, fb_index: usize, uniform_buffer_data: vs::ty::ObjectUniformData) -> Arc { + fn create_command_buffer(self: &mut Self, fb_index: usize, uniform_buffer_data: vs::ty::ObjectUniformData, game_objects: &Vec) -> Arc { // General setup let mut builder = AutoCommandBufferBuilder::primary_simultaneous_use(self.device.clone(), self.queue.family()).unwrap(); builder.update_buffer(self.uniform_buffers[fb_index].clone(), uniform_buffer_data).unwrap(); @@ -323,7 +323,7 @@ impl VulkanRenderer { // Draw meshes etc. let mut index = 0; for pipeline in &self.pipelines { - pipeline.draw(&mut builder, fb_index, self.game_data.game_objects.iter().filter(|go| go.pipeline_index == index).collect(), &self.game_data, &self.dynamic_state); + pipeline.draw(&mut builder, fb_index, game_objects.iter().filter(|go| go.pipeline_index == index).collect(), &self.game_data, &self.dynamic_state); index += 1; } @@ -332,13 +332,7 @@ impl VulkanRenderer { Arc::new(builder.build().unwrap()) } - pub fn update_descriptor_set(&mut self, game_object_handle: &mut GameObjectHandle) { - let pipeline_index = game_object_handle.get_game_object_mut(self).unwrap().pipeline_index; - let textures = game_object_handle.get_game_object_mut(self).unwrap().textures.clone(); - self.pipelines[pipeline_index].create_descriptor_set(&textures, self); - } - - pub fn render_loop(self: &mut Self, new_ubo: vs::ty::ObjectUniformData) { + pub fn render_loop(self: &mut Self, new_ubo: vs::ty::ObjectUniformData, game_objects: &Vec) { // cleanup previous frame self.previous_frame_end.as_mut().unwrap().cleanup_finished(); @@ -398,7 +392,7 @@ impl VulkanRenderer { Err(err) => panic!("{:?}", err) }; - let command_buffer = self.create_command_buffer(fb_index, new_ubo).clone(); + let command_buffer = self.create_command_buffer(fb_index, new_ubo, game_objects).clone(); let future = self.previous_frame_end.take().unwrap() .join(acquire_future) @@ -574,24 +568,7 @@ impl VulkanRenderer { Texture { image: image_view, sampler } } - pub fn update_texture(&mut self, texture: &mut Texture, new_data: &[u8], new_data_dimensions: [u32; 3], new_data_offset: [u32; 3], device: Arc) -> Option { - let new_image_usage = ImageUsage { - transfer_destination: true, - transfer_source: true, - sampled: true, - ..ImageUsage::none() - }; - - // let (new_image_view, new_image_initializer) = ImmutableImage::uninitialized( - // device.clone(), - // Dimensions::Dim2d { width: texture.image.dimensions().width(), height: texture.image.dimensions().height() }, - // texture.image.format(), - // texture.image.mipmap_levels(), - // new_image_usage, - // ImageLayout::ShaderReadOnlyOptimal, - // device.active_queue_families(), - // ).unwrap(); - + pub fn update_texture(&mut self, texture: &mut Texture, new_data: &[u8], new_data_dimensions: [u32; 3], new_data_offset: [u32; 3], device: Arc) { let old_sub_image = SubImage::new( texture.image.clone(), 0, @@ -601,30 +578,8 @@ impl VulkanRenderer { ImageLayout::ShaderReadOnlyOptimal, ); - // let new_sub_image = SubImage::new( - // Arc::new(new_image_initializer), - // 0, - // new_image_view.mipmap_levels(), - // 0, - // 1, - // ImageLayout::ShaderReadOnlyOptimal, - // ); - let mut cbb = AutoCommandBufferBuilder::new(device.clone(), self.queue.family()).unwrap(); - // cbb.copy_image( - // old_sub_image.clone(), - // [0, 0, 0], - // 0, - // 0, - // new_sub_image.clone(), - // [0, 0, 0], - // 0, - // 0, - // old_sub_image.dimensions().width_height_depth(), - // 1 - // ).unwrap(); - let upload_source = CpuAccessibleBuffer::from_iter( device.clone(), BufferUsage::transfer_source(), @@ -647,22 +602,68 @@ impl VulkanRenderer { let future = cb.execute(self.queue.clone()).unwrap(); future.flush().unwrap(); - - // Texture { image: texture.image.clone(), sampler: texture.sampler.clone() } - None } - pub fn add_game_object(self: &mut Self, mut game_object: GameObject) -> GameObjectHandle { - game_object.descriptor_sets = self.pipelines[game_object.pipeline_index].create_descriptor_set(&game_object.textures, self); - self.game_data.game_objects.push(game_object); + pub fn resize_texture(&mut self, game_object: &mut GameObject, old_texture: &mut Texture, new_size: Dimensions, device: Arc) { + let new_image_usage = ImageUsage { + transfer_destination: true, + transfer_source: true, + sampled: true, + ..ImageUsage::none() + }; + + let (new_image_view, new_image_initializer) = ImmutableImage::uninitialized( + device.clone(), + new_size, + old_texture.image.format(), + old_texture.image.mipmap_levels(), + new_image_usage, + ImageLayout::ShaderReadOnlyOptimal, + device.active_queue_families(), + ).unwrap(); - GameObjectHandle { - object_index: self.game_data.game_objects.len() - 1 - } + let old_sub_image = SubImage::new( + old_texture.image.clone(), + 0, + 1, + 0, + 1, + ImageLayout::ShaderReadOnlyOptimal, + ); + + let new_sub_image = SubImage::new( + Arc::new(new_image_initializer), + 0, + new_image_view.mipmap_levels(), + 0, + 1, + ImageLayout::ShaderReadOnlyOptimal, + ); + + let mut cbb = AutoCommandBufferBuilder::new(device.clone(), self.queue.family()).unwrap(); + + cbb.copy_image( + old_sub_image.clone(), + [0, 0, 0], + 0, + 0, + new_sub_image.clone(), + [0, 0, 0], + 0, + 0, + old_sub_image.dimensions().width_height_depth(), + 1 + ).unwrap(); + + let cb = cbb.build().unwrap(); + let future = cb.execute(self.queue.clone()).unwrap(); + future.flush().unwrap(); + + old_texture.image = new_image_view; + game_object.init_descriptor_sets(self); } pub fn clear_all(&mut self) { - self.game_data.game_objects.clear(); self.game_data.meshes.clear(); self.game_data.textures.clear(); } @@ -682,7 +683,7 @@ pub fn start_event_loop(mut renderer: VulkanRenderer, mut game: Box, e }, Event::RedrawEventsCleared => { let ubo = game.update(&mut renderer); - renderer.render_loop(ubo); + renderer.render_loop(ubo, &game.get_game_objects()); }, _ => {} }