diff --git a/src/bin/platformer/graphics.rs b/src/bin/platformer/graphics.rs index a0187ab..1938dcc 100644 --- a/src/bin/platformer/graphics.rs +++ b/src/bin/platformer/graphics.rs @@ -107,7 +107,7 @@ impl Graphics { Pass::default () .shader (&shaders [0]) .flags ([ - (gl::CULL_FACE, true), + (gl::CULL_FACE, false), (gl::DEPTH_TEST, true), (gl::TEXTURE_2D, true), (gl::STENCIL_TEST, false), @@ -164,6 +164,7 @@ impl Graphics { &self, state: &GameState, gl_state: &mut GlState, + level: &crate::LoadedLevel, ) { use uniforms as u; @@ -192,9 +193,9 @@ impl Graphics { let attrs = shader_vars.attrs; let unis = shader_vars.unis; - self.texture_earth.bind (); - - { + if false { + self.texture_earth.bind (); + let mvp = view_mat * Mat4::from_translation (state.player.pos) * Mat4::from_scale ((0.5, 0.5, 0.5).into ()); @@ -209,25 +210,89 @@ impl Graphics { self.texture_crate.bind (); glezz::uniform_3fv (unis [&u::ALBEDO], &white); - for aabb in &state.aabbs { - let min = aabb.min; - let max = aabb.max; - let center = (min + max) / 2.0; - let scale = (max - min) / 2.0; + if false { + for aabb in &state.aabbs { + let min = aabb.min; + let max = aabb.max; + let center = (min + max) / 2.0; + let scale = (max - min) / 2.0; + + let mvp = view_mat * + Mat4::from_translation (center) * + Mat4::from_scale (scale); + glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp); + + self.mesh_cube.draw_all (attrs, |_| { + true + }); + } + } + + if true { + use opengl_rust::renderable_model::attributes as a; - let mvp = view_mat * - Mat4::from_translation (center) * - Mat4::from_scale (scale); - glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp); + let scene = level.level.scenes ().next ().unwrap (); - self.mesh_cube.draw_all (attrs, |_| { - true - }); + unsafe { + gl::BindBuffer (gl::ARRAY_BUFFER, 0); + gl::BindBuffer (gl::ELEMENT_ARRAY_BUFFER, 0); + } + + for node in scene.nodes () { + let mesh = match node.mesh () { + None => continue, + Some (x) => x, + }; + + let mvp = view_mat * + Mat4::from_cols_array_2d (&node.transform ().matrix ()); + glezz::uniform_matrix_4fv (unis [&u::MVP], &mvp); + + for prim in mesh.primitives () { + use gltf::{ + Semantic, + }; + + let positions = match prim.get (&Semantic::Positions) { + None => continue, + Some (x) => x, + }; + let pos_view = match positions.view () { + None => continue, + Some (x) => x, + }; + let indices = match prim.indices () { + None => continue, + Some (x) => x, + }; + let indices_view = match indices.view () { + None => continue, + Some (x) => x, + }; + + unsafe { + gl::VertexAttribPointer ( + attrs [a::POS].unwrap (), + 3, + gl::FLOAT, + 0, + 4 * 3, + &level.buffer [positions.offset () + pos_view.offset ()] as *const u8 as *const c_void, + ); + gl::DrawElements ( + gl::TRIANGLES, + 3 * 12, + gl::UNSIGNED_SHORT, + &level.buffer [indices.offset () + indices_view.offset ()] as *const u8 as *const c_void, + ); + } + } + } } glezz::uniform_3fv (unis [&u::ALBEDO], &shadow_blue); - if true { + if false { // Raycast for player shadow let coll = opengl_rust::physics::get_candidate ( &[], &state.aabbs, @@ -274,7 +339,7 @@ impl Graphics { } } - { + if false { let sky_mvp_mat = view_mat * Mat4::from_scale ((64.0, 64.0, 64.0).into ()); self.texture_sky.bind (); @@ -284,7 +349,7 @@ impl Graphics { glezz::uniform_3fv (unis [&u::MIN_ALBEDO], &black); glezz::uniform_1i (unis [&u::TEXTURE], 0); - // self.mesh_sky.draw_all (attrs, |_| true); + self.mesh_sky.draw_all (attrs, |_| true); } }); } diff --git a/src/bin/platformer/main.rs b/src/bin/platformer/main.rs index f696861..e6ab09d 100644 --- a/src/bin/platformer/main.rs +++ b/src/bin/platformer/main.rs @@ -50,6 +50,13 @@ impl Default for GameState { } } +impl GameState { + fn reset_level (&mut self, level: &LoadedLevel) { + self.player = Default::default (); + self.player.pos = level.player_spawn; + } +} + #[tokio::main] async fn main () -> Result <()> { tracing_subscriber::fmt::fmt () @@ -81,16 +88,7 @@ async fn main () -> Result <()> { let mut time_step = TimeStep::new (60, 1000); - let level = gltf::Gltf::open ("gltf/level-00.gltf")?; - for scene in level.scenes () { - for node in scene.nodes () { - println! ( - "Node #{} has {} children", - node.index(), - node.children().count(), - ); - } - } + let level = LoadedLevel::from_path ("gltf/level-00.glb")?; let mut graphics = Graphics::new (); @@ -106,6 +104,8 @@ async fn main () -> Result <()> { let player_jump_speed = 8.0; let mut player_jump_vec: Option = None; + game_state.reset_level (&level); + 'running: loop { let _frames_to_do = time_step.step (); let mut player_wants_to_jump = false; @@ -117,7 +117,7 @@ async fn main () -> Result <()> { break 'running }, Event::KeyDown { keycode: Some (Keycode::R), .. } => { - game_state = Default::default (); + game_state.reset_level (&level); }, Event::KeyDown { keycode: Some (Keycode::Space), .. } => { player_wants_to_jump = true; @@ -180,7 +180,7 @@ async fn main () -> Result <()> { window.gl_make_current (&gl_ctx).unwrap (); - graphics.draw (&game_state, &mut gl_state); + graphics.draw (&game_state, &mut gl_state, &level); graphics.frames += 1; window.gl_swap_window (); @@ -191,6 +191,87 @@ async fn main () -> Result <()> { Ok (()) } +struct LoadedLevel { + player_spawn: Vec3, + buffer: Vec , + level: gltf::Document, +} + +impl LoadedLevel { + fn from_path (path: &str) -> Result { + use gltf::{ + Semantic, + scene::Transform, + }; + + let (level, buffers, _) = gltf::import (path)?; + let buffer = match buffers.get (0) { + None => bail! ("gltf didn't load any buffers"), + Some (x) => x.0.to_vec (), + }; + + let scene = match level.scenes ().next () { + None => bail! ("No scenes in glTF file"), + Some (x) => x, + }; + + let mut player_spawn = None; + + for node in scene.nodes () { + if node.name () == Some ("Player Spawn") { + let (translation, _, _) = node.transform ().decomposed (); + player_spawn = Some (Vec3::from (translation)); + } + else if let Some (camera) = node.camera () { + + } + else if let Some (mesh) = node.mesh () { + println! ("Node {:?} is a mesh", node.name ()); + for (i, prim) in mesh.primitives ().enumerate () { + let positions = match prim.get (&Semantic::Positions) { + None => continue, + Some (x) => x, + }; + let normals = match prim.get (&Semantic::Normals) { + None => continue, + Some (x) => x, + }; + let indices = match prim.indices () { + None => continue, + Some (x) => x, + }; + let pos_view = match positions.view () { + None => continue, + Some (x) => x, + }; + let norm_view = match normals.view () { + None => continue, + Some (x) => x, + }; + let indices_view = match indices.view () { + None => continue, + Some (x) => x, + }; + dbg! (positions.offset (), pos_view.offset (), pos_view.stride ()); + dbg! (normals.offset (), norm_view.offset (), norm_view.stride ()); + dbg! (indices.offset (), indices.data_type (), indices_view.offset (), indices_view.stride ()); + } + } + } + + let player_spawn = match player_spawn { + None => bail! ("glTF file must have `Player Spawn` node"), + Some (x) => x, + }; + + Ok (Self { + buffer, + level, + player_spawn, + }) + } +} + struct ShaderLocations { attr_pos: u32, attr_normal: u32,