From 3b906cb0249de5ae541ed068a18fd6f816737f51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20B=C3=B6klin?= Date: Tue, 18 May 2021 20:18:31 +0200 Subject: [PATCH] Make drag coefficient explicit with consts; update bird masses --- common/src/comp/body.rs | 12 +++++- common/src/comp/fluid_dynamics.rs | 68 ++++++++++++++++--------------- common/systems/src/phys.rs | 1 - 3 files changed, 46 insertions(+), 35 deletions(-) diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 4607c81de2..93f69dd905 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -184,8 +184,16 @@ impl Body { }, Body::BipedSmall(_) => 50.0, - // Ravens are 0.69-2 kg, crows are 0.51 kg on average. Our birds are quite large - Body::BirdMedium(_) => 3.0, + // ravens are 0.69-2 kg, crows are 0.51 kg on average. + Body::BirdMedium(body) => match body.species { + bird_medium::Species::Chicken => 2.0, // ~✅ Red junglefowl are 1-1.5 kg + bird_medium::Species::Duck => 2.0, + bird_medium::Species::Eagle => 10.0, // ~✅ Steller's sea eagle are 5-9 kg + bird_medium::Species::Goose => 3.5, // ~✅ Swan geese are 2.8-3.5 kg + bird_medium::Species::Owl => 2.0, + bird_medium::Species::Parrot => 2.0, + bird_medium::Species::Peacock => 5.0, + }, Body::BirdLarge(_) => 50.0, Body::Dragon(_) => 20_000.0, diff --git a/common/src/comp/fluid_dynamics.rs b/common/src/comp/fluid_dynamics.rs index 42b60ae0f8..986ec88a36 100644 --- a/common/src/comp/fluid_dynamics.rs +++ b/common/src/comp/fluid_dynamics.rs @@ -113,32 +113,27 @@ impl Body { // All the coefficients come pre-multiplied by their reference area 0.5 * fluid_density * v_sq - * wings - .and_then(|wings| match *wings { - Wings::Gliding { - 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 - ) - }; - Some((aspect_ratio.min(24.0), planform_area, ori)) - }, - _ => None, - }) - .map(|(ar, area, ori)| { + * match wings { + Some(&Wings::Gliding { + 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, area, aoa); + let c_l = lift_coefficient(ar, planform_area, aoa); // lift dir will be orthogonal to the local relative flow vector. // Local relative flow is the resulting vector of (relative) freestream @@ -162,22 +157,26 @@ impl Body { ori.pitched_down(aoa_eff).up() }; - // drag coefficient due to lift + // drag coefficient let c_d = { // 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; + // induced drag coefficient (drag due to lift) + let cdi = c_l.powi(2) / (PI * e * ar); - zero_lift_drag_coefficient(area) + zero_lift_drag_coefficient(planform_area) + self.parasite_drag_coefficient(wings) - + c_l.powi(2) / (PI * e * ar) + + cdi }; debug_assert!(c_d.is_sign_positive()); debug_assert!(c_l.is_sign_positive() || aoa.is_sign_negative()); c_l * *lift_dir + c_d * *rel_flow_dir - }) - .unwrap_or_else(|| self.parasite_drag_coefficient(wings) * *rel_flow_dir) + }, + + _ => self.parasite_drag_coefficient(wings) * *rel_flow_dir, + } } } @@ -192,7 +191,8 @@ impl Body { // Cross-section, head/feet first Body::BipedLarge(_) | Body::BipedSmall(_) | Body::Golem(_) | Body::Humanoid(_) => { let dim = self.dimensions().xy().map(|a| a * 0.5); - 0.7 * PI * dim.x * dim.y + const CD: f32 = 0.7; + CD * PI * dim.x * dim.y }, // Cross-section, nose/tail first @@ -201,7 +201,7 @@ impl Body { | Body::QuadrupedSmall(_) | Body::QuadrupedLow(_) => { let dim = self.dimensions().map(|a| a * 0.5); - let cd = if matches!(self, Body::QuadrupedLow(_)) { + let cd: f32 = if matches!(self, Body::QuadrupedLow(_)) { 0.7 } else { 1.0 @@ -212,7 +212,7 @@ impl Body { // Cross-section, zero-lift angle; exclude the wings (width * 0.2) Body::BirdMedium(_) | Body::BirdLarge(_) | Body::Dragon(_) => { let dim = self.dimensions().map(|a| a * 0.5); - let cd = if matches!(wings, Some(Wings::Folded) | None) { + let cd: f32 = if matches!(wings, Some(Wings::Folded) | None) { 0.7 } else { // "Field Estimates of Body Drag Coefficient on the Basis of Dives in Passerine @@ -231,7 +231,8 @@ impl Body { let dim = self.dimensions().map(|a| a * 0.5); // "A Simple Method to Determine Drag Coefficients in Aquatic Animals", // D. Bilo and W. Nachtigall, 1980 - 0.031 * PI * dim.x * 0.2 * dim.z + const CD: f32 = 0.031; + CD * PI * dim.x * 0.2 * dim.z }, Body::Object(object) => match object { @@ -247,7 +248,8 @@ impl Body { | object::Body::FireworkYellow | object::Body::MultiArrow => { let dim = self.dimensions().map(|a| a * 0.5); - 0.02 * PI * dim.x * dim.z + const CD: f32 = 0.02; + CD * PI * dim.x * dim.z }, // spherical-ish objects @@ -265,12 +267,14 @@ impl Body { | object::Body::Pumpkin4 | object::Body::Pumpkin5 => { let dim = self.dimensions().map(|a| a * 0.5); - 0.5 * PI * dim.x * dim.z + const CD: f32 = 0.5; + CD * PI * dim.x * dim.z }, _ => { let dim = self.dimensions(); - 2.0 * (PI / 6.0 * dim.x * dim.y * dim.z).powf(2.0 / 3.0) + const CD: f32 = 2.0; + CD * (PI / 6.0 * dim.x * dim.y * dim.z).powf(2.0 / 3.0) }, }, diff --git a/common/systems/src/phys.rs b/common/systems/src/phys.rs index e37b0bd342..d8473ee3ef 100644 --- a/common/systems/src/phys.rs +++ b/common/systems/src/phys.rs @@ -26,7 +26,6 @@ use specs::{ use std::ops::Range; use vek::*; - fn get_wings(character_state: Option<&CharacterState>) -> Option { match *character_state? { CharacterState::Glide(states::glide::Data {