Switch free flight mode to quaternion

main
_ 2020-03-09 01:53:08 +00:00
parent 3d9f8e1a13
commit 372761c1b2
1 changed files with 80 additions and 39 deletions

View File

@ -32,6 +32,35 @@ where V: Into <Vec3>
)) ))
} }
struct EulerAngles {
pub azimuth: f32,
pub altitude: f32,
}
impl Default for EulerAngles {
fn default () -> Self {
Self {
azimuth: 0.0,
altitude: 0.0,
}
}
}
impl EulerAngles {
pub fn to_vec3 (&self) -> Vec3 {
let alt = self.altitude.to_radians ();
let azi = self.azimuth.to_radians ();
let z = alt.sin ();
let xy_len = alt.cos ();
let x = xy_len * -azi.sin ();
let y = xy_len * azi.cos ();
(x, y, z).into ()
}
}
// TODO: Use iota macro // TODO: Use iota macro
const KEY_LEFT: usize = 0; const KEY_LEFT: usize = 0;
const KEY_RIGHT: usize = KEY_LEFT + 1; const KEY_RIGHT: usize = KEY_LEFT + 1;
@ -71,52 +100,57 @@ impl ControllerState {
if self.is_pressed (KEY_LEFT) { if self.is_pressed (KEY_LEFT) {
controlled_angle.azimuth += spin_f; controlled_angle.azimuth += spin_f;
std::cmp::min (spin_speed + 1, SPIN_RAMP_TIME)
} }
else if self.is_pressed (KEY_RIGHT) { else if self.is_pressed (KEY_RIGHT) {
controlled_angle.azimuth -= spin_f; controlled_angle.azimuth -= spin_f;
std::cmp::min (spin_speed + 1, SPIN_RAMP_TIME)
} }
else if self.is_pressed (KEY_UP) { else if self.is_pressed (KEY_UP) {
controlled_angle.altitude = f32::min (90.0, controlled_angle.altitude + spin_f); 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) { else if self.is_pressed (KEY_DOWN) {
controlled_angle.altitude = f32::max (-90.0, controlled_angle.altitude - spin_f); controlled_angle.altitude = f32::max (-90.0, controlled_angle.altitude - spin_f);
std::cmp::min (spin_speed + 1, SPIN_RAMP_TIME)
} }
else { else {
return 0;
}
std::cmp::min (spin_speed + 1, SPIN_RAMP_TIME)
}
pub fn control_quat (
&self,
controlled_quat: &mut Quat,
spin_speed: i32
) -> i32
{
const SPIN_RAMP_TIME: i32 = 30;
let spin_f = 4.0 * (spin_speed + 1) as f32 / SPIN_RAMP_TIME as f32;
let spin_f = spin_f.to_radians ();
let mut delta = Quat::default ();
if self.is_pressed (KEY_LEFT) {
delta = delta.mul_quat (Quat::from_rotation_y (-spin_f));
}
if self.is_pressed (KEY_RIGHT) {
delta = delta.mul_quat (Quat::from_rotation_y (spin_f));
}
if self.is_pressed (KEY_UP) {
delta = delta.mul_quat (Quat::from_rotation_x (-spin_f));
}
if self.is_pressed (KEY_DOWN) {
delta = delta.mul_quat (Quat::from_rotation_x (spin_f));
}
//println! ("spin_f {}, Quat {:?}", spin_f, delta);
if delta == Quat::default () {
0 0
} }
else {
*controlled_quat = (controlled_quat.mul_quat (delta)).normalize ();
std::cmp::min (spin_speed + 1, SPIN_RAMP_TIME)
} }
}
struct EulerAngles {
pub azimuth: f32,
pub altitude: f32,
}
impl Default for EulerAngles {
fn default () -> Self {
Self {
azimuth: 0.0,
altitude: 0.0,
}
}
}
impl EulerAngles {
pub fn to_vec3 (&self) -> Vec3 {
let alt = self.altitude.to_radians ();
let azi = self.azimuth.to_radians ();
let z = alt.sin ();
let xy_len = alt.cos ();
let x = xy_len * -azi.sin ();
let y = xy_len * azi.cos ();
(x, y, z).into ()
} }
} }
@ -143,8 +177,13 @@ struct WindTunnelState {
spin_speed: i32, spin_speed: i32,
} }
struct Airplane {
pos: Vec3,
ori: Quat,
}
struct FlightState { struct FlightState {
airplane: EulerAngles, airplane: Airplane,
spin_speed: i32, spin_speed: i32,
} }
@ -154,7 +193,7 @@ impl FlightState {
} }
pub fn step (&mut self, controller: &ControllerState) { pub fn step (&mut self, controller: &ControllerState) {
self.spin_speed = controller.control_eulers (&mut self.airplane, self.spin_speed); self.spin_speed = controller.control_quat (&mut self.airplane.ori, self.spin_speed);
} }
} }
@ -214,7 +253,10 @@ impl WorldState {
spin_speed: 0, spin_speed: 0,
}, },
flight: FlightState { flight: FlightState {
airplane: Default::default (), airplane: Airplane {
pos: (0.0, 0.0, 1.35).into (),
ori: Default::default (),
},
spin_speed: 0, spin_speed: 0,
}, },
} }
@ -986,10 +1028,9 @@ impl GameGraphics {
Mat4::from_rotation_x (euler.altitude.to_radians ()) Mat4::from_rotation_x (euler.altitude.to_radians ())
}, },
PlayMode::FreeFlight => { PlayMode::FreeFlight => {
let euler = &state.flight.airplane; let airplane = &state.flight.airplane;
Mat4::from_translation ((0.0, 0.0, 2.7 * 0.5).into ()) * Mat4::from_translation (airplane.pos) *
Mat4::from_rotation_z (euler.azimuth.to_radians ()) * Mat4::from_quat (airplane.ori)
Mat4::from_rotation_x (euler.altitude.to_radians ())
}, },
}; };
let inverse_airplane = airplane_model_mat.inverse (); let inverse_airplane = airplane_model_mat.inverse ();