diff --git a/src/bin/platformer/graphics.rs b/src/bin/platformer/graphics.rs index b7e460b..4a46613 100644 --- a/src/bin/platformer/graphics.rs +++ b/src/bin/platformer/graphics.rs @@ -167,11 +167,11 @@ impl Graphics { pub fn draw ( &self, - static_level: &crate::StaticLevel, + phys_tris: &[opengl_rust::physics::Triangle], logic: &crate::LogicState, gl_state: &mut GlState, level: &crate::LoadedLevel, - camera: &crate::Camera, + camera: &crate::level_loader::Camera, ) { // use serde::Deserialize; use uniforms as u; @@ -334,7 +334,7 @@ impl Graphics { if true { // Raycast for player shadow let coll = opengl_rust::physics::get_candidate ( - &static_level.tris, &[], + &phys_tris, &[], logic.player.pos, logic.player.pos + Vec3::new (0.0, 0.0, -100.0), 0.0 diff --git a/src/bin/platformer/level_loader.rs b/src/bin/platformer/level_loader.rs index 0934139..adcc70c 100644 --- a/src/bin/platformer/level_loader.rs +++ b/src/bin/platformer/level_loader.rs @@ -2,10 +2,13 @@ use anyhow::Result; use opengl_rust::{ prelude::*, + physics::Triangle, }; pub struct LoadedLevel { pub player_spawn: Vec3, + pub camera: Camera, + pub phys_tris: Vec , pub buffer: Vec , pub level: gltf::Document, } @@ -28,8 +31,16 @@ impl LoadedLevel { }; let mut player_spawn = None; + let mut camera = None; + let mut phys_tris: Vec = Vec::new (); for node in scene.nodes () { + if node.camera ().is_some () { + camera = Some (Camera { + transform: node.transform ().clone (), + }); + } + if node.name () == Some ("Player Spawn") { let (translation, _, _) = node.transform ().decomposed (); player_spawn = Some (Vec3::from (translation)); @@ -38,7 +49,9 @@ impl LoadedLevel { } else if let Some (mesh) = node.mesh () { - for (_i, prim) in mesh.primitives ().enumerate () { + let m = gltf_node_get_mat4 (&node); + + for (_, prim) in mesh.primitives ().enumerate () { let positions = match prim.get (&Semantic::Positions) { None => continue, Some (x) => x, @@ -51,7 +64,7 @@ impl LoadedLevel { None => continue, Some (x) => x, }; - let _pos_view = match positions.view () { + let pos_view = match positions.view () { None => continue, Some (x) => x, }; @@ -59,10 +72,53 @@ impl LoadedLevel { None => continue, Some (x) => x, }; - let _indices_view = match indices.view () { + let indices_view = match indices.view () { None => continue, Some (x) => x, }; + + let idx_start = indices.offset () + indices_view.offset (); + let idx_slice = &buffer [idx_start..idx_start + indices.count () * 2]; + let vert_start = positions.offset () + pos_view.offset (); + let vert_slice = &buffer [vert_start..vert_start + positions.count () * 4 * 3]; + + for chunk in idx_slice.chunks_exact (2 * 3) { + let read_idx = |i: usize| u16::from_le_bytes ([chunk [i * 2 + 0], chunk [i * 2 + 1]]); + + let idxs = [ + read_idx (0), + read_idx (1), + read_idx (2), + ]; + + let read_pos_coord = |i| f32::from_le_bytes ([ + vert_slice [i * 4 + 0], + vert_slice [i * 4 + 1], + vert_slice [i * 4 + 2], + vert_slice [i * 4 + 3], + ]); + + let read_pos = move |i| { + let i = usize::try_from (i).unwrap (); + m.transform_point3 (Vec3::new ( + read_pos_coord (i * 3 + 0), + read_pos_coord (i * 3 + 1), + read_pos_coord (i * 3 + 2), + )) + }; + + // glTF triangle winding is backwards from what I expected + // no biggie + let verts = [ + read_pos (idxs [0]), + read_pos (idxs [2]), + read_pos (idxs [1]), + ]; + + phys_tris.push (opengl_rust::physics::Triangle { + verts, + }); + } } } } @@ -72,10 +128,25 @@ impl LoadedLevel { Some (x) => x, }; + let camera = match camera { + None => bail! ("Couldn't find camera node in glTF file"), + Some (x) => x, + }; + Ok (Self { buffer, + camera, level, + phys_tris, player_spawn, }) } } + +pub struct Camera { + pub transform: gltf::scene::Transform, +} + +pub fn gltf_node_get_mat4 (node: &gltf::Node) -> Mat4 { + Mat4::from_cols_array_2d (&node.transform ().matrix ()) +} diff --git a/src/bin/platformer/logic.rs b/src/bin/platformer/logic.rs index a6ce41e..a7ffc89 100644 --- a/src/bin/platformer/logic.rs +++ b/src/bin/platformer/logic.rs @@ -1,11 +1,13 @@ use opengl_rust::{ prelude::*, - physics::PhysicsBody, + physics::{ + PhysicsBody, + Triangle, + }, }; use crate::{ LoadedLevel, - StaticLevel, VirtualGamepad, }; @@ -26,7 +28,7 @@ impl LogicState { self.player.pos = level.player_spawn; } - pub fn step (&mut self, static_level: &StaticLevel, phys_params: &opengl_rust::physics::Params, p_gp: VirtualGamepad) -> LogicStepOutput + pub fn step (&mut self, phys_tris: &[Triangle], phys_params: &opengl_rust::physics::Params, p_gp: VirtualGamepad) -> LogicStepOutput { let player_acc = 1.0; let player_acc_air = 0.125; @@ -107,7 +109,7 @@ impl LogicState { } } - let phys_result = opengl_rust::physics::step (&phys_params, &static_level.tris, &[], 0.5, &self.player); + let phys_result = opengl_rust::physics::step (&phys_params, phys_tris, &[], 0.5, &self.player); self.player = phys_result.body; if self.player.pos.z < kill_z { diff --git a/src/bin/platformer/main.rs b/src/bin/platformer/main.rs index 1daf78f..443dbfc 100644 --- a/src/bin/platformer/main.rs +++ b/src/bin/platformer/main.rs @@ -20,11 +20,6 @@ use virtual_gamepad::VirtualGamepad; pub struct GameState { logic: LogicState, - static_level: StaticLevel, -} - -pub struct StaticLevel { - tris: Vec , } #[tokio::main] @@ -59,103 +54,12 @@ async fn main () -> Result <()> { let mut time_step = TimeStep::new (60, 1000); let level = LoadedLevel::from_path ("gltf/level-00.glb")?; - let scene = level.level.scenes ().next ().unwrap (); - - let mut camera = None; - let mut phys_tris: Vec = Vec::new (); - - for node in scene.nodes () { - if node.camera ().is_some () { - camera = Some (Camera { - transform: node.transform ().clone (), - }); - } - - let mesh = match node.mesh () { - None => continue, - Some (x) => x, - }; - - let m = gltf_node_get_mat4 (&node); - - 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, - }; - - let idx_start = indices.offset () + indices_view.offset (); - let idx_slice = &level.buffer [idx_start..idx_start + indices.count () * 2]; - let vert_start = positions.offset () + pos_view.offset (); - let vert_slice = &level.buffer [vert_start..vert_start + positions.count () * 4 * 3]; - - for chunk in idx_slice.chunks_exact (2 * 3) { - let read_idx = |i: usize| u16::from_le_bytes ([chunk [i * 2 + 0], chunk [i * 2 + 1]]); - - let idxs = [ - read_idx (0), - read_idx (1), - read_idx (2), - ]; - - let read_pos_coord = |i| f32::from_le_bytes ([ - vert_slice [i * 4 + 0], - vert_slice [i * 4 + 1], - vert_slice [i * 4 + 2], - vert_slice [i * 4 + 3], - ]); - - let read_pos = move |i| { - let i = usize::try_from (i).unwrap (); - m.transform_point3 (Vec3::new ( - read_pos_coord (i * 3 + 0), - read_pos_coord (i * 3 + 1), - read_pos_coord (i * 3 + 2), - )) - }; - - // glTF triangle winding is backwards from what I expected - // no biggie - let verts = [ - read_pos (idxs [0]), - read_pos (idxs [2]), - read_pos (idxs [1]), - ]; - - phys_tris.push (opengl_rust::physics::Triangle { - verts, - }); - } - } - } - - let camera = match camera { - None => bail! ("Couldn't find camera node in glTF file"), - Some (x) => x, - }; let mut graphics = Graphics::new (); let mut gl_state = Default::default (); let mut game_state = GameState { logic: Default::default (), - static_level: StaticLevel { - tris: phys_tris, - }, }; let phys_params = opengl_rust::physics::Params { dt: 1.0 / 60.0, @@ -235,7 +139,7 @@ async fn main () -> Result <()> { let p_gp = player_gamepad; - let logic_step_output = game_state.logic.step (&game_state.static_level, &phys_params, p_gp); + let logic_step_output = game_state.logic.step (&level.phys_tris, &phys_params, p_gp); if logic_step_output.reset_level { game_state.logic.reset_level (&level); } @@ -247,10 +151,10 @@ async fn main () -> Result <()> { let prediction_frames = 4; let mut predicted_logic = game_state.logic.clone (); for _ in 0..prediction_frames { - predicted_logic.step (&game_state.static_level, &phys_params, p_gp); + predicted_logic.step (&level.phys_tris, &phys_params, p_gp); } - graphics.draw (&game_state.static_level, &predicted_logic, &mut gl_state, &level, &camera); + graphics.draw (&level.phys_tris, &predicted_logic, &mut gl_state, &level, &level.camera); graphics.frames += 1; if graphics.frames == next_upf_print { @@ -281,10 +185,3 @@ struct TriangleStream { pub indices: gpu_buffers::IndexBuffer, } */ -pub struct Camera { - transform: gltf::scene::Transform, -} - -fn gltf_node_get_mat4 (node: &gltf::Node) -> Mat4 { - Mat4::from_cols_array_2d (&node.transform ().matrix ()) -}