From 7b38c71cebcdabe6a9f623a1b8d75d229ef473e7 Mon Sep 17 00:00:00 2001 From: aiden Date: Wed, 21 Jun 2023 15:26:05 +0100 Subject: [PATCH] rendered a model!! wow --- src/main.rs | 2 + src/obj.rs | 125 +++++++++++++++++++++------------------------------ src/state.rs | 8 ++-- 3 files changed, 58 insertions(+), 77 deletions(-) diff --git a/src/main.rs b/src/main.rs index d7724d9..3928e44 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,6 +40,8 @@ var inches_per_1dg = inches_per_360dg / 360; var dots_per_1dg = inches_per_1dg * dpi; */ +#![feature(slice_as_chunks)] + use { std::{process::ExitCode, time::Instant}, winit::{ diff --git a/src/obj.rs b/src/obj.rs index e8c972c..b8855a8 100644 --- a/src/obj.rs +++ b/src/obj.rs @@ -1,4 +1,4 @@ -use std::{io::{Cursor, BufReader}, path::Path}; +use std::{path::Path, assert_eq}; use crate::texture; use image; @@ -7,10 +7,6 @@ use wgpu::util::DeviceExt; fn load_bytes>(file_name: T) -> Vec { return std::fs::read(file_name.as_ref()).unwrap(); } -fn load_string>(file_name: T) -> String { - return std::fs::read_to_string(file_name.as_ref()).unwrap(); -} - fn load_texture( file_name: &str, device: &wgpu::Device, @@ -22,29 +18,28 @@ fn load_texture( #[repr(C)] #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] -pub struct ModelVertex { - pub position: [f32; 3], - pub tex_coords: [f32; 2], - pub normal: [f32; 3], +pub struct Vertex { + pub position: [f32; 3], + pub tex_coords: [f32; 2], } pub struct Material { - pub name: String, - pub diffuse_texture: texture::Texture, - pub bind_group: wgpu::BindGroup, + pub name: String, + pub diffuse_texture: texture::Texture, + pub bind_group: wgpu::BindGroup, } pub struct Mesh { - pub name: String, - pub vertex_buffer: wgpu::Buffer, - pub index_buffer: wgpu::Buffer, - pub num_elements: u32, - pub material: usize, + pub name: String, + pub vertex_buffer: wgpu::Buffer, + pub index_buffer: wgpu::Buffer, + pub num_elements: u32, + pub material: usize, } pub struct Model { - pub meshes: Vec, - pub materials: Vec, + pub meshes: Vec, + pub materials: Vec, } pub fn load_obj( @@ -53,22 +48,9 @@ pub fn load_obj( queue: &wgpu::Queue, layout: &wgpu::BindGroupLayout, ) -> Model { - let obj_text = load_string(file_name); - let obj_cursor = Cursor::new(obj_text); - let mut obj_reader = BufReader::new(obj_cursor); - - let (models, obj_materials) = tobj::load_obj_buf( - &mut(obj_reader), - &(tobj::LoadOptions { - triangulate: true, - single_index: true, - ..Default::default() - }), - |p| { - let p = format!("models/{}", p.to_str().unwrap()); // fixme - let mat_text = load_string(p); - tobj::load_mtl_buf(&mut(BufReader::new(Cursor::new(mat_text)))) - } + let (models, obj_materials) = tobj::load_obj( + file_name, + &(tobj::GPU_LOAD_OPTIONS) ).unwrap(); let mut materials = Vec::new(); @@ -97,45 +79,42 @@ pub fn load_obj( }) } - let meshes = models - .into_iter() - .map(|m| { - let vertices = (0..m.mesh.positions.len() / 3) - .map(|i| ModelVertex { - position: [ - m.mesh.positions[i * 3], - m.mesh.positions[i * 3 + 1], - m.mesh.positions[i * 3 + 2], - ], - tex_coords: [m.mesh.texcoords[i * 2], m.mesh.texcoords[i * 2 + 1]], - normal: [ - m.mesh.normals[i * 3], - m.mesh.normals[i * 3 + 1], - m.mesh.normals[i * 3 + 2], - ], - }) - .collect::>(); + // models is a Vec of struct { mesh: Mesh, name: String } + let mut meshes = Vec::::new(); + for model in models { + let mesh = model.mesh; - let vertex_buffer = device.create_buffer_init(&(wgpu::util::BufferInitDescriptor { - label: Some(&(format!("{:?} Vertex Buffer", file_name))), - contents: bytemuck::cast_slice(&(vertices)), - usage: wgpu::BufferUsages::VERTEX, - })); - let index_buffer = device.create_buffer_init(&(wgpu::util::BufferInitDescriptor { - label: Some(&(format!("{:?} Index Buffer", file_name))), - contents: bytemuck::cast_slice(&(m.mesh.indices)), - usage: wgpu::BufferUsages::INDEX, - })); + let (positions, _) = mesh.positions.as_chunks::<3>(); + let (texcoords, _) = mesh.texcoords.as_chunks::<2>(); + assert_eq!(positions.len(), texcoords.len()); - Mesh { - name: file_name.to_string(), - vertex_buffer, - index_buffer, - num_elements: m.mesh.indices.len() as u32, - material: m.mesh.material_id.unwrap_or(0), - } - }) - .collect::>(); + let mut vertices = Vec::::new(); + for index in 0..positions.len() { + vertices.push(Vertex { + position: positions[index], + tex_coords: [texcoords[index][0], 1.0 - texcoords[index][1]], + }); + } + + let vertex_buffer = device.create_buffer_init(&(wgpu::util::BufferInitDescriptor { + label: Some(&(format!("{:?} Vertex Buffer", file_name))), + contents: bytemuck::cast_slice(&(vertices)), + usage: wgpu::BufferUsages::VERTEX, + })); + let index_buffer = device.create_buffer_init(&(wgpu::util::BufferInitDescriptor { + label: Some(&(format!("{:?} Index Buffer", file_name))), + contents: bytemuck::cast_slice(&(mesh.indices)), + usage: wgpu::BufferUsages::INDEX, + })); + + meshes.push(Mesh { + name: "x".to_string(), + vertex_buffer, + index_buffer, + num_elements: mesh.indices.len() as u32, + material: mesh.material_id.unwrap(), + }); + } Model { meshes, materials } -} \ No newline at end of file +} diff --git a/src/state.rs b/src/state.rs index 554a5dd..27230d1 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,7 +1,7 @@ use cgmath::{Deg, Rad, Point3}; use winit::window::Window; -use crate::{camera::*, Input, player::Player, obj::{self, ModelVertex}}; +use crate::{camera::*, Input, player::Player, obj::{self, Vertex}}; pub struct State { pub input: Input, @@ -196,9 +196,9 @@ impl State { buffers: &[ // index 0 wgpu::VertexBufferLayout { - array_stride: std::mem::size_of::() as wgpu::BufferAddress, + array_stride: std::mem::size_of::() as wgpu::BufferAddress, step_mode: wgpu::VertexStepMode::Vertex, - attributes: &(wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x2, 2 => Float32x3]), + attributes: &(wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x2]), }, ], }, @@ -216,7 +216,7 @@ impl State { topology: wgpu::PrimitiveTopology::TriangleList, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, - cull_mode: None, // should use Some(wgpu::Face::Back) once i have 3d objects (rather than 2d ones) in space + cull_mode: Some(wgpu::Face::Back), polygon_mode: wgpu::PolygonMode::Fill, unclipped_depth: false, conservative: false,