Skip to content
This repository has been archived by the owner on Jun 9, 2018. It is now read-only.

Commit

Permalink
Implement model loading.
Browse files Browse the repository at this point in the history
  • Loading branch information
c0gent committed Sep 23, 2017
1 parent 606ee91 commit 089d7cb
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 30 deletions.
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@
*.sublime-workspace
**/result.png
/examples/**/result**.png
# /examples/images-safe-clamp/result_patches.png
# /examples/images-safe-clamp/result_unrolled.png
**/result*.png
/*.obj

# Generated by Cargo
Cargo.lock
Expand All @@ -27,4 +26,3 @@ Cargo.lock
**/tmp
/src/junk
/bak

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ vks = { path = "../vks", features = ["proc_addr_loader_glob_functions"] }
libc = "*"
# nalgebra = "*"
cgmath = "*"
image = "*"
image = "*"
tobj = "*"
ordered-float = "*"
104 changes: 85 additions & 19 deletions src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
extern crate vkc;
extern crate cgmath;
extern crate image;
// extern crate winit;
extern crate tobj;

use std::mem;
use std::ptr;
use std::time;
use std::path::Path;
use std::collections::HashMap;
use image::{ImageFormat, DynamicImage};
use cgmath::{SquareMatrix, One, Rotation, Rotation3, Basis3, Matrix3, Matrix4, Vector3};
use vkc::winit::{EventsLoop, WindowBuilder, Window, Event, WindowEvent};
Expand All @@ -15,8 +19,11 @@ use vkc::{vk, util, device, VkcResult, Version, Instance, Device, Surface, Swapc
Buffer, DeviceMemory, Vertex, DescriptorSetLayout, UniformBufferObject, DescriptorPool,
Image, Sampler};

static MODEL_PATH: &str = "/src/shared_assets/models/chalet.obj";
static TEXTURE_PATH: &str = "/src/shared_assets/textures/chalet.jpg";
// static TEXTURE_PATH: &str = "/src/vkc/textures/texture.jpg";

const VERTICES: [Vertex; 8] = [
const VERTICES_UNUSED: [Vertex; 8] = [
Vertex { pos: [-0.5, -0.5, 0.0], color: [1.0, 0.0, 0.0], tex_coord: [1.0, 0.0]},
Vertex { pos: [0.5, -0.5, 0.0], color: [0.0, 1.0, 0.0], tex_coord: [0.0, 0.0] },
Vertex { pos: [0.5, 0.5, 0.0], color: [0.0, 0.0, 1.0], tex_coord: [0.0, 1.0] },
Expand All @@ -27,7 +34,7 @@ const VERTICES: [Vertex; 8] = [
Vertex { pos: [-0.5, 0.5, -0.5], color: [1.0, 1.0, 1.0], tex_coord: [1.0, 1.0] },
];

const INDICES: [u16; 12] = [
const INDICES_UNUSED: [u32; 12] = [
0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4
];
Expand Down Expand Up @@ -242,8 +249,6 @@ fn copy_buffer_to_image(device: &Device, command_pool: &CommandPool, buffer: &Bu
fn copy_buffer(device: &Device, command_pool: &CommandPool, src_buffer: &Buffer,
dst_buffer: &Buffer, size: vk::VkDeviceSize) -> VkcResult<()>
{
// unsafe { device.vk().core.vkBeginCommandBuffer(command_buffer, &begin_info); }

// TODO: Look into creating a separate command pool with the
// `VK_COMMAND_POOL_CREATE_TRANSIENT_BIT` flag for short lived command
// buffers like this.
Expand All @@ -261,9 +266,58 @@ fn copy_buffer(device: &Device, command_pool: &CommandPool, src_buffer: &Buffer,
end_single_time_commands(device, command_pool, command_buffer)
}

fn create_vertex_buffer(device: &Device, command_pool: &CommandPool) -> VkcResult<Buffer> {
fn load_model(device: &Device) -> VkcResult<(Vec<Vertex>, Vec<u32>)> {
let (models, materials) = tobj::load_obj(&Path::new(MODEL_PATH))
.expect("Error loading model");

let mut vertices = Vec::with_capacity(4096);
let mut indices = Vec::with_capacity(4096);

let mut unique_vertices: HashMap<Vertex, u32> = HashMap::with_capacity(1 << 20);

let mut mesh_id = 0usize;
for model in models {
let mesh = &model.mesh;
for &index in &mesh.indices {
let index = index as usize;

let vert_idz = 3 * index;
let tex_coord_idz = 2 * index;

let pos = [
mesh.positions[vert_idz],
mesh.positions[vert_idz + 1],
mesh.positions[vert_idz + 2],
];

let tex_coord = [
mesh.texcoords[tex_coord_idz],
1.0 - mesh.texcoords[tex_coord_idz + 1],
];

let vertex = Vertex {
pos,
color: [1.0, 1.0, 1.0],
tex_coord,
};

if !unique_vertices.contains_key(&vertex) {
unique_vertices.insert(vertex.clone(), vertices.len() as u32);
vertices.push(vertex.clone());
}

indices.push(unique_vertices[&vertex]);
}
mesh_id += 1;
}
Ok((vertices, indices))
}

fn create_vertex_buffer(device: &Device, command_pool: &CommandPool, vertices: &[Vertex])
-> VkcResult<Buffer>
{
// let buffer_bytes = (mem::size_of_val(&VERTICES[0]) * VERTICES.len()) as u64;
let buffer_bytes = (mem::size_of::<[Vertex; 4]>() * VERTICES.len()) as u64;
let buffer_bytes = (mem::size_of::<[Vertex; 4]>() * vertices.len()) as u64;

let staging_buffer = Buffer::new(device.clone(), buffer_bytes,
vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_SHARING_MODE_EXCLUSIVE,
Expand All @@ -273,8 +327,7 @@ fn create_vertex_buffer(device: &Device, command_pool: &CommandPool) -> VkcResul
unsafe {
vkc::check(device.vk().core.vkMapMemory(device.handle(),
staging_buffer.device_memory().handle(), 0, buffer_bytes, 0, &mut data));
// println!("##### VBO data (ptr): {:?}", data);
ptr::copy_nonoverlapping(&VERTICES, data as *mut _, buffer_bytes as usize);
ptr::copy_nonoverlapping(vertices.as_ptr(), data as *mut _, vertices.len());
device.vk().core.vkUnmapMemory(device.handle(), staging_buffer.device_memory().handle());
}

Expand All @@ -291,8 +344,10 @@ fn create_vertex_buffer(device: &Device, command_pool: &CommandPool) -> VkcResul
Ok(vertex_buffer)
}

fn create_index_buffer(device: &Device, command_pool: &CommandPool) -> VkcResult<Buffer> {
let buffer_bytes = (mem::size_of::<u16>() * INDICES.len()) as u64;
fn create_index_buffer<T>(device: &Device, command_pool: &CommandPool, indices: &[T])
-> VkcResult<Buffer>
{
let buffer_bytes = (mem::size_of::<T>() * indices.len()) as u64;

let staging_buffer = Buffer::new(device.clone(), buffer_bytes,
vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_SHARING_MODE_EXCLUSIVE,
Expand All @@ -302,7 +357,7 @@ fn create_index_buffer(device: &Device, command_pool: &CommandPool) -> VkcResult
let mut data = ptr::null_mut();
vkc::check(device.vk().core.vkMapMemory(device.handle(),
staging_buffer.device_memory().handle(), 0, buffer_bytes, 0, &mut data));
ptr::copy_nonoverlapping(&INDICES, data as *mut _, buffer_bytes as usize);
ptr::copy_nonoverlapping(indices.as_ptr(), data as *mut _, indices.len());
device.vk().core.vkUnmapMemory(device.handle(), staging_buffer.device_memory().handle());
}

Expand Down Expand Up @@ -378,7 +433,7 @@ fn create_depth_resources(device: &Device, command_pool: &CommandPool,
}

fn create_texture_image(device: &Device, command_pool: &CommandPool) -> VkcResult<Image> {
let pixels = image::open("/src/vkc/textures/texture.jpg").unwrap().to_rgba();
let pixels = image::open(TEXTURE_PATH).unwrap().to_rgba();
let (tex_width, tex_height) = pixels.dimensions();
let image_bytes = (tex_width * tex_height * 4) as u64;

Expand Down Expand Up @@ -520,10 +575,14 @@ struct App {
surface: Surface,
descriptor_set_layout: DescriptorSetLayout,
pipeline_layout: PipelineLayout,
vert_shader_code: Vec<u8>,
frag_shader_code: Vec<u8>,
command_pool: CommandPool,
texture_image: Image,
texture_image_view: ImageView,
texture_sampler: Sampler,
vertices: Vec<Vertex>,
indices: Vec<u32>,
vertex_buffer: Buffer,
index_buffer: Buffer,
uniform_buffer: Buffer,
Expand Down Expand Up @@ -553,8 +612,10 @@ impl App {
let render_pass = create_render_pass(device.clone(), swapchain.image_format())?;
let descriptor_set_layout = create_descriptor_set_layout(device.clone())?;
let pipeline_layout = PipelineLayout::new(device.clone(), Some(&descriptor_set_layout))?;
let vert_shader_code = util::read_file("/src/vkc/shaders/vert.spv")?;
let frag_shader_code = util::read_file("/src/vkc/shaders/frag.spv")?;
let graphics_pipeline = GraphicsPipeline::new(device.clone(), &pipeline_layout,
&render_pass, swapchain.extent().clone())?;
&render_pass, swapchain.extent().clone(), &vert_shader_code, &frag_shader_code)?;
let command_pool = CommandPool::new(device.clone(), &surface, queue_family_flags)?;
let (depth_image, depth_image_view) = create_depth_resources(&device, &command_pool,
swapchain.extent().clone())?;
Expand All @@ -564,8 +625,9 @@ impl App {
let texture_image_view = create_texture_image_view(device.clone(),
&texture_image)?;
let texture_sampler = create_texture_sampler(device.clone())?;
let vertex_buffer = create_vertex_buffer(&device, &command_pool)?;
let index_buffer = create_index_buffer(&device, &command_pool)?;
let (vertices, indices) = load_model(&device)?;
let vertex_buffer = create_vertex_buffer(&device, &command_pool, &vertices)?;
let index_buffer = create_index_buffer(&device, &command_pool, &indices)?;
let uniform_buffer = create_uniform_buffer(&device, &command_pool,
swapchain.extent().clone())?;
let descriptor_pool = create_descriptor_pool(device.clone())?;
Expand All @@ -574,7 +636,7 @@ impl App {
let command_buffers = vkc::create_command_buffers(&device, &command_pool, &render_pass,
&graphics_pipeline, &framebuffers, swapchain.extent(),
&vertex_buffer, &index_buffer,
VERTICES.len() as u32, INDICES.len() as u32, &pipeline_layout, descriptor_set)?;
vertices.len() as u32, vertices.len() as u32, &pipeline_layout, descriptor_set)?;
let image_available_semaphore = Semaphore::new(device.clone())?;
let render_finished_semaphore = Semaphore::new(device.clone())?;
let start_time = time::Instant::now();
Expand All @@ -597,10 +659,14 @@ impl App {
surface: surface,
descriptor_set_layout,
pipeline_layout,
vert_shader_code,
frag_shader_code,
command_pool,
texture_image,
texture_image_view,
texture_sampler,
vertices: vertices,
indices: indices,
vertex_buffer,
index_buffer,
uniform_buffer,
Expand Down Expand Up @@ -640,7 +706,7 @@ impl App {
swapchain.image_format())?;
let graphics_pipeline = GraphicsPipeline::new(self.device.clone(),
&self.pipeline_layout, &render_pass,
swapchain.extent().clone())?;
swapchain.extent().clone(), &self.vert_shader_code, &self.frag_shader_code)?;
let (depth_image, depth_image_view) = create_depth_resources(&self.device,
&self.command_pool, swapchain.extent().clone())?;
let framebuffers = vkc::create_framebuffers(&self.device,
Expand All @@ -649,8 +715,8 @@ impl App {
let command_buffers = vkc::create_command_buffers(&self.device, &self.command_pool,
&render_pass, &graphics_pipeline,
&framebuffers, swapchain.extent(),
&self.vertex_buffer, &self.index_buffer, VERTICES.len() as u32,
INDICES.len() as u32, &self.pipeline_layout, self.descriptor_set)?;
&self.vertex_buffer, &self.index_buffer, self.vertices.len() as u32,
self.indices.len() as u32, &self.pipeline_layout, self.descriptor_set)?;

self.swapchain = Some(swapchain);
self.swapchain_components = Some(SwapchainComponents {
Expand Down
4 changes: 3 additions & 1 deletion src/command_buffers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,10 @@ pub fn create_command_buffers(device: &Device, command_pool: &CommandPool,
let offsets = [0];
device.vk().core.vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers.as_ptr(),
offsets.as_ptr());
// device.vk().core.vkCmdBindIndexBuffer(command_buffer, index_buffer.handle(), 0,
// vk::VK_INDEX_TYPE_UINT16);
device.vk().core.vkCmdBindIndexBuffer(command_buffer, index_buffer.handle(), 0,
vk::VK_INDEX_TYPE_UINT16);
vk::VK_INDEX_TYPE_UINT32);

device.vk().core.vkCmdBindDescriptorSets(command_buffer,
vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1,
Expand Down
11 changes: 5 additions & 6 deletions src/graphics_pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use vks;
use ::{util, VkcResult, Device, ShaderModule, PipelineLayout, RenderPass, Vertex};



#[derive(Debug)]
struct Inner {
handle: vk::VkPipeline,
Expand All @@ -20,13 +21,11 @@ pub struct GraphicsPipeline {

impl GraphicsPipeline {
pub fn new(device: Device, pipeline_layout: &PipelineLayout,
render_pass: &RenderPass, swap_chain_extent: vk::VkExtent2D) -> VkcResult<GraphicsPipeline>
render_pass: &RenderPass, swap_chain_extent: vk::VkExtent2D, vert_shader_code: &[u8],
frag_shader_code: &[u8]) -> VkcResult<GraphicsPipeline>
{
let vert_shader_code = util::read_file("/src/vkc/shaders/vert.spv")?;
let frag_shader_code = util::read_file("/src/vkc/shaders/frag.spv")?;

let vert_shader_module = ShaderModule::new(device.clone(), &vert_shader_code)?;
let frag_shader_module = ShaderModule::new(device.clone(), &frag_shader_code)?;
let vert_shader_module = ShaderModule::new(device.clone(), vert_shader_code)?;
let frag_shader_module = ShaderModule::new(device.clone(), frag_shader_code)?;

let fn_name = unsafe { CStr::from_bytes_with_nul_unchecked(b"main\0") };

Expand Down
26 changes: 26 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ extern crate smallvec;
// extern crate cgmath;
extern crate vks;
extern crate libc;
extern crate tobj;
extern crate ordered_float;
pub extern crate winit;

mod error;
Expand Down Expand Up @@ -63,11 +65,13 @@ pub mod device;
pub mod util;

use std::ffi::OsStr;
use std::hash::{Hash, Hasher};
use libc::c_void;
use std::mem;
use std::ptr;
use winit::{EventsLoop, WindowBuilder, Window, CreationError, ControlFlow, Event, WindowEvent};
use loader::Loader;
use ordered_float::OrderedFloat;
// use nalgebra::Matrix4;
// pub use vulkan_h as vk;
// pub use vks::core as vkscore;
Expand Down Expand Up @@ -133,6 +137,7 @@ pub fn find_memory_type(device: &Device, type_filter: u32, properties: vk::VkMem



#[derive(Clone)]
#[repr(C)]
pub struct Vertex {
pub pos: [f32; 3],
Expand Down Expand Up @@ -177,6 +182,27 @@ impl Vertex {
}
}

impl Hash for Vertex {
fn hash<H: Hasher>(&self, state: &mut H) {
let pos = [OrderedFloat(self.pos[0]), OrderedFloat(self.pos[1]),
OrderedFloat(self.pos[2])];
let color = [OrderedFloat(self.color[0]), OrderedFloat(self.color[1]),
OrderedFloat(self.color[2])];
let tex_coord = [OrderedFloat(self.tex_coord[0]), OrderedFloat(self.tex_coord[1])];
pos.hash(state);
color.hash(state);
tex_coord.hash(state);
}
}

impl PartialEq for Vertex {
fn eq(&self, other: &Vertex) -> bool {
self.pos == other.pos && self.color == other.color && self.tex_coord == other.tex_coord
}
}

impl Eq for Vertex {}

// #[derive(Debug)]
// pub struct UniformBufferObject {
// pub model: Matrix4<f32>,
Expand Down
Binary file removed textures/texture.jpg
Binary file not shown.

0 comments on commit 089d7cb

Please sign in to comment.