remove game object handles

This commit is contained in:
2021-10-14 05:30:55 +02:00
parent ea9490ad3a
commit ba172ea332
5 changed files with 110 additions and 114 deletions

View File

@@ -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<GameObjectHandle> = 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()

View File

@@ -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<GameObjectHandle>,
pub game_objects: Vec<GameObject>,
pub text_objects: Vec<TextObject>,
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<GameObject> {
&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<TextVertex> {
// 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<f32>) {
pub fn update_text_texture(old_texture: Option<&mut Texture>, renderer: &mut VulkanRenderer, rect: Rectangle<u32>, text_data: &[u8]) -> (Option<Texture>, 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<BrushAction<Vec<TextVertex>>, BrushError>, texture_index: usize, mesh_index: Option<usize>, renderer: &mut VulkanRenderer) -> Option<MeshHandle> {
pub fn process_text_brush_data(result: Result<BrushAction<Vec<TextVertex>>, BrushError>, texture_index: usize, texture: Option<&mut Texture>, mesh_index: Option<usize>, game_object: Option<&mut GameObject>, renderer: &mut VulkanRenderer) -> Option<MeshHandle> {
match result {
Ok(BrushAction::Draw(quads)) => {
let mut final_vertices = vec![];
@@ -289,7 +289,11 @@ pub fn process_text_brush_data(result: Result<BrushAction<Vec<TextVertex>>, 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<GameObject>) {
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;
}

View File

@@ -178,7 +178,7 @@ pub fn intersect_triangle(ray_origin: Vector3<f32>, ray_direction: Vector3<f32>,
}
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<GameObject>) {
// 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;

View File

@@ -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<GameObject>);
}

View File

@@ -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<GameObject>;
}
pub struct Mesh<V> {
@@ -108,7 +110,6 @@ pub struct GameData {
pub recreate_pipeline: bool,
pub dimensions: [u32; 2],
pub shutdown: bool,
pub game_objects: Vec<GameObject>,
pub meshes: Vec<Mesh<Vertex>>,
pub meshes_text: Vec<Mesh<TextVertex>>,
pub textures: Vec<Texture>,
@@ -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<AutoCommandBuffer> {
fn create_command_buffer(self: &mut Self, fb_index: usize, uniform_buffer_data: vs::ty::ObjectUniformData, game_objects: &Vec<GameObject>) -> Arc<AutoCommandBuffer> {
// 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<GameObject>) {
// 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<Device>) -> Option<Texture> {
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<Device>) {
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<Device>) {
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<dyn Game>, e
},
Event::RedrawEventsCleared => {
let ubo = game.update(&mut renderer);
renderer.render_loop(ubo);
renderer.render_loop(ubo, &game.get_game_objects());
},
_ => {}
}