working on loading materials

master
mitchellhansen 4 years ago
parent e3c1ce7789
commit e5815ce0d6

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

@ -4,6 +4,7 @@ const int MAX_LIGHTS = 10;
layout(location = 0) in vec3 v_Normal;
layout(location = 1) in vec4 v_Position;
layout(location = 2) in vec2 v_Uv;
layout(location = 0) out vec4 o_Target;

Binary file not shown.

@ -2,9 +2,11 @@
layout(location = 0) in vec4 a_Pos;
layout(location = 1) in vec4 a_Normal;
layout(location = 2) in vec2 a_Uv;
layout(location = 0) out vec3 v_Normal;
layout(location = 1) out vec4 v_Position;
layout(location = 2) out vec2 v_Uv;
layout(set = 0, binding = 0) uniform Globals {
mat4 u_ViewProj;
@ -16,6 +18,7 @@ layout(set = 1, binding = 0) uniform Entity {
};
void main() {
v_Uv = a_Uv;
v_Normal = mat3(u_World) * vec3(a_Normal.xyz);
v_Position = u_World * vec4(a_Pos);
gl_Position = u_ViewProj * v_Position;

Binary file not shown.

@ -0,0 +1,13 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material
Ns 323.999994
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2
map_Kd 20200527_165845.jpg

File diff suppressed because it is too large Load Diff

@ -1,22 +1,23 @@
use bytemuck::{Pod, Zeroable};
use nalgebra::Vector4;
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct Vertex {
pos: [f32; 4],
normal: [f32; 4],
uv: [f32; 2],
}
impl Vertex {
pub fn position(&self) -> Vector4<f32> {
Vector4::new(self.pos[0], self.pos[1], self.pos[2], self.pos[3])
}
pub fn from(pos: [f32; 3], nor: [f32; 3]) -> Vertex {
pub fn from(pos: [f32; 3], nor: [f32; 3], uv: [f32; 2]) -> Vertex {
Vertex {
pos: [pos[0], pos[1], pos[2], 1.0],
normal: [nor[0], nor[1], nor[2], 0.0],
uv: [0.0, 0.0],
}
}
}
@ -24,16 +25,21 @@ impl Vertex {
unsafe impl Pod for Vertex {}
unsafe impl Zeroable for Vertex {}
#[derive(Clone, Debug)]
pub struct RawMesh {
vertices: Vec<Vertex>,
normals: Vec<[u32; 3]>,
}
pub fn load_obj(obj_path: &str, mtl_path: Option<&str>) -> (Vec<Vertex>, Vec<u32>) {
pub fn load_obj(mesh_path: &str) -> (Vec<Vertex>, Vec<u32>) {
let (models, materials) = tobj::load_obj(mesh_path, false).expect("Failed to load file");
let (models, materials) = tobj::load_obj(obj_path, true).expect("Failed to load file");
println!("# of models: {}", models.len());
println!("# of materials: {}", materials.len());
let mut index_data : Vec<u32> = Vec::new();
let mut index_data: Vec<u32> = Vec::new();
let mut vertex_data = Vec::new();
for model in models {
@ -49,24 +55,30 @@ pub fn load_obj(mesh_path: &str) -> (Vec<Vertex>, Vec<u32>) {
next_face = end;
}
// Normals and texture coordinates are also loaded, but not printed in this example
assert!(mesh.positions.len() % 3 == 0);
assert!(mesh.texcoords.len() % 2 == 0);
for v in 0..mesh.positions.len() / 3 {
vertex_data.push(
Vertex::from([
mesh.positions[3 * v],
mesh.positions[3 * v + 1],
mesh.positions[3 * v + 2]
],
[
mesh.normals[3 * v],
mesh.normals[3 * v + 1],
mesh.normals[3 * v + 2]
],
));
let texcoords = if mesh.texcoords.len() == 0 {
[0.0, 0.0]
} else {
[mesh.texcoords[2 * v], mesh.texcoords[2 * v + 1]]
};
vertex_data.push(Vertex::from(
[
mesh.positions[3 * v],
mesh.positions[3 * v + 1],
mesh.positions[3 * v + 2],
],
[
mesh.normals[3 * v],
mesh.normals[3 * v + 1],
mesh.normals[3 * v + 2],
],
texcoords,
));
}
}
(vertex_data.to_vec(), index_data.to_vec())
}
}

@ -49,6 +49,7 @@ use crate::imgui_supp::extended_winit_imgui_support;
use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform};
use crate::owned_event::{OwnedEvent, OwnedEventExtension};
use crate::physics::state::PhysicsState;
use std::fs;
mod camera;
mod components;
@ -83,6 +84,7 @@ ECS
input/io (yep!)
collision / physics (yep!)
entities & behaviours (got the entities!)
scripting!
*/
@ -156,6 +158,7 @@ fn main() {
// The renderer
let mut renderer = render::state::RenderState::init(&window, &mut imgui_context);
preload_meshes("./resources");
entity_loading(&mut world, &mut renderer);
resources.insert(renderer);
@ -305,6 +308,21 @@ fn main() {
});
}
pub fn preload_meshes(resources_path: &str) -> (){
println!("Preloading meshes...");
let paths = fs::read_dir(resources_path).unwrap();
for file in paths {
let file = file.unwrap().file_name();
let filename = file.to_str().unwrap();
if filename.ends_with(".obj") {
println!("Loading {:?} ...", filename);
}
}()
// I guess it's fine to have them loaded to the gpu
// But I also want to preserve the raw data
}
pub fn load_colliding_mesh_entity(world: &mut World, renderer: &mut render::state::RenderState, mesh_path: &str) {
let mut static_floor_body = RigidBodyBuilder::new_static()
@ -366,6 +384,11 @@ pub fn load_colliding_mesh_entity(world: &mut World, renderer: &mut render::stat
pub fn entity_loading(world: &mut World, renderer: &mut render::state::RenderState) {
let monkey_mesh =
renderer.load_mesh_to_buffer("./resources/monkey.obj", Some(wgpu::Color::GREEN));
let light_mesh =
renderer.load_mesh_to_buffer("./resources/light.obj", Some(wgpu::Color::BLACK));
let ball_mesh =
renderer.load_mesh_to_buffer("./resources/ball.obj", Some(wgpu::Color::BLUE));
let camera_ent: Entity = world.push((
Camera {
@ -380,8 +403,7 @@ pub fn entity_loading(world: &mut World, renderer: &mut render::state::RenderSta
CameraController::new(3.0, 1.0),
));
let light_mesh =
renderer.load_mesh_to_buffer("./resources/light.obj", Some(wgpu::Color::BLACK));
let light_entity: Entity = world.push((
Position {
@ -457,7 +479,6 @@ pub fn entity_loading(world: &mut World, renderer: &mut render::state::RenderSta
let ball_mesh = renderer.load_mesh_to_buffer("./resources/ball.obj", Some(wgpu::Color::BLUE));
let ball_mesh: Entity = world.push((
Position {

@ -110,7 +110,7 @@ impl RenderState {
/// Create a bare vertex & indices buffer
/// TODO I really should remove this / consolidate it
pub fn create_buffer(
fn create_buffer(
device: &wgpu::Device,
indices: Vec<u32>,
vertices: Vec<Vertex>,
@ -271,7 +271,7 @@ impl RenderState {
// Though the attr thing is still a macro. Which would cause issues if
// I wanted to get tricky with the 0,1 types
let vertex_size = mem::size_of::<Vertex>();
let vertex_attr = wgpu::vertex_attr_array![0 => Float4, 1 => Float4];
let vertex_attr = wgpu::vertex_attr_array![0 => Float4, 1 => Float4, 2 => Float2];
let vb_desc = wgpu::VertexBufferLayout {
array_stride: vertex_size as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,

@ -1 +1 @@
<mxfile host="Electron" modified="2021-02-05T04:05:12.722Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.1.8 Chrome/87.0.4280.88 Electron/11.1.1 Safari/537.36" etag="obF5lhMXlva4N7-E3vuM" version="14.1.8" type="device"><diagram id="LqEz0sV-94yUqItN7aiY" name="Page-1">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</diagram></mxfile>
<mxfile host="Electron" modified="2021-02-19T05:53:28.600Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.1.8 Chrome/87.0.4280.88 Electron/11.1.1 Safari/537.36" etag="lM6_THXf1cUAL8i2gB5_" version="14.1.8" type="device" pages="2"><diagram id="LqEz0sV-94yUqItN7aiY" name="Page-1">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</diagram><diagram id="rdqDIDw6EY2t9OKmYRQ_" name="Page-2">1VbBbpwwEP0ajq0WDO3mumSbSm3Vwx6anFYOnsWODIO8Q4B+fe1gFghRolRRN+WA/J5nBua9wSJgadFeGV7JHyhAB9FKtAG7DKJoHcf27oiuJ8JVctEzuVHCcyOxU79hCPRsrQQcZ4GEqElVczLDsoSMZhw3Bpt52AH1/KkVz2FB7DKul+wvJUj6vlb2Gne+gsolLbYKPsR74ii5wGZCsW3AUoNI/apoU9BOv0GaK5XzJP3JNmmxvt6nybdim37oi315TcqpCwMlvW3pqC99z3XtJdPIxR5v73zP1A1aGqxLAa7YKmCbRiqCXcUzt9vY6bGcpEJbFNqlLwuGoH1kxQtNhCdl7VQCFkCms3m+Chvc8RNpiR43o73hYJicGPvJc9xPVH4qPUpmF161VygYL4QCYWfQQzQkMceS6+3IbuZSjjHfESsv4B0Qdf6D4jXhXF5oFV279I+JRze+mFtftlPQDaC07U6SHLwZ6jkwpj2gIa/vzzX1F0ZaYbA2GTwTx/y5wE0Oz9WLnh4MA5qTup+/3Ju7/PmcLodTj0+Ov+Ty1OOJ5e/c5eScLrOnT8MCjnJPuL+tDwcw/8fBGK/PfTAmCzEzA5zgXcsYX/w7GS0cfx4e9iZ/YWz7Bw==</diagram></mxfile>
Loading…
Cancel
Save