DEV Community

Arthur031221
Arthur031221

Posted on

Rendering a 3D terrain flyover of a GPX route in the browser

I wanted a flyover video of a hike, and every tool I found wanted me to upload the track or pay for longer clips. So I built Ridgereel, a browser app that turns a GPX, TCX or FIT file into a 3D terrain flyover MP4.

Ridgereel flyover of the Yushan Main Peak trail

How it works

A Web Worker parses the file into a track. The route is cleaned of GPS jumps and resampled about every 5 m. Elevation tiles in the AWS Terrarium encoding are decoded into one height field, and imagery from Esri, OpenTopoMap or CARTO is stitched into a single texture.

Three.js draws the terrain with a camera relative sun, contour lines from fwidth in the shader, fog and an edge fade. The route is three opaque line layers. A 2D overlay adds the stats and the elevation profile.

Frames as a function of time

I prefetch all tiles before rendering, so a frame depends only on the time. Two things follow. Seeking back to the same time redraws identical pixels, which an end to end test checks in one session. And WebCodecs can encode an exact MP4 at 30 or 60 fps instead of recording the screen in real time. Browsers without WebCodecs fall back to a real time recording.

The camera rig has follow, drone and overview presets, each with an intro, a main orbit and an outro. In 9:16 the outro fits the whole route using the narrower horizontal field of view. That took one fix after the first render cut the route off at the edge.

Privacy

The file is never uploaded. A Playwright test loads a file whose name contains a marker, records every request, and fails if one goes anywhere but the four tile servers, isn't a GET, or carries the marker. Tile servers still see the area you open. By default the first and last 200 m of the route are cut and the map around them is pixelated.

Numbers and limits

The 15 s, 1080 x 1920 sample is 450 frames. It rendered in 236 s in headless Chrome 149 on a 3 core Linux machine with software WebGL, and the file is 12.8 MB. I haven't timed a GPU. I tested export in Chrome only. The sample route uses OpenStreetMap geometry with synthetic timestamps, and the file says so.

Live demo: https://arthur031221.github.io/Ridgereel/

Source and docs: https://github.com/Arthur031221/Ridgereel

Top comments (1)

Collapse
 
onecoderegister profile image
Andrew Cluev •

Sounds lovely! I especially like hiding the first and last 200 metres by default. People want to share the walk, not necessarily their front door 🙂 Good luck with Ridgereel!