fix(highway_3d): stop the lane at the hit line - #994
Merged
Merged
Conversation
The lane maps chart time to z exactly as notes do, over the window [now - BEHIND, now + AHEAD]. That puts its near edge at +TS*BEHIND — BEHIND seconds PAST the hit line, toward the player. Nothing is ever drawn there: drawNote and the chord frames both clamp to Math.min(0, dZ(dt)), so notes stop dead at z = 0. The overhang was therefore lane surface with nothing on it. Clamp the floor geometry's near edge to the hit line. The far edge is deliberately untouched — it still lands at -AHEAD*TS, aligned with the note horizon, which is why the span stays AHEAD+BEHIND in the sliced path and the clamp is applied per slice (a slice entirely past the line collapses to zero length and is skipped before the arpeggio probe, so it costs nothing). All four floor sites move together — the sliced lane (which also feeds both divider loops), the fallback lane, its dividers, and the fret boundary extension lines. They shared the identical `+ TS * BEHIND` shift; fixing only some would leave fret lines poking past a lane that now stops. Closes #991 Signed-off-by: Kris Anderson <topkoa@gmail.com>
topkoa
added a commit
that referenced
this pull request
Jul 16, 2026
Bring the branch up to date with main (includes #994, which also touched highway_3d/screen.js — the lane hit-line fix — in a different region).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #991.
The bug
The lane maps chart time to z exactly the way notes do —
z = dZ(t - now)— across the window[now - BEHIND, now + AHEAD]. That puts its near edge at+TS*BEHIND: half a second of lane sitting past the hit line, toward the player.Nothing is ever drawn there.
drawNoteclamps every note withMath.min(0, dZ(dt)), and the chord frames do the same, so notes stop dead atz = 0. The strip past the line was therefore lane surface with nothing on it — the artifact in the issue screenshot.The fix
Clamp the floor geometry's near edge to the hit line. That's it.
The far edge is deliberately untouched — it still lands at
-AHEAD*TS, aligned with the note horizon. That matters: a previous fix (still commented in the code) widened the span toAHEAD + BEHINDprecisely so the far edge would reach the horizon, because usingAHEADalone stopped it at-TS*(AHEAD-BEHIND)and left the lastBEHINDseconds of notes with no lane underneath. So the sliced path keeps itsAHEAD + BEHINDwindow and the clamp is applied per slice; a slice lying entirely past the line collapses to zero length and is skipped before the arpeggio probe, so it costs nothing.Verified numerically, both lane paths now span exactly
[-AHEAD*TS, 0]:0.000000(hit line)-5.175000=-AHEAD*TS0.000000-5.175000Why all four sites
Four places shared the identical
+ TS * BEHINDshift, and they're one invariant — highway floor geometry that should stop at the hit line:z0/z1per slice) — also feeds both divider loops, so those are fixed for free.laneLen/zLane) — also feeds the arpeggio outer dividers.divLen).extZMid).#4 is included on purpose: those lines share the same expression, so fixing only the lane would leave fret lines poking past a lane that now stops — visually worse than the original. Happy to narrow it to the lane proper if that's preferred.
Notes
AHEAD + BEHINDis written down at the clamp.node --checkclean.🤖 Generated with Claude Code