mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Gliding Debug Info
This commit is contained in:
parent
fab5c54253
commit
0858279810
@ -243,8 +243,9 @@ impl Body {
|
||||
Body::BirdMedium(_) | Body::BirdLarge(_) | Body::Dragon(_) => {
|
||||
let dim = self.dimensions().map(|a| a * 0.5);
|
||||
let cd: f32 = match self {
|
||||
// "Field Estimates of Body Drag Coefficient on the Basis of Dives in Passerine
|
||||
// Birds", Anders Hedenström and Felix Liechti, 2001
|
||||
// "Field Estimates of Body Drag Coefficient
|
||||
// on the Basis of Dives in Passerine Birds",
|
||||
// Anders Hedenström and Felix Liechti, 2001
|
||||
Body::BirdLarge(_) | Body::BirdMedium(_) => 0.2,
|
||||
// arbitrary
|
||||
_ => 0.7,
|
||||
@ -370,7 +371,8 @@ pub fn zero_lift_drag_coefficient(planform_area: f32) -> f32 { planform_area * 0
|
||||
/// freestream flow
|
||||
/// 2. up to around ~18°, at which point maximum lift has been achieved and
|
||||
/// thereafter falls precipitously, causing a stall (this is the stall
|
||||
/// angle) 3. effective aoa, i.e. geometric aoa - induced aoa; assumes
|
||||
/// angle)
|
||||
/// 3. effective aoa, i.e. geometric aoa - induced aoa; assumes
|
||||
/// no sideslip
|
||||
// TODO: Look into handling tapered wings
|
||||
fn lift_slope(aspect_ratio: f32, sweep_angle: Option<f32>) -> f32 {
|
||||
|
@ -69,8 +69,8 @@ fn integrate_forces(
|
||||
// This way we can only ever lose velocity and will never experience a reverse
|
||||
// in direction from events such as falling into water at high velocities.
|
||||
if new_v.dot(vel.0) < 0.0 {
|
||||
// Multiply by a factor to prevent full stop, as this can cause things to get
|
||||
// stuck in high-density medium
|
||||
// Multiply by a factor to prevent full stop,
|
||||
// as this can cause things to get stuck in high-density medium
|
||||
vel.0 -= vel.0.projected(&impulse) * 0.9;
|
||||
} else {
|
||||
vel.0 = new_v;
|
||||
|
@ -74,7 +74,7 @@ use client::Client;
|
||||
use common::{
|
||||
combat,
|
||||
comp::{
|
||||
self,
|
||||
self, fluid_dynamics,
|
||||
inventory::trade_pricing::TradePricing,
|
||||
item::{tool::ToolKind, ItemDesc, MaterialStatManifest, Quality},
|
||||
skills::{Skill, SkillGroupKind},
|
||||
@ -86,7 +86,7 @@ use common::{
|
||||
terrain::{SpriteKind, TerrainChunk},
|
||||
trade::{ReducedInventory, TradeAction},
|
||||
uid::Uid,
|
||||
util::srgba_to_linear,
|
||||
util::{srgba_to_linear, Dir},
|
||||
vol::RectRasterableVol,
|
||||
};
|
||||
use common_base::{prof_span, span};
|
||||
@ -233,7 +233,10 @@ widget_ids! {
|
||||
ping,
|
||||
coordinates,
|
||||
velocity,
|
||||
glide_ratio,
|
||||
glide_aoe,
|
||||
orientation,
|
||||
look_direction,
|
||||
loaded_distance,
|
||||
time,
|
||||
entity_count,
|
||||
@ -441,6 +444,9 @@ pub struct DebugInfo {
|
||||
pub coordinates: Option<comp::Pos>,
|
||||
pub velocity: Option<comp::Vel>,
|
||||
pub ori: Option<comp::Ori>,
|
||||
pub character_state: Option<comp::CharacterState>,
|
||||
pub look_dir: Dir,
|
||||
pub in_fluid: Option<comp::Fluid>,
|
||||
pub num_chunks: u32,
|
||||
pub num_lights: u32,
|
||||
pub num_visible_chunks: u32,
|
||||
@ -2150,6 +2156,8 @@ impl Hud {
|
||||
}
|
||||
|
||||
// Display debug window.
|
||||
// TODO:
|
||||
// Make it use i18n keys.
|
||||
if let Some(debug_info) = debug_info {
|
||||
prof_span!("debug info");
|
||||
// Alpha Version
|
||||
@ -2192,15 +2200,31 @@ impl Hud {
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.set(self.ids.coordinates, ui_widgets);
|
||||
// Player's velocity
|
||||
let velocity_text = match debug_info.velocity {
|
||||
Some(velocity) => format!(
|
||||
let (velocity_text, glide_ratio_text) = match debug_info.velocity {
|
||||
Some(velocity) => {
|
||||
let velocity = velocity.0;
|
||||
let velocity_text = format!(
|
||||
"Velocity: ({:.1}, {:.1}, {:.1}) [{:.1} u/s]",
|
||||
velocity.0.x,
|
||||
velocity.0.y,
|
||||
velocity.0.z,
|
||||
velocity.0.magnitude()
|
||||
),
|
||||
None => "Player has no Vel component".to_owned(),
|
||||
velocity.x,
|
||||
velocity.y,
|
||||
velocity.z,
|
||||
velocity.magnitude()
|
||||
);
|
||||
let horizontal_velocity = velocity.xy().magnitude();
|
||||
let dz = velocity.z;
|
||||
// don't divide by zero
|
||||
let glide_ratio_text = if dz.abs() > 0.0001 {
|
||||
format!("Glide Ratio: {:.1}", (-1.0) * (horizontal_velocity / dz))
|
||||
} else {
|
||||
"Glide Ratio: Altitude is constant".to_owned()
|
||||
};
|
||||
|
||||
(velocity_text, glide_ratio_text)
|
||||
},
|
||||
None => {
|
||||
let err = "Player has no Vel component";
|
||||
(err.to_owned(), err.to_owned())
|
||||
},
|
||||
};
|
||||
Text::new(&velocity_text)
|
||||
.color(TEXT_COLOR)
|
||||
@ -2208,23 +2232,54 @@ impl Hud {
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.set(self.ids.velocity, ui_widgets);
|
||||
Text::new(&glide_ratio_text)
|
||||
.color(TEXT_COLOR)
|
||||
.down_from(self.ids.velocity, 5.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.set(self.ids.glide_ratio, ui_widgets);
|
||||
let glide_angle_text = angle_of_attack_text(
|
||||
debug_info.in_fluid,
|
||||
debug_info.velocity,
|
||||
debug_info.character_state.as_ref(),
|
||||
);
|
||||
Text::new(&glide_angle_text)
|
||||
.color(TEXT_COLOR)
|
||||
.down_from(self.ids.glide_ratio, 5.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.set(self.ids.glide_aoe, ui_widgets);
|
||||
// Player's orientation vector
|
||||
let orientation_text = match debug_info.ori {
|
||||
Some(ori) => {
|
||||
let look_dir = ori.look_dir();
|
||||
let orientation = ori.look_dir();
|
||||
format!(
|
||||
"Orientation: ({:.1}, {:.1}, {:.1})",
|
||||
look_dir.x, look_dir.y, look_dir.z,
|
||||
"Orientation: ({:.2}, {:.2}, {:.2})",
|
||||
orientation.x, orientation.y, orientation.z,
|
||||
)
|
||||
},
|
||||
None => "Player has no Ori component".to_owned(),
|
||||
};
|
||||
Text::new(&orientation_text)
|
||||
.color(TEXT_COLOR)
|
||||
.down_from(self.ids.velocity, 5.0)
|
||||
.down_from(self.ids.glide_aoe, 5.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.set(self.ids.orientation, ui_widgets);
|
||||
let look_dir_text = {
|
||||
let look_vec = debug_info.look_dir.to_vec();
|
||||
|
||||
format!(
|
||||
"Look Direction: ({:.2}, {:.2}, {:.2})",
|
||||
look_vec.x, look_vec.y, look_vec.z,
|
||||
)
|
||||
};
|
||||
Text::new(&look_dir_text)
|
||||
.color(TEXT_COLOR)
|
||||
.down_from(self.ids.orientation, 5.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.set(self.ids.look_direction, ui_widgets);
|
||||
// Loaded distance
|
||||
Text::new(&format!(
|
||||
"View distance: {:.2} blocks ({:.2} chunks)",
|
||||
@ -2232,7 +2287,7 @@ impl Hud {
|
||||
client.loaded_distance() / TerrainChunk::RECT_SIZE.x as f32,
|
||||
))
|
||||
.color(TEXT_COLOR)
|
||||
.down_from(self.ids.orientation, 5.0)
|
||||
.down_from(self.ids.look_direction, 5.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.set(self.ids.loaded_distance, ui_widgets);
|
||||
@ -4007,3 +4062,39 @@ pub fn get_buff_time(buff: BuffInfo) -> String {
|
||||
"".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn angle_of_attack_text(
|
||||
fluid: Option<comp::Fluid>,
|
||||
velocity: Option<comp::Vel>,
|
||||
character_state: Option<&comp::CharacterState>,
|
||||
) -> String {
|
||||
use comp::CharacterState;
|
||||
|
||||
let glider_ori = if let Some(CharacterState::Glide(data)) = character_state {
|
||||
data.ori
|
||||
} else {
|
||||
return "Angle of Attack: Not gliding".to_owned();
|
||||
};
|
||||
|
||||
let fluid = if let Some(fluid) = fluid {
|
||||
fluid
|
||||
} else {
|
||||
return "Angle of Attack: Not in fluid".to_owned();
|
||||
};
|
||||
|
||||
let velocity = if let Some(velocity) = velocity {
|
||||
velocity
|
||||
} else {
|
||||
return "Angle of Attack: Player has no vel component".to_owned();
|
||||
};
|
||||
let rel_flow = fluid.relative_flow(&velocity).0;
|
||||
let v_sq = rel_flow.magnitude_squared();
|
||||
|
||||
if v_sq.abs() > 0.0001 {
|
||||
let rel_flow_dir = Dir::new(rel_flow / v_sq.sqrt());
|
||||
let aoe = fluid_dynamics::angle_of_attack(&glider_ori, &rel_flow_dir);
|
||||
format!("Angle of Attack: {:.1}", aoe.to_degrees())
|
||||
} else {
|
||||
"Angle of Attack: Not moving".to_owned()
|
||||
}
|
||||
}
|
||||
|
@ -583,9 +583,11 @@ impl PlayState for SessionState {
|
||||
}
|
||||
},
|
||||
GameInput::Fly => {
|
||||
// Not sure where to put comment, but I noticed when testing flight
|
||||
// Syncing of inputs between mounter and mountee broke with
|
||||
// controller change
|
||||
// Not sure where to put comment, but I noticed
|
||||
// when testing flight.
|
||||
//
|
||||
// Syncing of inputs between mounter and mountee
|
||||
// broke with controller change
|
||||
self.key_state.fly ^= state;
|
||||
let mut client = self.client.borrow_mut();
|
||||
client.handle_input(
|
||||
@ -978,40 +980,36 @@ impl PlayState for SessionState {
|
||||
.camera_mut()
|
||||
.compute_dependents(&*self.client.borrow().state().terrain());
|
||||
|
||||
// Generate debug info, if needed (it iterates through enough data that we might
|
||||
// Generate debug info, if needed
|
||||
// (it iterates through enough data that we might
|
||||
// as well avoid it unless we need it).
|
||||
let debug_info = global_state
|
||||
.settings
|
||||
.interface
|
||||
.toggle_debug
|
||||
.then(|| DebugInfo {
|
||||
let debug_info = global_state.settings.interface.toggle_debug.then(|| {
|
||||
let client = self.client.borrow();
|
||||
let ecs = client.state().ecs();
|
||||
let entity = client.entity();
|
||||
let coordinates = ecs.read_storage::<Pos>().get(entity).cloned();
|
||||
let velocity = ecs.read_storage::<Vel>().get(entity).cloned();
|
||||
let ori = ecs.read_storage::<comp::Ori>().get(entity).cloned();
|
||||
let look_dir = self.inputs.look_dir;
|
||||
let in_fluid = ecs
|
||||
.read_storage::<comp::PhysicsState>()
|
||||
.get(entity)
|
||||
.and_then(|state| state.in_fluid);
|
||||
let character_state = ecs
|
||||
.read_storage::<comp::CharacterState>()
|
||||
.get(entity)
|
||||
.cloned();
|
||||
|
||||
DebugInfo {
|
||||
tps: global_state.clock.stats().average_tps,
|
||||
frame_time: global_state.clock.stats().average_busy_dt,
|
||||
ping_ms: self.client.borrow().get_ping_ms_rolling_avg(),
|
||||
coordinates: self
|
||||
.client
|
||||
.borrow()
|
||||
.state()
|
||||
.ecs()
|
||||
.read_storage::<Pos>()
|
||||
.get(self.client.borrow().entity())
|
||||
.cloned(),
|
||||
velocity: self
|
||||
.client
|
||||
.borrow()
|
||||
.state()
|
||||
.ecs()
|
||||
.read_storage::<Vel>()
|
||||
.get(self.client.borrow().entity())
|
||||
.cloned(),
|
||||
ori: self
|
||||
.client
|
||||
.borrow()
|
||||
.state()
|
||||
.ecs()
|
||||
.read_storage::<comp::Ori>()
|
||||
.get(self.client.borrow().entity())
|
||||
.cloned(),
|
||||
coordinates,
|
||||
velocity,
|
||||
ori,
|
||||
look_dir,
|
||||
character_state,
|
||||
in_fluid,
|
||||
num_chunks: self.scene.terrain().chunk_count() as u32,
|
||||
num_lights: self.scene.lights().len() as u32,
|
||||
num_visible_chunks: self.scene.terrain().visible_chunk_count() as u32,
|
||||
@ -1021,6 +1019,7 @@ impl PlayState for SessionState {
|
||||
num_particles: self.scene.particle_mgr().particle_count() as u32,
|
||||
num_particles_visible: self.scene.particle_mgr().particle_count_visible()
|
||||
as u32,
|
||||
}
|
||||
});
|
||||
|
||||
// Extract HUD events ensuring the client borrow gets dropped.
|
||||
|
Loading…
Reference in New Issue
Block a user