diff --git a/client/src/lib.rs b/client/src/lib.rs index 455abfe5c5..eb32f48826 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -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; }); } } diff --git a/common/src/comp/fluid_dynamics.rs b/common/src/comp/fluid_dynamics.rs index 4f88545919..e27f4cfd1c 100644 --- a/common/src/comp/fluid_dynamics.rs +++ b/common/src/comp/fluid_dynamics.rs @@ -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 } } diff --git a/common/systems/src/phys.rs b/common/systems/src/phys.rs index 04a66b179a..22f77bca88 100644 --- a/common/systems/src/phys.rs +++ b/common/systems/src/phys.rs @@ -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 = 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 = 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,