Skip to content
Ivan Chaus
All news

PROJECT UPDATE: A simulation you cannot steer is a screensaver

Zoom that keeps the point under the cursor, drag to pan, speed that does not break the integrator, and an arcade mode that teaches orbital mechanics faster than any diagram.

  • Personal projects
  • Work in progress
The simulation zoomed in on a system, with the camera controls in use.

A simulation you cannot steer is a screensaver. The engine had been producing correct orbits for a day, and watching them was still unpleasant: one fixed viewport, one speed, and no way to follow anything that left the frame.

So this was a day of controls. More speed options, map drag, better zoom, and an arcade mode. Most of it is interface rather than physics — and the last one is the exception, which is why it is called what it is called.

Zoom that keeps the point under the cursor

Naive zoom scales about the origin, which means the thing you were looking at slides away exactly when you try to look at it more closely. The behaviour people expect is that the point under the pointer stays under the pointer.

That is one equation. Given a screen point s, a camera offset c, and a scale k, the world point under the cursor is:

w = (s − c) / k

Zooming means picking a new scale k' and then solving for the offset that keeps w mapping to the same s:

c' = s − w · k'
   = s − ((s − c) / k) · k'

Which reduces to a form that is much easier to read in code:

c' = s − (s − c) · (k' / k)

Panning is the easy half — accumulate the pointer delta straight into c:

c' = c + (s[n] − s[n-1])

Zoom steps multiply rather than add, so each notch of the wheel changes the view by the same proportion regardless of how far in you already are:

k' = k · z^n        z ~ 1.1,  n = wheel notches

Clamped at both ends, because a scale of zero is a division by zero and a scale of ten thousand is a single pixel filling the screen.

Speed, and why it is not one slider

The tempting way to add a speed control is to multiply the timestep. It is also the way to break the integrator: Δt is the one parameter the whole method's stability rests on, and doubling it does not run the simulation twice as fast so much as make it twice as wrong. Orbits that were closed start precessing; close encounters stop resolving.

The honest lever is the number of steps per frame, not the size of them:

per frame:  repeat N times ->  step(Δt)

Δt stays where the integrator is well behaved, and speed becomes N. Ten times the speed is ten times the work rather than ten times the error — which is a real cost, and it is a large part of why optimisation became its own problem a few days later.

Arcade mode

The one control that is not a camera control, and the one that is not honest either. Arcade mode multiplies gravity by fifty.

It is a single constant, and that is the whole implementation:

G_arcade = 50 · G

The reason it exists is impatience. A system with plausible masses and distances evolves at a pace that is correct and slow — you set something up, and then you wait to find out whether it holds. The steps-per-frame lever above solves that properly, and it costs fifty times the arithmetic to get fifty times the pace. Cranking G costs nothing.

But it is not a fast-forward, and the difference is the interesting part. More steps per frame computes the same trajectory sooner. Multiplying G computes a different trajectory. The system you are watching in arcade mode is not the one you built, played faster — it is a system in a universe where gravity is fifty times stronger.

Kepler's third law says how much faster that universe runs:

T² = 4π²a³ / GM        ->        T ∝ 1 / sqrt(G)

So fifty times the gravity is about seven times the pace, not fifty — and only for a system whose velocities were chosen for it.

Existing systems were not. Circular velocity is v = sqrt(GM / r), so a body that was in a clean circle is suddenly at about a seventh of the speed its orbit now requires:

v_needed / v_actual = sqrt(50) ~ 7.07

Which means everything falls inward. Orbits collapse into steep ellipses, near-misses become collisions, and bodies that were comfortably escaping get caught — escape velocity went up by the same factor. Turn it on and a tidy solar system becomes a pile-up.

That is a defect if you read the mode as a fast-forward and a feature if you read it as what it is: the button that stops the simulation pretending. It is also genuinely useful, because seven times the pace and a hard shove inward is a quick way to find out whether a configuration was ever stable or merely had not fallen over yet.

What this bought

The camera work changed nothing the engine produces — it changed whether the numbers are worth watching, which turned out to be the thing standing between a working integrator and a project I wanted to keep opening. Arcade mode is the opposite: it changes the numbers on purpose, and it is the only place in the project that does.