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); } }