diff options
| author | Irene Knapp <ireneista@irenes.space> | 2026-07-20 20:43:48 -0700 |
|---|---|---|
| committer | Irene Knapp <ireneista@irenes.space> | 2026-07-20 20:43:48 -0700 |
| commit | 3ac1e5e5a9ebcb4beb2bfe149dd5095f2250f60d (patch) | |
| tree | d409eb8dfcca1b56dffe8c143a2c9028818d6d5d /src | |
| parent | 365c2f8bdc217f33264e3aed394f67840a4c075d (diff) | |
yay Force-Push: yes Change-Id: Icb715692286c8560532ab73d32a49be8f485d790
Diffstat (limited to 'src')
| -rw-r--r-- | src/error.rs | 42 | ||||
| -rw-r--r-- | src/graphics_window_dressing.rs | 29 | ||||
| -rw-r--r-- | src/main.rs | 10 | ||||
| -rw-r--r-- | src/model_loader.rs | 44 | ||||
| -rw-r--r-- | src/shader_data.rs | 29 |
5 files changed, 111 insertions, 43 deletions
diff --git a/src/error.rs b/src/error.rs index 729ff23..304ed74 100644 --- a/src/error.rs +++ b/src/error.rs @@ -115,6 +115,48 @@ impl From<png::DecodingError> for Error { } } +impl From<tobj::LoadError> for Error { + fn from(e: tobj::LoadError) -> Self { + Error { + message: format!("While loading model from .obj: {}", + match e + { + tobj::LoadError::OpenFileFailed => "Can't open file.", + tobj::LoadError::ReadError => "Can't read from file.", + tobj::LoadError::UnrecognizedCharacter => + "Syntax error: Invalid character.", + tobj::LoadError::PositionParseError => + "Syntax error describing a spatial position.", + tobj::LoadError::NormalParseError => + "Syntax error describing a normal vector.", + tobj::LoadError::TexcoordParseError => + "Syntax error describing texture coordinates.", + tobj::LoadError::FaceParseError => + "Syntax error describing which vertices form a face.", + tobj::LoadError::MaterialParseError => + "Syntax error describing a rendering material.", + tobj::LoadError::InvalidObjectName => + "Syntax error in the name of an object.", + tobj::LoadError::InvalidPolygon => + "Geometric error with an alleged polygon.", + tobj::LoadError::FaceVertexOutOfBounds => + "Geometric error with a vertex's location.", + tobj::LoadError::FaceTexCoordOutOfBounds => + "Geometric error with texture coordinates.", + tobj::LoadError::FaceNormalOutOfBounds => + "Geometric error with a normal vector.", + tobj::LoadError::FaceColorOutOfBounds => + "Geometric error with a vertex color (yes).", + tobj::LoadError::InvalidLoadOptionConfig => + "Invoked incorrectly by Surreality.", + tobj::LoadError::GenericFailure => + "The library's author didn't choose to tell us why.", + }) + } + } +} + + pub fn ignore_errors(mut body: impl FnMut() -> Result<()>) -> () { if let Err(e) = body() { eprintln!("Error: {}", e); diff --git a/src/graphics_window_dressing.rs b/src/graphics_window_dressing.rs index ce5ccda..e774177 100644 --- a/src/graphics_window_dressing.rs +++ b/src/graphics_window_dressing.rs @@ -3,7 +3,8 @@ use crate::error::*; use crate::graphics_permanent::{ PermanentGraphicsState, GraphicsStateForReinit, QueueFamilyIndices }; -use crate::shader_data::{ VERTICES, INDICES, Vertex, UniformBlock }; +use crate::model_loader::load_model; +use crate::shader_data::{ Vertex, UniformBlock }; use std::collections::BTreeSet; use std::io::Cursor; @@ -50,6 +51,7 @@ pub struct WindowDressing { index_buffer: vk::Buffer, index_buffer_memory: vk::DeviceMemory, + index_count: usize, texture_image: vk::Image, texture_image_memory: vk::DeviceMemory, @@ -137,11 +139,14 @@ impl WindowDressing { let (primary_command_pool, transient_command_pool) = init_command_pools(device, indices)?; + let (vertices, indices) = load_model()?; + let index_count = indices.len(); + let (vertex_buffer, vertex_buffer_memory) - = init_vertex_buffer(instance, physical_device, device, + = init_vertex_buffer(vertices, instance, physical_device, device, graphics_queue, &transient_command_pool)?; let (index_buffer, index_buffer_memory) - = init_index_buffer(instance, physical_device, device, + = init_index_buffer(indices, instance, physical_device, device, graphics_queue, &transient_command_pool)?; let (texture_image, texture_image_memory, texture_image_view) @@ -163,7 +168,7 @@ impl WindowDressing { let command_buffers = init_commands( device, &swapchain.extent, &framebuffers, &render_pass, &pipeline_layout, &pipeline, &vertex_buffer, &index_buffer, - &descriptor_sets, &primary_command_pool)?; + index_count, &descriptor_sets, &primary_command_pool)?; let concurrency = init_concurrency(device, &swapchain.images)?; @@ -181,6 +186,7 @@ impl WindowDressing { vertex_buffer_memory, index_buffer, index_buffer_memory, + index_count, texture_image, texture_image_memory, texture_image_view, @@ -250,7 +256,7 @@ impl WindowDressing { let command_buffers = init_commands( device, &swapchain.extent, &framebuffers, &render_pass, &pipeline_layout, &pipeline, &self.vertex_buffer, - &self.index_buffer, &descriptor_sets, + &self.index_buffer, self.index_count, &descriptor_sets, &self.primary_command_pool)?; self.concurrency.image_fences.resize(swapchain.images.len(), @@ -689,23 +695,23 @@ fn init_framebuffers(device: &Device, extent: &vk::Extent2D, } -fn init_vertex_buffer(instance: &Instance, +fn init_vertex_buffer(vertices: Vec<Vertex<f32>>, instance: &Instance, physical_device: &vk::PhysicalDevice, device: &Device, queue: &vk::Queue, command_pool: &vk::CommandPool) -> Result<(vk::Buffer, vk::DeviceMemory)> { init_buffer(instance, physical_device, device, queue, command_pool, - vk::BufferUsageFlags::VERTEX_BUFFER, &VERTICES) + vk::BufferUsageFlags::VERTEX_BUFFER, &vertices) } -fn init_index_buffer(instance: &Instance, +fn init_index_buffer(indices: Vec<u32>, instance: &Instance, physical_device: &vk::PhysicalDevice, device: &Device, queue: &vk::Queue, command_pool: &vk::CommandPool) -> Result<(vk::Buffer, vk::DeviceMemory)> { init_buffer(instance, physical_device, device, queue, command_pool, - vk::BufferUsageFlags::INDEX_BUFFER, INDICES) + vk::BufferUsageFlags::INDEX_BUFFER, &indices) } @@ -912,6 +918,7 @@ fn init_commands(device: &Device, pipeline: &vk::Pipeline, vertex_buffer: &vk::Buffer, index_buffer: &vk::Buffer, + index_count: usize, descriptor_sets: &Vec<vk::DescriptorSet>, command_pool: &vk::CommandPool) -> Result<Vec<vk::CommandBuffer>> @@ -979,7 +986,7 @@ fn init_commands(device: &Device, unsafe { device.cmd_bind_index_buffer(command_buffer, *index_buffer, 0, - vk::IndexType::UINT16) + vk::IndexType::UINT32) }; unsafe { @@ -992,7 +999,7 @@ fn init_commands(device: &Device, }; unsafe { - device.cmd_draw_indexed(command_buffer, INDICES.len() as u32, + device.cmd_draw_indexed(command_buffer, index_count as u32, 1, 0, 0, 0) }; diff --git a/src/main.rs b/src/main.rs index 478a179..af41b0d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ use crate::linear_algebra::{ Vec3, Vec4, Mat4, Transformation }; use crate::shader_data::UniformBlock; use std::cell::RefCell; -use std::f32::consts::{ FRAC_PI_2, FRAC_PI_4, TAU }; +use std::f32::consts::{ FRAC_PI_4, TAU }; use std::ptr::copy_nonoverlapping; use std::time::Instant; use vulkanalia::Device; @@ -25,6 +25,7 @@ mod error; mod graphics_permanent; mod graphics_window_dressing; mod linear_algebra; +mod model_loader; mod shader_data; @@ -288,12 +289,11 @@ fn render_uniforms(device: &Device, device_memory: &vk::DeviceMemory, let scale = Vec3::new(1.0, 1.0, 1.0); let model = Transformation { - rotation: Vec4::rotation_quaternion(&Vec3::new(-1.0, 0.0, 0.0), FRAC_PI_2) - .rotate(&Vec3::new(0.0, 1.0, 0.0), time % TAU), + rotation: Vec4::rotation_quaternion(&Vec3::new(0.0, 1.0, 0.0), time % TAU), translation: Vec3::new(0.0, 0.0, 0.0), }; - let view = Transformation::look_at(&Vec3::new(0.0, -2.0, -2.0), - &Vec3::new(0.0, 0.0, 0.0), + let view = Transformation::look_at(&Vec3::new(0.0, -3.0, -8.0), + &Vec3::new(0.0, -1.0, 0.0), &Vec3::new(0.0, -1.0, 0.0)); let aspect_ratio = extent.width as f32 / extent.height as f32; let projection = Mat4::perspective(FRAC_PI_4, aspect_ratio, 0.1, 10.0); diff --git a/src/model_loader.rs b/src/model_loader.rs new file mode 100644 index 0000000..fea5ab5 --- /dev/null +++ b/src/model_loader.rs @@ -0,0 +1,44 @@ +#![forbid(unsafe_code)] +use crate::error::*; +use crate::linear_algebra::{ Vec2, Vec3 }; +use crate::shader_data::Vertex; + +use std::io::Cursor; + +use tobj::{ load_obj_buf, LoadOptions }; + + +pub fn load_model() -> Result<(Vec<Vertex<f32>>, Vec<u32>)> { + let obj = include_bytes!("../models/teapot.obj"); + + let load_options = LoadOptions { + single_index: true, + triangulate: true, + ..Default::default() + }; + let (models, materials) = load_obj_buf(&mut Cursor::new(obj), &load_options, + |_| Ok(Default::default()))?; + + let _ = materials?; + + let mut vertices = Vec::new(); + let mut indices = Vec::new(); + + for model in models { + for index in 0 .. model.mesh.positions.len() / 3 { + vertices.push(Vertex::new(Vec3::new(model.mesh.positions[index*3], + model.mesh.positions[index*3 + 1], + model.mesh.positions[index*3 + 2]), + Vec3::new(1.0, 1.0, 1.0), + Vec2::new(model.mesh.texcoords[index*2], + model.mesh.texcoords[index*2 + 1]))) + } + + for index in model.mesh.indices { + indices.push(index); + } + } + + Ok((vertices, indices)) +} + diff --git a/src/shader_data.rs b/src/shader_data.rs index bd7ff82..8197bfc 100644 --- a/src/shader_data.rs +++ b/src/shader_data.rs @@ -5,31 +5,6 @@ use std::mem::size_of; use vulkanalia::vk::{ self, HasBuilder }; -pub static VERTICES: [Vertex<f32>; 8] = [ - Vertex::new(Vec3::new(-0.5, -0.5, 0.0), Vec3::new(1.0, 0.0, 0.0), - Vec2::new(1.0, 0.0)), - Vertex::new(Vec3::new( 0.5, -0.5, 0.0), Vec3::new(0.0, 1.0, 0.0), - Vec2::new(0.0, 0.0)), - Vertex::new(Vec3::new( 0.5, 0.5, 0.0), Vec3::new(0.0, 0.0, 1.0), - Vec2::new(0.0, 1.0)), - Vertex::new(Vec3::new(-0.5, 0.5, 0.0), Vec3::new(1.0, 1.0, 1.0), - Vec2::new(1.0, 1.0)), - Vertex::new(Vec3::new(-0.5, -0.5, 0.5), Vec3::new(1.0, 0.0, 0.0), - Vec2::new(1.0, 0.0)), - Vertex::new(Vec3::new( 0.5, -0.5, 0.5), Vec3::new(0.0, 1.0, 0.0), - Vec2::new(0.0, 0.0)), - Vertex::new(Vec3::new( 0.5, 0.5, 0.5), Vec3::new(0.0, 0.0, 1.0), - Vec2::new(0.0, 1.0)), - Vertex::new(Vec3::new(-0.5, 0.5, 0.5), Vec3::new(1.0, 1.0, 1.0), - Vec2::new(1.0, 1.0)), -]; - -pub const INDICES: &[u16] = &[ - 0, 1, 2, 2, 3, 0, - 4, 5, 6, 6, 7, 4, -]; - - #[repr(C)] #[derive(Clone, Debug)] pub struct Vertex<T: Copy> { @@ -48,8 +23,8 @@ pub struct UniformBlock<T: Copy> { } impl<T: Copy> Vertex<T> { - const fn new(position: Vec3<T>, color: Vec3<T>, - texture_coordinates: Vec2<T>) + pub const fn new(position: Vec3<T>, color: Vec3<T>, + texture_coordinates: Vec2<T>) -> Self { Self { position, color, texture_coordinates } |