Load and save level

This commit is contained in:
2020-11-28 23:25:29 +01:00
parent 483645dcc5
commit 62ec222749
13 changed files with 305 additions and 47 deletions

View File

@@ -57,13 +57,17 @@ impl GameObject {
}
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Copy)]
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> {
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)
}
}

73
src/level.rs Normal file
View File

@@ -0,0 +1,73 @@
use std::{error::Error, io::{BufReader, BufWriter}};
use std::fs::File;
use serde_derive::{Deserialize, Serialize};
use crate::{TestGame, gameobject::GameObjectHandle, vulkan::{MeshHandle, VulkanRenderer}};
#[derive(Debug, Serialize, Deserialize)]
struct MeshJson {
path: String
}
#[derive(Debug, Serialize, Deserialize)]
struct ObjectJson {
mesh_index: usize,
position: [f32; 3],
rotation: [f32; 4],
scale: [f32; 3]
}
#[derive(Debug, Serialize, Deserialize)]
struct LevelJson {
meshes: Vec<MeshJson>,
objects: Vec<ObjectJson>
}
pub fn load_level(path: &str, game: &mut TestGame, renderer: &mut VulkanRenderer) -> Result<Vec<GameObjectHandle>, Box<dyn Error>> {
let file = File::open(path)?;
let reader = BufReader::new(file);
let level_json: LevelJson = serde_json::from_reader(reader)?;
let meshes: Vec<MeshHandle> = level_json.meshes.iter().map(|json_mesh| {
let mesh_handles = game.load_gltf(renderer, &json_mesh.path);
// TODO: Add empty parent GO instead of just loading the first mesh
mesh_handles[0].clone()
}).collect();
let objects: Vec<GameObjectHandle> = level_json.objects.iter().map(|json_obj| {
let mut handle = game.add_game_object(renderer, meshes[json_obj.mesh_index].clone());
let game_object = handle.get_game_object_mut(renderer).unwrap();
game_object.position = json_obj.position.into();
game_object.rotation = json_obj.rotation.into();
game_object.scale = json_obj.scale.into();
handle
}).collect();
Ok(objects)
}
pub fn save_level(path: &str, game: &mut TestGame, renderer: &mut VulkanRenderer) -> Result<(), Box<dyn Error>> {
let meshes = game.meshes.iter().map(|mesh_handle| {
MeshJson {
path: mesh_handle.original_path.to_string()
}
}).collect();
let objects = game.game_objects.iter().map(|game_object_handle| {
let game_object = game_object_handle.get_game_object(renderer).unwrap();
ObjectJson {
mesh_index: game_object_handle.object_index,
position: game_object.position.into(),
rotation: game_object.rotation.into(),
scale: game_object.scale.into()
}
}).collect();
let level_json = LevelJson {
meshes,
objects
};
let file = File::create(path)?;
let writer = BufWriter::new(file);
serde_json::to_writer_pretty(writer, &level_json)?;
Ok(())
}

View File

@@ -1,4 +1,7 @@
use cgmath::{Matrix4, vec3, Vector3, Vector4};
extern crate serde_json;
use cgmath::{Matrix4, Vector3, Vector4};
use level::{load_level, save_level};
use winit::event::Event;
use crate::config::{LogConfig, RenderConfig};
@@ -15,8 +18,9 @@ mod mesh;
mod gameobject;
mod player;
mod pipelines;
mod level;
struct TestGame {
pub struct TestGame {
input: InputState,
player: Player,
meshes: Vec<MeshHandle>,
@@ -35,7 +39,7 @@ impl TestGame {
meshes: vec![],
game_objects: vec![],
log_config,
texture_index_counter: 1,
texture_index_counter: 0,
last_time: 0.0,
components: vec![],
}
@@ -66,7 +70,12 @@ impl Game for TestGame {
}
if self.input.button_just_released("test") {
renderer.game_data.use_line_pipeline = !renderer.game_data.use_line_pipeline;
println!("Saving...");
save_level("levels/test.lvl", self, renderer).unwrap();
println!("Clearing level...");
self.clear_level(renderer);
println!("Loading...");
load_level("levels/test.lvl", self, renderer).unwrap();
}
if self.input.button_just_pressed("reload_shaders") {
@@ -105,15 +114,9 @@ fn _matrix_vector_mul(matrix: &Matrix4<f32>, vector: &Vector3<f32>) -> Vector3<f
impl TestGame {
fn game_start(self: &mut Self, renderer: &mut VulkanRenderer) {
// let cube = self.add_from_gltf(renderer, "models/box.glb");
// cube.get_game_object(renderer).unwrap().position = vec3(3.0, 4.0, 5.0);
//
// let sphere = self.add_from_gltf(renderer, "models/sphere.glb");
// sphere.get_game_object(renderer).unwrap().position = vec3(0.0, 0.0, 0.0);
let plane = self.add_from_gltf(renderer, "models/plane.glb");
plane.get_game_object(renderer).unwrap().position = vec3(0.0, -1.0, 0.0);
// let plane_mesh = self.load_gltf(renderer, "models/plane.gltf");
// self.add_game_object(renderer, plane_mesh[0].clone());
load_level("levels/test.lvl", self, renderer).unwrap();
println!("Game loaded!");
}
@@ -141,8 +144,9 @@ impl TestGame {
index: mesh_id,
diffuse_handle: diffuse_id,
normal_handle: normal_id,
original_path: gltf_path.to_string()
};
self.meshes.push(mesh_handle);
self.meshes.push(mesh_handle.clone());
mesh_handles.push(mesh_handle);
}
@@ -153,16 +157,18 @@ impl TestGame {
mesh_handles
}
fn add_from_gltf(&mut self, renderer: &mut VulkanRenderer, path: &str) -> &mut GameObjectHandle {
let meshes = self.load_gltf(renderer, path);
self.add_game_object(renderer, *meshes.first().unwrap())
}
fn add_game_object(&mut self, renderer: &mut VulkanRenderer, mesh: MeshHandle) -> &mut GameObjectHandle {
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, 0);
self.game_objects.push(obj_handle);
self.game_objects.last_mut().unwrap()
self.game_objects.last().unwrap().clone()
}
fn clear_level(&mut self, renderer: &mut VulkanRenderer) {
self.game_objects.clear();
self.meshes.clear();
self.texture_index_counter = 0;
renderer.clear_all();
}
}

View File

@@ -168,7 +168,7 @@ impl Drawcall for LineShader {
game_data.line_push_constants.clone()).unwrap();
}
fn create_descriptor_set(self: &Self, game_object: &mut GameObject, renderer: &VulkanRenderer) {
fn create_descriptor_set(self: &Self, _game_object: &mut GameObject, _renderer: &VulkanRenderer) {
}

View File

@@ -4,7 +4,7 @@ use std::sync::Arc;
use std::time::SystemTime;
use cgmath::{Matrix4, SquareMatrix};
use image::{ImageBuffer, ImageFormat, Rgb, Rgba};
use image::{ImageBuffer, Rgb, Rgba};
use image::buffer::ConvertBuffer;
use vulkano::{command_buffer::CommandBuffer, buffer::{BufferUsage, CpuAccessibleBuffer}, image::{ImageLayout, MipmapsCount}};
use vulkano::command_buffer::{AutoCommandBuffer, AutoCommandBufferBuilder, DynamicState};
@@ -67,11 +67,12 @@ pub struct Mesh {
pub index_buffer: Arc<CpuAccessibleBuffer<[u32]>>,
}
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Clone)]
pub struct MeshHandle {
pub index: usize,
pub diffuse_handle: TextureHandle,
pub normal_handle: TextureHandle,
pub original_path: String
}
pub(crate) type TextureHandle = usize;
@@ -274,23 +275,6 @@ impl VulkanRenderer {
Box::new(LineShader::new(device.clone(), render_pass.clone(), line_vertex_buffer)),
];
let default_tex = {
let image = image::load_from_memory_with_format(include_bytes!("../models/missing-texture.jpg"),
ImageFormat::Jpeg).unwrap().to_rgba8();
let image_data = image.into_raw().clone();
let (image_view, future) = ImmutableImage::from_iter(
image_data.iter().cloned(),
Dimensions::Dim2d { width: 128, height: 128 },
Format::R8G8B8A8Unorm,
queue.clone(),
).unwrap();
future.flush().unwrap();
image_view
};
// Dynamic viewports allow us to recreate just the viewport when the window is resized
// Otherwise we would have to recreate the whole pipeline.
let mut dynamic_state = DynamicState { line_width: None, viewports: None, scissors: None, compare_mask: None, write_mask: None, reference: None };
@@ -321,10 +305,6 @@ impl VulkanRenderer {
).unwrap());
}
data.textures.push(default_tex);
// In the loop below we are going to submit commands to the GPU. Submitting a command produces
// an object that implements the `GpuFuture` trait, which holds the resources for as long as
// they are in use by the GPU.
@@ -539,6 +519,12 @@ impl VulkanRenderer {
object_index: self.game_data.game_objects.len() - 1
}
}
pub fn clear_all(&mut self) {
self.game_data.game_objects.clear();
self.game_data.meshes.clear();
self.game_data.textures.clear();
}
}
pub fn start_event_loop(mut renderer: VulkanRenderer, mut game: Box<dyn Game>, event_loop: EventLoop<()>) {