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:
juliancoffee 2024-03-01 16:18:58 +02:00
parent 5c517e88c9
commit a06e79b089
3 changed files with 90 additions and 84 deletions

View File

@ -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;
});
}
}

View File

@ -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
}
}

View File

@ -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,