diff --git a/models/sphere.blend b/models/sphere.blend new file mode 100644 index 0000000..3b7bf68 Binary files /dev/null and b/models/sphere.blend differ diff --git a/models/sphere.glb b/models/sphere.glb new file mode 100644 index 0000000..91237f3 Binary files /dev/null and b/models/sphere.glb differ diff --git a/src/gameobject.rs b/src/gameobject.rs new file mode 100644 index 0000000..506af77 --- /dev/null +++ b/src/gameobject.rs @@ -0,0 +1,47 @@ +use cgmath::{Matrix4, SquareMatrix, Vector3, vec3}; +use crate::vulkan::{MeshHandle, VulkanRenderer}; +use crate::input::InputState; + +pub struct GameObject { + pub mesh_index: usize, + pub texture_index: usize, + pub model_matrix: Matrix4, +} + +impl GameObject { + pub fn new(mesh: MeshHandle, texture_index: usize) -> GameObject { + GameObject { mesh_index: mesh, texture_index, model_matrix: Matrix4::identity() } + } + + pub fn set_position(&mut self, x: f32, y: f32, z: f32) { + self.model_matrix.w.x = x; + self.model_matrix.w.y = y; + self.model_matrix.w.z = z; + } + + pub fn get_position(&self) -> Vector3 { + vec3(self.model_matrix.w.x, self.model_matrix.w.y, self.model_matrix.w.z) + } + + pub fn translate(&mut self, x: f32, y: f32, z: f32) { + self.model_matrix.w.x += x; + self.model_matrix.w.y += y; + self.model_matrix.w.z += z; + } + + pub fn update(&mut self, delta_time: f32, input: &InputState) { + if input.button_down("test") { + self.translate(delta_time as f32, 0.0, 0.0); + } + } +} + +pub struct GameObjectHandle { + pub object_index: usize +} + +impl GameObjectHandle { + pub fn get_game_object<'a>(&mut self, renderer: &'a mut VulkanRenderer) -> Option<&'a mut GameObject> { + renderer.game_data.game_objects.get_mut(self.object_index) + } +} \ No newline at end of file diff --git a/src/input.rs b/src/input.rs index 35fe6fc..b1c59b0 100644 --- a/src/input.rs +++ b/src/input.rs @@ -194,9 +194,9 @@ impl InputState { if self.log_config.input_events { let mods = mods_to_string(&KeyboardModifierState::from_deprecated_state(&input.modifiers)); if mods.len() > 0 { - println!("Keyboard {:?} {:?} {:?} + {:?}", device_id, input.state, &mods, input.scancode) + println!("Keyboard {:?} {:?} {:?} + {:?}", device_id, input.state, &mods, input.virtual_keycode) } else { - println!("Keyboard {:?} {:?} {:?}", device_id, input.state, input.scancode) + println!("Keyboard {:?} {:?} {:?}", device_id, input.state, input.virtual_keycode) } } @@ -352,6 +352,7 @@ impl InputState { let input = DigitalInput::Keyboard(KeyboardInput { scan_code, modifiers }); match state { ElementState::Pressed => { + if self.pressed_scan_codes.contains(&scan_code) { return; } self.input_events.insert(DigitalInputEvent::Pressed(input)); self.pressed_scan_codes.insert(scan_code); }, diff --git a/src/main.rs b/src/main.rs index ee45083..0c7c24c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,21 +3,25 @@ use winit::event::Event; use crate::config::LogConfig; use crate::input::InputState; -use crate::vulkan::{Game, GameObject, GameObjectHandle, LinePoint, MeshHandle, VulkanRenderer}; +use crate::vulkan::{Game, LinePoint, MeshHandle, VulkanRenderer}; use crate::vulkan::vs::ty::ObjectUniformData; +use crate::gameobject::{GameObject, GameObjectHandle}; mod vulkan; mod input; mod config; mod mesh; +mod gameobject; struct TestGame { input: InputState, cam_position: Vector3, cam_rotation: Quaternion, - test_meshes: Vec<(MeshHandle, usize)>, - cubes: Vec, + meshes: Vec<(MeshHandle, usize)>, + game_objects: Vec, log_config: LogConfig, + texture_index_counter: usize, + last_time: f32, } impl Game for TestGame { @@ -28,6 +32,13 @@ impl Game for TestGame { fn update(self: &mut Self, renderer: &mut VulkanRenderer) -> ObjectUniformData { self.input.frame_start(); let time = (renderer.game_data.start_time.elapsed().unwrap().as_micros() as f64 / 1000000.0) as f32; + let frame_time = time - self.last_time; + + let input = &self.input; + let objects = &mut self.game_objects; + objects.iter_mut().for_each(|game_object| { + game_object.get_game_object(renderer).unwrap().update(frame_time, &input); + }); // User interaction if self.input.button_just_released("quit") { @@ -39,12 +50,7 @@ impl Game for TestGame { } if self.input.button_down("print_framerate") { -// println!("{:.0} ms / {:.0} FPS", frame_time * 1000.0, 1.0 / frame_time); - } - - if self.input.button_just_pressed("test") { - println!("test"); - self.cubes = self.test_meshes.iter().map(|(mesh, tex_id)| renderer.add_game_object(GameObject::new(*mesh, *tex_id))).collect(); + println!("{:.0} ms / {:.0} FPS", frame_time * 1000.0, 1.0 / frame_time); } self.cam_rotation = self.cam_rotation * Quaternion::from_angle_y(Deg(self.input.get_axis("look_horizontal") * 0.05)); @@ -69,6 +75,7 @@ impl Game for TestGame { renderer.game_data.line_push_constants.view = view.into(); renderer.game_data.line_push_constants.projection = proj.into(); + self.last_time = time; self.input.frame_end(); ObjectUniformData { @@ -81,16 +88,34 @@ impl Game for TestGame { impl TestGame { fn game_start(self: &mut Self, renderer: &mut VulkanRenderer) { - let (meshes, textures) = mesh::load_mesh("models/box.gltf.glb", self.log_config.mesh_load_info).unwrap(); - self.test_meshes = meshes.into_iter().map(|m| { - let id = match m.texture_index { - Some(tex_id) => tex_id + 1, + self.load_gltf(renderer, "models/box.gltf.glb"); + self.load_gltf(renderer, "models/sphere.glb"); + + let cube = self.add_game_object(renderer, 0, 0); + cube.get_game_object(renderer).unwrap().set_position(0.0, 2.0, 0.0); + let sphere = self.add_game_object(renderer, 1, 0); + sphere.get_game_object(renderer).unwrap().set_position(2.0, 0.0, 0.0); + println!("Game loaded!"); + } + + fn load_gltf(&mut self, renderer: &mut VulkanRenderer, gltf_path: &str) { + let (meshes, textures) = mesh::load_mesh(gltf_path, self.log_config.mesh_load_info).unwrap(); + for cpu_mesh in meshes.into_iter() { + let id = match cpu_mesh.texture_index { + Some(tex_id) => tex_id + self.texture_index_counter, None => 0, }; - (renderer.upload_mesh(m), id) - }).collect(); + self.texture_index_counter += 1; + self.meshes.push((renderer.upload_mesh(cpu_mesh), id)); + } textures.iter().for_each(|tex| renderer.upload_texture(tex)); - println!("Game loaded!"); + } + + fn add_game_object(&mut self, renderer: &mut VulkanRenderer, mesh: MeshHandle, texture_index: usize) -> &mut GameObjectHandle { + let obj = GameObject::new(mesh, texture_index); + let obj_handle = renderer.add_game_object(obj); + self.game_objects.push(obj_handle); + self.game_objects.last_mut().unwrap() } } @@ -101,9 +126,11 @@ fn main() { input: InputState::new("config/input.toml", log_config), cam_rotation: Quaternion::one(), cam_position: Vector3::new(0.0, 3.0, -10.0), - test_meshes: vec![], - cubes: vec![], - log_config + meshes: vec![], + game_objects: vec![], + log_config, + texture_index_counter: 1, + last_time: 0.0 }; let line_count = 30; @@ -120,4 +147,4 @@ fn main() { game.game_start(&mut renderer); vulkan::start_event_loop(renderer, Box::new(game), event_loop); -} \ No newline at end of file +} diff --git a/src/vulkan.rs b/src/vulkan.rs index e73a35e..6426fcf 100644 --- a/src/vulkan.rs +++ b/src/vulkan.rs @@ -31,6 +31,7 @@ use line_vs::ty::LinePushConstants; use vs::ty::PushConstants; use crate::mesh::CPUMesh; +use crate::gameobject::{GameObject, GameObjectHandle}; const VALIDATION_LAYERS: &[&str] = &[ "VK_LAYER_LUNARG_standard_validation" @@ -62,13 +63,6 @@ pub struct Mesh { index_buffer: Arc>, } -pub struct GameObject { - pub mesh_index: usize, - pub texture_index: usize, - pub model_matrix: Matrix4, -} - -pub(crate) type GameObjectHandle = usize; pub(crate) type MeshHandle = usize; pub struct GameData { @@ -457,9 +451,11 @@ impl VulkanRenderer { self.game_data.textures.push(image_view); } - pub fn add_game_object(self: &mut Self, game_object: GameObject) -> usize { + pub fn add_game_object(self: &mut Self, game_object: GameObject) -> GameObjectHandle { self.game_data.game_objects.push(game_object); - self.game_data.game_objects.len() - 1 + GameObjectHandle { + object_index: self.game_data.game_objects.len() - 1 + } } } @@ -573,9 +569,3 @@ fn create_pipeline(device: Arc, re return Some(pipeline); } - -impl GameObject { - pub fn new(mesh: MeshHandle, texture_index: usize) -> GameObject { - GameObject { mesh_index: mesh, texture_index, model_matrix: Matrix4::identity() } - } -} \ No newline at end of file