· 4 min read
Why Tight Curves Break Voxel Track
Sweeping a box along a curved path is the obvious way to build rail, ballast and kerbs. Below a certain radius it produces a starburst of raised fins instead, and the fix is not more boxes.
Almost every long thin thing on the layout is built the same way. Take a path, walk along it at a fixed lateral offset, and drop a box at each step. Two offsets give you two rails. A wider one gives you ballast. Move outward again and you have a kerb, a footway, a girder.
It is a good technique. It is also the source of the single most persistent class of visual bug in the whole engine, and the reason curves come in exactly one radius.
What goes wrong
A box swept along a straight line is fine: consecutive boxes sit end to end and the seams are invisible.
A box swept along an arc is fine too, as long as the arc is gentle. Each box is rotated slightly relative to the last, and the outer edges open up a fraction while the inner edges close. At a large radius that closing is a fraction of a millimetre and nothing shows.
Tighten the radius and the inner edges do not just close — they overlap. Each box drives its inner corner into the body of the box behind it, and because the boxes are rotated relative to one another, the overlapping corners stick out. What you get is not a smooth curve with slightly thick geometry. It is a starburst: a ring of raised triangular fins pointing inward, one per step, catching the light and reading as damage.
Below roughly 1.5 units of radius it is unmissable. Above about 2 it is invisible. In between it depends on how wide the swept box is, which means a rail can survive a curve that a kerb cannot.
The fixes that do not work
More steps. The instinct is that the fins are a sampling artefact, so sampling finer should help. It makes it worse. Halving the step doubles the number of fins and halves their size, and a dense ring of small fins reads as a rough, noisy band rather than as a clean overlap — which is arguably uglier because it looks like a texture problem rather than a geometry one.
Fewer steps. Going the other way turns the curve into a visible polygon. You have traded a bad curve for an obviously faceted one.
Shrinking the box. Making the swept box narrower does delay the onset, but a rail thin enough to survive a 1.0-radius curve is too thin to see on a straight, and rails have to match across the whole layout.
The real problem is that a swept box has a width, and a curve tight enough will always eat it. There is no parameter that fixes it, only parameters that move where it starts.
What actually works
Do not build the tight thing by sweeping. The inner kerb of a road curve is the tightest band on the layout and it is not swept at all. It is laid as a corner pad: a single piece of geometry shaped to fill the inside of the turn, placed once. It has no seams because it has no steps.
That is the general answer. Where a sweep is too tight, replace the sweep with one piece that occupies the same space.
Keep one radius. Track curves are all the same radius, and that radius is comfortably above the threshold. This is not a limitation the player is protected from — it is a limitation the player never encounters, because the tight case does not exist in the catalogue. It also happens to match how real track systems work, where a set of curves comes in fixed radii, so it reads as correct rather than as missing.
The sibling bug: shared edges
There is a second failure in the same family, and it looks nothing like the first until you know what it is.
A wide band — a carriageway, a ballast shoulder — is built as several parallel lanes swept at adjacent offsets. The obvious thing is to have lane two start exactly where lane one ends, sharing an edge.
Do that and you get radial seams: thin dark lines running across the band at every step, appearing and disappearing as the camera moves. The cause is two coincident faces. Two surfaces at exactly the same depth, and the renderer has no basis for choosing which is in front, so it picks differently per pixel and per frame.
The fix is to overlap the lanes by about 0.3 rather than butting them. The seam disappears because there is no longer a plane where two faces agree. Overlapping geometry offends a certain kind of tidiness, but z-fighting is not a tidiness problem — it is a correctness problem, and the correct answer is to make sure no two faces are ever coplanar.
The one that took longest to find
Worth recording because it looked like neither of the above.
On straights running along the Z axis, both rails collapsed onto the centreline. On X-axis straights they were fine. Curves were fine.
The cause: the geometry was being offset and then rotated in place. Offsetting first bakes the lateral displacement into world space, so the rotation spins the piece about its own centre and the offset keeps pointing the way it always did — north, say, regardless of which way the track runs. On a track running east-west that is a lateral offset. On a track running north-south it is a longitudinal one, and both rails end up on the centreline with a slight lead and lag.
The rule that came out of it: never offset and then rotate. Rotate the direction, then offset along it. It is obvious once written down, and it cost most of a day.
- geometry
- engine
- rails
