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())) .zip(old.iter().zip(new.iter()))
.for_each(|((_, current), ((_, old), (_, new)))| { .for_each(|((_, current), ((_, old), (_, new)))| {
*current = CompressedWeather::lerp_unclamped(old, new, t); *current = CompressedWeather::lerp_unclamped(old, new, t);
current.wind = self.local_wind;
}); });
} }
} }

View File

@ -143,71 +143,71 @@ impl Body {
Vec3::zero() Vec3::zero()
} else { } else {
let rel_flow_dir = Dir::new(rel_flow.0 / v_sq.sqrt()); let rel_flow_dir = Dir::new(rel_flow.0 / v_sq.sqrt());
0.5 * fluid_density let power_vec = match wings {
* v_sq Some(&Wings {
* match wings { aspect_ratio,
Some(&Wings { planform_area,
aspect_ratio, ori,
planform_area, }) => {
ori, if aspect_ratio > 25.0 {
}) => { tracing::warn!(
if aspect_ratio > 25.0 { "Calculating lift for wings with an aspect ratio of {}. The formulas \
tracing::warn!( are only valid for aspect ratios below 25.",
"Calculating lift for wings with an aspect ratio of {}. The \ aspect_ratio
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 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 // aoa will be positive when we're pitched up and negative otherwise
let aoa = angle_of_attack(&ori, &rel_flow_dir); let aoa = angle_of_attack(&ori, &rel_flow_dir);
// c_l will be positive when aoa is positive (we have positive lift, // c_l will be positive when aoa is positive (we have positive lift,
// producing an upward force) and negative otherwise // producing an upward force) and negative otherwise
let c_l = lift_coefficient(ar, aoa); let c_l = lift_coefficient(ar, aoa);
// lift dir will be orthogonal to the local relative flow vector. // lift dir will be orthogonal to the local relative flow vector.
// Local relative flow is the resulting vector of (relative) freestream // Local relative flow is the resulting vector of (relative) freestream
// flow + downwash (created by the vortices // flow + downwash (created by the vortices
// of the wing tips) // of the wing tips)
let lift_dir: Dir = { let lift_dir: Dir = {
// induced angle of attack // induced angle of attack
let aoa_i = c_l / (PI * ar); let aoa_i = c_l / (PI * ar);
// effective angle of attack; the aoa as seen by aerofoil after // effective angle of attack; the aoa as seen by aerofoil after
// downwash // downwash
let aoa_eff = aoa - aoa_i; let aoa_eff = aoa - aoa_i;
// Angle between chord line and local relative wind is aoa_eff // Angle between chord line and local relative wind is aoa_eff
// radians. Direction of lift is // radians. Direction of lift is
// perpendicular to local relative wind. // perpendicular to local relative wind.
// At positive lift, local relative wind will be below our cord line // At positive lift, local relative wind will be below our cord line
// at an angle of aoa_eff. Thus if // at an angle of aoa_eff. Thus if
// we pitch down by aoa_eff radians then // we pitch down by aoa_eff radians then
// our chord line will be colinear with local relative wind vector // our chord line will be colinear with local relative wind vector
// and our up will be the direction // and our up will be the direction
// of lift. // of lift.
ori.pitched_down(aoa_eff).up() ori.pitched_down(aoa_eff).up()
}; };
// induced drag coefficient (drag due to lift) // induced drag coefficient (drag due to lift)
let cdi = { let cdi = {
// Oswald's efficiency factor (empirically derived--very magical) // Oswald's efficiency factor (empirically derived--very magical)
// (this definition should not be used for aspect ratios > 25) // (this definition should not be used for aspect ratios > 25)
let e = 1.78 * (1.0 - 0.045 * ar.powf(0.68)) - 0.64; let e = 1.78 * (1.0 - 0.045 * ar.powf(0.68)) - 0.64;
c_l.powi(2) / (PI * e * ar) c_l.powi(2) / (PI * e * ar)
}; };
// drag coefficient // drag coefficient
let c_d = zero_lift_drag_coefficient() + cdi; let c_d = zero_lift_drag_coefficient() + cdi;
debug_assert!(c_d.is_sign_positive()); debug_assert!(c_d.is_sign_positive());
debug_assert!(c_l.is_sign_positive() || aoa.is_sign_negative()); 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) 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, _ => 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() .join()
{ {
// Don't simulate for non-gliding, for now // Always reset air_vel to zero
if !state.is_glide() { let mut air_vel = Vec3::zero();
continue;
'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 { phys.in_fluid = phys.in_fluid.map(|f| match f {
Fluid::Air { elevation, .. } => Fluid::Air { Fluid::Air { elevation, .. } => Fluid::Air {
vel: Vel(wind_vel), vel: Vel(air_vel),
elevation, elevation,
}, },
fluid => fluid, fluid => fluid,