rendered a model!! wow

This commit is contained in:
aiden 2023-06-21 15:26:05 +01:00
parent 8481f8d529
commit 7b38c71ceb
Signed by: aiden
GPG Key ID: EFA9C74AEBF806E0
3 changed files with 58 additions and 77 deletions

@ -40,6 +40,8 @@ var inches_per_1dg = inches_per_360dg / 360;
var dots_per_1dg = inches_per_1dg * dpi; var dots_per_1dg = inches_per_1dg * dpi;
*/ */
#![feature(slice_as_chunks)]
use { use {
std::{process::ExitCode, time::Instant}, std::{process::ExitCode, time::Instant},
winit::{ winit::{

@ -1,4 +1,4 @@
use std::{io::{Cursor, BufReader}, path::Path}; use std::{path::Path, assert_eq};
use crate::texture; use crate::texture;
use image; use image;
@ -7,10 +7,6 @@ use wgpu::util::DeviceExt;
fn load_bytes<T: AsRef<Path>>(file_name: T) -> Vec<u8> { fn load_bytes<T: AsRef<Path>>(file_name: T) -> Vec<u8> {
return std::fs::read(file_name.as_ref()).unwrap(); return std::fs::read(file_name.as_ref()).unwrap();
} }
fn load_string<T: AsRef<Path>>(file_name: T) -> String {
return std::fs::read_to_string(file_name.as_ref()).unwrap();
}
fn load_texture( fn load_texture(
file_name: &str, file_name: &str,
device: &wgpu::Device, device: &wgpu::Device,
@ -22,29 +18,28 @@ fn load_texture(
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct ModelVertex { pub struct Vertex {
pub position: [f32; 3], pub position: [f32; 3],
pub tex_coords: [f32; 2], pub tex_coords: [f32; 2],
pub normal: [f32; 3],
} }
pub struct Material { pub struct Material {
pub name: String, pub name: String,
pub diffuse_texture: texture::Texture, pub diffuse_texture: texture::Texture,
pub bind_group: wgpu::BindGroup, pub bind_group: wgpu::BindGroup,
} }
pub struct Mesh { pub struct Mesh {
pub name: String, pub name: String,
pub vertex_buffer: wgpu::Buffer, pub vertex_buffer: wgpu::Buffer,
pub index_buffer: wgpu::Buffer, pub index_buffer: wgpu::Buffer,
pub num_elements: u32, pub num_elements: u32,
pub material: usize, pub material: usize,
} }
pub struct Model { pub struct Model {
pub meshes: Vec<Mesh>, pub meshes: Vec<Mesh>,
pub materials: Vec<Material>, pub materials: Vec<Material>,
} }
pub fn load_obj( pub fn load_obj(
@ -53,22 +48,9 @@ pub fn load_obj(
queue: &wgpu::Queue, queue: &wgpu::Queue,
layout: &wgpu::BindGroupLayout, layout: &wgpu::BindGroupLayout,
) -> Model { ) -> Model {
let obj_text = load_string(file_name); let (models, obj_materials) = tobj::load_obj(
let obj_cursor = Cursor::new(obj_text); file_name,
let mut obj_reader = BufReader::new(obj_cursor); &(tobj::GPU_LOAD_OPTIONS)
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))))
}
).unwrap(); ).unwrap();
let mut materials = Vec::new(); let mut materials = Vec::new();
@ -97,45 +79,42 @@ pub fn load_obj(
}) })
} }
let meshes = models // models is a Vec of struct { mesh: Mesh, name: String }
.into_iter() let mut meshes = Vec::<Mesh>::new();
.map(|m| { for model in models {
let vertices = (0..m.mesh.positions.len() / 3) let mesh = model.mesh;
.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::<Vec<_>>();
let vertex_buffer = device.create_buffer_init(&(wgpu::util::BufferInitDescriptor { let (positions, _) = mesh.positions.as_chunks::<3>();
label: Some(&(format!("{:?} Vertex Buffer", file_name))), let (texcoords, _) = mesh.texcoords.as_chunks::<2>();
contents: bytemuck::cast_slice(&(vertices)), assert_eq!(positions.len(), texcoords.len());
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,
}));
Mesh { let mut vertices = Vec::<Vertex>::new();
name: file_name.to_string(), for index in 0..positions.len() {
vertex_buffer, vertices.push(Vertex {
index_buffer, position: positions[index],
num_elements: m.mesh.indices.len() as u32, tex_coords: [texcoords[index][0], 1.0 - texcoords[index][1]],
material: m.mesh.material_id.unwrap_or(0), });
} }
})
.collect::<Vec<_>>(); 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 } Model { meshes, materials }
} }

@ -1,7 +1,7 @@
use cgmath::{Deg, Rad, Point3}; use cgmath::{Deg, Rad, Point3};
use winit::window::Window; 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 struct State {
pub input: Input, pub input: Input,
@ -196,9 +196,9 @@ impl State {
buffers: &[ buffers: &[
// index 0 // index 0
wgpu::VertexBufferLayout { wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<ModelVertex>() as wgpu::BufferAddress, array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex, 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, topology: wgpu::PrimitiveTopology::TriangleList,
strip_index_format: None, strip_index_format: None,
front_face: wgpu::FrontFace::Ccw, 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, polygon_mode: wgpu::PolygonMode::Fill,
unclipped_depth: false, unclipped_depth: false,
conservative: false, conservative: false,