Files
VS--Improved-Aerodynamics/src/main/java/dev/lumareth/improvedAerodynamics/flight/WariumAero.java
T
richard 4b7fb0e1e8 Add flight physics overhaul with Warium/Futurism mixins
- Route Warium and Futurism force queues through smoothed per-substep delivery
- Evaluate wing, stabilizer, control surface and air brake forces every physics substep
- Add optional improved flight model with angle-of-attack lift and stalls
- Add auto trim toggled by a client key and a server packet
- Add config options, translations, and mixin plugin version gating
- Bump mod version to 0.2.0 and bundle Futurism 0.0.4 as a compile-only dependency
2026-10-28 18:56:25 +01:00

79 lines
4.0 KiB
Java

package dev.lumareth.improvedAerodynamics.flight;
/**
* Warium VS 1.1.6's aerodynamic forces, term for term as its block procedures compute them, but evaluated from the
* ship's current motion. Like in Warium every block uses the velocity of the ship's center of mass. The procedures'
* conditions (air around the block, minimum speed, linked control node) were already checked on the server thread.
* Quirks are kept on purpose so craft fly exactly as before: vertical wings have no drag (Warium never sets the
* pressure that term uses), vertical control surface damping and air brakes ignore the speed multiplier.
*/
final class WariumAero {
private WariumAero() {
}
/**
* @param v ship velocity, ship axes
* @param w ship angular velocity, ship axes
* @param r block center relative to the center of mass, ship axes
* @param input control input of the surface, already combined from its keys and clamped like Warium does
* @param weight share of a tick's force this substep applies
*/
static void evaluate(AeroSurface s, double[] v, double[] w, double[] r, double input, double weight, Wrench out) {
double speed = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
double p = s.pressure() * weight;
double m = s.speedMultiplier();
double fd = s.fluidFactor();
int fx = s.facingX();
int fz = s.facingZ();
// Speed along the facing, Warium's "directionalspeed" of control surfaces and air brakes
double ds = -(fx * v[0] + fz * v[2]);
switch (s.type()) {
case WING -> {
out.addForce(r, 0.0, v[1] * Math.abs(v[1]) * -45.0 * p / m, 0.0);
out.addForce(r, 0.0, Math.abs(fx * v[0] + fz * v[2]) * 160.0 * p, 0.0);
double damping = speed * 600.0 * p / m;
out.addTorque(-w[0] * damping, -0.1 * w[1] * damping, -w[2] * damping);
double drag = -speed * p / m;
out.addForce(r, v[0] * drag, v[1] * drag, v[2] * drag);
}
case STABILIZER -> {
out.addForce(r, 0.0, v[1] * Math.abs(v[1]) * -45.0 * p / m, 0.0);
double damping = speed * 600.0 * p / m;
out.addTorque(-w[0] * damping, 0.0, -w[2] * damping);
double drag = -speed * p / m;
out.addForce(r, v[0] * drag, v[1] * drag, v[2] * drag);
}
case VERTICAL_WING -> {
sideForce(s, v, r, p, m, fd, out);
double damping = speed * 900.0 * p / m;
out.addTorque(-0.1 * w[0] * damping, -w[1] * damping, -0.1 * w[2] * damping);
}
case CONTROL_SURFACE -> {
out.addForce(r, 0.0, ds * 600.0 * input * p * fd / m, 0.0);
double damping = Math.abs(v[1]) * -90.0 * p / m;
out.addForce(r, 0.1 * v[0] * damping, v[1] * damping, 0.1 * v[2] * damping);
}
case VERTICAL_CONTROL_SURFACE -> {
double control = ds * 600.0 * input * p * fd / m;
out.addForce(r, s.rightX() * control, 0.0, s.rightZ() * control);
sideForce(s, v, r, p, m, fd, out);
double damping = speed * 600.0 * p;
out.addTorque(-0.1 * w[0] * damping, -w[1] * damping, -0.1 * w[2] * damping);
}
case AIR_BRAKE -> {
double brake = -Math.abs(ds * 100.0 * s.brakeInput() * p * fd);
out.addForce(r, v[0] * brake, v[1] * brake, v[2] * brake);
}
}
}
/** Vertical wings resisting sideways motion through them. */
private static void sideForce(AeroSurface s, double[] v, double[] r, double p, double m, double fd, Wrench out) {
int ax = Math.abs(s.rightX());
int az = Math.abs(s.rightZ());
double throttle = fd * (ax * (Math.abs(v[0]) + 0.1) + az * (Math.abs(v[2]) + 0.1)) * -40.0 * p / m;
out.addForce(r, v[0] * ax * throttle, 0.0, v[2] * az * throttle);
}
}