From 07017cfac68021b4fed57d536fe919997966674c Mon Sep 17 00:00:00 2001 From: Richard Zink Date: Thu, 8 Oct 2026 08:20:33 +0200 Subject: [PATCH] Add tile borders and NS-mirrored corner labels (burned in) User wants: - Border around each tile so they can see where one ends - Labels in the four corners, NS-mirrored (so N is at the bottom and S at the top, matching the tile's own NS axis) - Labels burned in to the canvas so they always show the tile identity during flight (not just a live overlay) Implementation: - Thin dark border (rgba(0,0,0,0.55), 2px) via strokeRect just inside the tile bounds - S at top-left, N at bottom-left (NS mirrored) in large bold text with white fill + black stroke for contrast - y=NNN at top-right, x=NNN at bottom-right in smaller monospace - All labels drawn directly on the canvas before texImage2D upload, so they're part of the texture the shader samples --- vendor/clouds3d.js | 52 +++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/vendor/clouds3d.js b/vendor/clouds3d.js index cc9f213..e8c68e8 100644 --- a/vendor/clouds3d.js +++ b/vendor/clouds3d.js @@ -354,27 +354,41 @@ function drawTileAt(lng, perp, dx, dz, centerTileX, centerTileY) { -GROUND_TILE_SIZE, GROUND_TILE_SIZE); groundLoadedTiles[tileX + '_' + tileY] = true; - // Debug labels: 'N' at the image's north edge (top of canvas - // tile area after UNPACK_FLIP_Y_WEBGL), 'S' at south edge. - // Tile coords X,Y at the centre so we can verify the canvas - // arrangement matches the world directions. - groundCtx.fillStyle = 'rgba(255,255,255,0.85)'; + // Thin border so the user can see where one tile ends and the + // next begins. + groundCtx.strokeStyle = 'rgba(0,0,0,0.55)'; + groundCtx.lineWidth = 2; + groundCtx.strokeRect(canvasX + 1, canvasY + 1, + GROUND_TILE_SIZE - 2, GROUND_TILE_SIZE - 2); + + // Burn labels into the four corners of the tile, NS-mirrored + // (so N ends up at the bottom and S at the top, mirroring the + // tile's own NS axis). User can read the tile identity + // directly from the rendered ground. + groundCtx.fillStyle = 'rgba(255,255,255,0.95)'; groundCtx.strokeStyle = 'rgba(0,0,0,0.85)'; groundCtx.lineWidth = 3; - groundCtx.font = 'bold 48px sans-serif'; - groundCtx.textAlign = 'center'; - // N at canvas top of tile area (image north is at top) - groundCtx.strokeText('N', canvasX + 128, canvasY + 56); - groundCtx.fillText('N', canvasX + 128, canvasY + 56); - // S at canvas bottom - groundCtx.strokeText('S', canvasX + 128, canvasY + 240); - groundCtx.fillText('S', canvasX + 128, canvasY + 240); - // Tile coords - groundCtx.font = 'bold 20px monospace'; - groundCtx.strokeText('x=' + tileX + ' y=' + tileY, - canvasX + 128, canvasY + 140); - groundCtx.fillText('x=' + tileX + ' y=' + tileY, - canvasX + 128, canvasY + 140); + groundCtx.textAlign = 'left'; + groundCtx.font = 'bold 40px sans-serif'; + // S at top-left (image south after Y mirror is at canvas top) + groundCtx.strokeText('S', canvasX + 12, canvasY + 44); + groundCtx.fillText('S', canvasX + 12, canvasY + 44); + // N at bottom-left (image north at canvas bottom) + groundCtx.strokeText('N', canvasX + 12, canvasY + 244); + groundCtx.fillText('N', canvasX + 12, canvasY + 244); + // Tile coordinates, top-right and bottom-right corners + groundCtx.textAlign = 'right'; + groundCtx.font = 'bold 18px monospace'; + // y at top-right + groundCtx.strokeText('y=' + tileY, + canvasX + GROUND_TILE_SIZE - 12, canvasY + 28); + groundCtx.fillText('y=' + tileY, + canvasX + GROUND_TILE_SIZE - 12, canvasY + 28); + // x at bottom-right + groundCtx.strokeText('x=' + tileX, + canvasX + GROUND_TILE_SIZE - 12, canvasY + GROUND_TILE_SIZE - 12); + groundCtx.fillText('x=' + tileX, + canvasX + GROUND_TILE_SIZE - 12, canvasY + GROUND_TILE_SIZE - 12); return true; }).catch(function() {