diff --git a/src/bin/pumpkin.rs b/src/bin/pumpkin.rs index 41ef619..04c8abd 100644 --- a/src/bin/pumpkin.rs +++ b/src/bin/pumpkin.rs @@ -1,7 +1,7 @@ #[macro_use] extern crate maplit; -use glam::{Mat4, Vec3, Vec4}; +use glam::{Mat4, Quat, Vec3, Vec4}; use sdl2::event::Event; use sdl2::keyboard::{Keycode, Scancode}; @@ -59,6 +59,36 @@ impl ControllerState { pub fn is_pressed (&self, code: usize) -> bool { self.keys [code] } + + pub fn control_eulers ( + &self, + controlled_angle: &mut EulerAngles, + spin_speed: i32 + ) -> i32 + { + const SPIN_RAMP_TIME: i32 = 30; + let spin_f = 4.0 * spin_speed as f32 / SPIN_RAMP_TIME as f32; + + if self.is_pressed (KEY_LEFT) { + controlled_angle.azimuth += spin_f; + std::cmp::min (spin_speed + 1, SPIN_RAMP_TIME) + } + else if self.is_pressed (KEY_RIGHT) { + controlled_angle.azimuth -= spin_f; + std::cmp::min (spin_speed + 1, SPIN_RAMP_TIME) + } + else if self.is_pressed (KEY_UP) { + controlled_angle.altitude = f32::min (90.0, controlled_angle.altitude + spin_f); + std::cmp::min (spin_speed + 1, SPIN_RAMP_TIME) + } + else if self.is_pressed (KEY_DOWN) { + controlled_angle.altitude = f32::max (-90.0, controlled_angle.altitude - spin_f); + std::cmp::min (spin_speed + 1, SPIN_RAMP_TIME) + } + else { + 0 + } + } } struct EulerAngles { @@ -113,9 +143,25 @@ struct WindTunnelState { spin_speed: i32, } +struct FlightState { + airplane: EulerAngles, + spin_speed: i32, +} + +impl FlightState { + pub fn handle_event (&mut self, event: &sdl2::event::Event) { + + } + + pub fn step (&mut self, controller: &ControllerState) { + self.spin_speed = controller.control_eulers (&mut self.airplane, self.spin_speed); + } +} + struct WorldState { play_mode: PlayMode, wind_tunnel: WindTunnelState, + flight: FlightState, } impl WindTunnelState { @@ -141,10 +187,6 @@ impl WindTunnelState { &mut self, controller: &ControllerState ) { - const SPIN_RAMP_TIME: i32 = 30; - - let spin_f = 4.0 * self.spin_speed as f32 / SPIN_RAMP_TIME as f32; - let controlled_angle = match self.user_control { UserControl::Camera => &mut self.camera, UserControl::Wind => &mut self.wind, @@ -152,25 +194,7 @@ impl WindTunnelState { UserControl::Sunlight => &mut self.sunlight, }; - if controller.is_pressed (KEY_LEFT) { - self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME); - controlled_angle.azimuth += spin_f; - } - else if controller.is_pressed (KEY_RIGHT) { - self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME); - controlled_angle.azimuth -= spin_f; - } - else if controller.is_pressed (KEY_UP) { - self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME); - controlled_angle.altitude = f32::min (90.0, controlled_angle.altitude + spin_f); - } - else if controller.is_pressed (KEY_DOWN) { - self.spin_speed = std::cmp::min (self.spin_speed + 1, SPIN_RAMP_TIME); - controlled_angle.altitude = f32::max (-90.0, controlled_angle.altitude - spin_f); - } - else { - self.spin_speed = 0; - } + self.spin_speed = controller.control_eulers (controlled_angle, self.spin_speed); } } @@ -189,6 +213,10 @@ impl WorldState { }, spin_speed: 0, }, + flight: FlightState { + airplane: Default::default (), + spin_speed: 0, + }, } } @@ -197,9 +225,12 @@ impl WorldState { Event::KeyDown { keycode: Some (Keycode::T), .. } => { self.play_mode = PlayMode::WindTunnel; }, + Event::KeyDown { keycode: Some (Keycode::F), .. } => { + self.play_mode = PlayMode::FreeFlight; + }, _ => match self.play_mode { PlayMode::WindTunnel => self.wind_tunnel.handle_event (event), - _ => (), + PlayMode::FreeFlight => self.flight.handle_event (event), }, } } @@ -210,7 +241,7 @@ impl WorldState { ) { match self.play_mode { PlayMode::WindTunnel => self.wind_tunnel.step (controller), - _ => (), + PlayMode::FreeFlight => self.flight.step (controller), } } } @@ -931,6 +962,38 @@ impl GameGraphics { green, ]; + let light = state.wind_tunnel.sunlight.to_vec3 (); + + let shadow_mat = { + let mut mat = Mat4::identity (); + mat.set_z_axis ((-light.x () / light.z (), -light.y () / light.z (), 0.0, 0.0).into ()); + mat + }; + + let mut passes = self.passes.iter (); + //println! ("Started frame"); + + passes.next ().unwrap ().with (gl_state, || { + glezz::clear_color (1.0f32, 0.0f32, 1.0f32, 1.0f32); + glezz::clear (gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT); + }); + + let airplane_model_mat = match state.play_mode { + PlayMode::WindTunnel => { + let euler = &state.wind_tunnel.airplane; + Mat4::from_translation ((0.0, 0.0, 2.7 * 0.5).into ()) * + Mat4::from_rotation_z (euler.azimuth.to_radians ()) * + Mat4::from_rotation_x (euler.altitude.to_radians ()) + }, + PlayMode::FreeFlight => { + let euler = &state.flight.airplane; + Mat4::from_translation ((0.0, 0.0, 2.7 * 0.5).into ()) * + Mat4::from_rotation_z (euler.azimuth.to_radians ()) * + Mat4::from_rotation_x (euler.altitude.to_radians ()) + }, + }; + let inverse_airplane = airplane_model_mat.inverse (); + let proj_mat = Mat4::perspective_rh_gl (30.0f32.to_radians (), 1280.0 / 720.0, 0.5, 500.0); let view_mat = match state.play_mode { @@ -946,43 +1009,18 @@ impl GameGraphics { Mat4::from_rotation_z (longitude) * Mat4::from_translation ((0.0, 0.0, -2.7 * 0.5).into ()) }, - _ => proj_mat, - }; - - let light = state.wind_tunnel.sunlight.to_vec3 (); - - let shadow_mat = { - let mut mat = Mat4::identity (); - mat.set_z_axis ((-light.x () / light.z (), -light.y () / light.z (), 0.0, 0.0).into ()); - mat - }; - - - - let sky_mvp_mat = view_mat * Mat4::from_scale ((16.0, 16.0, 16.0).into ()); - - //println! ("Started frame"); - - let mut passes = self.passes.iter (); - - passes.next ().unwrap ().with (gl_state, || { - glezz::clear_color (1.0f32, 0.0f32, 1.0f32, 1.0f32); - glezz::clear (gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT); - }); - - let airplane_model_mat = match state.play_mode { - PlayMode::WindTunnel => { - let state = &state.wind_tunnel; - Mat4::from_translation ((0.0, 0.0, 2.7 * 0.5).into ()) * - Mat4::from_scale ((0.125, 0.125, 0.125).into ()) * - Mat4::from_rotation_z (state.airplane.azimuth.to_radians ()) * - Mat4::from_rotation_x (state.airplane.altitude.to_radians ()) + PlayMode::FreeFlight => { + proj_mat * + Mat4::from_translation ((0.0, -0.6, -4.0).into ()) * + Mat4::from_rotation_x (-90.0f32.to_radians ()) * + inverse_airplane }, - _ => Mat4::identity (), }; + let airplane_model_mat = airplane_model_mat * + Mat4::from_scale ((0.125, 0.125, 0.125).into ()); + let world_model_mat = Mat4::identity (); - let inverse_pumpkin = airplane_model_mat.inverse (); use uniforms::*; @@ -995,9 +1033,8 @@ impl GameGraphics { let mvp = view_mat * airplane_model_mat; glezz::uniform_matrix_4fv (unis [&MVP], &mvp); - let object_space_light = make_object_space_vec (&inverse_pumpkin, &light); - - let object_space_sky = make_object_space_vec (&inverse_pumpkin, &Vec3::from ((0.0, 0.0, 1.0))); + let object_space_light = make_object_space_vec (&inverse_airplane, &light); + let object_space_sky = make_object_space_vec (&inverse_airplane, &Vec3::from ((0.0, 0.0, 1.0))); glezz::uniform_3fv (unis [&MIN_BRIGHT], &black); glezz::uniform_3fv (unis [&MIN_ALBEDO], &white); @@ -1023,6 +1060,8 @@ impl GameGraphics { let draw_sky = true; if draw_sky { + let sky_mvp_mat = view_mat * Mat4::from_scale ((16.0, 16.0, 16.0).into ()); + self.texture.bind (); glezz::uniform_matrix_4fv (unis [&MVP], &sky_mvp_mat); glezz::uniform_3fv (unis [&ALBEDO], &white);