Compare commits

..
Author SHA1 Message Date
Mazeyar Moeini FeizabadiandClaude Fable 5.2 ec354565c8 docs(changelog): add the #1719 fragment
Co-Authored-By: Claude Fable 5.2 <[email protected]>
2026-11-13 17:28:10 +01:00
Mazeyar Moeini FeizabadiandClaude Fable 5.2 1d81955f1d perf(detection): reuse the last sweep when the view and contacts are unchanged
Every detection paint projected, faded and bracketed every contact, even
when nothing it reads had changed since the paint before. Live Flights
moves the fleet every 80 ms, so at 60 fps about seven paints in ten
rebuilt the same paths.

Each paint now compares the view and every contact (same objects, same
coordinates, same value in each field the sweep reads) with what the
last sweep was built from, and on a match strokes the kept paths and
places callouts from the kept candidates. Nothing has to announce a
change. Solve paints, the Cyber sonar sweep, Global Context echoes and
depth-tested contacts are always swept.

Also in the sweep: the camera distance without Cesium's argument
checks, the identity hash worked out once per identity, and each
layer's identity sets looked up once per run of objects.

Co-Authored-By: Claude Fable 5.2 <[email protected]>
2026-11-13 17:27:04 +01:00
Sameh Khamis 140f7ebd21 Merge pull request #1714 from bilawalsidhu/sameh/fleet-models
Procedural fleet models for aircraft, vessels, transit and rail
2026-11-13 07:27:47 -08:00
Sameh Khamis 71bfc8aba0 docs: changelog entry names #1714 2026-11-13 07:19:21 -08:00
Sameh Khamis f0b0378b11 docs: fleet models on vessels, transit and rail; no live source names monorail, gondola or funicular; model frame axes 2026-11-13 07:16:25 -08:00
Sameh Khamis 0d1e3fb703 fix(models): update the fleet type table (SF34 and SB20 draw the ATR 72; no tower model) 2026-11-13 07:16:25 -08:00
Sameh Khamis a44c42eb94 fix(vessels, transit, rail): fleet models keep their cards and detection, stand on the floor, clip ships at the waterline and follow NVG/FLIR
- a vehicle drawn as a model keeps its selected card and stays in the detection overlay
- transit and rail models drop the 1.5 m floor lift their icons carry
- vessel models are clipped below the waterline
- models switch to an unlit white look under NVG/FLIR and back
- unknown transit modes keep their icon
- aircraft model specs are cached per set; no key-array copies per frame
2026-11-13 07:16:25 -08:00
Sameh Khamis 058ed0ffeb docs: the fleet models, and changelog entry 2026-11-13 07:16:25 -08:00
Sameh Khamis 7b93045895 feat(vessels, transit, rail): draw fleet models under the 3D toggle
Vessels, Transit and Rail turn nearby icons into fleet models at the
aircraft layers' distances. A vessel is drawn at its AIS length and beam
(static dimensions now reach vessel rows), standing at the sea surface; a
transit vehicle or train stands on its road or rail, raised by its type's
elevation, and is painted in its mode or category colour where the model
marks it.
2026-11-13 07:16:25 -08:00
Sameh Khamis fcc44d0eaf feat(flights): aircraft draw life-size fleet models chosen by type
Flights, Military Flights and Local ADS-B draw each aircraft with the fleet
model its ICAO type, class or emitter category selects, scaled to the type's
length, built from the up-front loaded bytes. The eight third-party aircraft
models and their attribution are removed; every shipped model is now the
project's own.
2026-11-13 07:16:25 -08:00
Sameh Khamis f6760ad96c feat(models): the project's procedural fleet models and the resolver that picks one per vehicle
121 GLBs under public/models/fleet (about 2 MB, MIT like the code) with
catalog.json and types.json. src/data/fleetModels.js picks a model by ICAO
type, aircraft class, emitter category, AIS ship type and size, GTFS route
type, transit mode or rail category, and sizes it life size; the set loads
once, up front. Trail anchors are measured from the meshes.
2026-11-13 07:16:25 -08:00
212 changed files with 8756 additions and 1660 deletions

No files matched your search

+2 -2
View File
@@ -1,13 +1,13 @@
# Data Sources & Attribution
God's Eye View's **code** is [MIT](LICENSE)-licensed. **The MIT grant covers the source code only — it does NOT extend to third-party data or visual assets.** Every third-party source keeps its own license and terms. This file documents the live and bundled data sources; bundled 3D-model provenance is recorded in [`public/models/README.md`](public/models/README.md).
God's Eye View's **code** is [MIT](LICENSE)-licensed. **The MIT grant covers the source code only — it does NOT extend to third-party data or visual assets.** Every third-party source keeps its own license and terms. This file documents the live and bundled data sources. The bundled 3D models are the project's own procedural fleet models, MIT-licensed with the code ([`public/models/README.md`](public/models/README.md)).
How to read this:
- **The non-permissive datasets are carved out, not omitted.** Some bundled data (e.g. TeleGeography, CC BY-NC-SA) isn't MIT-compatible. Rather than hide it, we **bundle it with a clear license carve-out** so the app works out of the box — but it stays under the provider's terms.
- **If your use doesn't fit a dataset's license, remove that dataset.** Most importantly: TeleGeography is **NonCommercial** — commercial users must delete it (or license it from TeleGeography). It's one self-contained folder.
- **Attribution is shown in-app** and listed here. Keep it intact. The required Google/Cesium credit renders on the on-globe credit line (bottom-left, `#cesium-credits`), and every per-layer credit below is registered into the expandable **"Data attribution"** lightbox on that line (`src/data/dataCredits.js` → `viewer.creditDisplay.addStaticCredit`). Both stay visible in clean-view and recording modes.
- **Bundled model attribution lives beside the model files.** [`public/models/README.md`](public/models/README.md) records each shipped model's creator, source, license, and modification status.
- **The bundled 3D models are the project's own.** Every model under `public/models/` is a procedural fleet model generated by the project maintainers and covered by the repository's MIT license; [`public/models/README.md`](public/models/README.md) describes the set.
---
+3 -4
View File
@@ -56,7 +56,6 @@ In short: the MIT grant does not extend to any third-party data. See
DATA_SOURCES.md for the full per-source license + attribution summary, and
remove any dataset whose terms don't fit your use.
The 3D models under public/models/ are also third-party works and are NOT
licensed under MIT. They remain under their individual licenses. See
public/models/README.md for the author, source, license, modification notice,
and attribution covering each model file.
The 3D models under public/models/ are the project's procedural fleet
models, generated from code by the project maintainers, and are covered by
the MIT license above like the source code. See public/models/README.md.
+1 -1
View File
@@ -60,7 +60,7 @@ Start with the included data sources, then add your own. Each layer is a separat
- **📡 Contacts:** A 250 km roster of everything near your target — step through live aircraft and drop into any cockpit.
- **🎯 Click-to-track anything:** Camera locks on, draws a fading trail, surfaces full metadata — and a tracked fire or vessel hands you off to the nearest live camera in one click.
- **🖊️ Voice whiteboard:** Speak annotations onto the world — real boundary polygons, marks, and routes.
- **🛫 3D hangar:** Real per-class aircraft models — 787, ATR-72, Citation, Bell 206, MQ-9 — and a tracked contact swaps from glyph to 3D model as you close in.
- **🛫 3D fleet:** 121 procedural models drawn life size by type — airliners, business jets, helicopters, drones, ships, buses, trams and trains — and every contact swaps from glyph to 3D model as you close in.
- **🎨 Reskin reality:** GLSL sensor looks over the normal globe — CRT, NVG, FLIR/thermal, Noir.
- **🟩 Detection overlay:** Screen-space bounding boxes and IDs on everything in view.
- **🎖️ Military HUD:** Tactical heads-up display with intelligence-style telemetry.
-4
View File
@@ -1,4 +0,0 @@
- Generate the Traditional Chinese catalog instead of translating it:
`npm run i18n -- --zh-hant` writes `zh-Hant` from `zh-CN` with OpenCC `s2tw`
and its character corrections, and `npm test` fails, naming the key, when
`zh-Hant` is edited by hand (German, @gekh, #1699).
+8
View File
@@ -0,0 +1,8 @@
- Draw every 3D model from the project's procedural fleet set: 121 models
(about 2 MB, MIT like the code) chosen per vehicle by type and drawn life
size, replacing the eight third-party aircraft models. Flights, Military
Flights and Local ADS-B pick a model by ICAO type, class and emitter
category; Vessels, Transit and Rail now draw models too, under the same 3D
toggle and distances, a ship at its AIS length and beam and a tram, bus or
train in its mode or category colour. The whole set loads once when a layer
starts (samehkhamis, #1714).
@@ -0,0 +1,4 @@
- The detection overlay no longer rebuilds every bracket on a paint where the
view and every contact are unchanged, which cuts frame work by a fifth to a
third at a whole-globe view of Live Flights with a still camera (mazy1998,
#1719).
+44 -19
View File
@@ -1706,7 +1706,7 @@ Applications supply the existing floor/snap, geoid, picking, sprite, camera,
trail, focus, readout, context, aircraft presentation and render services.
The factory never constructs a second application registry. Configure a source
before initialization; replacing it while initialized is rejected. Model loads
use the supplied asset resolver, including the preload path. Enrichment receives
use the supplied asset resolver, including the up-front fleet set load. Enrichment receives
an abort signal and cannot update a later lifecycle after destruction. Existing
camera, terrain floor, trail, selection and measured model-size policies remain.
@@ -2420,8 +2420,9 @@ is validated against Cesium 1.138.0 and must be revalidated on upgrades.
`scripts/qa-anime-sky.mjs` checks asset readiness, visible Normal sky and
Anime band coverage against a Vite dev server.
`scripts/qa-sky-model-lighting.mjs` compares a lit `airplane.glb` against
black and white environment maps in isolated scenes.
`scripts/qa-sky-model-lighting.mjs` compares a lit fleet airliner
(`public/models/fleet/aircraft/a320.glb`) against black and white environment
maps in isolated scenes.
## Model atmosphere on Apple Metal
@@ -3606,20 +3607,22 @@ This is the current runtime/source-of-truth snapshot for the project.
> 24.09 m aft (70 % of the model's rendered envelope, so inside it), 2.22 m
> below centre (6 %), and 2e-9 m off the centreline.
> - **The tracked trail attaches to REAL HULL, aft and below (2026-08-23):**
> `MODEL_TRAIL_ANCHOR_NATIVE` (`src/data/modelVisualAnchor.js`) holds, per GLB
> and in RAW glTF coordinates (see the transform-chain entry below), the point
> of the hull's CENTRELINE PROFILE (its y = 0 slice) closest to the aft-belly
> AABB corner. It is NOT the corner: a bounding-box corner is empty
> space, 4.80 m off the nearest triangle on `airplane.glb` and 6.14 m on
> `jet.glb`, so the trail ended in mid air beside the aircraft. The head segment
> `FLEET_TRAIL_ANCHORS` (`src/data/fleetTrailAnchors.js`, generated by
> `scripts/measure-fleet-trail-anchors.mjs`) holds, per fleet aircraft and
> helicopter model and in RAW glTF coordinates (see the transform-chain entry
> below), the point of the hull's CENTRELINE PROFILE (its centreline slice)
> closest to the aft-belly AABB corner. It is NOT the corner: a bounding-box
> corner is empty space (4.80 m off the nearest triangle on the airliner
> asset this was first measured on, 6.14 m on the jet), so the trail ended in
> mid air beside the aircraft. The head segment
> is drawn from a point behind the aircraft to this anchor, so the anchor must
> stay aft (83–96 % of each aft extreme) or the segment enters at the tail and
> stops inside the fuselage. `modelScale.test.mjs` reads the POSITION BUFFERS —
> stops inside the fuselage. `fleetModels.test.mjs` reads the POSITION BUFFERS —
> real vertices and triangles, because accessor min/max cannot tell a corner
> from a surface — and re-derives on-hull, aft, lowest-at-its-station,
> on-centreline, and the construction itself. Re-measure, never re-guess.
> - **The trail anchor rides CESIUM'S transform chain, not a hand-rolled one
> (2026-08-23 regression fix):** `MODEL_TRAIL_ANCHOR_NATIVE` stores RAW
> (2026-08-23 regression fix):** `FLEET_TRAIL_ANCHORS` stores RAW
> glTF coordinates and `modelAnchorWorld()` assembles
> `modelMatrix × components.transform × axisCorrection` — the same chain
> `ModelSceneGraph` renders with, built from Cesium's own exported
@@ -3654,7 +3657,7 @@ This is the current runtime/source-of-truth snapshot for the project.
> ENVELOPE, and between them the drawn start slides along the segment so the
> visible length grows CONTINUOUSLY from zero. Three earlier cuts are recorded
> because their shape matters: testing segment LENGTH against the radius HID
> real trail (58 m aft of `airplane.glb`'s 34.41 m envelope gives a 33.98 m
> real trail (58 m aft of an airliner's 34.41 m envelope gives a 33.98 m
> segment, suppressed, though ~23.6 m of it is open air); CLIPPING at the
> envelope and keeping only what lay outside stopped a moving trail visibly
> SHORT of the aircraft, since a bounding sphere encloses a lot of empty space
@@ -4830,8 +4833,9 @@ activeCameraCardEnabled: true })` may publish it through the retained
> - **Flights 3D/cockpit hardening:** the destination-direction cue is an
> inline SVG rather than a remotely loaded Material Icons ligature, so a
> blocked or late font can no longer expand the literal word `navigation`
> across the cockpit. The grounded `airplane.glb` belly offset is calibrated
> to the current asset's measured Y-up bounds (`0.063` native units).
> across the cockpit. A grounded aircraft stands its fleet model's scaled
> clearance (the catalog's `clearance`, measured below the model's origin)
> above the ground.
> Contact Previous/Next and Live Signals aircraft handoffs now
> re-seed the first-person camera anchor at the selected flight immediately;
> bounded feed-correction smoothing remains scoped to the same aircraft.
@@ -5096,9 +5100,7 @@ Shipped locales: **en** (source and fallback), **ar**, **de**, **es**, **fr**, *
- **Gate.** `npm run i18n` (and `src/i18n/catalog.test.mjs` under `npm test`)
extracts every message and fails on missing, empty, unused,
placeholder-mismatched, still-English (plural forms included) or
wrongly-shaped plural entries. `zh-Hant` is generated from `zh-CN`
(`npm run i18n -- --zh-hant`: OpenCC `s2tw` through `opencc-js`, then a
fixed list of character corrections), and the gate fails when it differs.
wrongly-shaped plural entries.
- **Not translated by design:** layer ids, share-link and hash parameters, API
fields, voice tool schemas, provider names, feed data (callsigns, vessel and
station names) and attribution.
@@ -7292,8 +7294,9 @@ pins and share links already supply complete boxes.
normal four-samples-per-250-ms budget. Retry timestamps more than the maximum
30-second backoff ahead of the current clock are ignored. A smaller rollback
can retain a bounded retry delay of up to 30 seconds.
- Commercial and military aircraft use the same high-level FLEET model regime: 2D billboards when zoomed out, optional glTF models when closer, controlled by the DISPLAY rail `3D` toggle and `Proximity` / `All` modes. Since 2026-08-16 (Hangar fleet) models are PER-CLASS: real CC-BY GLBs for light/bizjet/turboprop/widebody/helicopter/uav (`CLASS_MODEL_REAL` in `src/data/aircraftClass.js` — meters-baked, scale 1, per-model belly/radius; provenance in `public/models/README.md`), the shared `airplane.glb` for the remaining civilian classes, and the military layer maps weight classes (real GLBs / 747 heavies / `jet.glb` fastjets, per-model heading offsets, flat amber or emergency red). Textured civilians carry a HEAVY tint, not a light one: `MODEL_COLOR_BLEND_AMOUNT` is `0.94` in BOTH layers under Cesium's `ColorBlendMode.MIX`, so the class colour supplies 94% of the surface and the asset's own texture ~6%. The visual direction is clean light silhouettes with only a weak diffuse contribution from the approved textures, so liveries deliberately do NOT read. IR boost raises the blend to a full `1.0`. Under NVG/FLIR (map preset or Cockpit vision) models render unlit flat-white at full alpha and scene fog is disabled (fog otherwise blacks out distant models with the globe hidden); state restores on exit.
- **Aircraft models skip Cesium's dynamic environment map (2026-10-24).** Flights, Military Flights and Local ADS-B pass `environmentMapOptions: AIRCRAFT_ENVIRONMENT_MAP_OPTIONS` (`{ enabled: false }`, `src/data/aircraftModelLighting.js`) to every drawn model. Otherwise each `Model` renders the sky around it and reads it back from the GPU (`readPixels`) when it is first placed, and again whenever it moves more than 1 km, the scene's atmosphere settings change, or (under sunlight dynamic lighting) an hour of scene time passes (`DynamicEnvironmentMapManager`, Cesium 1.138). With the class colour supplying 94% of the surface, the models are lit from Cesium's default spherical harmonics instead, with no specular environment map, so the sky's model-lighting cube map no longer reaches aircraft. `src/data/aircraftModelLighting.test.mjs` pins the option at every drawn model call; the two preload calls only warm the glTF cache and are never drawn.
- Commercial and military aircraft use the same high-level FLEET model regime: 2D billboards when zoomed out, optional glTF models when closer, controlled by the DISPLAY rail `3D` toggle and `Proximity` / `All` modes. Every model is one of the project's procedural fleet models (`public/models/fleet/`, MIT, 121 GLBs, about 2 MB in all; `public/models/README.md`), chosen per aircraft by `aircraftModelSpec` (`src/data/fleetModels.js`): its ICAO type's entry in `types.json`, else the model of its `classifyAircraft` class for a type the map lacks, else its ADS-B emitter category's, else the default airliner. It is drawn LIFE SIZE: the type's published length over the model's built length (`src/layers/flights/modelSpec.js`, shared by Flights, Military Flights and Local ADS-B), and a grounded aircraft stands the model's scaled clearance above the ground. `classifyAircraft` still picks the 2D icons. The whole set loads once, up front, when a layer that draws it starts (`loadFleetModelSet`, which logs `[Fleet] N/121 models (X MB) loaded in N ms`); models are built from those bytes, never fetched mid-session, and an aircraft stays its billboard until the set has loaded. Textured civilians carry a HEAVY tint, not a light one: `MODEL_COLOR_BLEND_AMOUNT` is `0.94` in BOTH layers under Cesium's `ColorBlendMode.MIX`, so the class colour supplies 94% of the surface and the model's own vertex colour ~6%; military models are flat amber, or emergency red. IR boost raises the blend to a full `1.0`. Under NVG/FLIR (map preset or Cockpit vision) models render unlit flat-white at full alpha and scene fog is disabled (fog otherwise blacks out distant models with the globe hidden); state restores on exit.
- Vessels, Transit and Rail draw fleet models under the same DISPLAY rail `3D` toggle, at the same altitude ceiling, caps and add/keep radii as the aircraft (`FLEET_MODEL_POLICY`, `src/layers/flights/policy.js`; `createFleetModelLayer`, `src/data/fleetModelInstances.js`). A vessel's model follows its AIS ship type and is drawn at its reported length and beam (AIS static dimensions A+B and C+D, now carried on vessel rows as `length` and `beam`), standing at the sea surface, heading by true heading then course. A transit vehicle's model follows its layer mode (bus, tram, subway, rail or ferry; a vehicle of `unknown` mode keeps its icon), a train's its rail category and mode (rail, metro or tram). Neither the transit nor the rail sources carry a GTFS `route_type` or a finer mode (monorail, gondola, funicular, cable car), so the set's models for those and their `transit.elevation` lifts are not reached by any live source today. Both stand on the road or rail top they are drawn on, without the 1.5 m `GROUND_FLOOR_LIFT_M` their icons carry, and are painted in their mode or category colour where the model's `_TINT` attribute marks it. A vessel model is clipped at its waterline (one clipping plane per model, at the model origin's horizontal plane), so its hull below the water never shows through a plain globe, which Cesium does not depth-test models against. Under the NVG/FLIR styles (the Flights `irBoost` parameter) these models render unlit flat white, as aircraft models do. Each vehicle's icon stays the visual until its model is loaded, ready and placed; a model is picked as its icon is, and a vehicle drawn as its model keeps its selection card and its place in the detection overlay.
- **Aircraft models skip Cesium's dynamic environment map (2026-10-24).** Flights, Military Flights and Local ADS-B pass `environmentMapOptions: AIRCRAFT_ENVIRONMENT_MAP_OPTIONS` (`{ enabled: false }`, `src/data/aircraftModelLighting.js`) to every drawn model. Otherwise each `Model` renders the sky around it and reads it back from the GPU (`readPixels`) when it is first placed, and again whenever it moves more than 1 km, the scene's atmosphere settings change, or (under sunlight dynamic lighting) an hour of scene time passes (`DynamicEnvironmentMapManager`, Cesium 1.138). With the class colour supplying 94% of the surface, the models are lit from Cesium's default spherical harmonics instead, with no specular environment map, so the sky's model-lighting cube map no longer reaches aircraft. `src/data/aircraftModelLighting.test.mjs` pins the option at every drawn model call; every model is built from the fleet set loaded up front, so there is no separate preload.
- The DISPLAY-rail `3D` toggle is the user-facing activation path for both aircraft layers. Their small approved GLBs build their render resources without Cesium's frame-spread job queue, preventing continuous Photorealistic 3D Tiles streaming from starving model readiness; model caps, tracking, camera, and fallback billboards are unchanged.
- **The `3D` toggle DEFAULTS ON in `proximity` on a first run.** Proximity is itself the budget — models appear only below `MODEL_ALT_CEIL_M` and only for the nearest `MODEL_MAX` in view — so the default costs nothing at globe scale, and `all` remains a deliberate opt-in. A fresh boot runs NO layer-state restoration (`LayerStateCoordinator.start()` returns early with neither a share payload nor stored state), so four independent initializers decide what a first-run operator sees and must agree: `booleanOption('models3d', 'e', true)` in `src/data/layerState.js`, `_models3dEnabled = true` in BOTH flight layers, `this._models3dEnabled = true` in `src/ui/aircraftDisplay.js`, and the `active` / `visible` classes on `#models3d-toggle` / `#models3d-mode-row` in `index.html`. All four are pinned together in `src/data/layerState.test.mjs`. Explicit state still wins: because the codec omits default-valued options, `models3d: false` is now what travels in a link (`lo=…f.e.0`) and restores OFF at both aircraft layers. **Consequence for returning users:** a stored `gev:layer-state:v2` blob is a FULL options snapshot, so a session that wrote one before this change carries `models3d:false` and keeps 3D off until the operator flips it (or clears the key) — the durable snapshot is treated as the recipient's own state, by design.
- **Consequence of the flip on the recorded tracked/fleet inversion:** the 150–800 km band where surrounding contacts draw as models while the SELECTED one is still a glyph is now what an operator sees WITHOUT arming anything. The inversion itself is unchanged and still deliberate (see `src/data/trackedModelRegime.js`); only its reachability changed.
@@ -7456,6 +7459,28 @@ apply to `public/` assets or built-preview serving.
holds the way it stripped detection's would take bracket promptness with it, silently.
- Known, pre-existing, and deliberately out of scope here: the overlay's backing store does not
re-derive on a DPR change mid-session (`worldOverlay` sizing — untouched by this work).
- **A detection paint reuses the sweep before it when nothing it reads has changed
(`src/data/detectionPaintCache.js`).** The sweep in `_drawOverlay` (project every contact, fade
it, append its bracket, build callout candidates) depends only on the view and on the contacts.
Each paint still asks every layer for its contacts, then compares them with what the last sweep
was built from: the same objects in the same order, the same position coordinates, and the same
value in every field the sweep reads (`PAINTED_OBJECT_FIELDS`), under the same view (profile,
style, canvas size, keyhole, camera position, view-projection matrix, UI rectangles; see
`_paintViewOf`). On a match the kept bracket paths, counts and callout candidates are used again
and only the strokes and callouts are repainted. No layer has to announce a change, so none can
leave a stale picture behind. A sweep that READS a new object field or a new view value must add
it to those two lists; `detectionHost.test.mjs` compares 41 frames against a full sweep, canvas
call for canvas call.
- Never reused or kept: a solve paint (the sweep gathers the cohort), any paint while the Cyber
sonar sweep or a Global Context echo is live (brackets change with the clock), and any sweep
that reached a depth-tested contact (its answer comes from the scene).
- Where it pays: a held camera with contacts that move in steps. Live Flights re-positions the
fleet every 80 ms, so at 60 fps about seven paints in ten reuse a sweep. Once a frame takes
longer than 80 ms every paint sees moved aircraft and none is reused; after eight such sweeps
the contacts are only recorded on every eighth, so the comparison costs nothing there.
Satellites move on every frame and are never reused.
- `getDetectionDiagnostics().paintReuseCount` (and `data-paint-reuse-count`) counts reused
paints since `initDetection`; `placementBuildCount` is 0 on a reused paint.
- The detection MODE BANNER (`DENSE VIS:… SRC:… DENS:…% ELASTIC …ms`) is
developer telemetry and is HIDDEN by default. It paints only under
`?detectDebug=1` (the `trafficDebug` convention), resolved once per
-2
View File
@@ -104,8 +104,6 @@ npm run i18n -- --prune # drop entries whose English no longer exists
Changing the English changes the key: the old translation goes unused and the new text shows as missing. Add the translation to every `src/i18n/locales/<code>.json` (or ask a translator), prune, and run `npm test`; it fails until every language is complete.
Do not translate `zh-Hant`: it is generated. After `zh-CN`, run `npm run i18n -- --zh-hant` (see [zh-Hant.md](./translations/zh-Hant.md)).
To see a language, open the app with `?lang=ru`, or use the language picker (the globe button in the bottom-right corner).
An empty translation is reported, and so is one left as the English, plural forms included. When English is right on purpose (a code such as CRT, a product name), list it under the language in `src/i18n/same-as-english.json`.
-2
View File
@@ -36,8 +36,6 @@ npm run i18n -- --prune # drop entries the code no longer uses
Changing English text changes its key: the old translation becomes unused and the new text shows as missing. Translate it and prune.
Do not translate `zh-Hant`: it is generated. Translate `zh-CN`, then run `npm run i18n -- --zh-hant` (see [zh-Hant.md](./translations/zh-Hant.md)).
## Fixing a translation
Edit `src/i18n/locales/<code>.json` and run `npm run i18n`. To see your change, open the app with `?lang=<code>`.
+4 -12
View File
@@ -2,24 +2,16 @@
Catalog: `src/i18n/locales/zh-Hant.json`. General rules: [TRANSLATORS.md](../TRANSLATORS.md).
**Do not translate or edit this catalog: it is generated.** `zh-Hant` is the Simplified Chinese catalog (`zh-CN`, credited to abiyeenzo, #914, and EDIT-Aeterna, #979) written in Traditional characters. Wording and terminology are the same as in `zh-CN`; only the script differs. To add or change an entry, edit [zh-CN.md](./zh-CN.md) and the `zh-CN` catalog, then run:
`zh-Hant` is the Simplified Chinese catalog (`zh-CN`, credited to abiyeenzo, #914, and EDIT-Aeterna, #979) written in Traditional characters with OpenCC character conversion. Wording and terminology are the same as in `zh-CN`: change a term in [zh-CN.md](./zh-CN.md) and the `zh-CN` catalog first, then convert. Only the script differs.
```sh
npm run i18n -- --zh-hant # rewrite zh-Hant.json from zh-CN.json
```
`npm test` fails when `zh-Hant.json` differs from the conversion of `zh-CN.json`, naming the entry, and `npm run i18n -- --missing zh-Hant` points to this command instead of printing a template.
The command converts with OpenCC `s2tw` ([opencc-js](https://github.com/nk2028/opencc-js), `cn` → `tw`), which changes characters only. Never `s2twp`: it also swaps in Taiwan vocabulary (影片, 伺服器, 載入, 圖示), which this catalog does not use. After the conversion it fixes the characters OpenCC picks wrongly here: 年曆史 → 年歷史, 下遊 → 下游, 並道 → 併道 (not in 並道路, 並道歉, 並道理), 發佈 → 發布, 公佈 → 公布, 控制檯 → 控制台, and 周 → 週 where it means a week (1 週/秒). The list is `ZH_HANT_CORRECTIONS` in `scripts/i18n.mjs`; when the conversion picks another wrong character, add the pair there and run the command.
An entry `zh-CN` keeps in English on purpose needs the same line under `zh-Hant` in `src/i18n/same-as-english.json`.
After `s2tw` conversion, fix the characters OpenCC picks wrongly: 年曆史 → 年歷史, 下遊 → 下游, 並道 → 併道, 發佈 → 發布, 公佈 → 公布, 控制檯 → 控制台, and 周 → 週 where it means a week (1 週/秒).
## Style
- Wording, punctuation, spacing, units and the glossary are those of [zh-CN.md](./zh-CN.md), written in Traditional characters.
- Follow [zh-CN.md](./zh-CN.md) for wording, punctuation, spacing, units and the glossary, written in Traditional characters.
- Relative-time placeholders may already include 前. In `LIVE · updated {age}`, the caller supplies the complete relative age; do not append another 前.
- The picker displays 中文(繁體) / Chinese (Traditional); explicit Hans tags select Simplified Chinese.
## Plurals
`Intl.PluralRules('zh-Hant')` uses only `other`. The measure words come from the `zh-CN` entry: 「{count} 架飛機」、「{count} 艘船」.
`Intl.PluralRules('zh-Hant')` uses only `other`. Keep the measure words of the `zh-CN` entry: 「{count} 架飛機」、「{count} 艘船」.
-8
View File
@@ -32,7 +32,6 @@
"@vue/test-utils": "^2.5.1",
"flag-icons": "7.5.0",
"happy-dom": "^20.14.6",
"opencc-js": "1.4.2",
"prettier": "3.9.6",
"puppeteer": "^25.16.0",
"sharp": "^0.35.4",
@@ -2977,13 +2976,6 @@
"node": ">= 0.8"
}
},
"node_modules/opencc-js": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/opencc-js/-/opencc-js-1.4.2.tgz",
"integrity": "sha512-EdcspgdROiCCZDM+jZR6Pa670xW+EW2QhctPBQ8gRjg6lrx4IHEl+2s+kt5izk/TkxVRgdWuFgaGkaEdIUfdaw==",
"dev": true,
"license": "MIT AND Apache-2.0"
},
"node_modules/pako": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
-1
View File
@@ -85,7 +85,6 @@
"@vue/test-utils": "^2.5.1",
"flag-icons": "7.5.0",
"happy-dom": "^20.14.6",
"opencc-js": "1.4.2",
"prettier": "3.9.6",
"puppeteer": "^25.16.0",
"sharp": "^0.35.4",
+30 -17
View File
@@ -1,20 +1,33 @@
# Bundled 3D Model Attribution
# Bundled 3D Models
The model files in this directory are third-party visual assets. They are not
covered by the repository's MIT source-code license; each remains available
under the license listed below.
Every 3D model shipped in this directory is one of the project's procedural
fleet models under [`fleet/`](fleet/): aircraft, helicopters, ships, buoys,
transit and rail vehicles, and a few other airborne and ground objects. They
are generated from code by the project maintainers, contain no third-party
artwork, and are covered by the repository's [MIT license](../../LICENSE)
like the source code.
| File | Original work and creator | Source | License | Project modifications |
|---|---|---|---|---|
| `airplane.glb` | “boeing 747” by [zairiq-123](https://sketchfab.com/zairiq-123) | [Sketchfab model](https://sketchfab.com/3d-models/boeing-747-9b16672038ba48f98e6d80a159044ed9) | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) | Substantially modified and optimized for God's Eye View, including geometry/material simplification and coordinate/orientation preparation. The former 24× runtime calibration is baked into the mesh; location, rotation, and scale are applied; the bounding-box centre is at the origin; and the model uses glTF +Y-up with its nose toward local −X. Geometry remains uncompressed so the aircraft asset does not compete with photogrammetry for Draco worker capacity. |
| `jet.glb` | “Private Jet” by [Nick the Name](https://sketchfab.com/Nick_The_Name) | [Sketchfab model](https://sketchfab.com/3d-models/private-jet-cbdd1de6ced9461e950eafaa302cc82b) | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) | Repackaged as a glTF binary for the project's military-flight visualization. Imported hierarchy transforms are baked into the meshes; location, rotation, and scale are applied; the bounding-box centre is at the origin; and the model uses meter scale, glTF +Y-up, and the shared nose −X convention. Existing materials are preserved. |
| `bell206.glb` | “Bell 206 JetRanger” by [terran4627](https://sketchfab.com/terran4627) | [Sketchfab model](https://sketchfab.com/3d-models/bell-206-jetranger-d2f7ba1d671549d4b26aaf834139a1dd) | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) | Optimized for God's Eye View: geometry/material simplification, textures resized to 256 px WebP, orientation/scale vertex-baked to real-world meters (Y-up, nose −X), origin centered. |
| `c172.glb` | “Cessna 172” by [e737](https://sketchfab.com/e0057537) | [Sketchfab model](https://sketchfab.com/3d-models/cessna-172-64cddaee5aff470682659a8c08525046) | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) | Optimized for God's Eye View: geometry/material simplification, textures resized to 256 px WebP, orientation/scale vertex-baked to real-world meters (Y-up, nose −X), origin centered. |
| `citation2.glb` | “1990 Cessna Citation, Texture Detailed, Exterior” by [BlenderCommunityHead](https://sketchfab.com/aboodgoudagad) | [Sketchfab model](https://sketchfab.com/3d-models/1990-cessna-citation-texture-detailed-exterior-a78839624fe64900a8352cb23462350a) | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) | Optimized for God's Eye View: geometry/material simplification, textures resized to 256 px WebP, orientation/scale vertex-baked to real-world meters (Y-up, nose −X), origin centered. |
| `mq9.glb` | “MQ-9” by [IProZenoN](https://sketchfab.com/IProZenoN) | [Sketchfab model](https://sketchfab.com/3d-models/mq-9-fabe963feb354c5584b51f9c470c3f7e) | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) | Optimized for God's Eye View: geometry/material simplification, textures resized to 256 px WebP, orientation/scale vertex-baked to real-world meters (Y-up, nose −X), origin centered. |
| `b789.glb` | “Boeing 787-9” by [Nobilis 2](https://sketchfab.com/nobilishornet2) | [Sketchfab model](https://sketchfab.com/3d-models/boeing-787-9-b6711e2e698e4e469675c1154a50b7a3) | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) | Optimized for God's Eye View: geometry/material simplification, textures resized to 256 px WebP, orientation/scale vertex-baked to real-world meters (Y-up, nose −X), origin centered. |
| `atr72.glb` | “ATR 72 - 600” by [Oyan3D](https://sketchfab.com/oyan3D) | [Sketchfab model](https://sketchfab.com/3d-models/atr-72-600-1e1a7186f7444d288675262fcee44744) | [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) | Optimized for God's Eye View: geometry/material simplification, textures removed with dominant material colors baked into PBR factors (flat “abstracted” style), orientation/scale vertex-baked to real-world meters (Y-up, nose −X), origin centered. |
| Path | What it holds |
|---|---|
| `fleet/catalog.json` | Every model by name: its file, category, built length, beam and bounds (metres, in Cesium's Z-up model frame: x along the length with the nose toward −X, y across the beam, z up), the clearance below its origin, and its 2D icon class. |
| `fleet/types.json` | Which model draws which vehicle, and at what length: ICAO aircraft and helicopter type codes, ADS-B emitter categories, AIS ship-type and length ranges, GTFS route types, transit modes and rail categories, with the defaults. |
| `fleet/aircraft/`, `fleet/helicopters/`, `fleet/ships/`, `fleet/buoys/`, `fleet/transit/`, `fleet/other/` | The models, one GLB each (EXT_meshopt_compression and KHR_mesh_quantization, vertex colours, no textures). |
CC BY 4.0 permits sharing and adaptation, including commercial use, provided
appropriate credit is retained, the license is linked, and modifications are
identified. These credits do not imply endorsement by the original creators.
How the layers use them:
- Each layer draws a vehicle with the model its type selects, scaled to the
type's published length (a vessel to its reported AIS length and beam), so
every model is drawn life size. Ground objects, balloons and obstacles in
the `other` category are drawn at the size they are built.
- An aircraft model's origin is its axis; it stands that model's scaled
clearance above the ground. A ship's origin is its waterline, and a transit
or rail vehicle's the road or rail top (a monorail or gondola is raised by
its `transit.elevation` entry, for a source that names those modes).
- Transit and rail models carry a `_TINT` vertex attribute that marks where
the route or category colour is painted.
- The whole set loads once, up front, when a layer that draws it starts; no
model is fetched while a session runs.
`src/data/fleetModels.js` reads the set and chooses each vehicle's model;
`src/data/fleetModels.test.mjs` checks that every model `types.json` names is
in the catalog and on disk, and that no GLB exceeds 3 MB.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large. Load diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loaded 100 of 212 files, more files were not shown because too many files have changed in this diff. Show more