feat(flight): add aspect ratio lift and altitude-hold trim

- Derive lift slope and induced drag from each wing's aspect ratio, found by grouping connected wing blocks across short span gaps.
- Give stabilizers and vertical wings their own parasitic drag from the stabilizerDrag config.
- Replace designSpeed with a fixed lift constant and a liftScale multiplier.
- Make auto trim hold the altitude the craft has when the pilot releases pitch, using nested altitude, climb and attitude loops.
- Add /improvedaerodynamics (alias /aero) to list, read and set the main config values in game.
This commit is contained in:
richard committed 2026-10-28 22:06:50 +01:00
1 parent 4b7fb0e1e8
commit 599ecae21f
10 files changed
+329 -48

No files matched your search

@@ -27,14 +27,19 @@ final class ImprovedAero {
private static final double FLAP_EFFECTIVENESS = 0.75;
// Angle of attack of a level cambered wing, where K is calibrated
private static final double REFERENCE_ANGLE = Math.toRadians(4.0);
private static final double REFERENCE_SPEED = 40.0;
// Oswald efficiency of a finite wing
private static final double EFFICIENCY = 0.85;
private ImprovedAero() {
}
/** Lift constant K for the given design speed. */
static double liftConstant(double designSpeed) {
return 160.0 / (designSpeed * LIFT_SLOPE * REFERENCE_ANGLE);
}
/**
* Lift constant K, fixed for every craft: a level wing of average proportions makes Warium's lift at 40 blocks per
* second. Faster flight needs less angle of attack, slower flight more, and how fast a craft has to fly depends
* only on its weight, wing area, wing shape and the air pressure at its altitude.
*/
static final double LIFT_CONSTANT = 160.0 / (REFERENCE_SPEED * LIFT_SLOPE * REFERENCE_ANGLE);
/**
* Adds the surface's forces to out.
@@ -44,10 +49,12 @@ final class ImprovedAero {
* @param r block center relative to the center of mass, ship axes
* @param input control input of the surface, -1 to 1
* @param stalled whether the surface was stalled in the previous substep
* @param liftScale multiplier for the lift only, not the drag
* @param thinDrag parasitic drag coefficient of stabilizers and vertical wings
* @return whether the surface is stalled now
*/
static boolean evaluate(AeroSurface s, double[] v, double[] w, double[] r, double input, double weight,
double liftConstant, double stallAngleScale, boolean stalled, Wrench out) {
double liftConstant, double liftScale, double stallAngleScale, double thinDrag, boolean stalled, Wrench out) {
// Airflow at the block: ship velocity plus w x r
double vx = v[0] + w[1] * r[2] - w[2] * r[1];
double vy = v[1] + w[2] * r[0] - w[0] * r[2];
@@ -64,8 +71,8 @@ final class ImprovedAero {
return false;
}
// Warium's own per-block drag
double parasitic = -localSpeed * s.type().parasiticDrag * p / m;
// Warium's own per-block drag, lower for thin surfaces since they stabilize with lift, not drag
double parasitic = -localSpeed * (s.type().thin ? thinDrag : s.type().parasiticDrag) * p / m;
out.addForce(r, vx * parasitic, vy * parasitic, vz * parasitic);
// Chord c along the facing, normal n up for horizontal surfaces and to the side for vertical ones
@@ -103,9 +110,13 @@ final class ImprovedAero {
double center = stalled ? critical - STALL_HYSTERESIS : critical;
double attached = 1.0 - smoothstep(center - STALL_BLEND, center + STALL_BLEND, absAlpha);
double attachedLift = LIFT_SLOPE * alpha;
// Finite wing theory: lift slope and induced drag follow from the wing's aspect ratio
double aspectRatio = s.aspectRatio();
double slope = aspectRatio > 0.0 ? 2.0 * Math.PI / (1.0 + 2.0 / aspectRatio) : LIFT_SLOPE;
double inducedDrag = aspectRatio > 0.0 ? 1.0 / (Math.PI * EFFICIENCY * aspectRatio) : INDUCED_DRAG;
double attachedLift = slope * alpha;
double lift = attached * attachedLift + (1.0 - attached) * SEPARATED_LIFT * Math.sin(2.0 * alpha);
double drag = attached * INDUCED_DRAG * attachedLift * attachedLift
double drag = attached * inducedDrag * attachedLift * attachedLift
+ (1.0 - attached) * SEPARATED_DRAG * Math.sin(alpha) * Math.sin(alpha);
double q = liftConstant * p * fd * planeSpeedSq;
@@ -118,7 +129,7 @@ final class ImprovedAero {
double dx = -(u * cx + vn * nx) / planeSpeed;
double dy = -(vn * ny) / planeSpeed;
double dz = -(u * cz + vn * nz) / planeSpeed;
double liftForce = q * lift;
double liftForce = q * lift * liftScale;
double dragForce = q * drag / m;
out.addForce(r, lx * liftForce + dx * dragForce, ly * liftForce + dy * dragForce, lz * liftForce + dz * dragForce);
return stalled;