Add #flight=N|NE|E|SE|S|SW|W|NW URL parameter for corridor direction

Adds 8 compass directions for the tile-build axis. Camera position,
corridor rotation, and refetch math all read from window.__flightDir.

Test URLs:
  #flight=N   north  (default, +Z, current behaviour)
  #flight=E   east   (+X)
  #flight=S   south  (-Z)
  #flight=W   west   (-X)
  #flight=NE  northeast (diagonal)
  #flight=SE  southeast
  #flight=SW  southwest
  #flight=NW  northwest

Renders with no hash unchanged. Each direction rotates the
corridor so its long axis follows the chosen compass bearing, and
the camera drifts along that bearing.
This commit is contained in:
Richard Zink committed 2026-10-07 21:50:31 +02:00
1 parent c2d6fd38ba
commit 9027099d89
2 files changed
+33 -8

No files matched your search

+15
View File
@@ -516,6 +516,21 @@ var noiseDataUri = 'data:image/png;base64,PLACEHOLDER';
// URL override for easy A/B testing: #renderer=clouds2d / #renderer=clouds3d
var _urlRenderer = (location.hash.match(/renderer=(\w+)/) || [])[1];
var renderer = _urlRenderer || (window.CONFIG && window.CONFIG.renderer) || 'vanta';
// Flight direction for ground-tile corridor (N, NE, E, SE, S, SW, W, NW).
// Default 'N' (= +Z world) so behaviour is unchanged when hash is absent.
var _urlFlight = (location.hash.match(/flight=(\w+)/) || [])[1];
var FLIGHT_DIRS = {
N: { cos: 0.0, sin: 1.0, dx: 0, dz: 1 },
NE: { cos: 0.7071068, sin: 0.7071068, dx: 0.7071068, dz: 0.7071068 },
E: { cos: 1.0, sin: 0.0, dx: 1, dz: 0 },
SE: { cos: 0.7071068, sin:-0.7071068, dx: 0.7071068, dz:-0.7071068 },
S: { cos: 0.0, sin:-1.0, dx: 0, dz:-1 },
SW: { cos:-0.7071068, sin:-0.7071068, dx:-0.7071068, dz:-0.7071068 },
W: { cos:-1.0, sin: 0.0, dx:-1, dz: 0 },
NW: { cos:-0.7071068, sin: 0.7071068, dx:-0.7071068, dz: 0.7071068 }
};
window.__flightDir = FLIGHT_DIRS[_urlFlight && FLIGHT_DIRS[_urlFlight.toUpperCase()] ? _urlFlight.toUpperCase() : 'N'];
var useVanta = (renderer !== 'clouds2d' && renderer !== 'clouds3d');
var effect;
if (useVanta && typeof VANTA !== 'undefined') {
+18 -8
View File
@@ -139,7 +139,11 @@ var FRAG_SRC = [
'float drift = uTime * uSpeed * 0.12;',
// Fixed altitude well above the cloud ceiling (y=1.5).
'float camY = 2.2;',
'vec3 ro = vec3(0.0, camY, drift);',
// Camera position follows window.__flightDir (set from URL #flight=...).
// Default: drift along +Z (north). For east: drift along +X. For south: -Z, etc.
'float fdx = (window.__flightDir ? window.__flightDir.dx : 0.0);',
'float fdz = (window.__flightDir ? window.__flightDir.dz : 1.0);',
'vec3 ro = vec3(drift * fdx, camY, drift * fdz);',
// Ray direction: tilt more downward so the visible ground fits
// within the mosaic. At uv.y = 0 the ray goes ~26° below
// horizontal, putting the visible ground at tGround < 5
@@ -281,10 +285,11 @@ function init(canvas) {
var GROUND_TILE_URL = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/';
var GROUND_TILE_Z = 11;
var GROUND_TILE_SIZE = 256;
// Camera travels in +Z (forward) and looks in +Z (also forward).
// The corridor is aligned with both motion and look direction.
var GROUND_TRAVEL_COS = 0.0; // cos(90 deg)
var GROUND_TRAVEL_SIN = 1.0; // sin(90 deg)
// Camera flight direction. Set from window.__flightDir (URL: #flight=N|NE|E|...).
// Default is N (= +Z forward). Each flight direction rotates the
// corridor so its long axis follows the camera path.
var GROUND_TRAVEL_COS = (window.__flightDir && window.__flightDir.cos) || 0.0;
var GROUND_TRAVEL_SIN = (window.__flightDir && window.__flightDir.sin) || 1.0;
var GROUND_CORRIDOR_LONG = 25; // tiles along travel direction (~3.5 min of flight at uSpeed=1)
var GROUND_CORRIDOR_PERP = 5; // tiles perpendicular to travel
var GROUND_BUFFER_LONG = 11; // refetch when this close to forward edge
@@ -375,8 +380,13 @@ function rebuildGroundMosaic(centerTileX, centerTileY) {
// Called periodically from the render loop with the camera world
// position. Re-centres the mosaic if we're approaching its edge.
function maybeRefetchGround(cameraWorldX, cameraWorldZ, gl) {
var cameraTileX = GROUND_BASE_X + Math.floor(cameraWorldX);
var cameraTileY = GROUND_BASE_Y + Math.floor(cameraWorldZ);
var fdx = (window.__flightDir && window.__flightDir.dx) || 0;
var fdz = (window.__flightDir && window.__flightDir.dz) || 1;
// Camera position in world (X, Z) from the dominant flight direction
var camX = (fdx !== 0) ? cameraWorldX * fdx : 0;
var camZ = (fdz !== 0) ? cameraWorldZ * fdz : 0;
var cameraTileX = GROUND_BASE_X + Math.floor(camX);
var cameraTileY = GROUND_BASE_Y + Math.floor(camZ);
// Project camera offset onto the corridor's rotated axes.
// With GROUND_TRAVEL_COS/SIN = (0, 1) the corridor runs along
// +Z (camera's motion + look direction).
@@ -536,7 +546,7 @@ window.clouds3dRender = function(target) {
var drift = now * speed * 0.12;
if (performance.now() - groundLastCheck > 1500) {
groundLastCheck = performance.now();
maybeRefetchGround(drift, drift * 0.7, gl);
maybeRefetchGround(drift, drift, gl);
}
gl.drawArrays(gl.TRIANGLES, 0, 3);