mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Fix client-side wind simulation
- Apply local wind on the client WeatherGrid - Set air_vel to zero if not simulating
This commit is contained in:
parent
5c517e88c9
commit
a06e79b089
@ -237,6 +237,7 @@ impl WeatherLerp {
|
||||
.zip(old.iter().zip(new.iter()))
|
||||
.for_each(|((_, current), ((_, old), (_, new)))| {
|
||||
*current = CompressedWeather::lerp_unclamped(old, new, t);
|
||||
current.wind = self.local_wind;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -143,71 +143,71 @@ impl Body {
|
||||
Vec3::zero()
|
||||
} else {
|
||||
let rel_flow_dir = Dir::new(rel_flow.0 / v_sq.sqrt());
|
||||
0.5 * fluid_density
|
||||
* v_sq
|
||||
* match wings {
|
||||
Some(&Wings {
|
||||
aspect_ratio,
|
||||
planform_area,
|
||||
ori,
|
||||
}) => {
|
||||
if aspect_ratio > 25.0 {
|
||||
tracing::warn!(
|
||||
"Calculating lift for wings with an aspect ratio of {}. The \
|
||||
formulas are only valid for aspect ratios below 25.",
|
||||
aspect_ratio
|
||||
)
|
||||
};
|
||||
let ar = aspect_ratio.min(24.0);
|
||||
// We have an elliptical wing; proceed to calculate its lift and drag
|
||||
let power_vec = match wings {
|
||||
Some(&Wings {
|
||||
aspect_ratio,
|
||||
planform_area,
|
||||
ori,
|
||||
}) => {
|
||||
if aspect_ratio > 25.0 {
|
||||
tracing::warn!(
|
||||
"Calculating lift for wings with an aspect ratio of {}. The formulas \
|
||||
are only valid for aspect ratios below 25.",
|
||||
aspect_ratio
|
||||
)
|
||||
};
|
||||
let ar = aspect_ratio.min(24.0);
|
||||
// We have an elliptical wing; proceed to calculate its lift and drag
|
||||
|
||||
// aoa will be positive when we're pitched up and negative otherwise
|
||||
let aoa = angle_of_attack(&ori, &rel_flow_dir);
|
||||
// c_l will be positive when aoa is positive (we have positive lift,
|
||||
// producing an upward force) and negative otherwise
|
||||
let c_l = lift_coefficient(ar, aoa);
|
||||
// aoa will be positive when we're pitched up and negative otherwise
|
||||
let aoa = angle_of_attack(&ori, &rel_flow_dir);
|
||||
// c_l will be positive when aoa is positive (we have positive lift,
|
||||
// producing an upward force) and negative otherwise
|
||||
let c_l = lift_coefficient(ar, aoa);
|
||||
|
||||
// lift dir will be orthogonal to the local relative flow vector.
|
||||
// Local relative flow is the resulting vector of (relative) freestream
|
||||
// flow + downwash (created by the vortices
|
||||
// of the wing tips)
|
||||
let lift_dir: Dir = {
|
||||
// induced angle of attack
|
||||
let aoa_i = c_l / (PI * ar);
|
||||
// effective angle of attack; the aoa as seen by aerofoil after
|
||||
// downwash
|
||||
let aoa_eff = aoa - aoa_i;
|
||||
// Angle between chord line and local relative wind is aoa_eff
|
||||
// radians. Direction of lift is
|
||||
// perpendicular to local relative wind.
|
||||
// At positive lift, local relative wind will be below our cord line
|
||||
// at an angle of aoa_eff. Thus if
|
||||
// we pitch down by aoa_eff radians then
|
||||
// our chord line will be colinear with local relative wind vector
|
||||
// and our up will be the direction
|
||||
// of lift.
|
||||
ori.pitched_down(aoa_eff).up()
|
||||
};
|
||||
// lift dir will be orthogonal to the local relative flow vector.
|
||||
// Local relative flow is the resulting vector of (relative) freestream
|
||||
// flow + downwash (created by the vortices
|
||||
// of the wing tips)
|
||||
let lift_dir: Dir = {
|
||||
// induced angle of attack
|
||||
let aoa_i = c_l / (PI * ar);
|
||||
// effective angle of attack; the aoa as seen by aerofoil after
|
||||
// downwash
|
||||
let aoa_eff = aoa - aoa_i;
|
||||
// Angle between chord line and local relative wind is aoa_eff
|
||||
// radians. Direction of lift is
|
||||
// perpendicular to local relative wind.
|
||||
// At positive lift, local relative wind will be below our cord line
|
||||
// at an angle of aoa_eff. Thus if
|
||||
// we pitch down by aoa_eff radians then
|
||||
// our chord line will be colinear with local relative wind vector
|
||||
// and our up will be the direction
|
||||
// of lift.
|
||||
ori.pitched_down(aoa_eff).up()
|
||||
};
|
||||
|
||||
// induced drag coefficient (drag due to lift)
|
||||
let cdi = {
|
||||
// Oswald's efficiency factor (empirically derived--very magical)
|
||||
// (this definition should not be used for aspect ratios > 25)
|
||||
let e = 1.78 * (1.0 - 0.045 * ar.powf(0.68)) - 0.64;
|
||||
c_l.powi(2) / (PI * e * ar)
|
||||
};
|
||||
// induced drag coefficient (drag due to lift)
|
||||
let cdi = {
|
||||
// Oswald's efficiency factor (empirically derived--very magical)
|
||||
// (this definition should not be used for aspect ratios > 25)
|
||||
let e = 1.78 * (1.0 - 0.045 * ar.powf(0.68)) - 0.64;
|
||||
c_l.powi(2) / (PI * e * ar)
|
||||
};
|
||||
|
||||
// drag coefficient
|
||||
let c_d = zero_lift_drag_coefficient() + cdi;
|
||||
debug_assert!(c_d.is_sign_positive());
|
||||
debug_assert!(c_l.is_sign_positive() || aoa.is_sign_negative());
|
||||
// drag coefficient
|
||||
let c_d = zero_lift_drag_coefficient() + cdi;
|
||||
debug_assert!(c_d.is_sign_positive());
|
||||
debug_assert!(c_l.is_sign_positive() || aoa.is_sign_negative());
|
||||
|
||||
planform_area * scale.powf(2.0) * (c_l * *lift_dir + c_d * *rel_flow_dir)
|
||||
+ self.parasite_drag(scale) * *rel_flow_dir
|
||||
},
|
||||
planform_area * scale.powf(2.0) * (c_l * *lift_dir + c_d * *rel_flow_dir)
|
||||
+ self.parasite_drag(scale) * *rel_flow_dir
|
||||
},
|
||||
|
||||
_ => self.parasite_drag(scale) * *rel_flow_dir,
|
||||
}
|
||||
_ => self.parasite_drag(scale) * *rel_flow_dir,
|
||||
};
|
||||
|
||||
0.5 * fluid_density * v_sq * power_vec
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -759,35 +759,40 @@ impl<'a> PhysicsData<'a> {
|
||||
)
|
||||
.join()
|
||||
{
|
||||
// Don't simulate for non-gliding, for now
|
||||
if !state.is_glide() {
|
||||
continue;
|
||||
// Always reset air_vel to zero
|
||||
let mut air_vel = Vec3::zero();
|
||||
|
||||
'simulation: {
|
||||
// Don't simulate for non-gliding, for now
|
||||
if !state.is_glide() {
|
||||
break 'simulation;
|
||||
}
|
||||
|
||||
let pos_2d = pos.0.as_().xy();
|
||||
let chunk_pos: Vec2<i32> = pos_2d.wpos_to_cpos();
|
||||
let Some(current_chunk) = &read.terrain.get_key(chunk_pos) else {
|
||||
// oopsie
|
||||
break 'simulation;
|
||||
};
|
||||
|
||||
let meta = current_chunk.meta();
|
||||
|
||||
// Skip simulating for entites deeply under the ground
|
||||
if pos.0.z < meta.alt() - 25.0 {
|
||||
break 'simulation;
|
||||
}
|
||||
|
||||
// If couldn't simulate wind for some reason, skip
|
||||
if let Ok(simulated_vel) =
|
||||
simulated_wind_vel(pos, weather, &read.terrain, &read.time_of_day)
|
||||
{
|
||||
air_vel = simulated_vel
|
||||
};
|
||||
}
|
||||
|
||||
let pos_2d = pos.0.as_().xy();
|
||||
let chunk_pos: Vec2<i32> = pos_2d.wpos_to_cpos();
|
||||
let Some(current_chunk) = &read.terrain.get_key(chunk_pos) else {
|
||||
// oopsie
|
||||
continue;
|
||||
};
|
||||
|
||||
let meta = current_chunk.meta();
|
||||
|
||||
// Skip simulating for entites deeply under the ground
|
||||
if pos.0.z < meta.alt() - 25.0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If couldn't simulate wind for some reason, skip
|
||||
let Ok(wind_vel) =
|
||||
simulated_wind_vel(pos, weather, &read.terrain, &read.time_of_day)
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
phys.in_fluid = phys.in_fluid.map(|f| match f {
|
||||
Fluid::Air { elevation, .. } => Fluid::Air {
|
||||
vel: Vel(wind_vel),
|
||||
vel: Vel(air_vel),
|
||||
elevation,
|
||||
},
|
||||
fluid => fluid,
|
||||
|
Loading…
Reference in New Issue
Block a user