summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/error.rs42
-rw-r--r--src/graphics_window_dressing.rs29
-rw-r--r--src/main.rs10
-rw-r--r--src/model_loader.rs44
-rw-r--r--src/shader_data.rs29
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 }