mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Improve glider rotation
This commit is contained in:
parent
29b0aafdad
commit
a23a2a7b92
@ -3,7 +3,7 @@ use crate::{
|
|||||||
comp::{inventory::slot::EquipSlot, CharacterState, ControllerInputs, Ori, StateUpdate, Vel},
|
comp::{inventory::slot::EquipSlot, CharacterState, ControllerInputs, Ori, StateUpdate, Vel},
|
||||||
glider::Glider,
|
glider::Glider,
|
||||||
states::behavior::{CharacterBehavior, JoinData},
|
states::behavior::{CharacterBehavior, JoinData},
|
||||||
util::Dir,
|
util::{Dir, Plane, Projection},
|
||||||
};
|
};
|
||||||
use inline_tweak::tweak;
|
use inline_tweak::tweak;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -60,16 +60,19 @@ impl Data {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tgt_up(&self, max_roll: f32, tgt_dir: &Dir, flow_dir: &Dir, data: &JoinData) -> Dir {
|
fn roll_dir(&self, max_roll: f32, tgt_dir: &Dir, flow_dir: &Dir, data: &JoinData) -> Dir {
|
||||||
let char_up = data.ori.up();
|
let char_up = data.ori.up();
|
||||||
Dir::from_unnormalized(tgt_dir.to_vec() + flow_dir.to_vec())
|
Dir::from_unnormalized(tgt_dir.to_vec() + flow_dir.to_vec())
|
||||||
.map(|tgt_lift_dir| {
|
.map(|tgt_lift_dir| {
|
||||||
|
// this rolls to decrease the surface exposed to unfavourable wind that is
|
||||||
|
// causing us to drift off course
|
||||||
tgt_lift_dir.slerped_to(
|
tgt_lift_dir.slerped_to(
|
||||||
-*flow_dir,
|
-*flow_dir,
|
||||||
Dir::from_unnormalized(data.vel.0)
|
Dir::from_unnormalized(data.vel.0)
|
||||||
.map_or(0.0, |moving_dir| moving_dir.dot(flow_dir.to_vec()).max(0.0)),
|
.map_or(0.0, |moving_dir| moving_dir.dot(flow_dir.to_vec()).max(0.0)),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
.and_then(|dir| dir.projected(&Plane::from(data.ori.look_dir())))
|
||||||
.and_then(|dir| {
|
.and_then(|dir| {
|
||||||
(dir.dot(*char_up) > max_roll.cos())
|
(dir.dot(*char_up) > max_roll.cos())
|
||||||
.then_some(dir)
|
.then_some(dir)
|
||||||
@ -79,7 +82,6 @@ impl Data {
|
|||||||
.try_normalized()
|
.try_normalized()
|
||||||
.map(|axis| Quaternion::rotation_3d(max_roll, axis) * char_up)
|
.map(|axis| Quaternion::rotation_3d(max_roll, axis) * char_up)
|
||||||
})
|
})
|
||||||
.filter(|dir| dir.dot(*self.glider.ori.up()).is_sign_positive())
|
|
||||||
})
|
})
|
||||||
.unwrap_or(char_up)
|
.unwrap_or(char_up)
|
||||||
}
|
}
|
||||||
@ -101,11 +103,11 @@ impl CharacterBehavior for Data {
|
|||||||
} else if !handle_climb(&data, &mut update) {
|
} else if !handle_climb(&data, &mut update) {
|
||||||
// Tweaks
|
// Tweaks
|
||||||
let base_pitch = BASE_PITCH * tweak!(1.0);
|
let base_pitch = BASE_PITCH * tweak!(1.0);
|
||||||
let max_pitch = tweak!(0.3) * PI;
|
let max_pitch = tweak!(0.2) * PI;
|
||||||
let max_roll = tweak!(0.2) * PI;
|
let max_roll = tweak!(0.5) * PI;
|
||||||
let inputs_rate = tweak!(5.0);
|
let inputs_rate = tweak!(5.0);
|
||||||
let look_pitch_rate = tweak!(10.0);
|
let look_pitch_rate = tweak!(5.0);
|
||||||
let autoroll_rate = tweak!(10.0);
|
let autoroll_rate = tweak!(5.0);
|
||||||
let yaw_correction_rate = tweak!(1.0);
|
let yaw_correction_rate = tweak!(1.0);
|
||||||
let char_yaw_follow_rate = tweak!(2.0);
|
let char_yaw_follow_rate = tweak!(2.0);
|
||||||
// ----
|
// ----
|
||||||
@ -118,39 +120,42 @@ impl CharacterBehavior for Data {
|
|||||||
let flow_dir = Dir::from_unnormalized(air_flow.0).unwrap_or_else(Dir::up);
|
let flow_dir = Dir::from_unnormalized(air_flow.0).unwrap_or_else(Dir::up);
|
||||||
let tgt_dir = self.tgt_dir(base_pitch, max_pitch, data);
|
let tgt_dir = self.tgt_dir(base_pitch, max_pitch, data);
|
||||||
|
|
||||||
let char_up = data.ori.up();
|
|
||||||
|
|
||||||
let ori = self.glider.ori;
|
let ori = self.glider.ori;
|
||||||
let mut glider = self.glider;
|
let mut glider = self.glider;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
let char_fw = data.ori.look_dir();
|
||||||
|
let char_up = data.ori.up();
|
||||||
let glider_up = ori.up();
|
let glider_up = ori.up();
|
||||||
let up_dot = glider_up.dot(*char_up);
|
let glider_right = ori.right();
|
||||||
|
let mut next_up = glider_up;
|
||||||
|
|
||||||
if let Some(roll_input) = self.roll_input(data.inputs) {
|
if let Some(roll_input) = self.roll_input(data.inputs) {
|
||||||
if (up_dot - max_roll.cos()).is_sign_positive()
|
next_up = next_up.slerped_to(
|
||||||
|| (ori.right().dot(*char_up).is_sign_positive()
|
Quaternion::rotation_3d(roll_input * max_roll, char_fw) * char_up,
|
||||||
== roll_input.is_sign_positive())
|
data.dt.0 * inputs_rate,
|
||||||
{
|
|
||||||
glider.roll(data.dt.0 * inputs_rate * roll_input * max_roll);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let tgt_up = self.tgt_up(max_roll, &tgt_dir, &flow_dir, data);
|
|
||||||
glider.slerp_roll_towards(
|
|
||||||
tgt_up,
|
|
||||||
autoroll_rate * (1.0 - tgt_up.dot(*glider_up).max(0.0).powi(2)) * data.dt.0,
|
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
let roll_dir = self.roll_dir(max_roll, &tgt_dir, &flow_dir, data);
|
||||||
|
let s = 1.0 - roll_dir.dot(*glider_up).abs();
|
||||||
|
next_up = next_up.slerped_to(roll_dir, data.dt.0 * autoroll_rate * s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(pitch_input) = self.pitch_input(data.inputs) {
|
if let Some(pitch_input) = self.pitch_input(data.inputs) {
|
||||||
if (up_dot - max_pitch.cos()).is_sign_positive()
|
next_up = next_up.slerped_to(
|
||||||
|| (ori.look_dir().dot(*char_up).is_sign_negative()
|
Quaternion::rotation_3d(pitch_input * max_pitch, glider_right) * char_up,
|
||||||
== pitch_input.is_sign_positive())
|
data.dt.0 * inputs_rate,
|
||||||
{
|
);
|
||||||
glider.pitch(data.dt.0 * inputs_rate * pitch_input * max_pitch);
|
} else {
|
||||||
}
|
// slerp un-pitching for more stable rolling
|
||||||
|
let tgt_fw = tgt_dir.slerped_to(char_fw, tgt_dir.dot(*glider_right).powi(2));
|
||||||
|
next_up = next_up.slerped_to(
|
||||||
|
data.ori.pitched_towards(tgt_fw).up(),
|
||||||
|
data.dt.0 * look_pitch_rate,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
glider.slerp_pitch_towards(tgt_dir, look_pitch_rate * data.dt.0);
|
|
||||||
|
glider.ori = ori.prerotated(glider_up.rotation_between(next_up));
|
||||||
}
|
}
|
||||||
|
|
||||||
glider.slerp_yaw_towards(-flow_dir, data.dt.0 * yaw_correction_rate);
|
glider.slerp_yaw_towards(-flow_dir, data.dt.0 * yaw_correction_rate);
|
||||||
|
Loading…
Reference in New Issue
Block a user